test-kivy-app/kivy_venv/lib/python3.11/site-packages/kivymd/uix/sliverappbar/sliverappbar.py

435 lines
11 KiB
Python
Raw Normal View History

2024-09-15 12:12:16 +00:00
"""
Components/SliverAppbar
=======================
.. versionadded:: 1.0.0
.. rubric:: MDSliverAppbar is a Material Design widget in KivyMD which gives
scrollable or collapsible
2024-09-15 17:57:02 +00:00
`MDTopAppBar <https://kivymd.readthedocs.io/en/latest/components/appbar/>`_
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/sliver-appbar-preview.gif
:align: center
2024-09-15 12:12:16 +00:00
.. note:: This widget is a modification of the
`silverappbar.py <https://github.com/kivymd-extensions/akivymd/blob/main/kivymd_extensions/akivymd/uix/silverappbar.py>`_ module.
Usage
-----
.. code-block:: kv
MDScreen:
MDSliverAppbar:
2024-09-15 17:57:02 +00:00
MDTopAppBar:
[...]
2024-09-15 12:12:16 +00:00
MDSliverAppbarHeader:
# Custom content.
2024-09-15 17:57:02 +00:00
[...]
2024-09-15 12:12:16 +00:00
# Custom list.
MDSliverAppbarContent:
2024-09-15 17:57:02 +00:00
Anatomy
-------
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/sliver-appbar-anatomy.png
2024-09-15 12:12:16 +00:00
:align: center
Example
-------
.. code-block:: python
from kivy.lang.builder import Builder
from kivymd.app import MDApp
2024-09-15 17:57:02 +00:00
from kivymd.uix.list import MDListItem
2024-09-15 12:12:16 +00:00
KV = '''
2024-09-15 17:57:02 +00:00
<GuitarItem>
theme_bg_color: "Custom"
md_bg_color: "2d4a50"
MDListItemLeadingAvatar
source: "avatar.png"
MDListItemHeadlineText:
text: "Ibanez"
MDListItemSupportingText:
text: "GRG121DX-BKF"
MDListItemTertiaryText:
text: "$445,99"
MDListItemTrailingIcon:
icon: "guitar-electric"
2024-09-15 12:12:16 +00:00
MDScreen:
MDSliverAppbar:
background_color: "2d4a50"
2024-09-15 17:57:02 +00:00
hide_appbar: True
2024-09-15 12:12:16 +00:00
2024-09-15 17:57:02 +00:00
MDTopAppBar:
type: "medium"
MDTopAppBarLeadingButtonContainer:
MDActionTopAppBarButton:
icon: "arrow-left"
2024-09-15 12:12:16 +00:00
2024-09-15 17:57:02 +00:00
MDTopAppBarTitle:
text: "Sliver toolbar"
2024-09-15 12:12:16 +00:00
2024-09-15 17:57:02 +00:00
MDTopAppBarTrailingButtonContainer:
MDActionTopAppBarButton:
icon: "attachment"
MDActionTopAppBarButton:
icon: "calendar"
MDActionTopAppBarButton:
icon: "dots-vertical"
MDSliverAppbarHeader:
FitImage:
source: "bg.jpg"
2024-09-15 12:12:16 +00:00
MDSliverAppbarContent:
id: content
orientation: "vertical"
padding: "12dp"
2024-09-15 17:57:02 +00:00
theme_bg_color: "Custom"
md_bg_color: "2d4a50"
2024-09-15 12:12:16 +00:00
'''
2024-09-15 17:57:02 +00:00
class GuitarItem(MDListItem):
...
2024-09-15 12:12:16 +00:00
class Example(MDApp):
def build(self):
2024-09-15 17:57:02 +00:00
self.theme_cls.theme_style = "Dark"
2024-09-15 12:12:16 +00:00
return Builder.load_string(KV)
def on_start(self):
for x in range(10):
2024-09-15 17:57:02 +00:00
self.root.ids.content.add_widget(GuitarItem())
2024-09-15 12:12:16 +00:00
Example().run()
2024-09-15 17:57:02 +00:00
API break
=========
1.2.0 version
-------------
.. code-block:: kv
#:import SliverToolbar __main__.SliverToolbar
Root:
MDSliverAppbar:
[...]
MDSliverAppbarHeader:
[...]
MDSliverAppbarContent:
[...]
.. code-block:: python
class SliverToolbar(MDTopAppBar):
[...]
2.0.0 version
-------------
.. code-block:: kv
Root:
MDSliverAppbar:
[...]
MDTopAppBar:
[...]
MDSliverAppbarHeader:
[...]
MDSliverAppbarContent:
[...]
2024-09-15 12:12:16 +00:00
"""
__all__ = ("MDSliverAppbar", "MDSliverAppbarHeader", "MDSliverAppbarContent")
import os
from kivy.clock import Clock
from kivy.core.window import Window
from kivy.lang.builder import Builder
from kivy.properties import (
BooleanProperty,
ColorProperty,
NumericProperty,
VariableListProperty,
2024-09-15 17:57:02 +00:00
ObjectProperty,
2024-09-15 12:12:16 +00:00
)
2024-09-15 17:57:02 +00:00
from kivy.uix.boxlayout import BoxLayout
2024-09-15 12:12:16 +00:00
from kivymd import uix_path
2024-09-15 17:57:02 +00:00
from kivymd.theming import ThemableBehavior
2024-09-15 12:12:16 +00:00
from kivymd.uix.boxlayout import MDBoxLayout
2024-09-15 17:57:02 +00:00
from kivymd.uix.appbar import MDTopAppBar
2024-09-15 12:12:16 +00:00
with open(
os.path.join(uix_path, "sliverappbar", "sliverappbar.kv"), encoding="utf-8"
) as kv_file:
Builder.load_string(kv_file.read())
class MDSliverAppbarException(Exception):
pass
class MDSliverAppbarContent(MDBoxLayout):
"""
Implements a box for a scrollable list of custom items.
For more information, see in the
:class:`~kivymd.uix.boxlayout.MDBoxLayout` class documentation.
"""
2024-09-15 17:57:02 +00:00
class MDSliverAppbarHeader(BoxLayout):
2024-09-15 12:12:16 +00:00
"""
Sliver app bar header class.
For more information, see in the
2024-09-15 17:57:02 +00:00
:class:`~kivy.uix.boxlayout.BoxLayout` class documentation.
2024-09-15 12:12:16 +00:00
"""
2024-09-15 17:57:02 +00:00
class MDSliverAppbar(ThemableBehavior, BoxLayout):
2024-09-15 12:12:16 +00:00
"""
2024-09-15 17:57:02 +00:00
Sliver appbar class.
2024-09-15 12:12:16 +00:00
For more information, see in the
2024-09-15 17:57:02 +00:00
:class:`~kivymd.theming.ThemableBehavior` and
:class:`~kivy.uix.boxlayout.BoxLayout`
classes documentation.
2024-09-15 12:12:16 +00:00
:Events:
:attr:`on_scroll_content`
2024-09-15 17:57:02 +00:00
Fired when the list of custom content is being scrolled.
2024-09-15 12:12:16 +00:00
"""
background_color = ColorProperty(None)
"""
2024-09-15 17:57:02 +00:00
Background color of appbar in (r, g, b, a) or string format.
2024-09-15 12:12:16 +00:00
:attr:`background_color` is an :class:`~kivy.properties.ColorProperty`
and defaults to `None`.
"""
max_height = NumericProperty(Window.height / 2)
"""
Distance from top of screen to start of custom list content.
.. code-block:: kv
MDSliverAppbar:
max_height: "200dp"
2024-09-15 17:57:02 +00:00
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/sliver-appbar-max-height.png
2024-09-15 12:12:16 +00:00
:align: center
:attr:`max_height` is an :class:`~kivy.properties.NumericProperty`
and defaults to `Window.height / 2`.
"""
2024-09-15 17:57:02 +00:00
hide_appbar = BooleanProperty(None)
2024-09-15 12:12:16 +00:00
"""
2024-09-15 17:57:02 +00:00
Whether to hide the appbar when scrolling through a list
2024-09-15 12:12:16 +00:00
of custom content.
2024-09-15 17:57:02 +00:00
.. versionchanged:: 2.0.0
Rename `hide_toolbar` to `hide_appbar` attribute.
2024-09-15 12:12:16 +00:00
.. code-block:: kv
MDSliverAppbar:
2024-09-15 17:57:02 +00:00
hide_appbar: False
2024-09-15 12:12:16 +00:00
2024-09-15 17:57:02 +00:00
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/sliver-appbar-hide-appbar-false.gif
2024-09-15 12:12:16 +00:00
:align: center
2024-09-15 17:57:02 +00:00
.. code-block:: kv
2024-09-15 12:12:16 +00:00
MDSliverAppbar:
2024-09-15 17:57:02 +00:00
hide_appbar: True
2024-09-15 12:12:16 +00:00
2024-09-15 17:57:02 +00:00
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/sliver-appbar-hide-appbar-true.gif
2024-09-15 12:12:16 +00:00
:align: center
2024-09-15 17:57:02 +00:00
:attr:`hide_appbar` is an :class:`~kivy.properties.BooleanProperty`
and defaults to `None`.
2024-09-15 12:12:16 +00:00
"""
radius = VariableListProperty([20], length=4)
"""
Box radius for custom item list.
.. code-block:: kv
MDSliverAppbar:
radius: 20
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/sliver-app-bar-radius.png
:align: center
:attr:`radius` is an :class:`~kivy.properties.VariableListProperty`
and defaults to `[20]`.
"""
max_opacity = NumericProperty(1)
"""
Maximum background transparency value for the
:class:`~kivymd.uix.sliverappbar.sliverappbar.MDSliverAppbarHeader` class.
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/sliver-app-bar-max-opacity.gif
:align: center
.. code-block:: kv
MDSliverAppbar:
max_opacity: .5
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/sliver-app-bar-max-opacity-05.gif
:align: center
:attr:`max_opacity` is an :class:`~kivy.properties.NumericProperty`
and defaults to `1`.
"""
_opacity = NumericProperty()
_scroll_was_moving = BooleanProperty(False)
_last_scroll_y_pos = 0.0
2024-09-15 17:57:02 +00:00
_appbar = ObjectProperty()
2024-09-15 12:12:16 +00:00
2024-09-15 17:57:02 +00:00
def __init__(self, **kwargs):
super().__init__(**kwargs)
2024-09-15 12:12:16 +00:00
self.register_event_type("on_scroll_content")
2024-09-15 17:57:02 +00:00
def on_hide_appbar(self, instance, value) -> None:
"""Fired when the `hide_appbar` value changes."""
if not value:
self.background_color = self.theme_cls.transparentColor
2024-09-15 12:12:16 +00:00
def on_scroll_content(
self,
2024-09-15 17:57:02 +00:00
instance: object = None,
2024-09-15 12:12:16 +00:00
value: float = 1.0,
direction: str = "up",
):
"""
2024-09-15 17:57:02 +00:00
Fired when the list of custom content is being scrolled.
2024-09-15 12:12:16 +00:00
2024-09-15 17:57:02 +00:00
:param instance: :class:`~MDSliverAppbar`
2024-09-15 12:12:16 +00:00
:param value: see :attr:`~kivy.uix.scrollview.ScrollView.scroll_y`
:param direction: scroll direction: 'up/down'
"""
2024-09-15 17:57:02 +00:00
def on_background_color(self, instance, color) -> None:
"""Fired when the `background_color` value changes."""
2024-09-15 12:12:16 +00:00
2024-09-15 17:57:02 +00:00
if self._appbar:
self._appbar.canvas.get_group("md-top-app-bar-color")[
0
].rgba = color
2024-09-15 12:12:16 +00:00
def on_vbar(self) -> None:
if not self.background_color:
2024-09-15 17:57:02 +00:00
self.background_color = self.theme_cls.primaryColor
2024-09-15 12:12:16 +00:00
scroll_box = self.ids.scroll_box
vbar = self.ids.scroll.vbar
2024-09-15 17:57:02 +00:00
appbar_percent = (self._appbar.height / scroll_box.height) * 100
2024-09-15 12:12:16 +00:00
current_percent = (vbar[0] + vbar[1]) * 100
percent_min = (
1 - self.max_height / scroll_box.height
2024-09-15 17:57:02 +00:00
) * 100 + appbar_percent
2024-09-15 12:12:16 +00:00
if self._scroll_was_moving:
direction = self._get_direction_swipe(self.ids.scroll.scroll_y)
self._last_scroll_y_pos = self.ids.scroll.scroll_y
self.dispatch(
"on_scroll_content", self.ids.scroll.scroll_y, direction
)
2024-09-15 17:57:02 +00:00
if self.hide_appbar:
2024-09-15 12:12:16 +00:00
if percent_min <= current_percent:
opacity = (current_percent - percent_min) / (100 - percent_min)
self._opacity = self.max_opacity * (1 - opacity)
self.background_color = self.background_color[0:3] + [
1 - opacity
]
else:
self.background_color = self.background_color[0:3] + [1]
def add_widget(self, widget, index=0, canvas=None):
2024-09-15 17:57:02 +00:00
if isinstance(widget, MDSliverAppbarContent):
2024-09-15 12:12:16 +00:00
Clock.schedule_once(lambda x: self._set_radius(widget))
self.ids.scroll_box.add_widget(widget)
2024-09-15 17:57:02 +00:00
elif isinstance(widget, MDSliverAppbarHeader):
2024-09-15 12:12:16 +00:00
self.ids.header.add_widget(widget)
2024-09-15 17:57:02 +00:00
elif isinstance(widget, MDTopAppBar):
self._appbar = widget
widget.pos_hint = {"top": 1}
self.ids.float_box.add_widget(widget)
2024-09-15 12:12:16 +00:00
else:
super().add_widget(widget, index=index, canvas=canvas)
2024-09-15 17:57:02 +00:00
def on__appbar(self, instance, value):
def set_rgba_appbar(*args):
if self.hide_appbar:
value.theme_elevation_level = "Custom"
value.elevation_level = 0
value.theme_shadow_color = "Custom"
value.shadow_color = self.theme_cls.transparentColor
value.md_bg_color = self.theme_cls.transparentColor
value.canvas.get_group("md-top-app-bar-color")[
0
].rgba = self.theme_cls.transparentColor
Clock.schedule_once(set_rgba_appbar, 0.5)
def _set_radius(self, instance: MDSliverAppbarContent):
2024-09-15 12:12:16 +00:00
instance.radius = self.radius
2024-09-15 17:57:02 +00:00
def _get_direction_swipe(self, current_percent: float):
2024-09-15 12:12:16 +00:00
if self._last_scroll_y_pos > current_percent:
direction = "up"
else:
direction = "down"
return direction