Search code examples
pythonkivyscrollviewkivy-language

How can I initialize a for loop inside ScrollView with Kivy?


I am new to Kivy and I am trying to figure out how to use ScrollView. I am wondering how I can initialize buttons generated inside for loop inside ScrollView. Here is my code so far:

main.py

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button


class My_list(BoxLayout):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.orientation = "vertical"
        for i in range(10):
            b = Button(text=str(i))
            self.add_widget(b)

class MyBoxLayout(BoxLayout):
    pass

class MyApp(App):
    pass

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

my.kv

MyBoxLayout:

<MyBoxLayout>:
    orientation: "vertical"

#    ScrollView:
#        size_hint: 1, None
#        height: 200

    My_list:

    BoxLayout:
        size_hint: 1, .1
        TextInput:
        TextInput:

    Button:
        text: "Add Button"
        size_hint: 1, .1

This looks how I want it, but I want to move number buttons with scrollbar if there are too many to be shown on screen. Scrollbar should not affect input widgets and Add Button.

I tried this in my.kv:

ScrollView:
    size_hint: 1, None
    height: 200

    My_list: 

But it seems to mess up the whole layout. Is there a way to use the for loop inside .kv file? Or is what other way is to make this work?


Solution

  • As per Kivy documentation,

    You must carefully specify the size of your content to get the desired scroll/pan effect. By default, the size_hint is (1, 1), so the content size will fit your ScrollView exactly (you will have nothing to scroll). You must deactivate at least one of the size_hint instructions (x or y) of the child to enable scrolling. Setting size_hint_min to not be None will also enable scrolling for that dimension when the ScrollView is smaller than the minimum size.

    So the changes you need, in my.kv,

        ScrollView:
    #        size_hint: 1, None # Generally you don't need this.
    #        height: 200 # Neither this.
            
            My_list:
                size_hint_y: None # Let the container expand vertically.
                height: self.minimum_height # Or, you can specify any other value.
    

    And in My_list,

            b = Button(
                    text=str(i),
                    size_hint_y = None, # To set custom value.
                    height = dp(100), # Specify height of the widget explicitly.
                )
            self.add_widget(b)