Search code examples
androidpythonlayoutkivyboxlayout

How to increase the size of a layout when more content is added to it in Kivy?


How do I change the size of the BoxLayout widget so that it scrolls vertically when more and more content is added to it? You can run the script below but keep adding more text and click send in order to see the behavior.

Also if you can, i'm also trying to clear the input field messageInput.text after the text is sent for some reason widget.clear_widgets() does nothing.

from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.textinput import TextInput
from kivy.core.window import Window
import datetime as dt
from kivy.uix.scrollview import ScrollView
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout

Window.clearcolor = (252, 235, 233, 0)

class NotificationMsgs(BoxLayout):

    orientation = 'vertical'
    spacing = 10
    padding = [50, 10, 50, 10]

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

        selectMsgsList = ['default dummy text']
        selectCreatedList = ['2017-08-10 00:00:00']

        notifBox = BoxLayout(orientation='vertical')
        # notifBox.bind(minimum_height=notifBox.setter('height'))
        notifScrlv = ScrollView(size_hint=(1,1), do_scroll_x=False, do_scroll_y=True)
        notifScrlv.add_widget(notifBox)

        r = 0
        for _ in zip(selectMsgsList, selectCreatedList):
            myMessage = Label(text="[color=000000]" + selectMsgsList[r] + "[/color]", markup=True)
            dateCreated = Label(text="[color=000000]" + selectCreatedList[r] + "[/color]", markup=True)
            notifBox.add_widget(myMessage)
            notifBox.add_widget(dateCreated)
            r += 1

        self.add_widget(notifScrlv)

        messageInput = TextInput(hint_text='type message...', multiline=True, size_hint_y=None, height=120, padding=30)
        self.add_widget(messageInput)


        def send_notification(self):
            createdDatetimeText = dt.datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S")

            for _ in zip(selectMsgsList, selectCreatedList):
                myMessage = Label(text="[color=000000]" + messageInput.text + "[/color]", markup=True)
                dateCreated = Label(text="[color=000000]" + createdDatetimeText + "[/color]", markup=True)

                # messageInput.clear_widgets()
                notifBox.canvas.ask_update()
                notifScrlv.canvas.ask_update()

                notifBox.add_widget(myMessage)
                notifBox.add_widget(dateCreated)


        self.add_widget(Button(text='send', font_size=40, size_hint_y=None, height=120, on_press=send_notification, background_color=[0,0,1,1], border=[0,1,1,1]))


class NotificationDemoApp(App):
    def build(self):
        return NotificationMsgs()

    def on_pause(self):
        return True

# if __name__ == '__main__':
NotificationDemoApp().run()

Solution

  • enter image description here

    I have solved both your problems. You might want to improve the sizing on your own.

    1. You cannot use a BoxLayout, because it always takes the size of its parent widget. I have substituted it for a GridLayout. There are plenty of descriptions how to use GridLayout and ScrollView together. Such as https://stackoverflow.com/a/19035264/6646710

    2. Next clearing the text ca be achieved by setting the text Property of the TextInput to ""

    Here is the code. I did various changes, ask in the comments if you can't understand them.

    from kivy.uix.button import Button
    from kivy.uix.label import Label
    from kivy.uix.textinput import TextInput
    from kivy.core.window import Window
    import datetime as dt
    from kivy.uix.scrollview import ScrollView
    from kivy.app import App
    from kivy.uix.boxlayout import BoxLayout
    from kivy.uix.gridlayout import GridLayout
    
    
    Window.clearcolor = (252, 235, 233, 0)
    
    class NotificationMsgs(BoxLayout):
    
    
        orientation = 'vertical'
        spacing = 10
        padding = [50, 10, 50, 10]
    
        def __init__(self, **kwargs):
            super(NotificationMsgs, self).__init__(**kwargs)
    
            selectMsgsList = ['default dummy text']
            selectCreatedList = ['2017-08-10 00:00:00']
    
            notifBox = GridLayout(cols=1, size_hint_y=None)
            notifBox.bind(minimum_height = notifBox.setter('height'))
    
            notifScrlv = ScrollView()
            notifScrlv.add_widget(notifBox)
    
            r = 0
            for _ in zip(selectMsgsList, selectCreatedList):
                myMessage = Label(text="[color=000000]" + selectMsgsList[r] + "[/color]", markup=True)
                dateCreated = Label(text="[color=000000]" + selectCreatedList[r] + "[/color]", markup=True)
                notifBox.add_widget(myMessage)
                notifBox.add_widget(dateCreated)
                r += 1
    
            self.add_widget(notifScrlv)
    
            messageInput = TextInput(hint_text='type message...', multiline=True, size_hint_y=None, height=120, padding=30)
            self.add_widget(messageInput)
    
    
            def send_notification(self):
                createdDatetimeText = dt.datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S")
    
                for _ in zip(selectMsgsList, selectCreatedList):
                    myMessage = Label(text="[color=000000]" + messageInput.text + "[/color]", markup=True, size_hint_y=None, size=self.texture_size)
                    dateCreated = Label(text="[color=000000]" + createdDatetimeText + "[/color]", markup=True)
    
                    # messageInput.clear_widgets()
                    notifBox.canvas.ask_update()
                    notifScrlv.canvas.ask_update()
    
                    notifBox.add_widget(myMessage)
                    notifBox.add_widget(dateCreated)
    
                messageInput.text = ""
    
            self.add_widget(Button(text='send', font_size=40, size_hint_y=None, height=120, on_press=send_notification, background_color=[0,0,1,1], border=[0,1,1,1]))
    
    
    class NotificationDemoApp(App):
        def build(self):
            return NotificationMsgs()
    
        def on_pause(self):
            return True
    
    # if __name__ == '__main__':
    NotificationDemoApp().run()