Sideband/sbapp/kivymd/uix/snackbar/snackbar.py

550 lines
14 KiB
Python
Raw Normal View History

2022-07-07 14:16:10 -06:00
"""
Components/Snackbar
===================
.. seealso::
2023-07-09 18:49:58 -06:00
`Material Design spec, Snackbars <https://m3.material.io/components/snackbar/overview>`_
2022-07-07 14:16:10 -06:00
.. rubric:: Snackbars provide brief messages about app processes at the bottom
of the screen.
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/snackbar.png
:align: center
Usage
-----
2023-07-09 18:49:58 -06:00
.. code-block:: python
MDSnackbar(
MDLabel(
text="First string",
theme_text_color="Custom",
text_color="#393231",
),
).open()
Example
-------
2022-07-07 14:16:10 -06:00
.. code-block:: python
from kivy.lang import Builder
from kivymd.app import MDApp
2023-07-09 18:49:58 -06:00
from kivymd.uix.label import MDLabel
from kivymd.uix.snackbar import MDSnackbar
2022-07-07 14:16:10 -06:00
2023-07-09 18:49:58 -06:00
KV = '''
2022-10-02 09:16:59 -06:00
MDScreen:
2022-07-07 14:16:10 -06:00
MDRaisedButton:
text: "Create simple snackbar"
2023-07-09 18:49:58 -06:00
on_release: app.open_snackbar()
2022-07-07 14:16:10 -06:00
pos_hint: {"center_x": .5, "center_y": .5}
'''
2023-07-09 18:49:58 -06:00
class Example(MDApp):
def open_snackbar(self):
MDSnackbar(
MDLabel(
text="First string",
),
).open()
2022-07-07 14:16:10 -06:00
def build(self):
2023-07-09 18:49:58 -06:00
self.theme_cls.theme_style = "Dark"
self.theme_cls.primary_palette = "Orange"
2022-07-07 14:16:10 -06:00
return Builder.load_string(KV)
2023-07-09 18:49:58 -06:00
Example().run()
2022-07-07 14:16:10 -06:00
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/snackbar-simple.gif
:align: center
2023-07-09 18:49:58 -06:00
Control width and pos
---------------------
2022-07-07 14:16:10 -06:00
.. code-block:: python
2023-07-09 18:49:58 -06:00
MDSnackbar(
MDLabel(
text="First string",
),
pos=(dp(24), dp(56)),
size_hint_x=0.5,
2022-07-07 14:16:10 -06:00
).open()
2023-07-09 18:49:58 -06:00
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/snackbar-widith-and-pos.gif
2022-07-07 14:16:10 -06:00
:align: center
2023-07-09 18:49:58 -06:00
On mobile, use up to two lines of text to communicate the snackbar message:
2022-07-07 14:16:10 -06:00
.. code-block:: python
2023-07-09 18:49:58 -06:00
MDSnackbar(
MDLabel(
text="First string",
theme_text_color="Custom",
text_color="#393231",
),
MDLabel(
text="Second string",
theme_text_color="Custom",
text_color="#393231",
),
y=dp(24),
pos_hint={"center_x": 0.5},
size_hint_x=0.5,
md_bg_color="#E8D8D7",
2022-07-07 14:16:10 -06:00
).open()
2023-07-09 18:49:58 -06:00
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/snackbar-two-line.gif
2022-07-07 14:16:10 -06:00
:align: center
2023-07-09 18:49:58 -06:00
Usage action button
-------------------
2022-07-07 14:16:10 -06:00
2023-07-09 18:49:58 -06:00
A snackbar can contain a single action. "Dismiss" or "cancel" actions are
optional:
2022-07-07 14:16:10 -06:00
.. code-block:: python
2023-07-09 18:49:58 -06:00
MDSnackbar(
MDLabel(
text="First string",
theme_text_color="Custom",
text_color="#393231",
2022-07-07 14:16:10 -06:00
),
2023-07-09 18:49:58 -06:00
MDSnackbarActionButton(
text="Done",
theme_text_color="Custom",
text_color="#8E353C",
2022-07-07 14:16:10 -06:00
),
2023-07-09 18:49:58 -06:00
y=dp(24),
pos_hint={"center_x": 0.5},
size_hint_x=0.5,
md_bg_color="#E8D8D7",
2022-07-07 14:16:10 -06:00
).open()
2023-07-09 18:49:58 -06:00
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/snackbar-action-button.gif
2022-07-07 14:16:10 -06:00
:align: center
2023-07-09 18:49:58 -06:00
Callback action button
----------------------
2022-07-07 14:16:10 -06:00
.. code-block:: python
2023-07-09 18:49:58 -06:00
def snackbar_action_button_callback(self, *args):
print("Snackbar callback action button")
def open_snackbar(self):
self.snackbar = MDSnackbar(
MDLabel(
text="First string",
theme_text_color="Custom",
text_color="#393231",
),
MDSnackbarActionButton(
text="Done",
theme_text_color="Custom",
text_color="#8E353C",
_no_ripple_effect=True,
on_release=self.snackbar_action_button_callback,
),
y=dp(24),
pos_hint={"center_x": 0.5},
size_hint_x=0.5,
md_bg_color="#E8D8D7",
)
self.snackbar.open()
If an action is long, it can be displayed on a third line:
2022-07-07 14:16:10 -06:00
2023-07-09 18:49:58 -06:00
.. code-block:: python
2022-07-07 14:16:10 -06:00
2023-07-09 18:49:58 -06:00
MDSnackbar(
MDLabel(
text="If an action is long, it can be displayed",
theme_text_color="Custom",
text_color="#393231",
),
MDLabel(
text="on a third line.",
theme_text_color="Custom",
text_color="#393231",
),
MDLabel(
text=" ",
),
MDSnackbarActionButton(
text="Action button",
theme_text_color="Custom",
text_color="#8E353C",
y=dp(8),
_no_ripple_effect=True,
),
y=dp(24),
pos_hint={"center_x": 0.5},
size_hint_x=0.5,
md_bg_color="#E8D8D7",
).open()
2022-07-07 14:16:10 -06:00
2023-07-09 18:49:58 -06:00
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/snackbar-action-button-on-thrid-line.gif
2022-07-07 14:16:10 -06:00
:align: center
2023-07-09 18:49:58 -06:00
Icon (optional close affordance):
2022-07-07 14:16:10 -06:00
.. code-block:: python
2023-07-09 18:49:58 -06:00
def snackbar_close(self, *args):
self.snackbar.dismiss()
def open_snackbar(self):
self.snackbar = MDSnackbar(
MDLabel(
text="Icon (optional close affordance)",
theme_text_color="Custom",
text_color="#393231",
),
MDSnackbarActionButton(
text="Action button",
theme_text_color="Custom",
text_color="#8E353C",
_no_ripple_effect=True,
),
MDSnackbarCloseButton(
icon="close",
theme_text_color="Custom",
text_color="#8E353C",
_no_ripple_effect=True,
on_release=self.snackbar_close,
),
y=dp(24),
pos_hint={"center_x": 0.5},
size_hint_x=0.5,
md_bg_color="#E8D8D7",
)
self.snackbar.open()
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/snackbar-optional-close-affordance.gif
:align: center
2022-07-07 14:16:10 -06:00
2023-07-09 18:49:58 -06:00
API break
=========
2022-07-07 14:16:10 -06:00
2023-07-09 18:49:58 -06:00
1.1.1 version
-------------
2022-07-07 14:16:10 -06:00
2023-07-09 18:49:58 -06:00
.. code-block:: python
2022-07-07 14:16:10 -06:00
2023-07-09 18:49:58 -06:00
snackbar = Snackbar(
text="First string",
snackbar_x="10dp",
snackbar_y="24dp",
)
snackbar.size_hint_x = (
Window.width - (snackbar.snackbar_x * 2)
) / Window.width
snackbar.buttons = [
MDFlatButton(
text="Done",
theme_text_color="Custom",
text_color="#8E353C",
on_release=snackbar.dismiss,
),
]
snackbar.open()
2022-07-07 14:16:10 -06:00
2023-07-09 18:49:58 -06:00
1.2.0 version
-------------
2022-07-07 14:16:10 -06:00
2023-07-09 18:49:58 -06:00
.. code-block:: python
2022-07-07 14:16:10 -06:00
2023-07-09 18:49:58 -06:00
MDSnackbar(
MDLabel(
text="First string",
),
MDSnackbarActionButton(
text="Done",
theme_text_color="Custom",
text_color="#8E353C",
),
y=dp(24),
pos_hint={"center_x": 0.5},
size_hint_x=0.5,
md_bg_color="#E8D8D7",
).open()
2022-07-07 14:16:10 -06:00
"""
2023-07-09 18:49:58 -06:00
__all__ = (
"MDSnackbar",
"MDSnackbarActionButton",
"MDSnackbarCloseButton",
)
2022-07-07 14:16:10 -06:00
import os
2023-07-09 18:49:58 -06:00
from kivy import Logger
2022-07-07 14:16:10 -06:00
from kivy.animation import Animation
from kivy.clock import Clock
from kivy.core.window import Window
from kivy.lang import Builder
from kivy.properties import (
BooleanProperty,
ColorProperty,
ListProperty,
NumericProperty,
OptionProperty,
StringProperty,
)
from kivymd import uix_path
2023-07-09 18:49:58 -06:00
from kivymd.uix.behaviors import MotionShackBehavior
from kivymd.uix.boxlayout import MDBoxLayout
from kivymd.uix.button import MDFlatButton, MDIconButton
2022-07-07 14:16:10 -06:00
from kivymd.uix.card import MDCard
2023-07-09 18:49:58 -06:00
from kivymd.uix.label import MDLabel
from kivymd.uix.relativelayout import MDRelativeLayout
2022-07-07 14:16:10 -06:00
with open(
os.path.join(uix_path, "snackbar", "snackbar.kv"), encoding="utf-8"
) as kv_file:
Builder.load_string(kv_file.read())
2023-07-09 18:49:58 -06:00
class SnackbarLabelContainer(MDBoxLayout):
"""Container for placing snackbar text."""
class SnackbarActionButtonContainer(MDRelativeLayout):
"""Container for placing snackbar action button."""
class SnackbarCloseButtonContainer(MDRelativeLayout):
"""Container for placing snackbar close button."""
class MDSnackbarCloseButton(MDIconButton):
"""
Snackbar closed button class.
For more information, see in the
:class:`~kivymd.uix.button.MDIconButton` class documentation.
2022-07-07 14:16:10 -06:00
"""
2023-07-09 18:49:58 -06:00
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if not self.y and not self.pos_hint:
self.pos_hint = {"center_y": 0.5}
class MDSnackbarActionButton(MDFlatButton):
"""
Snackbar action button class.
For more information, see in the
:class:`~kivymd.uix.button.MDFlatButton` class documentation.
"""
2022-07-07 14:16:10 -06:00
2023-07-09 18:49:58 -06:00
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if not self.y and not self.pos_hint:
self.pos_hint = {"center_y": 0.5}
2022-07-07 14:16:10 -06:00
2023-07-09 18:49:58 -06:00
class MDSnackbar(MotionShackBehavior, MDCard):
"""
Snackbar class.
2022-07-07 14:16:10 -06:00
2023-07-09 18:49:58 -06:00
.. versionchanged:: 1.2.0
Rename `BaseSnackbar` to `MDSnackbar` class.
2022-07-07 14:16:10 -06:00
2023-07-09 18:49:58 -06:00
For more information, see in the
:class:`~kivymd.uix.card.MDCard` and
:class:`~kivymd.uix.behaviors.StencilBehavior`
class documentation.
2022-07-07 14:16:10 -06:00
2023-07-09 18:49:58 -06:00
:Events:
:attr:`on_open`
Called when a snackbar opened.
:attr:`on_dismiss`
Called when a snackbar closes.
2022-07-07 14:16:10 -06:00
"""
duration = NumericProperty(3)
"""
The amount of time that the snackbar will stay on screen for.
:attr:`duration` is a :class:`~kivy.properties.NumericProperty`
and defaults to `3`.
"""
auto_dismiss = BooleanProperty(True)
"""
Whether to use automatic closing of the snackbar or not.
:attr:`auto_dismiss` is a :class:`~kivy.properties.BooleanProperty`
2023-07-09 18:49:58 -06:00
and defaults to `True`.
2022-07-07 14:16:10 -06:00
"""
2023-07-09 18:49:58 -06:00
radius = ListProperty([5, 5, 5, 5])
2022-07-07 14:16:10 -06:00
"""
2023-07-09 18:49:58 -06:00
Snackbar radius.
2022-07-07 14:16:10 -06:00
2023-07-09 18:49:58 -06:00
:attr:`radius` is a :class:`~kivy.properties.ListProperty`
and defaults to `[5, 5, 5, 5]`
2022-07-07 14:16:10 -06:00
"""
2023-07-09 18:49:58 -06:00
bg_color = ColorProperty(None, deprecated=True)
2022-07-07 14:16:10 -06:00
"""
2023-07-09 18:49:58 -06:00
Snackbar background color in (r, g, b, a) or string format.
2022-07-07 14:16:10 -06:00
2023-07-09 18:49:58 -06:00
.. deprecated:: 1.2.0
Use 'md_bg_color` instead.
:attr:`bg_color` is a :class:`~kivy.properties.ColorProperty`
and defaults to `None`.
2022-07-07 14:16:10 -06:00
"""
2023-07-09 18:49:58 -06:00
buttons = ListProperty(deprecated=True)
2022-07-07 14:16:10 -06:00
"""
2023-07-09 18:49:58 -06:00
Snackbar buttons.
2022-07-07 14:16:10 -06:00
2023-07-09 18:49:58 -06:00
.. deprecated:: 1.2.0
:attr:`buttons` is a :class:`~kivy.properties.ListProperty`
and defaults to `[]`
2022-07-07 14:16:10 -06:00
"""
snackbar_animation_dir = OptionProperty(
"Bottom",
options=["Top", "Bottom", "Left", "Right"],
2023-07-09 18:49:58 -06:00
deprecated=True,
2022-07-07 14:16:10 -06:00
)
"""
Snackbar animation direction.
2023-07-09 18:49:58 -06:00
Available options are: `'Top'`, `'Bottom'`, `'Left'`, `'Right'`.
2022-07-07 14:16:10 -06:00
2023-07-09 18:49:58 -06:00
.. deprecated:: 1.2.0
2022-07-07 14:16:10 -06:00
:attr:`snackbar_animation_dir` is an :class:`~kivy.properties.OptionProperty`
and defaults to `'Bottom'`.
"""
2023-07-09 18:49:58 -06:00
snackbar_x = NumericProperty(0, deprecated=True)
2022-07-07 14:16:10 -06:00
"""
The snackbar x position in the screen
2023-07-09 18:49:58 -06:00
.. deprecated:: 1.2.0
2022-07-07 14:16:10 -06:00
:attr:`snackbar_x` is a :class:`~kivy.properties.NumericProperty`
2023-07-09 18:49:58 -06:00
and defaults to `0`.
2022-07-07 14:16:10 -06:00
"""
2023-07-09 18:49:58 -06:00
snackbar_y = NumericProperty(0, deprecated=True)
2022-07-07 14:16:10 -06:00
"""
The snackbar x position in the screen
2023-07-09 18:49:58 -06:00
.. deprecated:: 1.2.0
2022-07-07 14:16:10 -06:00
:attr:`snackbar_y` is a :class:`~kivy.properties.NumericProperty`
2023-07-09 18:49:58 -06:00
and defaults to `0`.
2022-07-07 14:16:10 -06:00
"""
2023-07-09 18:49:58 -06:00
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
2022-07-07 14:16:10 -06:00
self.register_event_type("on_open")
self.register_event_type("on_dismiss")
2023-07-09 18:49:58 -06:00
self.opacity = 0
2022-07-07 14:16:10 -06:00
2023-07-09 18:49:58 -06:00
def dismiss(self, *args) -> None:
2022-07-07 14:16:10 -06:00
"""Dismiss the snackbar."""
2023-07-09 18:49:58 -06:00
super().on_dismiss()
2022-07-07 14:16:10 -06:00
2023-07-09 18:49:58 -06:00
def open(self) -> None:
"""Show the snackbar."""
2022-07-07 14:16:10 -06:00
2023-07-09 18:49:58 -06:00
for widget in Window.parent.children:
if widget.__class__ is MDSnackbar:
2022-07-07 14:16:10 -06:00
return
2023-07-09 18:49:58 -06:00
Window.parent.add_widget(self)
super().on_open()
def add_widget(self, widget, *args, **kwargs):
def check_color(color):
if not widget.text_color:
widget.theme_text_color = "Custom"
widget.text_color = color
if isinstance(widget, MDSnackbarCloseButton):
widget.icon_size = "20sp"
check_color("white")
self.ids.close_container.add_widget(widget)
if len(self.ids.close_container.children) >= 2:
Logger.warning(
"KivyMD: "
"Do not use more than one button to close the snackbar. "
"This is contrary to the material design rules "
"of version 3"
2022-07-07 14:16:10 -06:00
)
2023-07-09 18:49:58 -06:00
if isinstance(widget, MDSnackbarActionButton):
self.ids.action_container.add_widget(widget)
check_color(self.theme_cls.primary_color)
if len(self.ids.action_container.children) >= 2:
Logger.warning(
"KivyMD: "
"Do not use more than one action button. "
"This is contrary to the material design rules "
"of version 3"
2022-07-07 14:16:10 -06:00
)
2023-07-09 18:49:58 -06:00
if isinstance(widget, MDLabel):
widget.adaptive_height = True
widget.pos_hint = {"center_y": 0.5}
check_color("white")
self.ids.label_container.add_widget(widget)
if len(self.ids.label_container.children) >= 4:
Logger.warning(
"KivyMD: "
"Do not use more than three lines in the snackbar. "
"This is contrary to the material design rules "
"of version 3"
2022-07-07 14:16:10 -06:00
)
2023-07-09 18:49:58 -06:00
elif isinstance(
widget,
(
SnackbarLabelContainer,
SnackbarActionButtonContainer,
SnackbarCloseButtonContainer,
),
2022-07-07 14:16:10 -06:00
):
2023-07-09 18:49:58 -06:00
return super().add_widget(widget)
2022-07-07 14:16:10 -06:00
2023-07-09 18:49:58 -06:00
def on_open(self, *args) -> None:
"""Called when a snackbar opened."""
2022-07-07 14:16:10 -06:00
2023-07-09 18:49:58 -06:00
def on_dismiss(self, *args) -> None:
"""Called when a snackbar closed."""
2022-07-07 14:16:10 -06:00
2023-07-09 18:49:58 -06:00
class Snackbar(MDSnackbar):
2022-07-07 14:16:10 -06:00
"""
2023-07-09 18:49:58 -06:00
.. deprecated:: 1.2.0
Use :class:`~kivymd.uix.snackbar.MDSnackbar`
class instead.
2022-07-07 14:16:10 -06:00
"""
2023-07-09 18:49:58 -06:00
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
Logger.warning(
"KivyMD: "
"The `Snackbar` class has been deprecated. "
"Use the `MDSnackbar` class instead."
)