770 lines
22 KiB
Python
770 lines
22 KiB
Python
"""
|
|
Components/NavigationRail
|
|
=========================
|
|
|
|
.. versionadded:: 1.0.0
|
|
|
|
.. seealso::
|
|
|
|
`Material Design spec, Navigation rail <https://m3.material.io/components/navigation-rail/overview>`_
|
|
|
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/navigation-rail.png
|
|
:align: center
|
|
|
|
.. rubric:: Navigation rails let people switch between UI views on mid-sized
|
|
devices.
|
|
|
|
- Can contain 3-7 destinations plus an optional FAB
|
|
- Always put the rail in the same place, even on different screens of an app
|
|
|
|
Example
|
|
-------
|
|
|
|
.. tabs::
|
|
|
|
.. tab:: Declarative KV style
|
|
|
|
.. code-block:: python
|
|
|
|
from kivy.lang import Builder
|
|
from kivy.properties import StringProperty
|
|
|
|
from kivymd.app import MDApp
|
|
from kivymd.uix.navigationrail import MDNavigationRailItem
|
|
|
|
KV = '''
|
|
<CommonNavigationRailItem>
|
|
|
|
MDNavigationRailItemIcon:
|
|
icon: root.icon
|
|
|
|
MDNavigationRailItemLabel:
|
|
text: root.text
|
|
|
|
|
|
MDBoxLayout:
|
|
|
|
MDNavigationRail:
|
|
type: "selected"
|
|
|
|
MDNavigationRailMenuButton:
|
|
icon: "menu"
|
|
|
|
MDNavigationRailFabButton:
|
|
icon: "home"
|
|
|
|
CommonNavigationRailItem:
|
|
icon: "folder-outline"
|
|
text: "Files"
|
|
|
|
CommonNavigationRailItem:
|
|
icon: "bookmark-outline"
|
|
text: "Bookmark"
|
|
|
|
CommonNavigationRailItem:
|
|
icon: "library-outline"
|
|
text: "Library"
|
|
|
|
MDScreen:
|
|
md_bg_color: self.theme_cls.secondaryContainerColor
|
|
'''
|
|
|
|
|
|
class CommonNavigationRailItem(MDNavigationRailItem):
|
|
text = StringProperty()
|
|
icon = StringProperty()
|
|
|
|
|
|
class Example(MDApp):
|
|
def build(self):
|
|
return Builder.load_string(KV)
|
|
|
|
|
|
Example().run()
|
|
|
|
.. tab:: Declarative python style
|
|
|
|
.. code-block:: python
|
|
|
|
from kivy.clock import Clock
|
|
from kivy.properties import StringProperty
|
|
|
|
from kivymd.app import MDApp
|
|
from kivymd.uix.boxlayout import MDBoxLayout
|
|
from kivymd.uix.navigationrail import (
|
|
MDNavigationRailItem,
|
|
MDNavigationRail,
|
|
MDNavigationRailMenuButton,
|
|
MDNavigationRailFabButton,
|
|
MDNavigationRailItemIcon,
|
|
MDNavigationRailItemLabel,
|
|
)
|
|
from kivymd.uix.screen import MDScreen
|
|
|
|
|
|
class CommonNavigationRailItem(MDNavigationRailItem):
|
|
text = StringProperty()
|
|
icon = StringProperty()
|
|
|
|
def on_icon(self, instance, value):
|
|
def on_icon(*ars):
|
|
self.add_widget(MDNavigationRailItemIcon(icon=value))
|
|
Clock.schedule_once(on_icon)
|
|
|
|
def on_text(self, instance, value):
|
|
def on_text(*ars):
|
|
self.add_widget(MDNavigationRailItemLabel(text=value))
|
|
Clock.schedule_once(on_text)
|
|
|
|
|
|
class Example(MDApp):
|
|
def build(self):
|
|
return MDBoxLayout(
|
|
MDNavigationRail(
|
|
MDNavigationRailMenuButton(
|
|
icon="menu",
|
|
),
|
|
MDNavigationRailFabButton(
|
|
icon="home",
|
|
),
|
|
CommonNavigationRailItem(
|
|
icon="bookmark-outline",
|
|
text="Files",
|
|
),
|
|
CommonNavigationRailItem(
|
|
icon="folder-outline",
|
|
text="Bookmark",
|
|
),
|
|
CommonNavigationRailItem(
|
|
icon="library-outline",
|
|
text="Library",
|
|
),
|
|
type="selected",
|
|
),
|
|
MDScreen(
|
|
md_bg_color=self.theme_cls.secondaryContainerColor,
|
|
),
|
|
)
|
|
|
|
|
|
Example().run()
|
|
|
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/navigation-rail-usage.png
|
|
:align: center
|
|
|
|
Anatomy
|
|
-------
|
|
|
|
.. code-block:: kv
|
|
|
|
MDNavigationRail:
|
|
|
|
# Optional.
|
|
MDNavigationRailMenuButton:
|
|
icon: "menu"
|
|
|
|
# Optional.
|
|
MDNavigationRailFabButton:
|
|
icon: "home"
|
|
|
|
MDNavigationRailItem
|
|
|
|
MDNavigationRailItemIcon:
|
|
icon: icon
|
|
|
|
MDNavigationRailItemLabel:
|
|
text: text
|
|
|
|
[...]
|
|
|
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/navigation-rail-anatomy.png
|
|
:align: center
|
|
|
|
Anatomy item
|
|
------------
|
|
|
|
.. code-block:: kv
|
|
|
|
MDNavigationRailItem
|
|
|
|
MDNavigationRailItemIcon:
|
|
icon: icon
|
|
|
|
MDNavigationRailItemLabel:
|
|
text: text
|
|
|
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/navigation-rail-anatomy-item.png
|
|
:align: center
|
|
|
|
Configurations
|
|
==============
|
|
|
|
Rail types
|
|
----------
|
|
|
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/navigation-rail-type.png
|
|
:align: center
|
|
|
|
1. Selected
|
|
2. Unselected
|
|
3. Labeled
|
|
|
|
Selected
|
|
--------
|
|
|
|
.. code-block:: kv
|
|
|
|
MDNavigationRail:
|
|
type: "selected" # default
|
|
|
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/navigation-rail-type-selected.gif
|
|
:align: center
|
|
|
|
Unselected
|
|
----------
|
|
|
|
.. code-block:: kv
|
|
|
|
MDNavigationRail:
|
|
type: "unselected"
|
|
|
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/navigation-rail-type-unselected.gif
|
|
:align: center
|
|
|
|
Labeled
|
|
-------
|
|
|
|
.. code-block:: kv
|
|
|
|
MDNavigationRail:
|
|
type: "labeled"
|
|
|
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/navigation-rail-type-labeled.gif
|
|
:align: center
|
|
|
|
Rail anchored
|
|
-------------
|
|
|
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/navigation-rail-anchored.png
|
|
:align: center
|
|
|
|
1. Top
|
|
2. Center
|
|
3. Bottom
|
|
|
|
Top
|
|
---
|
|
|
|
.. code-block:: kv
|
|
|
|
MDNavigationRail:
|
|
anchor: "top"
|
|
|
|
Center
|
|
------
|
|
|
|
.. code-block:: kv
|
|
|
|
MDNavigationRail:
|
|
anchor: "center" # default
|
|
|
|
Bottom
|
|
------
|
|
|
|
.. code-block:: kv
|
|
|
|
MDNavigationRail:
|
|
anchor: "bottom"
|
|
|
|
API break
|
|
=========
|
|
|
|
1.2.0 version
|
|
-------------
|
|
|
|
.. code-block:: kv
|
|
|
|
MDNavigationRail:
|
|
|
|
MDNavigationRailMenuButton:
|
|
icon: "menu"
|
|
|
|
MDNavigationRailFabButton:
|
|
icon: "home"
|
|
|
|
MDNavigationRailItem:
|
|
icon: icon
|
|
text: text
|
|
|
|
[...]
|
|
|
|
2.2.0 version
|
|
-------------
|
|
|
|
.. code-block:: kv
|
|
|
|
MDNavigationRail:
|
|
|
|
MDNavigationRailMenuButton:
|
|
icon: "menu"
|
|
|
|
MDNavigationRailFabButton:
|
|
icon: "home"
|
|
|
|
MDNavigationRailItem
|
|
|
|
MDNavigationRailItemIcon:
|
|
icon: icon
|
|
|
|
MDNavigationRailItemLabel:
|
|
text: text
|
|
|
|
[...]
|
|
"""
|
|
|
|
__all__ = (
|
|
"MDNavigationRail",
|
|
"MDNavigationRailItem",
|
|
"MDNavigationRailItemIcon",
|
|
"MDNavigationRailItemLabel",
|
|
"MDNavigationRailFabButton",
|
|
"MDNavigationRailMenuButton",
|
|
)
|
|
|
|
import os
|
|
|
|
from kivy.animation import Animation
|
|
from kivy.clock import Clock
|
|
from kivy.graphics import (
|
|
StencilPush,
|
|
RoundedRectangle,
|
|
StencilUse,
|
|
Color,
|
|
Ellipse,
|
|
StencilUnUse,
|
|
StencilPop,
|
|
)
|
|
from kivy.lang import Builder
|
|
from kivy.metrics import dp
|
|
from kivy.properties import (
|
|
BooleanProperty,
|
|
ColorProperty,
|
|
NumericProperty,
|
|
OptionProperty,
|
|
VariableListProperty,
|
|
ObjectProperty,
|
|
)
|
|
from kivy.uix.behaviors import ButtonBehavior
|
|
from kivy.uix.boxlayout import BoxLayout
|
|
from kivy.uix.relativelayout import RelativeLayout
|
|
|
|
from kivymd import uix_path
|
|
from kivymd.theming import ThemableBehavior
|
|
from kivymd.uix.behaviors import (
|
|
ScaleBehavior,
|
|
DeclarativeBehavior,
|
|
BackgroundColorBehavior,
|
|
RectangularRippleBehavior,
|
|
)
|
|
from kivymd.uix.behaviors.focus_behavior import FocusBehavior
|
|
from kivymd.uix.button import MDFabButton, MDIconButton
|
|
from kivymd.uix.label import MDIcon, MDLabel
|
|
|
|
with open(
|
|
os.path.join(uix_path, "navigationrail", "navigationrail.kv"),
|
|
encoding="utf-8",
|
|
) as kv_file:
|
|
Builder.load_string(kv_file.read())
|
|
|
|
|
|
class MDNavigationRailFabButton(MDFabButton):
|
|
"""
|
|
Implements a floating action button (FAB).
|
|
|
|
For more information, see in the
|
|
:class:`~kivymd.uix.button.button.MDFabButton`
|
|
class documentation.
|
|
"""
|
|
|
|
md_bg_color_disabled = ColorProperty(None)
|
|
"""
|
|
The background color in (r, g, b, a) or string format of the switch when
|
|
the widget is disabled.
|
|
|
|
:attr:`md_bg_color_disabled` is a :class:`~kivy.properties.ColorProperty`
|
|
and defaults to `None`.
|
|
"""
|
|
|
|
|
|
class MDNavigationRailMenuButton(MDIconButton):
|
|
"""
|
|
Implements a menu button.
|
|
|
|
For more information, see in the
|
|
:class:`~kivymd.uix.button.button.MDIconButton` class documentation.
|
|
"""
|
|
|
|
md_bg_color_disabled = ColorProperty(None)
|
|
"""
|
|
The background color in (r, g, b, a) or string format of the switch when
|
|
the widget is disabled.
|
|
|
|
:attr:`md_bg_color_disabled` is a :class:`~kivy.properties.ColorProperty`
|
|
and defaults to `None`.
|
|
"""
|
|
|
|
|
|
class MDNavigationRailItemIcon(RectangularRippleBehavior, MDIcon):
|
|
"""
|
|
Implements an icon for the :class:`~MDNavigationRailItem` class.
|
|
|
|
For more information, see in the
|
|
:class:`~kivymd.uix.behaviors.ripple_behavior.RectangularRippleBehavior` and
|
|
:class:`~kivymd.uix.label.label.MDIcon`
|
|
classes documentation.
|
|
|
|
.. versionchanged:: 2.0.0
|
|
"""
|
|
|
|
active_indicator_color = ColorProperty(None)
|
|
"""
|
|
Background color of the active indicator in (r, g, b, a) or string format.
|
|
|
|
:attr:`active_indicator_color` is an :class:`~kivy.properties.ColorProperty`
|
|
and defaults to `None`.
|
|
"""
|
|
|
|
_alpha = NumericProperty(0)
|
|
_active = BooleanProperty(False)
|
|
_navigation_rail = ObjectProperty()
|
|
_navigation_item = ObjectProperty()
|
|
_layer_color = ColorProperty([0, 0, 0, 0])
|
|
_selected_region_width = NumericProperty(dp(0))
|
|
|
|
def anim_complete(self, *args):
|
|
super().anim_complete()
|
|
self._navigation_rail.set_active_item(self._navigation_item)
|
|
|
|
def lay_canvas_instructions(self) -> None:
|
|
if not self.ripple_effect:
|
|
return
|
|
|
|
canvas_rectangle = self.canvas.before.get_group(
|
|
"navigation-rail-rounded-rectangle"
|
|
)[0]
|
|
|
|
with self.canvas.after if self.ripple_canvas_after else self.canvas.before:
|
|
if hasattr(self, "radius"):
|
|
self.radius = [
|
|
canvas_rectangle.radius[0][0],
|
|
]
|
|
self._round_rad = self.radius
|
|
StencilPush(group="rectangular_ripple_behavior")
|
|
RoundedRectangle(
|
|
pos=canvas_rectangle.pos,
|
|
size=canvas_rectangle.size,
|
|
radius=self._round_rad,
|
|
group="rectangular_ripple_behavior",
|
|
)
|
|
StencilUse(group="rectangular_ripple_behavior")
|
|
self.col_instruction = Color(
|
|
rgba=self.ripple_color, group="rectangular_ripple_behavior"
|
|
)
|
|
self.ellipse = Ellipse(
|
|
size=(self._ripple_rad, self._ripple_rad),
|
|
pos=(
|
|
self.ripple_pos[0] - self._ripple_rad / 2.0,
|
|
self.ripple_pos[1] - self._ripple_rad / 2.0,
|
|
),
|
|
group="rectangular_ripple_behavior",
|
|
)
|
|
StencilUnUse(group="rectangular_ripple_behavior")
|
|
RoundedRectangle(
|
|
pos=self.pos,
|
|
size=self.size,
|
|
radius=self._round_rad,
|
|
group="rectangular_ripple_behavior",
|
|
)
|
|
StencilPop(group="rectangular_ripple_behavior")
|
|
self.bind(ripple_color=self._set_color, _ripple_rad=self._set_ellipse)
|
|
|
|
|
|
class MDNavigationRailItemLabel(ScaleBehavior, MDLabel):
|
|
"""
|
|
Implements an label for the :class:`~MDNavigationRailItem` class.
|
|
|
|
For more information, see in the
|
|
:class:`~kivymd.uix.behaviors.scale_behavior.ScaleBehavior` and
|
|
:class:`~kivymd.uix.label.label.MDLabel`
|
|
classes documentation.
|
|
|
|
.. versionchanged:: 2.0.0
|
|
"""
|
|
|
|
scale_value_y = NumericProperty(0)
|
|
"""
|
|
Y-axis value.
|
|
|
|
:attr:`scale_value_y` is an :class:`~kivy.properties.NumericProperty`
|
|
and defaults to `0`.
|
|
"""
|
|
|
|
_active = BooleanProperty(False)
|
|
|
|
def on__active(self, instance, value) -> None:
|
|
"""Fired when the :attr:`_active` value changes."""
|
|
|
|
self.text_color = (
|
|
self.theme_cls.onSurfaceColor
|
|
if value
|
|
else self.theme_cls.onSurfaceVariantColor
|
|
)
|
|
|
|
|
|
class MDNavigationRailItem(
|
|
DeclarativeBehavior,
|
|
ButtonBehavior,
|
|
ThemableBehavior,
|
|
FocusBehavior,
|
|
BoxLayout,
|
|
):
|
|
"""
|
|
Implements a menu item with an icon and text.
|
|
|
|
For more information, see in the
|
|
:class:`~kivymd.uix.behaviors.declarative_behavior.DeclarativeBehavior` and
|
|
:class:`~kivy.uix.behaviors.ButtonBehavior` and
|
|
:class:`~kivymd.theming.ThemableBehavior` and
|
|
:class:`~kivymd.uix.behaviors.focus_behavior.FocusBehavior`
|
|
:class:`~kivy.uix.boxlayout.BoxLayout`
|
|
classes documentation.
|
|
"""
|
|
|
|
active = BooleanProperty(False)
|
|
"""
|
|
Is the element active.
|
|
|
|
:attr:`active` is an :class:`~kivy.properties.BooleanProperty`
|
|
and defaults to `False`.
|
|
"""
|
|
|
|
radius = VariableListProperty(0, length=4)
|
|
"""
|
|
Item radius.
|
|
|
|
.. versionchanged:: 2.0.0
|
|
|
|
:attr:`radius` is an :class:`~kivy.properties.VariableListProperty`
|
|
and defaults to `[0, 0, 0, 0]`.
|
|
"""
|
|
|
|
_navigation_rail = ObjectProperty()
|
|
_icon_item = ObjectProperty()
|
|
|
|
def on_active(self, instance, value) -> None:
|
|
"""Fired when the :attr:`active` value changes."""
|
|
|
|
if value:
|
|
Clock.schedule_once(self.on_leave)
|
|
|
|
def on_enter(self, *args) -> None:
|
|
"""Fired when mouse enter the bbox of the widget."""
|
|
|
|
if not self.active:
|
|
# FIXME: Move layer creation to
|
|
# kivymd/uix/behaviors/state_layer_behavior.py module.
|
|
self._icon_item._layer_color = self.theme_cls.onSurfaceColor[
|
|
:-1
|
|
] + [0.12]
|
|
Animation(
|
|
_selected_region_width=self._icon_item.width + dp(32),
|
|
d=0.2,
|
|
).start(self._icon_item)
|
|
|
|
def on_leave(self, *args) -> None:
|
|
"""Fired when the mouse goes outside the widget border."""
|
|
|
|
self._icon_item._layer_color = self.theme_cls.transparentColor
|
|
|
|
def add_widget(self, widget, *args, **kwargs):
|
|
if isinstance(widget, MDNavigationRailItemLabel):
|
|
Clock.schedule_once(lambda x: self._check_type_rail(widget))
|
|
elif isinstance(widget, MDNavigationRailItemIcon):
|
|
widget._navigation_rail = self._navigation_rail
|
|
widget._navigation_item = self
|
|
self._icon_item = widget
|
|
return super().add_widget(widget)
|
|
|
|
def _check_type_rail(self, instance: MDNavigationRailItemLabel):
|
|
if self._navigation_rail.type == "labeled":
|
|
instance.scale_value_y = 1
|
|
|
|
|
|
class MDNavigationRail(
|
|
DeclarativeBehavior,
|
|
ThemableBehavior,
|
|
BackgroundColorBehavior,
|
|
RelativeLayout,
|
|
):
|
|
"""
|
|
Navigation rail class.
|
|
|
|
For more information, see in the
|
|
:class:`~kivymd.uix.behaviors.declarative_behavior.DeclarativeBehavior` and
|
|
:class:`~kivymd.theming.ThemableBehavior` and
|
|
:class:`~kivymd.uix.behaviors.backgroundcolor_behavior.BackgroundColorBehavior` and
|
|
:class:`~kivy.uix.relativelayout.RelativeLayout`
|
|
classes documentation.
|
|
"""
|
|
|
|
radius = VariableListProperty(0, length=4)
|
|
"""
|
|
Rail radius.
|
|
|
|
:attr:`radius` is an :class:`~kivy.properties.VariableListProperty`
|
|
and defaults to `[0, 0, 0, 0]`.
|
|
"""
|
|
|
|
anchor = OptionProperty("center", options=["top", "bottom", "center"])
|
|
"""
|
|
The position of the panel with menu items.
|
|
Available options are: `'top'`, `'bottom'`, `'center'`.
|
|
|
|
:attr:`anchor` is an :class:`~kivy.properties.OptionProperty`
|
|
and defaults to `'top'`.
|
|
"""
|
|
|
|
type = OptionProperty(
|
|
"selected", options=["labeled", "selected", "unselected"]
|
|
)
|
|
"""
|
|
Type of switching menu items.
|
|
Available options are: `'labeled'`, `'selected'`, `'unselected'`.
|
|
|
|
:attr:`type` is an :class:`~kivy.properties.OptionProperty`
|
|
and defaults to `'labeled'`.
|
|
"""
|
|
|
|
fab_button: MDNavigationRailFabButton = ObjectProperty()
|
|
menu_button: MDNavigationRailFabButton = ObjectProperty()
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
super().__init__(*args, **kwargs)
|
|
Clock.schedule_once(self._check_anchor)
|
|
|
|
def on_size(self, *args) -> None:
|
|
"""Fired when the application screen size changes."""
|
|
|
|
Clock.schedule_once(self._set_pos_menu_fab_buttons)
|
|
Clock.schedule_once(self._check_anchor)
|
|
|
|
def get_items(self) -> list:
|
|
"""Returns a list of :class:`~MDNavigationRailItem` objects."""
|
|
|
|
return self.ids.box_items.children
|
|
|
|
def set_active_item(self, item: MDNavigationRailItem) -> None:
|
|
"""Sets the active menu list item."""
|
|
|
|
for widget in self.ids.box_items.children:
|
|
if item is widget:
|
|
widget.active = not widget.active
|
|
|
|
for widget_item in item.children:
|
|
if isinstance(widget_item, MDNavigationRailItemLabel):
|
|
widget_item._active = widget.active
|
|
if self.type == "selected":
|
|
Animation(
|
|
scale_value_y=1 if widget.active else 0,
|
|
height=widget_item.texture_size[1]
|
|
if widget.active
|
|
else 0,
|
|
d=0.2,
|
|
).start(widget_item)
|
|
if isinstance(widget_item, MDNavigationRailItemIcon):
|
|
widget_item._active = widget.active
|
|
widget_item._alpha = 1 if widget.active else 0
|
|
widget_item._selected_region_width = 0
|
|
Animation(
|
|
_selected_region_width=widget_item.width + dp(32)
|
|
if widget.active
|
|
else 0,
|
|
d=0.2,
|
|
).start(widget_item)
|
|
else:
|
|
widget.active = False
|
|
for widget_item in widget.children:
|
|
widget_item._active = widget.active
|
|
if isinstance(widget_item, MDNavigationRailItemLabel):
|
|
if self.type == "selected":
|
|
Animation(scale_value_y=0, height=0, d=0.2).start(
|
|
widget_item
|
|
)
|
|
if isinstance(widget_item, MDNavigationRailItemIcon):
|
|
Animation(
|
|
_selected_region_width=0,
|
|
_alpha=0,
|
|
d=0.2,
|
|
).start(widget_item)
|
|
|
|
def add_widget(self, widget, *args, **kwargs):
|
|
if isinstance(widget, MDNavigationRailFabButton):
|
|
self.fab_button = widget
|
|
super().add_widget(widget)
|
|
elif isinstance(widget, MDNavigationRailMenuButton):
|
|
self.menu_button = widget
|
|
super().add_widget(widget)
|
|
elif isinstance(widget, MDNavigationRailItem):
|
|
self.ids.box_items.add_widget(widget)
|
|
widget._navigation_rail = self
|
|
widget._navigation_item = widget
|
|
widget.bind(on_release=self.set_active_item)
|
|
else:
|
|
return super().add_widget(widget)
|
|
|
|
def _set_pos_menu_fab_buttons(self, *args):
|
|
def set_pos_menu_fab_buttons(*args):
|
|
if self.fab_button and not self.menu_button:
|
|
self.fab_button.y = self.height - (
|
|
self.fab_button.height + dp(48)
|
|
)
|
|
elif self.menu_button and not self.fab_button:
|
|
self.menu_button.y = self.height - (
|
|
self.menu_button.height + dp(38)
|
|
)
|
|
elif self.fab_button and self.menu_button:
|
|
self.menu_button.y = self.height - (
|
|
self.menu_button.height + dp(38)
|
|
)
|
|
self.fab_button.y = self.height - (
|
|
self.fab_button.height + dp(48) + dp(48)
|
|
)
|
|
|
|
Clock.schedule_once(set_pos_menu_fab_buttons)
|
|
|
|
def _check_anchor(self, *args):
|
|
def set_top_pos(*args):
|
|
anchor_button = None
|
|
if (
|
|
self.fab_button
|
|
and not self.menu_button
|
|
or self.fab_button
|
|
and self.menu_button
|
|
):
|
|
anchor_button = self.fab_button
|
|
elif self.menu_button and not self.fab_button:
|
|
anchor_button = self.menu_button
|
|
|
|
self.ids.box_items.y = (
|
|
anchor_button.y
|
|
- (len(self.ids.box_items.children) * dp(56))
|
|
- dp(56)
|
|
)
|
|
|
|
if self.anchor == "center":
|
|
self.ids.box_items.pos_hint = {"center_y": 0.5}
|
|
elif self.anchor == "top":
|
|
Clock.schedule_once(set_top_pos)
|
|
elif self.anchor == "bottom":
|
|
self.ids.box_items.y = dp(56)
|