Quantcast
Channel: Planet Python
Viewing all articles
Browse latest Browse all 22462

Codementor: Customizing your Navigation Drawer in Kivy & KivyMD

$
0
0

Kivy & KivyMD: NavigationDrawer

Kivy is an open source, cross-platform Python framework for the development of applications that makes use of innovative, multi-touch user interfaces.

KivyMD is a collection of Material Design compliant widgets for use with Kivy.

Prerequisites

This tutorial is meant for those who have a little or good familiarity with Kivy but don’t know how to move forward with implementing their own widgets or for those who don’t find Kivy visually attractive.

Some really cool resources for you:

Content

  • KivyMD’s Navigation Drawer.
  • Modify the Navigation Drawer by replacing the Title with a Circular image

Structure

Before you start, make sure that you have this file structure.
Download the files from here.

- navigationdrawer
    - __init__.py  # our modified navigarion drawer.
- kivymd
    - ...
    - navigationdrawer.py
    - ...
- images # contains the image
    - me.jpg
- main.py

Before we start let’s see how our main.py looks like.

  • NavigateApp class
    • Navigator’s object
    • Theme class’s object
  • Navigator class
    • NavigationDrawerIconButton

And we also have:

kivy

main.py

    from kivy.app import App
    from kivy.lang import Builder
    from kivy.properties import ObjectProperty, StringProperty
    from kivymd.theming import ThemeManager
    from kivymd.navigationdrawer import NavigationDrawer
    # from navigationdrawer import NavigationDrawer

    main_widget_kv = '''
    #:import Toolbar kivymd.toolbar.Toolbar

    BoxLayout:
        orientation: 'vertical'
        Toolbar:
            id: toolbar
            title: 'Welcome'
            background_color: app.theme_cls.primary_dark
            left_action_items: [['menu', lambda x: app.nav_drawer.toggle()]]
            right_action_items: [['more-vert', lambda x: app.raised_button.open(self.parent)]]
        Label:

    <Navigator>:
        NavigationDrawerIconButton:
            icon: 'face'
            text: 'Kuldeep Singh'
        NavigationDrawerIconButton:
            icon: 'email'
            text: 'kuldeepbb.grewal@gmail.com'
            on_release: app.root.ids.scr_mngr.current = 'bottomsheet'
        NavigationDrawerIconButton:
            icon: 'phone'
            text: '+91-7727XXXXXX'
        NavigationDrawerIconButton:
            icon: 'cake'
            text: '26/11/1994'
        NavigationDrawerIconButton:
            icon: 'city-alt'
            text: 'Rohtak'
        NavigationDrawerIconButton:
            icon: 'settings'
            text: 'Settings'
    '''

    class Navigator(NavigationDrawer):
        image_source = StringProperty('images/me.png')

    class NavigateApp(App):
        theme_cls = ThemeManager()
        nav_drawer = ObjectProperty()

        def build(self):
            main_widget = Builder.load_string(main_widget_kv)
            self.nav_drawer = Navigator()
            return main_widget

    NavigateApp().run()

Now that we have seen how the Navigation Drawer looks like, let’s look at its source code.


kivymd/navigationdrawer.py

    # -*- coding: utf-8 -*-
    from kivy.lang import Builder
    from kivymd.label import MDLabel 
    from kivy.animation import Animation
    from kivymd.slidingpanel import SlidingPanel
    from kivymd.icon_definitions import md_icons
    from kivymd.theming import ThemableBehavior
    from kivymd.elevationbehavior import ElevationBehavior
    from kivy.properties import StringProperty, ObjectProperty
    from kivymd.list import OneLineIconListItem, ILeftBody, BaseListItem

    Builder.load_string('''
    <NavDrawerToolbar@Toolbar>
        canvas:
            Color:
                rgba: root.theme_cls.divider_color
            Line:
                points: self.x, self.y, self.x+self.width,self.y

    <NavigationDrawer>
        _list: list
        elevation: 0
        canvas:
            Color:
                rgba: root.theme_cls.bg_light
            Rectangle:
                size: root.size
                pos: root.pos
        NavDrawerToolbar:
            title: root.title
            opposite_colors: False
            title_theme_color: 'Secondary'
            background_color: root.theme_cls.bg_light
            elevation: 0
        ScrollView:
            do_scroll_x: False
            MDList:
                id: ml
                id: list

    <NavigationDrawerIconButton>
        NDIconLabel:
            id: _icon
            font_style: 'Icon'
            theme_text_color: 'Secondary'
    ''')

    class NavigationDrawer(SlidingPanel, ThemableBehavior, ElevationBehavior):
        title = StringProperty()
        _list = ObjectProperty()

        def add_widget(self, widget, index=0):
            if issubclass(widget.__class__, BaseListItem):
                self._list.add_widget(widget, index)
                widget.bind(on_release=lambda x: self.toggle())
            else:
                super(NavigationDrawer, self).add_widget(widget, index)

        def _get_main_animation(self, duration, t, x, is_closing):
            a = super(NavigationDrawer, self)._get_main_animation(duration, t, x,
                                                                  is_closing)
            a &= Animation(elevation=0 if is_closing else 5, t=t, duration=duration)
            return a

    class NDIconLabel(ILeftBody, MDLabel):
        pass

    class NavigationDrawerIconButton(OneLineIconListItem):
        icon = StringProperty()

        def on_icon(self, instance, value):
            self.ids['_icon'].text = u"{}".format(md_icons[value])

Here we see that NavigationDrawer class has a widget named as NavDrawerToolbar which contains the Title property.
We want to add a Circular Image there.

How to do it? By modifying the NavigationDrawer class.

Modify the Navigation Drawer by replacing the title with a circular image

Modification in the kv lang.

Original:

<NavigationDrawer>
        ...
        NavDrawerToolbar:
            title: root.title
            opposite_colors: False
            title_theme_color: 'Secondary'
            background_color: root.theme_cls.bg_light
            elevation: 0
        ...

Modified:

<NavigationDrawer>
        ...
        BoxLayout:
            size_hint: (1, .4)
            NavDrawerToolbar:
                padding: 10, 10
                canvas.after:
                    Color:
                        rgba: (1, 1, 1, 1)
                    RoundedRectangle:
                        size: (self.size[1]-dp(14), self.size[1]-dp(14))
                        pos: (self.pos[0]+(self.size[0]-self.size[1])/2, self.pos[1]+dp(7))
                        source: root.image_source
                        radius: [self.size[1]-(self.size[1]/2)]
        ...

Modification on the Python side.

Original:

    class NavigationDrawer(SlidingPanel, ThemableBehavior, ElevationBehavior):
        title = StringProperty()
        ...

Modified:

    class NavigationDrawer(SlidingPanel, ThemableBehavior, ElevationBehavior):
        image_source = StringProperty()
        ...

Modified Navigationdrawer.py

navigationdrawer/__init__.py

    # -*- coding: utf-8 -*-
    from kivy.animation import Animation
    from kivy.lang import Builder
    from kivy.properties import StringProperty, ObjectProperty
    from kivymd.elevationbehavior import ElevationBehavior
    from kivymd.icon_definitions import md_icons
    from kivymd.label import MDLabel
    from kivymd.list import OneLineIconListItem, ILeftBody, BaseListItem
    from kivymd.slidingpanel import SlidingPanel
    from kivymd.theming import ThemableBehavior

    Builder.load_string('''
    <NavDrawerToolbar@Label>
        canvas:
            Color:
                rgba: root.parent.parent.theme_cls.divider_color
            Line:
                points: self.x, self.y, self.x+self.width,self.y

    <NavigationDrawer>
        _list: list
        elevation: 0
        canvas:
            Color:
                rgba: root.theme_cls.bg_light
            Rectangle:
                size: root.size
                pos: root.pos
        BoxLayout:
            size_hint: (1, .4)
            NavDrawerToolbar:
                padding: 10, 10
                canvas.after:
                    Color:
                        rgba: (1, 1, 1, 1)
                    RoundedRectangle:
                        size: (self.size[1]-dp(14), self.size[1]-dp(14))
                        pos: (self.pos[0]+(self.size[0]-self.size[1])/2, self.pos[1]+dp(7))
                        source: root.image_source
                        radius: [self.size[1]-(self.size[1]/2)]

        ScrollView:
            do_scroll_x: False
            MDList:
                id: ml
                id: list

    <NavigationDrawerIconButton>
        NDIconLabel:
            id: _icon
            font_style: 'Icon'
            theme_text_color: 'Secondary'
    ''')

    class NavigationDrawer(SlidingPanel, ThemableBehavior, ElevationBehavior):
        image_source = StringProperty()
        _list = ObjectProperty()

        def add_widget(self, widget, index=0):
            if issubclass(widget.__class__, BaseListItem):
                self._list.add_widget(widget, index)
                widget.bind(on_release=lambda x: self.toggle())
            else:
                super(NavigationDrawer, self).add_widget(widget, index)

        def _get_main_animation(self, duration, t, x, is_closing):
            a = super(NavigationDrawer, self)._get_main_animation(duration, t, x,
                                                                  is_closing)
            a &= Animation(elevation=0 if is_closing else 5, t=t, duration=duration)
            return a

    class NDIconLabel(ILeftBody, MDLabel):
        pass

    class NavigationDrawerIconButton(OneLineIconListItem):
        icon = StringProperty()

        def on_icon(self, instance, value):
            self.ids['_icon'].text = u"{}".format(md_icons[value])

Now that we have modified our Navigation Drawer let’s test it.

But before you do, make sure you uncomment NavigationDrawer from the navigationdrawer folder and comment out the NavigationDrawer from the kivymd in the main.py file.

    # from kivymd.navigationdrawer import NavigationDrawer
    from navigationdrawer import NavigationDrawer

And here it is. Our Navigation Drawer with a circular image.

kivy

About me

My online existence is mainly here at Codementor and at these places :)

Thank you.


Viewing all articles
Browse latest Browse all 22462

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>