2024-09-15 12:12:16 +00:00
|
|
|
"""
|
|
|
|
Components/SegmentedButton
|
|
|
|
==========================
|
|
|
|
|
|
|
|
.. versionadded:: 1.2.0
|
|
|
|
|
|
|
|
.. seealso::
|
|
|
|
|
|
|
|
`Material Design spec, Segmented buttons <https://m3.material.io/components/segmented-buttons/overview>`_
|
|
|
|
|
|
|
|
`Segmented control <https://kivymd.readthedocs.io/en/latest/components/segmentedcontrol/>`_
|
|
|
|
|
|
|
|
.. rubric:: Segmented buttons help people select options, switch views,
|
|
|
|
or sort elements.
|
|
|
|
|
|
|
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/segmented-button-preview.png
|
|
|
|
:align: center
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
- Segmented buttons can contain icons, label text, or both
|
|
|
|
- Two types: single-select and multi-select
|
|
|
|
- Use for simple choices between two to five items (for more items or complex
|
|
|
|
choices, use chips)
|
|
|
|
|
|
|
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/segmented-button-types.png
|
|
|
|
:align: center
|
|
|
|
|
|
|
|
1. Single-select segmented button
|
|
|
|
2. Multi-select segmented button
|
|
|
|
|
|
|
|
Anatomy
|
|
|
|
-------
|
|
|
|
|
|
|
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/segmented-button-anatomy.png
|
|
|
|
:align: center
|
|
|
|
|
|
|
|
Icons
|
2024-09-15 12:12:16 +00:00
|
|
|
-----
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
Icons may be used as labels by themselves or alongside text.
|
|
|
|
If an icon is used without label text, it must clearly communicate the option
|
|
|
|
it represents.
|
|
|
|
|
|
|
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/segmented-button-icons.png
|
|
|
|
:align: center
|
|
|
|
|
|
|
|
Use with text and icon
|
|
|
|
----------------------
|
|
|
|
|
2024-09-15 12:12:16 +00:00
|
|
|
.. code-block:: kv
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
MDSegmentedButton:
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
MDSegmentedButtonItem:
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
MDSegmentButtonIcon:
|
|
|
|
icon: "language-python"
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
MDSegmentButtonLabel:
|
|
|
|
text: "Python"
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
MDSegmentedButtonItem:
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
MDSegmentButtonIcon:
|
|
|
|
icon: "language-javascript"
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
MDSegmentButtonLabel:
|
|
|
|
text: "Java-Script"
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
MDSegmentedButtonItem:
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
MDSegmentButtonIcon:
|
|
|
|
icon: "language-swift"
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
MDSegmentButtonLabel:
|
|
|
|
text: "Swift"
|
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/segmented-button-use-with-text-and-icon.gif
|
|
|
|
:align: center
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
Use without text with an icon
|
|
|
|
-----------------------------
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
.. code-block:: kv
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
MDSegmentedButton:
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
MDSegmentedButtonItem:
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
MDSegmentButtonIcon:
|
|
|
|
icon: "language-python"
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
MDSegmentedButtonItem:
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
MDSegmentButtonIcon:
|
|
|
|
icon: "language-javascript"
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
MDSegmentedButtonItem:
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
MDSegmentButtonIcon:
|
|
|
|
icon: "language-swift"
|
|
|
|
|
|
|
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/segmented-button-use-without-text-with-an-icon.gif
|
2024-09-15 12:12:16 +00:00
|
|
|
:align: center
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
Use only text
|
|
|
|
-------------
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
|
|
.. code-block:: kv
|
|
|
|
|
|
|
|
MDSegmentedButton:
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
MDSegmentedButtonItem:
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
MDSegmentButtonLabel:
|
|
|
|
text: "Python"
|
|
|
|
|
|
|
|
MDSegmentedButtonItem:
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
MDSegmentButtonLabel:
|
|
|
|
text: "Java-Script"
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
MDSegmentedButtonItem:
|
|
|
|
|
|
|
|
MDSegmentButtonLabel:
|
|
|
|
text: "Swift"
|
|
|
|
|
|
|
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/segmented-button-use-only-text.gif
|
2024-09-15 12:12:16 +00:00
|
|
|
:align: center
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
Multiselect
|
|
|
|
-----------
|
|
|
|
|
|
|
|
For multiple marking of elements, use the
|
|
|
|
:attr:`kivymd.uix.segmentedbutton.segmentedbutton.MDSegmentedButton.multiselect`
|
|
|
|
parameter:
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
|
|
.. code-block:: kv
|
|
|
|
|
|
|
|
MDSegmentedButton:
|
2024-09-15 17:57:02 +00:00
|
|
|
multiselect: 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/segmented-button-multiselect-true.gif
|
2024-09-15 12:12:16 +00:00
|
|
|
:align: center
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
Type
|
|
|
|
----
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
Density can be used in denser UIs where space is limited. Density is only
|
|
|
|
applied to the height. Each step down in density removes 4dp from the height.
|
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/segmented-button-type.png
|
|
|
|
:align: center
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
.. code-block:: python
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
from kivy.lang import Builder
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
from kivymd.uix.label import MDLabel
|
|
|
|
from kivymd.uix.boxlayout import MDBoxLayout
|
|
|
|
from kivymd.uix.segmentedbutton import (
|
|
|
|
MDSegmentedButton,
|
|
|
|
MDSegmentedButtonItem,
|
|
|
|
MDSegmentButtonLabel,
|
|
|
|
)
|
|
|
|
from kivymd.app import MDApp
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
KV = '''
|
|
|
|
MDScreen:
|
|
|
|
md_bg_color: self.theme_cls.backgroundColor
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
MDBoxLayout:
|
|
|
|
id: box
|
|
|
|
orientation: "vertical"
|
|
|
|
size_hint_x: .7
|
|
|
|
adaptive_height: True
|
|
|
|
spacing: "24dp"
|
|
|
|
pos_hint: {"center_x": .5, "center_y": .5}
|
|
|
|
'''
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
|
|
|
class Example(MDApp):
|
|
|
|
def on_start(self):
|
|
|
|
for segment_type in ["large", "normal", "medium", "small"]:
|
|
|
|
self.root.ids.box.add_widget(
|
|
|
|
MDBoxLayout(
|
|
|
|
MDLabel(
|
|
|
|
text=f"Type '{segment_type}'",
|
|
|
|
adaptive_height=True,
|
|
|
|
bold=True,
|
|
|
|
pos_hint={"center_y": 0.5},
|
|
|
|
halign="center",
|
|
|
|
),
|
|
|
|
MDSegmentedButton(
|
|
|
|
MDSegmentedButtonItem(
|
|
|
|
MDSegmentButtonLabel(
|
|
|
|
text="Songs",
|
|
|
|
),
|
|
|
|
),
|
|
|
|
MDSegmentedButtonItem(
|
|
|
|
MDSegmentButtonLabel(
|
|
|
|
text="Albums",
|
|
|
|
),
|
|
|
|
),
|
|
|
|
MDSegmentedButtonItem(
|
|
|
|
MDSegmentButtonLabel(
|
|
|
|
text="Podcasts",
|
|
|
|
),
|
|
|
|
),
|
|
|
|
type=segment_type,
|
|
|
|
),
|
|
|
|
orientation="vertical",
|
|
|
|
spacing="12dp",
|
|
|
|
adaptive_height=True,
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
def build(self):
|
|
|
|
return Builder.load_string(KV)
|
|
|
|
|
|
|
|
|
|
|
|
Example().run()
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
|
|
A practical example
|
|
|
|
-------------------
|
|
|
|
|
|
|
|
.. code-block:: python
|
|
|
|
|
|
|
|
import os
|
|
|
|
|
|
|
|
from faker import Faker
|
|
|
|
|
|
|
|
from kivy.clock import Clock
|
|
|
|
from kivy.lang import Builder
|
|
|
|
from kivy.properties import StringProperty
|
|
|
|
|
|
|
|
from kivymd.app import MDApp
|
|
|
|
from kivymd.uix.boxlayout import MDBoxLayout
|
2024-09-15 17:57:02 +00:00
|
|
|
|
|
|
|
import asynckivy
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
|
|
KV = '''
|
|
|
|
<UserCard>
|
|
|
|
adaptive_height: True
|
|
|
|
radius: 16
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
MDListItem:
|
|
|
|
radius: 16
|
|
|
|
theme_bg_color: "Custom"
|
|
|
|
md_bg_color: self.theme_cls.secondaryContainerColor
|
|
|
|
|
|
|
|
MDListItemLeadingAvatar:
|
2024-09-15 12:12:16 +00:00
|
|
|
source: root.album
|
2024-09-15 17:57:02 +00:00
|
|
|
|
|
|
|
MDListItemHeadlineText:
|
|
|
|
text: root.name
|
|
|
|
|
|
|
|
MDListItemSupportingText:
|
|
|
|
text: root.path_to_file
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
|
|
|
|
|
|
MDScreen:
|
2024-09-15 17:57:02 +00:00
|
|
|
md_bg_color: self.theme_cls.backgroundColor
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
|
|
MDBoxLayout:
|
|
|
|
orientation: "vertical"
|
|
|
|
padding: "12dp"
|
|
|
|
spacing: "12dp"
|
|
|
|
|
|
|
|
MDLabel:
|
|
|
|
adaptive_height: True
|
|
|
|
text: "Your downloads"
|
2024-09-15 17:57:02 +00:00
|
|
|
theme_font_style: "Custom"
|
|
|
|
font_style: "Display"
|
|
|
|
role: "small"
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
|
|
MDSegmentedButton:
|
|
|
|
size_hint_x: 1
|
|
|
|
|
|
|
|
MDSegmentedButtonItem:
|
2024-09-15 17:57:02 +00:00
|
|
|
on_active: app.generate_card()
|
|
|
|
|
|
|
|
MDSegmentButtonLabel:
|
|
|
|
text: "Songs"
|
|
|
|
active: True
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
|
|
MDSegmentedButtonItem:
|
2024-09-15 17:57:02 +00:00
|
|
|
on_active: app.generate_card()
|
|
|
|
|
|
|
|
MDSegmentButtonLabel:
|
|
|
|
text: "Albums"
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
|
|
MDSegmentedButtonItem:
|
2024-09-15 17:57:02 +00:00
|
|
|
on_active: app.generate_card()
|
|
|
|
|
|
|
|
MDSegmentButtonLabel:
|
|
|
|
text: "Podcasts"
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
|
|
RecycleView:
|
|
|
|
id: card_list
|
|
|
|
viewclass: "UserCard"
|
|
|
|
bar_width: 0
|
|
|
|
|
|
|
|
RecycleBoxLayout:
|
|
|
|
orientation: 'vertical'
|
|
|
|
spacing: "16dp"
|
|
|
|
padding: "16dp"
|
|
|
|
default_size: None, dp(72)
|
|
|
|
default_size_hint: 1, None
|
|
|
|
size_hint_y: None
|
|
|
|
height: self.minimum_height
|
|
|
|
'''
|
|
|
|
|
|
|
|
|
|
|
|
class UserCard(MDBoxLayout):
|
|
|
|
name = StringProperty()
|
|
|
|
path_to_file = StringProperty()
|
|
|
|
album = StringProperty()
|
|
|
|
|
|
|
|
|
|
|
|
class Example(MDApp):
|
|
|
|
def build(self):
|
|
|
|
self.theme_cls.theme_style = "Dark"
|
2024-09-15 17:57:02 +00:00
|
|
|
self.theme_cls.primary_palette = "Olive"
|
2024-09-15 12:12:16 +00:00
|
|
|
return Builder.load_string(KV)
|
|
|
|
|
|
|
|
def generate_card(self):
|
|
|
|
async def generate_card():
|
|
|
|
for i in range(10):
|
|
|
|
await asynckivy.sleep(0)
|
|
|
|
self.root.ids.card_list.data.append(
|
|
|
|
{
|
|
|
|
"name": fake.name(),
|
|
|
|
"path_to_file": f"{os.path.splitext(fake.file_path())[0]}.mp3",
|
|
|
|
"album": fake.image_url(),
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
|
|
|
fake = Faker()
|
|
|
|
self.root.ids.card_list.data = []
|
|
|
|
Clock.schedule_once(lambda x: asynckivy.start(generate_card()))
|
|
|
|
|
|
|
|
|
|
|
|
Example().run()
|
|
|
|
|
|
|
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/segmented-button-practical-example.gif
|
|
|
|
:align: center
|
2024-09-15 17:57:02 +00:00
|
|
|
|
|
|
|
API break
|
|
|
|
=========
|
|
|
|
|
|
|
|
1.2.0 version
|
|
|
|
-------------
|
|
|
|
|
|
|
|
.. code-block:: kv
|
|
|
|
|
|
|
|
MDSegmentedButton:
|
|
|
|
on_marked: func(*args)
|
|
|
|
|
|
|
|
MDSegmentedButtonItem:
|
|
|
|
icon: ...
|
|
|
|
text: ...
|
|
|
|
|
|
|
|
2.0.0 version
|
|
|
|
-------------
|
|
|
|
|
|
|
|
.. code-block:: kv
|
|
|
|
|
|
|
|
MDSegmentedButton:
|
|
|
|
|
|
|
|
MDSegmentedButtonItem:
|
|
|
|
on_active: func(*args)
|
|
|
|
|
|
|
|
MDSegmentButtonIcon:
|
|
|
|
icon: ...
|
|
|
|
|
|
|
|
MDSegmentButtonLabel:
|
|
|
|
text: ...
|
|
|
|
|
2024-09-15 12:12:16 +00:00
|
|
|
"""
|
|
|
|
|
|
|
|
from __future__ import annotations
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
__all__ = (
|
|
|
|
"MDSegmentedButton",
|
|
|
|
"MDSegmentedButtonItem",
|
|
|
|
"MDSegmentButtonLabel",
|
|
|
|
"MDSegmentButtonIcon",
|
|
|
|
)
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
|
|
import os
|
|
|
|
|
|
|
|
from kivy.animation import Animation
|
|
|
|
from kivy.clock import Clock
|
|
|
|
from kivy.lang import Builder
|
2024-09-15 17:57:02 +00:00
|
|
|
from kivy.metrics import dp, sp
|
2024-09-15 12:12:16 +00:00
|
|
|
from kivy.properties import (
|
|
|
|
BooleanProperty,
|
|
|
|
ColorProperty,
|
|
|
|
ListProperty,
|
|
|
|
NumericProperty,
|
|
|
|
StringProperty,
|
2024-09-15 17:57:02 +00:00
|
|
|
OptionProperty,
|
|
|
|
ObjectProperty,
|
2024-09-15 12:12:16 +00:00
|
|
|
)
|
|
|
|
from kivy.uix.behaviors import ButtonBehavior
|
2024-09-15 17:57:02 +00:00
|
|
|
from kivy.uix.boxlayout import BoxLayout
|
|
|
|
from kivy.uix.relativelayout import RelativeLayout
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
from kivymd.theming import ThemableBehavior
|
2024-09-15 12:12:16 +00:00
|
|
|
from kivymd import uix_path
|
2024-09-15 17:57:02 +00:00
|
|
|
from kivymd.uix.behaviors import (
|
|
|
|
RectangularRippleBehavior,
|
|
|
|
DeclarativeBehavior,
|
|
|
|
BackgroundColorBehavior,
|
|
|
|
)
|
|
|
|
from kivymd.uix.behaviors.state_layer_behavior import StateLayerBehavior
|
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.label import MDIcon, MDLabel
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
|
|
with open(
|
|
|
|
os.path.join(uix_path, "segmentedbutton", "segmentedbutton.kv"),
|
|
|
|
encoding="utf-8",
|
|
|
|
) as kv_file:
|
2024-09-15 17:57:02 +00:00
|
|
|
Builder.load_string(kv_file.read(), filename="MDSegmentedButton")
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
|
|
|
|
|
|
class MDSegmentedButtonItem(
|
2024-09-15 17:57:02 +00:00
|
|
|
DeclarativeBehavior,
|
|
|
|
ThemableBehavior,
|
|
|
|
BackgroundColorBehavior,
|
|
|
|
RectangularRippleBehavior,
|
|
|
|
ButtonBehavior,
|
|
|
|
StateLayerBehavior,
|
|
|
|
RelativeLayout,
|
2024-09-15 12:12:16 +00:00
|
|
|
):
|
|
|
|
"""
|
|
|
|
Segment button item.
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
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:`~kivymd.uix.behaviors.ripple_behavior.RectangularRippleBehavior` and
|
2024-09-15 12:12:16 +00:00
|
|
|
:class:`~kivy.uix.behaviors.ButtonBehavior` and
|
2024-09-15 17:57:02 +00:00
|
|
|
:class:`~kivymd.uix.behaviors.state_layer_behavior.StateLayerBehavior` and
|
|
|
|
:class:`~kivy.uix.relativelayout.RelativeLayout` and
|
2024-09-15 12:12:16 +00:00
|
|
|
class documentation.
|
|
|
|
"""
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
selected_color = ColorProperty(None)
|
2024-09-15 12:12:16 +00:00
|
|
|
"""
|
2024-09-15 17:57:02 +00:00
|
|
|
Color of the marked segment.
|
|
|
|
|
|
|
|
.. versionadded:: 2.0.0
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
:attr:`selected_color` is a :class:`~kivy.properties.ColorProperty`
|
|
|
|
and defaults to `None`.
|
2024-09-15 12:12:16 +00:00
|
|
|
"""
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
md_bg_color_disabled = ColorProperty(None)
|
2024-09-15 12:12:16 +00:00
|
|
|
"""
|
2024-09-15 17:57:02 +00:00
|
|
|
The background color in (r, g, b, a) or string format of the list item when
|
|
|
|
the list item is disabled.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
:attr:`md_bg_color_disabled` is a :class:`~kivy.properties.ColorProperty`
|
|
|
|
and defaults to `None`.
|
2024-09-15 12:12:16 +00:00
|
|
|
"""
|
|
|
|
|
|
|
|
active = BooleanProperty(False)
|
|
|
|
"""
|
|
|
|
Background color of an disabled segment.
|
|
|
|
|
|
|
|
:attr:`active` is an :class:`~kivy.properties.BooleanProperty`
|
|
|
|
and defaults to `False`.
|
|
|
|
"""
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
_icon = ObjectProperty() # MDSegmentButtonIcon object
|
|
|
|
_label = ObjectProperty() # MDSegmentButtonLabel object
|
|
|
|
_segmented_button = ObjectProperty() # MDSegmentedButton object
|
|
|
|
_line_color = ColorProperty(None)
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
def add_widget(self, widget, *args, **kwargs):
|
|
|
|
def add_selected_icon(container: MDSegmentedButtonItemContainer):
|
|
|
|
selected_icon = MDSegmentButtonSelectedIcon(
|
|
|
|
_segmented_button=self._segmented_button, _item=self
|
|
|
|
)
|
|
|
|
container.add_widget(selected_icon, index=1)
|
|
|
|
|
|
|
|
if isinstance(
|
|
|
|
widget,
|
|
|
|
(MDSegmentButtonLabel, MDSegmentButtonIcon),
|
|
|
|
):
|
|
|
|
if isinstance(widget, MDSegmentButtonLabel):
|
|
|
|
self._label = widget
|
|
|
|
elif isinstance(widget, MDSegmentButtonIcon):
|
|
|
|
self._icon = widget
|
|
|
|
Clock.schedule_once(
|
|
|
|
lambda x: self._segmented_button._set_size_hint_min_x(widget)
|
|
|
|
)
|
|
|
|
self.ids.container.add_widget(widget)
|
|
|
|
elif isinstance(widget, MDSegmentedButtonItemContainer):
|
|
|
|
Clock.schedule_once(lambda x: add_selected_icon(widget))
|
|
|
|
return super().add_widget(widget)
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
def on_line_color(self, instance, value) -> None:
|
|
|
|
"""Fired when the values of :attr:`line_color` change."""
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
if not self.disabled and self.theme_line_color == "Custom":
|
|
|
|
self._line_color = value
|
|
|
|
|
|
|
|
def on_active(self, instance, value) -> None:
|
|
|
|
"""
|
|
|
|
Fired when the :attr:`active` value changes.
|
|
|
|
Animates the marker icon for the element.
|
|
|
|
"""
|
|
|
|
|
|
|
|
def set_active(*args):
|
|
|
|
t = (
|
|
|
|
self._segmented_button.opening_icon_transition
|
|
|
|
if value
|
|
|
|
else self._segmented_button.hiding_icon_transition
|
|
|
|
)
|
|
|
|
d = (
|
|
|
|
self._segmented_button.opening_icon_duration
|
|
|
|
if value
|
|
|
|
else self._segmented_button.hiding_icon_duration
|
|
|
|
)
|
|
|
|
|
|
|
|
if self._icon and self._segmented_button:
|
|
|
|
if self._label:
|
|
|
|
Animation(font_size=0 if value else sp(18), t=t, d=d).start(
|
|
|
|
self._icon
|
|
|
|
)
|
|
|
|
|
|
|
|
selected_icon = self._get_selected_icon_from_container()
|
|
|
|
if selected_icon:
|
|
|
|
Animation(font_size=sp(18) if value else 0, t=t, d=d).start(
|
|
|
|
selected_icon
|
2024-09-15 12:12:16 +00:00
|
|
|
)
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
Clock.schedule_once(set_active, 0.5)
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
def on_disabled(self, instance, value) -> None:
|
|
|
|
"""Fired when the :attr:`disabled` value changes."""
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
selected_icon = None
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
if self._icon and self._segmented_button:
|
|
|
|
selected_icon = self._get_selected_icon_from_item()
|
|
|
|
elif not self._icon and self._segmented_button:
|
|
|
|
selected_icon = self._get_selected_icon_from_container()
|
|
|
|
|
|
|
|
if selected_icon:
|
|
|
|
selected_icon.state_layer_color = self.theme_cls.transparentColor
|
|
|
|
|
|
|
|
def _get_selected_icon_from_container(self):
|
|
|
|
selected_icon = None
|
|
|
|
for item in self.ids.container.children:
|
|
|
|
if isinstance(item, MDSegmentButtonSelectedIcon):
|
|
|
|
selected_icon = item
|
|
|
|
break
|
|
|
|
return selected_icon
|
|
|
|
|
|
|
|
def _get_selected_icon_from_item(self):
|
|
|
|
selected_icon = None
|
|
|
|
for item in self.children:
|
|
|
|
if isinstance(item, MDSegmentButtonSelectedIcon):
|
|
|
|
selected_icon = item
|
|
|
|
break
|
|
|
|
return selected_icon
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
|
|
|
|
|
|
class MDSegmentedButton(MDBoxLayout):
|
|
|
|
"""
|
|
|
|
Segment button panel.
|
|
|
|
|
|
|
|
For more information, see in the
|
|
|
|
:class:`~kivymd.uix.boxlayout.MDBoxLayout` class documentation.
|
|
|
|
"""
|
|
|
|
|
|
|
|
multiselect = BooleanProperty(False)
|
|
|
|
"""
|
|
|
|
Do I allow multiple segment selection.
|
|
|
|
|
|
|
|
:attr:`multiselect` is an :class:`~kivy.properties.BooleanProperty`
|
|
|
|
and defaults to `False`.
|
|
|
|
"""
|
|
|
|
|
|
|
|
hiding_icon_transition = StringProperty("linear")
|
|
|
|
"""
|
|
|
|
Name of the transition hiding the current icon.
|
|
|
|
|
|
|
|
:attr:`hiding_icon_transition` is a :class:`~kivy.properties.StringProperty`
|
|
|
|
and defaults to `'linear'`.
|
|
|
|
"""
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
hiding_icon_duration = NumericProperty(0.1)
|
2024-09-15 12:12:16 +00:00
|
|
|
"""
|
|
|
|
Duration of hiding the current icon.
|
|
|
|
|
|
|
|
:attr:`hiding_icon_duration` is a :class:`~kivy.properties.NumericProperty`
|
2024-09-15 17:57:02 +00:00
|
|
|
and defaults to `1`.
|
2024-09-15 12:12:16 +00:00
|
|
|
"""
|
|
|
|
|
|
|
|
opening_icon_transition = StringProperty("linear")
|
|
|
|
"""
|
|
|
|
The name of the transition that opens a new icon of the "marked" type.
|
|
|
|
|
|
|
|
:attr:`opening_icon_transition` is a :class:`~kivy.properties.StringProperty`
|
|
|
|
and defaults to `'linear'`.
|
|
|
|
"""
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
opening_icon_duration = NumericProperty(0.1)
|
2024-09-15 12:12:16 +00:00
|
|
|
"""
|
|
|
|
The duration of opening a new icon of the "marked" type.
|
|
|
|
|
|
|
|
:attr:`opening_icon_duration` is a :class:`~kivy.properties.NumericProperty`
|
2024-09-15 17:57:02 +00:00
|
|
|
and defaults to `0.1`.
|
2024-09-15 12:12:16 +00:00
|
|
|
"""
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
selected_segments = ListProperty()
|
2024-09-15 12:12:16 +00:00
|
|
|
"""
|
|
|
|
The list of :class:`~MDSegmentedButtonItem` objects that are currently
|
|
|
|
marked.
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
:attr:`selected_segments` is a :class:`~kivy.properties.ListProperty`
|
2024-09-15 12:12:16 +00:00
|
|
|
and defaults to `[]`.
|
|
|
|
"""
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
type = OptionProperty(
|
|
|
|
"large", options=["large", "normal", "medium", "small"]
|
|
|
|
)
|
2024-09-15 12:12:16 +00:00
|
|
|
"""
|
2024-09-15 17:57:02 +00:00
|
|
|
Density can be used in denser UIs where space is limited.
|
|
|
|
Density is only applied to the height. Each step down in density removes
|
|
|
|
'4dp' from the height.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
.. versionadded:: 2.0.0
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
Available options are: 'large', 'normal', 'medium', 'small'.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
:attr:`type` is an :class:`~kivy.properties.OptionProperty`
|
|
|
|
and defaults to `'large'`.
|
|
|
|
"""
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
selected_icon_color = ColorProperty(None)
|
|
|
|
"""
|
|
|
|
Color in (r, g, b, a) or string format of the icon of the marked segment.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
.. versionadded:: 2.0.0
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
:attr:`selected_icon_color` is a :class:`~kivy.properties.ColorProperty`
|
|
|
|
and defaults to `None`.
|
|
|
|
"""
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
def get_marked_items(self) -> list:
|
|
|
|
"""Returns a list of active item objects."""
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
return [item for item in self.ids.container.children if item.active]
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
def get_items(self) -> list:
|
|
|
|
"""Returns a list of item objects."""
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
return [item for item in self.ids.container.children]
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
def adjust_segment_radius(self, *args) -> None:
|
|
|
|
"""Rounds off the first and last elements."""
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
_rad = self.height / 2
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
_last_radius = [0, _rad, _rad, 0]
|
|
|
|
_first_radius = [_rad, 0, 0, _rad]
|
|
|
|
_optimal_radius = [0, 0, 0, 0]
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
_child_count = len(self.ids.container.children)
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
for count, child in enumerate(self.ids.container.children):
|
|
|
|
if count == 0:
|
|
|
|
child.radius = _last_radius
|
|
|
|
elif count == _child_count - 1:
|
|
|
|
child.radius = _first_radius
|
|
|
|
else:
|
|
|
|
child.radius = _optimal_radius
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
|
|
def mark_item(self, segment_item: MDSegmentedButtonItem) -> None:
|
2024-09-15 17:57:02 +00:00
|
|
|
"""Fired when a segment element is clicked (`on_release` event)."""
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
if not segment_item.disabled:
|
|
|
|
if not segment_item.active and not self.multiselect:
|
|
|
|
segment_item.active = True
|
|
|
|
elif self.multiselect:
|
|
|
|
segment_item.active = not segment_item.active
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
if not self.multiselect:
|
|
|
|
for widget in self.ids.container.children:
|
|
|
|
if segment_item is not widget:
|
|
|
|
widget.active = False
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
|
|
def add_widget(self, widget, *args, **kwargs):
|
|
|
|
if isinstance(widget, MDSegmentedButtonItem):
|
2024-09-15 17:57:02 +00:00
|
|
|
widget._segmented_button = self
|
2024-09-15 12:12:16 +00:00
|
|
|
widget.bind(on_release=self.mark_item)
|
2024-09-15 17:57:02 +00:00
|
|
|
self.ids.container.add_widget(widget)
|
|
|
|
self.adjust_segment_radius()
|
|
|
|
elif isinstance(widget, MDSegmentedButtonContainer):
|
2024-09-15 12:12:16 +00:00
|
|
|
return super().add_widget(widget)
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
def remove_widget(self, widget, *args, **kwargs):
|
|
|
|
if isinstance(widget, MDSegmentedButtonItem):
|
|
|
|
for child in widget.children[0].children:
|
|
|
|
if isinstance(child, MDSegmentButtonLabel) or isinstance(
|
|
|
|
child, MDSegmentButtonIcon
|
|
|
|
):
|
|
|
|
self._set_size_hint_min_x(child, sign=-1)
|
|
|
|
self.ids.container.remove_widget(widget)
|
|
|
|
self.adjust_segment_radius()
|
|
|
|
elif isinstance(widget, MDSegmentedButtonContainer):
|
|
|
|
return super().remove_widget(widget)
|
|
|
|
|
|
|
|
def _set_size_hint_min_x(
|
|
|
|
self, widget: MDSegmentButtonLabel | MDSegmentButtonIcon, sign: int = 1
|
|
|
|
):
|
|
|
|
self.ids.container.size_hint_min_x += sign * (
|
|
|
|
widget.texture_size[0] + dp(36)
|
|
|
|
)
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
class MDSegmentedButtonContainer(BoxLayout):
|
|
|
|
"""
|
|
|
|
Implements a container for placing :class:`~MDSegmentedButtonItem`
|
|
|
|
elements.
|
|
|
|
|
|
|
|
.. versionadded:: 2.0.0
|
|
|
|
|
|
|
|
For more information, see in the
|
|
|
|
:class:`~kivy.uix.boxlayout.BoxLayout` class documentation.
|
|
|
|
"""
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
class MDSegmentedButtonItemContainer(BoxLayout):
|
|
|
|
"""
|
|
|
|
Implements a container for placing :class:`~MDSegmentButtonLabel`
|
|
|
|
and :class:`~MDSegmentButtonLabel` elements.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
.. versionadded:: 2.0.0
|
|
|
|
|
|
|
|
For more information, see in the
|
|
|
|
:class:`~kivy.uix.boxlayout.BoxLayout` class documentation.
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
class MDSegmentButtonSelectedIcon(MDIcon):
|
|
|
|
"""
|
|
|
|
Implements the selected icon with scaling behavior
|
|
|
|
for :class:`~MDSegmentedButtonItem` class.
|
|
|
|
|
|
|
|
.. versionadded:: 2.0.0
|
|
|
|
|
|
|
|
For more information, see in the
|
|
|
|
:class:`~kivymd.uix.label.label.MDIcon` class documentation.
|
|
|
|
"""
|
|
|
|
|
|
|
|
_segmented_button = ObjectProperty() # MDSegmentedButton object
|
|
|
|
_item = ObjectProperty() # MDSegmentedButtonItem object
|
|
|
|
|
|
|
|
|
|
|
|
class MDSegmentButtonIcon(MDIcon):
|
|
|
|
"""
|
|
|
|
Implements a icon for :class:`~MDSegmentedButtonItem` class.
|
|
|
|
|
|
|
|
.. versionadded:: 2.0.0
|
|
|
|
|
|
|
|
For more information, see in the
|
|
|
|
:class:`~kivymd.uix.label.label.MDIcon` class documentation.
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
class MDSegmentButtonLabel(MDLabel):
|
|
|
|
"""
|
|
|
|
Implements a label for :class:`~MDSegmentedButtonItem` class.
|
|
|
|
|
|
|
|
.. versionadded:: 2.0.0
|
|
|
|
|
|
|
|
For more information, see in the
|
|
|
|
:class:`~kivymd.uix.label.label.MDLabel` class documentation.
|
|
|
|
"""
|