Search code examples
pythonscrollkivyscrollview

Kivy ScrollView trys to scroll, but bounces back evert time


So I have a ScrollView inside a GridLayout, but my Scroll view wont scroll. it moves to reveal more buttins, and then bounce back to the the top!

All the solutions online say just use self.size_hint_y = None and just use self.height = self.minimum_height and I have as you can see and it didnt stop the bouncing back...

from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.gridlayout import GridLayout
from kivy.uix.scrollview import ScrollView
from kivy.uix.stacklayout import StackLayout


class MainWindow(GridLayout):

    def __init__(self, **kwargs):
        super(MainWindow, self).__init__(**kwargs)

        self.cols = 2
        self.rows = 1

        self.layout1 = ScrollViewExample()
        self.add_widget(self.layout1)
        self.layout1.size_hint = ("0.3dp", None)

        self.layout2 = MyGrid()
        self.layout2.size_hint = (1, 1)
        self.add_widget(self.layout2)


class SideMenuStack(StackLayout):
    def __init__(self, **kwargs):
        super(SideMenuStack, self).__init__(**kwargs)

        # self.cols = 2
        # self.rows = 50

        self.size_hint_y = None
        self.height = self.minimum_height

        for i in range(100):
            button = Button(text=str(i), size_hint=(None, None), size=("92dp", "92dp"))
            self.add_widget(button)


class ScrollViewExample(ScrollView):

    def __init__(self, **kwargs):
        super(ScrollViewExample, self).__init__(**kwargs)

        self.size_hint = (1, None)
        self.height = 10000
        self.layout1 = SideMenuStack()
        self.layout1.size_hint = (1, None)
        self.do_scroll_y = True
        self.do_scroll_x = False
        # self.effect_cls = 'ScrollEffect'
        self.scroll_distance = 100000
        self.add_widget(self.layout1)


class MyGrid(GridLayout):
    pass

class GuiApp(App):
    def build(self):
        return MainWindow()

if __name__ == "__main__":
    GuiApp().run()

Solution

  • Although your guess about self.size_hint_y = None is right but setting self.height = self.minimum_height in __init__ is not. Because during initialization the default values are applied. So what you need to do is, make the layout listen to any changes whenever any widget gets added to it (and thus increases its height).

    Now this is done by binding some callback to some attr. Here you can do it as,

    #        self.height = self.minimum_height
            self.bind(minimum_height = self.setter("height"))
    

    Thus you are actually setting a callback method (setter, it is default in kivy) to listen to any changes in minimum_height and then set this value as height.

    Some other changes included,

    # self.layout1.size_hint = ("0.3dp", None)
    self.layout1.size_hint = ("0.3dp", 1)
    .
    .
    .
    class ScrollViewExample(ScrollView):
    
        def __init__(self, **kwargs):
            ...
    #        self.size_hint = (1, None)
    #        self.height = 10000
            self.layout1 = SideMenuStack()
    #        self.layout1.size_hint = (1, None)
            self.do_scroll_y = True
            self.do_scroll_x = False
            # self.effect_cls = 'ScrollEffect'
    #        self.scroll_distance = 100000 # Perhaps you don't need it.
            ...