Updated KivyMD
@ -49,6 +49,9 @@ images_path = os.path.join(path, f"images{os.sep}")
|
|||||||
uix_path = os.path.join(path, "uix")
|
uix_path = os.path.join(path, "uix")
|
||||||
"""Path to uix directory."""
|
"""Path to uix directory."""
|
||||||
|
|
||||||
|
glsl_path = os.path.join(path, "data", "glsl")
|
||||||
|
"""Path to glsl directory."""
|
||||||
|
|
||||||
_log_message = (
|
_log_message = (
|
||||||
"KivyMD:"
|
"KivyMD:"
|
||||||
+ (" Release" if release else "")
|
+ (" Release" if release else "")
|
||||||
|
@ -43,9 +43,10 @@ __all__ = ("MDApp",)
|
|||||||
import os
|
import os
|
||||||
|
|
||||||
from kivy.app import App
|
from kivy.app import App
|
||||||
|
from kivy.clock import Clock
|
||||||
from kivy.lang import Builder
|
from kivy.lang import Builder
|
||||||
from kivy.logger import Logger
|
from kivy.logger import Logger
|
||||||
from kivy.properties import ObjectProperty
|
from kivy.properties import ObjectProperty, StringProperty
|
||||||
|
|
||||||
from kivymd.theming import ThemeManager
|
from kivymd.theming import ThemeManager
|
||||||
|
|
||||||
@ -56,6 +57,7 @@ class FpsMonitoring:
|
|||||||
def fps_monitor_start(self) -> None:
|
def fps_monitor_start(self) -> None:
|
||||||
"""Adds a monitor to the main application window."""
|
"""Adds a monitor to the main application window."""
|
||||||
|
|
||||||
|
def add_monitor(*args):
|
||||||
from kivy.core.window import Window
|
from kivy.core.window import Window
|
||||||
|
|
||||||
from kivymd.utils.fpsmonitor import FpsMonitor
|
from kivymd.utils.fpsmonitor import FpsMonitor
|
||||||
@ -64,6 +66,8 @@ class FpsMonitoring:
|
|||||||
monitor.start()
|
monitor.start()
|
||||||
Window.add_widget(monitor)
|
Window.add_widget(monitor)
|
||||||
|
|
||||||
|
Clock.schedule_once(add_monitor)
|
||||||
|
|
||||||
|
|
||||||
class MDApp(App, FpsMonitoring):
|
class MDApp(App, FpsMonitoring):
|
||||||
"""
|
"""
|
||||||
@ -71,6 +75,16 @@ class MDApp(App, FpsMonitoring):
|
|||||||
information.
|
information.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
icon = StringProperty("kivymd/images/logo/kivymd-icon-512.png")
|
||||||
|
"""
|
||||||
|
See :attr:`~kivy.app.App.icon` attribute for more information.
|
||||||
|
|
||||||
|
.. versionadded:: 1.1.0
|
||||||
|
|
||||||
|
:attr:`icon` is an :class:`~kivy.properties.StringProperty`
|
||||||
|
adn default to `kivymd/images/logo/kivymd-icon-512.png`.
|
||||||
|
"""
|
||||||
|
|
||||||
theme_cls = ObjectProperty()
|
theme_cls = ObjectProperty()
|
||||||
"""
|
"""
|
||||||
Instance of :class:`~ThemeManager` class.
|
Instance of :class:`~ThemeManager` class.
|
||||||
|
@ -412,7 +412,7 @@ To demonstrate the shades of the palette, you can run the following code:
|
|||||||
self.screen = Factory.Root()
|
self.screen = Factory.Root()
|
||||||
|
|
||||||
for name_tab in colors.keys():
|
for name_tab in colors.keys():
|
||||||
tab = Tab(text=name_tab)
|
tab = Tab(title=name_tab)
|
||||||
self.screen.ids.android_tabs.add_widget(tab)
|
self.screen.ids.android_tabs.add_widget(tab)
|
||||||
return self.screen
|
return self.screen
|
||||||
|
|
||||||
@ -427,7 +427,7 @@ To demonstrate the shades of the palette, you can run the following code:
|
|||||||
{
|
{
|
||||||
"viewclass": "ItemColor",
|
"viewclass": "ItemColor",
|
||||||
"md_bg_color": colors[tab_text][value_color],
|
"md_bg_color": colors[tab_text][value_color],
|
||||||
"text": value_color,
|
"title": value_color,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
51
sbapp/kivymd/data/glsl/elevation/elevation.frag
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
The shader code has been refactored for the KivyMD library.
|
||||||
|
You can find the original code of this shaders at the links:
|
||||||
|
|
||||||
|
https://www.shadertoy.com/view/WtdSDs
|
||||||
|
https://www.shadertoy.com/view/fsdyzB
|
||||||
|
|
||||||
|
Additional thanks to iq for optimizing conditional block for individual
|
||||||
|
corner radius:
|
||||||
|
https://iquilezles.org/articles/distfunctions
|
||||||
|
*/
|
||||||
|
|
||||||
|
// For lower opengl version
|
||||||
|
|
||||||
|
float custom_smoothstep(float a, float b, float x) {
|
||||||
|
float t = clamp((x - a) / (b - a), 0.0, 1.0);
|
||||||
|
return t * t * (3.0 - 2.0 * t);
|
||||||
|
}
|
||||||
|
|
||||||
|
float roundedBoxSDF(vec2 centerPosition, vec2 size, vec4 radius) {
|
||||||
|
radius.xy = (centerPosition.x > 0.0) ? radius.xy : radius.zw;
|
||||||
|
radius.x = (centerPosition.y > 0.0) ? radius.x : radius.y;
|
||||||
|
|
||||||
|
vec2 q = abs(centerPosition) - (size - shadow_softness) + radius.x;
|
||||||
|
return min(max(q.x, q.y), 0.0) + length(max(q, 0.0)) - radius.x;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
|
||||||
|
// Smooth the result (free antialiasing).
|
||||||
|
float edge0 = 0.0;
|
||||||
|
float smoothedAlpha = 1.0 - custom_smoothstep(0.0, edge0, 1.0);
|
||||||
|
// Get the resultant shape.
|
||||||
|
vec4 quadColor = mix(
|
||||||
|
vec4(
|
||||||
|
shadow_color[0],
|
||||||
|
shadow_color[1],
|
||||||
|
shadow_color[2],
|
||||||
|
0.0
|
||||||
|
),
|
||||||
|
shadow_color,
|
||||||
|
smoothedAlpha
|
||||||
|
);
|
||||||
|
// Apply a drop shadow effect.
|
||||||
|
float shadowDistance = roundedBoxSDF(
|
||||||
|
fragCoord.xy - mouse.xy - (size / 2.0), size / 2.0, shadow_radius
|
||||||
|
);
|
||||||
|
float shadowAlpha = 1.0 - custom_smoothstep(
|
||||||
|
-shadow_softness, shadow_softness, shadowDistance
|
||||||
|
);
|
||||||
|
fragColor = mix(quadColor, shadow_color, shadowAlpha - smoothedAlpha);
|
||||||
|
}
|
10
sbapp/kivymd/data/glsl/elevation/header.frag
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#ifdef GL_ES
|
||||||
|
precision highp float;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uniform vec4 resolution;
|
||||||
|
uniform vec4 mouse;
|
||||||
|
uniform vec2 size;
|
||||||
|
uniform vec4 shadow_radius;
|
||||||
|
uniform float shadow_softness;
|
||||||
|
uniform vec4 shadow_color;
|
10
sbapp/kivymd/data/glsl/elevation/main.frag
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
vec2 gfc(in vec4 fc) {
|
||||||
|
vec2 canvas_pos = resolution.zw;
|
||||||
|
vec2 uv = fc.xy;
|
||||||
|
uv.y -= canvas_pos.y;
|
||||||
|
return uv;
|
||||||
|
}
|
||||||
|
|
||||||
|
void main(void) {
|
||||||
|
mainImage(gl_FragColor, gfc(gl_FragCoord));
|
||||||
|
}
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 31 KiB |
Before Width: | Height: | Size: 31 KiB |
Before Width: | Height: | Size: 21 KiB |
@ -1 +0,0 @@
|
|||||||
{"quad_shadow-1.png": {"20": [2, 136, 128, 128], "21": [132, 136, 128, 128], "22": [262, 136, 128, 128], "23": [2, 6, 128, 128], "19": [132, 266, 128, 128], "18": [2, 266, 128, 128], "1": [262, 266, 128, 128], "3": [262, 6, 128, 128], "2": [132, 6, 128, 128]}, "quad_shadow-0.png": {"11": [262, 266, 128, 128], "10": [132, 266, 128, 128], "13": [132, 136, 128, 128], "12": [2, 136, 128, 128], "15": [2, 6, 128, 128], "14": [262, 136, 128, 128], "17": [262, 6, 128, 128], "16": [132, 6, 128, 128], "0": [2, 266, 128, 128]}, "quad_shadow-2.png": {"5": [132, 266, 128, 128], "4": [2, 266, 128, 128], "7": [2, 136, 128, 128], "6": [262, 266, 128, 128], "9": [262, 136, 128, 128], "8": [132, 136, 128, 128]}}
|
|
Before Width: | Height: | Size: 46 KiB |
Before Width: | Height: | Size: 43 KiB |
@ -1 +0,0 @@
|
|||||||
{"rec_shadow-1.png": {"20": [2, 266, 256, 128], "21": [260, 266, 256, 128], "22": [518, 266, 256, 128], "23": [776, 266, 256, 128], "3": [260, 136, 256, 128], "2": [2, 136, 256, 128], "5": [776, 136, 256, 128], "4": [518, 136, 256, 128], "7": [260, 6, 256, 128], "6": [2, 6, 256, 128], "9": [776, 6, 256, 128], "8": [518, 6, 256, 128]}, "rec_shadow-0.png": {"11": [518, 266, 256, 128], "10": [260, 266, 256, 128], "13": [2, 136, 256, 128], "12": [776, 266, 256, 128], "15": [518, 136, 256, 128], "14": [260, 136, 256, 128], "17": [2, 6, 256, 128], "16": [776, 136, 256, 128], "19": [518, 6, 256, 128], "18": [260, 6, 256, 128], "1": [776, 6, 256, 128], "0": [2, 266, 256, 128]}}
|
|
Before Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 32 KiB |
Before Width: | Height: | Size: 28 KiB |
@ -1 +0,0 @@
|
|||||||
{"rec_st_shadow-0.png": {"11": [262, 138, 128, 256], "10": [132, 138, 128, 256], "13": [522, 138, 128, 256], "12": [392, 138, 128, 256], "15": [782, 138, 128, 256], "14": [652, 138, 128, 256], "16": [912, 138, 128, 256], "0": [2, 138, 128, 256]}, "rec_st_shadow-1.png": {"20": [522, 138, 128, 256], "21": [652, 138, 128, 256], "17": [2, 138, 128, 256], "23": [912, 138, 128, 256], "19": [262, 138, 128, 256], "18": [132, 138, 128, 256], "22": [782, 138, 128, 256], "1": [392, 138, 128, 256]}, "rec_st_shadow-2.png": {"3": [132, 138, 128, 256], "2": [2, 138, 128, 256], "5": [392, 138, 128, 256], "4": [262, 138, 128, 256], "7": [652, 138, 128, 256], "6": [522, 138, 128, 256], "9": [912, 138, 128, 256], "8": [782, 138, 128, 256]}}
|
|
Before Width: | Height: | Size: 39 KiB |
Before Width: | Height: | Size: 40 KiB |
Before Width: | Height: | Size: 26 KiB |
@ -1 +0,0 @@
|
|||||||
{"round_shadow-1.png": {"20": [2, 136, 128, 128], "21": [132, 136, 128, 128], "22": [262, 136, 128, 128], "23": [2, 6, 128, 128], "19": [132, 266, 128, 128], "18": [2, 266, 128, 128], "1": [262, 266, 128, 128], "3": [262, 6, 128, 128], "2": [132, 6, 128, 128]}, "round_shadow-0.png": {"11": [262, 266, 128, 128], "10": [132, 266, 128, 128], "13": [132, 136, 128, 128], "12": [2, 136, 128, 128], "15": [2, 6, 128, 128], "14": [262, 136, 128, 128], "17": [262, 6, 128, 128], "16": [132, 6, 128, 128], "0": [2, 266, 128, 128]}, "round_shadow-2.png": {"5": [132, 266, 128, 128], "4": [2, 266, 128, 128], "7": [2, 136, 128, 128], "6": [262, 266, 128, 128], "9": [262, 136, 128, 128], "8": [132, 136, 128, 128]}}
|
|
@ -35,8 +35,15 @@ assert "Icons" in LabelBase._fonts.keys() # NOQA
|
|||||||
|
|
||||||
images = os.listdir(kivymd.images_path)
|
images = os.listdir(kivymd.images_path)
|
||||||
print(images)
|
print(images)
|
||||||
|
assert "logo" in images
|
||||||
|
assert "alpha_layer.png" in images
|
||||||
|
assert "black.png" in images
|
||||||
|
assert "blue.png" in images
|
||||||
|
assert "red.png" in images
|
||||||
|
assert "green.png" in images
|
||||||
|
assert "yellow.png" in images
|
||||||
assert "folder.png" in images
|
assert "folder.png" in images
|
||||||
assert "rec_shadow.atlas" in images
|
assert "transparent.png" in images
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
pyi_main.run(
|
pyi_main.run(
|
||||||
|
@ -1,14 +1,13 @@
|
|||||||
def test_create_project():
|
def test_create_project():
|
||||||
import os
|
import os
|
||||||
import sys
|
|
||||||
|
|
||||||
os.system(
|
os.system(
|
||||||
f"{sys.executable} -m kivymd.tools.patterns.create_project "
|
f"python3.10 -m kivymd.tools.patterns.create_project "
|
||||||
f"MVC "
|
f"MVC "
|
||||||
f"{os.path.expanduser('~')} "
|
f"{os.path.expanduser('~')} "
|
||||||
f"TestProject "
|
f"TestProject "
|
||||||
f"{sys.executable} "
|
f"python3.10 "
|
||||||
f"master "
|
f"stable "
|
||||||
f"--name_screen TestProjectScreen "
|
f"--name_screen TestProjectScreen "
|
||||||
f"--name_database restdb "
|
f"--name_database restdb "
|
||||||
f"--use_hotreload yes"
|
f"--use_hotreload yes"
|
||||||
|
@ -212,9 +212,8 @@ respects, the theming stays as documented.
|
|||||||
dictionary :attr:`kivymd.color_definition.colors`.
|
dictionary :attr:`kivymd.color_definition.colors`.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from kivy.animation import Animation
|
||||||
from kivy.app import App
|
from kivy.app import App
|
||||||
from kivy.atlas import Atlas
|
|
||||||
from kivy.clock import Clock
|
from kivy.clock import Clock
|
||||||
from kivy.core.window import Window
|
from kivy.core.window import Window
|
||||||
from kivy.event import EventDispatcher
|
from kivy.event import EventDispatcher
|
||||||
@ -224,13 +223,13 @@ from kivy.properties import (
|
|||||||
BooleanProperty,
|
BooleanProperty,
|
||||||
ColorProperty,
|
ColorProperty,
|
||||||
DictProperty,
|
DictProperty,
|
||||||
|
NumericProperty,
|
||||||
ObjectProperty,
|
ObjectProperty,
|
||||||
OptionProperty,
|
OptionProperty,
|
||||||
StringProperty,
|
StringProperty,
|
||||||
)
|
)
|
||||||
from kivy.utils import get_color_from_hex
|
from kivy.utils import get_color_from_hex
|
||||||
|
|
||||||
from kivymd import images_path
|
|
||||||
from kivymd.color_definitions import colors, hue, palette
|
from kivymd.color_definitions import colors, hue, palette
|
||||||
from kivymd.font_definitions import theme_font_styles
|
from kivymd.font_definitions import theme_font_styles
|
||||||
from kivymd.material_resources import DEVICE_IOS, DEVICE_TYPE
|
from kivymd.material_resources import DEVICE_IOS, DEVICE_TYPE
|
||||||
@ -624,6 +623,152 @@ class ThemeManager(EventDispatcher):
|
|||||||
and defaults to `'M2'`.
|
and defaults to `'M2'`.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
theme_style_switch_animation = BooleanProperty(False)
|
||||||
|
"""
|
||||||
|
Animate app colors when switching app color scheme ('Dark/light').
|
||||||
|
|
||||||
|
.. versionadded:: 1.1.0
|
||||||
|
|
||||||
|
.. tabs::
|
||||||
|
|
||||||
|
.. tab:: Declarative KV style
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from kivy.lang import Builder
|
||||||
|
|
||||||
|
from kivymd.app import MDApp
|
||||||
|
|
||||||
|
KV = '''
|
||||||
|
MDScreen:
|
||||||
|
|
||||||
|
MDCard:
|
||||||
|
orientation: "vertical"
|
||||||
|
padding: 0, 0, 0 , "36dp"
|
||||||
|
size_hint: .5, .5
|
||||||
|
pos_hint: {"center_x": .5, "center_y": .5}
|
||||||
|
elevation: 4
|
||||||
|
shadow_radius: 6
|
||||||
|
shadow_offset: 0, 2
|
||||||
|
|
||||||
|
MDLabel:
|
||||||
|
text: "Theme style - {}".format(app.theme_cls.theme_style)
|
||||||
|
halign: "center"
|
||||||
|
valign: "center"
|
||||||
|
bold: True
|
||||||
|
font_style: "H5"
|
||||||
|
|
||||||
|
MDRaisedButton:
|
||||||
|
text: "Set theme"
|
||||||
|
on_release: app.switch_theme_style()
|
||||||
|
pos_hint: {"center_x": .5}
|
||||||
|
'''
|
||||||
|
|
||||||
|
|
||||||
|
class Example(MDApp):
|
||||||
|
def build(self):
|
||||||
|
self.theme_cls.theme_style_switch_animation = True
|
||||||
|
self.theme_cls.theme_style = "Dark"
|
||||||
|
self.theme_cls.primary_palette = "Orange"
|
||||||
|
return Builder.load_string(KV)
|
||||||
|
|
||||||
|
def switch_theme_style(self):
|
||||||
|
self.theme_cls.primary_palette = (
|
||||||
|
"Orange" if self.theme_cls.primary_palette == "Red" else "Red"
|
||||||
|
)
|
||||||
|
self.theme_cls.theme_style = (
|
||||||
|
"Dark" if self.theme_cls.theme_style == "Light" else "Light"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
Example().run()
|
||||||
|
|
||||||
|
.. tab:: Declarative python style
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from kivymd.app import MDApp
|
||||||
|
from kivymd.uix.button import MDRaisedButton
|
||||||
|
from kivymd.uix.card import MDCard
|
||||||
|
from kivymd.uix.label import MDLabel
|
||||||
|
from kivymd.uix.screen import MDScreen
|
||||||
|
|
||||||
|
|
||||||
|
class Example(MDApp):
|
||||||
|
def build(self):
|
||||||
|
self.theme_cls.theme_style_switch_animation = True
|
||||||
|
self.theme_cls.theme_style = "Dark"
|
||||||
|
self.theme_cls.primary_palette = "Orange"
|
||||||
|
return (
|
||||||
|
MDScreen(
|
||||||
|
MDCard(
|
||||||
|
MDLabel(
|
||||||
|
id="label",
|
||||||
|
text="Theme style - {}".format(self.theme_cls.theme_style),
|
||||||
|
halign="center",
|
||||||
|
valign="center",
|
||||||
|
bold=True,
|
||||||
|
font_style="H5",
|
||||||
|
),
|
||||||
|
MDRaisedButton(
|
||||||
|
text="Set theme",
|
||||||
|
on_release=self.switch_theme_style,
|
||||||
|
pos_hint={"center_x": 0.5},
|
||||||
|
),
|
||||||
|
id="card",
|
||||||
|
orientation="vertical",
|
||||||
|
padding=(0, 0, 0, "36dp"),
|
||||||
|
size_hint=(0.5, 0.5),
|
||||||
|
pos_hint={"center_x": 0.5, "center_y": 0.5},
|
||||||
|
elevation=4,
|
||||||
|
shadow_radius=6,
|
||||||
|
shadow_offset=(0, 2),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
def switch_theme_style(self, *args):
|
||||||
|
self.theme_cls.primary_palette = (
|
||||||
|
"Orange" if self.theme_cls.primary_palette == "Red" else "Red"
|
||||||
|
)
|
||||||
|
self.theme_cls.theme_style = (
|
||||||
|
"Dark" if self.theme_cls.theme_style == "Light" else "Light"
|
||||||
|
)
|
||||||
|
self.root.ids.card.ids.label.text = (
|
||||||
|
"Theme style - {}".format(self.theme_cls.theme_style)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
Example().run()
|
||||||
|
|
||||||
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/theme-style-switch-animation.gif
|
||||||
|
:align: center
|
||||||
|
|
||||||
|
:attr:`theme_style_switch_animation` is an :class:`~kivy.properties.BooleanProperty`
|
||||||
|
and defaults to `False`.
|
||||||
|
"""
|
||||||
|
|
||||||
|
theme_style_switch_animation_duration = NumericProperty(0.2)
|
||||||
|
"""
|
||||||
|
Duration of the animation of switching the color scheme of the application
|
||||||
|
("Dark/light").
|
||||||
|
|
||||||
|
.. versionadded:: 1.1.0
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
class Example(MDApp):
|
||||||
|
def build(self):
|
||||||
|
self.theme_cls.theme_style_switch_animation = True
|
||||||
|
self.theme_cls.theme_style_switch_animation_duration = 0.8
|
||||||
|
|
||||||
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/theme-style-switch-animation-duration.gif
|
||||||
|
:align: center
|
||||||
|
|
||||||
|
:attr:`theme_style_switch_animation_duration` is an :class:`~kivy.properties.NumericProperty`
|
||||||
|
and defaults to `0.2`.
|
||||||
|
"""
|
||||||
|
|
||||||
theme_style = OptionProperty("Light", options=["Light", "Dark"])
|
theme_style = OptionProperty("Light", options=["Light", "Dark"])
|
||||||
"""
|
"""
|
||||||
App theme style.
|
App theme style.
|
||||||
@ -1184,14 +1329,22 @@ class ThemeManager(EventDispatcher):
|
|||||||
):
|
):
|
||||||
self.set_clearcolor_by_theme_style(theme_style)
|
self.set_clearcolor_by_theme_style(theme_style)
|
||||||
|
|
||||||
set_clearcolor = BooleanProperty(True)
|
_set_clearcolor = False
|
||||||
|
|
||||||
def set_clearcolor_by_theme_style(self, theme_style):
|
def set_clearcolor_by_theme_style(self, theme_style):
|
||||||
if not self.set_clearcolor:
|
if self.theme_style_switch_animation and self._set_clearcolor:
|
||||||
return
|
Animation(
|
||||||
|
clearcolor=get_color_from_hex(
|
||||||
|
self.colors[theme_style]["Background"]
|
||||||
|
),
|
||||||
|
d=self.theme_style_switch_animation_duration,
|
||||||
|
t="linear",
|
||||||
|
).start(Window)
|
||||||
|
else:
|
||||||
Window.clearcolor = get_color_from_hex(
|
Window.clearcolor = get_color_from_hex(
|
||||||
self.colors[theme_style]["Background"]
|
self.colors[theme_style]["Background"]
|
||||||
)
|
)
|
||||||
|
self._set_clearcolor = True
|
||||||
|
|
||||||
# Font name, size (sp), always caps, letter spacing (sp).
|
# Font name, size (sp), always caps, letter spacing (sp).
|
||||||
font_styles = DictProperty(
|
font_styles = DictProperty(
|
||||||
@ -1398,10 +1551,6 @@ class ThemeManager(EventDispatcher):
|
|||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
super().__init__(**kwargs)
|
super().__init__(**kwargs)
|
||||||
self.rec_shadow = Atlas(f"{images_path}rec_shadow.atlas")
|
|
||||||
self.rec_st_shadow = Atlas(f"{images_path}rec_st_shadow.atlas")
|
|
||||||
self.quad_shadow = Atlas(f"{images_path}quad_shadow.atlas")
|
|
||||||
self.round_shadow = Atlas(f"{images_path}round_shadow.atlas")
|
|
||||||
Clock.schedule_once(lambda x: self.on_theme_style(0, self.theme_style))
|
Clock.schedule_once(lambda x: self.on_theme_style(0, self.theme_style))
|
||||||
self._determine_device_orientation(None, Window.size)
|
self._determine_device_orientation(None, Window.size)
|
||||||
Window.bind(size=self._determine_device_orientation)
|
Window.bind(size=self._determine_device_orientation)
|
||||||
@ -1487,6 +1636,16 @@ class ThemableBehavior(EventDispatcher):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
|
self.unbind_properties = [
|
||||||
|
"theme_style",
|
||||||
|
"material_style",
|
||||||
|
"device_orientation",
|
||||||
|
"primary_color",
|
||||||
|
"primary_palette",
|
||||||
|
"accent_palette",
|
||||||
|
"text_color",
|
||||||
|
]
|
||||||
|
|
||||||
if self.theme_cls is not None:
|
if self.theme_cls is not None:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
@ -1507,3 +1666,24 @@ class ThemableBehavior(EventDispatcher):
|
|||||||
)
|
)
|
||||||
self.theme_cls = App.get_running_app().theme_cls
|
self.theme_cls = App.get_running_app().theme_cls
|
||||||
super().__init__(**kwargs)
|
super().__init__(**kwargs)
|
||||||
|
|
||||||
|
def dec_disabled(self, *args, **kwargs) -> None:
|
||||||
|
callabacks = self.theme_cls.get_property_observers("theme_style")
|
||||||
|
|
||||||
|
for callaback in callabacks:
|
||||||
|
try:
|
||||||
|
if hasattr(callaback, "proxy") and hasattr(
|
||||||
|
callaback.proxy, "theme_cls"
|
||||||
|
):
|
||||||
|
for property_name in self.unbind_properties:
|
||||||
|
self.theme_cls.unbind(
|
||||||
|
**{
|
||||||
|
property_name: getattr(
|
||||||
|
callaback.proxy, callaback.method_name
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
except ReferenceError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
super().dec_disabled(*args, **kwargs)
|
||||||
|
@ -13,6 +13,18 @@ from pathlib import Path
|
|||||||
import kivymd
|
import kivymd
|
||||||
|
|
||||||
datas = [
|
datas = [
|
||||||
|
# Add `.frag` files from the `kivymd/data/glsl/elevation` directory.
|
||||||
|
(
|
||||||
|
str(Path(kivymd.glsl_path).joinpath("elevation")) + os.sep,
|
||||||
|
str(
|
||||||
|
Path("kivymd").joinpath(
|
||||||
|
str(Path(kivymd.glsl_path)).split(str(Path("kivymd")) + os.sep)[
|
||||||
|
1
|
||||||
|
]
|
||||||
|
+ f"{os.sep}elevation"
|
||||||
|
)
|
||||||
|
),
|
||||||
|
),
|
||||||
# Add `.ttf` files from the `kivymd/fonts` directory.
|
# Add `.ttf` files from the `kivymd/fonts` directory.
|
||||||
(
|
(
|
||||||
kivymd.fonts_path,
|
kivymd.fonts_path,
|
||||||
|
@ -35,8 +35,8 @@
|
|||||||
if not root.front_layer_color \
|
if not root.front_layer_color \
|
||||||
else root.front_layer_color
|
else root.front_layer_color
|
||||||
radius:
|
radius:
|
||||||
[root.radius_left, root.radius_left,
|
[root.radius_left, root.radius_right,
|
||||||
root.radius_right, root.radius_right]
|
0, 0]
|
||||||
|
|
||||||
OneLineListItem:
|
OneLineListItem:
|
||||||
id: header_button
|
id: header_button
|
||||||
|
@ -202,7 +202,6 @@ from kivy.uix.boxlayout import BoxLayout
|
|||||||
|
|
||||||
from kivymd import uix_path
|
from kivymd import uix_path
|
||||||
from kivymd.theming import ThemableBehavior
|
from kivymd.theming import ThemableBehavior
|
||||||
from kivymd.uix.behaviors import FakeRectangularElevationBehavior
|
|
||||||
from kivymd.uix.boxlayout import MDBoxLayout
|
from kivymd.uix.boxlayout import MDBoxLayout
|
||||||
from kivymd.uix.card import MDCard
|
from kivymd.uix.card import MDCard
|
||||||
from kivymd.uix.floatlayout import MDFloatLayout
|
from kivymd.uix.floatlayout import MDFloatLayout
|
||||||
@ -528,5 +527,5 @@ class _BackLayer(BoxLayout):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class _FrontLayer(MDCard, FakeRectangularElevationBehavior):
|
class _FrontLayer(MDCard):
|
||||||
pass
|
pass
|
||||||
|
@ -35,7 +35,7 @@ Usage
|
|||||||
MDTopAppBar:
|
MDTopAppBar:
|
||||||
id: toolbar
|
id: toolbar
|
||||||
title: "Example Banners"
|
title: "Example Banners"
|
||||||
elevation: 10
|
elevation: 4
|
||||||
pos_hint: {'top': 1}
|
pos_hint: {'top': 1}
|
||||||
|
|
||||||
MDBoxLayout:
|
MDBoxLayout:
|
||||||
@ -157,7 +157,6 @@ from kivy.properties import (
|
|||||||
from kivy.uix.widget import Widget
|
from kivy.uix.widget import Widget
|
||||||
|
|
||||||
from kivymd import uix_path
|
from kivymd import uix_path
|
||||||
from kivymd.uix.behaviors import FakeRectangularElevationBehavior
|
|
||||||
from kivymd.uix.boxlayout import MDBoxLayout
|
from kivymd.uix.boxlayout import MDBoxLayout
|
||||||
from kivymd.uix.button import MDFlatButton
|
from kivymd.uix.button import MDFlatButton
|
||||||
from kivymd.uix.card import MDCard
|
from kivymd.uix.card import MDCard
|
||||||
@ -177,7 +176,7 @@ with open(
|
|||||||
Builder.load_string(kv_file.read())
|
Builder.load_string(kv_file.read())
|
||||||
|
|
||||||
|
|
||||||
class MDBanner(MDCard, FakeRectangularElevationBehavior):
|
class MDBanner(MDCard):
|
||||||
vertical_pad = NumericProperty(dp(68))
|
vertical_pad = NumericProperty(dp(68))
|
||||||
"""
|
"""
|
||||||
Indent the banner at the top of the screen.
|
Indent the banner at the top of the screen.
|
||||||
|
@ -11,18 +11,20 @@ from .backgroundcolor_behavior import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
# flake8: NOQA
|
# flake8: NOQA
|
||||||
from .declarative_bahavior import DeclarativeBehavior
|
from .declarative_behavior import DeclarativeBehavior
|
||||||
from .elevation import (
|
from .elevation import (
|
||||||
CircularElevationBehavior,
|
CircularElevationBehavior,
|
||||||
CommonElevationBehavior,
|
CommonElevationBehavior,
|
||||||
FakeCircularElevationBehavior,
|
FakeCircularElevationBehavior,
|
||||||
FakeRectangularElevationBehavior,
|
FakeRectangularElevationBehavior,
|
||||||
ObservableShadow,
|
|
||||||
RectangularElevationBehavior,
|
RectangularElevationBehavior,
|
||||||
RoundedRectangularElevationBehavior,
|
RoundedRectangularElevationBehavior,
|
||||||
)
|
)
|
||||||
from .magic_behavior import MagicBehavior
|
from .magic_behavior import MagicBehavior
|
||||||
from .ripple_behavior import CircularRippleBehavior, RectangularRippleBehavior
|
from .ripple_behavior import CircularRippleBehavior, RectangularRippleBehavior
|
||||||
|
from .rotate_behavior import RotateBehavior
|
||||||
|
from .scale_behavior import ScaleBehavior
|
||||||
|
from .stencil_behavior import StencilBehavior
|
||||||
from .touch_behavior import TouchBehavior
|
from .touch_behavior import TouchBehavior
|
||||||
|
|
||||||
from .hover_behavior import HoverBehavior # isort:skip
|
from .hover_behavior import HoverBehavior # isort:skip
|
||||||
|
@ -7,8 +7,9 @@ Behaviors/Background Color
|
|||||||
|
|
||||||
__all__ = ("BackgroundColorBehavior", "SpecificBackgroundColorBehavior")
|
__all__ = ("BackgroundColorBehavior", "SpecificBackgroundColorBehavior")
|
||||||
|
|
||||||
from typing import List
|
from typing import List, Union
|
||||||
|
|
||||||
|
from kivy.animation import Animation
|
||||||
from kivy.lang import Builder
|
from kivy.lang import Builder
|
||||||
from kivy.properties import (
|
from kivy.properties import (
|
||||||
ColorProperty,
|
ColorProperty,
|
||||||
@ -24,8 +25,6 @@ from kivy.utils import get_color_from_hex
|
|||||||
from kivymd.color_definitions import hue, palette, text_colors
|
from kivymd.color_definitions import hue, palette, text_colors
|
||||||
from kivymd.theming import ThemeManager
|
from kivymd.theming import ThemeManager
|
||||||
|
|
||||||
from .elevation import CommonElevationBehavior
|
|
||||||
|
|
||||||
Builder.load_string(
|
Builder.load_string(
|
||||||
"""
|
"""
|
||||||
#:import RelativeLayout kivy.uix.relativelayout.RelativeLayout
|
#:import RelativeLayout kivy.uix.relativelayout.RelativeLayout
|
||||||
@ -38,7 +37,7 @@ Builder.load_string(
|
|||||||
angle: self.angle
|
angle: self.angle
|
||||||
origin: self._background_origin
|
origin: self._background_origin
|
||||||
Color:
|
Color:
|
||||||
rgba: self.md_bg_color
|
rgba: self._md_bg_color
|
||||||
RoundedRectangle:
|
RoundedRectangle:
|
||||||
group: "Background_instruction"
|
group: "Background_instruction"
|
||||||
size: self.size
|
size: self.size
|
||||||
@ -67,7 +66,7 @@ Builder.load_string(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class BackgroundColorBehavior(CommonElevationBehavior):
|
class BackgroundColorBehavior:
|
||||||
background = StringProperty()
|
background = StringProperty()
|
||||||
"""
|
"""
|
||||||
Background image path.
|
Background image path.
|
||||||
@ -153,15 +152,26 @@ class BackgroundColorBehavior(CommonElevationBehavior):
|
|||||||
|
|
||||||
_background_x = NumericProperty(0)
|
_background_x = NumericProperty(0)
|
||||||
_background_y = NumericProperty(0)
|
_background_y = NumericProperty(0)
|
||||||
_background_origin = ReferenceListProperty(
|
_background_origin = ReferenceListProperty(_background_x, _background_y)
|
||||||
_background_x,
|
_md_bg_color = ColorProperty([0, 0, 0, 0])
|
||||||
_background_y,
|
|
||||||
)
|
|
||||||
|
|
||||||
def __init__(self, **kwarg):
|
def __init__(self, **kwarg):
|
||||||
super().__init__(**kwarg)
|
super().__init__(**kwarg)
|
||||||
self.bind(pos=self.update_background_origin)
|
self.bind(pos=self.update_background_origin)
|
||||||
|
|
||||||
|
def on_md_bg_color(self, instance_md_widget, color: Union[list, str]):
|
||||||
|
if (
|
||||||
|
hasattr(self, "theme_cls")
|
||||||
|
and self.theme_cls.theme_style_switch_animation
|
||||||
|
):
|
||||||
|
Animation(
|
||||||
|
_md_bg_color=color,
|
||||||
|
d=self.theme_cls.theme_style_switch_animation_duration,
|
||||||
|
t="linear",
|
||||||
|
).start(self)
|
||||||
|
else:
|
||||||
|
self._md_bg_color = color
|
||||||
|
|
||||||
def update_background_origin(
|
def update_background_origin(
|
||||||
self, instance_md_widget, pos: List[float]
|
self, instance_md_widget, pos: List[float]
|
||||||
) -> None:
|
) -> None:
|
||||||
@ -206,12 +216,14 @@ class SpecificBackgroundColorBehavior(BackgroundColorBehavior):
|
|||||||
super().__init__(**kwargs)
|
super().__init__(**kwargs)
|
||||||
if hasattr(self, "theme_cls"):
|
if hasattr(self, "theme_cls"):
|
||||||
self.theme_cls.bind(
|
self.theme_cls.bind(
|
||||||
primary_palette=self._update_specific_text_color
|
primary_palette=self._update_specific_text_color,
|
||||||
|
accent_palette=self._update_specific_text_color,
|
||||||
|
theme_style=self._update_specific_text_color,
|
||||||
|
)
|
||||||
|
self.bind(
|
||||||
|
background_hue=self._update_specific_text_color,
|
||||||
|
background_palette=self._update_specific_text_color,
|
||||||
)
|
)
|
||||||
self.theme_cls.bind(accent_palette=self._update_specific_text_color)
|
|
||||||
self.theme_cls.bind(theme_style=self._update_specific_text_color)
|
|
||||||
self.bind(background_hue=self._update_specific_text_color)
|
|
||||||
self.bind(background_palette=self._update_specific_text_color)
|
|
||||||
self._update_specific_text_color(None, None)
|
self._update_specific_text_color(None, None)
|
||||||
|
|
||||||
def _update_specific_text_color(
|
def _update_specific_text_color(
|
||||||
@ -234,5 +246,17 @@ class SpecificBackgroundColorBehavior(BackgroundColorBehavior):
|
|||||||
secondary_color[3] = 0.54
|
secondary_color[3] = 0.54
|
||||||
else:
|
else:
|
||||||
secondary_color[3] = 0.7
|
secondary_color[3] = 0.7
|
||||||
|
|
||||||
|
if (
|
||||||
|
hasattr(self, "theme_cls")
|
||||||
|
and self.theme_cls.theme_style_switch_animation
|
||||||
|
):
|
||||||
|
Animation(
|
||||||
|
specific_text_color=color,
|
||||||
|
specific_secondary_text_color=secondary_color,
|
||||||
|
d=self.theme_cls.theme_style_switch_animation_duration,
|
||||||
|
t="linear",
|
||||||
|
).start(self)
|
||||||
|
else:
|
||||||
self.specific_text_color = color
|
self.specific_text_color = color
|
||||||
self.specific_secondary_text_color = secondary_color
|
self.specific_secondary_text_color = secondary_color
|
||||||
|
@ -111,7 +111,7 @@ from kivy.properties import (
|
|||||||
from kivy.uix.behaviors import ToggleButtonBehavior
|
from kivy.uix.behaviors import ToggleButtonBehavior
|
||||||
|
|
||||||
|
|
||||||
class CommonRipple(object):
|
class CommonRipple:
|
||||||
"""Base class for ripple effect."""
|
"""Base class for ripple effect."""
|
||||||
|
|
||||||
ripple_rad_default = NumericProperty(1)
|
ripple_rad_default = NumericProperty(1)
|
||||||
|
133
sbapp/kivymd/uix/behaviors/rotate_behavior.py
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
"""
|
||||||
|
Behaviors/Rotate
|
||||||
|
================
|
||||||
|
|
||||||
|
.. versionadded:: 1.1.0
|
||||||
|
|
||||||
|
Base class for controlling the rotate of the widget.
|
||||||
|
|
||||||
|
.. note:: See `kivy.graphics.Rotate
|
||||||
|
<https://kivy.org/doc/stable/api-kivy.graphics.html#kivy.graphics.Rotate>`_
|
||||||
|
for more information.
|
||||||
|
|
||||||
|
Kivy
|
||||||
|
----
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from kivy.animation import Animation
|
||||||
|
from kivy.lang import Builder
|
||||||
|
from kivy.app import App
|
||||||
|
from kivy.properties import NumericProperty
|
||||||
|
from kivy.uix.button import Button
|
||||||
|
|
||||||
|
KV = '''
|
||||||
|
Screen:
|
||||||
|
|
||||||
|
RotateButton:
|
||||||
|
size_hint: .5, .5
|
||||||
|
pos_hint: {"center_x": .5, "center_y": .5}
|
||||||
|
on_release: app.change_rotate(self)
|
||||||
|
|
||||||
|
canvas.before:
|
||||||
|
PushMatrix
|
||||||
|
Rotate:
|
||||||
|
angle: self.rotate_value_angle
|
||||||
|
axis: 0, 0, 1
|
||||||
|
origin: self.center
|
||||||
|
canvas.after:
|
||||||
|
PopMatrix
|
||||||
|
'''
|
||||||
|
|
||||||
|
|
||||||
|
class RotateButton(Button):
|
||||||
|
rotate_value_angle = NumericProperty(0)
|
||||||
|
|
||||||
|
|
||||||
|
class Test(App):
|
||||||
|
def build(self):
|
||||||
|
return Builder.load_string(KV)
|
||||||
|
|
||||||
|
def change_rotate(self, instance_button: Button) -> None:
|
||||||
|
Animation(rotate_value_angle=45, d=0.3).start(instance_button)
|
||||||
|
|
||||||
|
|
||||||
|
Test().run()
|
||||||
|
|
||||||
|
KivyMD
|
||||||
|
------
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from kivy.animation import Animation
|
||||||
|
from kivy.lang import Builder
|
||||||
|
from kivy.uix.behaviors import ButtonBehavior
|
||||||
|
|
||||||
|
from kivymd.app import MDApp
|
||||||
|
from kivymd.uix.behaviors import RotateBehavior
|
||||||
|
from kivymd.uix.boxlayout import MDBoxLayout
|
||||||
|
|
||||||
|
KV = '''
|
||||||
|
MDScreen:
|
||||||
|
|
||||||
|
RotateBox:
|
||||||
|
size_hint: .5, .5
|
||||||
|
pos_hint: {"center_x": .5, "center_y": .5}
|
||||||
|
on_release: app.change_rotate(self)
|
||||||
|
md_bg_color: "red"
|
||||||
|
'''
|
||||||
|
|
||||||
|
|
||||||
|
class RotateBox(ButtonBehavior, RotateBehavior, MDBoxLayout):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class Test(MDApp):
|
||||||
|
def build(self):
|
||||||
|
return Builder.load_string(KV)
|
||||||
|
|
||||||
|
def change_rotate(self, instance_button: RotateBox) -> None:
|
||||||
|
Animation(rotate_value_angle=45, d=0.3).start(instance_button)
|
||||||
|
|
||||||
|
|
||||||
|
Test().run()
|
||||||
|
"""
|
||||||
|
|
||||||
|
__all__ = ("RotateBehavior",)
|
||||||
|
|
||||||
|
from kivy.lang import Builder
|
||||||
|
from kivy.properties import ListProperty, NumericProperty
|
||||||
|
|
||||||
|
Builder.load_string(
|
||||||
|
"""
|
||||||
|
<RotateBehavior>
|
||||||
|
canvas.before:
|
||||||
|
PushMatrix
|
||||||
|
Rotate:
|
||||||
|
angle: self.rotate_value_angle
|
||||||
|
axis: tuple(self.rotate_value_axis)
|
||||||
|
origin: self.center
|
||||||
|
canvas.after:
|
||||||
|
PopMatrix
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class RotateBehavior:
|
||||||
|
"""Base class for controlling the rotate of the widget."""
|
||||||
|
|
||||||
|
rotate_value_angle = NumericProperty(0)
|
||||||
|
"""
|
||||||
|
Property for getting/setting the angle of the rotation.
|
||||||
|
|
||||||
|
:attr:`rotate_value_angle` is an :class:`~kivy.properties.NumericProperty`
|
||||||
|
and defaults to `0`.
|
||||||
|
"""
|
||||||
|
|
||||||
|
rotate_value_axis = ListProperty((0, 0, 1))
|
||||||
|
"""
|
||||||
|
Property for getting/setting the axis of the rotation.
|
||||||
|
|
||||||
|
:attr:`rotate_value_axis` is an :class:`~kivy.properties.ListProperty`
|
||||||
|
and defaults to `(0, 0, 1)`.
|
||||||
|
"""
|
156
sbapp/kivymd/uix/behaviors/scale_behavior.py
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
"""
|
||||||
|
Behaviors/Scale
|
||||||
|
===============
|
||||||
|
|
||||||
|
.. versionadded:: 1.1.0
|
||||||
|
|
||||||
|
Base class for controlling the scale of the widget.
|
||||||
|
|
||||||
|
.. note:: See `kivy.graphics.Rotate
|
||||||
|
<https://kivy.org/doc/stable/api-kivy.graphics.html#kivy.graphics.Scale>`_
|
||||||
|
for more information.
|
||||||
|
|
||||||
|
Kivy
|
||||||
|
----
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from kivy.animation import Animation
|
||||||
|
from kivy.lang import Builder
|
||||||
|
from kivy.properties import NumericProperty
|
||||||
|
from kivy.uix.button import Button
|
||||||
|
from kivy.app import App
|
||||||
|
|
||||||
|
|
||||||
|
KV = '''
|
||||||
|
Screen:
|
||||||
|
|
||||||
|
ScaleButton:
|
||||||
|
size_hint: .5, .5
|
||||||
|
pos_hint: {"center_x": .5, "center_y": .5}
|
||||||
|
on_release: app.change_scale(self)
|
||||||
|
|
||||||
|
canvas.before:
|
||||||
|
PushMatrix
|
||||||
|
Scale:
|
||||||
|
x: self.scale_value_x
|
||||||
|
y: self.scale_value_y
|
||||||
|
z: self.scale_value_x
|
||||||
|
origin: self.center
|
||||||
|
canvas.after:
|
||||||
|
PopMatrix
|
||||||
|
'''
|
||||||
|
|
||||||
|
|
||||||
|
class ScaleButton(Button):
|
||||||
|
scale_value_x = NumericProperty(1)
|
||||||
|
scale_value_y = NumericProperty(1)
|
||||||
|
scale_value_z = NumericProperty(1)
|
||||||
|
|
||||||
|
|
||||||
|
class Test(App):
|
||||||
|
def build(self):
|
||||||
|
return Builder.load_string(KV)
|
||||||
|
|
||||||
|
def change_scale(self, instance_button: Button) -> None:
|
||||||
|
Animation(
|
||||||
|
scale_value_x=0.5,
|
||||||
|
scale_value_y=0.5,
|
||||||
|
scale_value_z=0.5,
|
||||||
|
d=0.3,
|
||||||
|
).start(instance_button)
|
||||||
|
|
||||||
|
|
||||||
|
Test().run()
|
||||||
|
|
||||||
|
KivyMD
|
||||||
|
------
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from kivy.animation import Animation
|
||||||
|
from kivy.lang import Builder
|
||||||
|
from kivy.uix.behaviors import ButtonBehavior
|
||||||
|
|
||||||
|
from kivymd.app import MDApp
|
||||||
|
from kivymd.uix.behaviors import ScaleBehavior
|
||||||
|
from kivymd.uix.boxlayout import MDBoxLayout
|
||||||
|
|
||||||
|
KV = '''
|
||||||
|
MDScreen:
|
||||||
|
|
||||||
|
ScaleBox:
|
||||||
|
size_hint: .5, .5
|
||||||
|
pos_hint: {"center_x": .5, "center_y": .5}
|
||||||
|
on_release: app.change_scale(self)
|
||||||
|
md_bg_color: "red"
|
||||||
|
'''
|
||||||
|
|
||||||
|
|
||||||
|
class ScaleBox(ButtonBehavior, ScaleBehavior, MDBoxLayout):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class Test(MDApp):
|
||||||
|
def build(self):
|
||||||
|
return Builder.load_string(KV)
|
||||||
|
|
||||||
|
def change_scale(self, instance_button: ScaleBox) -> None:
|
||||||
|
Animation(
|
||||||
|
scale_value_x=0.5,
|
||||||
|
scale_value_y=0.5,
|
||||||
|
scale_value_z=0.5,
|
||||||
|
d=0.3,
|
||||||
|
).start(instance_button)
|
||||||
|
|
||||||
|
|
||||||
|
Test().run()
|
||||||
|
"""
|
||||||
|
|
||||||
|
__all__ = ("ScaleBehavior",)
|
||||||
|
|
||||||
|
from kivy.lang import Builder
|
||||||
|
from kivy.properties import NumericProperty
|
||||||
|
|
||||||
|
Builder.load_string(
|
||||||
|
"""
|
||||||
|
<ScaleBehavior>
|
||||||
|
canvas.before:
|
||||||
|
PushMatrix
|
||||||
|
Scale:
|
||||||
|
x: self.scale_value_x
|
||||||
|
y: self.scale_value_y
|
||||||
|
z: self.scale_value_x
|
||||||
|
origin: self.center
|
||||||
|
canvas.after:
|
||||||
|
PopMatrix
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class ScaleBehavior:
|
||||||
|
"""Base class for controlling the scale of the widget."""
|
||||||
|
|
||||||
|
scale_value_x = NumericProperty(1)
|
||||||
|
"""
|
||||||
|
X-axis value.
|
||||||
|
|
||||||
|
:attr:`scale_value_x` is an :class:`~kivy.properties.NumericProperty`
|
||||||
|
and defaults to `1`.
|
||||||
|
"""
|
||||||
|
|
||||||
|
scale_value_y = NumericProperty(1)
|
||||||
|
"""
|
||||||
|
Y-axis value.
|
||||||
|
|
||||||
|
:attr:`scale_value_y` is an :class:`~kivy.properties.NumericProperty`
|
||||||
|
and defaults to `1`.
|
||||||
|
"""
|
||||||
|
|
||||||
|
scale_value_z = NumericProperty(1)
|
||||||
|
"""
|
||||||
|
Z-axis value.
|
||||||
|
|
||||||
|
:attr:`scale_value_z` is an :class:`~kivy.properties.NumericProperty`
|
||||||
|
and defaults to `1`.
|
||||||
|
"""
|
134
sbapp/kivymd/uix/behaviors/stencil_behavior.py
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
"""
|
||||||
|
Behaviors/Stencil
|
||||||
|
=================
|
||||||
|
|
||||||
|
.. versionadded:: 1.1.0
|
||||||
|
|
||||||
|
Base class for controlling the stencil instructions of the widget.
|
||||||
|
|
||||||
|
.. note:: See `Stencil instructions
|
||||||
|
<https://kivy.org/doc/stable/api-kivy.graphics.stencil_instructions.html>`_
|
||||||
|
for more information.
|
||||||
|
|
||||||
|
Kivy
|
||||||
|
----
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from kivy.lang import Builder
|
||||||
|
from kivy.app import App
|
||||||
|
|
||||||
|
KV = '''
|
||||||
|
Carousel:
|
||||||
|
|
||||||
|
Button:
|
||||||
|
size_hint: .9, .8
|
||||||
|
pos_hint: {"center_x": .5, "center_y": .5}
|
||||||
|
|
||||||
|
canvas.before:
|
||||||
|
StencilPush
|
||||||
|
RoundedRectangle:
|
||||||
|
pos: root.pos
|
||||||
|
size: root.size
|
||||||
|
StencilUse
|
||||||
|
canvas.after:
|
||||||
|
StencilUnUse
|
||||||
|
RoundedRectangle:
|
||||||
|
pos: root.pos
|
||||||
|
size: root.size
|
||||||
|
StencilPop
|
||||||
|
'''
|
||||||
|
|
||||||
|
|
||||||
|
class Test(App):
|
||||||
|
def build(self):
|
||||||
|
return Builder.load_string(KV)
|
||||||
|
|
||||||
|
|
||||||
|
Test().run()
|
||||||
|
|
||||||
|
KivyMD
|
||||||
|
------
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from kivy.lang import Builder
|
||||||
|
|
||||||
|
from kivymd.app import MDApp
|
||||||
|
from kivymd.uix.behaviors import StencilBehavior
|
||||||
|
from kivymd.uix.fitimage import FitImage
|
||||||
|
|
||||||
|
KV = '''
|
||||||
|
#:import os os
|
||||||
|
#:import images_path kivymd.images_path
|
||||||
|
|
||||||
|
|
||||||
|
MDCarousel:
|
||||||
|
|
||||||
|
StencilImage:
|
||||||
|
size_hint: .9, .8
|
||||||
|
pos_hint: {"center_x": .5, "center_y": .5}
|
||||||
|
source: os.path.join(images_path, "logo", "kivymd-icon-512.png")
|
||||||
|
'''
|
||||||
|
|
||||||
|
|
||||||
|
class StencilImage(FitImage, StencilBehavior):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class Test(MDApp):
|
||||||
|
def build(self):
|
||||||
|
return Builder.load_string(KV)
|
||||||
|
|
||||||
|
|
||||||
|
Test().run()
|
||||||
|
"""
|
||||||
|
|
||||||
|
__all__ = ("StencilBehavior",)
|
||||||
|
|
||||||
|
from kivy.lang import Builder
|
||||||
|
from kivy.properties import VariableListProperty
|
||||||
|
|
||||||
|
Builder.load_string(
|
||||||
|
"""
|
||||||
|
<StencilBehavior>
|
||||||
|
canvas.before:
|
||||||
|
StencilPush
|
||||||
|
RoundedRectangle:
|
||||||
|
pos: root.pos
|
||||||
|
size: root.size
|
||||||
|
# FIXME: Sometimes the radius has the value [], which get a
|
||||||
|
# `GraphicException: Invalid radius value, must be list of tuples/numerics` error
|
||||||
|
radius: root.radius if root.radius else [0, 0, 0, 0]
|
||||||
|
StencilUse
|
||||||
|
canvas.after:
|
||||||
|
StencilUnUse
|
||||||
|
RoundedRectangle:
|
||||||
|
pos: root.pos
|
||||||
|
size: root.size
|
||||||
|
# FIXME: Sometimes the radius has the value [], which get a
|
||||||
|
# `GraphicException: Invalid radius value, must be list of tuples/numerics` error
|
||||||
|
radius: root.radius if root.radius else [0, 0, 0, 0]
|
||||||
|
StencilPop
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class StencilBehavior:
|
||||||
|
"""Base class for controlling the stencil instructions of the widget."""
|
||||||
|
|
||||||
|
radius = VariableListProperty([0], length=4)
|
||||||
|
"""
|
||||||
|
Canvas radius.
|
||||||
|
|
||||||
|
.. versionadded:: 1.0.0
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
# Top left corner slice.
|
||||||
|
MDWidget:
|
||||||
|
radius: [25, 0, 0, 0]
|
||||||
|
|
||||||
|
:attr:`radius` is an :class:`~kivy.properties.VariableListProperty`
|
||||||
|
and defaults to `[0, 0, 0, 0]`.
|
||||||
|
"""
|
@ -14,19 +14,24 @@ example:
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
.. tabs::
|
||||||
|
|
||||||
|
.. tab:: Declarative KV style
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
from kivy.lang import Builder
|
from kivy.lang import Builder
|
||||||
|
|
||||||
from kivymd.app import MDApp
|
from kivymd.app import MDApp
|
||||||
from kivymd.uix.behaviors.toggle_behavior import MDToggleButton
|
from kivymd.uix.behaviors.toggle_behavior import MDToggleButton
|
||||||
from kivymd.uix.button import MDRectangleFlatButton
|
from kivymd.uix.button import MDFlatButton
|
||||||
|
|
||||||
KV = '''
|
KV = '''
|
||||||
Screen:
|
MDScreen:
|
||||||
|
|
||||||
MDBoxLayout:
|
MDBoxLayout:
|
||||||
adaptive_size: True
|
adaptive_size: True
|
||||||
|
spacing: "12dp"
|
||||||
pos_hint: {"center_x": .5, "center_y": .5}
|
pos_hint: {"center_x": .5, "center_y": .5}
|
||||||
|
|
||||||
MyToggleButton:
|
MyToggleButton:
|
||||||
@ -43,30 +48,68 @@ example:
|
|||||||
'''
|
'''
|
||||||
|
|
||||||
|
|
||||||
class MyToggleButton(MDRectangleFlatButton, MDToggleButton):
|
class MyToggleButton(MDFlatButton, MDToggleButton):
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super().__init__(**kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
self.background_down = self.theme_cls.primary_light
|
self.background_down = self.theme_cls.primary_color
|
||||||
|
|
||||||
|
|
||||||
class Test(MDApp):
|
class Test(MDApp):
|
||||||
def build(self):
|
def build(self):
|
||||||
|
self.theme_cls.theme_style = "Dark"
|
||||||
|
self.theme_cls.primary_palette = "Orange"
|
||||||
return Builder.load_string(KV)
|
return Builder.load_string(KV)
|
||||||
|
|
||||||
|
|
||||||
Test().run()
|
Test().run()
|
||||||
|
|
||||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/toggle-button-1.gif
|
.. tab:: Declarative python style
|
||||||
:align: center
|
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
class MyToggleButton(MDFillRoundFlatButton, MDToggleButton):
|
from kivymd.app import MDApp
|
||||||
def __init__(self, **kwargs):
|
from kivymd.uix.behaviors.toggle_behavior import MDToggleButton
|
||||||
self.background_down = MDApp.get_running_app().theme_cls.primary_dark
|
from kivymd.uix.boxlayout import MDBoxLayout
|
||||||
super().__init__(**kwargs)
|
from kivymd.uix.button import MDFlatButton
|
||||||
|
from kivymd.uix.screen import MDScreen
|
||||||
|
|
||||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/toggle-button-2.gif
|
|
||||||
|
class MyToggleButton(MDFlatButton, MDToggleButton):
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
self.background_down = self.theme_cls.primary_color
|
||||||
|
|
||||||
|
|
||||||
|
class Test(MDApp):
|
||||||
|
def build(self):
|
||||||
|
self.theme_cls.theme_style = "Dark"
|
||||||
|
self.theme_cls.primary_palette = "Orange"
|
||||||
|
return (
|
||||||
|
MDScreen(
|
||||||
|
MDBoxLayout(
|
||||||
|
MyToggleButton(
|
||||||
|
text="Show ads",
|
||||||
|
group="x",
|
||||||
|
),
|
||||||
|
MyToggleButton(
|
||||||
|
text="Do not show ads",
|
||||||
|
group="x",
|
||||||
|
),
|
||||||
|
MyToggleButton(
|
||||||
|
text="Does not matter",
|
||||||
|
group="x",
|
||||||
|
),
|
||||||
|
adaptive_size=True,
|
||||||
|
spacing="12dp",
|
||||||
|
pos_hint={"center_x": .5, "center_y": .5},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
Test().run()
|
||||||
|
|
||||||
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/toggle-button-1.gif
|
||||||
:align: center
|
:align: center
|
||||||
|
|
||||||
You can inherit the ``MyToggleButton`` class only from the following classes
|
You can inherit the ``MyToggleButton`` class only from the following classes
|
||||||
@ -88,6 +131,7 @@ from kivy.properties import BooleanProperty, ColorProperty
|
|||||||
from kivy.uix.behaviors import ToggleButtonBehavior
|
from kivy.uix.behaviors import ToggleButtonBehavior
|
||||||
|
|
||||||
from kivymd.uix.button import (
|
from kivymd.uix.button import (
|
||||||
|
ButtonContentsIconText,
|
||||||
MDFillRoundFlatButton,
|
MDFillRoundFlatButton,
|
||||||
MDFillRoundFlatIconButton,
|
MDFillRoundFlatIconButton,
|
||||||
MDFlatButton,
|
MDFlatButton,
|
||||||
@ -149,7 +193,8 @@ class MDToggleButton(ToggleButtonBehavior):
|
|||||||
# Do the object inherited from the "supported" buttons?
|
# Do the object inherited from the "supported" buttons?
|
||||||
if not issubclass(self.__class__, classinfo):
|
if not issubclass(self.__class__, classinfo):
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
f"Class {self.__class__} must be inherited from one of the classes in the list {classinfo}"
|
f"Class {self.__class__} must be inherited from one of the "
|
||||||
|
f"classes in the list {classinfo}"
|
||||||
)
|
)
|
||||||
if (
|
if (
|
||||||
not self.background_normal
|
not self.background_normal
|
||||||
@ -165,10 +210,12 @@ class MDToggleButton(ToggleButtonBehavior):
|
|||||||
):
|
):
|
||||||
self.__is_filled = True
|
self.__is_filled = True
|
||||||
self.background_normal = self.theme_cls.primary_color
|
self.background_normal = self.theme_cls.primary_color
|
||||||
# If not the background_normal must be the same as the inherited one:
|
# If not background_normal must be the same as the inherited one.
|
||||||
else:
|
else:
|
||||||
self.background_normal = self.md_bg_color[:]
|
self.background_normal = (
|
||||||
# If no background_down is setted:
|
self.md_bg_color[:] if self.md_bg_color else (0, 0, 0, 0)
|
||||||
|
)
|
||||||
|
# If no background_down is setter.
|
||||||
if (
|
if (
|
||||||
not self.background_down
|
not self.background_down
|
||||||
): # This means that if the value == [] or None will return True.
|
): # This means that if the value == [] or None will return True.
|
||||||
@ -200,3 +247,6 @@ class MDToggleButton(ToggleButtonBehavior):
|
|||||||
): # If the background is transparent, the font color must be the
|
): # If the background is transparent, the font color must be the
|
||||||
# primary color.
|
# primary color.
|
||||||
self.text_color = self.font_color_normal
|
self.text_color = self.font_color_normal
|
||||||
|
|
||||||
|
if issubclass(self.__class__, ButtonContentsIconText):
|
||||||
|
self.icon_color = self.text_color
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
#:import sm kivy.uix.screenmanager
|
|
||||||
#:import STANDARD_INCREMENT kivymd.material_resources.STANDARD_INCREMENT
|
#:import STANDARD_INCREMENT kivymd.material_resources.STANDARD_INCREMENT
|
||||||
|
|
||||||
|
|
||||||
@ -7,9 +6,9 @@
|
|||||||
height:
|
height:
|
||||||
STANDARD_INCREMENT if app.theme_cls.material_style == "M2" else "80dp"
|
STANDARD_INCREMENT if app.theme_cls.material_style == "M2" else "80dp"
|
||||||
|
|
||||||
MDScreenManager:
|
ScreenManager:
|
||||||
id: tab_manager
|
id: tab_manager
|
||||||
transition: sm.FadeTransition(duration=.2)
|
transition: root.transition(duration=root.transition_duration)
|
||||||
on_current:
|
on_current:
|
||||||
root.dispatch( \
|
root.dispatch( \
|
||||||
"on_switch_tabs", \
|
"on_switch_tabs", \
|
||||||
@ -96,7 +95,7 @@
|
|||||||
radius: [16,]
|
radius: [16,]
|
||||||
size: root._selected_region_width, dp(32)
|
size: root._selected_region_width, dp(32)
|
||||||
pos:
|
pos:
|
||||||
self.center_x - self.width - dp(8), \
|
self.center_x - root._selected_region_width / 2, \
|
||||||
self.center_y - (dp(16))
|
self.center_y - (dp(16))
|
||||||
|
|
||||||
MDLabel:
|
MDLabel:
|
||||||
|
@ -62,6 +62,10 @@ For ease of understanding, this code works like this:
|
|||||||
Example
|
Example
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
.. tabs::
|
||||||
|
|
||||||
|
.. tab:: Declarative KV style
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
from kivy.lang import Builder
|
from kivy.lang import Builder
|
||||||
@ -73,14 +77,15 @@ Example
|
|||||||
|
|
||||||
def build(self):
|
def build(self):
|
||||||
self.theme_cls.material_style = "M3"
|
self.theme_cls.material_style = "M3"
|
||||||
|
self.theme_cls.theme_style = "Dark"
|
||||||
return Builder.load_string(
|
return Builder.load_string(
|
||||||
'''
|
'''
|
||||||
MDScreen:
|
MDScreen:
|
||||||
|
|
||||||
MDBottomNavigation:
|
MDBottomNavigation:
|
||||||
panel_color: "#eeeaea"
|
#panel_color: "#eeeaea"
|
||||||
selected_color_background: "#97ecf8"
|
selected_color_background: "orange"
|
||||||
text_color_active: 0, 0, 0, 1
|
text_color_active: "lightgrey"
|
||||||
|
|
||||||
MDBottomNavigationItem:
|
MDBottomNavigationItem:
|
||||||
name: 'screen 1'
|
name: 'screen 1'
|
||||||
@ -94,12 +99,12 @@ Example
|
|||||||
|
|
||||||
MDBottomNavigationItem:
|
MDBottomNavigationItem:
|
||||||
name: 'screen 2'
|
name: 'screen 2'
|
||||||
text: 'Discord'
|
text: 'Twitter'
|
||||||
icon: 'discord'
|
icon: 'twitter'
|
||||||
badge_icon: "numeric-5"
|
badge_icon: "numeric-5"
|
||||||
|
|
||||||
MDLabel:
|
MDLabel:
|
||||||
text: 'Discord'
|
text: 'Twitter'
|
||||||
halign: 'center'
|
halign: 'center'
|
||||||
|
|
||||||
MDBottomNavigationItem:
|
MDBottomNavigationItem:
|
||||||
@ -116,6 +121,62 @@ Example
|
|||||||
|
|
||||||
Test().run()
|
Test().run()
|
||||||
|
|
||||||
|
.. tab:: Declarative python style
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from kivymd.app import MDApp
|
||||||
|
from kivymd.uix.bottomnavigation import MDBottomNavigation, MDBottomNavigationItem
|
||||||
|
from kivymd.uix.label import MDLabel
|
||||||
|
from kivymd.uix.screen import MDScreen
|
||||||
|
|
||||||
|
|
||||||
|
class Test(MDApp):
|
||||||
|
def build(self):
|
||||||
|
self.theme_cls.material_style = "M3"
|
||||||
|
self.theme_cls.theme_style = "Dark"
|
||||||
|
return (
|
||||||
|
MDScreen(
|
||||||
|
MDBottomNavigation(
|
||||||
|
MDBottomNavigationItem(
|
||||||
|
MDLabel(
|
||||||
|
text='Mail',
|
||||||
|
halign='center',
|
||||||
|
),
|
||||||
|
name='screen 1',
|
||||||
|
text='Mail',
|
||||||
|
icon='gmail',
|
||||||
|
badge_icon="numeric-10",
|
||||||
|
),
|
||||||
|
MDBottomNavigationItem(
|
||||||
|
MDLabel(
|
||||||
|
text='Twitter',
|
||||||
|
halign='center',
|
||||||
|
),
|
||||||
|
name='screen 1',
|
||||||
|
text='Twitter',
|
||||||
|
icon='twitter',
|
||||||
|
badge_icon="numeric-10",
|
||||||
|
),
|
||||||
|
MDBottomNavigationItem(
|
||||||
|
MDLabel(
|
||||||
|
text='LinkedIN',
|
||||||
|
halign='center',
|
||||||
|
),
|
||||||
|
name='screen 1',
|
||||||
|
text='LinkedIN',
|
||||||
|
icon='linkedin',
|
||||||
|
badge_icon="numeric-10",
|
||||||
|
),
|
||||||
|
selected_color_background="orange",
|
||||||
|
text_color_active="lightgrey",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
Test().run()
|
||||||
|
|
||||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/bottom-navigation.gif
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/bottom-navigation.gif
|
||||||
:align: center
|
:align: center
|
||||||
|
|
||||||
@ -192,16 +253,13 @@ from kivy.properties import (
|
|||||||
)
|
)
|
||||||
from kivy.uix.behaviors import ButtonBehavior
|
from kivy.uix.behaviors import ButtonBehavior
|
||||||
from kivy.uix.boxlayout import BoxLayout
|
from kivy.uix.boxlayout import BoxLayout
|
||||||
from kivy.uix.screenmanager import ScreenManagerException
|
from kivy.uix.screenmanager import FadeTransition, ScreenManagerException
|
||||||
|
|
||||||
from kivymd import uix_path
|
from kivymd import uix_path
|
||||||
from kivymd.material_resources import STANDARD_INCREMENT
|
from kivymd.material_resources import STANDARD_INCREMENT
|
||||||
from kivymd.theming import ThemableBehavior, ThemeManager
|
from kivymd.theming import ThemableBehavior, ThemeManager
|
||||||
from kivymd.uix.anchorlayout import MDAnchorLayout
|
from kivymd.uix.anchorlayout import MDAnchorLayout
|
||||||
from kivymd.uix.behaviors import (
|
from kivymd.uix.behaviors import CommonElevationBehavior, DeclarativeBehavior
|
||||||
DeclarativeBehavior,
|
|
||||||
FakeRectangularElevationBehavior,
|
|
||||||
)
|
|
||||||
from kivymd.uix.behaviors.backgroundcolor_behavior import (
|
from kivymd.uix.behaviors.backgroundcolor_behavior import (
|
||||||
SpecificBackgroundColorBehavior,
|
SpecificBackgroundColorBehavior,
|
||||||
)
|
)
|
||||||
@ -413,16 +471,9 @@ class MDBottomNavigationItem(MDTab):
|
|||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
def on_tab_press(self, *args) -> None:
|
def animate_header(
|
||||||
"""Called when clicking on a panel item."""
|
self, bottom_navigation_object, bottom_navigation_header_object
|
||||||
|
) -> None:
|
||||||
bottom_navigation_object = self.parent_widget
|
|
||||||
bottom_navigation_header_object = (
|
|
||||||
bottom_navigation_object.previous_tab.header
|
|
||||||
)
|
|
||||||
bottom_navigation_object.ids.tab_manager.current = self.name
|
|
||||||
|
|
||||||
if bottom_navigation_object.previous_tab is not self:
|
|
||||||
if bottom_navigation_object.use_text:
|
if bottom_navigation_object.use_text:
|
||||||
Animation(_label_font_size=sp(12), d=0.1).start(
|
Animation(_label_font_size=sp(12), d=0.1).start(
|
||||||
bottom_navigation_object.previous_tab.header
|
bottom_navigation_object.previous_tab.header
|
||||||
@ -441,7 +492,21 @@ class MDBottomNavigationItem(MDTab):
|
|||||||
).start(bottom_navigation_object.previous_tab.header)
|
).start(bottom_navigation_object.previous_tab.header)
|
||||||
bottom_navigation_object.previous_tab.header.active = False
|
bottom_navigation_object.previous_tab.header.active = False
|
||||||
self.header.active = True
|
self.header.active = True
|
||||||
bottom_navigation_object.previous_tab = self
|
|
||||||
|
def on_tab_press(self, *args) -> None:
|
||||||
|
"""Called when clicking on a panel item."""
|
||||||
|
|
||||||
|
bottom_navigation_object = self.parent_widget
|
||||||
|
bottom_navigation_header_object = (
|
||||||
|
bottom_navigation_object.previous_tab.header
|
||||||
|
)
|
||||||
|
|
||||||
|
if bottom_navigation_object.previous_tab is not self:
|
||||||
|
self.animate_header(
|
||||||
|
bottom_navigation_object, bottom_navigation_header_object
|
||||||
|
)
|
||||||
|
|
||||||
|
super().on_tab_press(*args)
|
||||||
|
|
||||||
def on_disabled(
|
def on_disabled(
|
||||||
self, instance_bottom_navigation_item, disabled_value: bool
|
self, instance_bottom_navigation_item, disabled_value: bool
|
||||||
@ -498,6 +563,26 @@ class MDBottomNavigation(DeclarativeBehavior, TabbedPanelBase):
|
|||||||
.. versionadded:: 1.0.0
|
.. versionadded:: 1.0.0
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
transition = ObjectProperty(FadeTransition)
|
||||||
|
"""
|
||||||
|
Transition animation of bottom navigation screen manager.
|
||||||
|
|
||||||
|
.. versionadded:: 1.1.0
|
||||||
|
|
||||||
|
:attr:`transition` is an :class:`~kivy.properties.ObjectProperty`
|
||||||
|
and defaults to `FadeTransition`.
|
||||||
|
"""
|
||||||
|
|
||||||
|
transition_duration = NumericProperty(0.2)
|
||||||
|
"""
|
||||||
|
Duration animation of bottom navigation screen manager.
|
||||||
|
|
||||||
|
.. versionadded:: 1.1.0
|
||||||
|
|
||||||
|
:attr:`transition_duration` is an :class:`~kivy.properties.NumericProperty`
|
||||||
|
and defaults to `0.2`.
|
||||||
|
"""
|
||||||
|
|
||||||
text_color_normal = ColorProperty([1, 1, 1, 1])
|
text_color_normal = ColorProperty([1, 1, 1, 1])
|
||||||
"""
|
"""
|
||||||
Text color of the label when it is not selected.
|
Text color of the label when it is not selected.
|
||||||
@ -772,8 +857,6 @@ class MDBottomNavigation(DeclarativeBehavior, TabbedPanelBase):
|
|||||||
|
|
||||||
|
|
||||||
class MDBottomNavigationBar(
|
class MDBottomNavigationBar(
|
||||||
ThemableBehavior,
|
ThemableBehavior, CommonElevationBehavior, MDFloatLayout
|
||||||
FakeRectangularElevationBehavior,
|
|
||||||
MDFloatLayout,
|
|
||||||
):
|
):
|
||||||
pass
|
pass
|
||||||
|
@ -34,7 +34,7 @@ Usage :class:`~MDListBottomSheet`
|
|||||||
MDTopAppBar:
|
MDTopAppBar:
|
||||||
title: "Example BottomSheet"
|
title: "Example BottomSheet"
|
||||||
pos_hint: {"top": 1}
|
pos_hint: {"top": 1}
|
||||||
elevation: 10
|
elevation: 4
|
||||||
|
|
||||||
MDRaisedButton:
|
MDRaisedButton:
|
||||||
text: "Open list bottom sheet"
|
text: "Open list bottom sheet"
|
||||||
@ -94,7 +94,7 @@ which will be used as an icon to the left of the item:
|
|||||||
MDTopAppBar:
|
MDTopAppBar:
|
||||||
title: 'Example BottomSheet'
|
title: 'Example BottomSheet'
|
||||||
pos_hint: {"top": 1}
|
pos_hint: {"top": 1}
|
||||||
elevation: 10
|
elevation: 4
|
||||||
|
|
||||||
MDRaisedButton:
|
MDRaisedButton:
|
||||||
text: "Open grid bottom sheet"
|
text: "Open grid bottom sheet"
|
||||||
@ -180,7 +180,7 @@ which will be used as an icon to the left of the item:
|
|||||||
MDTopAppBar:
|
MDTopAppBar:
|
||||||
title: 'Example BottomSheet'
|
title: 'Example BottomSheet'
|
||||||
pos_hint: {"top": 1}
|
pos_hint: {"top": 1}
|
||||||
elevation: 10
|
elevation: 4
|
||||||
|
|
||||||
MDRaisedButton:
|
MDRaisedButton:
|
||||||
text: "Open custom bottom sheet"
|
text: "Open custom bottom sheet"
|
||||||
|
@ -93,6 +93,8 @@ from kivymd.uix.behaviors import DeclarativeBehavior
|
|||||||
|
|
||||||
class MDBoxLayout(DeclarativeBehavior, BoxLayout, MDAdaptiveWidget):
|
class MDBoxLayout(DeclarativeBehavior, BoxLayout, MDAdaptiveWidget):
|
||||||
"""
|
"""
|
||||||
Box layout class. For more information, see in the
|
Box layout class.
|
||||||
|
|
||||||
|
For more information, see in the
|
||||||
:class:`~kivy.uix.boxlayout.BoxLayout` class documentation.
|
:class:`~kivy.uix.boxlayout.BoxLayout` class documentation.
|
||||||
"""
|
"""
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
# NOQA F401
|
# NOQA F401
|
||||||
from .button import (
|
from .button import (
|
||||||
BaseButton,
|
BaseButton,
|
||||||
|
ButtonContentsIconText,
|
||||||
MDFillRoundFlatButton,
|
MDFillRoundFlatButton,
|
||||||
MDFillRoundFlatIconButton,
|
MDFillRoundFlatIconButton,
|
||||||
MDFlatButton,
|
MDFlatButton,
|
||||||
|
@ -3,9 +3,9 @@
|
|||||||
Clear
|
Clear
|
||||||
Color:
|
Color:
|
||||||
rgba:
|
rgba:
|
||||||
(self._md_bg_color or [0.0, 0.0, 0.0, 0.0]) \
|
self._md_bg_color \
|
||||||
if not self.disabled else \
|
if not self.disabled else \
|
||||||
(self._md_bg_color_disabled or [0.0, 0.0, 0.0, 0.0])
|
self._md_bg_color_disabled
|
||||||
RoundedRectangle:
|
RoundedRectangle:
|
||||||
size: self.size
|
size: self.size
|
||||||
pos: self.pos
|
pos: self.pos
|
||||||
@ -13,19 +13,17 @@
|
|||||||
radius: [root._radius, ]
|
radius: [root._radius, ]
|
||||||
Color:
|
Color:
|
||||||
rgba:
|
rgba:
|
||||||
root._line_color or [0.0, 0.0, 0.0, 0.0] \
|
root._line_color \
|
||||||
if not root.disabled else \
|
if not root.disabled else \
|
||||||
( \
|
(root._line_color_disabled or self._disabled_color)
|
||||||
root._line_color_disabled \
|
|
||||||
or self._disabled_color \
|
|
||||||
or [0.0, 0.0, 0.0, 0.0] \
|
|
||||||
)
|
|
||||||
Line:
|
Line:
|
||||||
width: root.line_width
|
width: root.line_width
|
||||||
rounded_rectangle:
|
rounded_rectangle:
|
||||||
(self.x, self.y, self.width, self.height, \
|
( \
|
||||||
|
self.x, self.y, self.width, self.height, \
|
||||||
root._radius, root._radius, root._radius, root._radius, \
|
root._radius, root._radius, root._radius, root._radius, \
|
||||||
self.height)
|
self.height \
|
||||||
|
)
|
||||||
|
|
||||||
size_hint: None, None
|
size_hint: None, None
|
||||||
anchor_x: root.halign
|
anchor_x: root.halign
|
||||||
@ -33,21 +31,28 @@
|
|||||||
_round_rad: [self._radius] * 4
|
_round_rad: [self._radius] * 4
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<ButtonContentsText>
|
<ButtonContentsText>
|
||||||
lbl_txt: lbl_txt
|
lbl_txt: lbl_txt
|
||||||
width:
|
width:
|
||||||
max(root._min_width, \
|
max( \
|
||||||
root.padding[0] + lbl_txt.texture_size[0] + root.padding[2])
|
root._min_width, \
|
||||||
|
root.padding[0] + lbl_txt.texture_size[0] + root.padding[2] \
|
||||||
|
)
|
||||||
size_hint_min_x:
|
size_hint_min_x:
|
||||||
max(root._min_width, \
|
max( \
|
||||||
root.padding[0] + lbl_txt.texture_size[0] + root.padding[2])
|
root._min_width, \
|
||||||
|
root.padding[0] + lbl_txt.texture_size[0] + root.padding[2] \
|
||||||
|
)
|
||||||
height:
|
height:
|
||||||
max(root._min_height, \
|
max( \
|
||||||
root.padding[1] + lbl_txt.texture_size[1] + root.padding[3])
|
root._min_height, \
|
||||||
|
root.padding[1] + lbl_txt.texture_size[1] + root.padding[3] \
|
||||||
|
)
|
||||||
size_hint_min_y:
|
size_hint_min_y:
|
||||||
max(root._min_height, \
|
max( \
|
||||||
root.padding[1] + lbl_txt.texture_size[1] + root.padding[3])
|
root._min_height, \
|
||||||
|
root.padding[1] + lbl_txt.texture_size[1] + root.padding[3] \
|
||||||
|
)
|
||||||
|
|
||||||
MDLabel:
|
MDLabel:
|
||||||
id: lbl_txt
|
id: lbl_txt
|
||||||
@ -84,7 +89,10 @@
|
|||||||
# This is only a temporary fix and does not fix the cause of the error.
|
# This is only a temporary fix and does not fix the cause of the error.
|
||||||
(root._icon_color if root._icon_color else root.theme_cls.text_color) \
|
(root._icon_color if root._icon_color else root.theme_cls.text_color) \
|
||||||
if not root.disabled else \
|
if not root.disabled else \
|
||||||
root.theme_cls.disabled_hint_text_color
|
root.theme_cls.disabled_hint_text_color \
|
||||||
|
if not root.disabled_color else \
|
||||||
|
root.disabled_color
|
||||||
|
|
||||||
on_icon:
|
on_icon:
|
||||||
if self.icon not in md_icons.keys(): self.size_hint = (1, 1)
|
if self.icon not in md_icons.keys(): self.size_hint = (1, 1)
|
||||||
theme_text_color: root._theme_icon_color
|
theme_text_color: root._theme_icon_color
|
||||||
@ -131,7 +139,7 @@
|
|||||||
id: box
|
id: box
|
||||||
adaptive_size: True
|
adaptive_size: True
|
||||||
padding: 0
|
padding: 0
|
||||||
spacing: "4dp"
|
spacing: "8dp"
|
||||||
|
|
||||||
MDIcon:
|
MDIcon:
|
||||||
id: lbl_ic
|
id: lbl_ic
|
||||||
@ -193,48 +201,21 @@
|
|||||||
radius: [self.height / 2]
|
radius: [self.height / 2]
|
||||||
|
|
||||||
|
|
||||||
<BaseFloatingRootButton>
|
<MDFloatingRootButton>
|
||||||
theme_text_color: "Custom"
|
theme_text_color: "Custom"
|
||||||
md_bg_color: self.theme_cls.primary_color
|
md_bg_color: self.theme_cls.primary_color
|
||||||
|
|
||||||
|
|
||||||
|
<MDFloatingLabel>
|
||||||
|
padding_x: "8dp"
|
||||||
|
padding_y: "8dp"
|
||||||
|
adaptive_size: True
|
||||||
|
theme_text_color: "Custom"
|
||||||
|
|
||||||
canvas.before:
|
canvas.before:
|
||||||
PushMatrix
|
|
||||||
Rotate:
|
|
||||||
angle: self._angle
|
|
||||||
axis: (0, 0, 1)
|
|
||||||
origin: self.center
|
|
||||||
canvas.after:
|
|
||||||
PopMatrix
|
|
||||||
|
|
||||||
|
|
||||||
# FIXME: Use :class:`~kivymd.uix.boxlayout.MDBoxLayout` instead
|
|
||||||
# :class:`~kivy.uix.boxlayout.BoxLayout`.
|
|
||||||
<BaseFloatingLabel>
|
|
||||||
size_hint: None, None
|
|
||||||
padding: "8dp", "4dp", "8dp", "4dp"
|
|
||||||
height: label.texture_size[1] + self.padding[1] * 2
|
|
||||||
width: label.texture_size[0] + self.padding[0] * 2
|
|
||||||
elevation: 10
|
|
||||||
|
|
||||||
# TODO: Use `md_bg_color` and `radius` instead `canvasю
|
|
||||||
canvas:
|
|
||||||
Color:
|
Color:
|
||||||
rgba:
|
rgba: self.bg_color
|
||||||
self.theme_cls.primary_color \
|
|
||||||
if not root.bg_color else \
|
|
||||||
root.bg_color
|
|
||||||
RoundedRectangle:
|
RoundedRectangle:
|
||||||
pos: self.pos
|
|
||||||
size: self.size
|
size: self.size
|
||||||
radius: [5]
|
pos: self.pos
|
||||||
|
radius: self.radius
|
||||||
Label:
|
|
||||||
id: label
|
|
||||||
markup: True
|
|
||||||
text: root.text
|
|
||||||
size_hint: None, None
|
|
||||||
size: self.texture_size
|
|
||||||
color:
|
|
||||||
root.theme_cls.text_color \
|
|
||||||
if not root.text_color else \
|
|
||||||
root.text_color
|
|
||||||
|
@ -2,17 +2,6 @@
|
|||||||
md_bg_color: app.theme_cls.divider_color
|
md_bg_color: app.theme_cls.divider_color
|
||||||
|
|
||||||
|
|
||||||
<MDCard>
|
|
||||||
canvas.before:
|
|
||||||
Color:
|
|
||||||
rgba: self.md_bg_color
|
|
||||||
RoundedRectangle:
|
|
||||||
size: self.size
|
|
||||||
pos: self.pos
|
|
||||||
radius: root.radius
|
|
||||||
source: root.background
|
|
||||||
|
|
||||||
|
|
||||||
<MDSeparator>
|
<MDSeparator>
|
||||||
md_bg_color:
|
md_bg_color:
|
||||||
self.theme_cls.divider_color \
|
self.theme_cls.divider_color \
|
||||||
|
@ -26,26 +26,6 @@ Components/Card
|
|||||||
MDCard
|
MDCard
|
||||||
------
|
------
|
||||||
|
|
||||||
.. warning:: Starting from the KivyMD 1.1.0 library version, it is necessary
|
|
||||||
to manually inherit the card class from one of the ``Elevation`` classes
|
|
||||||
from ``kivymd/uix/behaviors/elevation.py`` module to draw the card shadow.
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
from kivymd.uix.behaviors import RoundedRectangularElevationBehavior
|
|
||||||
from kivymd.uix.card import MDCard
|
|
||||||
|
|
||||||
|
|
||||||
class MD3Card(MDCard, RoundedRectangularElevationBehavior):
|
|
||||||
'''Implements a material design v3 card.'''
|
|
||||||
|
|
||||||
It actually allows for better control over the providers that implement the
|
|
||||||
rendering of the shadows.
|
|
||||||
|
|
||||||
.. note:: You can read more information about the classes that implement the
|
|
||||||
rendering of shadows on this
|
|
||||||
`documentation page <https://kivymd.readthedocs.io/en/latest/behaviors/elevation/>`_.
|
|
||||||
|
|
||||||
An example of the implementation of a card in the style of material design version 3
|
An example of the implementation of a card in the style of material design version 3
|
||||||
------------------------------------------------------------------------------------
|
------------------------------------------------------------------------------------
|
||||||
|
|
||||||
@ -59,7 +39,6 @@ An example of the implementation of a card in the style of material design versi
|
|||||||
from kivy.properties import StringProperty
|
from kivy.properties import StringProperty
|
||||||
|
|
||||||
from kivymd.app import MDApp
|
from kivymd.app import MDApp
|
||||||
from kivymd.uix.behaviors import RoundedRectangularElevationBehavior
|
|
||||||
from kivymd.uix.card import MDCard
|
from kivymd.uix.card import MDCard
|
||||||
|
|
||||||
KV = '''
|
KV = '''
|
||||||
@ -93,7 +72,7 @@ An example of the implementation of a card in the style of material design versi
|
|||||||
'''
|
'''
|
||||||
|
|
||||||
|
|
||||||
class MD3Card(MDCard, RoundedRectangularElevationBehavior):
|
class MD3Card(MDCard):
|
||||||
'''Implements a material design v3 card.'''
|
'''Implements a material design v3 card.'''
|
||||||
|
|
||||||
text = StringProperty()
|
text = StringProperty()
|
||||||
@ -126,7 +105,6 @@ An example of the implementation of a card in the style of material design versi
|
|||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
from kivymd.app import MDApp
|
from kivymd.app import MDApp
|
||||||
from kivymd.uix.behaviors import RoundedRectangularElevationBehavior
|
|
||||||
from kivymd.uix.boxlayout import MDBoxLayout
|
from kivymd.uix.boxlayout import MDBoxLayout
|
||||||
from kivymd.uix.button import MDIconButton
|
from kivymd.uix.button import MDIconButton
|
||||||
from kivymd.uix.card import MDCard
|
from kivymd.uix.card import MDCard
|
||||||
@ -135,7 +113,7 @@ An example of the implementation of a card in the style of material design versi
|
|||||||
from kivymd.uix.screen import MDScreen
|
from kivymd.uix.screen import MDScreen
|
||||||
|
|
||||||
|
|
||||||
class MD3Card(MDCard, RoundedRectangularElevationBehavior):
|
class MD3Card(MDCard):
|
||||||
'''Implements a material design v3 card.'''
|
'''Implements a material design v3 card.'''
|
||||||
|
|
||||||
|
|
||||||
@ -170,7 +148,6 @@ An example of the implementation of a card in the style of material design versi
|
|||||||
adaptive_size=True,
|
adaptive_size=True,
|
||||||
color="grey",
|
color="grey",
|
||||||
pos=("12dp", "12dp"),
|
pos=("12dp", "12dp"),
|
||||||
bold=True,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
line_color=(0.2, 0.2, 0.2, 0.8),
|
line_color=(0.2, 0.2, 0.2, 0.8),
|
||||||
@ -255,10 +232,9 @@ End full code
|
|||||||
|
|
||||||
MDBoxLayout:
|
MDBoxLayout:
|
||||||
orientation: "vertical"
|
orientation: "vertical"
|
||||||
spacing: "10dp"
|
|
||||||
|
|
||||||
MDTopAppBar:
|
MDTopAppBar:
|
||||||
elevation: 10
|
elevation: 4
|
||||||
title: "MDCardSwipe"
|
title: "MDCardSwipe"
|
||||||
|
|
||||||
MDScrollView:
|
MDScrollView:
|
||||||
@ -286,7 +262,7 @@ End full code
|
|||||||
'''Creates a list of cards.'''
|
'''Creates a list of cards.'''
|
||||||
|
|
||||||
for i in range(20):
|
for i in range(20):
|
||||||
self.screen.ids.md_list.add_widget(
|
self.root.ids.md_list.add_widget(
|
||||||
SwipeToDeleteItem(text=f"One-line item {i}")
|
SwipeToDeleteItem(text=f"One-line item {i}")
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -316,7 +292,7 @@ End full code
|
|||||||
MDScreen(
|
MDScreen(
|
||||||
MDBoxLayout(
|
MDBoxLayout(
|
||||||
MDTopAppBar(
|
MDTopAppBar(
|
||||||
elevation=10,
|
elevation=4,
|
||||||
title="MDCardSwipe",
|
title="MDCardSwipe",
|
||||||
),
|
),
|
||||||
MDScrollView(
|
MDScrollView(
|
||||||
@ -328,7 +304,6 @@ End full code
|
|||||||
),
|
),
|
||||||
id="box",
|
id="box",
|
||||||
orientation="vertical",
|
orientation="vertical",
|
||||||
spacing="10dp",
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -426,7 +401,7 @@ You can use this event to remove items from a list:
|
|||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
def on_swipe_complete(self, instance):
|
def on_swipe_complete(self, instance):
|
||||||
self.screen.ids.md_list.remove_widget(instance)
|
self.root.ids.md_list.remove_widget(instance)
|
||||||
|
|
||||||
.. tab:: Decralative python styles
|
.. tab:: Decralative python styles
|
||||||
|
|
||||||
@ -496,10 +471,9 @@ End full code
|
|||||||
|
|
||||||
MDBoxLayout:
|
MDBoxLayout:
|
||||||
orientation: "vertical"
|
orientation: "vertical"
|
||||||
spacing: "10dp"
|
|
||||||
|
|
||||||
MDTopAppBar:
|
MDTopAppBar:
|
||||||
elevation: 10
|
elevation: 4
|
||||||
title: "MDCardSwipe"
|
title: "MDCardSwipe"
|
||||||
|
|
||||||
MDScrollView:
|
MDScrollView:
|
||||||
@ -560,7 +534,7 @@ End full code
|
|||||||
MDScreen(
|
MDScreen(
|
||||||
MDBoxLayout(
|
MDBoxLayout(
|
||||||
MDTopAppBar(
|
MDTopAppBar(
|
||||||
elevation=10,
|
elevation=4,
|
||||||
title="MDCardSwipe",
|
title="MDCardSwipe",
|
||||||
),
|
),
|
||||||
MDScrollView(
|
MDScrollView(
|
||||||
@ -572,7 +546,6 @@ End full code
|
|||||||
),
|
),
|
||||||
id="box",
|
id="box",
|
||||||
orientation="vertical",
|
orientation="vertical",
|
||||||
spacing="10dp",
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -630,26 +603,21 @@ Focus behavior
|
|||||||
from kivy.lang import Builder
|
from kivy.lang import Builder
|
||||||
|
|
||||||
from kivymd.app import MDApp
|
from kivymd.app import MDApp
|
||||||
from kivymd.uix.behaviors import FakeRectangularElevationBehavior
|
|
||||||
from kivymd.uix.card import MDCard
|
|
||||||
|
|
||||||
KV = '''
|
KV = '''
|
||||||
MDScreen:
|
MDScreen:
|
||||||
|
|
||||||
ElevationCard:
|
MDCard:
|
||||||
size_hint: .7, .4
|
size_hint: .7, .4
|
||||||
focus_behavior: True
|
focus_behavior: True
|
||||||
pos_hint: {"center_x": .5, "center_y": .5}
|
pos_hint: {"center_x": .5, "center_y": .5}
|
||||||
md_bg_color: "darkgrey"
|
md_bg_color: "darkgrey"
|
||||||
unfocus_color: "darkgrey"
|
unfocus_color: "darkgrey"
|
||||||
focus_color: "grey"
|
focus_color: "grey"
|
||||||
|
elevation: 6
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
|
||||||
class ElevationCard(MDCard, FakeRectangularElevationBehavior):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class Example(MDApp):
|
class Example(MDApp):
|
||||||
def build(self):
|
def build(self):
|
||||||
self.theme_cls.theme_style = "Dark"
|
self.theme_cls.theme_style = "Dark"
|
||||||
@ -663,27 +631,23 @@ Focus behavior
|
|||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
from kivymd.app import MDApp
|
from kivymd.app import MDApp
|
||||||
from kivymd.uix.behaviors import FakeRectangularElevationBehavior
|
|
||||||
from kivymd.uix.card import MDCard
|
from kivymd.uix.card import MDCard
|
||||||
from kivymd.uix.screen import MDScreen
|
from kivymd.uix.screen import MDScreen
|
||||||
|
|
||||||
|
|
||||||
class ElevationCard(MDCard, FakeRectangularElevationBehavior):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class Example(MDApp):
|
class Example(MDApp):
|
||||||
def build(self):
|
def build(self):
|
||||||
self.theme_cls.theme_style = "Dark"
|
self.theme_cls.theme_style = "Dark"
|
||||||
return (
|
return (
|
||||||
MDScreen(
|
MDScreen(
|
||||||
ElevationCard(
|
MDCard(
|
||||||
size_hint=(0.7, 0.4),
|
size_hint=(0.7, 0.4),
|
||||||
focus_behavior=True,
|
focus_behavior=True,
|
||||||
pos_hint={"center_x": 0.5, "center_y": 0.5},
|
pos_hint={"center_x": 0.5, "center_y": 0.5},
|
||||||
md_bg_color="darkgrey",
|
md_bg_color="darkgrey",
|
||||||
unfocus_color="darkgrey",
|
unfocus_color="darkgrey",
|
||||||
focus_color="grey",
|
focus_color="grey",
|
||||||
|
elevation=6,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -691,7 +655,6 @@ Focus behavior
|
|||||||
|
|
||||||
Example().run()
|
Example().run()
|
||||||
|
|
||||||
|
|
||||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/card-focus.gif
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/card-focus.gif
|
||||||
:align: center
|
:align: center
|
||||||
|
|
||||||
@ -732,12 +695,14 @@ from kivy.properties import (
|
|||||||
VariableListProperty,
|
VariableListProperty,
|
||||||
)
|
)
|
||||||
from kivy.uix.boxlayout import BoxLayout
|
from kivy.uix.boxlayout import BoxLayout
|
||||||
|
from kivy.utils import get_color_from_hex
|
||||||
|
|
||||||
from kivymd import uix_path
|
from kivymd import uix_path
|
||||||
from kivymd.color_definitions import colors
|
from kivymd.color_definitions import colors
|
||||||
from kivymd.theming import ThemableBehavior
|
from kivymd.theming import ThemableBehavior
|
||||||
from kivymd.uix.behaviors import (
|
from kivymd.uix.behaviors import (
|
||||||
BackgroundColorBehavior,
|
BackgroundColorBehavior,
|
||||||
|
CommonElevationBehavior,
|
||||||
DeclarativeBehavior,
|
DeclarativeBehavior,
|
||||||
RectangularRippleBehavior,
|
RectangularRippleBehavior,
|
||||||
)
|
)
|
||||||
@ -781,6 +746,7 @@ class MDCard(
|
|||||||
ThemableBehavior,
|
ThemableBehavior,
|
||||||
BackgroundColorBehavior,
|
BackgroundColorBehavior,
|
||||||
RectangularRippleBehavior,
|
RectangularRippleBehavior,
|
||||||
|
CommonElevationBehavior,
|
||||||
FocusBehavior,
|
FocusBehavior,
|
||||||
BoxLayout,
|
BoxLayout,
|
||||||
):
|
):
|
||||||
@ -800,14 +766,6 @@ class MDCard(
|
|||||||
and defaults to `False`.
|
and defaults to `False`.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
elevation = NumericProperty(None, allownone=True)
|
|
||||||
"""
|
|
||||||
Elevation value.
|
|
||||||
|
|
||||||
:attr:`elevation` is an :class:`~kivy.properties.NumericProperty`
|
|
||||||
and defaults to 1.
|
|
||||||
"""
|
|
||||||
|
|
||||||
radius = VariableListProperty([dp(6), dp(6), dp(6), dp(6)])
|
radius = VariableListProperty([dp(6), dp(6), dp(6), dp(6)])
|
||||||
"""
|
"""
|
||||||
Card radius by default.
|
Card radius by default.
|
||||||
@ -831,15 +789,16 @@ class MDCard(
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
_bg_color_map = (
|
_bg_color_map = (
|
||||||
colors["Light"]["CardsDialogs"],
|
get_color_from_hex(colors["Light"]["CardsDialogs"]),
|
||||||
colors["Dark"]["CardsDialogs"],
|
get_color_from_hex(colors["Dark"]["CardsDialogs"]),
|
||||||
[1.0, 1.0, 1.0, 0.0],
|
[1.0, 1.0, 1.0, 0.0],
|
||||||
)
|
)
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
self.theme_cls.bind(theme_style=self.update_md_bg_color)
|
self.theme_cls.bind(
|
||||||
self.theme_cls.bind(material_style=self.set_style)
|
material_style=self.set_style, theme_style=self.update_md_bg_color
|
||||||
|
)
|
||||||
Clock.schedule_once(self.set_style)
|
Clock.schedule_once(self.set_style)
|
||||||
Clock.schedule_once(
|
Clock.schedule_once(
|
||||||
lambda x: self.on_ripple_behavior(0, self.ripple_behavior)
|
lambda x: self.on_ripple_behavior(0, self.ripple_behavior)
|
||||||
@ -848,7 +807,9 @@ class MDCard(
|
|||||||
|
|
||||||
def update_md_bg_color(self, instance_card, theme_style: str) -> None:
|
def update_md_bg_color(self, instance_card, theme_style: str) -> None:
|
||||||
if self.md_bg_color in self._bg_color_map:
|
if self.md_bg_color in self._bg_color_map:
|
||||||
self.md_bg_color = colors[theme_style]["CardsDialogs"]
|
self.md_bg_color = get_color_from_hex(
|
||||||
|
colors[theme_style]["CardsDialogs"]
|
||||||
|
)
|
||||||
|
|
||||||
def set_style(self, *args) -> None:
|
def set_style(self, *args) -> None:
|
||||||
self.set_radius()
|
self.set_radius()
|
||||||
@ -865,7 +826,7 @@ class MDCard(
|
|||||||
if self.style == "outlined" or self.style == "filled":
|
if self.style == "outlined" or self.style == "filled":
|
||||||
self.elevation = 0
|
self.elevation = 0
|
||||||
elif self.style == "elevated":
|
elif self.style == "elevated":
|
||||||
self.elevation = 1
|
self.elevation = 2
|
||||||
|
|
||||||
def set_radius(self) -> None:
|
def set_radius(self) -> None:
|
||||||
if (
|
if (
|
||||||
|
@ -132,7 +132,7 @@ Use with elevation
|
|||||||
icon_right: "close-circle-outline"
|
icon_right: "close-circle-outline"
|
||||||
line_color: app.theme_cls.disabled_hint_text_color
|
line_color: app.theme_cls.disabled_hint_text_color
|
||||||
md_bg_color: 1, 0, 0, .5
|
md_bg_color: 1, 0, 0, .5
|
||||||
elevation: 12
|
elevation: 4
|
||||||
|
|
||||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/chip-with-elevation.png
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/chip-with-elevation.png
|
||||||
:align: center
|
:align: center
|
||||||
@ -304,7 +304,6 @@ __all__ = ("MDChip",)
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from kivy import Logger
|
|
||||||
from kivy.animation import Animation
|
from kivy.animation import Animation
|
||||||
from kivy.lang import Builder
|
from kivy.lang import Builder
|
||||||
from kivy.metrics import dp
|
from kivy.metrics import dp
|
||||||
@ -314,14 +313,13 @@ from kivy.uix.behaviors import ButtonBehavior
|
|||||||
from kivymd import uix_path
|
from kivymd import uix_path
|
||||||
from kivymd.theming import ThemableBehavior
|
from kivymd.theming import ThemableBehavior
|
||||||
from kivymd.uix.behaviors import (
|
from kivymd.uix.behaviors import (
|
||||||
FakeRectangularElevationBehavior,
|
CommonElevationBehavior,
|
||||||
RectangularRippleBehavior,
|
RectangularRippleBehavior,
|
||||||
|
ScaleBehavior,
|
||||||
TouchBehavior,
|
TouchBehavior,
|
||||||
)
|
)
|
||||||
from kivymd.uix.boxlayout import MDBoxLayout
|
from kivymd.uix.boxlayout import MDBoxLayout
|
||||||
from kivymd.uix.label import MDIcon
|
from kivymd.uix.label import MDIcon
|
||||||
from kivymd.uix.stacklayout import MDStackLayout
|
|
||||||
from kivymd.uix.templates import ScaleWidget
|
|
||||||
|
|
||||||
with open(
|
with open(
|
||||||
os.path.join(uix_path, "chip", "chip.kv"), encoding="utf-8"
|
os.path.join(uix_path, "chip", "chip.kv"), encoding="utf-8"
|
||||||
@ -330,12 +328,12 @@ with open(
|
|||||||
|
|
||||||
|
|
||||||
class MDChip(
|
class MDChip(
|
||||||
|
MDBoxLayout,
|
||||||
ThemableBehavior,
|
ThemableBehavior,
|
||||||
RectangularRippleBehavior,
|
RectangularRippleBehavior,
|
||||||
FakeRectangularElevationBehavior,
|
|
||||||
TouchBehavior,
|
|
||||||
ButtonBehavior,
|
ButtonBehavior,
|
||||||
MDBoxLayout,
|
CommonElevationBehavior,
|
||||||
|
TouchBehavior,
|
||||||
):
|
):
|
||||||
text = StringProperty()
|
text = StringProperty()
|
||||||
"""
|
"""
|
||||||
@ -456,7 +454,7 @@ class MDChip(
|
|||||||
self.active = False
|
self.active = False
|
||||||
|
|
||||||
|
|
||||||
class MDScalableCheckIcon(MDIcon, ScaleWidget):
|
class MDScalableCheckIcon(MDIcon, ScaleBehavior):
|
||||||
pos_hint = {"center_y": 0.5}
|
pos_hint = {"center_y": 0.5}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
#:import DEVICE_TYPE kivymd.material_resources.DEVICE_TYPE
|
#:import DEVICE_TYPE kivymd.material_resources.DEVICE_TYPE
|
||||||
#:import FakeRectangularElevationBehavior kivymd.uix.behaviors.FakeRectangularElevationBehavior
|
|
||||||
|
|
||||||
|
|
||||||
<CellRow>
|
<CellRow>
|
||||||
@ -66,7 +65,7 @@
|
|||||||
size_hint_y: None
|
size_hint_y: None
|
||||||
height: self.minimum_height
|
height: self.minimum_height
|
||||||
spacing: "4dp"
|
spacing: "4dp"
|
||||||
tooltip_text: root.text
|
tooltip_text: root.tooltip if root.tooltip else root.text
|
||||||
|
|
||||||
BoxLayout:
|
BoxLayout:
|
||||||
id: box
|
id: box
|
||||||
@ -175,7 +174,11 @@
|
|||||||
font_size: "14sp"
|
font_size: "14sp"
|
||||||
on_release: root.table_data.open_pagination_menu()
|
on_release: root.table_data.open_pagination_menu()
|
||||||
text:
|
text:
|
||||||
f"{root.table_data.rows_num if root.table_data.rows_num < len(root.table_data.row_data) else len(root.table_data.row_data)}"
|
"{}".format( \
|
||||||
|
root.table_data.rows_num \
|
||||||
|
if root.table_data.rows_num < len(root.table_data.row_data) else \
|
||||||
|
len(root.table_data.row_data) \
|
||||||
|
)
|
||||||
|
|
||||||
Widget:
|
Widget:
|
||||||
size_hint_x: None
|
size_hint_x: None
|
||||||
@ -192,9 +195,11 @@
|
|||||||
if root.theme_cls.theme_style == "Dark" else \
|
if root.theme_cls.theme_style == "Dark" else \
|
||||||
(0, 0, 0, 1)
|
(0, 0, 0, 1)
|
||||||
text:
|
text:
|
||||||
f"1-" \
|
"1-{} of {}".format( \
|
||||||
f"{root.table_data.rows_num if root.table_data.rows_num > len(root.table_data.row_data) else len(root.table_data.row_data)} " \
|
root.table_data.rows_num \
|
||||||
f"of {len(root.table_data.row_data)}"
|
if root.table_data.rows_num > len(root.table_data.row_data) else \
|
||||||
|
len(root.table_data.row_data), len(root.table_data.row_data) \
|
||||||
|
)
|
||||||
|
|
||||||
MDIconButton:
|
MDIconButton:
|
||||||
id: button_back
|
id: button_back
|
||||||
@ -217,7 +222,7 @@
|
|||||||
on_release: root.table_data.set_next_row_data_parts("forward")
|
on_release: root.table_data.set_next_row_data_parts("forward")
|
||||||
|
|
||||||
|
|
||||||
<TableContainer@MDCard+FakeRectangularElevationBehavior>
|
<TableContainer@MDCard>
|
||||||
|
|
||||||
|
|
||||||
<MDDataTable>
|
<MDDataTable>
|
||||||
|
@ -11,19 +11,6 @@ Components/DataTables
|
|||||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/data-tables-previous.png
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/data-tables-previous.png
|
||||||
:align: center
|
:align: center
|
||||||
|
|
||||||
Warnings
|
|
||||||
---------
|
|
||||||
|
|
||||||
.. warning:: Data tables are still far from perfect. The class is in constant
|
|
||||||
change, because of optimizations and bug fixes. If you find a bug or have
|
|
||||||
an improvement you want to share, take some time and share your discoveries
|
|
||||||
with us over the main git repo.
|
|
||||||
Any help is well appreciated.
|
|
||||||
|
|
||||||
.. warning:: In versions prior to `Kivy 2.1.0-dev0` exists an error in which is
|
|
||||||
the table has only one row in the current page, the table will only render
|
|
||||||
one column instead of the whole row.
|
|
||||||
|
|
||||||
.. note:: `MDDataTable` allows developers to sort the data provided by column.
|
.. note:: `MDDataTable` allows developers to sort the data provided by column.
|
||||||
This happens thanks to the use of an external function that you can bind
|
This happens thanks to the use of an external function that you can bind
|
||||||
while you're defining the table columns. Be aware that the sorting function
|
while you're defining the table columns. Be aware that the sorting function
|
||||||
@ -159,6 +146,15 @@ class CellHeader(MDTooltip, BoxLayout):
|
|||||||
and defaults to `''`.
|
and defaults to `''`.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
tooltip = StringProperty()
|
||||||
|
"""
|
||||||
|
Tooltip containing descriptive text for the column.
|
||||||
|
If the tooltip is not provided, column `text` shall be used instead.
|
||||||
|
|
||||||
|
:attr:`tooltip` is a :class:`~kivy.properties.StringProperty`
|
||||||
|
and defaults to `''`.
|
||||||
|
"""
|
||||||
|
|
||||||
# TODO: Added example.
|
# TODO: Added example.
|
||||||
sort_action = ObjectProperty()
|
sort_action = ObjectProperty()
|
||||||
"""
|
"""
|
||||||
@ -340,11 +336,19 @@ class TableHeader(ThemableBehavior, ScrollView):
|
|||||||
CellHeader(
|
CellHeader(
|
||||||
text=col_heading[0],
|
text=col_heading[0],
|
||||||
sort_action=col_heading[2],
|
sort_action=col_heading[2],
|
||||||
|
tooltip=col_heading[3],
|
||||||
width=self.cols_minimum[i],
|
width=self.cols_minimum[i],
|
||||||
table_data=self.table_data,
|
table_data=self.table_data,
|
||||||
is_sorted=(col_heading[0] == self.sorted_on),
|
is_sorted=(col_heading[0] == self.sorted_on),
|
||||||
sorted_order=self.sorted_order,
|
sorted_order=self.sorted_order,
|
||||||
)
|
)
|
||||||
|
if len(col_heading) == 4
|
||||||
|
else CellHeader(
|
||||||
|
text=col_heading[0],
|
||||||
|
sort_action=col_heading[2],
|
||||||
|
width=self.cols_minimum[i],
|
||||||
|
table_data=self.table_data,
|
||||||
|
)
|
||||||
if len(col_heading) == 3
|
if len(col_heading) == 3
|
||||||
else CellHeader(
|
else CellHeader(
|
||||||
text=col_heading[0],
|
text=col_heading[0],
|
||||||
@ -356,6 +360,9 @@ class TableHeader(ThemableBehavior, ScrollView):
|
|||||||
else:
|
else:
|
||||||
# Sets the text in the first cell.
|
# Sets the text in the first cell.
|
||||||
self.ids.first_cell.text = col_heading[0]
|
self.ids.first_cell.text = col_heading[0]
|
||||||
|
self.ids.first_cell.tooltip = (
|
||||||
|
col_heading[3] if len(col_heading) == 4 else ""
|
||||||
|
)
|
||||||
self.ids.first_cell.ids.separator.height = 0
|
self.ids.first_cell.ids.separator.height = 0
|
||||||
self.ids.first_cell.width = self.cols_minimum[i]
|
self.ids.first_cell.width = self.cols_minimum[i]
|
||||||
|
|
||||||
@ -765,6 +772,9 @@ class TablePagination(ThemableBehavior, MDBoxLayout):
|
|||||||
|
|
||||||
class MDDataTable(ThemableBehavior, AnchorLayout):
|
class MDDataTable(ThemableBehavior, AnchorLayout):
|
||||||
"""
|
"""
|
||||||
|
See :class:`~kivy.uix.anchorlayout.AnchorLayout` class documentation for
|
||||||
|
more information.
|
||||||
|
|
||||||
:Events:
|
:Events:
|
||||||
:attr:`on_row_press`
|
:attr:`on_row_press`
|
||||||
Called when a table row is clicked.
|
Called when a table row is clicked.
|
||||||
@ -775,7 +785,6 @@ class MDDataTable(ThemableBehavior, AnchorLayout):
|
|||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
|
|
||||||
from kivy.metrics import dp
|
from kivy.metrics import dp
|
||||||
|
|
||||||
from kivymd.app import MDApp
|
from kivymd.app import MDApp
|
||||||
@ -914,6 +923,10 @@ class MDDataTable(ThemableBehavior, AnchorLayout):
|
|||||||
"""
|
"""
|
||||||
Data for header columns.
|
Data for header columns.
|
||||||
|
|
||||||
|
.. tabs::
|
||||||
|
|
||||||
|
.. tab:: Imperative python style
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
from kivy.metrics import dp
|
from kivy.metrics import dp
|
||||||
@ -925,14 +938,17 @@ class MDDataTable(ThemableBehavior, AnchorLayout):
|
|||||||
|
|
||||||
class Example(MDApp):
|
class Example(MDApp):
|
||||||
def build(self):
|
def build(self):
|
||||||
|
self.theme_cls.theme_style = "Dark"
|
||||||
|
self.theme_cls.primary_palette = "Orange"
|
||||||
|
|
||||||
layout = AnchorLayout()
|
layout = AnchorLayout()
|
||||||
self.data_tables = MDDataTable(
|
self.data_tables = MDDataTable(
|
||||||
size_hint=(0.7, 0.6),
|
size_hint=(0.7, 0.6),
|
||||||
use_pagination=True,
|
use_pagination=True,
|
||||||
check=True,
|
check=True,
|
||||||
# name column, width column, sorting function column(optional)
|
# name column, width column, sorting function column(optional), custom tooltip
|
||||||
column_data=[
|
column_data=[
|
||||||
("No.", dp(30)),
|
("No.", dp(30), None, "Custom tooltip"),
|
||||||
("Status", dp(30)),
|
("Status", dp(30)),
|
||||||
("Signal Name", dp(60)),
|
("Signal Name", dp(60)),
|
||||||
("Severity", dp(30)),
|
("Severity", dp(30)),
|
||||||
@ -947,6 +963,43 @@ class MDDataTable(ThemableBehavior, AnchorLayout):
|
|||||||
|
|
||||||
Example().run()
|
Example().run()
|
||||||
|
|
||||||
|
.. tab:: Declarative python style
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from kivy.metrics import dp
|
||||||
|
|
||||||
|
from kivymd.app import MDApp
|
||||||
|
from kivymd.uix.anchorlayout import MDAnchorLayout
|
||||||
|
from kivymd.uix.datatables import MDDataTable
|
||||||
|
|
||||||
|
|
||||||
|
class Example(MDApp):
|
||||||
|
def build(self):
|
||||||
|
self.theme_cls.theme_style = "Dark"
|
||||||
|
self.theme_cls.primary_palette = "Orange"
|
||||||
|
return MDAnchorLayout(
|
||||||
|
MDDataTable(
|
||||||
|
size_hint=(0.7, 0.6),
|
||||||
|
use_pagination=True,
|
||||||
|
check=True,
|
||||||
|
# name column, width column, sorting function column(optional)
|
||||||
|
column_data=[
|
||||||
|
("No.", dp(30)),
|
||||||
|
("Status", dp(30)),
|
||||||
|
("Signal Name", dp(60)),
|
||||||
|
("Severity", dp(30)),
|
||||||
|
("Stage", dp(30)),
|
||||||
|
("Schedule", dp(30),
|
||||||
|
lambda *args: print("Sorted using Schedule")),
|
||||||
|
("Team Lead", dp(30)),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
Example().run()
|
||||||
|
|
||||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/data-tables-column-data.png
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/data-tables-column-data.png
|
||||||
:align: center
|
:align: center
|
||||||
|
|
||||||
@ -1060,6 +1113,9 @@ class MDDataTable(ThemableBehavior, AnchorLayout):
|
|||||||
|
|
||||||
class Example(MDApp):
|
class Example(MDApp):
|
||||||
def build(self):
|
def build(self):
|
||||||
|
self.theme_cls.theme_style = "Dark"
|
||||||
|
self.theme_cls.primary_palette = "Orange"
|
||||||
|
|
||||||
layout = AnchorLayout()
|
layout = AnchorLayout()
|
||||||
data_tables = MDDataTable(
|
data_tables = MDDataTable(
|
||||||
size_hint=(0.9, 0.6),
|
size_hint=(0.9, 0.6),
|
||||||
@ -1187,7 +1243,7 @@ class MDDataTable(ThemableBehavior, AnchorLayout):
|
|||||||
"""
|
"""
|
||||||
Use or not use checkboxes for rows.
|
Use or not use checkboxes for rows.
|
||||||
|
|
||||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/data-tables-check.gif
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/data-tables-check.png
|
||||||
:align: center
|
:align: center
|
||||||
|
|
||||||
:attr:`check` is an :class:`~kivy.properties.BooleanProperty`
|
:attr:`check` is an :class:`~kivy.properties.BooleanProperty`
|
||||||
@ -1209,6 +1265,9 @@ class MDDataTable(ThemableBehavior, AnchorLayout):
|
|||||||
|
|
||||||
class Example(MDApp):
|
class Example(MDApp):
|
||||||
def build(self):
|
def build(self):
|
||||||
|
self.theme_cls.theme_style = "Dark"
|
||||||
|
self.theme_cls.primary_palette = "Orange"
|
||||||
|
|
||||||
layout = AnchorLayout()
|
layout = AnchorLayout()
|
||||||
data_tables = MDDataTable(
|
data_tables = MDDataTable(
|
||||||
size_hint=(0.9, 0.6),
|
size_hint=(0.9, 0.6),
|
||||||
@ -1238,19 +1297,19 @@ class MDDataTable(ThemableBehavior, AnchorLayout):
|
|||||||
and defaults to `False`.
|
and defaults to `False`.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
elevation = NumericProperty(8)
|
elevation = NumericProperty(4)
|
||||||
"""
|
"""
|
||||||
Table elevation.
|
Table elevation.
|
||||||
|
|
||||||
:attr:`elevation` is an :class:`~kivy.properties.NumericProperty`
|
:attr:`elevation` is an :class:`~kivy.properties.NumericProperty`
|
||||||
and defaults to `8`.
|
and defaults to `4`.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
rows_num = NumericProperty(5)
|
rows_num = NumericProperty(5)
|
||||||
"""
|
"""
|
||||||
The number of rows displayed on one page of the table.
|
The number of rows displayed on one page of the table.
|
||||||
|
|
||||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/data-tables-use-pagination.gif
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/data-tables-use-pagination-rows-num.png
|
||||||
:align: center
|
:align: center
|
||||||
|
|
||||||
:attr:`rows_num` is an :class:`~kivy.properties.NumericProperty`
|
:attr:`rows_num` is an :class:`~kivy.properties.NumericProperty`
|
||||||
@ -1266,7 +1325,7 @@ class MDDataTable(ThemableBehavior, AnchorLayout):
|
|||||||
|
|
||||||
.. rubric:: Center
|
.. rubric:: Center
|
||||||
|
|
||||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/data-tables-menu-pos-center.png
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/data-tables-menu-pos-top.png
|
||||||
:align: center
|
:align: center
|
||||||
|
|
||||||
.. rubric:: Auto
|
.. rubric:: Auto
|
||||||
@ -1282,11 +1341,6 @@ class MDDataTable(ThemableBehavior, AnchorLayout):
|
|||||||
"""
|
"""
|
||||||
Menu height for selecting the number of displayed rows.
|
Menu height for selecting the number of displayed rows.
|
||||||
|
|
||||||
.. rubric:: 140dp
|
|
||||||
|
|
||||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/data-tables-menu-height-140.png
|
|
||||||
:align: center
|
|
||||||
|
|
||||||
.. rubric:: 240dp
|
.. rubric:: 240dp
|
||||||
|
|
||||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/data-tables-menu-height-240.png
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/data-tables-menu-height-240.png
|
||||||
@ -1298,7 +1352,7 @@ class MDDataTable(ThemableBehavior, AnchorLayout):
|
|||||||
|
|
||||||
background_color = ColorProperty([0, 0, 0, 0])
|
background_color = ColorProperty([0, 0, 0, 0])
|
||||||
"""
|
"""
|
||||||
Background color in the format (r, g, b, a).
|
Background color in the format (r, g, b, a) or string format.
|
||||||
See :attr:`~kivy.uix.modalview.ModalView.background_color`.
|
See :attr:`~kivy.uix.modalview.ModalView.background_color`.
|
||||||
|
|
||||||
Use markup strings
|
Use markup strings
|
||||||
@ -1315,6 +1369,9 @@ class MDDataTable(ThemableBehavior, AnchorLayout):
|
|||||||
|
|
||||||
class Example(MDApp):
|
class Example(MDApp):
|
||||||
def build(self):
|
def build(self):
|
||||||
|
self.theme_cls.theme_style = "Dark"
|
||||||
|
self.theme_cls.primary_palette = "Orange"
|
||||||
|
|
||||||
layout = AnchorLayout()
|
layout = AnchorLayout()
|
||||||
data_tables = MDDataTable(
|
data_tables = MDDataTable(
|
||||||
size_hint=(0.9, 0.6),
|
size_hint=(0.9, 0.6),
|
||||||
@ -1354,7 +1411,8 @@ class MDDataTable(ThemableBehavior, AnchorLayout):
|
|||||||
|
|
||||||
background_color_header = ColorProperty(None)
|
background_color_header = ColorProperty(None)
|
||||||
"""
|
"""
|
||||||
Background color for :class:`~TableHeader` class.
|
Background color in the format (r, g, b, a) or string format for
|
||||||
|
:class:`~TableHeader` class.
|
||||||
|
|
||||||
.. versionadded:: 1.0.0
|
.. versionadded:: 1.0.0
|
||||||
|
|
||||||
@ -1374,7 +1432,8 @@ class MDDataTable(ThemableBehavior, AnchorLayout):
|
|||||||
|
|
||||||
background_color_cell = ColorProperty(None)
|
background_color_cell = ColorProperty(None)
|
||||||
"""
|
"""
|
||||||
Background color for :class:`~CellRow` class.
|
Background color in the format (r, g, b, a) or string format for
|
||||||
|
:class:`~CellRow` class.
|
||||||
|
|
||||||
.. versionadded:: 1.0.0
|
.. versionadded:: 1.0.0
|
||||||
|
|
||||||
@ -1395,7 +1454,8 @@ class MDDataTable(ThemableBehavior, AnchorLayout):
|
|||||||
|
|
||||||
background_color_selected_cell = ColorProperty(None)
|
background_color_selected_cell = ColorProperty(None)
|
||||||
"""
|
"""
|
||||||
Background selected color for :class:`~CellRow` class.
|
Background selected color in the format (r, g, b, a) or string format for
|
||||||
|
:class:`~CellRow` class.
|
||||||
|
|
||||||
.. versionadded:: 1.0.0
|
.. versionadded:: 1.0.0
|
||||||
|
|
||||||
@ -1408,7 +1468,7 @@ class MDDataTable(ThemableBehavior, AnchorLayout):
|
|||||||
background_color_selected_cell="e4514f",
|
background_color_selected_cell="e4514f",
|
||||||
)
|
)
|
||||||
|
|
||||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/data-tables-background-color-selected-cell.gif
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/data-tables-background-color-selected-cell.png
|
||||||
:align: center
|
:align: center
|
||||||
|
|
||||||
:attr:`background_color_selected_cell` is a :class:`~kivy.properties.ColorProperty` and
|
:attr:`background_color_selected_cell` is a :class:`~kivy.properties.ColorProperty` and
|
||||||
@ -1503,6 +1563,9 @@ class MDDataTable(ThemableBehavior, AnchorLayout):
|
|||||||
data_tables = None
|
data_tables = None
|
||||||
|
|
||||||
def build(self):
|
def build(self):
|
||||||
|
self.theme_cls.theme_style = "Dark"
|
||||||
|
self.theme_cls.primary_palette = "Orange"
|
||||||
|
|
||||||
layout = MDFloatLayout() # root layout
|
layout = MDFloatLayout() # root layout
|
||||||
# Creating control buttons.
|
# Creating control buttons.
|
||||||
button_box = MDBoxLayout(
|
button_box = MDBoxLayout(
|
||||||
@ -1604,6 +1667,9 @@ class MDDataTable(ThemableBehavior, AnchorLayout):
|
|||||||
data_tables = None
|
data_tables = None
|
||||||
|
|
||||||
def build(self):
|
def build(self):
|
||||||
|
self.theme_cls.theme_style = "Dark"
|
||||||
|
self.theme_cls.primary_palette = "Orange"
|
||||||
|
|
||||||
layout = MDFloatLayout()
|
layout = MDFloatLayout()
|
||||||
layout.add_widget(
|
layout.add_widget(
|
||||||
MDRaisedButton(
|
MDRaisedButton(
|
||||||
|
@ -18,7 +18,11 @@
|
|||||||
PopMatrix
|
PopMatrix
|
||||||
|
|
||||||
|
|
||||||
<DialogContainer@MDCard+FakeRectangularElevationBehavior>
|
<DialogContainer@MDCard>
|
||||||
|
shadow_color: 0.0, 0.0, 0.0, 0.0
|
||||||
|
elevation: 0
|
||||||
|
shadow_softness: 0
|
||||||
|
shadow_offset: 0, 0
|
||||||
|
|
||||||
|
|
||||||
<MDDialog>
|
<MDDialog>
|
||||||
@ -28,7 +32,6 @@
|
|||||||
orientation: "vertical"
|
orientation: "vertical"
|
||||||
size_hint_y: None
|
size_hint_y: None
|
||||||
height: self.minimum_height
|
height: self.minimum_height
|
||||||
elevation: 24
|
|
||||||
padding: "24dp", "24dp", "8dp", "8dp"
|
padding: "24dp", "24dp", "8dp", "8dp"
|
||||||
radius: root.radius
|
radius: root.radius
|
||||||
md_bg_color:
|
md_bg_color:
|
||||||
|
@ -38,6 +38,8 @@ Usage
|
|||||||
dialog = None
|
dialog = None
|
||||||
|
|
||||||
def build(self):
|
def build(self):
|
||||||
|
self.theme_cls.theme_style = "Dark"
|
||||||
|
self.theme_cls.primary_palette = "Orange"
|
||||||
return Builder.load_string(KV)
|
return Builder.load_string(KV)
|
||||||
|
|
||||||
def show_alert_dialog(self):
|
def show_alert_dialog(self):
|
||||||
@ -87,6 +89,7 @@ from kivy.uix.modalview import ModalView
|
|||||||
from kivymd import uix_path
|
from kivymd import uix_path
|
||||||
from kivymd.material_resources import DEVICE_TYPE
|
from kivymd.material_resources import DEVICE_TYPE
|
||||||
from kivymd.theming import ThemableBehavior
|
from kivymd.theming import ThemableBehavior
|
||||||
|
from kivymd.uix.behaviors import CommonElevationBehavior
|
||||||
from kivymd.uix.button import BaseButton
|
from kivymd.uix.button import BaseButton
|
||||||
from kivymd.uix.card import MDSeparator
|
from kivymd.uix.card import MDSeparator
|
||||||
from kivymd.uix.list import BaseListItem
|
from kivymd.uix.list import BaseListItem
|
||||||
@ -97,7 +100,40 @@ with open(
|
|||||||
Builder.load_string(kv_file.read())
|
Builder.load_string(kv_file.read())
|
||||||
|
|
||||||
|
|
||||||
class BaseDialog(ThemableBehavior, ModalView):
|
class BaseDialog(ThemableBehavior, ModalView, CommonElevationBehavior):
|
||||||
|
elevation = NumericProperty(3)
|
||||||
|
"""
|
||||||
|
See :attr:`kivymd.uix.behaviors.elevation.CommonElevationBehavior.elevation`
|
||||||
|
attribute for more information.
|
||||||
|
|
||||||
|
.. versionadded:: 1.1.0
|
||||||
|
|
||||||
|
:attr:`elevation` is an :class:`~kivy.properties.NumericProperty`
|
||||||
|
and defaults to `3`.
|
||||||
|
"""
|
||||||
|
|
||||||
|
shadow_softness = NumericProperty(24)
|
||||||
|
"""
|
||||||
|
See :attr:`kivymd.uix.behaviors.elevation.CommonElevationBehavior.shadow_softness`
|
||||||
|
attribute for more information.
|
||||||
|
|
||||||
|
.. versionadded:: 1.1.0
|
||||||
|
|
||||||
|
:attr:`shadow_softness` is an :class:`~kivy.properties.NumericProperty`
|
||||||
|
and defaults to `24`.
|
||||||
|
"""
|
||||||
|
|
||||||
|
shadow_offset = ListProperty((0, 4))
|
||||||
|
"""
|
||||||
|
See :attr:`kivymd.uix.behaviors.elevation.CommonElevationBehavior.shadow_offset`
|
||||||
|
attribute for more information.
|
||||||
|
|
||||||
|
.. versionadded:: 1.1.0
|
||||||
|
|
||||||
|
:attr:`shadow_offset` is an :class:`~kivy.properties.ListProperty`
|
||||||
|
and defaults to `[0, 4]`.
|
||||||
|
"""
|
||||||
|
|
||||||
radius = ListProperty([dp(7), dp(7), dp(7), dp(7)])
|
radius = ListProperty([dp(7), dp(7), dp(7), dp(7)])
|
||||||
"""
|
"""
|
||||||
Dialog corners rounding value.
|
Dialog corners rounding value.
|
||||||
@ -251,6 +287,8 @@ class MDDialog(BaseDialog):
|
|||||||
dialog = None
|
dialog = None
|
||||||
|
|
||||||
def build(self):
|
def build(self):
|
||||||
|
self.theme_cls.theme_style = "Dark"
|
||||||
|
self.theme_cls.primary_palette = "Orange"
|
||||||
return Builder.load_string(KV)
|
return Builder.load_string(KV)
|
||||||
|
|
||||||
def show_simple_dialog(self):
|
def show_simple_dialog(self):
|
||||||
@ -259,9 +297,8 @@ class MDDialog(BaseDialog):
|
|||||||
title="Set backup account",
|
title="Set backup account",
|
||||||
type="simple",
|
type="simple",
|
||||||
items=[
|
items=[
|
||||||
Item(text="user01@gmail.com", source="user-1.png"),
|
Item(text="user01@gmail.com", source="kivymd/images/logo/kivymd-icon-128.png"),
|
||||||
Item(text="user02@gmail.com", source="user-2.png"),
|
Item(text="user02@gmail.com", source="data/logo/kivy-icon-128.png"),
|
||||||
Item(text="Add account", source="add-icon.png"),
|
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
self.dialog.open()
|
self.dialog.open()
|
||||||
@ -317,6 +354,8 @@ class MDDialog(BaseDialog):
|
|||||||
dialog = None
|
dialog = None
|
||||||
|
|
||||||
def build(self):
|
def build(self):
|
||||||
|
self.theme_cls.theme_style = "Dark"
|
||||||
|
self.theme_cls.primary_palette = "Orange"
|
||||||
return Builder.load_string(KV)
|
return Builder.load_string(KV)
|
||||||
|
|
||||||
def show_confirmation_dialog(self):
|
def show_confirmation_dialog(self):
|
||||||
@ -385,6 +424,10 @@ class MDDialog(BaseDialog):
|
|||||||
"""
|
"""
|
||||||
Custom content class.
|
Custom content class.
|
||||||
|
|
||||||
|
.. tabs::
|
||||||
|
|
||||||
|
.. tab:: Declarative KV style
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
from kivy.lang import Builder
|
from kivy.lang import Builder
|
||||||
@ -425,6 +468,8 @@ class MDDialog(BaseDialog):
|
|||||||
dialog = None
|
dialog = None
|
||||||
|
|
||||||
def build(self):
|
def build(self):
|
||||||
|
self.theme_cls.theme_style = "Dark"
|
||||||
|
self.theme_cls.primary_palette = "Orange"
|
||||||
return Builder.load_string(KV)
|
return Builder.load_string(KV)
|
||||||
|
|
||||||
def show_confirmation_dialog(self):
|
def show_confirmation_dialog(self):
|
||||||
@ -451,6 +496,69 @@ class MDDialog(BaseDialog):
|
|||||||
|
|
||||||
Example().run()
|
Example().run()
|
||||||
|
|
||||||
|
.. tab:: Declarative Python style
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from kivymd.app import MDApp
|
||||||
|
from kivymd.uix.boxlayout import MDBoxLayout
|
||||||
|
from kivymd.uix.button import MDFlatButton
|
||||||
|
from kivymd.uix.dialog import MDDialog
|
||||||
|
from kivymd.uix.floatlayout import MDFloatLayout
|
||||||
|
from kivymd.uix.textfield import MDTextField
|
||||||
|
|
||||||
|
|
||||||
|
class Example(MDApp):
|
||||||
|
dialog = None
|
||||||
|
|
||||||
|
def build(self):
|
||||||
|
self.theme_cls.theme_style = "Dark"
|
||||||
|
self.theme_cls.primary_palette = "Orange"
|
||||||
|
return (
|
||||||
|
MDFloatLayout(
|
||||||
|
MDFlatButton(
|
||||||
|
text="ALERT DIALOG",
|
||||||
|
pos_hint={'center_x': 0.5, 'center_y': 0.5},
|
||||||
|
on_release=self.show_confirmation_dialog,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
def show_confirmation_dialog(self, *args):
|
||||||
|
if not self.dialog:
|
||||||
|
self.dialog = MDDialog(
|
||||||
|
title="Address:",
|
||||||
|
type="custom",
|
||||||
|
content_cls=MDBoxLayout(
|
||||||
|
MDTextField(
|
||||||
|
hint_text="City",
|
||||||
|
),
|
||||||
|
MDTextField(
|
||||||
|
hint_text="Street",
|
||||||
|
),
|
||||||
|
orientation="vertical",
|
||||||
|
spacing="12dp",
|
||||||
|
size_hint_y=None,
|
||||||
|
height="120dp",
|
||||||
|
),
|
||||||
|
buttons=[
|
||||||
|
MDFlatButton(
|
||||||
|
text="CANCEL",
|
||||||
|
theme_text_color="Custom",
|
||||||
|
text_color=self.theme_cls.primary_color,
|
||||||
|
),
|
||||||
|
MDFlatButton(
|
||||||
|
text="OK",
|
||||||
|
theme_text_color="Custom",
|
||||||
|
text_color=self.theme_cls.primary_color,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
self.dialog.open()
|
||||||
|
|
||||||
|
|
||||||
|
Example().run()
|
||||||
|
|
||||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/dialog-custom.png
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/dialog-custom.png
|
||||||
:align: center
|
:align: center
|
||||||
|
|
||||||
@ -460,7 +568,7 @@ class MDDialog(BaseDialog):
|
|||||||
|
|
||||||
md_bg_color = ColorProperty(None)
|
md_bg_color = ColorProperty(None)
|
||||||
"""
|
"""
|
||||||
Background color in the format (r, g, b, a).
|
Background color in the (r, g, b, a) or string format.
|
||||||
|
|
||||||
:attr:`md_bg_color` is an :class:`~kivy.properties.ColorProperty`
|
:attr:`md_bg_color` is an :class:`~kivy.properties.ColorProperty`
|
||||||
and defaults to `None`.
|
and defaults to `None`.
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<_Triangle>:
|
<_Triangle>:
|
||||||
canvas:
|
canvas:
|
||||||
Color:
|
Color:
|
||||||
rgba: root.theme_cls.text_color
|
rgba: app.theme_cls.text_color
|
||||||
Triangle:
|
Triangle:
|
||||||
points:
|
points:
|
||||||
[ \
|
[ \
|
||||||
@ -13,7 +13,8 @@
|
|||||||
|
|
||||||
<MDDropDownItem>
|
<MDDropDownItem>
|
||||||
orientation: "vertical"
|
orientation: "vertical"
|
||||||
adaptive_size: True
|
size_hint: None, None
|
||||||
|
size: self.minimum_size
|
||||||
spacing: "5dp"
|
spacing: "5dp"
|
||||||
padding: "5dp", "5dp", "5dp", 0
|
padding: "5dp", "5dp", "5dp", 0
|
||||||
|
|
||||||
|
@ -15,13 +15,13 @@ Usage
|
|||||||
from kivymd.app import MDApp
|
from kivymd.app import MDApp
|
||||||
|
|
||||||
KV = '''
|
KV = '''
|
||||||
Screen
|
MDScreen
|
||||||
|
|
||||||
MDDropDownItem:
|
MDDropDownItem:
|
||||||
id: drop_item
|
id: drop_item
|
||||||
pos_hint: {'center_x': .5, 'center_y': .5}
|
pos_hint: {'center_x': .5, 'center_y': .5}
|
||||||
text: 'Item'
|
text: 'Item'
|
||||||
on_release: self.set_item("New Item")
|
on_release: print("Press item")
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
|
||||||
@ -48,12 +48,12 @@ import os
|
|||||||
from kivy.lang import Builder
|
from kivy.lang import Builder
|
||||||
from kivy.properties import NumericProperty, StringProperty
|
from kivy.properties import NumericProperty, StringProperty
|
||||||
from kivy.uix.behaviors import ButtonBehavior
|
from kivy.uix.behaviors import ButtonBehavior
|
||||||
|
from kivy.uix.boxlayout import BoxLayout
|
||||||
from kivy.uix.widget import Widget
|
from kivy.uix.widget import Widget
|
||||||
|
|
||||||
from kivymd import uix_path
|
from kivymd import uix_path
|
||||||
from kivymd.theming import ThemableBehavior
|
from kivymd.theming import ThemableBehavior
|
||||||
from kivymd.uix.behaviors import FakeRectangularElevationBehavior
|
from kivymd.uix.behaviors import DeclarativeBehavior
|
||||||
from kivymd.uix.boxlayout import MDBoxLayout
|
|
||||||
|
|
||||||
with open(
|
with open(
|
||||||
os.path.join(uix_path, "dropdownitem", "dropdownitem.kv"), encoding="utf-8"
|
os.path.join(uix_path, "dropdownitem", "dropdownitem.kv"), encoding="utf-8"
|
||||||
@ -61,15 +61,12 @@ with open(
|
|||||||
Builder.load_string(kv_file.read())
|
Builder.load_string(kv_file.read())
|
||||||
|
|
||||||
|
|
||||||
class _Triangle(ThemableBehavior, Widget):
|
class _Triangle(Widget):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class MDDropDownItem(
|
class MDDropDownItem(
|
||||||
ThemableBehavior,
|
DeclarativeBehavior, ThemableBehavior, ButtonBehavior, BoxLayout
|
||||||
FakeRectangularElevationBehavior,
|
|
||||||
ButtonBehavior,
|
|
||||||
MDBoxLayout,
|
|
||||||
):
|
):
|
||||||
text = StringProperty()
|
text = StringProperty()
|
||||||
"""
|
"""
|
||||||
|
@ -6,28 +6,29 @@
|
|||||||
background_normal: ""
|
background_normal: ""
|
||||||
background_down: ""
|
background_down: ""
|
||||||
dir_or_file_name: ""
|
dir_or_file_name: ""
|
||||||
|
icon_color: 0, 0, 0, 0
|
||||||
_selected: False
|
_selected: False
|
||||||
events_callback: lambda x: None
|
events_callback: lambda x: None
|
||||||
orientation: "vertical"
|
orientation: "vertical"
|
||||||
|
|
||||||
ModifiedOneLineIconListItem:
|
ModifiedOneLineIconListItem:
|
||||||
text: root.dir_or_file_name
|
text: root.dir_or_file_name
|
||||||
|
on_release: root.events_callback(root.path, root)
|
||||||
bg_color:
|
bg_color:
|
||||||
self.theme_cls.bg_darkest \
|
self.theme_cls.bg_darkest \
|
||||||
if root._selected else self.theme_cls.bg_normal
|
if root._selected else \
|
||||||
on_release: root.events_callback(root.path, root)
|
self.theme_cls.bg_normal
|
||||||
|
|
||||||
IconLeftWidget:
|
IconLeftWidget:
|
||||||
icon: root.icon
|
icon: root.icon
|
||||||
theme_text_color: "Custom"
|
theme_icon_color: "Custom"
|
||||||
text_color: self.theme_cls.primary_color
|
icon_color: root.icon_color
|
||||||
|
|
||||||
MDSeparator:
|
MDSeparator:
|
||||||
|
|
||||||
|
|
||||||
<LabelContent@MDLabel>
|
<LabelContent@MDLabel>
|
||||||
size_hint_y: None
|
adaptive_height: True
|
||||||
height: self.texture_size[1]
|
|
||||||
shorten: True
|
shorten: True
|
||||||
shorten_from: "center"
|
shorten_from: "center"
|
||||||
halign: "center"
|
halign: "center"
|
||||||
@ -61,23 +62,6 @@
|
|||||||
text: root.name
|
text: root.name
|
||||||
|
|
||||||
|
|
||||||
<FloatButton>
|
|
||||||
anchor_x: "right"
|
|
||||||
anchor_y: "bottom"
|
|
||||||
size_hint_y: None
|
|
||||||
height: dp(56)
|
|
||||||
padding: dp(10)
|
|
||||||
|
|
||||||
MDFloatingActionButton:
|
|
||||||
size_hint: None, None
|
|
||||||
size:dp(56), dp(56)
|
|
||||||
icon: root.icon
|
|
||||||
opposite_colors: True
|
|
||||||
elevation: 8
|
|
||||||
on_release: root.callback()
|
|
||||||
md_bg_color: root.md_bg_color
|
|
||||||
|
|
||||||
|
|
||||||
<MDFileManager>
|
<MDFileManager>
|
||||||
md_bg_color: root.theme_cls.bg_normal
|
md_bg_color: root.theme_cls.bg_normal
|
||||||
|
|
||||||
@ -90,7 +74,11 @@
|
|||||||
title: root.current_path
|
title: root.current_path
|
||||||
right_action_items: [["close-box", lambda x: root.exit_manager(1)]]
|
right_action_items: [["close-box", lambda x: root.exit_manager(1)]]
|
||||||
left_action_items: [["chevron-left", lambda x: root.back()]]
|
left_action_items: [["chevron-left", lambda x: root.back()]]
|
||||||
elevation: 10
|
elevation: 3
|
||||||
|
md_bg_color:
|
||||||
|
app.theme_cls.primary_color \
|
||||||
|
if not root.background_color_toolbar else \
|
||||||
|
root.background_color_toolbar
|
||||||
|
|
||||||
RecycleView:
|
RecycleView:
|
||||||
id: rv
|
id: rv
|
||||||
|
@ -9,7 +9,7 @@ Usage
|
|||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
path = '/' # path to the directory that will be opened in the file manager
|
path = os.path.expanduser("~") # path to the directory that will be opened in the file manager
|
||||||
file_manager = MDFileManager(
|
file_manager = MDFileManager(
|
||||||
exit_manager=self.exit_manager, # function called when the user reaches directory tree root
|
exit_manager=self.exit_manager, # function called when the user reaches directory tree root
|
||||||
select_path=self.select_path, # function called when selecting a file/directory
|
select_path=self.select_path, # function called when selecting a file/directory
|
||||||
@ -19,7 +19,7 @@ Usage
|
|||||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/file-manager.png
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/file-manager.png
|
||||||
:align: center
|
:align: center
|
||||||
|
|
||||||
.. warning:: Be careful! To use the `/` path on Android devices, you need
|
.. warning:: Be careful! To use the `'/'` path on Android devices, you need
|
||||||
special permissions. Therefore, you are likely to get an error.
|
special permissions. Therefore, you are likely to get an error.
|
||||||
|
|
||||||
Or with ``preview`` mode:
|
Or with ``preview`` mode:
|
||||||
@ -32,7 +32,7 @@ Or with ``preview`` mode:
|
|||||||
preview=True,
|
preview=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/file-manager-previous.png
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/file-manager-preview.png
|
||||||
:align: center
|
:align: center
|
||||||
|
|
||||||
.. warning:: The `preview` mode is intended only for viewing images and will
|
.. warning:: The `preview` mode is intended only for viewing images and will
|
||||||
@ -43,6 +43,8 @@ Example
|
|||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
from kivy.core.window import Window
|
from kivy.core.window import Window
|
||||||
from kivy.lang import Builder
|
from kivy.lang import Builder
|
||||||
|
|
||||||
@ -53,19 +55,19 @@ Example
|
|||||||
|
|
||||||
KV = '''
|
KV = '''
|
||||||
MDBoxLayout:
|
MDBoxLayout:
|
||||||
orientation: 'vertical'
|
orientation: "vertical"
|
||||||
|
|
||||||
MDTopAppBar:
|
MDTopAppBar:
|
||||||
title: "MDFileManager"
|
title: "MDFileManager"
|
||||||
left_action_items: [['menu', lambda x: None]]
|
left_action_items: [["menu", lambda x: None]]
|
||||||
elevation: 10
|
elevation: 3
|
||||||
|
|
||||||
MDFloatLayout:
|
MDFloatLayout:
|
||||||
|
|
||||||
MDRoundFlatIconButton:
|
MDRoundFlatIconButton:
|
||||||
text: "Open manager"
|
text: "Open manager"
|
||||||
icon: "folder"
|
icon: "folder"
|
||||||
pos_hint: {'center_x': .5, 'center_y': .6}
|
pos_hint: {"center_x": .5, "center_y": .5}
|
||||||
on_release: app.file_manager_open()
|
on_release: app.file_manager_open()
|
||||||
'''
|
'''
|
||||||
|
|
||||||
@ -76,23 +78,23 @@ Example
|
|||||||
Window.bind(on_keyboard=self.events)
|
Window.bind(on_keyboard=self.events)
|
||||||
self.manager_open = False
|
self.manager_open = False
|
||||||
self.file_manager = MDFileManager(
|
self.file_manager = MDFileManager(
|
||||||
exit_manager=self.exit_manager,
|
exit_manager=self.exit_manager, select_path=self.select_path
|
||||||
select_path=self.select_path,
|
|
||||||
preview=True,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def build(self):
|
def build(self):
|
||||||
|
self.theme_cls.theme_style = "Dark"
|
||||||
|
self.theme_cls.primary_palette = "Orange"
|
||||||
return Builder.load_string(KV)
|
return Builder.load_string(KV)
|
||||||
|
|
||||||
def file_manager_open(self):
|
def file_manager_open(self):
|
||||||
self.file_manager.show('/') # output manager to the screen
|
self.file_manager.show(os.path.expanduser("~")) # output manager to the screen
|
||||||
self.manager_open = True
|
self.manager_open = True
|
||||||
|
|
||||||
def select_path(self, path):
|
def select_path(self, path: str):
|
||||||
'''It will be called when you click on the file name
|
'''
|
||||||
|
It will be called when you click on the file name
|
||||||
or the catalog selection button.
|
or the catalog selection button.
|
||||||
|
|
||||||
:type path: str;
|
|
||||||
:param path: path to the selected directory or file;
|
:param path: path to the selected directory or file;
|
||||||
'''
|
'''
|
||||||
|
|
||||||
@ -126,6 +128,9 @@ Not tested on `iOS`.
|
|||||||
|
|
||||||
def file_manager_open(self):
|
def file_manager_open(self):
|
||||||
self.file_manager.show_disks()
|
self.file_manager.show_disks()
|
||||||
|
|
||||||
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/file-manager-show-disks.png
|
||||||
|
:align: center
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__all__ = ("MDFileManager",)
|
__all__ = ("MDFileManager",)
|
||||||
@ -136,6 +141,7 @@ import re
|
|||||||
from typing import List, Tuple, Union
|
from typing import List, Tuple, Union
|
||||||
|
|
||||||
from kivy import platform
|
from kivy import platform
|
||||||
|
from kivy.clock import Clock
|
||||||
from kivy.factory import Factory
|
from kivy.factory import Factory
|
||||||
from kivy.lang import Builder
|
from kivy.lang import Builder
|
||||||
from kivy.metrics import dp
|
from kivy.metrics import dp
|
||||||
@ -148,7 +154,6 @@ from kivy.properties import (
|
|||||||
OptionProperty,
|
OptionProperty,
|
||||||
StringProperty,
|
StringProperty,
|
||||||
)
|
)
|
||||||
from kivy.uix.anchorlayout import AnchorLayout
|
|
||||||
from kivy.uix.behaviors import ButtonBehavior
|
from kivy.uix.behaviors import ButtonBehavior
|
||||||
from kivy.uix.modalview import ModalView
|
from kivy.uix.modalview import ModalView
|
||||||
|
|
||||||
@ -156,6 +161,7 @@ from kivymd import images_path, uix_path
|
|||||||
from kivymd.theming import ThemableBehavior
|
from kivymd.theming import ThemableBehavior
|
||||||
from kivymd.uix.behaviors import CircularRippleBehavior
|
from kivymd.uix.behaviors import CircularRippleBehavior
|
||||||
from kivymd.uix.boxlayout import MDBoxLayout
|
from kivymd.uix.boxlayout import MDBoxLayout
|
||||||
|
from kivymd.uix.button import MDFloatingActionButton
|
||||||
from kivymd.uix.fitimage import FitImage
|
from kivymd.uix.fitimage import FitImage
|
||||||
from kivymd.uix.list import BaseListItem
|
from kivymd.uix.list import BaseListItem
|
||||||
from kivymd.uix.relativelayout import MDRelativeLayout
|
from kivymd.uix.relativelayout import MDRelativeLayout
|
||||||
@ -167,9 +173,7 @@ with open(
|
|||||||
|
|
||||||
|
|
||||||
class BodyManager(MDBoxLayout):
|
class BodyManager(MDBoxLayout):
|
||||||
"""
|
"""Base class for folders and files icons."""
|
||||||
Base class for folders and files icons.
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
class BodyManagerWithPreview(MDBoxLayout):
|
class BodyManagerWithPreview(MDBoxLayout):
|
||||||
@ -182,47 +186,146 @@ class IconButton(CircularRippleBehavior, ButtonBehavior, FitImage):
|
|||||||
"""Folder icons/thumbnails images in ``preview`` mode."""
|
"""Folder icons/thumbnails images in ``preview`` mode."""
|
||||||
|
|
||||||
|
|
||||||
class FloatButton(ThemableBehavior, AnchorLayout):
|
|
||||||
callback = ObjectProperty()
|
|
||||||
md_bg_color = ColorProperty([1, 1, 1, 1])
|
|
||||||
icon = StringProperty()
|
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
|
||||||
super().__init__(**kwargs)
|
|
||||||
self.theme_cls.bind(primary_palette=self.set_md_bg_color)
|
|
||||||
|
|
||||||
def set_md_bg_color(self, *args):
|
|
||||||
self.md_bg_color = self.theme_cls.primary_color
|
|
||||||
|
|
||||||
|
|
||||||
class ModifiedOneLineIconListItem(BaseListItem):
|
class ModifiedOneLineIconListItem(BaseListItem):
|
||||||
_txt_left_pad = NumericProperty("72dp")
|
_txt_left_pad = NumericProperty("72dp")
|
||||||
_txt_top_pad = NumericProperty("16dp")
|
_txt_top_pad = NumericProperty("16dp")
|
||||||
_txt_bot_pad = NumericProperty("15dp")
|
_txt_bot_pad = NumericProperty("15dp")
|
||||||
_num_lines = 1
|
_num_lines = 1
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super().__init__(**kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
self.height = dp(48)
|
self.height = dp(48)
|
||||||
|
|
||||||
|
|
||||||
class MDFileManager(ThemableBehavior, MDRelativeLayout):
|
class MDFileManager(MDRelativeLayout, ThemableBehavior):
|
||||||
icon = StringProperty("check")
|
|
||||||
"""
|
"""
|
||||||
The icon that will be used on the directory selection button.
|
Implements a modal dialog with a file manager.
|
||||||
|
|
||||||
|
For more information, see in the
|
||||||
|
:class:`~kivymd.uix.relativelayout.MDRelativeLayout` class documentation.
|
||||||
|
|
||||||
|
:Events:
|
||||||
|
`on_pre_open`:
|
||||||
|
Called before the MDFileManager is opened.
|
||||||
|
`on_open`:
|
||||||
|
Called when the MDFileManager is opened.
|
||||||
|
`on_pre_dismiss`:
|
||||||
|
Called before the MDFileManager is closed.
|
||||||
|
`on_dismiss`:
|
||||||
|
Called when the MDFileManager is closed.
|
||||||
|
"""
|
||||||
|
|
||||||
|
icon = StringProperty("check", deprecated=True)
|
||||||
|
"""
|
||||||
|
Icon that will be used on the directory selection button.
|
||||||
|
|
||||||
|
.. deprecated:: 1.1.0
|
||||||
|
Use :attr:`icon_selection_button` instead.
|
||||||
|
|
||||||
:attr:`icon` is an :class:`~kivy.properties.StringProperty`
|
:attr:`icon` is an :class:`~kivy.properties.StringProperty`
|
||||||
and defaults to `check`.
|
and defaults to `check`.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
icon_selection_button = StringProperty("check")
|
||||||
|
"""
|
||||||
|
Icon that will be used on the directory selection button.
|
||||||
|
|
||||||
|
.. versionadded:: 1.1.0
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
MDFileManager(
|
||||||
|
...
|
||||||
|
icon_selection_button="pencil",
|
||||||
|
)
|
||||||
|
|
||||||
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/file-manager-icon-selection-button.png
|
||||||
|
:align: center
|
||||||
|
|
||||||
|
:attr:`icon_selection_button` is an :class:`~kivy.properties.StringProperty`
|
||||||
|
and defaults to `check`.
|
||||||
|
"""
|
||||||
|
|
||||||
|
background_color_selection_button = ColorProperty(None)
|
||||||
|
"""
|
||||||
|
Background color of the current directory/path selection button.
|
||||||
|
|
||||||
|
.. versionadded:: 1.1.0
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
MDFileManager(
|
||||||
|
...
|
||||||
|
background_color_selection_button="brown",
|
||||||
|
)
|
||||||
|
|
||||||
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/file-manager-background-color-selection-button.png
|
||||||
|
:align: center
|
||||||
|
|
||||||
|
:attr:`background_color_selection_button` is an :class:`~kivy.properties.ColorProperty`
|
||||||
|
and defaults to `None`.
|
||||||
|
"""
|
||||||
|
|
||||||
|
background_color_toolbar = ColorProperty(None)
|
||||||
|
"""
|
||||||
|
Background color of the file manager toolbar.
|
||||||
|
|
||||||
|
.. versionadded:: 1.1.0
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
MDFileManager(
|
||||||
|
...
|
||||||
|
background_color_toolbar="brown",
|
||||||
|
)
|
||||||
|
|
||||||
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/file-manager-background-color-toolbar.png
|
||||||
|
:align: center
|
||||||
|
|
||||||
|
:attr:`background_color_toolbar` is an :class:`~kivy.properties.ColorProperty`
|
||||||
|
and defaults to `None`.
|
||||||
|
"""
|
||||||
|
|
||||||
icon_folder = StringProperty(f"{images_path}folder.png")
|
icon_folder = StringProperty(f"{images_path}folder.png")
|
||||||
"""
|
"""
|
||||||
The icon that will be used for folder icons when using ``preview = True``.
|
Icon that will be used for folder icons when using ``preview = True``.
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
MDFileManager(
|
||||||
|
...
|
||||||
|
preview=True,
|
||||||
|
icon_folder="path/to/icon.png",
|
||||||
|
)
|
||||||
|
|
||||||
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/file-manager-icon-folder.png
|
||||||
|
:align: center
|
||||||
|
|
||||||
:attr:`icon` is an :class:`~kivy.properties.StringProperty`
|
:attr:`icon` is an :class:`~kivy.properties.StringProperty`
|
||||||
and defaults to `check`.
|
and defaults to `check`.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
icon_color = ColorProperty(None)
|
||||||
|
"""
|
||||||
|
Color of the folder icon when the :attr:`preview` property is set to False.
|
||||||
|
|
||||||
|
.. versionadded:: 1.1.0
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
MDFileManager(
|
||||||
|
...
|
||||||
|
preview=False,
|
||||||
|
icon_color="brown",
|
||||||
|
)
|
||||||
|
|
||||||
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/file-manager-icon-color.png
|
||||||
|
:align: center
|
||||||
|
|
||||||
|
:attr:`icon_color` is an :class:`~kivy.properties.ColorProperty`
|
||||||
|
and defaults to `None`.
|
||||||
|
"""
|
||||||
|
|
||||||
exit_manager = ObjectProperty(lambda x: None)
|
exit_manager = ObjectProperty(lambda x: None)
|
||||||
"""
|
"""
|
||||||
Function called when the user reaches directory tree root.
|
Function called when the user reaches directory tree root.
|
||||||
@ -259,12 +362,12 @@ class MDFileManager(ThemableBehavior, MDRelativeLayout):
|
|||||||
and defaults to `all`.
|
and defaults to `all`.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
current_path = StringProperty(os.getcwd())
|
current_path = StringProperty(os.path.expanduser("~"))
|
||||||
"""
|
"""
|
||||||
Current directory.
|
Current directory.
|
||||||
|
|
||||||
:attr:`current_path` is an :class:`~kivy.properties.StringProperty`
|
:attr:`current_path` is an :class:`~kivy.properties.StringProperty`
|
||||||
and defaults to `/`.
|
and defaults to `os.path.expanduser("~")`.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
use_access = BooleanProperty(True)
|
use_access = BooleanProperty(True)
|
||||||
@ -295,9 +398,9 @@ class MDFileManager(ThemableBehavior, MDRelativeLayout):
|
|||||||
"name", options=["nothing", "name", "date", "size", "type"]
|
"name", options=["nothing", "name", "date", "size", "type"]
|
||||||
)
|
)
|
||||||
"""
|
"""
|
||||||
It can take the values 'nothing' 'name' 'date' 'size' 'type' - sorts files by option
|
It can take the values 'nothing' 'name' 'date' 'size' 'type' - sorts files
|
||||||
By default, sort by name.
|
by option. By default, sort by name. Available options are:
|
||||||
Available options are: `'nothing'`, `'name'`, `'date'`, `'size'`, `'type'`.
|
`'nothing'`, `'name'`, `'date'`, `'size'`, `'type'`.
|
||||||
|
|
||||||
:attr:`sort_by` is an :class:`~kivy.properties.OptionProperty`
|
:attr:`sort_by` is an :class:`~kivy.properties.OptionProperty`
|
||||||
and defaults to `name`.
|
and defaults to `name`.
|
||||||
@ -325,29 +428,33 @@ class MDFileManager(ThemableBehavior, MDRelativeLayout):
|
|||||||
"""
|
"""
|
||||||
Contains the list of files that are currently selected.
|
Contains the list of files that are currently selected.
|
||||||
|
|
||||||
:attr:`selection` is a read-only :class:`~kivy.properties.ListProperty` and
|
:attr:`selection` is a read-only :class:`~kivy.properties.ListProperty`
|
||||||
defaults to `[]`.
|
and defaults to `[]`.
|
||||||
|
"""
|
||||||
|
|
||||||
|
selection_button = ObjectProperty()
|
||||||
|
"""
|
||||||
|
The instance of the directory/path selection button.
|
||||||
|
|
||||||
|
.. versionadded:: 1.1.0
|
||||||
|
|
||||||
|
:attr:`selection_button` is a read-only :class:`~kivy.properties.ObjectProperty`
|
||||||
|
and defaults to `None`.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
_window_manager = None
|
_window_manager = None
|
||||||
_window_manager_open = False
|
_window_manager_open = False
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super().__init__(**kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
self.register_event_type("on_pre_open")
|
||||||
|
self.register_event_type("on_open")
|
||||||
|
self.register_event_type("on_pre_dismiss")
|
||||||
|
self.register_event_type("on_dismiss")
|
||||||
|
|
||||||
toolbar_label = self.ids.toolbar.children[1].children[0]
|
toolbar_label = self.ids.toolbar.children[1].children[0]
|
||||||
toolbar_label.font_style = "Subtitle1"
|
toolbar_label.font_style = "Subtitle1"
|
||||||
if (
|
Clock.schedule_once(self._create_selection_button)
|
||||||
self.selector == "any"
|
|
||||||
or self.selector == "multi"
|
|
||||||
or self.selector == "folder"
|
|
||||||
):
|
|
||||||
self.add_widget(
|
|
||||||
FloatButton(
|
|
||||||
callback=self.select_directory_on_press_button,
|
|
||||||
md_bg_color=self.theme_cls.primary_color,
|
|
||||||
icon=self.icon,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
if self.preview:
|
if self.preview:
|
||||||
self.ext = [".png", ".jpg", ".jpeg"]
|
self.ext = [".png", ".jpg", ".jpeg"]
|
||||||
@ -400,15 +507,7 @@ class MDFileManager(ThemableBehavior, MDRelativeLayout):
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
self.ids.rv.data = manager_list
|
self.ids.rv.data = manager_list
|
||||||
|
self._show()
|
||||||
if not self._window_manager:
|
|
||||||
self._window_manager = ModalView(
|
|
||||||
size_hint=self.size_hint, auto_dismiss=False
|
|
||||||
)
|
|
||||||
self._window_manager.add_widget(self)
|
|
||||||
if not self._window_manager_open:
|
|
||||||
self._window_manager.open()
|
|
||||||
self._window_manager_open = True
|
|
||||||
|
|
||||||
def show(self, path: str) -> None:
|
def show(self, path: str) -> None:
|
||||||
"""
|
"""
|
||||||
@ -474,6 +573,9 @@ class MDFileManager(ThemableBehavior, MDRelativeLayout):
|
|||||||
"icon": icon,
|
"icon": icon,
|
||||||
"dir_or_file_name": name,
|
"dir_or_file_name": name,
|
||||||
"events_callback": self.select_dir_or_file,
|
"events_callback": self.select_dir_or_file,
|
||||||
|
"icon_color": self.theme_cls.primary_color
|
||||||
|
if not self.icon_color
|
||||||
|
else self.icon_color,
|
||||||
"_selected": False,
|
"_selected": False,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@ -488,19 +590,14 @@ class MDFileManager(ThemableBehavior, MDRelativeLayout):
|
|||||||
"icon": "file-outline",
|
"icon": "file-outline",
|
||||||
"dir_or_file_name": os.path.split(name)[1],
|
"dir_or_file_name": os.path.split(name)[1],
|
||||||
"events_callback": self.select_dir_or_file,
|
"events_callback": self.select_dir_or_file,
|
||||||
|
"icon_color": self.theme_cls.primary_color
|
||||||
|
if not self.icon_color
|
||||||
|
else self.icon_color,
|
||||||
"_selected": False,
|
"_selected": False,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
self.ids.rv.data = manager_list
|
self.ids.rv.data = manager_list
|
||||||
|
self._show()
|
||||||
if not self._window_manager:
|
|
||||||
self._window_manager = ModalView(
|
|
||||||
size_hint=self.size_hint, auto_dismiss=False
|
|
||||||
)
|
|
||||||
self._window_manager.add_widget(self)
|
|
||||||
if not self._window_manager_open:
|
|
||||||
self._window_manager.open()
|
|
||||||
self._window_manager_open = True
|
|
||||||
|
|
||||||
def get_access_string(self, path: str) -> str:
|
def get_access_string(self, path: str) -> str:
|
||||||
access_string = ""
|
access_string = ""
|
||||||
@ -557,7 +654,9 @@ class MDFileManager(ThemableBehavior, MDRelativeLayout):
|
|||||||
def close(self) -> None:
|
def close(self) -> None:
|
||||||
"""Closes the file manager window."""
|
"""Closes the file manager window."""
|
||||||
|
|
||||||
|
self.dispatch("on_pre_dismiss")
|
||||||
self._window_manager.dismiss()
|
self._window_manager.dismiss()
|
||||||
|
self.dispatch("on_dismiss")
|
||||||
self._window_manager_open = False
|
self._window_manager_open = False
|
||||||
|
|
||||||
def select_dir_or_file(
|
def select_dir_or_file(
|
||||||
@ -609,6 +708,84 @@ class MDFileManager(ThemableBehavior, MDRelativeLayout):
|
|||||||
if self.selector == "folder" or self.selector == "any":
|
if self.selector == "folder" or self.selector == "any":
|
||||||
self.select_path(self.current_path)
|
self.select_path(self.current_path)
|
||||||
|
|
||||||
|
def on_icon(self, instance_file_manager, icon_name: str) -> None:
|
||||||
|
"""Called when the :attr:`icon` property is changed."""
|
||||||
|
|
||||||
|
self.icon_selection_button = icon_name
|
||||||
|
|
||||||
|
def on_background_color_toolbar(
|
||||||
|
self, instance_file_manager, color: Union[str, list]
|
||||||
|
) -> None:
|
||||||
|
"""
|
||||||
|
Called when the :attr:`background_color_toolbar` property is changed.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def on_background_color_toolbar(*args):
|
||||||
|
self.ids.toolbar.md_bg_color = color
|
||||||
|
|
||||||
|
Clock.schedule_once(on_background_color_toolbar)
|
||||||
|
|
||||||
|
def on_pre_open(self, *args):
|
||||||
|
"""
|
||||||
|
Default pre-open event handler.
|
||||||
|
|
||||||
|
.. versionadded:: 1.1.0
|
||||||
|
"""
|
||||||
|
|
||||||
|
def on_open(self, *args):
|
||||||
|
"""
|
||||||
|
Default open event handler.
|
||||||
|
|
||||||
|
.. versionadded:: 1.1.0
|
||||||
|
"""
|
||||||
|
|
||||||
|
def on_pre_dismiss(self, *args):
|
||||||
|
"""
|
||||||
|
Default pre-dismiss event handler.
|
||||||
|
|
||||||
|
.. versionadded:: 1.1.0
|
||||||
|
"""
|
||||||
|
|
||||||
|
def on_dismiss(self, *args):
|
||||||
|
"""
|
||||||
|
Default dismiss event handler.
|
||||||
|
|
||||||
|
.. versionadded:: 1.1.0
|
||||||
|
"""
|
||||||
|
|
||||||
|
def _show(self):
|
||||||
|
if not self._window_manager:
|
||||||
|
self._window_manager = ModalView(
|
||||||
|
size_hint=self.size_hint, auto_dismiss=False
|
||||||
|
)
|
||||||
|
self.size_hint = (1, 1)
|
||||||
|
self._window_manager.add_widget(self)
|
||||||
|
|
||||||
|
if not self._window_manager_open:
|
||||||
|
self._window_manager.open()
|
||||||
|
self._window_manager_open = True
|
||||||
|
|
||||||
|
self.dispatch("on_pre_open")
|
||||||
|
self.dispatch("on_open")
|
||||||
|
|
||||||
|
def _create_selection_button(self, *args):
|
||||||
|
if (
|
||||||
|
self.selector == "any"
|
||||||
|
or self.selector == "multi"
|
||||||
|
or self.selector == "folder"
|
||||||
|
):
|
||||||
|
self.selection_button = MDFloatingActionButton(
|
||||||
|
on_release=self.select_directory_on_press_button,
|
||||||
|
md_bg_color=self.theme_cls.primary_color
|
||||||
|
if not self.background_color_selection_button
|
||||||
|
else self.background_color_selection_button,
|
||||||
|
icon=self.icon_selection_button,
|
||||||
|
pos_hint={"right": 0.99},
|
||||||
|
y=dp(12),
|
||||||
|
elevation=0,
|
||||||
|
)
|
||||||
|
self.add_widget(self.selection_button)
|
||||||
|
|
||||||
def __sort_files(self, files):
|
def __sort_files(self, files):
|
||||||
def sort_by_name(files):
|
def sort_by_name(files):
|
||||||
files.sort(key=locale.strxfrm)
|
files.sort(key=locale.strxfrm)
|
||||||
|
@ -132,11 +132,11 @@ from kivy.properties import BooleanProperty, ObjectProperty
|
|||||||
from kivy.uix.image import AsyncImage
|
from kivy.uix.image import AsyncImage
|
||||||
from kivy.uix.widget import Widget
|
from kivy.uix.widget import Widget
|
||||||
|
|
||||||
|
from kivymd.uix.behaviors import StencilBehavior
|
||||||
from kivymd.uix.boxlayout import MDBoxLayout
|
from kivymd.uix.boxlayout import MDBoxLayout
|
||||||
from kivymd.uix.templates import StencilWidget
|
|
||||||
|
|
||||||
|
|
||||||
class FitImage(MDBoxLayout, StencilWidget):
|
class FitImage(MDBoxLayout, StencilBehavior):
|
||||||
source = ObjectProperty()
|
source = ObjectProperty()
|
||||||
"""
|
"""
|
||||||
Filename/source of your image.
|
Filename/source of your image.
|
||||||
|
@ -90,4 +90,7 @@ from kivymd.uix.behaviors import DeclarativeBehavior
|
|||||||
|
|
||||||
|
|
||||||
class MDGridLayout(DeclarativeBehavior, GridLayout, MDAdaptiveWidget):
|
class MDGridLayout(DeclarativeBehavior, GridLayout, MDAdaptiveWidget):
|
||||||
pass
|
"""
|
||||||
|
Grid layout class. For more information, see in the
|
||||||
|
:class:`~kivy.uix.gridlayout.GridLayout` class documentation.
|
||||||
|
"""
|
||||||
|
@ -63,7 +63,7 @@ Base example
|
|||||||
x: 24
|
x: 24
|
||||||
|
|
||||||
FitImage:
|
FitImage:
|
||||||
source: "https://github.com/kivymd/internal/raw/main/logo/kivymd_logo_blue.png"
|
source: "kivymd/images/logo/kivymd-icon-512.png"
|
||||||
size_hint: None, None
|
size_hint: None, None
|
||||||
size: hero_from.size
|
size: hero_from.size
|
||||||
|
|
||||||
@ -72,7 +72,7 @@ Base example
|
|||||||
pos_hint: {"center_x": .5}
|
pos_hint: {"center_x": .5}
|
||||||
y: "36dp"
|
y: "36dp"
|
||||||
on_release:
|
on_release:
|
||||||
root.current_hero = "hero"
|
root.current_heroes = ["hero"]
|
||||||
root.current = "screen B"
|
root.current = "screen B"
|
||||||
|
|
||||||
MDScreen:
|
MDScreen:
|
||||||
@ -82,6 +82,7 @@ Base example
|
|||||||
|
|
||||||
MDHeroTo:
|
MDHeroTo:
|
||||||
id: hero_to
|
id: hero_to
|
||||||
|
tag: "hero"
|
||||||
size_hint: None, None
|
size_hint: None, None
|
||||||
size: "220dp", "220dp"
|
size: "220dp", "220dp"
|
||||||
pos_hint: {"center_x": .5, "center_y": .5}
|
pos_hint: {"center_x": .5, "center_y": .5}
|
||||||
@ -91,7 +92,7 @@ Base example
|
|||||||
pos_hint: {"center_x": .5}
|
pos_hint: {"center_x": .5}
|
||||||
y: "36dp"
|
y: "36dp"
|
||||||
on_release:
|
on_release:
|
||||||
root.current_hero = "hero"
|
root.current_heroes = ["hero"]
|
||||||
root.current = "screen A"
|
root.current = "screen A"
|
||||||
'''
|
'''
|
||||||
|
|
||||||
@ -113,6 +114,7 @@ Note that the child of the :class:`~MDHeroFrom` widget must have the size of the
|
|||||||
|
|
||||||
MDHeroFrom:
|
MDHeroFrom:
|
||||||
id: hero_from
|
id: hero_from
|
||||||
|
tag: "hero"
|
||||||
|
|
||||||
FitImage:
|
FitImage:
|
||||||
size_hint: None, None
|
size_hint: None, None
|
||||||
@ -127,7 +129,7 @@ container in which the hero is located:
|
|||||||
MDRaisedButton:
|
MDRaisedButton:
|
||||||
text: "Move Hero To Screen B"
|
text: "Move Hero To Screen B"
|
||||||
on_release:
|
on_release:
|
||||||
root.current_hero = "hero"
|
root.current_heroes = ["hero"]
|
||||||
root.current = "screen 2"
|
root.current = "screen 2"
|
||||||
|
|
||||||
If you need to switch to a screen that does not contain heroes, set the
|
If you need to switch to a screen that does not contain heroes, set the
|
||||||
@ -138,7 +140,7 @@ If you need to switch to a screen that does not contain heroes, set the
|
|||||||
MDRaisedButton:
|
MDRaisedButton:
|
||||||
text: "Go To Another Screen"
|
text: "Go To Another Screen"
|
||||||
on_release:
|
on_release:
|
||||||
root.current_hero = ""
|
root.current_heroes = []
|
||||||
root.current = "another screen"
|
root.current = "another screen"
|
||||||
|
|
||||||
Example
|
Example
|
||||||
@ -166,7 +168,7 @@ Example
|
|||||||
x: 24
|
x: 24
|
||||||
|
|
||||||
FitImage:
|
FitImage:
|
||||||
source: "https://github.com/kivymd/internal/raw/main/logo/kivymd_logo_blue.png"
|
source: "kivymd/images/logo/kivymd-icon-512.png"
|
||||||
size_hint: None, None
|
size_hint: None, None
|
||||||
size: hero_from.size
|
size: hero_from.size
|
||||||
|
|
||||||
@ -175,7 +177,7 @@ Example
|
|||||||
pos_hint: {"center_x": .5}
|
pos_hint: {"center_x": .5}
|
||||||
y: "36dp"
|
y: "36dp"
|
||||||
on_release:
|
on_release:
|
||||||
root.current_hero = "hero"
|
root.current_heroes = ["hero"]
|
||||||
root.current = "screen B"
|
root.current = "screen B"
|
||||||
|
|
||||||
MDScreen:
|
MDScreen:
|
||||||
@ -185,6 +187,7 @@ Example
|
|||||||
|
|
||||||
MDHeroTo:
|
MDHeroTo:
|
||||||
id: hero_to
|
id: hero_to
|
||||||
|
tag: "hero"
|
||||||
size_hint: None, None
|
size_hint: None, None
|
||||||
size: "220dp", "220dp"
|
size: "220dp", "220dp"
|
||||||
pos_hint: {"center_x": .5, "center_y": .5}
|
pos_hint: {"center_x": .5, "center_y": .5}
|
||||||
@ -194,7 +197,7 @@ Example
|
|||||||
pos_hint: {"center_x": .5}
|
pos_hint: {"center_x": .5}
|
||||||
y: "52dp"
|
y: "52dp"
|
||||||
on_release:
|
on_release:
|
||||||
root.current_hero = ""
|
root.current_heroes = []
|
||||||
root.current = "screen C"
|
root.current = "screen C"
|
||||||
|
|
||||||
MDRaisedButton:
|
MDRaisedButton:
|
||||||
@ -202,7 +205,7 @@ Example
|
|||||||
pos_hint: {"center_x": .5}
|
pos_hint: {"center_x": .5}
|
||||||
y: "8dp"
|
y: "8dp"
|
||||||
on_release:
|
on_release:
|
||||||
root.current_hero = "hero"
|
root.current_heroes = ["hero"]
|
||||||
root.current = "screen A"
|
root.current = "screen A"
|
||||||
|
|
||||||
MDScreen:
|
MDScreen:
|
||||||
@ -283,7 +286,7 @@ background color of the hero during the flight between the screens:
|
|||||||
pos_hint: {"center_x": .5}
|
pos_hint: {"center_x": .5}
|
||||||
y: "36dp"
|
y: "36dp"
|
||||||
on_release:
|
on_release:
|
||||||
root.current_hero = "hero"
|
root.current_heroes = ["hero"]
|
||||||
root.current = "screen B"
|
root.current = "screen B"
|
||||||
|
|
||||||
MDScreen:
|
MDScreen:
|
||||||
@ -293,6 +296,7 @@ background color of the hero during the flight between the screens:
|
|||||||
|
|
||||||
MDHeroTo:
|
MDHeroTo:
|
||||||
id: hero_to
|
id: hero_to
|
||||||
|
tag: "hero"
|
||||||
size_hint: None, None
|
size_hint: None, None
|
||||||
size: "220dp", "220dp"
|
size: "220dp", "220dp"
|
||||||
pos_hint: {"center_x": .5, "center_y": .5}
|
pos_hint: {"center_x": .5, "center_y": .5}
|
||||||
@ -302,7 +306,7 @@ background color of the hero during the flight between the screens:
|
|||||||
pos_hint: {"center_x": .5}
|
pos_hint: {"center_x": .5}
|
||||||
y: "36dp"
|
y: "36dp"
|
||||||
on_release:
|
on_release:
|
||||||
root.current_hero = "hero"
|
root.current_heroes = ["hero"]
|
||||||
root.current = "screen A"
|
root.current = "screen A"
|
||||||
'''
|
'''
|
||||||
|
|
||||||
@ -370,7 +374,7 @@ Usage with ScrollView
|
|||||||
radius: 24
|
radius: 24
|
||||||
box_radius: 0, 0, 24, 24
|
box_radius: 0, 0, 24, 24
|
||||||
box_color: 0, 0, 0, .5
|
box_color: 0, 0, 0, .5
|
||||||
source: "image.jpg"
|
source: "kivymd/images/logo/kivymd-icon-512.png"
|
||||||
size_hint: None, None
|
size_hint: None, None
|
||||||
size: root.size
|
size: root.size
|
||||||
mipmap: True
|
mipmap: True
|
||||||
@ -399,7 +403,7 @@ Usage with ScrollView
|
|||||||
|
|
||||||
MDScreen:
|
MDScreen:
|
||||||
name: "screen B"
|
name: "screen B"
|
||||||
hero_to: hero_to
|
heroes_to: [hero_to]
|
||||||
|
|
||||||
MDHeroTo:
|
MDHeroTo:
|
||||||
id: hero_to
|
id: hero_to
|
||||||
@ -412,7 +416,7 @@ Usage with ScrollView
|
|||||||
pos_hint: {"center_x": .5}
|
pos_hint: {"center_x": .5}
|
||||||
y: "36dp"
|
y: "36dp"
|
||||||
on_release:
|
on_release:
|
||||||
root.current_hero = "hero"
|
root.current_heroes = [hero_to.tag]
|
||||||
root.current = "screen A"
|
root.current = "screen A"
|
||||||
'''
|
'''
|
||||||
|
|
||||||
@ -441,7 +445,8 @@ Usage with ScrollView
|
|||||||
|
|
||||||
def on_release(self):
|
def on_release(self):
|
||||||
def switch_screen(*args):
|
def switch_screen(*args):
|
||||||
self.manager.current_hero = self.tag
|
self.manager.current_heroes = [self.tag]
|
||||||
|
self.manager.ids.hero_to.tag = self.tag
|
||||||
self.manager.current = "screen B"
|
self.manager.current = "screen B"
|
||||||
|
|
||||||
Clock.schedule_once(switch_screen, 0.2)
|
Clock.schedule_once(switch_screen, 0.2)
|
||||||
@ -465,6 +470,93 @@ Usage with ScrollView
|
|||||||
|
|
||||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/hero-usage-with-scrollview.gif
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/hero-usage-with-scrollview.gif
|
||||||
:align: center
|
:align: center
|
||||||
|
|
||||||
|
Using multiple heroes at the same time
|
||||||
|
--------------------------------------
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from kivy.lang import Builder
|
||||||
|
|
||||||
|
from kivymd.app import MDApp
|
||||||
|
|
||||||
|
KV = '''
|
||||||
|
MDScreenManager:
|
||||||
|
|
||||||
|
MDScreen:
|
||||||
|
name: "screen A"
|
||||||
|
md_bg_color: "lightblue"
|
||||||
|
|
||||||
|
MDHeroFrom:
|
||||||
|
id: hero_kivymd
|
||||||
|
tag: "kivymd"
|
||||||
|
size_hint: None, None
|
||||||
|
size: "200dp", "200dp"
|
||||||
|
pos_hint: {"top": .98}
|
||||||
|
x: 24
|
||||||
|
|
||||||
|
FitImage:
|
||||||
|
source: "kivymd/images/logo/kivymd-icon-512.png"
|
||||||
|
size_hint: None, None
|
||||||
|
size: hero_kivymd.size
|
||||||
|
|
||||||
|
MDHeroFrom:
|
||||||
|
id: hero_kivy
|
||||||
|
tag: "kivy"
|
||||||
|
size_hint: None, None
|
||||||
|
size: "200dp", "200dp"
|
||||||
|
pos_hint: {"top": .98}
|
||||||
|
x: 324
|
||||||
|
|
||||||
|
FitImage:
|
||||||
|
source: "data/logo/kivy-icon-512.png"
|
||||||
|
size_hint: None, None
|
||||||
|
size: hero_kivy.size
|
||||||
|
|
||||||
|
MDRaisedButton:
|
||||||
|
text: "Move Hero To Screen B"
|
||||||
|
pos_hint: {"center_x": .5}
|
||||||
|
y: "36dp"
|
||||||
|
on_release:
|
||||||
|
root.current_heroes = ["kivymd", "kivy"]
|
||||||
|
root.current = "screen B"
|
||||||
|
|
||||||
|
MDScreen:
|
||||||
|
name: "screen B"
|
||||||
|
heroes_to: hero_to_kivymd, hero_to_kivy
|
||||||
|
md_bg_color: "cadetblue"
|
||||||
|
|
||||||
|
MDHeroTo:
|
||||||
|
id: hero_to_kivy
|
||||||
|
tag: "kivy"
|
||||||
|
size_hint: None, None
|
||||||
|
pos_hint: {"center_x": .5, "center_y": .5}
|
||||||
|
|
||||||
|
MDHeroTo:
|
||||||
|
id: hero_to_kivymd
|
||||||
|
tag: "kivymd"
|
||||||
|
size_hint: None, None
|
||||||
|
pos_hint: {"right": 1, "top": 1}
|
||||||
|
|
||||||
|
MDRaisedButton:
|
||||||
|
text: "Move Hero To Screen A"
|
||||||
|
pos_hint: {"center_x": .5}
|
||||||
|
y: "36dp"
|
||||||
|
on_release:
|
||||||
|
root.current_heroes = ["kivy", "kivymd"]
|
||||||
|
root.current = "screen A"
|
||||||
|
'''
|
||||||
|
|
||||||
|
|
||||||
|
class Test(MDApp):
|
||||||
|
def build(self):
|
||||||
|
return Builder.load_string(KV)
|
||||||
|
|
||||||
|
|
||||||
|
Test().run()
|
||||||
|
|
||||||
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/hero-multiple-heroes.gif
|
||||||
|
:align: center
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from kivy.properties import StringProperty
|
from kivy.properties import StringProperty
|
||||||
@ -476,6 +568,9 @@ class MDHeroFrom(MDBoxLayout):
|
|||||||
"""
|
"""
|
||||||
The container from which the hero begins his flight.
|
The container from which the hero begins his flight.
|
||||||
|
|
||||||
|
For more information, see in the
|
||||||
|
:class:`~kivymd.uix.boxlayout.MDBoxLayout` class documentation.
|
||||||
|
|
||||||
:Events:
|
:Events:
|
||||||
`on_transform_in`
|
`on_transform_in`
|
||||||
when the hero flies from screen **A** to screen **B**.
|
when the hero flies from screen **A** to screen **B**.
|
||||||
@ -487,7 +582,7 @@ class MDHeroFrom(MDBoxLayout):
|
|||||||
"""
|
"""
|
||||||
Tag ID for heroes.
|
Tag ID for heroes.
|
||||||
|
|
||||||
:attr:`shift_right` is an :class:`~kivy.properties.StringProperty`
|
:attr:`tag` is an :class:`~kivy.properties.StringProperty`
|
||||||
and defaults to `''`.
|
and defaults to `''`.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@ -504,4 +599,17 @@ class MDHeroFrom(MDBoxLayout):
|
|||||||
|
|
||||||
|
|
||||||
class MDHeroTo(MDBoxLayout):
|
class MDHeroTo(MDBoxLayout):
|
||||||
"""The container in which the hero comes."""
|
"""
|
||||||
|
The container in which the hero comes.
|
||||||
|
|
||||||
|
For more information, see in the
|
||||||
|
:class:`~kivymd.uix.boxlayout.MDBoxLayout` class documentation.
|
||||||
|
"""
|
||||||
|
|
||||||
|
tag = StringProperty(allownone=True)
|
||||||
|
"""
|
||||||
|
Tag ID for heroes.
|
||||||
|
|
||||||
|
:attr:`tag` is an :class:`~kivy.properties.StringProperty`
|
||||||
|
and defaults to `''`.
|
||||||
|
"""
|
||||||
|
@ -65,12 +65,13 @@ Implementation
|
|||||||
:align: center
|
:align: center
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__all__ = "MDSmartTile"
|
__all__ = [
|
||||||
|
"MDSmartTile",
|
||||||
|
]
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from kivy.lang import Builder
|
from kivy.lang import Builder
|
||||||
from kivy.logger import Logger
|
|
||||||
from kivy.properties import (
|
from kivy.properties import (
|
||||||
BooleanProperty,
|
BooleanProperty,
|
||||||
ColorProperty,
|
ColorProperty,
|
||||||
|
@ -17,8 +17,14 @@
|
|||||||
rgba: (1, 1, 1, 1) if self.source else (0, 0, 0, 0)
|
rgba: (1, 1, 1, 1) if self.source else (0, 0, 0, 0)
|
||||||
Rectangle:
|
Rectangle:
|
||||||
source: self.source if self.source else None
|
source: self.source if self.source else None
|
||||||
pos: self.pos
|
pos:
|
||||||
size: self.size
|
self.pos \
|
||||||
|
if not self.source else \
|
||||||
|
(self.x - self._size[0] / 2, self.y)
|
||||||
|
size:
|
||||||
|
self._size \
|
||||||
|
if self.source else \
|
||||||
|
self.size
|
||||||
|
|
||||||
font_style: "Icon"
|
font_style: "Icon"
|
||||||
text: u"{}".format(md_icons[root.icon]) if root.icon in md_icons else "blank"
|
text: u"{}".format(md_icons[root.icon]) if root.icon in md_icons else "blank"
|
||||||
|
@ -222,14 +222,18 @@ __all__ = ("MDLabel", "MDIcon")
|
|||||||
import os
|
import os
|
||||||
from typing import Union
|
from typing import Union
|
||||||
|
|
||||||
|
from kivy.animation import Animation
|
||||||
from kivy.clock import Clock
|
from kivy.clock import Clock
|
||||||
|
from kivy.graphics import Color, Rectangle
|
||||||
from kivy.lang import Builder
|
from kivy.lang import Builder
|
||||||
from kivy.metrics import sp
|
from kivy.metrics import sp
|
||||||
from kivy.properties import (
|
from kivy.properties import (
|
||||||
AliasProperty,
|
AliasProperty,
|
||||||
BooleanProperty,
|
BooleanProperty,
|
||||||
ColorProperty,
|
ColorProperty,
|
||||||
|
ListProperty,
|
||||||
NumericProperty,
|
NumericProperty,
|
||||||
|
ObjectProperty,
|
||||||
OptionProperty,
|
OptionProperty,
|
||||||
StringProperty,
|
StringProperty,
|
||||||
)
|
)
|
||||||
@ -322,6 +326,7 @@ class MDLabel(DeclarativeBehavior, ThemableBehavior, Label, MDAdaptiveWidget):
|
|||||||
|
|
||||||
parent_background = ColorProperty(None)
|
parent_background = ColorProperty(None)
|
||||||
can_capitalize = BooleanProperty(True)
|
can_capitalize = BooleanProperty(True)
|
||||||
|
canvas_bg = ObjectProperty()
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
super().__init__(**kwargs)
|
super().__init__(**kwargs)
|
||||||
@ -349,6 +354,7 @@ class MDLabel(DeclarativeBehavior, ThemableBehavior, Label, MDAdaptiveWidget):
|
|||||||
font_info = self.theme_cls.font_styles[self.font_style]
|
font_info = self.theme_cls.font_styles[self.font_style]
|
||||||
self.font_name = font_info[0]
|
self.font_name = font_info[0]
|
||||||
self.font_size = sp(font_info[1])
|
self.font_size = sp(font_info[1])
|
||||||
|
|
||||||
if font_info[2] and self.can_capitalize:
|
if font_info[2] and self.can_capitalize:
|
||||||
self._capitalizing = True
|
self._capitalizing = True
|
||||||
else:
|
else:
|
||||||
@ -374,29 +380,68 @@ class MDLabel(DeclarativeBehavior, ThemableBehavior, Label, MDAdaptiveWidget):
|
|||||||
# generic None value it's not yet been set
|
# generic None value it's not yet been set
|
||||||
self._text_color_str = ""
|
self._text_color_str = ""
|
||||||
if theme_text_color == "Custom" and self.text_color:
|
if theme_text_color == "Custom" and self.text_color:
|
||||||
self.color = self.text_color
|
color = self.text_color
|
||||||
elif (
|
elif (
|
||||||
theme_text_color == "ContrastParentBackground"
|
theme_text_color == "ContrastParentBackground"
|
||||||
and self.parent_background
|
and self.parent_background
|
||||||
):
|
):
|
||||||
self.color = get_contrast_text_color(self.parent_background)
|
color = get_contrast_text_color(self.parent_background)
|
||||||
else:
|
else:
|
||||||
self.color = [0, 0, 0, 1]
|
color = [0, 0, 0, 1]
|
||||||
|
|
||||||
def on_text_color(self, instance_label, color: list) -> None:
|
if self.theme_cls.theme_style_switch_animation:
|
||||||
|
Animation(
|
||||||
|
color=color,
|
||||||
|
d=self.theme_cls.theme_style_switch_animation_duration,
|
||||||
|
t="linear",
|
||||||
|
).start(self)
|
||||||
|
else:
|
||||||
|
self.color = color
|
||||||
|
|
||||||
|
def on_text_color(self, instance_label, color: Union[list, str]) -> None:
|
||||||
if self.theme_text_color == "Custom":
|
if self.theme_text_color == "Custom":
|
||||||
|
if self.theme_cls.theme_style_switch_animation:
|
||||||
|
Animation(
|
||||||
|
color=self.text_color,
|
||||||
|
d=self.theme_cls.theme_style_switch_animation_duration,
|
||||||
|
t="linear",
|
||||||
|
).start(self)
|
||||||
|
else:
|
||||||
self.color = self.text_color
|
self.color = self.text_color
|
||||||
|
|
||||||
def on_opposite_colors(self, *args) -> None:
|
def on_opposite_colors(self, *args) -> None:
|
||||||
self.on_theme_text_color(self, self.theme_text_color)
|
self.on_theme_text_color(self, self.theme_text_color)
|
||||||
|
|
||||||
|
def on_md_bg_color(self, instance_label, color: Union[list, str]) -> None:
|
||||||
|
self.canvas.remove_group("Background_instruction")
|
||||||
|
with self.canvas.before:
|
||||||
|
Color(rgba=color)
|
||||||
|
self.canvas_bg = Rectangle(pos=self.pos, size=self.size)
|
||||||
|
self.bind(pos=self.update_canvas_bg_pos)
|
||||||
|
|
||||||
|
def on_size(self, instance_label, size: list) -> None:
|
||||||
|
if self.canvas_bg:
|
||||||
|
self.canvas_bg.size = size
|
||||||
|
|
||||||
|
def update_canvas_bg_pos(self, instance_label, pos: list) -> None:
|
||||||
|
if self.canvas_bg:
|
||||||
|
self.canvas_bg.pos = pos
|
||||||
|
|
||||||
def _do_update_theme_color(self, *args):
|
def _do_update_theme_color(self, *args):
|
||||||
if self._text_color_str:
|
if self._text_color_str:
|
||||||
self.color = getattr(self.theme_cls, self._text_color_str)
|
|
||||||
if not self.disabled:
|
if not self.disabled:
|
||||||
self.color = getattr(self.theme_cls, self._text_color_str)
|
color = getattr(self.theme_cls, self._text_color_str)
|
||||||
else:
|
else:
|
||||||
self.color = getattr(self.theme_cls, "disabled_hint_text_color")
|
color = getattr(self.theme_cls, "disabled_hint_text_color")
|
||||||
|
|
||||||
|
if self.theme_cls.theme_style_switch_animation:
|
||||||
|
Animation(
|
||||||
|
color=color,
|
||||||
|
d=self.theme_cls.theme_style_switch_animation_duration,
|
||||||
|
t="linear",
|
||||||
|
).start(self)
|
||||||
|
else:
|
||||||
|
self.color = color
|
||||||
|
|
||||||
|
|
||||||
class MDIcon(MDFloatLayout, MDLabel):
|
class MDIcon(MDFloatLayout, MDLabel):
|
||||||
@ -456,11 +501,16 @@ class MDIcon(MDFloatLayout, MDLabel):
|
|||||||
and defaults to `None`.
|
and defaults to `None`.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
_size = ListProperty((0, 0))
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
Clock.schedule_once(self.adjust_size)
|
||||||
|
|
||||||
|
def adjust_size(self, *args) -> None:
|
||||||
from kivymd.uix.selectioncontrol import MDCheckbox
|
from kivymd.uix.selectioncontrol import MDCheckbox
|
||||||
|
|
||||||
super().__init__(**kwargs)
|
|
||||||
if not isinstance(self, MDCheckbox):
|
if not isinstance(self, MDCheckbox):
|
||||||
self.size_hint = (None, None)
|
self.size_hint = (None, None)
|
||||||
self.size = self.texture_size
|
self._size = self.texture_size[1], self.texture_size[1]
|
||||||
self.adaptive_size = True
|
self.adaptive_size = True
|
||||||
|
@ -57,6 +57,7 @@ based on the above classes.
|
|||||||
- OneLineAvatarListItem_
|
- OneLineAvatarListItem_
|
||||||
- TwoLineAvatarListItem_
|
- TwoLineAvatarListItem_
|
||||||
- ThreeLineAvatarListItem_
|
- ThreeLineAvatarListItem_
|
||||||
|
|
||||||
- OneLineIconListItem_
|
- OneLineIconListItem_
|
||||||
- TwoLineIconListItem_
|
- TwoLineIconListItem_
|
||||||
- ThreeLineIconListItem_
|
- ThreeLineIconListItem_
|
||||||
@ -68,9 +69,17 @@ based on the above classes.
|
|||||||
- TwoLineAvatarIconListItem_
|
- TwoLineAvatarIconListItem_
|
||||||
- ThreeLineAvatarIconListItem_
|
- ThreeLineAvatarIconListItem_
|
||||||
|
|
||||||
|
- OneLineRightIconListItem_
|
||||||
|
- TwoLineRightIconListItem_
|
||||||
|
- ThreeLineRightIconListItem_
|
||||||
|
|
||||||
Usage
|
Usage
|
||||||
-----
|
-----
|
||||||
|
|
||||||
|
.. tabs::
|
||||||
|
|
||||||
|
.. tab:: Declarative KV style
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
from kivy.lang import Builder
|
from kivy.lang import Builder
|
||||||
@ -79,15 +88,16 @@ Usage
|
|||||||
from kivymd.uix.list import OneLineListItem
|
from kivymd.uix.list import OneLineListItem
|
||||||
|
|
||||||
KV = '''
|
KV = '''
|
||||||
ScrollView:
|
MDScrollView:
|
||||||
|
|
||||||
MDList:
|
MDList:
|
||||||
id: container
|
id: container
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
|
||||||
class Test(MDApp):
|
class Example(MDApp):
|
||||||
def build(self):
|
def build(self):
|
||||||
|
self.theme_cls.theme_style = "Dark"
|
||||||
return Builder.load_string(KV)
|
return Builder.load_string(KV)
|
||||||
|
|
||||||
def on_start(self):
|
def on_start(self):
|
||||||
@ -96,7 +106,34 @@ Usage
|
|||||||
OneLineListItem(text=f"Single-line item {i}")
|
OneLineListItem(text=f"Single-line item {i}")
|
||||||
)
|
)
|
||||||
|
|
||||||
Test().run()
|
Example().run()
|
||||||
|
|
||||||
|
.. tab:: Declarative python style
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from kivymd.app import MDApp
|
||||||
|
from kivymd.uix.list import OneLineListItem
|
||||||
|
|
||||||
|
|
||||||
|
class Example(MDApp):
|
||||||
|
def build(self):
|
||||||
|
self.theme_cls.theme_style = "Dark"
|
||||||
|
return (
|
||||||
|
MDScrollView(
|
||||||
|
MDList(
|
||||||
|
id="container"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
def on_start(self):
|
||||||
|
for i in range(20):
|
||||||
|
self.root.ids.container.add_widget(
|
||||||
|
OneLineListItem(text=f"Single-line item {i}")
|
||||||
|
)
|
||||||
|
|
||||||
|
Example().run()
|
||||||
|
|
||||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/lists.gif
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/lists.gif
|
||||||
:align: center
|
:align: center
|
||||||
@ -104,6 +141,10 @@ Usage
|
|||||||
Events of List
|
Events of List
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
|
.. tabs::
|
||||||
|
|
||||||
|
.. tab:: Declarative KV style
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
from kivy.lang import Builder
|
from kivy.lang import Builder
|
||||||
@ -111,7 +152,7 @@ Events of List
|
|||||||
from kivymd.app import MDApp
|
from kivymd.app import MDApp
|
||||||
|
|
||||||
KV = '''
|
KV = '''
|
||||||
ScrollView:
|
MDScrollView:
|
||||||
|
|
||||||
MDList:
|
MDList:
|
||||||
|
|
||||||
@ -129,12 +170,47 @@ Events of List
|
|||||||
'''
|
'''
|
||||||
|
|
||||||
|
|
||||||
class MainApp(MDApp):
|
class Example(MDApp):
|
||||||
def build(self):
|
def build(self):
|
||||||
|
self.theme_cls.theme_style = "Dark"
|
||||||
return Builder.load_string(KV)
|
return Builder.load_string(KV)
|
||||||
|
|
||||||
|
|
||||||
MainApp().run()
|
Example().run()
|
||||||
|
|
||||||
|
.. tab:: Declarative python style
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from kivymd.app import MDApp
|
||||||
|
from kivymd.uix.scrollview import MDScrollView
|
||||||
|
from kivymd.uix.list import MDList, OneLineAvatarIconListItem, IconLeftWidget
|
||||||
|
|
||||||
|
|
||||||
|
class Example(MDApp):
|
||||||
|
def build(self):
|
||||||
|
self.theme_cls.theme_style = "Dark"
|
||||||
|
return (
|
||||||
|
MDScrollView(
|
||||||
|
MDList(
|
||||||
|
OneLineAvatarIconListItem(
|
||||||
|
IconLeftWidget(
|
||||||
|
icon="github"
|
||||||
|
),
|
||||||
|
on_release=lambda x: print("Click!")
|
||||||
|
),
|
||||||
|
OneLineAvatarIconListItem(
|
||||||
|
IconLeftWidget(
|
||||||
|
icon="gitlab"
|
||||||
|
),
|
||||||
|
on_release=lambda x: print("Click 2!")
|
||||||
|
),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
Example().run()
|
||||||
|
|
||||||
.. OneLineListItem:
|
.. OneLineListItem:
|
||||||
OneLineListItem
|
OneLineListItem
|
||||||
@ -179,21 +255,40 @@ ThreeLineListItem
|
|||||||
OneLineAvatarListItem
|
OneLineAvatarListItem
|
||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
|
.. tabs::
|
||||||
|
|
||||||
|
.. tab:: Declarative KV style
|
||||||
|
|
||||||
.. code-block:: kv
|
.. code-block:: kv
|
||||||
|
|
||||||
OneLineAvatarListItem:
|
OneLineAvatarListItem:
|
||||||
text: "Single-line item with avatar"
|
text: "Single-line item with avatar"
|
||||||
|
|
||||||
ImageLeftWidget:
|
ImageLeftWidget:
|
||||||
source: "data/logo/kivy-icon-256.png"
|
source: "kivymd/images/logo/kivymd-icon-256.png"
|
||||||
|
|
||||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/lists-map.png
|
.. tab:: Declarative python style
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
OneLineAvatarListItem(
|
||||||
|
ImageLeftWidget(
|
||||||
|
source="kivymd/images/logo/kivymd-icon-256.png"
|
||||||
|
),
|
||||||
|
text="Single-line item with avatar",
|
||||||
|
)
|
||||||
|
|
||||||
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/OneLineAvatarListItem.png
|
||||||
:align: center
|
:align: center
|
||||||
|
|
||||||
.. TwoLineAvatarListItem:
|
.. TwoLineAvatarListItem:
|
||||||
TwoLineAvatarListItem
|
TwoLineAvatarListItem
|
||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
|
.. tabs::
|
||||||
|
|
||||||
|
.. tab:: Declarative KV style
|
||||||
|
|
||||||
.. code-block:: kv
|
.. code-block:: kv
|
||||||
|
|
||||||
TwoLineAvatarListItem:
|
TwoLineAvatarListItem:
|
||||||
@ -201,16 +296,31 @@ TwoLineAvatarListItem
|
|||||||
secondary_text: "Secondary text here"
|
secondary_text: "Secondary text here"
|
||||||
|
|
||||||
ImageLeftWidget:
|
ImageLeftWidget:
|
||||||
source: "data/logo/kivy-icon-256.png"
|
source: "kivymd/images/logo/kivymd-icon-256.png"
|
||||||
|
|
||||||
|
.. tab:: Declarative python style
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
OneLineAvatarListItem(
|
||||||
|
ImageLeftWidget(
|
||||||
|
source="kivymd/images/logo/kivymd-icon-256.png"
|
||||||
|
),
|
||||||
|
text="Single-line item with avatar",
|
||||||
|
secondary_text: "Secondary text here",
|
||||||
|
)
|
||||||
|
|
||||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/TwoLineAvatarListItem.png
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/TwoLineAvatarListItem.png
|
||||||
:align: center
|
:align: center
|
||||||
|
|
||||||
|
|
||||||
.. ThreeLineAvatarListItem:
|
.. ThreeLineAvatarListItem:
|
||||||
ThreeLineAvatarListItem
|
ThreeLineAvatarListItem
|
||||||
-----------------------
|
-----------------------
|
||||||
|
|
||||||
|
.. tabs::
|
||||||
|
|
||||||
|
.. tab:: Declarative KV style
|
||||||
|
|
||||||
.. code-block:: kv
|
.. code-block:: kv
|
||||||
|
|
||||||
ThreeLineAvatarListItem:
|
ThreeLineAvatarListItem:
|
||||||
@ -219,15 +329,128 @@ ThreeLineAvatarListItem
|
|||||||
tertiary_text: "fit more text than usual"
|
tertiary_text: "fit more text than usual"
|
||||||
|
|
||||||
ImageLeftWidget:
|
ImageLeftWidget:
|
||||||
source: "data/logo/kivy-icon-256.png"
|
source: "kivymd/images/logo/kivymd-icon-256.png"
|
||||||
|
|
||||||
|
.. tab:: Declarative python style
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
OneLineAvatarListItem(
|
||||||
|
ImageLeftWidget(
|
||||||
|
source="kivymd/images/logo/kivymd-icon-256.png"
|
||||||
|
),
|
||||||
|
text="Single-line item with avatar",
|
||||||
|
secondary_text: "Secondary text here",
|
||||||
|
tertiary_text: "fit more text than usual"
|
||||||
|
)
|
||||||
|
|
||||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/ThreeLineAvatarListItem.png
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/ThreeLineAvatarListItem.png
|
||||||
:align: center
|
:align: center
|
||||||
|
|
||||||
|
.. OneLineRightIconListItem:
|
||||||
|
OneLineRightIconListItem
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
.. tabs::
|
||||||
|
|
||||||
|
.. tab:: Declarative KV style
|
||||||
|
|
||||||
|
.. code-block:: kv
|
||||||
|
|
||||||
|
OneLineRightIconListItem:
|
||||||
|
text: "Single-line item with avatar"
|
||||||
|
|
||||||
|
ImageRightWidget:
|
||||||
|
source: "kivymd/images/logo/kivymd-icon-256.png"
|
||||||
|
|
||||||
|
.. tab:: Declarative python style
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
OneLineRightIconListItem(
|
||||||
|
ImageRightWidget(
|
||||||
|
source="kivymd/images/logo/kivymd-icon-256.png"
|
||||||
|
),
|
||||||
|
text="Single-line item with avatar",
|
||||||
|
)
|
||||||
|
|
||||||
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/OneLineRightIconListItem.png
|
||||||
|
:align: center
|
||||||
|
|
||||||
|
.. TwoLineRightIconListItem:
|
||||||
|
TwoLineRightIconListItem
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
.. tabs::
|
||||||
|
|
||||||
|
.. tab:: Declarative KV style
|
||||||
|
|
||||||
|
.. code-block:: kv
|
||||||
|
|
||||||
|
TwoLineRightIconListItem:
|
||||||
|
text: "Single-line item with avatar"
|
||||||
|
secondary_text: "Secondary text here"
|
||||||
|
|
||||||
|
ImageRightWidget:
|
||||||
|
source: "kivymd/images/logo/kivymd-icon-256.png"
|
||||||
|
|
||||||
|
.. tab:: Declarative python style
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
TwoLineRightIconListItem(
|
||||||
|
ImageRightWidget(
|
||||||
|
source="kivymd/images/logo/kivymd-icon-256.png"
|
||||||
|
),
|
||||||
|
text="Single-line item with avatar",
|
||||||
|
secondary_text: "Secondary text here",
|
||||||
|
)
|
||||||
|
|
||||||
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/TwoLineRightIconListItem.png
|
||||||
|
:align: center
|
||||||
|
|
||||||
|
.. ThreeLineRightIconListItem:
|
||||||
|
ThreeLineRightIconListItem
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
.. tabs::
|
||||||
|
|
||||||
|
.. tab:: Declarative KV style
|
||||||
|
|
||||||
|
.. code-block:: kv
|
||||||
|
|
||||||
|
ThreeLineRightIconListItem:
|
||||||
|
text: "Single-line item with avatar"
|
||||||
|
secondary_text: "Secondary text here"
|
||||||
|
tertiary_text: "fit more text than usual"
|
||||||
|
|
||||||
|
ImageRightWidget:
|
||||||
|
source: "kivymd/images/logo/kivymd-icon-256.png"
|
||||||
|
|
||||||
|
.. tab:: Declarative python style
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
ThreeLineRightIconListItem(
|
||||||
|
ImageRightWidget(
|
||||||
|
source="kivymd/images/logo/kivymd-icon-256.png"
|
||||||
|
),
|
||||||
|
text="Single-line item with avatar",
|
||||||
|
secondary_text: "Secondary text here",
|
||||||
|
tertiary_text: "fit more text than usual",
|
||||||
|
)
|
||||||
|
|
||||||
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/ThreeLineRightIconListItem.png
|
||||||
|
:align: center
|
||||||
|
|
||||||
.. OneLineIconListItem:
|
.. OneLineIconListItem:
|
||||||
OneLineIconListItem
|
OneLineIconListItem
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
|
.. tabs::
|
||||||
|
|
||||||
|
.. tab:: Declarative KV style
|
||||||
|
|
||||||
.. code-block:: kv
|
.. code-block:: kv
|
||||||
|
|
||||||
OneLineIconListItem:
|
OneLineIconListItem:
|
||||||
@ -236,6 +459,17 @@ OneLineIconListItem
|
|||||||
IconLeftWidget:
|
IconLeftWidget:
|
||||||
icon: "language-python"
|
icon: "language-python"
|
||||||
|
|
||||||
|
.. tab:: Declarative python style
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
OneLineIconListItem(
|
||||||
|
IconLeftWidget(
|
||||||
|
icon="language-python"
|
||||||
|
),
|
||||||
|
text="Single-line item with avatar"
|
||||||
|
)
|
||||||
|
|
||||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/OneLineIconListItem.png
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/OneLineIconListItem.png
|
||||||
:align: center
|
:align: center
|
||||||
|
|
||||||
@ -243,6 +477,10 @@ OneLineIconListItem
|
|||||||
TwoLineIconListItem
|
TwoLineIconListItem
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
|
.. tabs::
|
||||||
|
|
||||||
|
.. tab:: Declarative KV style
|
||||||
|
|
||||||
.. code-block:: kv
|
.. code-block:: kv
|
||||||
|
|
||||||
TwoLineIconListItem:
|
TwoLineIconListItem:
|
||||||
@ -252,6 +490,18 @@ TwoLineIconListItem
|
|||||||
IconLeftWidget:
|
IconLeftWidget:
|
||||||
icon: "language-python"
|
icon: "language-python"
|
||||||
|
|
||||||
|
.. tab:: Declarative python style
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
TwoLineIconListItem(
|
||||||
|
IconLeftWidget(
|
||||||
|
icon="language-python"
|
||||||
|
),
|
||||||
|
text="Single-line item with avatar",
|
||||||
|
secondary_text: "Secondary text here"
|
||||||
|
)
|
||||||
|
|
||||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/TwoLineIconListItem.png
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/TwoLineIconListItem.png
|
||||||
:align: center
|
:align: center
|
||||||
|
|
||||||
@ -259,6 +509,10 @@ TwoLineIconListItem
|
|||||||
ThreeLineIconListItem
|
ThreeLineIconListItem
|
||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
|
.. tabs::
|
||||||
|
|
||||||
|
.. tab:: Declarative KV style
|
||||||
|
|
||||||
.. code-block:: kv
|
.. code-block:: kv
|
||||||
|
|
||||||
ThreeLineIconListItem:
|
ThreeLineIconListItem:
|
||||||
@ -269,6 +523,19 @@ ThreeLineIconListItem
|
|||||||
IconLeftWidget:
|
IconLeftWidget:
|
||||||
icon: "language-python"
|
icon: "language-python"
|
||||||
|
|
||||||
|
.. tab:: Declarative python style
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
ThreeLineIconListItem(
|
||||||
|
IconLeftWidget(
|
||||||
|
icon="language-python"
|
||||||
|
),
|
||||||
|
text="Single-line item with avatar",
|
||||||
|
secondary_text: "Secondary text here",
|
||||||
|
tertiary_text: "fit more text than usual",
|
||||||
|
)
|
||||||
|
|
||||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/ThreeLineIconListItem.png
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/ThreeLineIconListItem.png
|
||||||
:align: center
|
:align: center
|
||||||
|
|
||||||
@ -276,6 +543,10 @@ ThreeLineIconListItem
|
|||||||
OneLineAvatarIconListItem
|
OneLineAvatarIconListItem
|
||||||
-------------------------
|
-------------------------
|
||||||
|
|
||||||
|
.. tabs::
|
||||||
|
|
||||||
|
.. tab:: Declarative KV style
|
||||||
|
|
||||||
.. code-block:: kv
|
.. code-block:: kv
|
||||||
|
|
||||||
OneLineAvatarIconListItem:
|
OneLineAvatarIconListItem:
|
||||||
@ -287,6 +558,20 @@ OneLineAvatarIconListItem
|
|||||||
IconRightWidget:
|
IconRightWidget:
|
||||||
icon: "minus"
|
icon: "minus"
|
||||||
|
|
||||||
|
.. tab:: Declarative python style
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
OneLineAvatarIconListItem(
|
||||||
|
IconLeftWidget(
|
||||||
|
icon="plus"
|
||||||
|
),
|
||||||
|
IconRightWidget(
|
||||||
|
icon="minus"
|
||||||
|
),
|
||||||
|
text="Single-line item with avatar",
|
||||||
|
)
|
||||||
|
|
||||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/OneLineAvatarIconListItem.png
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/OneLineAvatarIconListItem.png
|
||||||
:align: center
|
:align: center
|
||||||
|
|
||||||
@ -294,6 +579,10 @@ OneLineAvatarIconListItem
|
|||||||
TwoLineAvatarIconListItem
|
TwoLineAvatarIconListItem
|
||||||
-------------------------
|
-------------------------
|
||||||
|
|
||||||
|
.. tabs::
|
||||||
|
|
||||||
|
.. tab:: Declarative KV style
|
||||||
|
|
||||||
.. code-block:: kv
|
.. code-block:: kv
|
||||||
|
|
||||||
TwoLineAvatarIconListItem:
|
TwoLineAvatarIconListItem:
|
||||||
@ -306,6 +595,21 @@ TwoLineAvatarIconListItem
|
|||||||
IconRightWidget:
|
IconRightWidget:
|
||||||
icon: "minus"
|
icon: "minus"
|
||||||
|
|
||||||
|
.. tab:: Declarative python style
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
TwoLineAvatarIconListItem(
|
||||||
|
IconLeftWidget(
|
||||||
|
icon="plus"
|
||||||
|
),
|
||||||
|
IconRightWidget(
|
||||||
|
icon="minus"
|
||||||
|
),
|
||||||
|
text="Single-line item with avatar",
|
||||||
|
secondary_text: "Secondary text here",
|
||||||
|
)
|
||||||
|
|
||||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/TwoLineAvatarIconListItem.png
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/TwoLineAvatarIconListItem.png
|
||||||
:align: center
|
:align: center
|
||||||
|
|
||||||
@ -313,6 +617,10 @@ TwoLineAvatarIconListItem
|
|||||||
ThreeLineAvatarIconListItem
|
ThreeLineAvatarIconListItem
|
||||||
---------------------------
|
---------------------------
|
||||||
|
|
||||||
|
.. tabs::
|
||||||
|
|
||||||
|
.. tab:: Declarative KV style
|
||||||
|
|
||||||
.. code-block:: kv
|
.. code-block:: kv
|
||||||
|
|
||||||
ThreeLineAvatarIconListItem:
|
ThreeLineAvatarIconListItem:
|
||||||
@ -326,12 +634,32 @@ ThreeLineAvatarIconListItem
|
|||||||
IconRightWidget:
|
IconRightWidget:
|
||||||
icon: "minus"
|
icon: "minus"
|
||||||
|
|
||||||
|
.. tab:: Declarative python style
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
ThreeLineAvatarIconListItem(
|
||||||
|
IconLeftWidget(
|
||||||
|
icon="plus"
|
||||||
|
),
|
||||||
|
IconRightWidget(
|
||||||
|
icon="minus"
|
||||||
|
),
|
||||||
|
text="Single-line item with avatar",
|
||||||
|
secondary_text: "Secondary text here",
|
||||||
|
tertiary_text: "fit more text than usual",
|
||||||
|
)
|
||||||
|
|
||||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/ThreeLineAvatarIconListItem.png
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/ThreeLineAvatarIconListItem.png
|
||||||
:align: center
|
:align: center
|
||||||
|
|
||||||
Custom list item
|
Custom list item
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
|
.. tabs::
|
||||||
|
|
||||||
|
.. tab:: Declarative KV style
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
from kivy.lang import Builder
|
from kivy.lang import Builder
|
||||||
@ -352,9 +680,7 @@ Custom list item
|
|||||||
RightCheckbox:
|
RightCheckbox:
|
||||||
|
|
||||||
|
|
||||||
MDBoxLayout:
|
MDScrollView:
|
||||||
|
|
||||||
ScrollView:
|
|
||||||
|
|
||||||
MDList:
|
MDList:
|
||||||
id: scroll
|
id: scroll
|
||||||
@ -371,8 +697,9 @@ Custom list item
|
|||||||
'''Custom right container.'''
|
'''Custom right container.'''
|
||||||
|
|
||||||
|
|
||||||
class MainApp(MDApp):
|
class Example(MDApp):
|
||||||
def build(self):
|
def build(self):
|
||||||
|
self.theme_cls.theme_style = "Dark"
|
||||||
return Builder.load_string(KV)
|
return Builder.load_string(KV)
|
||||||
|
|
||||||
def on_start(self):
|
def on_start(self):
|
||||||
@ -383,11 +710,58 @@ Custom list item
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
MainApp().run()
|
Example().run()
|
||||||
|
|
||||||
|
.. tab:: Declarative python style
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from kivymd.app import MDApp
|
||||||
|
from kivymd.uix.list import IRightBodyTouch, OneLineAvatarIconListItem
|
||||||
|
from kivymd.uix.selectioncontrol import MDCheckbox
|
||||||
|
from kivymd.uix.scrollview import MDScrollView
|
||||||
|
from kivymd.uix.list import MDList
|
||||||
|
from kivymd.icon_definitions import md_icons
|
||||||
|
|
||||||
|
|
||||||
|
class RightCheckbox(IRightBodyTouch, MDCheckbox):
|
||||||
|
'''Custom right container.'''
|
||||||
|
|
||||||
|
|
||||||
|
class Example(MDApp):
|
||||||
|
def build(self):
|
||||||
|
self.theme_cls.theme_style = "Dark"
|
||||||
|
return (
|
||||||
|
MDScrollView(
|
||||||
|
MDList(
|
||||||
|
id="scroll"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
def on_start(self):
|
||||||
|
icons = list(md_icons.keys())
|
||||||
|
for i in range(30):
|
||||||
|
self.root.ids.scroll.add_widget(
|
||||||
|
OneLineAvatarIconListItem(
|
||||||
|
IconLeftWidget(
|
||||||
|
icon=icons[i]
|
||||||
|
),
|
||||||
|
RightCheckbox(),
|
||||||
|
text=f"Item {i}",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
Example().run()
|
||||||
|
|
||||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/custom-list-item.png
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/custom-list-item.png
|
||||||
:align: center
|
:align: center
|
||||||
|
|
||||||
|
.. tabs::
|
||||||
|
|
||||||
|
.. tab:: Declarative KV style
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
from kivy.lang import Builder
|
from kivy.lang import Builder
|
||||||
@ -421,12 +795,57 @@ Custom list item
|
|||||||
adaptive_width = True
|
adaptive_width = True
|
||||||
|
|
||||||
|
|
||||||
class MainApp(MDApp):
|
class Example(MDApp):
|
||||||
def build(self):
|
def build(self):
|
||||||
|
self.theme_cls.theme_style = "Dark"
|
||||||
return Builder.load_string(KV)
|
return Builder.load_string(KV)
|
||||||
|
|
||||||
|
|
||||||
MainApp().run()
|
Example().run()
|
||||||
|
|
||||||
|
.. tab:: Declarative python style
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from kivymd.app import MDApp
|
||||||
|
from kivymd.uix.boxlayout import MDBoxLayout
|
||||||
|
from kivymd.uix.list import IRightBodyTouch
|
||||||
|
from kivymd.uix.button import MDIconButton
|
||||||
|
from kivymd.uix.list import OneLineAvatarIconListItem, IconLeftWidget
|
||||||
|
|
||||||
|
|
||||||
|
class YourContainer(IRightBodyTouch, MDBoxLayout):
|
||||||
|
adaptive_width = True
|
||||||
|
|
||||||
|
|
||||||
|
class Example(MDApp):
|
||||||
|
def build(self):
|
||||||
|
self.theme_cls.theme_style = "Dark"
|
||||||
|
return (
|
||||||
|
OneLineAvatarIconListItem(
|
||||||
|
IconLeftWidget(
|
||||||
|
icon="cog"
|
||||||
|
),
|
||||||
|
YourContainer(
|
||||||
|
MDIconButton(
|
||||||
|
icon="minus"
|
||||||
|
),
|
||||||
|
MDIconButton(
|
||||||
|
icon="plus"
|
||||||
|
),
|
||||||
|
id="container"
|
||||||
|
),
|
||||||
|
text="One-line item with avatar"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
def on_start(self):
|
||||||
|
container = self.root.ids.container
|
||||||
|
self.root.ids._right_container.width = container.width
|
||||||
|
container.x = container.width
|
||||||
|
|
||||||
|
|
||||||
|
Example().run()
|
||||||
|
|
||||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/custom-list-right-container.png
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/custom-list-right-container.png
|
||||||
:align: center
|
:align: center
|
||||||
@ -437,6 +856,10 @@ Behavior
|
|||||||
When using the `AvatarListItem` and `IconListItem` classes, when an icon is clicked,
|
When using the `AvatarListItem` and `IconListItem` classes, when an icon is clicked,
|
||||||
the event of this icon is triggered:
|
the event of this icon is triggered:
|
||||||
|
|
||||||
|
.. tabs::
|
||||||
|
|
||||||
|
.. tab:: Declarative KV style
|
||||||
|
|
||||||
.. code-block:: kv
|
.. code-block:: kv
|
||||||
|
|
||||||
OneLineIconListItem:
|
OneLineIconListItem:
|
||||||
@ -445,11 +868,26 @@ the event of this icon is triggered:
|
|||||||
IconLeftWidget:
|
IconLeftWidget:
|
||||||
icon: "language-python"
|
icon: "language-python"
|
||||||
|
|
||||||
|
.. tab:: Declarative python style
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
OneLineIconListItem(
|
||||||
|
IconLeftWidget(
|
||||||
|
icon="language-python"
|
||||||
|
),
|
||||||
|
text="Single-line item with avatar",
|
||||||
|
)
|
||||||
|
|
||||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/list-icon-trigger.gif
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/list-icon-trigger.gif
|
||||||
:align: center
|
:align: center
|
||||||
|
|
||||||
You can disable the icon event using the `WithoutTouch` classes:
|
You can disable the icon event using the `WithoutTouch` classes:
|
||||||
|
|
||||||
|
.. tabs::
|
||||||
|
|
||||||
|
.. tab:: Declarative KV style
|
||||||
|
|
||||||
.. code-block:: kv
|
.. code-block:: kv
|
||||||
|
|
||||||
OneLineIconListItem:
|
OneLineIconListItem:
|
||||||
@ -458,6 +896,17 @@ You can disable the icon event using the `WithoutTouch` classes:
|
|||||||
IconLeftWidgetWithoutTouch:
|
IconLeftWidgetWithoutTouch:
|
||||||
icon: "language-python"
|
icon: "language-python"
|
||||||
|
|
||||||
|
.. tab:: Declarative python style
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
OneLineIconListItem(
|
||||||
|
IconLeftWidgetWithoutTouch(
|
||||||
|
icon="language-python"
|
||||||
|
),
|
||||||
|
text="Single-line item with avatar",
|
||||||
|
)
|
||||||
|
|
||||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/list-icon-without-trigger.gif
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/list-icon-without-trigger.gif
|
||||||
:align: center
|
:align: center
|
||||||
"""
|
"""
|
||||||
@ -539,13 +988,9 @@ class MDList(MDGridLayout):
|
|||||||
|
|
||||||
_list_vertical_padding = NumericProperty("8dp")
|
_list_vertical_padding = NumericProperty("8dp")
|
||||||
|
|
||||||
def add_widget(self, widget, index=0, canvas=None):
|
def __init__(self, *args, **kwargs):
|
||||||
super().add_widget(widget, index, canvas)
|
super().__init__(*args, **kwargs)
|
||||||
self.height += widget.height
|
self.adaptive_height = True
|
||||||
|
|
||||||
def remove_widget(self, widget):
|
|
||||||
super().remove_widget(widget)
|
|
||||||
self.height -= widget.height
|
|
||||||
|
|
||||||
|
|
||||||
class BaseListItem(
|
class BaseListItem(
|
||||||
@ -569,8 +1014,8 @@ class BaseListItem(
|
|||||||
|
|
||||||
text_color = ColorProperty(None)
|
text_color = ColorProperty(None)
|
||||||
"""
|
"""
|
||||||
Text color in ``rgba`` format used if :attr:`~theme_text_color` is set
|
Text color in (r, g, b, a) or string format used
|
||||||
to `'Custom'`.
|
if :attr:`~theme_text_color` is set to `'Custom'`.
|
||||||
|
|
||||||
:attr:`text_color` is a :class:`~kivy.properties.ColorProperty`
|
:attr:`text_color` is a :class:`~kivy.properties.ColorProperty`
|
||||||
and defaults to `None`.
|
and defaults to `None`.
|
||||||
@ -578,7 +1023,9 @@ class BaseListItem(
|
|||||||
|
|
||||||
font_style = StringProperty("Subtitle1")
|
font_style = StringProperty("Subtitle1")
|
||||||
"""
|
"""
|
||||||
Text font style. See ``kivymd.font_definitions.py``.
|
Text font style.
|
||||||
|
See `font-definitions <https://kivymd.readthedocs.io/en/latest/themes/font-definitions/>`_
|
||||||
|
for more information.
|
||||||
|
|
||||||
:attr:`font_style` is a :class:`~kivy.properties.StringProperty`
|
:attr:`font_style` is a :class:`~kivy.properties.StringProperty`
|
||||||
and defaults to `'Subtitle1'`.
|
and defaults to `'Subtitle1'`.
|
||||||
@ -586,7 +1033,7 @@ class BaseListItem(
|
|||||||
|
|
||||||
theme_text_color = StringProperty("Primary", allownone=True)
|
theme_text_color = StringProperty("Primary", allownone=True)
|
||||||
"""
|
"""
|
||||||
Theme text color in ``rgba`` format for primary text.
|
The name of the color scheme for for the primary text.
|
||||||
|
|
||||||
:attr:`theme_text_color` is a :class:`~kivy.properties.StringProperty`
|
:attr:`theme_text_color` is a :class:`~kivy.properties.StringProperty`
|
||||||
and defaults to `'Primary'`.
|
and defaults to `'Primary'`.
|
||||||
@ -610,7 +1057,7 @@ class BaseListItem(
|
|||||||
|
|
||||||
secondary_text_color = ColorProperty(None)
|
secondary_text_color = ColorProperty(None)
|
||||||
"""
|
"""
|
||||||
Text color in ``rgba`` format used for secondary text
|
Text color in (r, g, b, a) or string format used for secondary text
|
||||||
if :attr:`~secondary_theme_text_color` is set to `'Custom'`.
|
if :attr:`~secondary_theme_text_color` is set to `'Custom'`.
|
||||||
|
|
||||||
:attr:`secondary_text_color` is a :class:`~kivy.properties.ColorProperty`
|
:attr:`secondary_text_color` is a :class:`~kivy.properties.ColorProperty`
|
||||||
@ -619,7 +1066,7 @@ class BaseListItem(
|
|||||||
|
|
||||||
tertiary_text_color = ColorProperty(None)
|
tertiary_text_color = ColorProperty(None)
|
||||||
"""
|
"""
|
||||||
Text color in ``rgba`` format used for tertiary text
|
Text color in (r, g, b, a) or string format used for tertiary text
|
||||||
if :attr:`~tertiary_theme_text_color` is set to 'Custom'.
|
if :attr:`~tertiary_theme_text_color` is set to 'Custom'.
|
||||||
|
|
||||||
:attr:`tertiary_text_color` is a :class:`~kivy.properties.ColorProperty`
|
:attr:`tertiary_text_color` is a :class:`~kivy.properties.ColorProperty`
|
||||||
@ -628,7 +1075,7 @@ class BaseListItem(
|
|||||||
|
|
||||||
secondary_theme_text_color = StringProperty("Secondary", allownone=True)
|
secondary_theme_text_color = StringProperty("Secondary", allownone=True)
|
||||||
"""
|
"""
|
||||||
Theme text color for secondary text.
|
The name of the color scheme for for the secondary text.
|
||||||
|
|
||||||
:attr:`secondary_theme_text_color` is a :class:`~kivy.properties.StringProperty`
|
:attr:`secondary_theme_text_color` is a :class:`~kivy.properties.StringProperty`
|
||||||
and defaults to `'Secondary'`.
|
and defaults to `'Secondary'`.
|
||||||
@ -636,7 +1083,7 @@ class BaseListItem(
|
|||||||
|
|
||||||
tertiary_theme_text_color = StringProperty("Secondary", allownone=True)
|
tertiary_theme_text_color = StringProperty("Secondary", allownone=True)
|
||||||
"""
|
"""
|
||||||
Theme text color for tertiary text.
|
The name of the color scheme for for the tertiary text.
|
||||||
|
|
||||||
:attr:`tertiary_theme_text_color` is a :class:`~kivy.properties.StringProperty`
|
:attr:`tertiary_theme_text_color` is a :class:`~kivy.properties.StringProperty`
|
||||||
and defaults to `'Secondary'`.
|
and defaults to `'Secondary'`.
|
||||||
@ -644,7 +1091,9 @@ class BaseListItem(
|
|||||||
|
|
||||||
secondary_font_style = StringProperty("Body1")
|
secondary_font_style = StringProperty("Body1")
|
||||||
"""
|
"""
|
||||||
Font style for secondary line. See ``kivymd.font_definitions.py``.
|
Font style for secondary line.
|
||||||
|
See `font-definitions <https://kivymd.readthedocs.io/en/latest/themes/font-definitions/>`_
|
||||||
|
for more information.
|
||||||
|
|
||||||
:attr:`secondary_font_style` is a :class:`~kivy.properties.StringProperty`
|
:attr:`secondary_font_style` is a :class:`~kivy.properties.StringProperty`
|
||||||
and defaults to `'Body1'`.
|
and defaults to `'Body1'`.
|
||||||
@ -652,7 +1101,9 @@ class BaseListItem(
|
|||||||
|
|
||||||
tertiary_font_style = StringProperty("Body1")
|
tertiary_font_style = StringProperty("Body1")
|
||||||
"""
|
"""
|
||||||
Font style for tertiary line. See ``kivymd.font_definitions.py``.
|
Font style for tertiary line.
|
||||||
|
See `font-definitions <https://kivymd.readthedocs.io/en/latest/themes/font-definitions/>`_
|
||||||
|
for more information.
|
||||||
|
|
||||||
:attr:`tertiary_font_style` is a :class:`~kivy.properties.StringProperty`
|
:attr:`tertiary_font_style` is a :class:`~kivy.properties.StringProperty`
|
||||||
and defaults to `'Body1'`.
|
and defaults to `'Body1'`.
|
||||||
@ -671,7 +1122,7 @@ class BaseListItem(
|
|||||||
|
|
||||||
divider_color = ColorProperty(None)
|
divider_color = ColorProperty(None)
|
||||||
"""
|
"""
|
||||||
Divider color.
|
Divider color in (r, g, b, a) or string format.
|
||||||
|
|
||||||
.. versionadded:: 1.0.0
|
.. versionadded:: 1.0.0
|
||||||
|
|
||||||
@ -681,7 +1132,7 @@ class BaseListItem(
|
|||||||
|
|
||||||
bg_color = ColorProperty(None)
|
bg_color = ColorProperty(None)
|
||||||
"""
|
"""
|
||||||
Background color for menu item.
|
Background color for list item in (r, g, b, a) or string format.
|
||||||
|
|
||||||
:attr:`bg_color` is a :class:`~kivy.properties.ColorProperty`
|
:attr:`bg_color` is a :class:`~kivy.properties.ColorProperty`
|
||||||
and defaults to `None`.
|
and defaults to `None`.
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#:import STD_INC kivymd.material_resources.STANDARD_INCREMENT
|
#:import STANDARD_INCREMENT kivymd.material_resources.STANDARD_INCREMENT
|
||||||
|
|
||||||
|
|
||||||
<RightContent>
|
<RightContent>
|
||||||
@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
<MDMenu>
|
<MDMenu>
|
||||||
size_hint: None, None
|
size_hint: None, None
|
||||||
width: root.width_mult * STD_INC
|
width: root.width_mult * STANDARD_INCREMENT
|
||||||
bar_width: 0
|
bar_width: 0
|
||||||
key_viewclass: "viewclass"
|
key_viewclass: "viewclass"
|
||||||
key_size: "height"
|
key_size: "height"
|
||||||
@ -28,7 +28,7 @@
|
|||||||
orientation: "vertical"
|
orientation: "vertical"
|
||||||
|
|
||||||
|
|
||||||
<MenuContainer@MDCard+FakeRectangularElevationBehavior>
|
<MenuContainer@MDCard>
|
||||||
|
|
||||||
|
|
||||||
<MDDropdownMenu>
|
<MDDropdownMenu>
|
||||||
|
@ -781,7 +781,7 @@ class MDDropdownMenu(ThemableBehavior, FloatLayout):
|
|||||||
and defaults to `'[dp(7)]'`.
|
and defaults to `'[dp(7)]'`.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
elevation = NumericProperty(10)
|
elevation = NumericProperty(4)
|
||||||
"""
|
"""
|
||||||
Elevation value of menu dialog.
|
Elevation value of menu dialog.
|
||||||
|
|
||||||
@ -790,7 +790,7 @@ class MDDropdownMenu(ThemableBehavior, FloatLayout):
|
|||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
self.menu = MDDropdownMenu(
|
self.menu = MDDropdownMenu(
|
||||||
elevation=16,
|
elevation=4,
|
||||||
...,
|
...,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -798,7 +798,7 @@ class MDDropdownMenu(ThemableBehavior, FloatLayout):
|
|||||||
:align: center
|
:align: center
|
||||||
|
|
||||||
:attr:`elevation` is an :class:`~kivy.properties.NumericProperty`
|
:attr:`elevation` is an :class:`~kivy.properties.NumericProperty`
|
||||||
and defaults to `10`.
|
and defaults to `4`.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
_start_coords = []
|
_start_coords = []
|
||||||
|
@ -61,7 +61,7 @@ A simple example
|
|||||||
|
|
||||||
MDTopAppBar:
|
MDTopAppBar:
|
||||||
title: "Navigation Drawer"
|
title: "Navigation Drawer"
|
||||||
elevation: 10
|
elevation: 4
|
||||||
pos_hint: {"top": 1}
|
pos_hint: {"top": 1}
|
||||||
md_bg_color: "#e7e4c0"
|
md_bg_color: "#e7e4c0"
|
||||||
specific_text_color: "#4a4939"
|
specific_text_color: "#4a4939"
|
||||||
@ -115,7 +115,7 @@ A simple example
|
|||||||
MDScreen(
|
MDScreen(
|
||||||
MDTopAppBar(
|
MDTopAppBar(
|
||||||
title="Navigation Drawer",
|
title="Navigation Drawer",
|
||||||
elevation=10,
|
elevation=4,
|
||||||
pos_hint={"top": 1},
|
pos_hint={"top": 1},
|
||||||
md_bg_color="#e7e4c0",
|
md_bg_color="#e7e4c0",
|
||||||
specific_text_color="#4a4939",
|
specific_text_color="#4a4939",
|
||||||
@ -188,7 +188,7 @@ Standard content for the navigation bar
|
|||||||
|
|
||||||
MDTopAppBar:
|
MDTopAppBar:
|
||||||
title: "Navigation Drawer"
|
title: "Navigation Drawer"
|
||||||
elevation: 10
|
elevation: 4
|
||||||
pos_hint: {"top": 1}
|
pos_hint: {"top": 1}
|
||||||
md_bg_color: "#e7e4c0"
|
md_bg_color: "#e7e4c0"
|
||||||
specific_text_color: "#4a4939"
|
specific_text_color: "#4a4939"
|
||||||
@ -296,7 +296,7 @@ Standard content for the navigation bar
|
|||||||
MDScreen(
|
MDScreen(
|
||||||
MDTopAppBar(
|
MDTopAppBar(
|
||||||
title="Navigation Drawer",
|
title="Navigation Drawer",
|
||||||
elevation=10,
|
elevation=4,
|
||||||
pos_hint={"top": 1},
|
pos_hint={"top": 1},
|
||||||
md_bg_color="#e7e4c0",
|
md_bg_color="#e7e4c0",
|
||||||
specific_text_color="#4a4939",
|
specific_text_color="#4a4939",
|
||||||
@ -396,7 +396,7 @@ Switching screens in the ``ScreenManager`` and using the common ``MDTopAppBar``
|
|||||||
|
|
||||||
MDTopAppBar:
|
MDTopAppBar:
|
||||||
pos_hint: {"top": 1}
|
pos_hint: {"top": 1}
|
||||||
elevation: 10
|
elevation: 4
|
||||||
title: "MDNavigationDrawer"
|
title: "MDNavigationDrawer"
|
||||||
left_action_items: [["menu", lambda x: nav_drawer.set_state("open")]]
|
left_action_items: [["menu", lambda x: nav_drawer.set_state("open")]]
|
||||||
|
|
||||||
@ -465,7 +465,7 @@ Switching screens in the ``ScreenManager`` and using the common ``MDTopAppBar``
|
|||||||
MDScreen(
|
MDScreen(
|
||||||
MDTopAppBar(
|
MDTopAppBar(
|
||||||
pos_hint={"top": 1},
|
pos_hint={"top": 1},
|
||||||
elevation=10,
|
elevation=4,
|
||||||
title="MDNavigationDrawer",
|
title="MDNavigationDrawer",
|
||||||
left_action_items=[["menu", lambda x: self.nav_drawer_open()]],
|
left_action_items=[["menu", lambda x: self.nav_drawer_open()]],
|
||||||
),
|
),
|
||||||
@ -551,14 +551,9 @@ from kivy.properties import (
|
|||||||
StringProperty,
|
StringProperty,
|
||||||
VariableListProperty,
|
VariableListProperty,
|
||||||
)
|
)
|
||||||
from kivy.uix.floatlayout import FloatLayout
|
|
||||||
from kivy.uix.screenmanager import ScreenManager
|
from kivy.uix.screenmanager import ScreenManager
|
||||||
|
|
||||||
from kivymd import uix_path
|
from kivymd import uix_path
|
||||||
from kivymd.uix.behaviors import (
|
|
||||||
DeclarativeBehavior,
|
|
||||||
FakeRectangularElevationBehavior,
|
|
||||||
)
|
|
||||||
from kivymd.uix.behaviors.focus_behavior import FocusBehavior
|
from kivymd.uix.behaviors.focus_behavior import FocusBehavior
|
||||||
from kivymd.uix.boxlayout import MDBoxLayout
|
from kivymd.uix.boxlayout import MDBoxLayout
|
||||||
from kivymd.uix.card import MDCard
|
from kivymd.uix.card import MDCard
|
||||||
@ -1029,7 +1024,7 @@ class MDNavigationDrawerMenu(MDScrollView):
|
|||||||
widget.text_color = widget._text_color
|
widget.text_color = widget._text_color
|
||||||
|
|
||||||
|
|
||||||
class MDNavigationDrawer(MDCard, FakeRectangularElevationBehavior):
|
class MDNavigationDrawer(MDCard):
|
||||||
type = OptionProperty("modal", options=("standard", "modal"))
|
type = OptionProperty("modal", options=("standard", "modal"))
|
||||||
"""
|
"""
|
||||||
Type of drawer. Modal type will be on top of screen. Standard type will be
|
Type of drawer. Modal type will be on top of screen. Standard type will be
|
||||||
|
@ -29,6 +29,10 @@ Usage
|
|||||||
|
|
||||||
MDNavigationRailItem:
|
MDNavigationRailItem:
|
||||||
|
|
||||||
|
.. tabs::
|
||||||
|
|
||||||
|
.. tab:: Declarative KV style
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
from kivy.lang import Builder
|
from kivy.lang import Builder
|
||||||
@ -36,8 +40,6 @@ Usage
|
|||||||
from kivymd.app import MDApp
|
from kivymd.app import MDApp
|
||||||
|
|
||||||
KV = '''
|
KV = '''
|
||||||
|
|
||||||
|
|
||||||
MDBoxLayout:
|
MDBoxLayout:
|
||||||
|
|
||||||
MDNavigationRail:
|
MDNavigationRail:
|
||||||
@ -69,19 +71,62 @@ Usage
|
|||||||
|
|
||||||
Example().run()
|
Example().run()
|
||||||
|
|
||||||
|
.. tab:: Declarative python style
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from kivymd.app import MDApp
|
||||||
|
from kivymd.uix.boxlayout import MDBoxLayout
|
||||||
|
from kivymd.uix.navigationrail import MDNavigationRail, MDNavigationRailItem
|
||||||
|
|
||||||
|
|
||||||
|
class Example(MDApp):
|
||||||
|
def build(self):
|
||||||
|
self.theme_cls.theme_style = "Dark"
|
||||||
|
self.theme_cls.primary_palette = "Orange"
|
||||||
|
return (
|
||||||
|
MDBoxLayout(
|
||||||
|
MDNavigationRail(
|
||||||
|
MDNavigationRailItem(
|
||||||
|
text="Python",
|
||||||
|
icon="language-python",
|
||||||
|
),
|
||||||
|
MDNavigationRailItem(
|
||||||
|
text="JavaScript",
|
||||||
|
icon="language-javascript",
|
||||||
|
),
|
||||||
|
MDNavigationRailItem(
|
||||||
|
text="CPP",
|
||||||
|
icon="language-cpp",
|
||||||
|
),
|
||||||
|
MDNavigationRailItem(
|
||||||
|
text="Git",
|
||||||
|
icon="git",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
Example().run()
|
||||||
|
|
||||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/navigation-rail-usage.png
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/navigation-rail-usage.png
|
||||||
:align: center
|
:align: center
|
||||||
|
|
||||||
Example
|
Example
|
||||||
=======
|
=======
|
||||||
|
|
||||||
|
.. tabs::
|
||||||
|
|
||||||
|
.. tab:: Declarative KV and imperative python styles
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
from kivy.clock import Clock
|
from kivy.clock import Clock
|
||||||
from kivy.lang import Builder
|
from kivy.lang import Builder
|
||||||
|
|
||||||
from kivymd.app import MDApp
|
from kivymd.app import MDApp
|
||||||
from kivymd.uix.behaviors import RoundedRectangularElevationBehavior
|
from kivymd.uix.behaviors import CommonElevationBehavior
|
||||||
from kivymd.uix.boxlayout import MDBoxLayout
|
from kivymd.uix.boxlayout import MDBoxLayout
|
||||||
from kivymd.uix.button import MDFillRoundFlatIconButton
|
from kivymd.uix.button import MDFillRoundFlatIconButton
|
||||||
from kivymd.uix.label import MDLabel
|
from kivymd.uix.label import MDLabel
|
||||||
@ -92,7 +137,9 @@ Example
|
|||||||
|
|
||||||
|
|
||||||
<ExtendedButton>
|
<ExtendedButton>
|
||||||
elevation: 3
|
elevation: 3.5
|
||||||
|
shadow_radius: 12
|
||||||
|
shadow_softness: 4
|
||||||
-height: "56dp"
|
-height: "56dp"
|
||||||
|
|
||||||
|
|
||||||
@ -162,7 +209,7 @@ Example
|
|||||||
id: nav_drawer
|
id: nav_drawer
|
||||||
radius: (0, 16, 16, 0)
|
radius: (0, 16, 16, 0)
|
||||||
md_bg_color: "#fffcf4"
|
md_bg_color: "#fffcf4"
|
||||||
elevation: 12
|
elevation: 4
|
||||||
width: "240dp"
|
width: "240dp"
|
||||||
|
|
||||||
MDNavigationDrawerMenu:
|
MDNavigationDrawerMenu:
|
||||||
@ -171,7 +218,7 @@ Example
|
|||||||
orientation: "vertical"
|
orientation: "vertical"
|
||||||
adaptive_height: True
|
adaptive_height: True
|
||||||
spacing: "12dp"
|
spacing: "12dp"
|
||||||
padding: 0, 0, 0, "12dp"
|
padding: "3dp", 0, 0, "12dp"
|
||||||
|
|
||||||
MDIconButton:
|
MDIconButton:
|
||||||
icon: "menu"
|
icon: "menu"
|
||||||
@ -198,9 +245,7 @@ Example
|
|||||||
'''
|
'''
|
||||||
|
|
||||||
|
|
||||||
class ExtendedButton(
|
class ExtendedButton(MDFillRoundFlatIconButton, CommonElevationBehavior):
|
||||||
RoundedRectangularElevationBehavior, MDFillRoundFlatIconButton
|
|
||||||
):
|
|
||||||
'''
|
'''
|
||||||
Implements a button of type
|
Implements a button of type
|
||||||
`Extended FAB <https://m3.material.io/components/extended-fab/overview>`_.
|
`Extended FAB <https://m3.material.io/components/extended-fab/overview>`_.
|
||||||
@ -214,8 +259,8 @@ Example
|
|||||||
of the KivyMD library, so we will implement it ourselves in this class.
|
of the KivyMD library, so we will implement it ourselves in this class.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super().__init__(**kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
self.padding = "16dp"
|
self.padding = "16dp"
|
||||||
Clock.schedule_once(self.set_spacing)
|
Clock.schedule_once(self.set_spacing)
|
||||||
|
|
||||||
@ -272,6 +317,212 @@ Example
|
|||||||
|
|
||||||
Example().run()
|
Example().run()
|
||||||
|
|
||||||
|
.. tab:: Declarative python style
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from kivy.clock import Clock
|
||||||
|
from kivy.metrics import dp
|
||||||
|
|
||||||
|
from kivymd.app import MDApp
|
||||||
|
from kivymd.uix.behaviors import CommonElevationBehavior
|
||||||
|
from kivymd.uix.boxlayout import MDBoxLayout
|
||||||
|
from kivymd.uix.button import MDFillRoundFlatIconButton, MDIconButton
|
||||||
|
from kivymd.uix.label import MDLabel
|
||||||
|
from kivymd.uix.navigationdrawer import (
|
||||||
|
MDNavigationDrawerItem,
|
||||||
|
MDNavigationLayout,
|
||||||
|
MDNavigationDrawer,
|
||||||
|
MDNavigationDrawerMenu,
|
||||||
|
)
|
||||||
|
from kivymd.uix.navigationrail import (
|
||||||
|
MDNavigationRail,
|
||||||
|
MDNavigationRailMenuButton,
|
||||||
|
MDNavigationRailFabButton,
|
||||||
|
MDNavigationRailItem,
|
||||||
|
)
|
||||||
|
from kivymd.uix.screen import MDScreen
|
||||||
|
from kivymd.uix.screenmanager import MDScreenManager
|
||||||
|
|
||||||
|
|
||||||
|
class DrawerClickableItem(MDNavigationDrawerItem):
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
self.focus_color = "#e7e4c0"
|
||||||
|
self.unfocus_color = self.theme_cls.bg_light
|
||||||
|
self.radius = 24
|
||||||
|
|
||||||
|
|
||||||
|
class ExtendedButton(MDFillRoundFlatIconButton, CommonElevationBehavior):
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
self.padding = "16dp"
|
||||||
|
self.elevation = 3.5
|
||||||
|
self.shadow_radius = 12
|
||||||
|
self.shadow_softness = 4
|
||||||
|
self.height = dp(56)
|
||||||
|
Clock.schedule_once(self.set_spacing)
|
||||||
|
|
||||||
|
def set_spacing(self, interval):
|
||||||
|
self.ids.box.spacing = "12dp"
|
||||||
|
|
||||||
|
def set_radius(self, *args):
|
||||||
|
if self.rounded_button:
|
||||||
|
self._radius = self.radius = self.height / 4
|
||||||
|
|
||||||
|
|
||||||
|
class Example(MDApp):
|
||||||
|
def build(self):
|
||||||
|
self.theme_cls.material_style = "M3"
|
||||||
|
self.theme_cls.primary_palette = "Orange"
|
||||||
|
return MDScreen(
|
||||||
|
MDNavigationLayout(
|
||||||
|
MDScreenManager(
|
||||||
|
MDScreen(
|
||||||
|
MDBoxLayout(
|
||||||
|
MDBoxLayout(
|
||||||
|
MDLabel(
|
||||||
|
text="12:00",
|
||||||
|
adaptive_height=True,
|
||||||
|
pos_hint={"center_y": 0.5},
|
||||||
|
),
|
||||||
|
adaptive_height=True,
|
||||||
|
md_bg_color="#fffcf4",
|
||||||
|
padding="12dp",
|
||||||
|
),
|
||||||
|
MDBoxLayout(
|
||||||
|
MDNavigationRail(
|
||||||
|
MDNavigationRailMenuButton(
|
||||||
|
on_release=self.open_nav_drawer,
|
||||||
|
),
|
||||||
|
MDNavigationRailFabButton(
|
||||||
|
md_bg_color="#b0f0d6",
|
||||||
|
),
|
||||||
|
MDNavigationRailItem(
|
||||||
|
text="Python",
|
||||||
|
icon="language-python",
|
||||||
|
),
|
||||||
|
MDNavigationRailItem(
|
||||||
|
text="JavaScript",
|
||||||
|
icon="language-javascript",
|
||||||
|
),
|
||||||
|
MDNavigationRailItem(
|
||||||
|
text="CPP",
|
||||||
|
icon="language-cpp",
|
||||||
|
),
|
||||||
|
MDNavigationRailItem(
|
||||||
|
text="Swift",
|
||||||
|
icon="language-swift",
|
||||||
|
),
|
||||||
|
id="navigation_rail",
|
||||||
|
md_bg_color="#fffcf4",
|
||||||
|
selected_color_background="#e7e4c0",
|
||||||
|
ripple_color_item="#e7e4c0",
|
||||||
|
),
|
||||||
|
MDScreenManager(
|
||||||
|
id="screen_manager_content",
|
||||||
|
),
|
||||||
|
id="root_box",
|
||||||
|
),
|
||||||
|
id="box_rail",
|
||||||
|
orientation="vertical",
|
||||||
|
),
|
||||||
|
id="box",
|
||||||
|
),
|
||||||
|
id="screen",
|
||||||
|
),
|
||||||
|
id="screen_manager",
|
||||||
|
),
|
||||||
|
MDNavigationDrawer(
|
||||||
|
MDNavigationDrawerMenu(
|
||||||
|
MDBoxLayout(
|
||||||
|
MDIconButton(
|
||||||
|
icon="menu",
|
||||||
|
),
|
||||||
|
ExtendedButton(
|
||||||
|
text="Compose",
|
||||||
|
icon="pencil",
|
||||||
|
),
|
||||||
|
orientation="vertical",
|
||||||
|
adaptive_height=True,
|
||||||
|
spacing="12dp",
|
||||||
|
padding=("3dp", 0, 0, "12dp"),
|
||||||
|
),
|
||||||
|
DrawerClickableItem(
|
||||||
|
text="Python",
|
||||||
|
icon="language-python",
|
||||||
|
),
|
||||||
|
DrawerClickableItem(
|
||||||
|
text="JavaScript",
|
||||||
|
icon="language-javascript",
|
||||||
|
),
|
||||||
|
DrawerClickableItem(
|
||||||
|
text="CPP",
|
||||||
|
icon="language-cpp",
|
||||||
|
),
|
||||||
|
DrawerClickableItem(
|
||||||
|
text="Swift",
|
||||||
|
icon="language-swift",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
id="nav_drawer",
|
||||||
|
radius=(0, 16, 16, 0),
|
||||||
|
elevation=4,
|
||||||
|
width="240dp",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
def switch_screen(self, *args, screen_manager_content=None):
|
||||||
|
'''
|
||||||
|
Called when tapping on rail menu items. Switches application screens.
|
||||||
|
'''
|
||||||
|
|
||||||
|
instance_navigation_rail, instance_navigation_rail_item = args
|
||||||
|
screen_manager_content.current = (
|
||||||
|
instance_navigation_rail_item.icon.split("-")[1].lower()
|
||||||
|
)
|
||||||
|
|
||||||
|
def open_nav_drawer(self, *args):
|
||||||
|
self.root.ids.nav_drawer.set_state("open")
|
||||||
|
|
||||||
|
def on_start(self):
|
||||||
|
'''Creates application screens.'''
|
||||||
|
|
||||||
|
screen_manager = self.root.ids.screen_manager
|
||||||
|
root_box = screen_manager.ids.screen.ids.box.ids.box_rail.ids.root_box
|
||||||
|
navigation_rail = root_box.ids.navigation_rail
|
||||||
|
screen_manager_content = root_box.ids.screen_manager_content
|
||||||
|
navigation_rail_items = navigation_rail.get_items()[:]
|
||||||
|
navigation_rail_items.reverse()
|
||||||
|
navigation_rail.bind(
|
||||||
|
on_item_release=lambda *args: self.switch_screen(
|
||||||
|
*args, screen_manager_content=screen_manager_content
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
for widget in navigation_rail_items:
|
||||||
|
name_screen = widget.icon.split("-")[1].lower()
|
||||||
|
screen_manager_content.add_widget(
|
||||||
|
MDScreen(
|
||||||
|
MDBoxLayout(
|
||||||
|
MDLabel(
|
||||||
|
text=name_screen.capitalize(),
|
||||||
|
font_style="H1",
|
||||||
|
halign="right",
|
||||||
|
adaptive_height=True,
|
||||||
|
shorten=True,
|
||||||
|
),
|
||||||
|
padding="12dp",
|
||||||
|
),
|
||||||
|
name=name_screen,
|
||||||
|
md_bg_color="#edd769",
|
||||||
|
radius=[18, 0, 0, 0],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
Example().run()
|
||||||
|
|
||||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/navigation-rail-example.gif
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/navigation-rail-example.gif
|
||||||
:align: center
|
:align: center
|
||||||
|
|
||||||
@ -306,12 +557,11 @@ from kivy.uix.behaviors import ButtonBehavior
|
|||||||
|
|
||||||
from kivymd import uix_path
|
from kivymd import uix_path
|
||||||
from kivymd.theming import ThemableBehavior
|
from kivymd.theming import ThemableBehavior
|
||||||
from kivymd.uix.behaviors import FakeRectangularElevationBehavior
|
from kivymd.uix.behaviors import ScaleBehavior
|
||||||
from kivymd.uix.boxlayout import MDBoxLayout
|
from kivymd.uix.boxlayout import MDBoxLayout
|
||||||
from kivymd.uix.button import MDFloatingActionButton, MDIconButton
|
from kivymd.uix.button import MDFloatingActionButton, MDIconButton
|
||||||
from kivymd.uix.card import MDCard
|
from kivymd.uix.card import MDCard
|
||||||
from kivymd.uix.floatlayout import MDFloatLayout
|
from kivymd.uix.floatlayout import MDFloatLayout
|
||||||
from kivymd.uix.templates import ScaleWidget
|
|
||||||
from kivymd.uix.widget import MDWidget
|
from kivymd.uix.widget import MDWidget
|
||||||
|
|
||||||
with open(
|
with open(
|
||||||
@ -333,7 +583,7 @@ class PanelItems(MDBoxLayout):
|
|||||||
"""Box for menu items."""
|
"""Box for menu items."""
|
||||||
|
|
||||||
|
|
||||||
class RippleWidget(MDWidget, ScaleWidget):
|
class RippleWidget(MDWidget, ScaleBehavior):
|
||||||
"""
|
"""
|
||||||
Implements a background color for a menu item -
|
Implements a background color for a menu item -
|
||||||
(:class:`~MDNavigationRailItem`).
|
(:class:`~MDNavigationRailItem`).
|
||||||
@ -562,7 +812,7 @@ class MDNavigationRailItem(ThemableBehavior, ButtonBehavior, MDBoxLayout):
|
|||||||
self.navigation_rail.dispatch("on_item_release", self)
|
self.navigation_rail.dispatch("on_item_release", self)
|
||||||
|
|
||||||
|
|
||||||
class MDNavigationRail(MDCard, FakeRectangularElevationBehavior):
|
class MDNavigationRail(MDCard):
|
||||||
"""
|
"""
|
||||||
:Events:
|
:Events:
|
||||||
:attr:`on_item_press`
|
:attr:`on_item_press`
|
||||||
|
@ -307,34 +307,6 @@
|
|||||||
else (dp(32), dp(32))
|
else (dp(32), dp(32))
|
||||||
disabled: True
|
disabled: True
|
||||||
|
|
||||||
canvas:
|
|
||||||
Color:
|
|
||||||
rgba:
|
|
||||||
( \
|
|
||||||
( \
|
|
||||||
self.theme_cls.primary_color if not root.owner.selector_color \
|
|
||||||
else root.owner.selector_color \
|
|
||||||
) \
|
|
||||||
if root.is_selected and not self.disabled \
|
|
||||||
else (0, 0, 0, 0) \
|
|
||||||
) \
|
|
||||||
if self.owner.mode != "range" else \
|
|
||||||
( \
|
|
||||||
( \
|
|
||||||
self.theme_cls.primary_color if not root.owner.selector_color \
|
|
||||||
else root.owner.selector_color \
|
|
||||||
) \
|
|
||||||
if root.is_selected and not self.disabled \
|
|
||||||
and (self.owner.mode == "range" and self.owner._start_range_date) \
|
|
||||||
else (0, 0, 0, 0) \
|
|
||||||
)
|
|
||||||
Ellipse:
|
|
||||||
size:
|
|
||||||
(dp(42), dp(42)) \
|
|
||||||
if root.theme_cls.device_orientation == "portrait" \
|
|
||||||
else (dp(32), dp(32))
|
|
||||||
pos: self.pos
|
|
||||||
|
|
||||||
# Fill marking the available dates of the range, if using the `range` mode
|
# Fill marking the available dates of the range, if using the `range` mode
|
||||||
# or use `min_date/max_date`.
|
# or use `min_date/max_date`.
|
||||||
canvas.before:
|
canvas.before:
|
||||||
@ -355,12 +327,14 @@
|
|||||||
if root.theme_cls.device_orientation == "portrait" \
|
if root.theme_cls.device_orientation == "portrait" \
|
||||||
else \
|
else \
|
||||||
(dp(32), dp(28)) \
|
(dp(32), dp(28)) \
|
||||||
if self.index in [6, 13, 20, 27, 30] or self.owner._date_range \
|
if self.index in [6, 13, 20, 27, 34] or self.owner._date_range \
|
||||||
and self.text and self.owner._date_range[-1] == date( \
|
and self.text and self.owner._date_range[-1] == date( \
|
||||||
self.current_year, \
|
self.current_year, \
|
||||||
self.current_month, \
|
self.current_month, \
|
||||||
int(self.text) \
|
int(self.text) \
|
||||||
) \
|
) \
|
||||||
|
or self.text and int(self.text) == \
|
||||||
|
calendar.monthrange(self.current_year, self.current_month)[1] \
|
||||||
else (dp(46), dp(28))
|
else (dp(46), dp(28))
|
||||||
pos:
|
pos:
|
||||||
(self.x - dp(1.5), self.y + dp(5)) \
|
(self.x - dp(1.5), self.y + dp(5)) \
|
||||||
@ -395,29 +369,15 @@
|
|||||||
else [0, 0, 0, 0]) \
|
else [0, 0, 0, 0]) \
|
||||||
)
|
)
|
||||||
|
|
||||||
# Circle marking the beginning and end of the date range if the "range"
|
# Selection circle.
|
||||||
# mode is used.
|
|
||||||
Color:
|
Color:
|
||||||
rgba:
|
rgba:
|
||||||
[0, 0, 0, 0] if not self.owner._date_range else \
|
|
||||||
(
|
|
||||||
( \
|
( \
|
||||||
self.theme_cls.primary_color if not root.owner.selector_color \
|
self.theme_cls.primary_color if not root.owner.selector_color \
|
||||||
else root.owner.selector_color \
|
else root.owner.selector_color \
|
||||||
) \
|
) \
|
||||||
if self.text and self.owner._date_range[0] == date( \
|
if root.is_selected and not self.disabled \
|
||||||
self.current_year, \
|
else (0, 0, 0, 0)
|
||||||
self.current_month, \
|
|
||||||
int(self.text) \
|
|
||||||
) \
|
|
||||||
or \
|
|
||||||
self.text and self.owner._date_range[-1] == date( \
|
|
||||||
self.current_year, \
|
|
||||||
self.current_month, \
|
|
||||||
int(self.text) \
|
|
||||||
) \
|
|
||||||
else (0, 0, 0, 0) \
|
|
||||||
)
|
|
||||||
Ellipse:
|
Ellipse:
|
||||||
size:
|
size:
|
||||||
(dp(42), dp(42)) \
|
(dp(42), dp(42)) \
|
||||||
|
@ -11,11 +11,12 @@ Components/DatePicker
|
|||||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/picker-previous.png
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/picker-previous.png
|
||||||
:align: center
|
:align: center
|
||||||
|
|
||||||
.. warning:: The widget is under testing. Therefore, we would be grateful if
|
|
||||||
you would let us know about the bugs found.
|
|
||||||
|
|
||||||
.. rubric:: Usage
|
.. rubric:: Usage
|
||||||
|
|
||||||
|
.. tabs::
|
||||||
|
|
||||||
|
.. tab:: Declarative KV style
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
from kivy.lang import Builder
|
from kivy.lang import Builder
|
||||||
@ -26,11 +27,6 @@ Components/DatePicker
|
|||||||
KV = '''
|
KV = '''
|
||||||
MDFloatLayout:
|
MDFloatLayout:
|
||||||
|
|
||||||
MDTopAppBar:
|
|
||||||
title: "MDDatePicker"
|
|
||||||
pos_hint: {"top": 1}
|
|
||||||
elevation: 10
|
|
||||||
|
|
||||||
MDRaisedButton:
|
MDRaisedButton:
|
||||||
text: "Open date picker"
|
text: "Open date picker"
|
||||||
pos_hint: {'center_x': .5, 'center_y': .5}
|
pos_hint: {'center_x': .5, 'center_y': .5}
|
||||||
@ -40,8 +36,58 @@ Components/DatePicker
|
|||||||
|
|
||||||
class Test(MDApp):
|
class Test(MDApp):
|
||||||
def build(self):
|
def build(self):
|
||||||
|
self.theme_cls.theme_style = "Dark"
|
||||||
|
self.theme_cls.primary_palette = "Orange"
|
||||||
return Builder.load_string(KV)
|
return Builder.load_string(KV)
|
||||||
|
|
||||||
|
def on_save(self, instance, value, date_range):
|
||||||
|
'''
|
||||||
|
Events called when the "OK" dialog box button is clicked.
|
||||||
|
|
||||||
|
:type instance: <kivymd.uix.picker.MDDatePicker object>;
|
||||||
|
:param value: selected date;
|
||||||
|
:type value: <class 'datetime.date'>;
|
||||||
|
:param date_range: list of 'datetime.date' objects in the selected range;
|
||||||
|
:type date_range: <class 'list'>;
|
||||||
|
'''
|
||||||
|
|
||||||
|
print(instance, value, date_range)
|
||||||
|
|
||||||
|
def on_cancel(self, instance, value):
|
||||||
|
'''Events called when the "CANCEL" dialog box button is clicked.'''
|
||||||
|
|
||||||
|
def show_date_picker(self):
|
||||||
|
date_dialog = MDDatePicker()
|
||||||
|
date_dialog.bind(on_save=self.on_save, on_cancel=self.on_cancel)
|
||||||
|
date_dialog.open()
|
||||||
|
|
||||||
|
|
||||||
|
Test().run()
|
||||||
|
|
||||||
|
.. tab:: Declarative python style
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from kivymd.app import MDApp
|
||||||
|
from kivymd.uix.button import MDRaisedButton
|
||||||
|
from kivymd.uix.pickers import MDDatePicker
|
||||||
|
from kivymd.uix.screen import MDScreen
|
||||||
|
|
||||||
|
|
||||||
|
class Test(MDApp):
|
||||||
|
def build(self):
|
||||||
|
self.theme_cls.theme_style = "Dark"
|
||||||
|
self.theme_cls.primary_palette = "Orange"
|
||||||
|
return (
|
||||||
|
MDScreen(
|
||||||
|
MDRaisedButton(
|
||||||
|
text="Open data picker",
|
||||||
|
pos_hint={'center_x': .5, 'center_y': .5},
|
||||||
|
on_release=self.show_date_picker,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
def on_save(self, instance, value, date_range):
|
def on_save(self, instance, value, date_range):
|
||||||
'''
|
'''
|
||||||
Events called when the "OK" dialog box button is clicked.
|
Events called when the "OK" dialog box button is clicked.
|
||||||
@ -60,7 +106,7 @@ Components/DatePicker
|
|||||||
def on_cancel(self, instance, value):
|
def on_cancel(self, instance, value):
|
||||||
'''Events called when the "CANCEL" dialog box button is clicked.'''
|
'''Events called when the "CANCEL" dialog box button is clicked.'''
|
||||||
|
|
||||||
def show_date_picker(self):
|
def show_date_picker(self, *args):
|
||||||
date_dialog = MDDatePicker()
|
date_dialog = MDDatePicker()
|
||||||
date_dialog.bind(on_save=self.on_save, on_cancel=self.on_cancel)
|
date_dialog.bind(on_save=self.on_save, on_cancel=self.on_cancel)
|
||||||
date_dialog.open()
|
date_dialog.open()
|
||||||
@ -68,8 +114,7 @@ Components/DatePicker
|
|||||||
|
|
||||||
Test().run()
|
Test().run()
|
||||||
|
|
||||||
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/MDDatePicker.png
|
||||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/MDDatePicker.gif
|
|
||||||
:align: center
|
:align: center
|
||||||
|
|
||||||
Open date dialog with the specified date
|
Open date dialog with the specified date
|
||||||
@ -81,7 +126,7 @@ Open date dialog with the specified date
|
|||||||
date_dialog = MDDatePicker(year=1983, month=4, day=12)
|
date_dialog = MDDatePicker(year=1983, month=4, day=12)
|
||||||
date_dialog.open()
|
date_dialog.open()
|
||||||
|
|
||||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/previous-date.png
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/specified-date.png
|
||||||
:align: center
|
:align: center
|
||||||
|
|
||||||
Interval date
|
Interval date
|
||||||
@ -94,12 +139,16 @@ that are not included in this range will have the status `disabled`.
|
|||||||
|
|
||||||
def show_date_picker(self):
|
def show_date_picker(self):
|
||||||
date_dialog = MDDatePicker(
|
date_dialog = MDDatePicker(
|
||||||
min_date=datetime.date(2021, 2, 15),
|
min_date=datetime.date.today(),
|
||||||
max_date=datetime.date(2021, 3, 27),
|
max_date=datetime.date(
|
||||||
|
datetime.date.today().year,
|
||||||
|
datetime.date.today().month,
|
||||||
|
datetime.date.today().day + 2,
|
||||||
|
),
|
||||||
)
|
)
|
||||||
date_dialog.open()
|
date_dialog.open()
|
||||||
|
|
||||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/range-date.gif
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/range-date.png
|
||||||
:align: center
|
:align: center
|
||||||
|
|
||||||
The range of available dates can be changed in the picker dialog:
|
The range of available dates can be changed in the picker dialog:
|
||||||
@ -122,7 +171,7 @@ You can set the range of years using the :attr:`~kivymd.uix.picker.MDDatePicker.
|
|||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
def show_date_picker(self):
|
def show_date_picker(self):
|
||||||
date_dialog = MDDatePicker(min_year=2021, max_year=2030)
|
date_dialog = MDDatePicker(min_year=2022, max_year=2030)
|
||||||
date_dialog.open()
|
date_dialog.open()
|
||||||
|
|
||||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/min-max-year-date.png
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/min-max-year-date.png
|
||||||
@ -141,18 +190,21 @@ Set and select a date range
|
|||||||
:align: center
|
:align: center
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
__all__ = ("MDDatePicker", "BaseDialogPicker", "DatePickerInputField")
|
__all__ = ("MDDatePicker", "BaseDialogPicker", "DatePickerInputField")
|
||||||
|
|
||||||
import calendar
|
import calendar
|
||||||
import datetime
|
import datetime
|
||||||
|
import math
|
||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
from datetime import date
|
from datetime import date
|
||||||
|
from itertools import zip_longest
|
||||||
from typing import Union
|
from typing import Union
|
||||||
|
|
||||||
from kivy import Logger
|
from kivy import Logger
|
||||||
from kivy.animation import Animation
|
from kivy.animation import Animation
|
||||||
from kivy.clock import Clock
|
|
||||||
from kivy.lang import Builder
|
from kivy.lang import Builder
|
||||||
from kivy.metrics import dp
|
from kivy.metrics import dp
|
||||||
from kivy.properties import (
|
from kivy.properties import (
|
||||||
@ -175,7 +227,7 @@ from kivymd.theming import ThemableBehavior, ThemeManager
|
|||||||
from kivymd.toast import toast
|
from kivymd.toast import toast
|
||||||
from kivymd.uix.behaviors import (
|
from kivymd.uix.behaviors import (
|
||||||
CircularRippleBehavior,
|
CircularRippleBehavior,
|
||||||
FakeRectangularElevationBehavior,
|
CommonElevationBehavior,
|
||||||
SpecificBackgroundColorBehavior,
|
SpecificBackgroundColorBehavior,
|
||||||
)
|
)
|
||||||
from kivymd.uix.boxlayout import MDBoxLayout
|
from kivymd.uix.boxlayout import MDBoxLayout
|
||||||
@ -194,7 +246,7 @@ with open(
|
|||||||
|
|
||||||
class BaseDialogPicker(
|
class BaseDialogPicker(
|
||||||
BaseDialog,
|
BaseDialog,
|
||||||
FakeRectangularElevationBehavior,
|
CommonElevationBehavior,
|
||||||
SpecificBackgroundColorBehavior,
|
SpecificBackgroundColorBehavior,
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
@ -255,11 +307,11 @@ class BaseDialogPicker(
|
|||||||
|
|
||||||
primary_color = ColorProperty(None)
|
primary_color = ColorProperty(None)
|
||||||
"""
|
"""
|
||||||
Background color of toolbar in (r, g, b, a) format.
|
Background color of toolbar in (r, g, b, a) or string format.
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
MDDatePicker(primary_color=get_color_from_hex("#72225b"))
|
MDDatePicker(primary_color="brown")
|
||||||
|
|
||||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/primary-color-date.png
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/primary-color-date.png
|
||||||
:align: center
|
:align: center
|
||||||
@ -270,13 +322,13 @@ class BaseDialogPicker(
|
|||||||
|
|
||||||
accent_color = ColorProperty(None)
|
accent_color = ColorProperty(None)
|
||||||
"""
|
"""
|
||||||
Background color of calendar/clock face in (r, g, b, a) format.
|
Background color of calendar/clock face in (r, g, b, a) or string format.
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
MDDatePicker(
|
MDDatePicker(
|
||||||
primary_color=get_color_from_hex("#72225b"),
|
primary_color="brown",
|
||||||
accent_color=get_color_from_hex("#5d1a4a"),
|
accent_color="darkred",
|
||||||
)
|
)
|
||||||
|
|
||||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/accent-color-date.png
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/accent-color-date.png
|
||||||
@ -288,14 +340,15 @@ class BaseDialogPicker(
|
|||||||
|
|
||||||
selector_color = ColorProperty(None)
|
selector_color = ColorProperty(None)
|
||||||
"""
|
"""
|
||||||
Background color of the selected day of the month or hour in (r, g, b, a) format.
|
Background color of the selected day of the month or hour in (r, g, b, a)
|
||||||
|
or string format.
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
MDDatePicker(
|
MDDatePicker(
|
||||||
primary_color=get_color_from_hex("#72225b"),
|
primary_color="brown",
|
||||||
accent_color=get_color_from_hex("#5d1a4a"),
|
accent_color="darkred",
|
||||||
selector_color=get_color_from_hex("#e93f39"),
|
selector_color="red",
|
||||||
)
|
)
|
||||||
|
|
||||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/selector-color-date.png
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/selector-color-date.png
|
||||||
@ -307,15 +360,15 @@ class BaseDialogPicker(
|
|||||||
|
|
||||||
text_toolbar_color = ColorProperty(None)
|
text_toolbar_color = ColorProperty(None)
|
||||||
"""
|
"""
|
||||||
Color of labels for text on a toolbar in (r, g, b, a) format.
|
Color of labels for text on a toolbar in (r, g, b, a) or string format.
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
MDDatePicker(
|
MDDatePicker(
|
||||||
primary_color=get_color_from_hex("#72225b"),
|
primary_color="brown",
|
||||||
accent_color=get_color_from_hex("#5d1a4a"),
|
accent_color="darkred",
|
||||||
selector_color=get_color_from_hex("#e93f39"),
|
selector_color="red",
|
||||||
text_toolbar_color=get_color_from_hex("#cccccc"),
|
text_toolbar_color="lightgrey",
|
||||||
)
|
)
|
||||||
|
|
||||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-toolbar-color-date.png
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-toolbar-color-date.png
|
||||||
@ -327,16 +380,16 @@ class BaseDialogPicker(
|
|||||||
|
|
||||||
text_color = ColorProperty(None)
|
text_color = ColorProperty(None)
|
||||||
"""
|
"""
|
||||||
Color of text labels in calendar/clock face in (r, g, b, a) format.
|
Color of text labels in calendar/clock face in (r, g, b, a) or string format.
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
MDDatePicker(
|
MDDatePicker(
|
||||||
primary_color=get_color_from_hex("#72225b"),
|
primary_color="brown",
|
||||||
accent_color=get_color_from_hex("#5d1a4a"),
|
accent_color="darkred",
|
||||||
selector_color=get_color_from_hex("#e93f39"),
|
selector_color="red",
|
||||||
text_toolbar_color=get_color_from_hex("#cccccc"),
|
text_toolbar_color="lightgrey",
|
||||||
text_color=("#ffffff"),
|
text_color="orange",
|
||||||
)
|
)
|
||||||
|
|
||||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-color-date.png
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-color-date.png
|
||||||
@ -348,17 +401,18 @@ class BaseDialogPicker(
|
|||||||
|
|
||||||
text_current_color = ColorProperty(None)
|
text_current_color = ColorProperty(None)
|
||||||
"""
|
"""
|
||||||
Color of the text of the current day of the month/hour in (r, g, b, a) format.
|
Color of the text of the current day of the month/hour in (r, g, b, a)
|
||||||
|
or string format.
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
MDDatePicker(
|
MDDatePicker(
|
||||||
primary_color=get_color_from_hex("#72225b"),
|
primary_color="brown",
|
||||||
accent_color=get_color_from_hex("#5d1a4a"),
|
accent_color="darkred",
|
||||||
selector_color=get_color_from_hex("#e93f39"),
|
selector_color="red",
|
||||||
text_toolbar_color=get_color_from_hex("#cccccc"),
|
text_toolbar_color="lightgrey",
|
||||||
text_color=("#ffffff"),
|
text_color="orange",
|
||||||
text_current_color=get_color_from_hex("#e93f39"),
|
text_current_color="white",
|
||||||
)
|
)
|
||||||
|
|
||||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-current-color-date.png
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-current-color-date.png
|
||||||
@ -375,13 +429,13 @@ class BaseDialogPicker(
|
|||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
MDDatePicker(
|
MDDatePicker(
|
||||||
primary_color=get_color_from_hex("#72225b"),
|
primary_color="brown",
|
||||||
accent_color=get_color_from_hex("#5d1a4a"),
|
accent_color="darkred",
|
||||||
selector_color=get_color_from_hex("#e93f39"),
|
selector_color="red",
|
||||||
text_toolbar_color=get_color_from_hex("#cccccc"),
|
text_toolbar_color="lightgrey",
|
||||||
text_color=("#ffffff"),
|
text_color="orange",
|
||||||
text_current_color=get_color_from_hex("#e93f39"),
|
text_current_color="white",
|
||||||
text_button_color=(1, 1, 1, .5),
|
text_button_color="lightgrey",
|
||||||
)
|
)
|
||||||
|
|
||||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-button-color-date.png
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-button-color-date.png
|
||||||
@ -391,52 +445,124 @@ class BaseDialogPicker(
|
|||||||
and defaults to `None`.
|
and defaults to `None`.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
input_field_background_color = ColorProperty(None)
|
input_field_background_color_normal = ColorProperty(None)
|
||||||
"""
|
"""
|
||||||
Background color of input fields in (r, g, b, a) format.
|
Background color normal of input fields in (r, g, b, a) or string format.
|
||||||
|
|
||||||
|
.. versionadded:: 1.1.0
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
MDDatePicker(
|
MDDatePicker(
|
||||||
primary_color=get_color_from_hex("#72225b"),
|
primary_color="brown",
|
||||||
accent_color=get_color_from_hex("#5d1a4a"),
|
accent_color="darkred",
|
||||||
selector_color=get_color_from_hex("#e93f39"),
|
selector_color="red",
|
||||||
text_toolbar_color=get_color_from_hex("#cccccc"),
|
text_toolbar_color="lightgrey",
|
||||||
text_color=("#ffffff"),
|
text_color="orange",
|
||||||
text_current_color=get_color_from_hex("#e93f39"),
|
text_current_color="white",
|
||||||
input_field_background_color=(1, 1, 1, 0.2),
|
text_button_color="lightgrey",
|
||||||
|
input_field_background_color_normal="coral",
|
||||||
)
|
)
|
||||||
|
|
||||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/input-field-background-color-date.png
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/input-field-background-color-date.png
|
||||||
:align: center
|
:align: center
|
||||||
|
|
||||||
:attr:`input_field_background_color` is an :class:`~kivy.properties.ColorProperty`
|
:attr:`input_field_background_color_normal` is an :class:`~kivy.properties.ColorProperty`
|
||||||
and defaults to `None`.
|
and defaults to `None`.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
input_field_background_color_focus = ColorProperty(None)
|
||||||
|
"""
|
||||||
|
Background color normal of input fields in (r, g, b, a) or string format.
|
||||||
|
|
||||||
|
.. versionadded:: 1.1.0
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
MDDatePicker(
|
||||||
|
primary_color="brown",
|
||||||
|
accent_color="darkred",
|
||||||
|
selector_color="red",
|
||||||
|
text_toolbar_color="lightgrey",
|
||||||
|
text_color="orange",
|
||||||
|
text_current_color="white",
|
||||||
|
text_button_color="lightgrey",
|
||||||
|
input_field_background_color_normal="coral",
|
||||||
|
input_field_background_color_focus="red",
|
||||||
|
)
|
||||||
|
|
||||||
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/input-field-background-color-focus-date.png
|
||||||
|
:align: center
|
||||||
|
|
||||||
|
:attr:`input_field_background_color_focus` is an :class:`~kivy.properties.ColorProperty`
|
||||||
|
and defaults to `None`.
|
||||||
|
"""
|
||||||
|
|
||||||
|
input_field_background_color = ColorProperty(None)
|
||||||
|
"""
|
||||||
|
.. deprecated:: 1.1.0
|
||||||
|
Use :attr:`input_field_background_color_normal` instead.
|
||||||
|
"""
|
||||||
|
|
||||||
input_field_text_color = ColorProperty(None)
|
input_field_text_color = ColorProperty(None)
|
||||||
"""
|
"""
|
||||||
Text color of input fields in (r, g, b, a) format.
|
.. deprecated:: 1.1.0
|
||||||
|
Use :attr:`input_field_text_color_normal` instead.
|
||||||
|
"""
|
||||||
|
|
||||||
Background color of input fields.
|
input_field_text_color_normal = ColorProperty(None)
|
||||||
|
"""
|
||||||
|
Text color normal of input fields in (r, g, b, a) or string format.
|
||||||
|
|
||||||
|
.. versionadded:: 1.1.0
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
MDDatePicker(
|
MDDatePicker(
|
||||||
primary_color=get_color_from_hex("#72225b"),
|
primary_color="brown",
|
||||||
accent_color=get_color_from_hex("#5d1a4a"),
|
accent_color="darkred",
|
||||||
selector_color=get_color_from_hex("#e93f39"),
|
selector_color="red",
|
||||||
text_toolbar_color=get_color_from_hex("#cccccc"),
|
text_toolbar_color="lightgrey",
|
||||||
text_color=("#ffffff"),
|
text_color="orange",
|
||||||
text_current_color=get_color_from_hex("#e93f39"),
|
text_current_color="white",
|
||||||
input_field_background_color=(1, 1, 1, 0.2),
|
text_button_color="lightgrey",
|
||||||
input_field_text_color=(1, 1, 1, 1),
|
input_field_background_color_normal="brown",
|
||||||
|
input_field_background_color_focus="red",
|
||||||
|
input_field_text_color_normal="white",
|
||||||
)
|
)
|
||||||
|
|
||||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/input-field-background-color-date.png
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/input-field-text-color-normal-date.png
|
||||||
:align: center
|
:align: center
|
||||||
|
|
||||||
:attr:`input_field_text_color` is an :class:`~kivy.properties.ColorProperty`
|
:attr:`input_field_text_color_normal` is an :class:`~kivy.properties.ColorProperty`
|
||||||
|
and defaults to `None`.
|
||||||
|
"""
|
||||||
|
|
||||||
|
input_field_text_color_focus = ColorProperty(None)
|
||||||
|
"""
|
||||||
|
Text color focus of input fields in (r, g, b, a) or string format.
|
||||||
|
|
||||||
|
.. versionadded:: 1.1.0
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
MDDatePicker(
|
||||||
|
primary_color="brown",
|
||||||
|
accent_color="darkred",
|
||||||
|
selector_color="red",
|
||||||
|
text_toolbar_color="lightgrey",
|
||||||
|
text_color="orange",
|
||||||
|
text_current_color="white",
|
||||||
|
text_button_color="lightgrey",
|
||||||
|
input_field_background_color_normal="brown",
|
||||||
|
input_field_background_color_focus="red",
|
||||||
|
input_field_text_color_normal="white",
|
||||||
|
)
|
||||||
|
|
||||||
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/input-field-text-color-normal-date.png
|
||||||
|
:align: center
|
||||||
|
|
||||||
|
:attr:`input_field_text_color_focus` is an :class:`~kivy.properties.ColorProperty`
|
||||||
and defaults to `None`.
|
and defaults to `None`.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@ -447,16 +573,18 @@ class BaseDialogPicker(
|
|||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
MDDatePicker(
|
MDDatePicker(
|
||||||
primary_color=get_color_from_hex("#72225b"),
|
primary_color="brown",
|
||||||
accent_color=get_color_from_hex("#5d1a4a"),
|
accent_color="darkred",
|
||||||
selector_color=get_color_from_hex("#e93f39"),
|
selector_color="red",
|
||||||
text_toolbar_color=get_color_from_hex("#cccccc"),
|
text_toolbar_color="lightgrey",
|
||||||
text_color=("#ffffff"),
|
text_color="orange",
|
||||||
text_current_color=get_color_from_hex("#e93f39"),
|
text_current_color="white",
|
||||||
input_field_background_color=(1, 1, 1, 0.2),
|
text_button_color="lightgrey",
|
||||||
input_field_text_color=(1, 1, 1, 1),
|
input_field_background_color_normal="brown",
|
||||||
font_name="Weather.ttf",
|
input_field_background_color_focus="red",
|
||||||
|
input_field_text_color_normal="white",
|
||||||
|
input_field_text_color_focus="lightgrey",
|
||||||
|
font_name="nasalization.ttf",
|
||||||
)
|
)
|
||||||
|
|
||||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/font-name-date.png
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/font-name-date.png
|
||||||
@ -471,6 +599,20 @@ class BaseDialogPicker(
|
|||||||
self.register_event_type("on_save")
|
self.register_event_type("on_save")
|
||||||
self.register_event_type("on_cancel")
|
self.register_event_type("on_cancel")
|
||||||
|
|
||||||
|
def on_input_field_background_color(
|
||||||
|
self, instance, value: str | list | tuple
|
||||||
|
) -> None:
|
||||||
|
"""For supported of current API."""
|
||||||
|
|
||||||
|
self.input_field_background_color_normal = value
|
||||||
|
|
||||||
|
def on_input_field_text_color(
|
||||||
|
self, instance, value: str | list | tuple
|
||||||
|
) -> None:
|
||||||
|
"""For supported of current API."""
|
||||||
|
|
||||||
|
self.input_field_text_color_normal = value
|
||||||
|
|
||||||
def on_save(self, *args) -> None:
|
def on_save(self, *args) -> None:
|
||||||
"""Events called when the "OK" dialog box button is clicked."""
|
"""Events called when the "OK" dialog box button is clicked."""
|
||||||
|
|
||||||
@ -606,13 +748,18 @@ class DatePickerDaySelectableItem(
|
|||||||
|
|
||||||
self.owner.set_selected_widget(self)
|
self.owner.set_selected_widget(self)
|
||||||
|
|
||||||
|
def on_touch_down(self, touch):
|
||||||
|
# If year_layout is active don't dispatch on_touch_down events,
|
||||||
|
# so date items don't consume touch.
|
||||||
|
if not self.owner.ids._year_layout.disabled:
|
||||||
|
return
|
||||||
|
super().on_touch_down(touch)
|
||||||
|
|
||||||
|
|
||||||
class DatePickerYearSelectableItem(RecycleDataViewBehavior, MDLabel):
|
class DatePickerYearSelectableItem(RecycleDataViewBehavior, MDLabel):
|
||||||
"""Implements an item for a pick list of the year."""
|
"""Implements an item for a pick list of the year."""
|
||||||
|
|
||||||
index = None
|
index = None
|
||||||
selected = BooleanProperty(False)
|
|
||||||
selectable = BooleanProperty(True)
|
|
||||||
selected_color = ColorProperty([0, 0, 0, 0])
|
selected_color = ColorProperty([0, 0, 0, 0])
|
||||||
owner = ObjectProperty()
|
owner = ObjectProperty()
|
||||||
|
|
||||||
@ -623,7 +770,7 @@ class DatePickerYearSelectableItem(RecycleDataViewBehavior, MDLabel):
|
|||||||
def on_touch_down(self, touch):
|
def on_touch_down(self, touch):
|
||||||
if super().on_touch_down(touch):
|
if super().on_touch_down(touch):
|
||||||
return True
|
return True
|
||||||
if self.collide_point(*touch.pos) and self.selectable:
|
if self.collide_point(*touch.pos):
|
||||||
self.owner.year = int(self.text)
|
self.owner.year = int(self.text)
|
||||||
# self.owner.sel_year = self.owner.year
|
# self.owner.sel_year = self.owner.year
|
||||||
self.owner.ids.label_full_date.text = self.owner.set_text_full_date(
|
self.owner.ids.label_full_date.text = self.owner.set_text_full_date(
|
||||||
@ -635,7 +782,6 @@ class DatePickerYearSelectableItem(RecycleDataViewBehavior, MDLabel):
|
|||||||
return self.parent.select_with_touch(self.index, touch)
|
return self.parent.select_with_touch(self.index, touch)
|
||||||
|
|
||||||
def apply_selection(self, table_data, index, is_selected):
|
def apply_selection(self, table_data, index, is_selected):
|
||||||
self.selected = is_selected
|
|
||||||
if is_selected:
|
if is_selected:
|
||||||
self.selected_color = (
|
self.selected_color = (
|
||||||
self.owner.selector_color
|
self.owner.selector_color
|
||||||
@ -661,7 +807,7 @@ class DatePickerYearSelectableItem(RecycleDataViewBehavior, MDLabel):
|
|||||||
class MDDatePicker(BaseDialogPicker):
|
class MDDatePicker(BaseDialogPicker):
|
||||||
text_weekday_color = ColorProperty(None)
|
text_weekday_color = ColorProperty(None)
|
||||||
"""
|
"""
|
||||||
Text color of weekday names in (r, g, b, a) format.
|
Text color of weekday names in (r, g, b, a) or string format.
|
||||||
|
|
||||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/md-date-picker-text-weekday-color.png
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/md-date-picker-text-weekday-color.png
|
||||||
:align: center
|
:align: center
|
||||||
@ -813,7 +959,6 @@ class MDDatePicker(BaseDialogPicker):
|
|||||||
_enter_data_field_two = None
|
_enter_data_field_two = None
|
||||||
_enter_data_field_container = None
|
_enter_data_field_container = None
|
||||||
_date_range = []
|
_date_range = []
|
||||||
_sel_day_widget = ObjectProperty()
|
|
||||||
_scale_calendar_layout = NumericProperty(1)
|
_scale_calendar_layout = NumericProperty(1)
|
||||||
_scale_year_layout = NumericProperty(0)
|
_scale_year_layout = NumericProperty(0)
|
||||||
_shift_dialog_height = NumericProperty(0)
|
_shift_dialog_height = NumericProperty(0)
|
||||||
@ -838,11 +983,6 @@ class MDDatePicker(BaseDialogPicker):
|
|||||||
self.month = self.sel_month
|
self.month = self.sel_month
|
||||||
self.year = self.sel_year
|
self.year = self.sel_year
|
||||||
self.day = self.sel_day
|
self.day = self.sel_day
|
||||||
self._current_selected_date = (
|
|
||||||
self.sel_day,
|
|
||||||
self.sel_month,
|
|
||||||
self.sel_year,
|
|
||||||
)
|
|
||||||
super().__init__(**kwargs)
|
super().__init__(**kwargs)
|
||||||
self.theme_cls.bind(device_orientation=self.on_device_orientation)
|
self.theme_cls.bind(device_orientation=self.on_device_orientation)
|
||||||
|
|
||||||
@ -861,16 +1001,6 @@ class MDDatePicker(BaseDialogPicker):
|
|||||||
self.generate_list_widgets_days()
|
self.generate_list_widgets_days()
|
||||||
self.update_calendar(self.sel_year, self.sel_month)
|
self.update_calendar(self.sel_year, self.sel_month)
|
||||||
|
|
||||||
if (
|
|
||||||
not self.max_date
|
|
||||||
and not self.min_date
|
|
||||||
and not self._date_range
|
|
||||||
and self.mode != "range"
|
|
||||||
):
|
|
||||||
# Mark the current day.
|
|
||||||
self.set_month_day(self.sel_day)
|
|
||||||
self._sel_day_widget.dispatch("on_release")
|
|
||||||
|
|
||||||
def on_device_orientation(
|
def on_device_orientation(
|
||||||
self, instance_theme_manager: ThemeManager, orientation_value: str
|
self, instance_theme_manager: ThemeManager, orientation_value: str
|
||||||
) -> None:
|
) -> None:
|
||||||
@ -924,18 +1054,14 @@ class MDDatePicker(BaseDialogPicker):
|
|||||||
Animation(opacity=1, d=0.15).start(self.ids.chevron_left)
|
Animation(opacity=1, d=0.15).start(self.ids.chevron_left)
|
||||||
Animation(opacity=1, d=0.15).start(self.ids.chevron_right)
|
Animation(opacity=1, d=0.15).start(self.ids.chevron_right)
|
||||||
Animation(_scale_year_layout=0, d=0.15).start(self)
|
Animation(_scale_year_layout=0, d=0.15).start(self)
|
||||||
Animation(
|
Animation(_scale_calendar_layout=1, d=0.15).start(self)
|
||||||
_shift_dialog_height=dp(0), _scale_calendar_layout=1, d=0.15
|
|
||||||
).start(self)
|
|
||||||
|
|
||||||
self._calendar_layout.clear_widgets()
|
# Move selection to the same day and month of the selected year.
|
||||||
self.generate_list_widgets_days()
|
self.sel_year = self.year
|
||||||
|
last_day = calendar.monthrange(self.year, self.sel_month)[1]
|
||||||
|
self.sel_day = min(self.sel_day, last_day)
|
||||||
self.update_calendar(self.year, self.month)
|
self.update_calendar(self.year, self.month)
|
||||||
|
|
||||||
if self.mode != "range":
|
|
||||||
self.set_month_day(self.day)
|
|
||||||
self._sel_day_widget.dispatch("on_release")
|
|
||||||
|
|
||||||
def transformation_to_dialog_select_year(self) -> None:
|
def transformation_to_dialog_select_year(self) -> None:
|
||||||
def disabled_chevron_buttons(*args):
|
def disabled_chevron_buttons(*args):
|
||||||
self.ids.chevron_left.disabled = True
|
self.ids.chevron_left.disabled = True
|
||||||
@ -943,15 +1069,20 @@ class MDDatePicker(BaseDialogPicker):
|
|||||||
|
|
||||||
self._select_year_dialog_open = True
|
self._select_year_dialog_open = True
|
||||||
self.ids._year_layout.disabled = False
|
self.ids._year_layout.disabled = False
|
||||||
self._scale_calendar_layout = 0
|
|
||||||
Animation(opacity=0, d=0.15).start(self.ids.chevron_left)
|
Animation(opacity=0, d=0.15).start(self.ids.chevron_left)
|
||||||
Animation(opacity=0, d=0.15).start(self.ids.chevron_right)
|
Animation(opacity=0, d=0.15).start(self.ids.chevron_right)
|
||||||
|
Animation(_scale_calendar_layout=0, d=0.15).start(self)
|
||||||
anim = Animation(_scale_year_layout=1, d=0.15)
|
anim = Animation(_scale_year_layout=1, d=0.15)
|
||||||
anim.bind(on_complete=disabled_chevron_buttons)
|
anim.bind(on_complete=disabled_chevron_buttons)
|
||||||
anim.start(self)
|
anim.start(self)
|
||||||
self.ids.triangle.icon = "menu-up"
|
self.ids.triangle.icon = "menu-up"
|
||||||
self.generate_list_widgets_years()
|
self.generate_list_widgets_years()
|
||||||
self.set_position_to_current_year()
|
self.set_position_to_current_year()
|
||||||
|
if self.min_year <= self.year < self.max_year:
|
||||||
|
index = self.year - self.min_year
|
||||||
|
self.ids._year_layout.children[0].select_node(index)
|
||||||
|
else:
|
||||||
|
self.ids._year_layout.children[0].clear_selection()
|
||||||
|
|
||||||
def transformation_to_dialog_input_date(self) -> None:
|
def transformation_to_dialog_input_date(self) -> None:
|
||||||
def set_date_to_input_field():
|
def set_date_to_input_field():
|
||||||
@ -1063,13 +1194,10 @@ class MDDatePicker(BaseDialogPicker):
|
|||||||
if not self.min_date and not self.max_date:
|
if not self.min_date and not self.max_date:
|
||||||
list_date = self._enter_data_field.get_list_date()
|
list_date = self._enter_data_field.get_list_date()
|
||||||
if len(list_date) == 3 and len(list_date[2]) == 4:
|
if len(list_date) == 3 and len(list_date[2]) == 4:
|
||||||
# self._sel_day_widget.is_selected = False
|
self.sel_day = int(list_date[0])
|
||||||
self.update_calendar(int(list_date[2]), int(list_date[1]))
|
self.sel_month = int(list_date[1])
|
||||||
self.set_month_day(int(list_date[0]))
|
self.sel_year = int(list_date[2])
|
||||||
# self._sel_day_widget.dispatch("on_release")
|
self.update_calendar(self.sel_year, self.sel_month)
|
||||||
if self.mode != "range":
|
|
||||||
self._sel_day_widget.is_selected = False
|
|
||||||
self._sel_day_widget.dispatch("on_release")
|
|
||||||
elif self.min_date and self.max_date:
|
elif self.min_date and self.max_date:
|
||||||
list_min_date = self._enter_data_field.get_list_date()
|
list_min_date = self._enter_data_field.get_list_date()
|
||||||
list_max_date = self._enter_data_field_two.get_list_date()
|
list_max_date = self._enter_data_field_two.get_list_date()
|
||||||
@ -1107,8 +1235,6 @@ class MDDatePicker(BaseDialogPicker):
|
|||||||
def update_calendar_for_date_range(self) -> None:
|
def update_calendar_for_date_range(self) -> None:
|
||||||
# self.compare_date_range()
|
# self.compare_date_range()
|
||||||
self._date_range = self.get_date_range()
|
self._date_range = self.get_date_range()
|
||||||
self._calendar_layout.clear_widgets()
|
|
||||||
self.generate_list_widgets_days()
|
|
||||||
self.update_calendar(self.year, self.month)
|
self.update_calendar(self.year, self.month)
|
||||||
|
|
||||||
def update_text_full_date(self, list_date) -> None:
|
def update_text_full_date(self, list_date) -> None:
|
||||||
@ -1140,79 +1266,72 @@ class MDDatePicker(BaseDialogPicker):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def update_calendar(self, year, month) -> None:
|
def update_calendar(self, year, month) -> None:
|
||||||
try:
|
self.year, self.month = year, month
|
||||||
dates = [x for x in self.calendar.itermonthdates(year, month)]
|
if self.mode == "picker":
|
||||||
except ValueError as e:
|
selected_date = date(self.sel_year, self.sel_month, self.sel_day)
|
||||||
if str(e) == "year is out of range":
|
selected_dates = {selected_date}
|
||||||
pass
|
|
||||||
else:
|
else:
|
||||||
self.year = year
|
selected_dates = {self._start_range_date, self._end_range_date}
|
||||||
self.month = month
|
dates = self.calendar.itermonthdates(year, month)
|
||||||
for idx in range(len(self._calendar_list)):
|
for widget, widget_date in zip_longest(self._calendar_list, dates):
|
||||||
self._calendar_list[idx].current_month = int(self.month)
|
# Only widgets whose dates are in the displayed month are visible.
|
||||||
self._calendar_list[idx].current_year = int(self.year)
|
visible = (
|
||||||
|
widget_date is not None
|
||||||
# Dates of the month not in the range 1-31.
|
and widget_date.month == month
|
||||||
if idx >= len(dates) or dates[idx].month != month:
|
and widget_date.year == year
|
||||||
# self._calendar_list[idx].disabled = True
|
)
|
||||||
self._calendar_list[idx].text = ""
|
widget.text = str(widget_date.day) if visible else ""
|
||||||
# Dates of the month in the range 1-31.
|
widget.current_year = year
|
||||||
else:
|
widget.current_month = month
|
||||||
self._calendar_list[idx].disabled = False
|
widget.is_today = visible and widget_date == self.today
|
||||||
self._calendar_list[idx].text = str(dates[idx].day)
|
widget.is_selected = visible and widget_date in selected_dates
|
||||||
self._calendar_list[idx].is_today = dates[idx] == self.today
|
# I don't understand why, but this line is important. Without this
|
||||||
# The marked date widget has a True value in the `is_selected`
|
# line, some widgets that we are trying to disable remain enabled.
|
||||||
# attribute. In the KV file it is checked if the date widget
|
widget.disabled = False
|
||||||
# (DatePickerDaySelectableItem) has the `is_selected = False`
|
widget.disabled = (
|
||||||
# attribute value, then the date widget is not highlighted.
|
not visible
|
||||||
if (
|
or self.mode == "range"
|
||||||
0
|
and self._date_range
|
||||||
if not self._calendar_list[idx].text
|
and widget_date not in self._date_range
|
||||||
else int(self._calendar_list[idx].text),
|
|
||||||
self._calendar_list[idx].current_month,
|
|
||||||
self._calendar_list[idx].current_year,
|
|
||||||
) == self._current_selected_date:
|
|
||||||
self._calendar_list[idx].is_selected = True
|
|
||||||
else:
|
|
||||||
self._calendar_list[idx].is_selected = False
|
|
||||||
# Dates outside the set range - disabled.
|
|
||||||
if (
|
|
||||||
self.mode == "picker"
|
|
||||||
and self._date_range
|
|
||||||
and self._calendar_list[idx].text
|
|
||||||
) or (
|
|
||||||
self.mode == "range"
|
|
||||||
and self._start_range_date
|
|
||||||
and self._end_range_date
|
|
||||||
and self._calendar_list[idx].text
|
|
||||||
):
|
|
||||||
if (
|
|
||||||
date(
|
|
||||||
self._calendar_list[idx].current_year,
|
|
||||||
self._calendar_list[idx].current_month,
|
|
||||||
int(self._calendar_list[idx].text),
|
|
||||||
)
|
)
|
||||||
not in self._date_range
|
|
||||||
):
|
|
||||||
self._calendar_list[idx].disabled = True
|
|
||||||
|
|
||||||
def get_field(self) -> MDTextField:
|
def get_field(self) -> MDTextField:
|
||||||
"""Creates and returns a text field object used to enter dates."""
|
"""Creates and returns a text field object used to enter dates."""
|
||||||
|
|
||||||
if issubclass(self.input_field_cls, MDTextField):
|
if issubclass(self.input_field_cls, MDTextField):
|
||||||
|
text_color_focus = (
|
||||||
|
self.input_field_text_color_focus
|
||||||
|
if self.input_field_text_color_focus
|
||||||
|
else self.theme_cls.primary_color
|
||||||
|
)
|
||||||
|
text_color_normal = (
|
||||||
|
self.input_field_text_color_normal
|
||||||
|
if self.input_field_text_color_normal
|
||||||
|
else self.theme_cls.disabled_hint_text_color
|
||||||
|
)
|
||||||
|
fill_color_focus = (
|
||||||
|
self.input_field_background_color_focus
|
||||||
|
if self.input_field_background_color_focus
|
||||||
|
else self.theme_cls.bg_dark
|
||||||
|
)
|
||||||
|
fill_color_normal = (
|
||||||
|
self.input_field_background_color_normal
|
||||||
|
if self.input_field_background_color_normal
|
||||||
|
else self.theme_cls.bg_darkest
|
||||||
|
)
|
||||||
|
|
||||||
field = self.input_field_cls(
|
field = self.input_field_cls(
|
||||||
owner=self,
|
owner=self,
|
||||||
helper_text=self.helper_text,
|
helper_text=self.helper_text,
|
||||||
line_color_normal=self.theme_cls.divider_color,
|
fill_color_normal=fill_color_normal,
|
||||||
|
fill_color_focus=fill_color_focus,
|
||||||
|
hint_text_color_normal=text_color_normal,
|
||||||
|
hint_text_color_focus=text_color_focus,
|
||||||
|
text_color_normal=text_color_normal,
|
||||||
|
text_color_focus=text_color_focus,
|
||||||
|
line_color_focus=text_color_focus,
|
||||||
|
line_color_normal=text_color_normal,
|
||||||
)
|
)
|
||||||
field.color_mode = "custom"
|
|
||||||
field.line_color_focus = (
|
|
||||||
self.theme_cls.primary_color
|
|
||||||
if not self.input_field_text_color
|
|
||||||
else self.input_field_text_color
|
|
||||||
)
|
|
||||||
field.current_hint_text_color = field.line_color_focus
|
|
||||||
field._current_hint_text_color = field.line_color_focus
|
|
||||||
return field
|
return field
|
||||||
else:
|
else:
|
||||||
raise TypeError(
|
raise TypeError(
|
||||||
@ -1239,10 +1358,7 @@ class MDDatePicker(BaseDialogPicker):
|
|||||||
"set_text_full_date:\n\t" f"Month [{month}] out of range."
|
"set_text_full_date:\n\t" f"Month [{month}] out of range."
|
||||||
)
|
)
|
||||||
if int(day) > calendar.monthrange(int(year), (month))[1]:
|
if int(day) > calendar.monthrange(int(year), (month))[1]:
|
||||||
raise ValueError(
|
return ""
|
||||||
"set_text_full_date:\n\t"
|
|
||||||
f"Day [{day}] out of range for the month {month}"
|
|
||||||
)
|
|
||||||
date = datetime.date(int(year), int(month), int(day))
|
date = datetime.date(int(year), int(month), int(day))
|
||||||
separator = (
|
separator = (
|
||||||
"\n"
|
"\n"
|
||||||
@ -1345,46 +1461,55 @@ class MDDatePicker(BaseDialogPicker):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def set_selected_widget(self, widget) -> None:
|
def set_selected_widget(self, widget) -> None:
|
||||||
if self._sel_day_widget:
|
self.sel_year = self.year
|
||||||
self._sel_day_widget.is_selected = False
|
self.sel_month = self.month
|
||||||
|
|
||||||
widget.is_selected = True
|
|
||||||
self.sel_month = int(self.month)
|
|
||||||
self.sel_year = int(self.year)
|
|
||||||
self.sel_day = int(widget.text)
|
self.sel_day = int(widget.text)
|
||||||
self._current_selected_date = (
|
self.update_calendar(self.sel_year, self.sel_month)
|
||||||
self.sel_day,
|
|
||||||
self.sel_month,
|
|
||||||
self.sel_year,
|
|
||||||
)
|
|
||||||
self._sel_day_widget = widget
|
|
||||||
|
|
||||||
def set_month_day(self, day) -> None:
|
def set_month_day(self, day) -> None:
|
||||||
for idx in range(len(self._calendar_list)):
|
# This method is no longer used. The code bellow repeats the behavior
|
||||||
if str(day) == str(self._calendar_list[idx].text):
|
# that was previously required of it for backward compatibility
|
||||||
self._sel_day_widget = self._calendar_list[idx]
|
# reasons.
|
||||||
self.sel_day = int(self._calendar_list[idx].text)
|
self.sel_day = day
|
||||||
if self._sel_day_widget:
|
self.update_calendar(self.sel_year, self.sel_month)
|
||||||
self._sel_day_widget.is_selected = False
|
|
||||||
self._sel_day_widget = self._calendar_list[idx]
|
|
||||||
|
|
||||||
def set_position_to_current_year(self) -> None:
|
def set_position_to_current_year(self) -> None:
|
||||||
# TODO: Add the feature to set the position of the list of years
|
year_layout = self.ids._year_layout
|
||||||
# for the current year. This is not currently possible because the
|
# When this method is called for the first time, RecycleView has not
|
||||||
# ``RecycleView`` class does not support this functionality.
|
# yet added widgets to the year list, so we use the default height.
|
||||||
# There is a solution to this problem
|
widget_height = year_layout.children[0].default_size[1]
|
||||||
# - https://github.com/Bakterija/log_fruit/blob/dev/src/app_modules/widgets/app_recycleview/recycleview.py.
|
cols_amount = year_layout.children[0].cols
|
||||||
# But I have not been able to get it to work.
|
rows_amount = math.ceil((self.max_year - self.min_year) / cols_amount)
|
||||||
pass
|
row_index = (self.year - self.min_year) // cols_amount
|
||||||
|
# To find the middle of the current year widget, we add the height of
|
||||||
|
# the rows under this widget with half the widget height.
|
||||||
|
widget_center_y = (rows_amount - row_index - 1 + 0.5) * widget_height
|
||||||
|
viewport_height = year_layout.height
|
||||||
|
year_list_height = rows_amount * widget_height
|
||||||
|
# If there are too few years in the list to fill the entire viewport,
|
||||||
|
# RecycleView displays additional empty space outside the list.
|
||||||
|
# We have to move the viewport up so that this space is displayed
|
||||||
|
# under the years list. Also, this guard condition protects against
|
||||||
|
# the division by zero error below.
|
||||||
|
if viewport_height >= year_list_height:
|
||||||
|
year_layout.scroll_y = 1
|
||||||
|
return
|
||||||
|
viewport_bottom = widget_center_y - 0.5 * viewport_height
|
||||||
|
# We set scroll_y property to the ratio of the actual lifting height
|
||||||
|
# of the viewport to the maximum possible, and clamp this ratio in the
|
||||||
|
# range from 0 to 1 so that the viewport still is in a valid position
|
||||||
|
# if it is impossible to show the widget in the middle.
|
||||||
|
scroll_y = viewport_bottom / (year_list_height - viewport_height)
|
||||||
|
year_layout.scroll_y = min(1, max(0, scroll_y))
|
||||||
|
|
||||||
def generate_list_widgets_years(self) -> None:
|
def generate_list_widgets_years(self) -> None:
|
||||||
|
self.ids._year_layout.data = []
|
||||||
for i, number_year in enumerate(range(self.min_year, self.max_year)):
|
for i, number_year in enumerate(range(self.min_year, self.max_year)):
|
||||||
self.ids._year_layout.data.append(
|
self.ids._year_layout.data.append(
|
||||||
{
|
{
|
||||||
"owner": self,
|
"owner": self,
|
||||||
"text": str(number_year),
|
"text": str(number_year),
|
||||||
"index": i,
|
"index": i,
|
||||||
"selectable": True,
|
|
||||||
"viewclass": "DatePickerYearSelectableItem",
|
"viewclass": "DatePickerYearSelectableItem",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@ -1416,26 +1541,9 @@ class MDDatePicker(BaseDialogPicker):
|
|||||||
Called when "chevron-left" and "chevron-right" buttons are pressed.
|
Called when "chevron-left" and "chevron-right" buttons are pressed.
|
||||||
Switches the calendar to the previous/next month.
|
Switches the calendar to the previous/next month.
|
||||||
"""
|
"""
|
||||||
|
month_delta = 1 if operation == "next" else -1
|
||||||
operation = 1 if operation == "next" else -1
|
year = self.year + (self.month - 1 + month_delta) // 12
|
||||||
month = (
|
month = (self.month - 1 + month_delta) % 12 + 1
|
||||||
12
|
if year <= 0:
|
||||||
if self.month + operation == 0
|
year, month = 1, 1
|
||||||
else 1
|
|
||||||
if self.month + operation == 13
|
|
||||||
else self.month + operation
|
|
||||||
)
|
|
||||||
year = (
|
|
||||||
self.year - 1
|
|
||||||
if self.month + operation == 0
|
|
||||||
else self.year + 1
|
|
||||||
if self.month + operation == 13
|
|
||||||
else self.year
|
|
||||||
)
|
|
||||||
self.update_calendar(year, month)
|
self.update_calendar(year, month)
|
||||||
if self.sel_day:
|
|
||||||
x = calendar.monthrange(year, month)[1]
|
|
||||||
if x < self.sel_day:
|
|
||||||
self.sel_day = (
|
|
||||||
x if year <= self.sel_year and month <= self.sel_year else 1
|
|
||||||
)
|
|
||||||
|
@ -16,7 +16,11 @@ Components/TimePicker
|
|||||||
|
|
||||||
.. rubric:: Usage
|
.. rubric:: Usage
|
||||||
|
|
||||||
.. code-block::
|
.. tabs::
|
||||||
|
|
||||||
|
.. tab:: Declarative KV style
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
from kivy.lang import Builder
|
from kivy.lang import Builder
|
||||||
|
|
||||||
@ -35,6 +39,8 @@ Components/TimePicker
|
|||||||
|
|
||||||
class Test(MDApp):
|
class Test(MDApp):
|
||||||
def build(self):
|
def build(self):
|
||||||
|
self.theme_cls.theme_style = "Dark"
|
||||||
|
self.theme_cls.primary_palette = "Orange"
|
||||||
return Builder.load_string(KV)
|
return Builder.load_string(KV)
|
||||||
|
|
||||||
def show_time_picker(self):
|
def show_time_picker(self):
|
||||||
@ -46,6 +52,38 @@ Components/TimePicker
|
|||||||
|
|
||||||
Test().run()
|
Test().run()
|
||||||
|
|
||||||
|
.. tab:: Declarative python style
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from kivymd.app import MDApp
|
||||||
|
from kivymd.uix.button import MDRaisedButton
|
||||||
|
from kivymd.uix.pickers import MDTimePicker
|
||||||
|
from kivymd.uix.screen import MDScreen
|
||||||
|
|
||||||
|
|
||||||
|
class Test(MDApp):
|
||||||
|
def build(self):
|
||||||
|
self.theme_cls.theme_style = "Dark"
|
||||||
|
self.theme_cls.primary_palette = "Orange"
|
||||||
|
return (
|
||||||
|
MDScreen(
|
||||||
|
MDRaisedButton(
|
||||||
|
text="Open time picker",
|
||||||
|
pos_hint={'center_x': .5, 'center_y': .5},
|
||||||
|
on_release=self.show_time_picker,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
def show_time_picker(self, *args):
|
||||||
|
'''Open time picker dialog.'''
|
||||||
|
|
||||||
|
MDTimePicker().open()
|
||||||
|
|
||||||
|
|
||||||
|
Test().run()
|
||||||
|
|
||||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/MDTimePicker.png
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/MDTimePicker.png
|
||||||
:align: center
|
:align: center
|
||||||
|
|
||||||
@ -91,11 +129,11 @@ Use the :attr:`~MDTimePicker.set_time` method of the
|
|||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
time_dialog = MDTimePicker(
|
MDTimePicker(
|
||||||
primary_color=get_color_from_hex("#72225b"),
|
primary_color="brown",
|
||||||
accent_color=get_color_from_hex("#5d1a4a"),
|
accent_color="red",
|
||||||
text_button_color=(1, 1, 1, 1),
|
text_button_color="white",
|
||||||
)
|
).open()
|
||||||
|
|
||||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/time-picker-customization.png
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/time-picker-customization.png
|
||||||
:align: center
|
:align: center
|
||||||
@ -194,8 +232,8 @@ class TimeInputTextField(MDTextField):
|
|||||||
hour_regx = "^[0-9]$|^0[1-9]$|^1[0-2]$"
|
hour_regx = "^[0-9]$|^0[1-9]$|^1[0-2]$"
|
||||||
minute_regx = "^[0-9]$|^0[0-9]$|^[1-5][0-9]$"
|
minute_regx = "^[0-9]$|^0[0-9]$|^[1-5][0-9]$"
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super().__init__(**kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
Clock.schedule_once(self.set_text)
|
Clock.schedule_once(self.set_text)
|
||||||
self.register_event_type("on_select")
|
self.register_event_type("on_select")
|
||||||
self.bind(text_color_focus=self.setter("hint_text_color_normal"))
|
self.bind(text_color_focus=self.setter("hint_text_color_normal"))
|
||||||
@ -217,6 +255,7 @@ class TimeInputTextField(MDTextField):
|
|||||||
to somehow make them aligned.
|
to somehow make them aligned.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
def set_text(*args):
|
||||||
if not self.text:
|
if not self.text:
|
||||||
self.text = " "
|
self.text = " "
|
||||||
|
|
||||||
@ -229,6 +268,8 @@ class TimeInputTextField(MDTextField):
|
|||||||
if len(self.text) > 1:
|
if len(self.text) > 1:
|
||||||
self.text = self.text.replace(" ", "")
|
self.text = self.text.replace(" ", "")
|
||||||
|
|
||||||
|
Clock.schedule_once(set_text)
|
||||||
|
|
||||||
def on_focus(self, *args) -> None:
|
def on_focus(self, *args) -> None:
|
||||||
super().on_focus(*args)
|
super().on_focus(*args)
|
||||||
if self.text.strip():
|
if self.text.strip():
|
||||||
|
@ -36,7 +36,7 @@ Example
|
|||||||
title: app.title
|
title: app.title
|
||||||
md_bg_color: app.theme_cls.primary_color
|
md_bg_color: app.theme_cls.primary_color
|
||||||
background_palette: 'Primary'
|
background_palette: 'Primary'
|
||||||
elevation: 10
|
elevation: 4
|
||||||
left_action_items: [['menu', lambda x: x]]
|
left_action_items: [['menu', lambda x: x]]
|
||||||
|
|
||||||
MDScrollViewRefreshLayout:
|
MDScrollViewRefreshLayout:
|
||||||
|
@ -29,7 +29,7 @@ MDScreen
|
|||||||
md_bg_color: app.theme_cls.primary_color
|
md_bg_color: app.theme_cls.primary_color
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from kivy.properties import ObjectProperty
|
from kivy.properties import ListProperty, ObjectProperty
|
||||||
from kivy.uix.screenmanager import Screen
|
from kivy.uix.screenmanager import Screen
|
||||||
|
|
||||||
from kivymd.uix import MDAdaptiveWidget
|
from kivymd.uix import MDAdaptiveWidget
|
||||||
@ -44,20 +44,34 @@ class MDScreen(DeclarativeBehavior, Screen, MDAdaptiveWidget):
|
|||||||
see in the :class:`~kivy.uix.screenmanager.Screen` class documentation.
|
see in the :class:`~kivy.uix.screenmanager.Screen` class documentation.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
hero_to = ObjectProperty()
|
hero_to = ObjectProperty(deprecated=True)
|
||||||
"""
|
"""
|
||||||
Must be a :class:`~kivymd.uix.hero.MDHeroTo` class.
|
Must be a :class:`~kivymd.uix.hero.MDHeroTo` class.
|
||||||
|
|
||||||
See the documentation of the
|
See the documentation of the
|
||||||
`MDHeroTo <https://kivymd.readthedocs.io/en/latest/components/hero/>`_
|
`MDHeroTo <https://kivymd.readthedocs.io/en/latest/components/hero/>`_
|
||||||
widget for more detailed information.
|
widget for more detailed information.
|
||||||
|
|
||||||
.. versionchanged:: 1.0.0
|
.. deprecated:: 1.0.0
|
||||||
|
Use attr:`heroes_to` attribute instead.
|
||||||
|
|
||||||
:attr:`hero_to` is an :class:`~kivy.properties.ObjectProperty`
|
:attr:`hero_to` is an :class:`~kivy.properties.ObjectProperty`
|
||||||
and defaults to `None`.
|
and defaults to `None`.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def on_hero_to(self, screen, widget) -> None:
|
heroes_to = ListProperty()
|
||||||
|
"""
|
||||||
|
Must be a list of :class:`~kivymd.uix.hero.MDHeroTo` class.
|
||||||
|
|
||||||
|
.. versionadded:: 1.0.0
|
||||||
|
|
||||||
|
:attr:`heroes_to` is an :class:`~kivy.properties.LiatProperty`
|
||||||
|
and defaults to `[]`.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def on_hero_to(self, screen, widget: MDHeroTo) -> None:
|
||||||
|
"""Called when the value of the :attr:`hero_to` attribute changes."""
|
||||||
|
|
||||||
if not isinstance(widget, MDHeroTo) or not issubclass(
|
if not isinstance(widget, MDHeroTo) or not issubclass(
|
||||||
widget.__class__, MDHeroTo
|
widget.__class__, MDHeroTo
|
||||||
):
|
):
|
||||||
@ -65,3 +79,4 @@ class MDScreen(DeclarativeBehavior, Screen, MDAdaptiveWidget):
|
|||||||
f"The `{widget}` widget must be an `kivymd.uix.hero.MDHeroTo` "
|
f"The `{widget}` widget must be an `kivymd.uix.hero.MDHeroTo` "
|
||||||
f"class or inherited from this class"
|
f"class or inherited from this class"
|
||||||
)
|
)
|
||||||
|
self.heroes_to = [widget]
|
||||||
|
@ -8,8 +8,23 @@ Components/ScreenManager
|
|||||||
If you want to use Hero animations you need to use
|
If you want to use Hero animations you need to use
|
||||||
:class:`~kivymd.uix.screenmanager.MDScreenManager` not
|
:class:`~kivymd.uix.screenmanager.MDScreenManager` not
|
||||||
:class:`~kivy.uix.screenmanager.ScreenManager` class.
|
:class:`~kivy.uix.screenmanager.ScreenManager` class.
|
||||||
|
|
||||||
|
Transition
|
||||||
|
----------
|
||||||
|
|
||||||
|
:class:`~kivymd.uix.screenmanager.MDScreenManager` class supports the following
|
||||||
|
transitions:
|
||||||
|
|
||||||
|
- :class:`~kivymd.uix.transition.MDFadeSlideTransition`
|
||||||
|
- :class:`~kivymd.uix.transition.MDSlideTransition`
|
||||||
|
- :class:`~kivymd.uix.transition.MDSwapTransition`
|
||||||
|
|
||||||
|
You need to use the :class:`~kivymd.uix.screenmanager.MDScreenManager` class
|
||||||
|
when you want to use hero animations on your screens. If you don't need hero
|
||||||
|
animation use the :class:`~kivy.uix.screenmanager.ScreenManager` class.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from kivy import Logger
|
||||||
from kivy.clock import Clock
|
from kivy.clock import Clock
|
||||||
from kivy.properties import ListProperty, StringProperty
|
from kivy.properties import ListProperty, StringProperty
|
||||||
from kivy.uix.screenmanager import ScreenManager
|
from kivy.uix.screenmanager import ScreenManager
|
||||||
@ -21,17 +36,22 @@ from kivymd.uix.hero import MDHeroFrom
|
|||||||
class MDScreenManager(DeclarativeBehavior, ScreenManager):
|
class MDScreenManager(DeclarativeBehavior, ScreenManager):
|
||||||
"""
|
"""
|
||||||
Screen manager. This is the main class that will control your
|
Screen manager. This is the main class that will control your
|
||||||
:class:`~kivymd.uix.screen.MDScreen` stack and memory. For more
|
:class:`~kivymd.uix.screen.MDScreen` stack and memory.
|
||||||
|
|
||||||
|
For more
|
||||||
information, see in the :class:`~kivy.uix.screenmanager.ScreenManager`
|
information, see in the :class:`~kivy.uix.screenmanager.ScreenManager`
|
||||||
class documentation.
|
class documentation.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
current_hero = StringProperty(None)
|
current_hero = StringProperty(None, deprecated=True)
|
||||||
"""
|
"""
|
||||||
The name of the current tag for the :class:`~kivymd.uix.hero.MDHeroFrom`
|
The name of the current tag for the :class:`~kivymd.uix.hero.MDHeroFrom`
|
||||||
and :class:`~kivymd.uix.hero.MDHeroTo` objects that will be animated when
|
and :class:`~kivymd.uix.hero.MDHeroTo` objects that will be animated when
|
||||||
animating the transition between screens.
|
animating the transition between screens.
|
||||||
|
|
||||||
|
.. deprecated:: 1.1.0
|
||||||
|
Use :attr:`current_heroes` attribute instead.
|
||||||
|
|
||||||
See the `Hero <https://kivymd.readthedocs.io/en/latest/components/hero/>`_
|
See the `Hero <https://kivymd.readthedocs.io/en/latest/components/hero/>`_
|
||||||
module documentation for more information about creating and using Hero
|
module documentation for more information about creating and using Hero
|
||||||
animations.
|
animations.
|
||||||
@ -40,6 +60,17 @@ class MDScreenManager(DeclarativeBehavior, ScreenManager):
|
|||||||
and defaults to `None`.
|
and defaults to `None`.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
current_heroes = ListProperty()
|
||||||
|
"""
|
||||||
|
A list of names (tags) of heroes that need to be animated when moving
|
||||||
|
to the next screen.
|
||||||
|
|
||||||
|
.. versionadded:: 1.1.0
|
||||||
|
|
||||||
|
:attr:`current_heroes` is an :class:`~kivy.properties.ListProperty`
|
||||||
|
and defaults to `[]`.
|
||||||
|
"""
|
||||||
|
|
||||||
# Collection of `MDHeroFrom` objects on all screens of the current
|
# Collection of `MDHeroFrom` objects on all screens of the current
|
||||||
# screen manager.
|
# screen manager.
|
||||||
_heroes_data = ListProperty()
|
_heroes_data = ListProperty()
|
||||||
@ -58,28 +89,48 @@ class MDScreenManager(DeclarativeBehavior, ScreenManager):
|
|||||||
|
|
||||||
self.transition = MDSlideTransition()
|
self.transition = MDSlideTransition()
|
||||||
|
|
||||||
def get_hero_from_widget(self) -> None:
|
def get_hero_from_widget(self) -> list:
|
||||||
"""
|
"""
|
||||||
Get an :class:`~kivymd.uix.hero.MDHeroTo` object with the
|
Get a list of :class:`~kivymd.uix.hero.MDHeroFrom` objects according
|
||||||
:attr:`~current_hero` tag.
|
to the tag names specified in the :attr:`~current_heroes` list.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
hero_from_widget = None
|
hero_from_widget = []
|
||||||
|
|
||||||
|
for name_hero in self.current_heroes:
|
||||||
for hero_widget in self._heroes_data:
|
for hero_widget in self._heroes_data:
|
||||||
if isinstance(hero_widget, MDHeroFrom) or issubclass(
|
if isinstance(hero_widget, MDHeroFrom) or issubclass(
|
||||||
hero_widget.__class__, MDHeroFrom
|
hero_widget.__class__, MDHeroFrom
|
||||||
):
|
):
|
||||||
if hero_widget.tag == self.current_hero:
|
if hero_widget.tag == name_hero:
|
||||||
hero_from_widget = hero_widget
|
hero_from_widget.append(hero_widget)
|
||||||
break
|
|
||||||
|
|
||||||
return hero_from_widget
|
return hero_from_widget
|
||||||
|
|
||||||
|
def on_current_hero(self, instance, value: str) -> None:
|
||||||
|
"""
|
||||||
|
Called when the value of the :attr:`current_hero` attribute changes.
|
||||||
|
"""
|
||||||
|
|
||||||
|
Logger.warning(
|
||||||
|
"KivyMD: "
|
||||||
|
"`kivymd/uix/screenmanager.MDScreenManager.current_hero` "
|
||||||
|
"attribute is deprecated. "
|
||||||
|
"Use `kivymd/uix/screenmanager.MDScreenManager.current_heroes` "
|
||||||
|
"attribute instead."
|
||||||
|
)
|
||||||
|
if value:
|
||||||
|
self.current_heroes = [value]
|
||||||
|
else:
|
||||||
|
self.current_heroes = []
|
||||||
|
|
||||||
def add_widget(self, widget, *args, **kwargs):
|
def add_widget(self, widget, *args, **kwargs):
|
||||||
super().add_widget(widget, *args, **kwargs)
|
super().add_widget(widget, *args, **kwargs)
|
||||||
Clock.schedule_once(lambda x: self._create_heroes_data(widget))
|
Clock.schedule_once(lambda x: self._create_heroes_data(widget))
|
||||||
|
|
||||||
|
# TODO: Add a method to delete an object from the arrt:`_heroes_data`
|
||||||
|
# collection when deleting an object using the `remove_widget` method.
|
||||||
|
|
||||||
def _create_heroes_data(self, widget):
|
def _create_heroes_data(self, widget):
|
||||||
def find_hero_widget(child_widget):
|
def find_hero_widget(child_widget):
|
||||||
widget_hero = None
|
widget_hero = None
|
||||||
|
@ -15,8 +15,11 @@
|
|||||||
pos_hint: {"center_y": .5}
|
pos_hint: {"center_y": .5}
|
||||||
x: root._segment_switch_x
|
x: root._segment_switch_x
|
||||||
md_bg_color: root.segment_color
|
md_bg_color: root.segment_color
|
||||||
elevation: 6
|
elevation: 2
|
||||||
_radius: root.radius[0] - 4
|
_radius: root.radius[0] - 4
|
||||||
|
width:
|
||||||
|
segment_panel.width / segment_panel.children_number \
|
||||||
|
- segment_panel.spacing
|
||||||
|
|
||||||
SegmentPanel:
|
SegmentPanel:
|
||||||
id: segment_panel
|
id: segment_panel
|
||||||
|
@ -10,6 +10,10 @@ Components/SegmentedControl
|
|||||||
Usage
|
Usage
|
||||||
=====
|
=====
|
||||||
|
|
||||||
|
.. tabs::
|
||||||
|
|
||||||
|
.. tab:: Declarative KV style
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
from kivy.lang import Builder
|
from kivy.lang import Builder
|
||||||
@ -34,34 +38,49 @@ Usage
|
|||||||
'''
|
'''
|
||||||
|
|
||||||
|
|
||||||
class Test(MDApp):
|
class Example(MDApp):
|
||||||
def build(self):
|
def build(self):
|
||||||
|
self.theme_cls.theme_style = "Dark"
|
||||||
|
self.theme_cls.primary_palette = "Orange"
|
||||||
return Builder.load_string(KV)
|
return Builder.load_string(KV)
|
||||||
|
|
||||||
|
|
||||||
Test().run()
|
Example().run()
|
||||||
|
|
||||||
Or only in python code:
|
.. tab:: Declarative python style
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
from kivymd.app import MDApp
|
from kivymd.app import MDApp
|
||||||
from kivymd.uix.screen import MDScreen
|
from kivymd.uix.screen import MDScreen
|
||||||
from kivymd.uix.segmentedcontrol import MDSegmentedControl, MDSegmentedControlItem
|
from kivymd.uix.segmentedcontrol import (
|
||||||
|
MDSegmentedControl, MDSegmentedControlItem
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class Test(MDApp):
|
class Example(MDApp):
|
||||||
def build(self):
|
def build(self):
|
||||||
screen = MDScreen()
|
self.theme_cls.theme_style = "Dark"
|
||||||
segment_control = MDSegmentedControl(pos_hint={"center_x": .5, "center_y": .5})
|
self.theme_cls.primary_palette = "Orange"
|
||||||
segment_control.add_widget(MDSegmentedControlItem(text="Male"))
|
return (
|
||||||
segment_control.add_widget(MDSegmentedControlItem(text="Female"))
|
MDScreen(
|
||||||
segment_control.add_widget(MDSegmentedControlItem(text="All"))
|
MDSegmentedControl(
|
||||||
screen.add_widget(segment_control)
|
MDSegmentedControlItem(
|
||||||
return screen
|
text="Male"
|
||||||
|
),
|
||||||
|
MDSegmentedControlItem(
|
||||||
|
text="Female"
|
||||||
|
),
|
||||||
|
MDSegmentedControlItem(
|
||||||
|
text="All"
|
||||||
|
),
|
||||||
|
pos_hint={"center_x": 0.5, "center_y": 0.5}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
Test().run()
|
Example().run()
|
||||||
|
|
||||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/md-segmented-control-usage.gif
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/md-segmented-control-usage.gif
|
||||||
:align: center
|
:align: center
|
||||||
@ -117,12 +136,22 @@ with open(
|
|||||||
|
|
||||||
|
|
||||||
class MDSegmentedControlItem(MDLabel):
|
class MDSegmentedControlItem(MDLabel):
|
||||||
"""Implements a label to place on the :class:`~SegmentPanel` panel."""
|
"""
|
||||||
|
Implements a label to place on the :class:`~SegmentPanel` panel.
|
||||||
|
|
||||||
|
See :class:`~kivymd.uix.label.MDLabel` class documentation for more
|
||||||
|
information.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
# TODO: Add an attribute for the color of the active segment label.
|
# TODO: Add an attribute for the color of the active segment label.
|
||||||
class MDSegmentedControl(MDRelativeLayout, ThemableBehavior):
|
class MDSegmentedControl(MDRelativeLayout, ThemableBehavior):
|
||||||
"""
|
"""
|
||||||
|
Implements a segmented control panel.
|
||||||
|
|
||||||
|
Relative layout class. For more information, see in the
|
||||||
|
:class:`~kivy.uix.relativelayout.RelativeLayout` class documentation.
|
||||||
|
|
||||||
:Events:
|
:Events:
|
||||||
`on_active`
|
`on_active`
|
||||||
Called when the segment is activated.
|
Called when the segment is activated.
|
||||||
@ -135,7 +164,7 @@ class MDSegmentedControl(MDRelativeLayout, ThemableBehavior):
|
|||||||
.. code-block:: kv
|
.. code-block:: kv
|
||||||
|
|
||||||
MDSegmentedControl:
|
MDSegmentedControl:
|
||||||
md_bg_color: "#451938"
|
md_bg_color: "brown"
|
||||||
|
|
||||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/md-segmented-control-md-bg-color.png
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/md-segmented-control-md-bg-color.png
|
||||||
:align: center
|
:align: center
|
||||||
@ -151,8 +180,8 @@ class MDSegmentedControl(MDRelativeLayout, ThemableBehavior):
|
|||||||
.. code-block:: kv
|
.. code-block:: kv
|
||||||
|
|
||||||
MDSegmentedControl:
|
MDSegmentedControl:
|
||||||
md_bg_color: "#451938"
|
md_bg_color: "brown"
|
||||||
segment_color: "#e4514f"
|
segment_color: "red"
|
||||||
|
|
||||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/md-segmented-control-segment-color.png
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/md-segmented-control-segment-color.png
|
||||||
:align: center
|
:align: center
|
||||||
@ -160,8 +189,8 @@ class MDSegmentedControl(MDRelativeLayout, ThemableBehavior):
|
|||||||
.. code-block:: kv
|
.. code-block:: kv
|
||||||
|
|
||||||
MDSegmentedControl:
|
MDSegmentedControl:
|
||||||
md_bg_color: "#451938"
|
md_bg_color: "brown"
|
||||||
segment_color: "#e4514f"
|
segment_color: "red"
|
||||||
|
|
||||||
MDSegmentedControlItem:
|
MDSegmentedControlItem:
|
||||||
text: "[color=fff]Male[/color]"
|
text: "[color=fff]Male[/color]"
|
||||||
@ -196,9 +225,9 @@ class MDSegmentedControl(MDRelativeLayout, ThemableBehavior):
|
|||||||
.. code-block:: kv
|
.. code-block:: kv
|
||||||
|
|
||||||
MDSegmentedControl:
|
MDSegmentedControl:
|
||||||
md_bg_color: "#451938"
|
md_bg_color: "brown"
|
||||||
segment_color: "#e4514f"
|
segment_color: "red"
|
||||||
separator_color: 1, 1, 1, 1
|
separator_color: "white"
|
||||||
|
|
||||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/md-segmented-control-separator-color.png
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/md-segmented-control-separator-color.png
|
||||||
:align: center
|
:align: center
|
||||||
@ -255,9 +284,6 @@ class MDSegmentedControl(MDRelativeLayout, ThemableBehavior):
|
|||||||
|
|
||||||
Clock.schedule_once(self.set_default_colors)
|
Clock.schedule_once(self.set_default_colors)
|
||||||
Clock.schedule_once(self._remove_last_separator)
|
Clock.schedule_once(self._remove_last_separator)
|
||||||
# FIXME: Sometimes this interval is not enough to get the width
|
|
||||||
# of the segment label textures.
|
|
||||||
Clock.schedule_once(self._set_width_segment_switch, 2.2)
|
|
||||||
|
|
||||||
def set_default_colors(self, *args) -> None:
|
def set_default_colors(self, *args) -> None:
|
||||||
"""
|
"""
|
||||||
@ -313,6 +339,10 @@ class MDSegmentedControl(MDRelativeLayout, ThemableBehavior):
|
|||||||
self.ids.segment_panel.add_widget(widget)
|
self.ids.segment_panel.add_widget(widget)
|
||||||
separator = MDSeparator(orientation="vertical")
|
separator = MDSeparator(orientation="vertical")
|
||||||
self.ids.segment_panel.add_widget(separator)
|
self.ids.segment_panel.add_widget(separator)
|
||||||
|
if not self.ids.segment_panel._started:
|
||||||
|
self.ids.segment_panel._started = True
|
||||||
|
else:
|
||||||
|
self.ids.segment_panel.children_number += 1
|
||||||
Clock.schedule_once(
|
Clock.schedule_once(
|
||||||
lambda x: self.update_separator_color(separator)
|
lambda x: self.update_separator_color(separator)
|
||||||
)
|
)
|
||||||
@ -326,15 +356,6 @@ class MDSegmentedControl(MDRelativeLayout, ThemableBehavior):
|
|||||||
self.current_active_segment = widget
|
self.current_active_segment = widget
|
||||||
self.dispatch("on_active", widget)
|
self.dispatch("on_active", widget)
|
||||||
|
|
||||||
def _set_width_segment_switch(self, *args):
|
|
||||||
"""
|
|
||||||
Sets the width of the switch. I think this is not done quite correctly.
|
|
||||||
"""
|
|
||||||
|
|
||||||
self.ids.segment_switch.width = self.ids.segment_panel.children[
|
|
||||||
0
|
|
||||||
].width + dp(12)
|
|
||||||
|
|
||||||
def _remove_last_separator(self, *args):
|
def _remove_last_separator(self, *args):
|
||||||
self.ids.segment_panel.remove_widget(self.ids.segment_panel.children[0])
|
self.ids.segment_panel.remove_widget(self.ids.segment_panel.children[0])
|
||||||
|
|
||||||
@ -350,3 +371,7 @@ class SegmentPanel(MDBoxLayout):
|
|||||||
Implements a panel for placing items - :class:`~MDSegmentedControlItem`
|
Implements a panel for placing items - :class:`~MDSegmentedControlItem`
|
||||||
for the :class:`~MDSegmentedControl` class.
|
for the :class:`~MDSegmentedControl` class.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
children_number = NumericProperty(1)
|
||||||
|
|
||||||
|
_started = BooleanProperty(defaultvalue=False)
|
||||||
|
@ -101,7 +101,7 @@
|
|||||||
size_hint: None, None
|
size_hint: None, None
|
||||||
size: dp(24), dp(24)
|
size: dp(24), dp(24)
|
||||||
elevation:
|
elevation:
|
||||||
(8 if root.active else 5) \
|
(2.5 if root.active else 1) \
|
||||||
if app.theme_cls.material_style != "M3" else \
|
if app.theme_cls.material_style != "M3" else \
|
||||||
0
|
0
|
||||||
pos:
|
pos:
|
||||||
|
@ -192,15 +192,10 @@ from kivy.properties import (
|
|||||||
)
|
)
|
||||||
from kivy.uix.behaviors import ToggleButtonBehavior
|
from kivy.uix.behaviors import ToggleButtonBehavior
|
||||||
from kivy.uix.floatlayout import FloatLayout
|
from kivy.uix.floatlayout import FloatLayout
|
||||||
from kivy.utils import get_color_from_hex
|
|
||||||
|
|
||||||
from kivymd import uix_path
|
from kivymd import uix_path
|
||||||
from kivymd.color_definitions import colors
|
|
||||||
from kivymd.theming import ThemableBehavior
|
from kivymd.theming import ThemableBehavior
|
||||||
from kivymd.uix.behaviors import (
|
from kivymd.uix.behaviors import CircularRippleBehavior, CommonElevationBehavior
|
||||||
CircularRippleBehavior,
|
|
||||||
FakeCircularElevationBehavior,
|
|
||||||
)
|
|
||||||
from kivymd.uix.floatlayout import MDFloatLayout
|
from kivymd.uix.floatlayout import MDFloatLayout
|
||||||
from kivymd.uix.label import MDIcon
|
from kivymd.uix.label import MDIcon
|
||||||
|
|
||||||
@ -361,8 +356,10 @@ class MDCheckbox(CircularRippleBehavior, ToggleButtonBehavior, MDIcon):
|
|||||||
disabled=self.update_color,
|
disabled=self.update_color,
|
||||||
state=self.update_color,
|
state=self.update_color,
|
||||||
)
|
)
|
||||||
self.theme_cls.bind(primary_color=self.update_primary_color)
|
self.theme_cls.bind(
|
||||||
self.theme_cls.bind(theme_style=self.update_primary_color)
|
theme_style=self.update_primary_color,
|
||||||
|
primary_color=self.update_primary_color,
|
||||||
|
)
|
||||||
self.update_icon()
|
self.update_icon()
|
||||||
self.update_color()
|
self.update_color()
|
||||||
|
|
||||||
@ -423,7 +420,7 @@ class ThumbIcon(MDIcon):
|
|||||||
|
|
||||||
|
|
||||||
class Thumb(
|
class Thumb(
|
||||||
FakeCircularElevationBehavior,
|
CommonElevationBehavior,
|
||||||
CircularRippleBehavior,
|
CircularRippleBehavior,
|
||||||
MDFloatLayout,
|
MDFloatLayout,
|
||||||
):
|
):
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
#:import colors kivymd.color_definitions.colors
|
#:import colors kivymd.color_definitions.colors
|
||||||
|
|
||||||
|
|
||||||
<HintBoxContainer@MDCard+FakeRectangularElevationBehavior>
|
<HintBoxContainer@MDCard>
|
||||||
|
|
||||||
|
|
||||||
<MDSlider>
|
<MDSlider>
|
||||||
@ -131,16 +131,20 @@
|
|||||||
) \
|
) \
|
||||||
) \
|
) \
|
||||||
)
|
)
|
||||||
elevation: 0 if root._is_off else (4 if root.active else 2)
|
elevation: 0 if root._is_off else (3 if root.active else 1)
|
||||||
|
|
||||||
HintBoxContainer:
|
HintBoxContainer:
|
||||||
id: hint_box
|
id: hint_box
|
||||||
size_hint: None, None
|
size_hint: None, None
|
||||||
md_bg_color: root.hint_bg_color
|
md_bg_color: root.hint_bg_color if root.hint_bg_color else [0, 0, 0, 0]
|
||||||
elevation: 0
|
elevation: 1.5
|
||||||
opacity: 1 if root.active else 0
|
opacity: 1 if root.active else 0
|
||||||
radius: root.hint_radius
|
radius: root.hint_radius
|
||||||
padding: "6dp", "6dp", "6dp", "8dp"
|
padding: "6dp", "6dp", "6dp", "8dp"
|
||||||
|
shadow_color:
|
||||||
|
([0, 0, 0, 0.6] if root.hint_bg_color else [0, 0, 0, 0]) \
|
||||||
|
if root.active else \
|
||||||
|
[0, 0, 0, 0]
|
||||||
size:
|
size:
|
||||||
lbl_value.width + self.padding[0] * 2, \
|
lbl_value.width + self.padding[0] * 2, \
|
||||||
lbl_value.height + self.padding[0]
|
lbl_value.height + self.padding[0]
|
||||||
|
@ -82,7 +82,7 @@ class MDSlider(ThemableBehavior, Slider):
|
|||||||
and defaults to `True`.
|
and defaults to `True`.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
hint_bg_color = ColorProperty([0, 0, 0, 0])
|
hint_bg_color = ColorProperty(None)
|
||||||
"""
|
"""
|
||||||
Hint rectangle color in (r.g.b.a) format.
|
Hint rectangle color in (r.g.b.a) format.
|
||||||
|
|
||||||
|
@ -38,8 +38,8 @@ Example
|
|||||||
|
|
||||||
from kivy.lang.builder import Builder
|
from kivy.lang.builder import Builder
|
||||||
|
|
||||||
|
from kivymd.app import MDApp
|
||||||
from kivymd.uix.card import MDCard
|
from kivymd.uix.card import MDCard
|
||||||
from kivymd.uix.behaviors import RoundedRectangularElevationBehavior
|
|
||||||
|
|
||||||
KV = '''
|
KV = '''
|
||||||
<CardItem>
|
<CardItem>
|
||||||
@ -47,7 +47,6 @@ Example
|
|||||||
height: "86dp"
|
height: "86dp"
|
||||||
padding: "4dp"
|
padding: "4dp"
|
||||||
radius: 12
|
radius: 12
|
||||||
elevation: 4
|
|
||||||
|
|
||||||
FitImage:
|
FitImage:
|
||||||
source: "avatar.jpg"
|
source: "avatar.jpg"
|
||||||
@ -95,8 +94,10 @@ Example
|
|||||||
'''
|
'''
|
||||||
|
|
||||||
|
|
||||||
class CardItem(MDCard, RoundedRectangularElevationBehavior):
|
class CardItem(MDCard):
|
||||||
pass
|
def __init__(self, *args, **kwargs):
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
self.elevation = 3
|
||||||
|
|
||||||
|
|
||||||
class Example(MDApp):
|
class Example(MDApp):
|
||||||
@ -192,7 +193,6 @@ class MDSliverAppbar(MDBoxLayout, ThemableBehavior):
|
|||||||
|
|
||||||
from kivymd.uix.card import MDCard
|
from kivymd.uix.card import MDCard
|
||||||
from kivymd.uix.toolbar import MDTopAppBar
|
from kivymd.uix.toolbar import MDTopAppBar
|
||||||
from kivymd.uix.behaviors import RoundedRectangularElevationBehavior
|
|
||||||
|
|
||||||
KV = '''
|
KV = '''
|
||||||
#:import SliverToolbar __main__.SliverToolbar
|
#:import SliverToolbar __main__.SliverToolbar
|
||||||
@ -203,7 +203,6 @@ class MDSliverAppbar(MDBoxLayout, ThemableBehavior):
|
|||||||
height: "86dp"
|
height: "86dp"
|
||||||
padding: "4dp"
|
padding: "4dp"
|
||||||
radius: 12
|
radius: 12
|
||||||
elevation: 4
|
|
||||||
|
|
||||||
FitImage:
|
FitImage:
|
||||||
source: "avatar.jpg"
|
source: "avatar.jpg"
|
||||||
@ -252,13 +251,16 @@ class MDSliverAppbar(MDBoxLayout, ThemableBehavior):
|
|||||||
'''
|
'''
|
||||||
|
|
||||||
|
|
||||||
class CardItem(MDCard, RoundedRectangularElevationBehavior):
|
class CardItem(MDCard):
|
||||||
pass
|
def __init__(self, *args, **kwargs):
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
self.elevation = 3
|
||||||
|
|
||||||
|
|
||||||
class SliverToolbar(MDTopAppBar):
|
class SliverToolbar(MDTopAppBar):
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
super().__init__(**kwargs)
|
super().__init__(**kwargs)
|
||||||
|
self.shadow_color = (0, 0, 0, 0)
|
||||||
self.type_height = "medium"
|
self.type_height = "medium"
|
||||||
self.headline_text = "Headline medium"
|
self.headline_text = "Headline medium"
|
||||||
self.left_action_items = [["arrow-left", lambda x: x]]
|
self.left_action_items = [["arrow-left", lambda x: x]]
|
||||||
@ -422,6 +424,7 @@ class MDSliverAppbar(MDBoxLayout, ThemableBehavior):
|
|||||||
# Adding a custom MDTopAppBar object.
|
# Adding a custom MDTopAppBar object.
|
||||||
if issubclass(instance_toolbar_cls.__class__, MDTopAppBar):
|
if issubclass(instance_toolbar_cls.__class__, MDTopAppBar):
|
||||||
instance_toolbar_cls.pos_hint = {"top": 1}
|
instance_toolbar_cls.pos_hint = {"top": 1}
|
||||||
|
instance_toolbar_cls.elevation = 0
|
||||||
self.ids.float_box.add_widget(instance_toolbar_cls)
|
self.ids.float_box.add_widget(instance_toolbar_cls)
|
||||||
else:
|
else:
|
||||||
raise MDSliverAppbarException(
|
raise MDSliverAppbarException(
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
padding: "10dp", "10dp", "10dp", "10dp"
|
padding: "10dp", "10dp", "10dp", "10dp"
|
||||||
md_bg_color: "323232" if not root.bg_color else root.bg_color
|
md_bg_color: "323232" if not root.bg_color else root.bg_color
|
||||||
radius: root.radius
|
radius: root.radius
|
||||||
elevation: 11 if root.padding else 0
|
elevation: 4 if root.padding else 0
|
||||||
|
|
||||||
canvas:
|
canvas:
|
||||||
Color:
|
Color:
|
||||||
|
@ -284,7 +284,6 @@ from kivy.properties import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
from kivymd import uix_path
|
from kivymd import uix_path
|
||||||
from kivymd.uix.behaviors import FakeRectangularElevationBehavior
|
|
||||||
from kivymd.uix.button import BaseButton
|
from kivymd.uix.button import BaseButton
|
||||||
from kivymd.uix.card import MDCard
|
from kivymd.uix.card import MDCard
|
||||||
|
|
||||||
@ -294,7 +293,7 @@ with open(
|
|||||||
Builder.load_string(kv_file.read())
|
Builder.load_string(kv_file.read())
|
||||||
|
|
||||||
|
|
||||||
class BaseSnackbar(MDCard, FakeRectangularElevationBehavior):
|
class BaseSnackbar(MDCard):
|
||||||
"""
|
"""
|
||||||
:Events:
|
:Events:
|
||||||
:attr:`on_open`
|
:attr:`on_open`
|
||||||
|
@ -38,7 +38,7 @@ Example
|
|||||||
MDTopAppBar:
|
MDTopAppBar:
|
||||||
id: toolbar
|
id: toolbar
|
||||||
title: "MDSwiper"
|
title: "MDSwiper"
|
||||||
elevation: 10
|
elevation: 4
|
||||||
pos_hint: {"top": 1}
|
pos_hint: {"top": 1}
|
||||||
|
|
||||||
MDSwiper:
|
MDSwiper:
|
||||||
@ -142,7 +142,7 @@ Example
|
|||||||
MDTopAppBar:
|
MDTopAppBar:
|
||||||
id: toolbar
|
id: toolbar
|
||||||
title: "MDSwiper"
|
title: "MDSwiper"
|
||||||
elevation: 10
|
elevation: 4
|
||||||
pos_hint: {"top": 1}
|
pos_hint: {"top": 1}
|
||||||
|
|
||||||
MDSwiper:
|
MDSwiper:
|
||||||
@ -203,7 +203,6 @@ from kivy.animation import Animation
|
|||||||
from kivy.clock import Clock
|
from kivy.clock import Clock
|
||||||
from kivy.core.window import Window
|
from kivy.core.window import Window
|
||||||
from kivy.effects.dampedscroll import DampedScrollEffect
|
from kivy.effects.dampedscroll import DampedScrollEffect
|
||||||
from kivy.event import EventDispatcher
|
|
||||||
from kivy.lang.builder import Builder
|
from kivy.lang.builder import Builder
|
||||||
from kivy.properties import (
|
from kivy.properties import (
|
||||||
BooleanProperty,
|
BooleanProperty,
|
||||||
@ -212,7 +211,6 @@ from kivy.properties import (
|
|||||||
StringProperty,
|
StringProperty,
|
||||||
)
|
)
|
||||||
from kivy.uix.anchorlayout import AnchorLayout
|
from kivy.uix.anchorlayout import AnchorLayout
|
||||||
from kivy.uix.boxlayout import BoxLayout
|
|
||||||
from kivy.utils import platform
|
from kivy.utils import platform
|
||||||
|
|
||||||
from kivymd import uix_path
|
from kivymd import uix_path
|
||||||
@ -294,7 +292,7 @@ class MDSwiperItem(MDBoxLayout):
|
|||||||
anim.start(self)
|
anim.start(self)
|
||||||
|
|
||||||
|
|
||||||
class MDSwiper(MDScrollView, EventDispatcher):
|
class MDSwiper(MDScrollView):
|
||||||
items_spacing = NumericProperty("20dp")
|
items_spacing = NumericProperty("20dp")
|
||||||
"""
|
"""
|
||||||
The space between each :class:`MDSwiperItem`.
|
The space between each :class:`MDSwiperItem`.
|
||||||
|
@ -79,6 +79,10 @@
|
|||||||
layout: layout
|
layout: layout
|
||||||
size_hint: 1, None
|
size_hint: 1, None
|
||||||
elevation: root.elevation
|
elevation: root.elevation
|
||||||
|
radius: root.radius
|
||||||
|
shadow_offset: root.shadow_offset
|
||||||
|
shadow_color: root.shadow_color
|
||||||
|
shadow_softness: root.shadow_softness
|
||||||
height: root.tab_bar_height
|
height: root.tab_bar_height
|
||||||
md_bg_color:
|
md_bg_color:
|
||||||
self.theme_cls.primary_color \
|
self.theme_cls.primary_color \
|
||||||
|
@ -944,7 +944,6 @@ from kivy.properties import (
|
|||||||
from kivy.uix.anchorlayout import AnchorLayout
|
from kivy.uix.anchorlayout import AnchorLayout
|
||||||
from kivy.uix.behaviors import ToggleButtonBehavior
|
from kivy.uix.behaviors import ToggleButtonBehavior
|
||||||
from kivy.uix.scrollview import ScrollView
|
from kivy.uix.scrollview import ScrollView
|
||||||
from kivy.uix.widget import Widget
|
|
||||||
from kivy.utils import boundary
|
from kivy.utils import boundary
|
||||||
|
|
||||||
from kivymd import uix_path
|
from kivymd import uix_path
|
||||||
@ -953,11 +952,11 @@ from kivymd.icon_definitions import md_icons
|
|||||||
from kivymd.theming import ThemableBehavior, ThemeManager
|
from kivymd.theming import ThemableBehavior, ThemeManager
|
||||||
from kivymd.uix.behaviors import (
|
from kivymd.uix.behaviors import (
|
||||||
DeclarativeBehavior,
|
DeclarativeBehavior,
|
||||||
FakeRectangularElevationBehavior,
|
|
||||||
RectangularRippleBehavior,
|
RectangularRippleBehavior,
|
||||||
SpecificBackgroundColorBehavior,
|
SpecificBackgroundColorBehavior,
|
||||||
)
|
)
|
||||||
from kivymd.uix.boxlayout import MDBoxLayout
|
from kivymd.uix.boxlayout import MDBoxLayout
|
||||||
|
from kivymd.uix.card import MDCard
|
||||||
from kivymd.uix.carousel import MDCarousel
|
from kivymd.uix.carousel import MDCarousel
|
||||||
from kivymd.uix.label import MDLabel
|
from kivymd.uix.label import MDLabel
|
||||||
|
|
||||||
@ -1024,7 +1023,7 @@ class MDTabsLabel(ToggleButtonBehavior, RectangularRippleBehavior, MDLabel):
|
|||||||
Clock.schedule_once(self.tab_bar._label_request_indicator_update, 0)
|
Clock.schedule_once(self.tab_bar._label_request_indicator_update, 0)
|
||||||
|
|
||||||
|
|
||||||
class MDTabsBase(Widget):
|
class MDTabsBase:
|
||||||
"""
|
"""
|
||||||
This class allow you to create a tab.
|
This class allow you to create a tab.
|
||||||
You must create a new class that inherits from MDTabsBase.
|
You must create a new class that inherits from MDTabsBase.
|
||||||
@ -1130,9 +1129,9 @@ class MDTabsBase(Widget):
|
|||||||
This property will affect the Tab's Title Label widget.
|
This property will affect the Tab's Title Label widget.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
self.tab_label = MDTabsLabel(tab=self)
|
self.tab_label = MDTabsLabel(tab=self)
|
||||||
super().__init__(**kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
self.bind(
|
self.bind(
|
||||||
icon=self._update_text,
|
icon=self._update_text,
|
||||||
title=self._update_text,
|
title=self._update_text,
|
||||||
@ -1273,9 +1272,7 @@ class MDTabsScrollView(ScrollView):
|
|||||||
_update(self.effect_y, scroll_y)
|
_update(self.effect_y, scroll_y)
|
||||||
|
|
||||||
|
|
||||||
class MDTabsBar(
|
class MDTabsBar(MDCard):
|
||||||
ThemableBehavior, FakeRectangularElevationBehavior, MDBoxLayout
|
|
||||||
):
|
|
||||||
"""
|
"""
|
||||||
This class is just a boxlayout that contains the scroll view for tabs.
|
This class is just a boxlayout that contains the scroll view for tabs.
|
||||||
It is also responsible for resizing the tab shortcut when necessary.
|
It is also responsible for resizing the tab shortcut when necessary.
|
||||||
@ -1551,13 +1548,43 @@ class MDTabs(
|
|||||||
and defaults to `None`.
|
and defaults to `None`.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
shadow_softness = NumericProperty(12)
|
||||||
|
"""
|
||||||
|
See :attr:`kivymd.uix.behaviors.CommonElevationBehavior.shadow_softness`
|
||||||
|
attribute.
|
||||||
|
|
||||||
|
.. versionadded:: 1.1.0
|
||||||
|
|
||||||
|
:attr:`shadow_softness` is an :class:`~kivy.properties.NumericProperty`
|
||||||
|
and defaults to `12`.
|
||||||
|
"""
|
||||||
|
|
||||||
|
shadow_color = ColorProperty([0, 0, 0, 0.6])
|
||||||
|
"""
|
||||||
|
See :attr:`kivymd.uix.behaviors.CommonElevationBehavior.shadow_color`
|
||||||
|
attribute.
|
||||||
|
|
||||||
|
.. versionadded:: 1.1.0
|
||||||
|
|
||||||
|
:attr:`shadow_color` is an :class:`~kivy.properties.ColorProperty`
|
||||||
|
and defaults to `[0, 0, 0, 0.6]`.
|
||||||
|
"""
|
||||||
|
|
||||||
|
shadow_offset = ListProperty((0, 0))
|
||||||
|
"""
|
||||||
|
See :attr:`kivymd.uix.behaviors.CommonElevationBehavior.shadow_offset`
|
||||||
|
attribute.
|
||||||
|
|
||||||
|
.. versionadded:: 1.1.0
|
||||||
|
|
||||||
|
:attr:`shadow_offset` is an :class:`~kivy.properties.ListProperty`
|
||||||
|
and defaults to `[0, 0]`.
|
||||||
|
"""
|
||||||
|
|
||||||
elevation = NumericProperty(0)
|
elevation = NumericProperty(0)
|
||||||
"""
|
"""
|
||||||
Tab value elevation.
|
See :attr:`kivymd.uix.behaviors.CommonElevationBehavior.elevation`
|
||||||
|
attribute.
|
||||||
.. seealso::
|
|
||||||
|
|
||||||
`Behaviors/Elevation <https://kivymd.readthedocs.io/en/latest/behaviors/elevation/index.html>`_
|
|
||||||
|
|
||||||
:attr:`elevation` is an :class:`~kivy.properties.NumericProperty`
|
:attr:`elevation` is an :class:`~kivy.properties.NumericProperty`
|
||||||
and defaults to `0`.
|
and defaults to `0`.
|
||||||
|
@ -487,6 +487,8 @@ class MDTapTargetView(ThemableBehavior, EventDispatcher):
|
|||||||
_outer_radius = NumericProperty(0)
|
_outer_radius = NumericProperty(0)
|
||||||
_target_radius = NumericProperty(0)
|
_target_radius = NumericProperty(0)
|
||||||
|
|
||||||
|
__elevation = 0
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
self.ripple_max_dist = dp(90)
|
self.ripple_max_dist = dp(90)
|
||||||
self.on_outer_radius(self, self.outer_radius)
|
self.on_outer_radius(self, self.outer_radius)
|
||||||
@ -514,6 +516,89 @@ class MDTapTargetView(ThemableBehavior, EventDispatcher):
|
|||||||
if not self.outer_circle_color:
|
if not self.outer_circle_color:
|
||||||
self.outer_circle_color = self.theme_cls.primary_color[:-1]
|
self.outer_circle_color = self.theme_cls.primary_color[:-1]
|
||||||
|
|
||||||
|
def start(self, *args):
|
||||||
|
"""Starts widget opening animation."""
|
||||||
|
|
||||||
|
self._initialize()
|
||||||
|
self._animate_outer()
|
||||||
|
self.state = "open"
|
||||||
|
self.core_title_text.opacity = 1
|
||||||
|
self.core_description_text.opacity = 1
|
||||||
|
self.dispatch("on_open")
|
||||||
|
|
||||||
|
elevation = getattr(self.widget, "elevation", None)
|
||||||
|
if elevation:
|
||||||
|
self.__elevation = elevation
|
||||||
|
self.widget.elevation = 0
|
||||||
|
|
||||||
|
def stop(self, *args):
|
||||||
|
"""Starts widget close animation."""
|
||||||
|
|
||||||
|
# It needs a better implementation.
|
||||||
|
if self.anim_ripple is not None:
|
||||||
|
self.anim_ripple.unbind(on_complete=self._repeat_ripple)
|
||||||
|
self.core_title_text.opacity = 0
|
||||||
|
self.core_description_text.opacity = 0
|
||||||
|
anim = Animation(
|
||||||
|
d=0.15,
|
||||||
|
t="in_cubic",
|
||||||
|
**dict(
|
||||||
|
zip(
|
||||||
|
["_outer_radius", "_target_radius", "target_ripple_radius"],
|
||||||
|
[0, 0, 0],
|
||||||
|
)
|
||||||
|
),
|
||||||
|
)
|
||||||
|
anim.bind(on_complete=self._after_stop)
|
||||||
|
anim.start(self.widget)
|
||||||
|
|
||||||
|
def on_open(self, *args):
|
||||||
|
"""Called at the time of the start of the widget opening animation."""
|
||||||
|
|
||||||
|
def on_close(self, *args):
|
||||||
|
"""Called at the time of the start of the widget closed animation."""
|
||||||
|
|
||||||
|
def on_draw_shadow(self, instance, value):
|
||||||
|
Logger.warning(
|
||||||
|
"The shadow adding method will be implemented in future versions"
|
||||||
|
)
|
||||||
|
|
||||||
|
def on_description_text(self, instance, value):
|
||||||
|
self.core_description_text.text = value
|
||||||
|
|
||||||
|
def on_description_text_size(self, instance, value):
|
||||||
|
self.core_description_text.font_size = value
|
||||||
|
|
||||||
|
def on_description_text_bold(self, instance, value):
|
||||||
|
self.core_description_text.bold = value
|
||||||
|
|
||||||
|
def on_title_text(self, instance, value):
|
||||||
|
self.core_title_text.text = value
|
||||||
|
|
||||||
|
def on_title_text_size(self, instance, value):
|
||||||
|
self.core_title_text.font_size = value
|
||||||
|
|
||||||
|
def on_title_text_bold(self, instance, value):
|
||||||
|
self.core_title_text.bold = value
|
||||||
|
|
||||||
|
def on_outer_radius(self, instance, value):
|
||||||
|
self._outer_radius = self.outer_radius * 2
|
||||||
|
|
||||||
|
def on_target_radius(self, instance, value):
|
||||||
|
self._target_radius = self.target_radius * 2
|
||||||
|
|
||||||
|
def on_target_touch(self):
|
||||||
|
if self.stop_on_target_touch:
|
||||||
|
self.stop()
|
||||||
|
|
||||||
|
def on_outer_touch(self):
|
||||||
|
if self.stop_on_outer_touch:
|
||||||
|
self.stop()
|
||||||
|
|
||||||
|
def on_outside_click(self):
|
||||||
|
if self.cancelable:
|
||||||
|
self.stop()
|
||||||
|
|
||||||
def _initialize(self):
|
def _initialize(self):
|
||||||
setattr(self.widget, "_outer_radius", 0)
|
setattr(self.widget, "_outer_radius", 0)
|
||||||
setattr(self.widget, "_target_radius", 0)
|
setattr(self.widget, "_target_radius", 0)
|
||||||
@ -527,7 +612,7 @@ class MDTapTargetView(ThemableBehavior, EventDispatcher):
|
|||||||
|
|
||||||
def _draw_canvas(self):
|
def _draw_canvas(self):
|
||||||
_pos = self._ttv_pos()
|
_pos = self._ttv_pos()
|
||||||
self.widget.canvas.before.clear()
|
self.widget.canvas.before.remove_group("ttv_group")
|
||||||
|
|
||||||
with self.widget.canvas.before:
|
with self.widget.canvas.before:
|
||||||
# Outer circle.
|
# Outer circle.
|
||||||
@ -588,34 +673,14 @@ class MDTapTargetView(ThemableBehavior, EventDispatcher):
|
|||||||
group="ttv_group",
|
group="ttv_group",
|
||||||
)
|
)
|
||||||
|
|
||||||
def stop(self, *args):
|
|
||||||
"""Starts widget close animation."""
|
|
||||||
|
|
||||||
# It needs a better implementation.
|
|
||||||
if self.anim_ripple is not None:
|
|
||||||
self.anim_ripple.unbind(on_complete=self._repeat_ripple)
|
|
||||||
self.core_title_text.opacity = 0
|
|
||||||
self.core_description_text.opacity = 0
|
|
||||||
anim = Animation(
|
|
||||||
d=0.15,
|
|
||||||
t="in_cubic",
|
|
||||||
**dict(
|
|
||||||
zip(
|
|
||||||
["_outer_radius", "_target_radius", "target_ripple_radius"],
|
|
||||||
[0, 0, 0],
|
|
||||||
)
|
|
||||||
),
|
|
||||||
)
|
|
||||||
anim.bind(on_complete=self._after_stop)
|
|
||||||
anim.start(self.widget)
|
|
||||||
|
|
||||||
def _after_stop(self, *args):
|
def _after_stop(self, *args):
|
||||||
self.widget.canvas.before.remove_group("ttv_group")
|
self.widget.canvas.before.remove_group("ttv_group")
|
||||||
args[0].stop_all(self.widget)
|
args[0].stop_all(self.widget)
|
||||||
elev = getattr(self.widget, "elevation", None)
|
|
||||||
|
|
||||||
if elev:
|
elevation = getattr(self.widget, "elevation", None)
|
||||||
self._fix_elev()
|
if elevation:
|
||||||
|
self.widget.elevation = self.__elevation
|
||||||
|
|
||||||
self.dispatch("on_close")
|
self.dispatch("on_close")
|
||||||
|
|
||||||
# Don't forget to unbind the function or it'll mess
|
# Don't forget to unbind the function or it'll mess
|
||||||
@ -639,16 +704,6 @@ class MDTapTargetView(ThemableBehavior, EventDispatcher):
|
|||||||
)
|
)
|
||||||
Color(a=1)
|
Color(a=1)
|
||||||
|
|
||||||
def start(self, *args):
|
|
||||||
"""Starts widget opening animation."""
|
|
||||||
|
|
||||||
self._initialize()
|
|
||||||
self._animate_outer()
|
|
||||||
self.state = "open"
|
|
||||||
self.core_title_text.opacity = 1
|
|
||||||
self.core_description_text.opacity = 1
|
|
||||||
self.dispatch("on_open")
|
|
||||||
|
|
||||||
def _animate_outer(self):
|
def _animate_outer(self):
|
||||||
anim = Animation(
|
anim = Animation(
|
||||||
d=0.2,
|
d=0.2,
|
||||||
@ -684,53 +739,6 @@ class MDTapTargetView(ThemableBehavior, EventDispatcher):
|
|||||||
setattr(self.widget, "target_ripple_alpha", 1)
|
setattr(self.widget, "target_ripple_alpha", 1)
|
||||||
self._animate_ripple()
|
self._animate_ripple()
|
||||||
|
|
||||||
def on_open(self, *args):
|
|
||||||
"""Called at the time of the start of the widget opening animation."""
|
|
||||||
|
|
||||||
def on_close(self, *args):
|
|
||||||
"""Called at the time of the start of the widget closed animation."""
|
|
||||||
|
|
||||||
def on_draw_shadow(self, instance, value):
|
|
||||||
Logger.warning(
|
|
||||||
"The shadow adding method will be implemented in future versions"
|
|
||||||
)
|
|
||||||
|
|
||||||
def on_description_text(self, instance, value):
|
|
||||||
self.core_description_text.text = value
|
|
||||||
|
|
||||||
def on_description_text_size(self, instance, value):
|
|
||||||
self.core_description_text.font_size = value
|
|
||||||
|
|
||||||
def on_description_text_bold(self, instance, value):
|
|
||||||
self.core_description_text.bold = value
|
|
||||||
|
|
||||||
def on_title_text(self, instance, value):
|
|
||||||
self.core_title_text.text = value
|
|
||||||
|
|
||||||
def on_title_text_size(self, instance, value):
|
|
||||||
self.core_title_text.font_size = value
|
|
||||||
|
|
||||||
def on_title_text_bold(self, instance, value):
|
|
||||||
self.core_title_text.bold = value
|
|
||||||
|
|
||||||
def on_outer_radius(self, instance, value):
|
|
||||||
self._outer_radius = self.outer_radius * 2
|
|
||||||
|
|
||||||
def on_target_radius(self, instance, value):
|
|
||||||
self._target_radius = self.target_radius * 2
|
|
||||||
|
|
||||||
def on_target_touch(self):
|
|
||||||
if self.stop_on_target_touch:
|
|
||||||
self.stop()
|
|
||||||
|
|
||||||
def on_outer_touch(self):
|
|
||||||
if self.stop_on_outer_touch:
|
|
||||||
self.stop()
|
|
||||||
|
|
||||||
def on_outside_click(self):
|
|
||||||
if self.cancelable:
|
|
||||||
self.stop()
|
|
||||||
|
|
||||||
def _some_func(self, wid, touch):
|
def _some_func(self, wid, touch):
|
||||||
"""
|
"""
|
||||||
This function decides which one to dispatch based on the touch
|
This function decides which one to dispatch based on the touch
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
<RotateWidget>
|
|
||||||
canvas.before:
|
|
||||||
PushMatrix
|
|
||||||
Rotate:
|
|
||||||
angle: self.rotate_value_angle
|
|
||||||
axis: tuple(self.rotate_value_axis)
|
|
||||||
origin: self.center
|
|
||||||
canvas.after:
|
|
||||||
PopMatrix
|
|
@ -2,127 +2,31 @@
|
|||||||
Templates/RotateWidget
|
Templates/RotateWidget
|
||||||
======================
|
======================
|
||||||
|
|
||||||
.. versionadded:: 1.0.0
|
.. deprecated:: 1.0.0
|
||||||
|
|
||||||
Base class for controlling the rotate of the widget.
|
.. note:: `RotateWidget` class has been deprecated. Please use
|
||||||
|
`RotateBahavior <https://kivymd.readthedocs.io/en/latest/behaviors/rotate/>`_
|
||||||
.. note:: See `kivy.graphics.Rotate
|
class instead.
|
||||||
<https://kivy.org/doc/stable/api-kivy.graphics.html#kivy.graphics.Rotate>`_
|
|
||||||
for more information.
|
|
||||||
|
|
||||||
Kivy
|
|
||||||
----
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
from kivy.animation import Animation
|
|
||||||
from kivy.lang import Builder
|
|
||||||
from kivy.app import App
|
|
||||||
from kivy.properties import NumericProperty
|
|
||||||
from kivy.uix.button import Button
|
|
||||||
|
|
||||||
KV = '''
|
|
||||||
Screen:
|
|
||||||
|
|
||||||
RotateButton:
|
|
||||||
size_hint: .5, .5
|
|
||||||
pos_hint: {"center_x": .5, "center_y": .5}
|
|
||||||
on_release: app.change_rotate(self)
|
|
||||||
|
|
||||||
canvas.before:
|
|
||||||
PushMatrix
|
|
||||||
Rotate:
|
|
||||||
angle: self.rotate_value_angle
|
|
||||||
axis: 0, 0, 1
|
|
||||||
origin: self.center
|
|
||||||
canvas.after:
|
|
||||||
PopMatrix
|
|
||||||
'''
|
|
||||||
|
|
||||||
|
|
||||||
class RotateButton(Button):
|
|
||||||
rotate_value_angle = NumericProperty(0)
|
|
||||||
|
|
||||||
|
|
||||||
class Test(App):
|
|
||||||
def build(self):
|
|
||||||
return Builder.load_string(KV)
|
|
||||||
|
|
||||||
def change_rotate(self, instance_button: Button) -> None:
|
|
||||||
Animation(rotate_value_angle=45, d=0.3).start(instance_button)
|
|
||||||
|
|
||||||
|
|
||||||
Test().run()
|
|
||||||
|
|
||||||
KivyMD
|
|
||||||
------
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
from kivy.animation import Animation
|
|
||||||
from kivy.lang import Builder
|
|
||||||
|
|
||||||
from kivymd.app import MDApp
|
|
||||||
from kivymd.uix.button import MDRaisedButton
|
|
||||||
from kivymd.uix.templates import RotateWidget
|
|
||||||
|
|
||||||
KV = '''
|
|
||||||
MDScreen:
|
|
||||||
|
|
||||||
RotateButton:
|
|
||||||
size_hint: .5, .5
|
|
||||||
pos_hint: {"center_x": .5, "center_y": .5}
|
|
||||||
on_release: app.change_rotate(self)
|
|
||||||
elevation:0
|
|
||||||
'''
|
|
||||||
|
|
||||||
|
|
||||||
class RotateButton(MDRaisedButton, RotateWidget):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class Test(MDApp):
|
|
||||||
def build(self):
|
|
||||||
return Builder.load_string(KV)
|
|
||||||
|
|
||||||
def change_rotate(self, instance_button: MDRaisedButton) -> None:
|
|
||||||
Animation(rotate_value_angle=45, d=0.3).start(instance_button)
|
|
||||||
|
|
||||||
|
|
||||||
Test().run()
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__all__ = ("RotateWidget",)
|
__all__ = ("RotateWidget",)
|
||||||
|
|
||||||
import os
|
from kivy import Logger
|
||||||
|
|
||||||
from kivy.lang import Builder
|
from kivymd.uix.behaviors import RotateBehavior
|
||||||
from kivy.properties import ListProperty, NumericProperty
|
|
||||||
|
|
||||||
from kivymd import uix_path
|
|
||||||
|
|
||||||
with open(
|
|
||||||
os.path.join(uix_path, "templates", "rotatewidget", "rotatewidget.kv"),
|
|
||||||
encoding="utf-8",
|
|
||||||
) as kv_file:
|
|
||||||
Builder.load_string(kv_file.read())
|
|
||||||
|
|
||||||
|
|
||||||
class RotateWidget:
|
class RotateWidget(RotateBehavior):
|
||||||
"""Base class for controlling the rotate of the widget."""
|
|
||||||
|
|
||||||
rotate_value_angle = NumericProperty(0)
|
|
||||||
"""
|
"""
|
||||||
Property for getting/setting the angle of the rotation.
|
.. deprecated:: 1.1.0
|
||||||
|
Use :class:`~kivymd.uix.behaviors.rotate_behavior.RotateBehavior`
|
||||||
:attr:`rotate_value_angle` is an :class:`~kivy.properties.NumericProperty`
|
class instead.
|
||||||
and defaults to `0`.
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
rotate_value_axis = ListProperty((0, 0, 1))
|
def __init__(self, **kwargs):
|
||||||
"""
|
super().__init__(**kwargs)
|
||||||
Property for getting/setting the axis of the rotation.
|
Logger.warning(
|
||||||
|
"KivyMD: "
|
||||||
:attr:`rotate_value_axis` is an :class:`~kivy.properties.NumericProperty`
|
"The `RotateWidget` class has been deprecated. "
|
||||||
and defaults to `(0, 0, 1)`.
|
"Use the `RotateBehavior` class instead."
|
||||||
"""
|
)
|
||||||
|
@ -1,10 +0,0 @@
|
|||||||
<ScaleWidget>
|
|
||||||
canvas.before:
|
|
||||||
PushMatrix
|
|
||||||
Scale:
|
|
||||||
x: self.scale_value_x
|
|
||||||
y: self.scale_value_y
|
|
||||||
z: self.scale_value_x
|
|
||||||
origin: self.center
|
|
||||||
canvas.after:
|
|
||||||
PopMatrix
|
|
@ -2,149 +2,33 @@
|
|||||||
Templates/ScaleWidget
|
Templates/ScaleWidget
|
||||||
=====================
|
=====================
|
||||||
|
|
||||||
.. versionadded:: 1.0.0
|
.. deprecated:: 1.1.0
|
||||||
|
|
||||||
Base class for controlling the scale of the widget.
|
Base class for controlling the scale of the widget.
|
||||||
|
|
||||||
.. note:: See `kivy.graphics.Scale
|
.. note:: `ScaleWidget` class has been deprecated. Please use
|
||||||
<https://kivy.org/doc/stable/api-kivy.graphics.html#kivy.graphics.Scale>`_
|
`ScaleBehavior <https://kivymd.readthedocs.io/en/latest/behaviors/scale/>`_
|
||||||
for more information.
|
class instead.
|
||||||
|
|
||||||
Kivy
|
|
||||||
----
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
from kivy.animation import Animation
|
|
||||||
from kivy.lang import Builder
|
|
||||||
from kivy.properties import NumericProperty
|
|
||||||
from kivy.uix.button import Button
|
|
||||||
from kivy.app import App
|
|
||||||
|
|
||||||
|
|
||||||
KV = '''
|
|
||||||
Screen:
|
|
||||||
|
|
||||||
ScaleButton:
|
|
||||||
size_hint: .5, .5
|
|
||||||
pos_hint: {"center_x": .5, "center_y": .5}
|
|
||||||
on_release: app.change_scale(self)
|
|
||||||
|
|
||||||
canvas.before:
|
|
||||||
PushMatrix
|
|
||||||
Scale:
|
|
||||||
x: self.scale_value_x
|
|
||||||
y: self.scale_value_y
|
|
||||||
z: self.scale_value_x
|
|
||||||
origin: self.center
|
|
||||||
canvas.after:
|
|
||||||
PopMatrix
|
|
||||||
'''
|
|
||||||
|
|
||||||
|
|
||||||
class ScaleButton(Button):
|
|
||||||
scale_value_x = NumericProperty(1)
|
|
||||||
scale_value_y = NumericProperty(1)
|
|
||||||
scale_value_z = NumericProperty(1)
|
|
||||||
|
|
||||||
|
|
||||||
class Test(App):
|
|
||||||
def build(self):
|
|
||||||
return Builder.load_string(KV)
|
|
||||||
|
|
||||||
def change_scale(self, instance_button: Button) -> None:
|
|
||||||
Animation(
|
|
||||||
scale_value_x=0.5,
|
|
||||||
scale_value_y=0.5,
|
|
||||||
scale_value_z=0.5,
|
|
||||||
d=0.3,
|
|
||||||
).start(instance_button)
|
|
||||||
|
|
||||||
|
|
||||||
Test().run()
|
|
||||||
|
|
||||||
KivyMD
|
|
||||||
------
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
from kivy.animation import Animation
|
|
||||||
from kivy.lang import Builder
|
|
||||||
|
|
||||||
from kivymd.app import MDApp
|
|
||||||
from kivymd.uix.button import MDRaisedButton
|
|
||||||
from kivymd.uix.templates import ScaleWidget
|
|
||||||
|
|
||||||
KV = '''
|
|
||||||
MDScreen:
|
|
||||||
|
|
||||||
ScaleButton:
|
|
||||||
size_hint: .5, .5
|
|
||||||
pos_hint: {"center_x": .5, "center_y": .5}
|
|
||||||
on_release: app.change_scale(self)
|
|
||||||
elevation:0
|
|
||||||
'''
|
|
||||||
|
|
||||||
|
|
||||||
class ScaleButton(MDRaisedButton, ScaleWidget):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class Test(MDApp):
|
|
||||||
def build(self):
|
|
||||||
return Builder.load_string(KV)
|
|
||||||
|
|
||||||
def change_scale(self, instance_button: MDRaisedButton) -> None:
|
|
||||||
Animation(
|
|
||||||
scale_value_x=0.5,
|
|
||||||
scale_value_y=0.5,
|
|
||||||
scale_value_z=0.5,
|
|
||||||
d=0.3,
|
|
||||||
).start(instance_button)
|
|
||||||
|
|
||||||
|
|
||||||
Test().run()
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__all__ = ("ScaleWidget",)
|
__all__ = ("ScaleWidget",)
|
||||||
|
|
||||||
import os
|
from kivy import Logger
|
||||||
|
|
||||||
from kivy.lang import Builder
|
from kivymd.uix.behaviors import ScaleBehavior
|
||||||
from kivy.properties import NumericProperty
|
|
||||||
|
|
||||||
from kivymd import uix_path
|
|
||||||
|
|
||||||
with open(
|
|
||||||
os.path.join(uix_path, "templates", "scalewidget", "scalewidget.kv"),
|
|
||||||
encoding="utf-8",
|
|
||||||
) as kv_file:
|
|
||||||
Builder.load_string(kv_file.read())
|
|
||||||
|
|
||||||
|
|
||||||
class ScaleWidget:
|
class ScaleWidget(ScaleBehavior):
|
||||||
"""Base class for controlling the scale of the widget."""
|
|
||||||
|
|
||||||
scale_value_x = NumericProperty(1)
|
|
||||||
"""
|
"""
|
||||||
X-axis value.
|
.. deprecated:: 1.1.0
|
||||||
|
Use :class:`~kivymd.uix.behaviors.scale_behavior.ScaleBehavior`
|
||||||
:attr:`scale_value_x` is an :class:`~kivy.properties.NumericProperty`
|
class instead.
|
||||||
and defaults to `1`.
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
scale_value_y = NumericProperty(1)
|
def __init__(self, **kwargs):
|
||||||
"""
|
super().__init__(**kwargs)
|
||||||
Y-axis value.
|
Logger.warning(
|
||||||
|
"KivyMD: "
|
||||||
:attr:`scale_value_y` is an :class:`~kivy.properties.NumericProperty`
|
"The `ScaleWidget` class has been deprecated. "
|
||||||
and defaults to `1`.
|
"Use the `ScaleBehavior` class instead."
|
||||||
"""
|
)
|
||||||
|
|
||||||
scale_value_z = NumericProperty(1)
|
|
||||||
"""
|
|
||||||
Z-axis value.
|
|
||||||
|
|
||||||
:attr:`scale_value_z` is an :class:`~kivy.properties.NumericProperty`
|
|
||||||
and defaults to `1`.
|
|
||||||
"""
|
|
||||||
|
@ -1,19 +0,0 @@
|
|||||||
<StencilWidget>
|
|
||||||
canvas.before:
|
|
||||||
StencilPush
|
|
||||||
RoundedRectangle:
|
|
||||||
pos: root.pos
|
|
||||||
size: root.size
|
|
||||||
# FIXME: Sometimes the radius has the value [], which get a
|
|
||||||
# `GraphicException: Invalid radius value, must be list of tuples/numerics` error
|
|
||||||
radius: root.radius if root.radius else [0, 0, 0, 0]
|
|
||||||
StencilUse
|
|
||||||
canvas.after:
|
|
||||||
StencilUnUse
|
|
||||||
RoundedRectangle:
|
|
||||||
pos: root.pos
|
|
||||||
size: root.size
|
|
||||||
# FIXME: Sometimes the radius has the value [], which get a
|
|
||||||
# `GraphicException: Invalid radius value, must be list of tuples/numerics` error
|
|
||||||
radius: root.radius if root.radius else [0, 0, 0, 0]
|
|
||||||
StencilPop
|
|
@ -2,115 +2,33 @@
|
|||||||
Templates/StencilWidget
|
Templates/StencilWidget
|
||||||
=======================
|
=======================
|
||||||
|
|
||||||
.. versionadded:: 1.0.0
|
.. deprecated:: 1.1.0
|
||||||
|
|
||||||
Base class for controlling the stencil instructions of the widget.
|
Base class for controlling the stencil instructions of the widget.
|
||||||
|
|
||||||
.. note:: See `Stencil instructions
|
.. note:: `StencilWidget` class has been deprecated. Please use
|
||||||
<https://kivy.org/doc/stable/api-kivy.graphics.stencil_instructions.html>`_
|
`StencilBehavior <https://kivymd.readthedocs.io/en/latest/behaviors/stencil/>`_
|
||||||
for more information.
|
class instead.
|
||||||
|
|
||||||
Kivy
|
|
||||||
----
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
from kivy.lang import Builder
|
|
||||||
from kivy.app import App
|
|
||||||
|
|
||||||
KV = '''
|
|
||||||
Carousel:
|
|
||||||
|
|
||||||
Button:
|
|
||||||
size_hint: .9, .8
|
|
||||||
pos_hint: {"center_x": .5, "center_y": .5}
|
|
||||||
|
|
||||||
canvas.before:
|
|
||||||
StencilPush
|
|
||||||
RoundedRectangle:
|
|
||||||
pos: root.pos
|
|
||||||
size: root.size
|
|
||||||
StencilUse
|
|
||||||
canvas.after:
|
|
||||||
StencilUnUse
|
|
||||||
RoundedRectangle:
|
|
||||||
pos: root.pos
|
|
||||||
size: root.size
|
|
||||||
StencilPop
|
|
||||||
'''
|
|
||||||
|
|
||||||
|
|
||||||
class Test(App):
|
|
||||||
def build(self):
|
|
||||||
return Builder.load_string(KV)
|
|
||||||
|
|
||||||
|
|
||||||
Test().run()
|
|
||||||
|
|
||||||
KivyMD
|
|
||||||
------
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
from kivy.lang import Builder
|
|
||||||
|
|
||||||
from kivymd.app import MDApp
|
|
||||||
from kivymd.uix.templates import StencilWidget
|
|
||||||
from kivymd.uix.fitimage import FitImage
|
|
||||||
|
|
||||||
KV = '''
|
|
||||||
MDCarousel:
|
|
||||||
|
|
||||||
StencilImage:
|
|
||||||
size_hint: .9, .8
|
|
||||||
pos_hint: {"center_x": .5, "center_y": .5}
|
|
||||||
source: "image.png"
|
|
||||||
'''
|
|
||||||
|
|
||||||
|
|
||||||
class StencilImage(FitImage, StencilWidget):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class Test(MDApp):
|
|
||||||
def build(self):
|
|
||||||
return Builder.load_string(KV)
|
|
||||||
|
|
||||||
|
|
||||||
Test().run()
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__all__ = ("StencilWidget",)
|
__all__ = ("StencilWidget",)
|
||||||
|
|
||||||
import os
|
from kivy import Logger
|
||||||
|
|
||||||
from kivy.lang import Builder
|
from kivymd.uix.behaviors import StencilBehavior
|
||||||
from kivy.properties import VariableListProperty
|
|
||||||
|
|
||||||
from kivymd import uix_path
|
|
||||||
|
|
||||||
with open(
|
|
||||||
os.path.join(uix_path, "templates", "stencilwidget", "stencilwidget.kv"),
|
|
||||||
encoding="utf-8",
|
|
||||||
) as kv_file:
|
|
||||||
Builder.load_string(kv_file.read())
|
|
||||||
|
|
||||||
|
|
||||||
class StencilWidget:
|
class StencilWidget(StencilBehavior):
|
||||||
"""Base class for controlling the stencil instructions of the widget"""
|
|
||||||
|
|
||||||
radius = VariableListProperty([0], length=4)
|
|
||||||
"""
|
"""
|
||||||
Canvas radius.
|
.. deprecated:: 1.1.0
|
||||||
|
Use :class:`~kivymd.uix.behaviors.scale_behavior.StencilBehavior`
|
||||||
.. versionadded:: 1.0.0
|
class instead.
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
# Top left corner slice.
|
|
||||||
MDWidget:
|
|
||||||
radius: [25, 0, 0, 0]
|
|
||||||
|
|
||||||
:attr:`radius` is an :class:`~kivy.properties.VariableListProperty`
|
|
||||||
and defaults to `[0, 0, 0, 0]`.
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
super().__init__(**kwargs)
|
||||||
|
Logger.warning(
|
||||||
|
"KivyMD: "
|
||||||
|
"The `StencilWidget` class has been deprecated. "
|
||||||
|
"Use the `StencilBehavior` class instead."
|
||||||
|
)
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
<MDTextField>
|
<MDTextField>
|
||||||
|
input_filter: self.field_filter
|
||||||
|
do_backspace: self.do_backspace
|
||||||
|
|
||||||
canvas.before:
|
canvas.before:
|
||||||
Clear
|
Clear
|
||||||
|
|
||||||
|
@ -14,7 +14,6 @@ Components/TextField
|
|||||||
`KivyMD` provides the following field classes for use:
|
`KivyMD` provides the following field classes for use:
|
||||||
|
|
||||||
- MDTextField_
|
- MDTextField_
|
||||||
- MDTextFieldRound_
|
|
||||||
- MDTextFieldRect_
|
- MDTextFieldRect_
|
||||||
|
|
||||||
.. Note:: :class:`~MDTextField` inherited from
|
.. Note:: :class:`~MDTextField` inherited from
|
||||||
@ -79,15 +78,15 @@ parameter to `True`:
|
|||||||
from kivymd.app import MDApp
|
from kivymd.app import MDApp
|
||||||
|
|
||||||
KV = '''
|
KV = '''
|
||||||
BoxLayout:
|
MDScreen:
|
||||||
padding: "10dp"
|
|
||||||
|
|
||||||
MDTextField:
|
MDTextField:
|
||||||
id: text_field_error
|
id: text_field_error
|
||||||
hint_text: "Helper text on error (press 'Enter')"
|
hint_text: "Helper text on error (press 'Enter')"
|
||||||
helper_text: "There will always be a mistake"
|
helper_text: "There will always be a mistake"
|
||||||
helper_text_mode: "on_error"
|
helper_text_mode: "on_error"
|
||||||
pos_hint: {"center_y": .5}
|
pos_hint: {"center_x": .5, "center_y": .5}
|
||||||
|
size_hint_x: .5
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
|
||||||
@ -97,6 +96,8 @@ parameter to `True`:
|
|||||||
self.screen = Builder.load_string(KV)
|
self.screen = Builder.load_string(KV)
|
||||||
|
|
||||||
def build(self):
|
def build(self):
|
||||||
|
self.theme_cls.theme_style = "Dark"
|
||||||
|
self.theme_cls.primary_palette = "Orange"
|
||||||
self.screen.ids.text_field_error.bind(
|
self.screen.ids.text_field_error.bind(
|
||||||
on_text_validate=self.set_error_message,
|
on_text_validate=self.set_error_message,
|
||||||
on_focus=self.set_error_message,
|
on_focus=self.set_error_message,
|
||||||
@ -119,6 +120,7 @@ Helper text mode `'on_error'` (with required)
|
|||||||
|
|
||||||
MDTextField:
|
MDTextField:
|
||||||
hint_text: "required = True"
|
hint_text: "required = True"
|
||||||
|
text: "required = True"
|
||||||
required: True
|
required: True
|
||||||
helper_text_mode: "on_error"
|
helper_text_mode: "on_error"
|
||||||
helper_text: "Enter text"
|
helper_text: "Enter text"
|
||||||
@ -186,7 +188,7 @@ Round mode
|
|||||||
max_text_length: 15
|
max_text_length: 15
|
||||||
helper_text: "Massage"
|
helper_text: "Massage"
|
||||||
|
|
||||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-field-round-mode.png
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-field-round-mode.gif
|
||||||
:align: center
|
:align: center
|
||||||
|
|
||||||
.. MDTextFieldRect:
|
.. MDTextFieldRect:
|
||||||
@ -203,6 +205,7 @@ MDTextFieldRect
|
|||||||
MDTextFieldRect:
|
MDTextFieldRect:
|
||||||
size_hint: 1, None
|
size_hint: 1, None
|
||||||
height: "30dp"
|
height: "30dp"
|
||||||
|
background_color: app.theme_cls.bg_normal
|
||||||
|
|
||||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-field-rect.gif
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-field-rect.gif
|
||||||
:align: center
|
:align: center
|
||||||
@ -278,18 +281,17 @@ __all__ = ("MDTextField", "MDTextFieldRect")
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
from datetime import date
|
||||||
from typing import Union
|
from typing import Union
|
||||||
|
|
||||||
from kivy.animation import Animation
|
from kivy.animation import Animation
|
||||||
from kivy.clock import Clock
|
from kivy.clock import Clock
|
||||||
from kivy.lang import Builder
|
from kivy.lang import Builder
|
||||||
from kivy.logger import Logger
|
|
||||||
from kivy.metrics import dp, sp
|
from kivy.metrics import dp, sp
|
||||||
from kivy.properties import (
|
from kivy.properties import (
|
||||||
AliasProperty,
|
AliasProperty,
|
||||||
BooleanProperty,
|
BooleanProperty,
|
||||||
ColorProperty,
|
ColorProperty,
|
||||||
DictProperty,
|
|
||||||
ListProperty,
|
ListProperty,
|
||||||
NumericProperty,
|
NumericProperty,
|
||||||
ObjectProperty,
|
ObjectProperty,
|
||||||
@ -311,6 +313,220 @@ with open(
|
|||||||
Builder.load_string(kv_file.read())
|
Builder.load_string(kv_file.read())
|
||||||
|
|
||||||
|
|
||||||
|
# TODO: Add a class to work with the phone number mask.
|
||||||
|
|
||||||
|
|
||||||
|
class AutoFormatTelephoneNumber:
|
||||||
|
"""
|
||||||
|
Implements automatic formatting of the text entered in the text field
|
||||||
|
according to the mask, for example '+38 (###) ### ## ##'.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self._backspace = False
|
||||||
|
|
||||||
|
def isnumeric(self, value):
|
||||||
|
try:
|
||||||
|
int(value)
|
||||||
|
return True
|
||||||
|
except ValueError:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def do_backspace(self, *args):
|
||||||
|
if self.validator and self.validator == "phone":
|
||||||
|
self._backspace = True
|
||||||
|
text = self.text
|
||||||
|
text = text[:-1]
|
||||||
|
self.text = text
|
||||||
|
self._backspace = False
|
||||||
|
|
||||||
|
def field_filter(self, value, boolean):
|
||||||
|
if self.validator and self.validator == "phone":
|
||||||
|
if len(self.text) == 14:
|
||||||
|
return
|
||||||
|
if self.isnumeric(value):
|
||||||
|
return value
|
||||||
|
return value
|
||||||
|
|
||||||
|
def format(self, value):
|
||||||
|
if value != "" and not value.isspace() and not self._backspace:
|
||||||
|
if len(value) <= 1 and self.focus:
|
||||||
|
self.text = value
|
||||||
|
self._check_cursor()
|
||||||
|
elif len(value) == 4:
|
||||||
|
start = self.text[:-1]
|
||||||
|
end = self.text[-1]
|
||||||
|
self.text = "%s) %s" % (start, end)
|
||||||
|
self._check_cursor()
|
||||||
|
elif len(value) == 8:
|
||||||
|
self.text += "-"
|
||||||
|
self._check_cursor()
|
||||||
|
elif len(value) in [12, 16]:
|
||||||
|
start = self.text[:-1]
|
||||||
|
end = self.text[-1]
|
||||||
|
self.text = "%s-%s" % (start, end)
|
||||||
|
self._check_cursor()
|
||||||
|
|
||||||
|
def _check_cursor(self):
|
||||||
|
def set_pos_cursor(pos_corsor, interval=0.5):
|
||||||
|
self.cursor = (pos_corsor, 0)
|
||||||
|
|
||||||
|
if self.focus:
|
||||||
|
Clock.schedule_once(lambda x: set_pos_cursor(len(self.text)), 0.1)
|
||||||
|
|
||||||
|
|
||||||
|
class Validator:
|
||||||
|
"""Container class for various validation methods."""
|
||||||
|
|
||||||
|
datetime_date = ObjectProperty()
|
||||||
|
"""
|
||||||
|
The last valid date as a <class 'datetime.date'> object.
|
||||||
|
|
||||||
|
:attr:`datetime_date` is an :class:`~kivy.properties.ObjectProperty`
|
||||||
|
and defaults to `None`.
|
||||||
|
"""
|
||||||
|
|
||||||
|
date_interval = ListProperty([None, None])
|
||||||
|
"""
|
||||||
|
The date interval that is valid for input.
|
||||||
|
Can be entered as <class 'datetime.date'> objects or a string format.
|
||||||
|
Both values or just one value can be entered.
|
||||||
|
|
||||||
|
In string format, must follow the current date_format.
|
||||||
|
Example: Given date_format -> "mm/dd/yyyy"
|
||||||
|
Input examples -> "12/31/1900", "12/31/2100" or "12/31/1900", None.
|
||||||
|
|
||||||
|
:attr:`date_interval` is an :class:`~kivy.properties.ListProperty`
|
||||||
|
and defaults to `[None, None]`.
|
||||||
|
"""
|
||||||
|
|
||||||
|
date_format = OptionProperty(
|
||||||
|
None,
|
||||||
|
options=[
|
||||||
|
"dd/mm/yyyy",
|
||||||
|
"mm/dd/yyyy",
|
||||||
|
"yyyy/mm/dd",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
"""
|
||||||
|
Format of date strings that will be entered.
|
||||||
|
Available options are: `'dd/mm/yyyy'`, `'mm/dd/yyyy'`, `'yyyy/mm/dd'`.
|
||||||
|
|
||||||
|
:attr:`date_format` is an :class:`~kivy.properties.OptionProperty`
|
||||||
|
and defaults to `None`.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def is_email_valid(self, text: str) -> bool:
|
||||||
|
if not re.match(r"[^@]+@[^@]+\.[^@]+", text):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def is_time_valid(self, text: str) -> bool:
|
||||||
|
if re.match(r"^(2[0-3]|[01]?[0-9]):([0-5]?[0-9])$", text) or re.match(
|
||||||
|
r"^(2[0-3]|[01]?[0-9]):([0-5]?[0-9]):([0-5]?[0-9])$", text
|
||||||
|
):
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def is_date_valid(self, text: str) -> bool:
|
||||||
|
if not self.date_format:
|
||||||
|
raise Exception("TextInput date_format was not defined.")
|
||||||
|
|
||||||
|
# Regex strings.
|
||||||
|
dd = "[0][1-9]|[1-2][0-9]|[3][0-1]"
|
||||||
|
mm = "[0][1-9]|[1][0-2]"
|
||||||
|
yyyy = "[0-9][0-9][0-9][0-9]"
|
||||||
|
fmt = self.date_format.split("/")
|
||||||
|
largs = locals()
|
||||||
|
# Access the local variables dict in the correct format based on
|
||||||
|
# date_format split. Example: "mm/dd/yyyy" -> ["mm", "dd", "yyyy"]
|
||||||
|
# largs[fmt[0]] would be largs["mm"] so the month regex string.
|
||||||
|
if re.match(
|
||||||
|
f"^({largs[fmt[0]]})/({largs[fmt[1]]})/({largs[fmt[2]]})$", text
|
||||||
|
):
|
||||||
|
input_split = text.split("/")
|
||||||
|
largs[fmt[0]] = input_split[0]
|
||||||
|
largs[fmt[1]] = input_split[1]
|
||||||
|
largs[fmt[2]] = input_split[2]
|
||||||
|
# Organize input into correct slots and try to convert
|
||||||
|
# to datetime object. This way February exceptions are
|
||||||
|
# tested. Also tests with the date_interval are simpler
|
||||||
|
# using datetime objects.
|
||||||
|
try:
|
||||||
|
datetime = date(
|
||||||
|
int(largs["yyyy"]), int(largs["mm"]), int(largs["dd"])
|
||||||
|
)
|
||||||
|
except ValueError:
|
||||||
|
return True
|
||||||
|
|
||||||
|
if self.date_interval:
|
||||||
|
if (
|
||||||
|
self.date_interval[0]
|
||||||
|
and not self.date_interval[0] <= datetime
|
||||||
|
or self.date_interval[1]
|
||||||
|
and not datetime <= self.date_interval[1]
|
||||||
|
):
|
||||||
|
return True
|
||||||
|
|
||||||
|
self.datetime_date = datetime
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
def on_date_interval(self, *args) -> None:
|
||||||
|
"""Default event handler for date_interval input."""
|
||||||
|
|
||||||
|
def on_date_interval():
|
||||||
|
if not self.date_format:
|
||||||
|
raise Exception("TextInput date_format was not defined.")
|
||||||
|
|
||||||
|
fmt = self.date_format.split("/")
|
||||||
|
largs = {}
|
||||||
|
# Convert string inputs into datetime.date objects and store
|
||||||
|
# them back into self.date_interval.
|
||||||
|
try:
|
||||||
|
if self.date_interval[0] and not isinstance(
|
||||||
|
self.date_interval[0], date
|
||||||
|
):
|
||||||
|
split = self.date_interval[0].split("/")
|
||||||
|
largs[fmt[0]] = split[0]
|
||||||
|
largs[fmt[1]] = split[1]
|
||||||
|
largs[fmt[2]] = split[2]
|
||||||
|
self.date_interval[0] = date(
|
||||||
|
int(largs["yyyy"]), int(largs["mm"]), int(largs["dd"])
|
||||||
|
)
|
||||||
|
if self.date_interval[1] and not isinstance(
|
||||||
|
self.date_interval[1], date
|
||||||
|
):
|
||||||
|
split = self.date_interval[1].split("/")
|
||||||
|
largs[fmt[0]] = split[0]
|
||||||
|
largs[fmt[1]] = split[1]
|
||||||
|
largs[fmt[2]] = split[2]
|
||||||
|
self.date_interval[1] = date(
|
||||||
|
int(largs["yyyy"]), int(largs["mm"]), int(largs["dd"])
|
||||||
|
)
|
||||||
|
|
||||||
|
except Exception:
|
||||||
|
raise Exception(
|
||||||
|
r"TextInput date_interval was defined incorrectly, it must "
|
||||||
|
r"be composed of <class 'datetime.date'> objects or strings"
|
||||||
|
r" following current date_format."
|
||||||
|
)
|
||||||
|
|
||||||
|
# Test if the interval is valid.
|
||||||
|
if isinstance(self.date_interval[0], date) and isinstance(
|
||||||
|
self.date_interval[1], date
|
||||||
|
):
|
||||||
|
if self.date_interval[0] >= self.date_interval[1]:
|
||||||
|
raise Exception(
|
||||||
|
"TextInput date_interval last date must be greater"
|
||||||
|
" than the first date or set to None."
|
||||||
|
)
|
||||||
|
|
||||||
|
Clock.schedule_once(lambda x: on_date_interval())
|
||||||
|
|
||||||
|
|
||||||
class MDTextFieldRect(ThemableBehavior, TextInput):
|
class MDTextFieldRect(ThemableBehavior, TextInput):
|
||||||
line_anim = BooleanProperty(True)
|
line_anim = BooleanProperty(True)
|
||||||
"""
|
"""
|
||||||
@ -383,7 +599,13 @@ class TextfieldLabel(ThemableBehavior, Label):
|
|||||||
self.font_size = sp(self.theme_cls.font_styles[self.font_style][1])
|
self.font_size = sp(self.theme_cls.font_styles[self.font_style][1])
|
||||||
|
|
||||||
|
|
||||||
class MDTextField(DeclarativeBehavior, ThemableBehavior, TextInput):
|
class MDTextField(
|
||||||
|
DeclarativeBehavior,
|
||||||
|
ThemableBehavior,
|
||||||
|
TextInput,
|
||||||
|
Validator,
|
||||||
|
AutoFormatTelephoneNumber,
|
||||||
|
):
|
||||||
helper_text = StringProperty()
|
helper_text = StringProperty()
|
||||||
"""
|
"""
|
||||||
Text for ``helper_text`` mode.
|
Text for ``helper_text`` mode.
|
||||||
@ -430,17 +652,185 @@ class MDTextField(DeclarativeBehavior, ThemableBehavior, TextInput):
|
|||||||
and defaults to `'line'`.
|
and defaults to `'line'`.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
phone_mask = StringProperty("")
|
||||||
|
|
||||||
|
validator = OptionProperty(None, options=["date", "email", "time", "phone"])
|
||||||
|
"""
|
||||||
|
The type of text field for entering Email, time, etc.
|
||||||
|
Automatically sets the type of the text field as "error" if the user input
|
||||||
|
does not match any of the set validation types.
|
||||||
|
Available options are: `'date'`, `'email'`, `'time'`.
|
||||||
|
|
||||||
|
When using `'date'`, :attr:`date_format` must be defined.
|
||||||
|
|
||||||
|
.. versionadded:: 1.1.0
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
MDTextField:
|
||||||
|
hint_text: "Email"
|
||||||
|
helper_text: "user@gmail.com"
|
||||||
|
validator: "email"
|
||||||
|
|
||||||
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-field-validator.png
|
||||||
|
:align: center
|
||||||
|
|
||||||
|
.. tabs::
|
||||||
|
|
||||||
|
.. tab:: Declarative KV style
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from kivy.lang import Builder
|
||||||
|
|
||||||
|
from kivymd.app import MDApp
|
||||||
|
|
||||||
|
KV = '''
|
||||||
|
MDScreen:
|
||||||
|
|
||||||
|
MDBoxLayout:
|
||||||
|
orientation: "vertical"
|
||||||
|
spacing: "20dp"
|
||||||
|
adaptive_height: True
|
||||||
|
size_hint_x: .8
|
||||||
|
pos_hint: {"center_x": .5, "center_y": .5}
|
||||||
|
|
||||||
|
MDTextField:
|
||||||
|
hint_text: "Date dd/mm/yyyy without limits"
|
||||||
|
helper_text: "Enter a valid dd/mm/yyyy date"
|
||||||
|
validator: "date"
|
||||||
|
date_format: "dd/mm/yyyy"
|
||||||
|
|
||||||
|
MDTextField:
|
||||||
|
hint_text: "Date mm/dd/yyyy without limits"
|
||||||
|
helper_text: "Enter a valid mm/dd/yyyy date"
|
||||||
|
validator: "date"
|
||||||
|
date_format: "mm/dd/yyyy"
|
||||||
|
|
||||||
|
MDTextField:
|
||||||
|
hint_text: "Date yyyy/mm/dd without limits"
|
||||||
|
helper_text: "Enter a valid yyyy/mm/dd date"
|
||||||
|
validator: "date"
|
||||||
|
date_format: "yyyy/mm/dd"
|
||||||
|
|
||||||
|
MDTextField:
|
||||||
|
hint_text: "Date dd/mm/yyyy in [01/01/1900, 01/01/2100] interval"
|
||||||
|
helper_text: "Enter a valid dd/mm/yyyy date"
|
||||||
|
validator: "date"
|
||||||
|
date_format: "dd/mm/yyyy"
|
||||||
|
date_interval: "01/01/1900", "01/01/2100"
|
||||||
|
|
||||||
|
MDTextField:
|
||||||
|
hint_text: "Date dd/mm/yyyy in [01/01/1900, None] interval"
|
||||||
|
helper_text: "Enter a valid dd/mm/yyyy date"
|
||||||
|
validator: "date"
|
||||||
|
date_format: "dd/mm/yyyy"
|
||||||
|
date_interval: "01/01/1900", None
|
||||||
|
|
||||||
|
MDTextField:
|
||||||
|
hint_text: "Date dd/mm/yyyy in [None, 01/01/2100] interval"
|
||||||
|
helper_text: "Enter a valid dd/mm/yyyy date"
|
||||||
|
validator: "date"
|
||||||
|
date_format: "dd/mm/yyyy"
|
||||||
|
date_interval: None, "01/01/2100"
|
||||||
|
'''
|
||||||
|
|
||||||
|
|
||||||
|
class Test(MDApp):
|
||||||
|
def build(self):
|
||||||
|
self.theme_cls.theme_style = "Dark"
|
||||||
|
self.theme_cls.primary_palette = "Orange"
|
||||||
|
return Builder.load_string(KV)
|
||||||
|
|
||||||
|
|
||||||
|
Test().run()
|
||||||
|
|
||||||
|
.. tab:: Declarative python style
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from kivymd.app import MDApp
|
||||||
|
from kivymd.uix.boxlayout import MDBoxLayout
|
||||||
|
from kivymd.uix.screen import MDScreen
|
||||||
|
from kivymd.uix.textfield import MDTextField
|
||||||
|
|
||||||
|
|
||||||
|
class Test(MDApp):
|
||||||
|
def build(self):
|
||||||
|
self.theme_cls.theme_style = "Dark"
|
||||||
|
self.theme_cls.primary_palette = "Orange"
|
||||||
|
return (
|
||||||
|
MDScreen(
|
||||||
|
MDBoxLayout(
|
||||||
|
MDTextField(
|
||||||
|
hint_text="Date dd/mm/yyyy without limits",
|
||||||
|
helper_text="Enter a valid dd/mm/yyyy date",
|
||||||
|
validator="date",
|
||||||
|
date_format="dd/mm/yyyy",
|
||||||
|
),
|
||||||
|
MDTextField(
|
||||||
|
hint_text="Date mm/dd/yyyy without limits",
|
||||||
|
helper_text="Enter a valid mm/dd/yyyy date",
|
||||||
|
validator="date",
|
||||||
|
date_format="mm/dd/yyyy",
|
||||||
|
),
|
||||||
|
MDTextField(
|
||||||
|
hint_text="Date yyyy/mm/dd without limits",
|
||||||
|
helper_text="Enter a valid yyyy/mm/dd date",
|
||||||
|
validator="date",
|
||||||
|
date_format="yyyy/mm/dd",
|
||||||
|
),
|
||||||
|
MDTextField(
|
||||||
|
hint_text="Date dd/mm/yyyy in [01/01/1900, 01/01/2100] interval",
|
||||||
|
helper_text="Enter a valid dd/mm/yyyy date",
|
||||||
|
validator="date",
|
||||||
|
date_format="dd/mm/yyyy",
|
||||||
|
date_interval=["01/01/1900", "01/01/2100"],
|
||||||
|
),
|
||||||
|
MDTextField(
|
||||||
|
hint_text="Date dd/mm/yyyy in [01/01/1900, None] interval",
|
||||||
|
helper_text="Enter a valid dd/mm/yyyy date",
|
||||||
|
validator="date",
|
||||||
|
date_format="dd/mm/yyyy",
|
||||||
|
date_interval=["01/01/1900", None],
|
||||||
|
),
|
||||||
|
MDTextField(
|
||||||
|
hint_text="Date dd/mm/yyyy in [None, 01/01/2100] interval",
|
||||||
|
helper_text="Enter a valid dd/mm/yyyy date",
|
||||||
|
validator="date",
|
||||||
|
date_format="dd/mm/yyyy",
|
||||||
|
date_interval=[None, "01/01/2100"],
|
||||||
|
),
|
||||||
|
orientation="vertical",
|
||||||
|
spacing="20dp",
|
||||||
|
adaptive_height=True,
|
||||||
|
size_hint_x=0.8,
|
||||||
|
pos_hint={"center_x": 0.5, "center_y": 0.5},
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
Test().run()
|
||||||
|
|
||||||
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-field-validator-date.png
|
||||||
|
:align: center
|
||||||
|
|
||||||
|
:attr:`validator` is an :class:`~kivy.properties.OptionProperty`
|
||||||
|
and defaults to `None`.
|
||||||
|
"""
|
||||||
|
|
||||||
line_color_normal = ColorProperty([0, 0, 0, 0])
|
line_color_normal = ColorProperty([0, 0, 0, 0])
|
||||||
"""
|
"""
|
||||||
Line color normal (static underline line) in ``rgba`` format.
|
Line color normal (static underline line) in (r, g, b, a) or string format.
|
||||||
|
|
||||||
.. code-block:: kv
|
.. code-block:: kv
|
||||||
|
|
||||||
MDTextField:
|
MDTextField:
|
||||||
hint_text: "line_color_normal"
|
hint_text: "line_color_normal"
|
||||||
line_color_normal: 1, 0, 1, 1
|
line_color_normal: "red"
|
||||||
|
|
||||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-field-line-color-normal.gif
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-field-line-color-normal.png
|
||||||
:align: center
|
:align: center
|
||||||
|
|
||||||
:attr:`line_color_normal` is an :class:`~kivy.properties.ColorProperty`
|
:attr:`line_color_normal` is an :class:`~kivy.properties.ColorProperty`
|
||||||
@ -449,13 +839,13 @@ class MDTextField(DeclarativeBehavior, ThemableBehavior, TextInput):
|
|||||||
|
|
||||||
line_color_focus = ColorProperty([0, 0, 0, 0])
|
line_color_focus = ColorProperty([0, 0, 0, 0])
|
||||||
"""
|
"""
|
||||||
Line color focus (active underline line) in ``rgba`` format.
|
Line color focus (active underline line) in (r, g, b, a) or string format.
|
||||||
|
|
||||||
.. code-block:: kv
|
.. code-block:: kv
|
||||||
|
|
||||||
MDTextField:
|
MDTextField:
|
||||||
hint_text: "line_color_focus"
|
hint_text: "line_color_focus"
|
||||||
line_color_focus: 0, 1, 0, 1
|
line_color_focus: "red"
|
||||||
|
|
||||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-field-line-color-focus.gif
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-field-line-color-focus.gif
|
||||||
:align: center
|
:align: center
|
||||||
@ -474,7 +864,7 @@ class MDTextField(DeclarativeBehavior, ThemableBehavior, TextInput):
|
|||||||
|
|
||||||
error_color = ColorProperty([0, 0, 0, 0])
|
error_color = ColorProperty([0, 0, 0, 0])
|
||||||
"""
|
"""
|
||||||
Error color in ``rgba`` format for ``required = True``.
|
Error color in (r, g, b, a) or string format for ``required = True``.
|
||||||
|
|
||||||
:attr:`error_color` is an :class:`~kivy.properties.ColorProperty`
|
:attr:`error_color` is an :class:`~kivy.properties.ColorProperty`
|
||||||
and defaults to `[0, 0, 0, 0]`.
|
and defaults to `[0, 0, 0, 0]`.
|
||||||
@ -482,7 +872,18 @@ class MDTextField(DeclarativeBehavior, ThemableBehavior, TextInput):
|
|||||||
|
|
||||||
fill_color_normal = ColorProperty([0, 0, 0, 0])
|
fill_color_normal = ColorProperty([0, 0, 0, 0])
|
||||||
"""
|
"""
|
||||||
Fill background color in 'fill' mode when text field is out of focus.
|
Fill background color in (r, g, b, a) or string format in 'fill' mode when]
|
||||||
|
text field is out of focus.
|
||||||
|
|
||||||
|
.. code=block:: kv
|
||||||
|
|
||||||
|
MDTextField:
|
||||||
|
hint_text: "Fill mode"
|
||||||
|
mode: "fill"
|
||||||
|
fill_color_normal: "brown"
|
||||||
|
|
||||||
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-field-fill-color-normal.png
|
||||||
|
:align: center
|
||||||
|
|
||||||
:attr:`fill_color_normal` is an :class:`~kivy.properties.ColorProperty`
|
:attr:`fill_color_normal` is an :class:`~kivy.properties.ColorProperty`
|
||||||
and defaults to `[0, 0, 0, 0]`.
|
and defaults to `[0, 0, 0, 0]`.
|
||||||
@ -490,7 +891,18 @@ class MDTextField(DeclarativeBehavior, ThemableBehavior, TextInput):
|
|||||||
|
|
||||||
fill_color_focus = ColorProperty([0, 0, 0, 0])
|
fill_color_focus = ColorProperty([0, 0, 0, 0])
|
||||||
"""
|
"""
|
||||||
Fill background color in 'fill' mode when the text field has focus.
|
Fill background color in (r, g, b, a) or string format in 'fill' mode when
|
||||||
|
the text field has focus.
|
||||||
|
|
||||||
|
.. code=block:: kv
|
||||||
|
|
||||||
|
MDTextField:
|
||||||
|
hint_text: "Fill mode"
|
||||||
|
mode: "fill"
|
||||||
|
fill_color_focus: "brown"
|
||||||
|
|
||||||
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-field-fill-color-focus.gif
|
||||||
|
:align: center
|
||||||
|
|
||||||
:attr:`fill_color_focus` is an :class:`~kivy.properties.ColorProperty`
|
:attr:`fill_color_focus` is an :class:`~kivy.properties.ColorProperty`
|
||||||
and defaults to `[0, 0, 0, 0]`.
|
and defaults to `[0, 0, 0, 0]`.
|
||||||
@ -514,7 +926,8 @@ class MDTextField(DeclarativeBehavior, ThemableBehavior, TextInput):
|
|||||||
|
|
||||||
hint_text_color_normal = ColorProperty([0, 0, 0, 0])
|
hint_text_color_normal = ColorProperty([0, 0, 0, 0])
|
||||||
"""
|
"""
|
||||||
Hint text color when text field is out of focus.
|
Hint text color in (r, g, b, a) or string format when text field is out
|
||||||
|
of focus.
|
||||||
|
|
||||||
.. versionadded:: 1.0.0
|
.. versionadded:: 1.0.0
|
||||||
|
|
||||||
@ -522,9 +935,9 @@ class MDTextField(DeclarativeBehavior, ThemableBehavior, TextInput):
|
|||||||
|
|
||||||
MDTextField:
|
MDTextField:
|
||||||
hint_text: "hint_text_color_normal"
|
hint_text: "hint_text_color_normal"
|
||||||
hint_text_color_normal: 0, 1, 0, 1
|
hint_text_color_normal: "red"
|
||||||
|
|
||||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-field-hint-text-color-normal.gif
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-field-hint-text-color-normal.png
|
||||||
:align: center
|
:align: center
|
||||||
|
|
||||||
:attr:`hint_text_color_normal` is an :class:`~kivy.properties.ColorProperty`
|
:attr:`hint_text_color_normal` is an :class:`~kivy.properties.ColorProperty`
|
||||||
@ -533,7 +946,8 @@ class MDTextField(DeclarativeBehavior, ThemableBehavior, TextInput):
|
|||||||
|
|
||||||
hint_text_color_focus = ColorProperty([0, 0, 0, 0])
|
hint_text_color_focus = ColorProperty([0, 0, 0, 0])
|
||||||
"""
|
"""
|
||||||
Hint text color when the text field has focus.
|
Hint text color in (r, g, b, a) or string format when the text field has
|
||||||
|
focus.
|
||||||
|
|
||||||
.. versionadded:: 1.0.0
|
.. versionadded:: 1.0.0
|
||||||
|
|
||||||
@ -541,7 +955,7 @@ class MDTextField(DeclarativeBehavior, ThemableBehavior, TextInput):
|
|||||||
|
|
||||||
MDTextField:
|
MDTextField:
|
||||||
hint_text: "hint_text_color_focus"
|
hint_text: "hint_text_color_focus"
|
||||||
hint_text_color_focus: 0, 1, 0, 1
|
hint_text_color_focus: "red"
|
||||||
|
|
||||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-field-hint-text-color-focus.gif
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-field-hint-text-color-focus.gif
|
||||||
:align: center
|
:align: center
|
||||||
@ -552,7 +966,8 @@ class MDTextField(DeclarativeBehavior, ThemableBehavior, TextInput):
|
|||||||
|
|
||||||
helper_text_color_normal = ColorProperty([0, 0, 0, 0])
|
helper_text_color_normal = ColorProperty([0, 0, 0, 0])
|
||||||
"""
|
"""
|
||||||
Helper text color when text field is out of focus.
|
Helper text color in (r, g, b, a) or string format when text field is out
|
||||||
|
of focus.
|
||||||
|
|
||||||
.. versionadded:: 1.0.0
|
.. versionadded:: 1.0.0
|
||||||
|
|
||||||
@ -561,7 +976,7 @@ class MDTextField(DeclarativeBehavior, ThemableBehavior, TextInput):
|
|||||||
MDTextField:
|
MDTextField:
|
||||||
helper_text: "helper_text_color_normal"
|
helper_text: "helper_text_color_normal"
|
||||||
helper_text_mode: "persistent"
|
helper_text_mode: "persistent"
|
||||||
helper_text_color_normal: 0, 1, 0, 1
|
helper_text_color_normal: "red"
|
||||||
|
|
||||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-field-helper-text-color-normal.png
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-field-helper-text-color-normal.png
|
||||||
:align: center
|
:align: center
|
||||||
@ -572,7 +987,8 @@ class MDTextField(DeclarativeBehavior, ThemableBehavior, TextInput):
|
|||||||
|
|
||||||
helper_text_color_focus = ColorProperty([0, 0, 0, 0])
|
helper_text_color_focus = ColorProperty([0, 0, 0, 0])
|
||||||
"""
|
"""
|
||||||
Helper text color when the text field has focus.
|
Helper text color in (r, g, b, a) or string format when the text field has
|
||||||
|
focus.
|
||||||
|
|
||||||
.. versionadded:: 1.0.0
|
.. versionadded:: 1.0.0
|
||||||
|
|
||||||
@ -581,7 +997,7 @@ class MDTextField(DeclarativeBehavior, ThemableBehavior, TextInput):
|
|||||||
MDTextField:
|
MDTextField:
|
||||||
helper_text: "helper_text_color_focus"
|
helper_text: "helper_text_color_focus"
|
||||||
helper_text_mode: "persistent"
|
helper_text_mode: "persistent"
|
||||||
helper_text_color_focus: 0, 1, 0, 1
|
helper_text_color_focus: "red"
|
||||||
|
|
||||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-field-helper-text-color-focus.gif
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-field-helper-text-color-focus.gif
|
||||||
:align: center
|
:align: center
|
||||||
@ -592,7 +1008,8 @@ class MDTextField(DeclarativeBehavior, ThemableBehavior, TextInput):
|
|||||||
|
|
||||||
icon_right_color_normal = ColorProperty([0, 0, 0, 0])
|
icon_right_color_normal = ColorProperty([0, 0, 0, 0])
|
||||||
"""
|
"""
|
||||||
Color of right icon when text field is out of focus.
|
Color in (r, g, b, a) or string format of right icon when text field is out
|
||||||
|
of focus.
|
||||||
|
|
||||||
.. versionadded:: 1.0.0
|
.. versionadded:: 1.0.0
|
||||||
|
|
||||||
@ -601,9 +1018,9 @@ class MDTextField(DeclarativeBehavior, ThemableBehavior, TextInput):
|
|||||||
MDTextField:
|
MDTextField:
|
||||||
icon_right: "language-python"
|
icon_right: "language-python"
|
||||||
hint_text: "icon_right_color_normal"
|
hint_text: "icon_right_color_normal"
|
||||||
icon_right_color_normal: 0, 1, 0, 1
|
icon_right_color_normal: "red"
|
||||||
|
|
||||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-field-icon-right-color-normal.gif
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-field-icon-right-color-normal.png
|
||||||
:align: center
|
:align: center
|
||||||
|
|
||||||
:attr:`icon_right_color_normal` is an :class:`~kivy.properties.ColorProperty`
|
:attr:`icon_right_color_normal` is an :class:`~kivy.properties.ColorProperty`
|
||||||
@ -612,7 +1029,8 @@ class MDTextField(DeclarativeBehavior, ThemableBehavior, TextInput):
|
|||||||
|
|
||||||
icon_right_color_focus = ColorProperty([0, 0, 0, 0])
|
icon_right_color_focus = ColorProperty([0, 0, 0, 0])
|
||||||
"""
|
"""
|
||||||
Color of right icon when the text field has focus.
|
Color in (r, g, b, a) or string format of right icon when the text field
|
||||||
|
has focus.
|
||||||
|
|
||||||
.. versionadded:: 1.0.0
|
.. versionadded:: 1.0.0
|
||||||
|
|
||||||
@ -621,7 +1039,7 @@ class MDTextField(DeclarativeBehavior, ThemableBehavior, TextInput):
|
|||||||
MDTextField:
|
MDTextField:
|
||||||
icon_right: "language-python"
|
icon_right: "language-python"
|
||||||
hint_text: "icon_right_color_focus"
|
hint_text: "icon_right_color_focus"
|
||||||
icon_right_color_focus: 0, 1, 0, 1
|
icon_right_color_focus: "red"
|
||||||
|
|
||||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-field-icon-right-color-focus.gif
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-field-icon-right-color-focus.gif
|
||||||
:align: center
|
:align: center
|
||||||
@ -632,47 +1050,30 @@ class MDTextField(DeclarativeBehavior, ThemableBehavior, TextInput):
|
|||||||
|
|
||||||
icon_left_color_normal = ColorProperty([0, 0, 0, 0])
|
icon_left_color_normal = ColorProperty([0, 0, 0, 0])
|
||||||
"""
|
"""
|
||||||
Color of right icon when text field is out of focus.
|
Color in (r, g, b, a) or string format of right icon when text field is out
|
||||||
|
of focus.
|
||||||
|
|
||||||
.. versionadded:: 1.0.0
|
.. versionadded:: 1.0.0
|
||||||
|
|
||||||
.. code-block:: kv
|
|
||||||
|
|
||||||
MDTextField:
|
|
||||||
icon_right: "language-python"
|
|
||||||
hint_text: "icon_right_color_normal"
|
|
||||||
icon_left_color_normal: 0, 1, 0, 1
|
|
||||||
|
|
||||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-field-icon-right-color-normal.gif
|
|
||||||
:align: center
|
|
||||||
|
|
||||||
:attr:`icon_left_color_normal` is an :class:`~kivy.properties.ColorProperty`
|
:attr:`icon_left_color_normal` is an :class:`~kivy.properties.ColorProperty`
|
||||||
and defaults to `[0, 0, 0, 0]`.
|
and defaults to `[0, 0, 0, 0]`.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
icon_left_color_focus = ColorProperty([0, 0, 0, 0])
|
icon_left_color_focus = ColorProperty([0, 0, 0, 0])
|
||||||
"""
|
"""
|
||||||
Color of right icon when the text field has focus.
|
Color in (r, g, b, a) or string format of right icon when the text field
|
||||||
|
has focus.
|
||||||
|
|
||||||
.. versionadded:: 1.0.0
|
.. versionadded:: 1.0.0
|
||||||
|
|
||||||
.. code-block:: kv
|
|
||||||
|
|
||||||
MDTextField:
|
|
||||||
icon_right: "language-python"
|
|
||||||
hint_text: "icon_right_color_focus"
|
|
||||||
icon_right_color_focus: 0, 1, 0, 1
|
|
||||||
|
|
||||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-field-icon-right-color-focus.gif
|
|
||||||
:align: center
|
|
||||||
|
|
||||||
:attr:`icon_left_color_focus` is an :class:`~kivy.properties.ColorProperty`
|
:attr:`icon_left_color_focus` is an :class:`~kivy.properties.ColorProperty`
|
||||||
and defaults to `[0, 0, 0, 0]`.
|
and defaults to `[0, 0, 0, 0]`.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
max_length_text_color = ColorProperty([0, 0, 0, 0])
|
max_length_text_color = ColorProperty([0, 0, 0, 0])
|
||||||
"""
|
"""
|
||||||
Text color of the maximum length of characters to be input.
|
Text color in (r, g, b, a) or string format of the maximum length of
|
||||||
|
characters to be input.
|
||||||
|
|
||||||
.. versionadded:: 1.0.0
|
.. versionadded:: 1.0.0
|
||||||
|
|
||||||
@ -680,10 +1081,10 @@ class MDTextField(DeclarativeBehavior, ThemableBehavior, TextInput):
|
|||||||
|
|
||||||
MDTextField:
|
MDTextField:
|
||||||
hint_text: "max_length_text_color"
|
hint_text: "max_length_text_color"
|
||||||
max_length_text_color: 0, 1, 0, 1
|
max_length_text_color: "red"
|
||||||
max_text_length: 5
|
max_text_length: 5
|
||||||
|
|
||||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-field-max-length-text-color.gif
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-field-max-length-text-color.png
|
||||||
:align: center
|
:align: center
|
||||||
|
|
||||||
:attr:`max_length_text_color` is an :class:`~kivy.properties.ColorProperty`
|
:attr:`max_length_text_color` is an :class:`~kivy.properties.ColorProperty`
|
||||||
@ -718,7 +1119,7 @@ class MDTextField(DeclarativeBehavior, ThemableBehavior, TextInput):
|
|||||||
|
|
||||||
text_color_normal = ColorProperty([0, 0, 0, 0])
|
text_color_normal = ColorProperty([0, 0, 0, 0])
|
||||||
"""
|
"""
|
||||||
Text color in ``rgba`` format when text field is out of focus.
|
Text color in (r, g, b, a) or string format when text field is out of focus.
|
||||||
|
|
||||||
.. versionadded:: 1.0.0
|
.. versionadded:: 1.0.0
|
||||||
|
|
||||||
@ -726,9 +1127,9 @@ class MDTextField(DeclarativeBehavior, ThemableBehavior, TextInput):
|
|||||||
|
|
||||||
MDTextField:
|
MDTextField:
|
||||||
hint_text: "text_color_normal"
|
hint_text: "text_color_normal"
|
||||||
text_color_normal: 0, 1, 0, 1
|
text_color_normal: "red"
|
||||||
|
|
||||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-field-text-color-normal.gif
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-field-text-color-normal.png
|
||||||
:align: center
|
:align: center
|
||||||
|
|
||||||
:attr:`text_color_normal` is an :class:`~kivy.properties.ColorProperty`
|
:attr:`text_color_normal` is an :class:`~kivy.properties.ColorProperty`
|
||||||
@ -737,7 +1138,7 @@ class MDTextField(DeclarativeBehavior, ThemableBehavior, TextInput):
|
|||||||
|
|
||||||
text_color_focus = ColorProperty([0, 0, 0, 0])
|
text_color_focus = ColorProperty([0, 0, 0, 0])
|
||||||
"""
|
"""
|
||||||
Text color in ``rgba`` format when text field has focus.
|
Text color in (r, g, b, a) or string format when text field has focus.
|
||||||
|
|
||||||
.. versionadded:: 1.0.0
|
.. versionadded:: 1.0.0
|
||||||
|
|
||||||
@ -745,7 +1146,7 @@ class MDTextField(DeclarativeBehavior, ThemableBehavior, TextInput):
|
|||||||
|
|
||||||
MDTextField:
|
MDTextField:
|
||||||
hint_text: "text_color_focus"
|
hint_text: "text_color_focus"
|
||||||
text_color_focus: 0, 1, 0, 1
|
text_color_focus: "red"
|
||||||
|
|
||||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-field-text-color-focus.gif
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-field-text-color-focus.gif
|
||||||
:align: center
|
:align: center
|
||||||
@ -879,8 +1280,8 @@ class MDTextField(DeclarativeBehavior, ThemableBehavior, TextInput):
|
|||||||
text=self.set_text,
|
text=self.set_text,
|
||||||
)
|
)
|
||||||
self.theme_cls.bind(
|
self.theme_cls.bind(
|
||||||
primary_color=lambda x, y: self.set_default_colors(0, True),
|
primary_color=self.set_default_colors,
|
||||||
theme_style=lambda x, y: self.set_default_colors(0, True),
|
theme_style=self.set_default_colors,
|
||||||
)
|
)
|
||||||
Clock.schedule_once(self.check_text)
|
Clock.schedule_once(self.check_text)
|
||||||
|
|
||||||
@ -930,9 +1331,17 @@ class MDTextField(DeclarativeBehavior, ThemableBehavior, TextInput):
|
|||||||
)
|
)
|
||||||
|
|
||||||
if self.error_color == [0, 0, 0, 0] or updated:
|
if self.error_color == [0, 0, 0, 0] or updated:
|
||||||
self.error_color = self.theme_cls.error_color
|
self.error_color = (
|
||||||
|
self.theme_cls.error_color
|
||||||
|
if self.error_color == [0, 0, 0, 0]
|
||||||
|
else self.error_color
|
||||||
|
)
|
||||||
if self.max_length_text_color == [0, 0, 0, 0] or updated:
|
if self.max_length_text_color == [0, 0, 0, 0] or updated:
|
||||||
self.max_length_text_color = self.theme_cls.disabled_hint_text_color
|
self.max_length_text_color = (
|
||||||
|
self.theme_cls.disabled_hint_text_color
|
||||||
|
if self.max_length_text_color == [0, 0, 0, 0]
|
||||||
|
else self.max_length_text_color
|
||||||
|
)
|
||||||
|
|
||||||
self._hint_text_color = self.hint_text_color_normal
|
self._hint_text_color = self.hint_text_color_normal
|
||||||
self._text_color_normal = self.text_color_normal
|
self._text_color_normal = self.text_color_normal
|
||||||
@ -1101,8 +1510,11 @@ class MDTextField(DeclarativeBehavior, ThemableBehavior, TextInput):
|
|||||||
|
|
||||||
self.text = re.sub("\n", " ", text) if not self.multiline else text
|
self.text = re.sub("\n", " ", text) if not self.multiline else text
|
||||||
self.set_max_text_length()
|
self.set_max_text_length()
|
||||||
|
if self.validator and self.validator == "phone":
|
||||||
|
pass
|
||||||
|
# self.format(self.text)
|
||||||
|
|
||||||
if self.text and self.max_length_text_color and self._get_has_error():
|
if (self.text and self.max_length_text_color) or self._get_has_error():
|
||||||
self.error = True
|
self.error = True
|
||||||
if (
|
if (
|
||||||
self.text
|
self.text
|
||||||
@ -1301,22 +1713,34 @@ class MDTextField(DeclarativeBehavior, ThemableBehavior, TextInput):
|
|||||||
if value_height >= self.max_height and self.max_height:
|
if value_height >= self.max_height and self.max_height:
|
||||||
self.height = self.max_height
|
self.height = self.max_height
|
||||||
|
|
||||||
def on_text_color_normal(self, instance_text_field, color: list):
|
def on_text_color_normal(
|
||||||
|
self, instance_text_field, color: Union[list, str]
|
||||||
|
):
|
||||||
self._text_color_normal = color
|
self._text_color_normal = color
|
||||||
|
|
||||||
def on_hint_text_color_normal(self, instance_text_field, color: list):
|
def on_hint_text_color_normal(
|
||||||
|
self, instance_text_field, color: Union[list, str]
|
||||||
|
):
|
||||||
self._hint_text_color = color
|
self._hint_text_color = color
|
||||||
|
|
||||||
def on_helper_text_color_normal(self, instance_text_field, color: list):
|
def on_helper_text_color_normal(
|
||||||
|
self, instance_text_field, color: Union[list, str]
|
||||||
|
):
|
||||||
self._helper_text_color = color
|
self._helper_text_color = color
|
||||||
|
|
||||||
def on_icon_right_color_normal(self, instance_text_field, color: list):
|
def on_icon_right_color_normal(
|
||||||
|
self, instance_text_field, color: Union[list, str]
|
||||||
|
):
|
||||||
self._icon_right_color = color
|
self._icon_right_color = color
|
||||||
|
|
||||||
def on_line_color_normal(self, instance_text_field, color: list):
|
def on_line_color_normal(
|
||||||
|
self, instance_text_field, color: Union[list, str]
|
||||||
|
):
|
||||||
self._line_color_normal = color
|
self._line_color_normal = color
|
||||||
|
|
||||||
def on_max_length_text_color(self, instance_text_field, color: list):
|
def on_max_length_text_color(
|
||||||
|
self, instance_text_field, color: Union[list, str]
|
||||||
|
):
|
||||||
self._max_length_text_color = color
|
self._max_length_text_color = color
|
||||||
|
|
||||||
def _set_color(self, attr_name: str, color: str, updated: bool) -> None:
|
def _set_color(self, attr_name: str, color: str, updated: bool) -> None:
|
||||||
@ -1353,6 +1777,13 @@ class MDTextField(DeclarativeBehavior, ThemableBehavior, TextInput):
|
|||||||
the :attr:`~MDTextField.required` parameter is set to `True`.
|
the :attr:`~MDTextField.required` parameter is set to `True`.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
if self.validator and self.validator != "phone":
|
||||||
|
has_error = {
|
||||||
|
"date": self.is_date_valid,
|
||||||
|
"email": self.is_email_valid,
|
||||||
|
"time": self.is_time_valid,
|
||||||
|
}[self.validator](self.text)
|
||||||
|
return has_error
|
||||||
if self.max_text_length and len(self.text) > self.max_text_length:
|
if self.max_text_length and len(self.text) > self.max_text_length:
|
||||||
has_error = True
|
has_error = True
|
||||||
else:
|
else:
|
||||||
@ -1367,9 +1798,12 @@ class MDTextField(DeclarativeBehavior, ThemableBehavior, TextInput):
|
|||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
from kivy.core.window import Window
|
||||||
from kivy.lang import Builder
|
from kivy.lang import Builder
|
||||||
from kivy.uix.textinput import TextInput
|
from kivy.uix.textinput import TextInput
|
||||||
|
|
||||||
|
Window.size = (800, 750)
|
||||||
|
|
||||||
from kivymd.app import MDApp
|
from kivymd.app import MDApp
|
||||||
|
|
||||||
KV = """
|
KV = """
|
||||||
@ -1385,41 +1819,53 @@ MDScreen:
|
|||||||
|
|
||||||
MDTextField:
|
MDTextField:
|
||||||
hint_text: "Label"
|
hint_text: "Label"
|
||||||
helper_text: "Error massage"
|
helper_text: "Error message"
|
||||||
mode: "rectangle"
|
mode: "rectangle"
|
||||||
max_text_length: 5
|
max_text_length: 5
|
||||||
|
|
||||||
MDTextField:
|
MDTextField:
|
||||||
icon_left: "git"
|
icon_left: "git"
|
||||||
hint_text: "Label"
|
hint_text: "Label"
|
||||||
helper_text: "Error massage"
|
helper_text: "Error message"
|
||||||
mode: "rectangle"
|
mode: "rectangle"
|
||||||
|
|
||||||
MDTextField:
|
MDTextField:
|
||||||
icon_left: "git"
|
icon_left: "git"
|
||||||
hint_text: "Label"
|
hint_text: "Label"
|
||||||
helper_text: "Error massage"
|
helper_text: "Error message"
|
||||||
mode: "fill"
|
mode: "fill"
|
||||||
|
|
||||||
MDTextField:
|
MDTextField:
|
||||||
hint_text: "Label"
|
hint_text: "Label"
|
||||||
helper_text: "Error massage"
|
helper_text: "Error message"
|
||||||
mode: "fill"
|
mode: "fill"
|
||||||
|
|
||||||
MDTextField:
|
MDTextField:
|
||||||
hint_text: "Label"
|
hint_text: "Label"
|
||||||
helper_text: "Error massage"
|
helper_text: "Error message"
|
||||||
|
|
||||||
MDTextField:
|
MDTextField:
|
||||||
icon_left: "git"
|
icon_left: "git"
|
||||||
hint_text: "Label"
|
hint_text: "Label"
|
||||||
helper_text: "Error massage"
|
helper_text: "Error message"
|
||||||
|
|
||||||
MDTextField:
|
MDTextField:
|
||||||
hint_text: "Round mode"
|
hint_text: "Round mode"
|
||||||
mode: "round"
|
mode: "round"
|
||||||
max_text_length: 15
|
max_text_length: 15
|
||||||
helper_text: "Massage"
|
helper_text: "Message"
|
||||||
|
|
||||||
|
MDTextField:
|
||||||
|
hint_text: "Date dd/mm/yyyy in [01/01/1900, 01/01/2100] interval"
|
||||||
|
helper_text: "Enter a valid dd/mm/yyyy date"
|
||||||
|
validator: "date"
|
||||||
|
date_format: "dd/mm/yyyy"
|
||||||
|
date_interval: "01/01/1900", "01/01/2100"
|
||||||
|
|
||||||
|
MDTextField:
|
||||||
|
hint_text: "Email"
|
||||||
|
helper_text: "user@gmail.com"
|
||||||
|
validator: "email"
|
||||||
|
|
||||||
MDFlatButton:
|
MDFlatButton:
|
||||||
text: "SET TEXT"
|
text: "SET TEXT"
|
||||||
@ -1429,6 +1875,8 @@ MDScreen:
|
|||||||
|
|
||||||
class Test(MDApp):
|
class Test(MDApp):
|
||||||
def build(self):
|
def build(self):
|
||||||
|
self.theme_cls.theme_style = "Dark"
|
||||||
|
self.theme_cls.primary_palette = "Orange"
|
||||||
return Builder.load_string(KV)
|
return Builder.load_string(KV)
|
||||||
|
|
||||||
def set_text(self):
|
def set_text(self):
|
||||||
|
@ -121,8 +121,8 @@ Shadow elevation control
|
|||||||
.. code-block:: kv
|
.. code-block:: kv
|
||||||
|
|
||||||
MDTopAppBar:
|
MDTopAppBar:
|
||||||
title: "Elevation 10"
|
title: "Elevation 4"
|
||||||
elevation: 10
|
elevation: 4
|
||||||
|
|
||||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/toolbar-7.png
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/toolbar-7.png
|
||||||
:align: center
|
:align: center
|
||||||
@ -327,7 +327,7 @@ Material design 3 style
|
|||||||
:align: center
|
:align: center
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__all__ = ("MDTopAppBar", "MDBottomAppBar")
|
__all__ = ("MDTopAppBar", "MDBottomAppBar", "ActionTopAppBarButton")
|
||||||
|
|
||||||
import os
|
import os
|
||||||
from math import cos, radians, sin
|
from math import cos, radians, sin
|
||||||
@ -337,10 +337,8 @@ from kivy.animation import Animation
|
|||||||
from kivy.clock import Clock
|
from kivy.clock import Clock
|
||||||
from kivy.core.window import Window
|
from kivy.core.window import Window
|
||||||
from kivy.lang import Builder
|
from kivy.lang import Builder
|
||||||
from kivy.logger import Logger
|
|
||||||
from kivy.metrics import dp
|
from kivy.metrics import dp
|
||||||
from kivy.properties import (
|
from kivy.properties import (
|
||||||
AliasProperty,
|
|
||||||
BooleanProperty,
|
BooleanProperty,
|
||||||
ColorProperty,
|
ColorProperty,
|
||||||
ListProperty,
|
ListProperty,
|
||||||
@ -356,15 +354,15 @@ from kivymd import uix_path
|
|||||||
from kivymd.color_definitions import text_colors
|
from kivymd.color_definitions import text_colors
|
||||||
from kivymd.theming import ThemableBehavior
|
from kivymd.theming import ThemableBehavior
|
||||||
from kivymd.uix.behaviors import (
|
from kivymd.uix.behaviors import (
|
||||||
|
CommonElevationBehavior,
|
||||||
DeclarativeBehavior,
|
DeclarativeBehavior,
|
||||||
FakeRectangularElevationBehavior,
|
ScaleBehavior,
|
||||||
SpecificBackgroundColorBehavior,
|
SpecificBackgroundColorBehavior,
|
||||||
)
|
)
|
||||||
from kivymd.uix.button import MDFloatingActionButton, MDIconButton
|
from kivymd.uix.button import MDFloatingActionButton, MDIconButton
|
||||||
from kivymd.uix.controllers import WindowController
|
from kivymd.uix.controllers import WindowController
|
||||||
from kivymd.uix.list import OneLineIconListItem
|
from kivymd.uix.list import OneLineIconListItem
|
||||||
from kivymd.uix.menu import MDDropdownMenu
|
from kivymd.uix.menu import MDDropdownMenu
|
||||||
from kivymd.uix.templates import ScaleWidget
|
|
||||||
from kivymd.uix.tooltip import MDTooltip
|
from kivymd.uix.tooltip import MDTooltip
|
||||||
from kivymd.utils.set_bars_colors import set_bars_colors
|
from kivymd.utils.set_bars_colors import set_bars_colors
|
||||||
|
|
||||||
@ -374,7 +372,7 @@ with open(
|
|||||||
Builder.load_string(kv_file.read())
|
Builder.load_string(kv_file.read())
|
||||||
|
|
||||||
|
|
||||||
class ActionBottomAppBarButton(MDFloatingActionButton, ScaleWidget):
|
class ActionBottomAppBarButton(MDFloatingActionButton, ScaleBehavior):
|
||||||
"""
|
"""
|
||||||
Implements a floating action button (FAB) for a toolbar with type 'bottom'.
|
Implements a floating action button (FAB) for a toolbar with type 'bottom'.
|
||||||
"""
|
"""
|
||||||
@ -409,11 +407,11 @@ class OverFlowMenuItem(OneLineIconListItem):
|
|||||||
|
|
||||||
class NotchedBox(
|
class NotchedBox(
|
||||||
ThemableBehavior,
|
ThemableBehavior,
|
||||||
FakeRectangularElevationBehavior,
|
CommonElevationBehavior,
|
||||||
SpecificBackgroundColorBehavior,
|
SpecificBackgroundColorBehavior,
|
||||||
BoxLayout,
|
BoxLayout,
|
||||||
):
|
):
|
||||||
elevation = NumericProperty(6)
|
elevation = NumericProperty(4)
|
||||||
notch_radius = NumericProperty()
|
notch_radius = NumericProperty()
|
||||||
notch_center_x = NumericProperty("100dp")
|
notch_center_x = NumericProperty("100dp")
|
||||||
|
|
||||||
@ -961,8 +959,10 @@ class MDTopAppBar(DeclarativeBehavior, NotchedBox, WindowController):
|
|||||||
self.icon_color = self.theme_cls.primary_color
|
self.icon_color = self.theme_cls.primary_color
|
||||||
|
|
||||||
self.bind(specific_text_color=self.update_action_bar_text_colors)
|
self.bind(specific_text_color=self.update_action_bar_text_colors)
|
||||||
self.theme_cls.bind(material_style=self.update_bar_height)
|
self.theme_cls.bind(
|
||||||
self.theme_cls.bind(primary_palette=self.update_md_bg_color)
|
material_style=self.update_bar_height,
|
||||||
|
primary_palette=self.update_md_bg_color,
|
||||||
|
)
|
||||||
|
|
||||||
Clock.schedule_once(
|
Clock.schedule_once(
|
||||||
lambda x: self.on_left_action_items(0, self.left_action_items)
|
lambda x: self.on_left_action_items(0, self.left_action_items)
|
||||||
@ -1103,6 +1103,7 @@ class MDTopAppBar(DeclarativeBehavior, NotchedBox, WindowController):
|
|||||||
+ self.theme_cls.standard_increment / 2
|
+ self.theme_cls.standard_increment / 2
|
||||||
+ self._shift
|
+ self._shift
|
||||||
)
|
)
|
||||||
|
self.shadow_offset = [0, 30]
|
||||||
self.on_mode(None, self.mode)
|
self.on_mode(None, self.mode)
|
||||||
|
|
||||||
def on_type_height(self, instance_toolbar, height_type_value: str) -> None:
|
def on_type_height(self, instance_toolbar, height_type_value: str) -> None:
|
||||||
|
@ -314,7 +314,7 @@ class MDTooltip(ThemableBehavior, HoverBehavior, TouchBehavior):
|
|||||||
Clock.schedule_once(self.animation_tooltip_dismiss)
|
Clock.schedule_once(self.animation_tooltip_dismiss)
|
||||||
|
|
||||||
def on_show(self) -> None:
|
def on_show(self) -> None:
|
||||||
"""Default dismiss event handler."""
|
"""Default display event handler."""
|
||||||
|
|
||||||
def on_dismiss(self) -> None:
|
def on_dismiss(self) -> None:
|
||||||
"""
|
"""
|
||||||
|
@ -35,7 +35,9 @@ __all__ = (
|
|||||||
"MDTransitionBase",
|
"MDTransitionBase",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
from kivy import Logger
|
||||||
from kivy.animation import Animation, AnimationTransition
|
from kivy.animation import Animation, AnimationTransition
|
||||||
|
from kivy.properties import DictProperty
|
||||||
from kivy.uix.screenmanager import (
|
from kivy.uix.screenmanager import (
|
||||||
ScreenManagerException,
|
ScreenManagerException,
|
||||||
SlideTransition,
|
SlideTransition,
|
||||||
@ -43,13 +45,41 @@ from kivy.uix.screenmanager import (
|
|||||||
TransitionBase,
|
TransitionBase,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
from kivymd.uix.hero import MDHeroFrom, MDHeroTo
|
||||||
from kivymd.uix.screenmanager import MDScreenManager
|
from kivymd.uix.screenmanager import MDScreenManager
|
||||||
|
|
||||||
|
|
||||||
class MDTransitionBase(TransitionBase):
|
class MDTransitionBase(TransitionBase):
|
||||||
|
"""
|
||||||
|
TransitionBase is used to animate 2 screens within the
|
||||||
|
:class:`~kivymd.uix.screenmanager.MDScreenManager`.
|
||||||
|
|
||||||
|
For more
|
||||||
|
information, see in the :class:`~kivy.uix.screenmanager.TransitionBase`
|
||||||
|
class documentation.
|
||||||
|
"""
|
||||||
|
|
||||||
_direction = "in"
|
_direction = "in"
|
||||||
hero_widget = None
|
# Collection of child widgets of all 'MDHeroFrom' widgets that are
|
||||||
hero_from_widget = None # kivymd.uix.hero.MDHeroFrom object
|
# on the screen, for example:
|
||||||
|
#
|
||||||
|
# MDScreen:
|
||||||
|
#
|
||||||
|
# MDHeroFrom:
|
||||||
|
# tag: "kivymd"
|
||||||
|
#
|
||||||
|
# FitImage:
|
||||||
|
#
|
||||||
|
# MDHeroFrom:
|
||||||
|
# tag: "kivy"
|
||||||
|
#
|
||||||
|
# FitImage:
|
||||||
|
#
|
||||||
|
# {
|
||||||
|
# 'kivy': <kivymd.uix.fitimage.fitimage.FitImage object>,
|
||||||
|
# 'kivymd': <kivymd.uix.fitimage.fitimage.FitImage object>,
|
||||||
|
# }
|
||||||
|
_hero_from_widget_children = DictProperty()
|
||||||
|
|
||||||
def start(self, instance_screen_manager: MDScreenManager) -> None:
|
def start(self, instance_screen_manager: MDScreenManager) -> None:
|
||||||
super().start(instance_screen_manager)
|
super().start(instance_screen_manager)
|
||||||
@ -59,67 +89,160 @@ class MDTransitionBase(TransitionBase):
|
|||||||
]()
|
]()
|
||||||
|
|
||||||
def animated_hero_in(self) -> None:
|
def animated_hero_in(self) -> None:
|
||||||
if self.manager._heroes_data and self.manager.current_hero:
|
"""Animates the flight of heroes from screen **A** to screen **B**."""
|
||||||
self.hero_from_widget = self.manager.get_hero_from_widget()
|
|
||||||
self._check_widget_properties()
|
|
||||||
self.hero_widget = self.hero_from_widget.children[0]
|
|
||||||
self.hero_from_widget.remove_widget(self.hero_widget)
|
|
||||||
|
|
||||||
self.hero_widget.pos = self.screen_out.to_widget(
|
if self.manager._heroes_data and self.manager.current_heroes:
|
||||||
*self.hero_from_widget.to_window(*self.hero_from_widget.pos)
|
for hero_from_widget in self.manager.get_hero_from_widget():
|
||||||
|
for heroes_tag in self.manager.current_heroes:
|
||||||
|
if heroes_tag == hero_from_widget.tag:
|
||||||
|
self._check_widget_properties(hero_from_widget)
|
||||||
|
|
||||||
|
# Get child widget of the 'MDHeroFrom' container.
|
||||||
|
hero_widget = hero_from_widget.children[0]
|
||||||
|
self._hero_from_widget_children[
|
||||||
|
hero_from_widget.tag
|
||||||
|
] = hero_widget
|
||||||
|
|
||||||
|
# Removing the child widget from the 'MDHeroFrom'
|
||||||
|
# container.
|
||||||
|
hero_from_widget.remove_widget(hero_widget)
|
||||||
|
|
||||||
|
# We set the size, position of the child widget of the
|
||||||
|
# 'MDHeroFrom' container and add this widget to the
|
||||||
|
# root window.
|
||||||
|
hero_widget.pos = self.screen_out.to_widget(
|
||||||
|
*hero_from_widget.to_window(*hero_from_widget.pos)
|
||||||
)
|
)
|
||||||
self.hero_widget.size = self.hero_from_widget.size
|
hero_widget.size = hero_from_widget.size
|
||||||
self.manager.get_root_window().add_widget(self.hero_widget)
|
self.manager.get_root_window().add_widget(hero_widget)
|
||||||
|
|
||||||
|
# Animating widgets added to the root window.
|
||||||
|
if self.screen_in.heroes_to:
|
||||||
|
for hero_to_widget in self.screen_in.heroes_to:
|
||||||
|
self._check_hero_to_widget_tag(
|
||||||
|
hero_to_widget, hero_from_widget
|
||||||
|
)
|
||||||
|
if hero_to_widget.tag == heroes_tag:
|
||||||
Animation(
|
Animation(
|
||||||
size=self.screen_in.hero_to.size,
|
size=hero_to_widget.size,
|
||||||
d=self.duration,
|
d=self.duration,
|
||||||
pos=self.screen_in.hero_to.pos,
|
pos=hero_to_widget.pos,
|
||||||
).start(self.hero_widget)
|
).start(hero_widget)
|
||||||
self.hero_from_widget.dispatch(
|
hero_from_widget.dispatch(
|
||||||
"on_transform_in", self.hero_widget, self.duration
|
"on_transform_in",
|
||||||
|
hero_widget,
|
||||||
|
self.duration,
|
||||||
)
|
)
|
||||||
|
|
||||||
def animated_hero_out(self) -> None:
|
def animated_hero_out(self) -> None:
|
||||||
if self.manager._heroes_data and self.manager.current_hero:
|
"""Animates the flight of heroes from screen **B** to screen **A**."""
|
||||||
self.screen_out.hero_to.remove_widget(self.hero_widget)
|
|
||||||
self.manager.get_root_window().add_widget(self.hero_widget)
|
|
||||||
|
|
||||||
self.hero_from_widget.dispatch(
|
if (
|
||||||
"on_transform_out", self.hero_widget, self.duration
|
self.manager._heroes_data
|
||||||
|
and self.manager.current_heroes
|
||||||
|
and self.screen_out.heroes_to
|
||||||
|
):
|
||||||
|
|
||||||
|
for heroes_tag in self.manager.current_heroes:
|
||||||
|
for hero_to_widget in self.screen_out.heroes_to:
|
||||||
|
if hero_to_widget.tag == heroes_tag:
|
||||||
|
hero_from_children = self._hero_from_widget_children[
|
||||||
|
heroes_tag
|
||||||
|
]
|
||||||
|
hero_to_widget.remove_widget(hero_from_children)
|
||||||
|
self.manager.get_root_window().add_widget(
|
||||||
|
hero_from_children
|
||||||
|
)
|
||||||
|
|
||||||
|
for (
|
||||||
|
hero_from_widget
|
||||||
|
) in self.manager.get_hero_from_widget():
|
||||||
|
hero_from_widget.dispatch(
|
||||||
|
"on_transform_out",
|
||||||
|
self._hero_from_widget_children[
|
||||||
|
hero_from_widget.tag
|
||||||
|
],
|
||||||
|
self.duration,
|
||||||
)
|
)
|
||||||
Animation(
|
Animation(
|
||||||
pos=self.screen_in.to_widget(
|
pos=self.screen_in.to_widget(
|
||||||
*self.hero_from_widget.to_window(*self.hero_from_widget.pos)
|
*hero_from_widget.to_window(
|
||||||
|
*hero_from_widget.pos
|
||||||
|
)
|
||||||
),
|
),
|
||||||
size=self.hero_from_widget.size,
|
size=hero_from_widget.size,
|
||||||
d=self.duration,
|
d=self.duration,
|
||||||
).start(self.hero_widget)
|
).start(
|
||||||
|
self._hero_from_widget_children[
|
||||||
|
hero_from_widget.tag
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
def on_complete(self) -> None:
|
def on_complete(self) -> None:
|
||||||
|
"""
|
||||||
|
Override method.
|
||||||
|
See :attr:`kivy.uix.screenmanager.TransitionBase.on_complete'.
|
||||||
|
"""
|
||||||
|
|
||||||
super().on_complete()
|
super().on_complete()
|
||||||
|
|
||||||
|
if self.manager._heroes_data and self.manager.current_heroes:
|
||||||
|
for hero_from_widget in self.manager.get_hero_from_widget():
|
||||||
|
for heroes_tag in self.manager.current_heroes:
|
||||||
|
if heroes_tag == hero_from_widget.tag:
|
||||||
|
hero_from_children = self._hero_from_widget_children[
|
||||||
|
heroes_tag
|
||||||
|
]
|
||||||
|
self.manager.get_root_window().remove_widget(
|
||||||
|
hero_from_children
|
||||||
|
)
|
||||||
|
|
||||||
|
# Adding a child widget from the 'MDHeraFrom' container
|
||||||
|
# to the 'MDHeroTo' container.
|
||||||
|
if self._direction == "in":
|
||||||
|
for hero_to_widget in self.screen_in.heroes_to:
|
||||||
|
if hero_to_widget.tag == heroes_tag:
|
||||||
|
hero_to_widget.add_widget(
|
||||||
|
hero_from_children
|
||||||
|
)
|
||||||
|
# Restores the child widget for the 'MDHeraFrom'
|
||||||
|
# container.
|
||||||
|
elif self._direction == "out":
|
||||||
|
hero_from_widget.add_widget(hero_from_children)
|
||||||
|
|
||||||
if self._direction == "out":
|
if self._direction == "out":
|
||||||
self._direction = "in"
|
self._direction = "in"
|
||||||
if self.manager._heroes_data and self.manager.current_hero:
|
|
||||||
self.manager.get_root_window().remove_widget(self.hero_widget)
|
|
||||||
self.hero_from_widget.add_widget(self.hero_widget)
|
|
||||||
else:
|
else:
|
||||||
self._direction = "out"
|
self._direction = "out"
|
||||||
if self.manager._heroes_data and self.manager.current_hero:
|
|
||||||
self.manager.get_root_window().remove_widget(self.hero_widget)
|
|
||||||
self.screen_in.hero_to.add_widget(self.hero_widget)
|
|
||||||
|
|
||||||
def _check_widget_properties(self):
|
# Checks the attributes for the 'self.screen_in' screen.
|
||||||
if not self.screen_in.hero_to:
|
# Called from the animated_hero_in method.
|
||||||
|
def _check_widget_properties(self, hero_from_widget: MDHeroFrom):
|
||||||
|
if not self.screen_in.heroes_to:
|
||||||
raise Exception(
|
raise Exception(
|
||||||
f"The `hero_to` attribute is not specified for screen {self.screen_in}"
|
f"The `heroes_to` attribute is not specified for screen "
|
||||||
|
f"{self.screen_in}"
|
||||||
)
|
)
|
||||||
if len(self.hero_from_widget.children) > 1:
|
# The 'MDHeroFrom' widget allows you to place only one widget in
|
||||||
|
# itself.
|
||||||
|
if len(hero_from_widget.children) > 1:
|
||||||
raise Exception(
|
raise Exception(
|
||||||
f"{self.hero_from_widget.__class__} accept only one widget"
|
f"{hero_from_widget.__class__} accept only one widget"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# For new API support.
|
||||||
|
def _check_hero_to_widget_tag(
|
||||||
|
self, hero_to_widget: MDHeroTo, hero_from_widget: MDHeroFrom
|
||||||
|
) -> None:
|
||||||
|
if not hero_to_widget.tag:
|
||||||
|
Logger.warning(
|
||||||
|
"KivyMD: "
|
||||||
|
f"Set the tag '{hero_from_widget.tag}' "
|
||||||
|
f"for the {hero_to_widget} widget to the same "
|
||||||
|
f"as for the {hero_from_widget} widget"
|
||||||
|
)
|
||||||
|
hero_to_widget.tag = hero_from_widget.tag
|
||||||
|
|
||||||
|
|
||||||
class MDSwapTransition(SwapTransition, MDTransitionBase):
|
class MDSwapTransition(SwapTransition, MDTransitionBase):
|
||||||
pass
|
pass
|
||||||
|
@ -36,11 +36,13 @@ MDWidget
|
|||||||
|
|
||||||
__all__ = ("MDWidget",)
|
__all__ = ("MDWidget",)
|
||||||
|
|
||||||
|
from kivy.uix.widget import Widget
|
||||||
|
|
||||||
from kivymd.uix import MDAdaptiveWidget
|
from kivymd.uix import MDAdaptiveWidget
|
||||||
from kivymd.uix.behaviors import DeclarativeBehavior
|
from kivymd.uix.behaviors import DeclarativeBehavior
|
||||||
|
|
||||||
|
|
||||||
class MDWidget(DeclarativeBehavior, MDAdaptiveWidget):
|
class MDWidget(DeclarativeBehavior, MDAdaptiveWidget, Widget):
|
||||||
"""
|
"""
|
||||||
See :class:`~kivy.uix.Widget` class documentation for more information.
|
See :class:`~kivy.uix.Widget` class documentation for more information.
|
||||||
|
|
||||||
|