Search code examples
kivykivymd

Positioning a text field inside a toolbar in Kivy


I'm trying to put a textfield inside a toolbar with KivyMD, but the textfield is always directly against the right side of the window. I tried to adjust it with pos_hint, but none of the values I put for the x-coordinates moved it.

Screen:
canvas.before:
    Rectangle:
        pos: self.pos
        size: self.size
        source: 'assets/bg.png'

BoxLayout:
    orientation: 'vertical'
    MDToolbar:
        id: toolbar
        title: 'Placeholder'
        elevation: 10
        pos_hint: {"top": 1}

        left_action_items: [['menu', lambda x: app.menu.open()]]

        MDTextFieldRound:
            id: textinput
            icon_left: 'magnify'
            pos_hint: {'x': 0.1 ,'center_y': 0.5, 'right': 0.3}
            size_hint: {.6, .4}
            text_color: 'white'
            hint_text: 'Search'**strong text**
        
    MDLabel:
        text: 'Placeholder'
        color: 'white'
        halign: 'center'

Screenshot of toolbar

Any help is appreciated, thanks.


Solution

  • You can insert your widgets wherever you want, for this you can specify a position in the widget tree - add_widget(widget, index). I wrote a special get_widgets function for your solution, which goes through all the widgets in the class. In the example below, you can place the text field on the left, right, and center. Also examine the MDToolbar source code

    from kivy.lang.builder import Builder
    from kivy.metrics import dp
    from kivy.clock import Clock
    from kivy.weakproxy import WeakProxy
    
    from kivymd.app import MDApp
    from kivymd.uix.boxlayout import MDBoxLayout
    from kivymd.uix.textfield import MDTextField
    
    KV = """
    MDScreen:
        MDBoxLayout:
            orientation: 'vertical'
            MDToolbar:
                id: toolbar
                title: 'Placeholder'
                pos_hint: {"top": 1}
    
            MDLabel:
                text: 'Placeholder'
                color: 'white'
                halign: 'center'
    """
    
    
    class TestApp(MDApp):
        def __init__(self, **kwargs):
            super().__init__(**kwargs)
            self.search_content = None
    
        def build(self):
            return Builder.load_string(KV)
    
        def on_start(self):
            Clock.schedule_once(lambda dt: self.add_search('left'))
    
        @staticmethod
        def get_widgets(root: WeakProxy, class_: str):
            """
            :param root: root widget
            :param class_: which subclass are we looking for
            :return:
            """
    
            widgets = []
            for widget in root.walk():
                if widget.__class__.__name__ == class_:
                    widgets.append(widget)
                    print(widget)
    
            return widgets
    
        def add_search(self, side: str):
            """
            :param side: left/right/center
            :return:
            """
            box = self.get_widgets(self.root.ids.toolbar, 'MDBoxLayout')[0]  # get root `MDBoxLayout`
    
            if side == 'left':
                index = 2
            elif side == 'right':
                index = 1
            else:
                index = 0
                self.root.ids.toolbar.ids.label_title.size_hint = None, None
                self.root.ids.toolbar.ids.label_title.opacity = 0
                
                # NOTE: If you remove this `MDLabel`, you cant change `self.theme_cls.material_style`
                # box.remove_widget(self.root.ids.toolbar.ids.label_title)
    
            boxlayout = MDBoxLayout(padding=[dp(18), dp(0), dp(18), dp(18)])
            self.search_content = MDTextField(icon_left='magnify',
                                              mode='round',
                                              color_mode="custom",
                                              line_color_normal=(1, 0, 1, 1),
                                              line_color_focus=(0, 0, 1, 1),
                                              text_color_focus=self.theme_cls.text_color,
                                              text_color_normal=self.theme_cls.text_color[0:3] + [0.7],
                                              hint_text='Empty field',
                                              )
    
            boxlayout.add_widget(self.search_content)
            box.add_widget(boxlayout, index)
    
    
    TestApp().run()