Search code examples
pythonlayoutkivykivy-language

Python kivy md Navigation Bar placement?


I am trying to restructure the kivymd project file but I am not able to place the navigation bar at the place at which it is normally. I cannot see why this is happening (see pictures and code below).

This is how it looks like enter image description here enter image description here

and this is how it should look like enter image description here enter image description here

I am using the three files app.py, app.kv and labels.py (for injecting labels from a *.py file).

# app.kv
# -*- coding: utf-8 -*-

import os

import kivy.app
from kivy.lang import Builder
from application.kivymd.list import BaseListItem
from application.kivymd.material_resources import DEVICE_TYPE
from application.kivymd.navigationdrawer import MDNavigationDrawer, NavigationDrawerHeaderBase
from application.kivymd.theming import ThemeManager

    # User defined imports
    from kivy.core.window import Window

    Window.fullscreen = "auto"


    class HackedDemoNavDrawer(MDNavigationDrawer):
        # DO NOT USE
        def add_widget(self, widget, index=0):
            if issubclass(widget.__class__, BaseListItem):
                self._list.add_widget(widget, index)
                if len(self._list.children) == 1:
                    widget._active = True
                    self.active_item = widget
                # widget.bind(on_release=lambda x: self.panel.toggle_state())
                widget.bind(on_release=lambda x: x._set_active(True, list=self))
            elif issubclass(widget.__class__, NavigationDrawerHeaderBase):
                self._header_container.add_widget(widget)
            else:
                super(MDNavigationDrawer, self).add_widget(widget, index)


    class MainApp(kivy.app.App):
        theme_cls = ThemeManager()
        title = "Application"

        def build(self):
            main_widget = Builder.load_file(
                os.path.join(os.path.dirname(__file__), "./app.kv")
            )
            # self.theme_cls.theme_style = 'Dark'

            main_widget.ids.text_field_error.bind(
                on_text_validate=self.set_error_message,
                on_focus=self.set_error_message)
            self.bottom_navigation_remove_mobile(main_widget)
            return main_widget

        def bottom_navigation_remove_mobile(self, widget):
            # Removes some items from bottom-navigation demo when on mobile
            if DEVICE_TYPE == 'mobile':
                widget.ids.bottom_navigation_demo.remove_widget(widget.ids.bottom_navigation_desktop_2)
            if DEVICE_TYPE == 'mobile' or DEVICE_TYPE == 'tablet':
                widget.ids.bottom_navigation_demo.remove_widget(widget.ids.bottom_navigation_desktop_1)

        def set_error_message(self, *args):
            if len(self.root.ids.text_field_error.text) == 2:
                self.root.ids.text_field_error.error = True
            else:
                self.root.ids.text_field_error.error = False

        def on_pause(self):
            return True

        def on_stop(self):
            pass


    if __name__ == '__main__':
        MainApp().run()

This is the app.kv file which is injected into the app.py file

# app.kv
#:import Toolbar application.kivymd.toolbar.Toolbar
#:import MDNavigationDrawer application.kivymd.navigationdrawer.MDNavigationDrawer
#:import NavigationLayout application.kivymd.navigationdrawer.NavigationLayout
#:import NavigationDrawerDivider application.kivymd.navigationdrawer.NavigationDrawerDivider
#:import NavigationDrawerToolbar application.kivymd.navigationdrawer.NavigationDrawerToolbar
#:import NavigationDrawerSubheader application.kivymd.navigationdrawer.NavigationDrawerSubheader
#:import MDCheckbox application.kivymd.selectioncontrols.MDCheckbox
#:import MDSwitch application.kivymd.selectioncontrols.MDSwitch
#:import MDTextField application.kivymd.textfields.MDTextField
#:import MDThemePicker application.kivymd.theme_picker.MDThemePicker
#:import labels application.labels

NavigationLayout:
    id: nav_layout
    MDNavigationDrawer:
        id: nav_drawer
        NavigationDrawerToolbar:
            title: labels.NAVIGATION
        NavigationDrawerIconButton:
            icon: 'checkbox-blank-circle'
            text: labels.DASHBOARD
            on_release: app.root.ids.scr_mngr.current = 'dashboard'
        NavigationDrawerIconButton:
            icon: 'checkbox-blank-circle'
            text: labels.SYSTEM_INSPECTOR
            on_release: app.root.ids.scr_mngr.current = 'system_inspector'
        NavigationDrawerIconButton:
            icon: 'checkbox-blank-circle'
            text: labels.SYSTEM_PARAMETERS
            on_release: app.root.ids.scr_mngr.current = 'system_parameters'
    BoxLayout:
        orientation: 'vertical'
        halign: "center"
        Toolbar:
            id: toolbar
            title: labels.APPLICATION_NAME
            md_bg_color: app.theme_cls.primary_color
            background_palette: 'Primary'
            background_hue: '500'
            left_action_items: [['menu', lambda x: app.root.toggle_nav_drawer()]]
            #right_action_items: [['dots-vertical', lambda x: app.root.toggle_nav_drawer()]]
        ScreenManager:
            id: scr_mngr
            Screen:
                name: 'dashboard'
                MDLabel:
                    font_style: 'Body1'
                    theme_text_color: 'Primary'
                    text: "This is the dashboard!"
                    size_hint_x:None
                    width: '250dp'
                    halign: "center"
                    pos_hint: {"center_x": 0.50, "center_y": 0.75}
                MDCheckbox:
                    id:            grp_chkbox_1
                    group:        'test'
                    size_hint:    None, None
                    size:        dp(48), dp(48)
                    pos_hint:    {'center_x': 0.25, 'center_y': 0.5}
                MDCheckbox:
                    id:            grp_chkbox_2
                    group:        'test'
                    size_hint:    None, None
                    size:        dp(48), dp(48)
                    pos_hint:    {'center_x': 0.5, 'center_y': 0.5}
                MDSwitch:
                    size_hint:    None, None
                    size:        dp(36), dp(48)
                    pos_hint:    {'center_x': 0.75, 'center_y': 0.5}
                    _active:        False
            Screen:
                name: 'system_inspector'
                MDLabel:
                    font_style: 'Body1'
                    theme_text_color: 'Primary'
                    text: "This is the system_inspector page!"
                    size_hint_x:None
                    width: '250dp'
                    halign: "center"
                    pos_hint: {"center_x": 0.50, "center_y": 0.75}
                MDCheckbox:
                    id:            grp_chkbox_1
                    group:        'test'
                    size_hint:    None, None
                    size:        dp(48), dp(48)
                    pos_hint:    {'center_x': 0.25, 'center_y': 0.5}
                MDCheckbox:
                    id:            grp_chkbox_2
                    group:        'test'
                    size_hint:    None, None
                    size:        dp(48), dp(48)
                    pos_hint:    {'center_x': 0.5, 'center_y': 0.5}
                MDSwitch:
                    size_hint:    None, None
                    size:        dp(36), dp(48)
                    pos_hint:    {'center_x': 0.75, 'center_y': 0.5}
                    _active:        False
            Screen:
                name: 'system_parameters'
                BoxLayout:
                    orientation: "horizontal"
                    BoxLayout:
                        orientation: 'vertical'
                        size_hint_y: None
                        height: self.minimum_height
                        padding: dp(48)
                        spacing: 10
                        MDTextField:
                            hint_text: "No helper text"
                            input_filter: "float"
                        MDTextField:
                            hint_text: "Helper text on focus"
                            helper_text: "This will disappear when you click off"
                            helper_text_mode: "on_focus"
                            input_filter: "int"
                        MDTextField:
                            hint_text: "No helper text"
                        MDTextField:
                            hint_text: "Helper text on focus"
                            helper_text: "This will disappear when you click off"
                            helper_text_mode: "on_focus"
                    BoxLayout:
                        orientation: 'vertical'
                        size_hint_y: None
                        height: self.minimum_height
                        padding: dp(48)
                        spacing: 10
                        MDTextField:
                            hint_text: "No helper text"
                        MDTextField:
                            hint_text: "Helper text on focus"
                            helper_text: "This will disappear when you click off"
                            helper_text_mode: "on_focus"
                        MDTextField:
                            hint_text: "No helper text"
                        MDTextField:
                            hint_text: "Helper text on focus"
                            helper_text: "This will disappear when you click off"
                            helper_text_mode: "on_focus"
            Screen:
                name: 'textfields'
                ScrollView:
                    BoxLayout:
                        orientation: 'vertical'
                        size_hint_y: None
                        height: self.minimum_height
                        padding: dp(48)
                        spacing: 10
                        MDTextField:
                            hint_text: "No helper text"
                        MDTextField:
                            hint_text: "Helper text on focus"
                            helper_text: "This will disappear when you click off"
                            helper_text_mode: "on_focus"
                        MDTextField:
                            hint_text: "Persistent helper text"
                            helper_text: "Text is always here"
                            helper_text_mode: "persistent"
                        MDTextField:
                            id: text_field_error
                            hint_text: "Helper text on error (Hit Enter with two characters here)"
                            helper_text: "Two is my least favorite number"
                            helper_text_mode: "on_error"
                        MDTextField:
                            hint_text: "Max text length = 10"
                            max_text_length: 10
                        MDTextField:
                            hint_text: "required = True"
                            required: True
                            helper_text_mode: "on_error"
                        MDTextField:
                            multiline: True
                            hint_text: "Multi-line text"
                            helper_text: "Messages are also supported here"
                            helper_text_mode: "persistent"
                        MDTextField:
                            hint_text: "color_mode = \'accent\'"
                            color_mode: 'accent'
                        MDTextField:
                            hint_text: "color_mode = \'custom\'"
                            color_mode: 'custom'
                            helper_text_mode: "on_focus"
                            helper_text: "Color is defined by \'line_color_focus\' property"
                            line_color_focus: self.theme_cls.opposite_bg_normal  # This is the color used by the textfield
                        MDTextField:
                            hint_text: "disabled = True"
                            disabled: True
            Screen:
                name: 'nav_drawer'
                HackedDemoNavDrawer:
                    # NavigationDrawerToolbar:
                    #     title: "Navigation Drawer Widgets"
                    NavigationDrawerIconButton:
                        icon: 'checkbox-blank-circle'
                        text: "Badge text ---->"
                        badge_text: "99+"
                    NavigationDrawerIconButton:
                        active_color_type: 'accent'
                        text: "Accent active color"
                    NavigationDrawerIconButton:
                        active_color_type: 'custom'
                        text: "Custom active color"
                        active_color: [1, 0, 1, 1]
                    NavigationDrawerIconButton:
                        use_active: False
                        text: "Use active = False"
                    NavigationDrawerIconButton:
                        text: "Different icon"
                        icon: 'alarm'
                    NavigationDrawerDivider:
                    NavigationDrawerSubheader:
                        text: "NavigationDrawerSubheader"
                    NavigationDrawerIconButton:
                        text: "NavigationDrawerDivider \/"
                    NavigationDrawerDivider:

Here is the labels.py file for injecting the labels into the kv file.

# labels.py
APPLICATION_NAME = "Application"
NAVIGATION = "Navigation"
DASHBOARD = "Dashboard"
SYSTEM_INSPECTOR = "System Inspector"
SYSTEM_PARAMETERS = "System Parameters"

Solution

  • Solution

    You might have a kv file with a name, main.kv

    With KivyMD installed on my machine, and some minor changes, the KivyMD App ran fine.

    Example

    app.py

    # app.py
    # -*- coding: utf-8 -*-
    
    import os
    
    from kivy.app import App
    from kivy.lang import Builder
    
    from kivymd.list import BaseListItem
    from kivymd.material_resources import DEVICE_TYPE
    from kivymd.navigationdrawer import MDNavigationDrawer, NavigationDrawerHeaderBase
    from kivymd.theming import ThemeManager
    
    # User defined imports
    from kivy.core.window import Window
    
    # Window.fullscreen = "auto"
    
    
    class HackedDemoNavDrawer(MDNavigationDrawer):
        # DO NOT USE
        def add_widget(self, widget, index=0):
            if issubclass(widget.__class__, BaseListItem):
                self._list.add_widget(widget, index)
                if len(self._list.children) == 1:
                    widget._active = True
                    self.active_item = widget
                # widget.bind(on_release=lambda x: self.panel.toggle_state())
                widget.bind(on_release=lambda x: x._set_active(True, list=self))
            elif issubclass(widget.__class__, NavigationDrawerHeaderBase):
                self._header_container.add_widget(widget)
            else:
                super(MDNavigationDrawer, self).add_widget(widget, index)
    
    
    class MainApp(App):
        theme_cls = ThemeManager()
        title = "Application"
    
        def build(self):
            main_widget = Builder.load_file(
                os.path.join(os.path.dirname(__file__), "./app.kv")
            )
            # self.theme_cls.theme_style = 'Dark'
    
            main_widget.ids.text_field_error.bind(
                on_text_validate=self.set_error_message,
                on_focus=self.set_error_message)
            self.bottom_navigation_remove_mobile(main_widget)
            return main_widget
    
        def bottom_navigation_remove_mobile(self, widget):
            # Removes some items from bottom-navigation demo when on mobile
            if DEVICE_TYPE == 'mobile':
                widget.ids.bottom_navigation_demo.remove_widget(widget.ids.bottom_navigation_desktop_2)
            if DEVICE_TYPE == 'mobile' or DEVICE_TYPE == 'tablet':
                widget.ids.bottom_navigation_demo.remove_widget(widget.ids.bottom_navigation_desktop_1)
    
        def set_error_message(self, *args):
            if len(self.root.ids.text_field_error.text) == 2:
                self.root.ids.text_field_error.error = True
            else:
                self.root.ids.text_field_error.error = False
    
        def on_pause(self):
            return True
    
        def on_stop(self):
            pass
    
    
    if __name__ == '__main__':
        MainApp().run()
    

    labels.py

    # labels.py
    APPLICATION_NAME = "Application"
    NAVIGATION = "Navigation"
    DASHBOARD = "Dashboard"
    SYSTEM_INSPECTOR = "System Inspector"
    SYSTEM_PARAMETERS = "System Parameters"
    

    app.kv

    # app.kv
    #:kivy 1.11.0
    #:import Toolbar kivymd.toolbar.Toolbar
    #:import MDNavigationDrawer kivymd.navigationdrawer.MDNavigationDrawer
    #:import NavigationLayout kivymd.navigationdrawer.NavigationLayout
    #:import NavigationDrawerDivider kivymd.navigationdrawer.NavigationDrawerDivider
    #:import NavigationDrawerToolbar kivymd.navigationdrawer.NavigationDrawerToolbar
    #:import NavigationDrawerSubheader kivymd.navigationdrawer.NavigationDrawerSubheader
    #:import MDCheckbox kivymd.selectioncontrols.MDCheckbox
    #:import MDSwitch kivymd.selectioncontrols.MDSwitch
    #:import MDTextField kivymd.textfields.MDTextField
    #:import MDThemePicker kivymd.theme_picker.MDThemePicker
    #:import labels labels
    
    NavigationLayout:
        id: nav_layout
        MDNavigationDrawer:
            id: nav_drawer
            NavigationDrawerToolbar:
                title: labels.NAVIGATION
            NavigationDrawerIconButton:
                icon: 'checkbox-blank-circle'
                text: labels.DASHBOARD
                on_release: app.root.ids.scr_mngr.current = 'dashboard'
            NavigationDrawerIconButton:
                icon: 'checkbox-blank-circle'
                text: labels.SYSTEM_INSPECTOR
                on_release: app.root.ids.scr_mngr.current = 'system_inspector'
            NavigationDrawerIconButton:
                icon: 'checkbox-blank-circle'
                text: labels.SYSTEM_PARAMETERS
                on_release: app.root.ids.scr_mngr.current = 'system_parameters'
        BoxLayout:
            orientation: 'vertical'
            halign: "center"
            Toolbar:
                id: toolbar
                title: labels.APPLICATION_NAME
                md_bg_color: app.theme_cls.primary_color
                background_palette: 'Primary'
                background_hue: '500'
                left_action_items: [['menu', lambda x: app.root.toggle_nav_drawer()]]
                #right_action_items: [['dots-vertical', lambda x: app.root.toggle_nav_drawer()]]
            ScreenManager:
                id: scr_mngr
                Screen:
                    name: 'dashboard'
                    MDLabel:
                        font_style: 'Body1'
                        theme_text_color: 'Primary'
                        text: "This is the dashboard!"
                        size_hint_x:None
                        width: '250dp'
                        halign: "center"
                        pos_hint: {"center_x": 0.50, "center_y": 0.75}
                    MDCheckbox:
                        id:            grp_chkbox_1
                        group:        'test'
                        size_hint:    None, None
                        size:        dp(48), dp(48)
                        pos_hint:    {'center_x': 0.25, 'center_y': 0.5}
                    MDCheckbox:
                        id:            grp_chkbox_2
                        group:        'test'
                        size_hint:    None, None
                        size:        dp(48), dp(48)
                        pos_hint:    {'center_x': 0.5, 'center_y': 0.5}
                    MDSwitch:
                        size_hint:    None, None
                        size:        dp(36), dp(48)
                        pos_hint:    {'center_x': 0.75, 'center_y': 0.5}
                        _active:        False
                Screen:
                    name: 'system_inspector'
                    MDLabel:
                        font_style: 'Body1'
                        theme_text_color: 'Primary'
                        text: "This is the system_inspector page!"
                        size_hint_x:None
                        width: '250dp'
                        halign: "center"
                        pos_hint: {"center_x": 0.50, "center_y": 0.75}
                    MDCheckbox:
                        id:            grp_chkbox_1
                        group:        'test'
                        size_hint:    None, None
                        size:        dp(48), dp(48)
                        pos_hint:    {'center_x': 0.25, 'center_y': 0.5}
                    MDCheckbox:
                        id:            grp_chkbox_2
                        group:        'test'
                        size_hint:    None, None
                        size:        dp(48), dp(48)
                        pos_hint:    {'center_x': 0.5, 'center_y': 0.5}
                    MDSwitch:
                        size_hint:    None, None
                        size:        dp(36), dp(48)
                        pos_hint:    {'center_x': 0.75, 'center_y': 0.5}
                        _active:        False
                Screen:
                    name: 'system_parameters'
                    BoxLayout:
                        orientation: "horizontal"
                        BoxLayout:
                            orientation: 'vertical'
                            size_hint_y: None
                            height: self.minimum_height
                            padding: dp(48)
                            spacing: 10
                            MDTextField:
                                hint_text: "No helper text"
                                input_filter: "float"
                            MDTextField:
                                hint_text: "Helper text on focus"
                                helper_text: "This will disappear when you click off"
                                helper_text_mode: "on_focus"
                                input_filter: "int"
                            MDTextField:
                                hint_text: "No helper text"
                            MDTextField:
                                hint_text: "Helper text on focus"
                                helper_text: "This will disappear when you click off"
                                helper_text_mode: "on_focus"
                        BoxLayout:
                            orientation: 'vertical'
                            size_hint_y: None
                            height: self.minimum_height
                            padding: dp(48)
                            spacing: 10
                            MDTextField:
                                hint_text: "No helper text"
                            MDTextField:
                                hint_text: "Helper text on focus"
                                helper_text: "This will disappear when you click off"
                                helper_text_mode: "on_focus"
                            MDTextField:
                                hint_text: "No helper text"
                            MDTextField:
                                hint_text: "Helper text on focus"
                                helper_text: "This will disappear when you click off"
                                helper_text_mode: "on_focus"
                Screen:
                    name: 'textfields'
                    ScrollView:
                        BoxLayout:
                            orientation: 'vertical'
                            size_hint_y: None
                            height: self.minimum_height
                            padding: dp(48)
                            spacing: 10
                            MDTextField:
                                hint_text: "No helper text"
                            MDTextField:
                                hint_text: "Helper text on focus"
                                helper_text: "This will disappear when you click off"
                                helper_text_mode: "on_focus"
                            MDTextField:
                                hint_text: "Persistent helper text"
                                helper_text: "Text is always here"
                                helper_text_mode: "persistent"
                            MDTextField:
                                id: text_field_error
                                hint_text: "Helper text on error (Hit Enter with two characters here)"
                                helper_text: "Two is my least favorite number"
                                helper_text_mode: "on_error"
                            MDTextField:
                                hint_text: "Max text length = 10"
                                max_text_length: 10
                            MDTextField:
                                hint_text: "required = True"
                                required: True
                                helper_text_mode: "on_error"
                            MDTextField:
                                multiline: True
                                hint_text: "Multi-line text"
                                helper_text: "Messages are also supported here"
                                helper_text_mode: "persistent"
                            MDTextField:
                                hint_text: "color_mode = \'accent\'"
                                color_mode: 'accent'
                            MDTextField:
                                hint_text: "color_mode = \'custom\'"
                                color_mode: 'custom'
                                helper_text_mode: "on_focus"
                                helper_text: "Color is defined by \'line_color_focus\' property"
                                line_color_focus: self.theme_cls.opposite_bg_normal  # This is the color used by the textfield
                            MDTextField:
                                hint_text: "disabled = True"
                                disabled: True
                Screen:
                    name: 'nav_drawer'
                    HackedDemoNavDrawer:
                        # NavigationDrawerToolbar:
                        #     title: "Navigation Drawer Widgets"
                        NavigationDrawerIconButton:
                            icon: 'checkbox-blank-circle'
                            text: "Badge text ---->"
                            badge_text: "99+"
                        NavigationDrawerIconButton:
                            active_color_type: 'accent'
                            text: "Accent active color"
                        NavigationDrawerIconButton:
                            active_color_type: 'custom'
                            text: "Custom active color"
                            active_color: [1, 0, 1, 1]
                        NavigationDrawerIconButton:
                            use_active: False
                            text: "Use active = False"
                        NavigationDrawerIconButton:
                            text: "Different icon"
                            icon: 'alarm'
                        NavigationDrawerDivider:
                        NavigationDrawerSubheader:
                            text: "NavigationDrawerSubheader"
                        NavigationDrawerIconButton:
                            text: "NavigationDrawerDivider \/"
                        NavigationDrawerDivider:
    

    Output

    Img01 Img02 Img03 Img04