Nordicca
Nordicca

Reputation: 46

How to set a custom widget size/position to it's parent layout in kivy?

I am trying to add a custom widget to a GridLayout, but the size and position don't dynamically scale to fit the parent layout. My goal is to add one of these CustomWidgets to the GridLayout by pressing a button. I am able to achieve the results I want if I copy+paste the contents of my .kv files' <CustomWidgets> class directly into the .kv GridLayout (left image), but this sidesteps the purpose of the button.

I've linked an image to help clarify my expected vs actual outcome. The left image shows my desired result of pressing the "Add Activity" button three times. The right image shows the actual outcome when I try adding a custom widget by pressing the "Add Activity" button three times.

enter image description here

My guess is this problem can be solved if the 'size_hint_x: self.x' is set after adding it to the GridLayout. I've tried to set the CustomWidget 'size_hint_x' to fit the parent layout within the .kv GridLayout by setting it after building

    CustomWidgets:
        size_hint_x: self.x

with no luck. I am able to set a number value as the width of the CustomWidget but then it doesn't dynamically change to fit the size of the window.

DemoApp.py

class CustomGridLayout(GridLayout):

    def add_list_item(self):
        print("add list item - CustomGridLayout")
        self.ids['list_layout'].add_widget(CustomWidgets())
    pass

class CustomWidgets(Widget):
    pass

class DemoApp(App):
    def build(self):
        underlying_layout = CustomGridLayout()
        return underlying_layout

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

demo.kv

<CustomGridLayout>:
    id: underlying_layout
    orientation: 'vertical'
    cols: 1
    row: 2

    ScrollView:
        GridLayout: #<- This is the GridLayout I want to add custom widgets to
            id: list_layout
            cols: 1
            height: self.minimum_height
            row_default_height: 60
            size_hint_y: None
            Label:
                height: 20
                text: 'List:'

    AnchorLayout:
        size_hint_y: .4
        Button:
            text: 'Add List Item'
            on_press: root.add_list_item()

<CustomWidgets>
    StackLayout:
        cols: 3
        rows: 1
        orientation: 'lr-tb'
        #size_hint: self.x , None   #<-- Is there a size_hint I can provide that will adjust size once widget is added?
        height: 80
        Button:
            size_hint: .25, None
        TextInput:
            size_hint: .5, None
        Button:
            size_hint: .25, None

Upvotes: 0

Views: 2153

Answers (1)

John Anderson
John Anderson

Reputation: 39117

I think it will work better if you have your CustomWigets extend StackLayout instead of containing a StackLayout, like this:

class CustomWidgets(StackLayout):
    pass

Then, in your kv file:

<CustomWidgets>
    orientation: 'lr-tb'
    size_hint: 1.0 , None   #<-- Is there a size_hint I can provide that will adjust size once widget is added?
    height: 80
    Button:
        size_hint: .25, None
    TextInput:
        size_hint: .5, None
    Button:
        size_hint: .25, None

the size_hint: 1.0 , None will keep the CustomWidgets width equal to its parents width.

When your CustomWidgets extended Widget and contained a StackLayout, then the size_hint of the contained StackLayout indicates a fraction of its parent, which was the CustomWidgets itself. And the Widget class ignores size_hint, only Layout classes and Window use it.

Upvotes: 1

Related Questions