Search code examples
pythonpython-3.xkivykivy-language

Kivy Popup dynamically change height


I have the following Kivy Option Popup

s ='''
<OptionPopup>:
    id: optionPopup
    size_hint : (None,None)
    width : min(0.95 * self.window.width, dp(500))
    title: "Option Title"
    height: content.height
    BoxLayout:
        id: content
        orientation: 'vertical'
        spacing: '5dp'
        height: contentButtons.height + cancelButton.height
        BoxLayout:
            id: contentButtons
            orientation: 'vertical'
            spacing: '0dp'
            height : self.minimum_height

        SettingSpacer:
        Button:
            id:cancelButton
            size_hint_y : None
            height: '50dp'
            text: "Back"
            on_release: optionPopup._dismiss()


'''
Builder.load_string(s)

This Popup exists only once in my application and I will dynamically add Buttons to the optionPopup.ids["contentButtons"]. Meaning the contentButton layout minimum_height gets changed. How can I properly adjust the size of my parent Boxlayouts content and the PopUp windows? The above kv options seem to do the right thing like binding optionPopup.height to content.height, but it does not work?

The popup


Solution

  • The correct kv settings are

    s ='''
    <OptionPopup>:
        id: optionPopup
        size_hint : (None,None)
        width : min(0.95 * self.window.width, dp(500))
        title: "Option Title"
        height: dp(content.height) + dp(80)
        BoxLayout:
            id: content
            size_hint : (1,None)
            orientation: 'vertical'
            spacing: '5dp'
            height: dp(content.minimum_height)
            BoxLayout:
                size_hint : (1,None)
                id: contentButtons
                orientation: 'vertical'
                spacing: '0dp'
                height : dp(self.minimum_height)
    
            SettingSpacer:
            Button:
                id:cancelButton
                size_hint_y : None
                height: '50dp'
                text: "Back"
                on_release: optionPopup._dismiss()
    
    
    '''
    Builder.load_string(s)
    
    class OptionPopup(Popup): 
        def __init__(self,**kwargs):
            self.window= Window
            super(OptionPopup,self).__init__(**kwargs)
            self.content = self.ids["content"]
            self.contentButtons = self.ids["contentButtons"]
    
        def _dismiss(self,*largs):
            self.dismiss()
    
        def open(self):
            super(OptionPopup,self).open()
    
        def _validate(self,instance):
            if self.optionCallBack is not None:
                self.optionCallBack(instance.optId)
            self.dismiss()
    
        def setOptions(self,options, callBack):
            self.optionCallBack = callBack
            print('OptionPopup::setOptions', options)
            print('OptionPopup::setOptionCallback: \n option changes go to: ',self.optionCallBack)
            self.contentButtons.clear_widgets()
            for optId,name in options.items():
                b = Button(text=name, size_hint_y=None, height='50dp')
                b.optId = optId
                b.bind(on_release=self._validate)
                self.contentButtons.add_widget(b)
    
        def setTitle(self,text):
            self.title = text
    

    You can test this code by adding it to your application:

    # Test the popup
    o = OptionPopup()
    o.setOptions({'opt1' : 'Options 1','opt2' : 'Options 2', 'opt3' : 'Options 3'})
    o.open()