Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kivy: Swiping (Carousel & ScreenManager)

Tags:

kivy

I have two Screens in a ScreenManager that both contains a number of buttons in a ScrollView. The idea is that one steps forward (right) by clicking a button. And step back (left) by swiping back. So I am trying to add a Carousel to implement that one swipe on the second page. This is what I have tried:

self.root = ScreenManager(id = 'screen_manager')

main_screen = Screen(name = 'main_screen')

scroller = Scroller()
button_text = ['teach', 'move', 'b3', 'b4', 'b5', 'b6', 'b7', 'b8']
for text in button_text:
    scroller.view.add_widget(Field(name=text, direction='left', current='teach'))
main_screen.add_widget(scroller)
self.root.add_widget(main_screen)

carousel = Carousel(direction='left', id='carousel')

teach = Screen(name = 'teach')
scroller2 = Scroller()
button_text = ['vocab', 'drills']
for text in button_text:
    scroller2.view.add_widget(Field(name=text, direction='right', current='main_screen'))
carousel.add_widget(scroller2)
teach.add_widget(carousel)
self.root.add_widget(teach)

But since I have only added the second Screen, it's not possible to swipe in either direction. Carousel's load_slide() method takes a slide as argument. Assuming by slide they mean a Carousel. Given I am going to have a lot pages, I probably need the Carousel to be loaded dynamically, using add_widget() and remove_widget(). Would appreciate some pointers.

Working example of the code I have so far: http://dpaste.com/33464R2

like image 880
dan-klasson Avatar asked Jun 19 '15 09:06

dan-klasson


2 Answers

I have another method that can be used. It is not through Carousel but it allows you to change screen through swiping. You can create a method that takes in the x point of your initial contact point of the screen and the x point of your final contact of the screen and subtract them. Here is the link to the video(https://www.youtube.com/watch?v=8pqtMAUEUyo&t=65s)

    def on_touch_move(self, touch):
        if touch.ox - touch.x > 50:  # check for swiping gestures
            # ScreenManger change screen

touch.ox is the initial contact point of the screen(x axis) and touch.x is the final. If the difference is then greater than a set value it changes screen.

like image 196
Abacito Avatar answered Nov 08 '22 04:11

Abacito


As you asked in your comment.

I have bunch of pages. Each page will have a bunch of buttons. Some pages have more buttons than can fit on the screen, so they need to be scrollable.

Now, Scrollable part, you already figured out.(You can do it in kivy file also), See here. And you can easily add that in the code below.

Clicking on a button should take you to the next child screen (with a scroll effect). On any child it should be possible to go back to it's parent by swiping back.

Here(Code below) you can both swipe or click on buttons to navigate.

Now,

Given I am going to have a lot pages, I probably need the Carousel to be loaded dynamically, using add_widget() and remove_widget().

These examples will help you. Kivy-Showcase and Container

In kivy-showcase have a look at load_screen method and also the build function

Here is an example to add_widgets on click of a button

Builder.load_string('''
[SideBar@BoxLayout]:
    content: content
    orientation: 'vertical'
    size_hint: .2,1
    BoxLayout:
        orientation: 'vertical'
        # just add a id that can be accessed later on
        id: content

<Root>:
    Button:
        center_x: root.center_x
        text: 'press to add_widgets'
        size_hint: .2, .2
        on_press:
            sb.content.clear_widgets()
            root.load_content(sb.content)
    SideBar:
        id: sb
''')

class Root(BoxLayout):

    def load_content(self, content):
        for but in range(20):
            content.add_widget(Button(text=str(but)))

class MyApp(App):
    def build(self):
        return Root()

if __name__ == '__main__':
    MyApp().run() 

Here is the example for screens.

Here is main.py file

from kivy.app import App
from kivy.uix.screenmanager import Screen
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import ObjectProperty

class ShowTime(BoxLayout):
    carousel = ObjectProperty(None)

class Screen1(Screen):
    pass

class Screen2(Screen):
    pass

class MainApp(App):
    def build(self):
         return ShowTime()

if __name__ == '__main__':
    MainApp().run()

Here is the main.kv file

<Screen1>:
    name: "screen1"
    BoxLayout:
        orientation: 'vertical'
        padding: 50
        spacing: 50
        Button:
            text: "Next (2)"
            on_release: self.parent.parent.parent.parent.parent.ids.carousel.load_next()
        Button:
            text: "Go back (2)"
            on_release: self.parent.parent.parent.parent.parent.ids.carousel.load_previous()

<Screen2>:
    name: "screen2"
    BoxLayout:
        orientation: 'vertical'
        padding: 100
        spacing: 100
        Button:
            text: "go back (3)"
            on_release: self.parent.parent.parent.parent.parent.ids.carousel.load_previous()

<Showtime>:
    carousel: carousel
    Carousel:
        id: carousel
        loop: True
        BoxLayout:
            padding: 100
            spacing: 100
            Button:
                text: 'Tap me or Swipe (1)'
                on_release: carousel.load_next()
        Screen1:
        Screen2:

EDIT 1:

Q- How to use load_slide() method?

load_slide() method takes slides as its parameter def load_slide(self, slide):

Q- So now how to get slide?.

slide is a list property slides = ListProperty([]),

Print this where button has text "go back (3)"

on_release: print( self.parent.parent.parent.parent.parent.ids.carousel.slides) you will get a list of all slides under id(carousel).

This is how you use it. .....ids.carousel.load_slide(....ids.carousel..slides[2])

like image 40
kiok46 Avatar answered Nov 08 '22 03:11

kiok46