Reverted kivymd to avoid shader crash on Android
@ -49,9 +49,6 @@ images_path = os.path.join(path, f"images{os.sep}")
|
||||
uix_path = os.path.join(path, "uix")
|
||||
"""Path to uix directory."""
|
||||
|
||||
glsl_path = os.path.join(path, "data", "glsl")
|
||||
"""Path to glsl directory."""
|
||||
|
||||
_log_message = (
|
||||
"KivyMD:"
|
||||
+ (" Release" if release else "")
|
||||
|
@ -45,7 +45,7 @@ import os
|
||||
from kivy.app import App
|
||||
from kivy.lang import Builder
|
||||
from kivy.logger import Logger
|
||||
from kivy.properties import ObjectProperty, StringProperty
|
||||
from kivy.properties import ObjectProperty
|
||||
|
||||
from kivymd.theming import ThemeManager
|
||||
|
||||
@ -71,16 +71,6 @@ class MDApp(App, FpsMonitoring):
|
||||
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()
|
||||
"""
|
||||
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()
|
||||
|
||||
for name_tab in colors.keys():
|
||||
tab = Tab(title=name_tab)
|
||||
tab = Tab(text=name_tab)
|
||||
self.screen.ids.android_tabs.add_widget(tab)
|
||||
return self.screen
|
||||
|
||||
@ -427,7 +427,7 @@ To demonstrate the shades of the palette, you can run the following code:
|
||||
{
|
||||
"viewclass": "ItemColor",
|
||||
"md_bg_color": colors[tab_text][value_color],
|
||||
"title": value_color,
|
||||
"text": value_color,
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -1,44 +0,0 @@
|
||||
/*
|
||||
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
|
||||
*/
|
||||
|
||||
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 - 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 - smoothstep(
|
||||
-shadow_softness, shadow_softness, shadowDistance
|
||||
);
|
||||
fragColor = mix(quadColor, shadow_color, shadowAlpha - smoothedAlpha);
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
#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;
|
@ -1,10 +0,0 @@
|
||||
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: 2.3 KiB After Width: | Height: | Size: 29 KiB |
BIN
sbapp/kivymd/images/quad_shadow-0.png
Normal file
After Width: | Height: | Size: 31 KiB |
BIN
sbapp/kivymd/images/quad_shadow-1.png
Normal file
After Width: | Height: | Size: 31 KiB |
BIN
sbapp/kivymd/images/quad_shadow-2.png
Normal file
After Width: | Height: | Size: 21 KiB |
1
sbapp/kivymd/images/quad_shadow.atlas
Normal file
@ -0,0 +1 @@
|
||||
{"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]}}
|
BIN
sbapp/kivymd/images/rec_shadow-0.png
Normal file
After Width: | Height: | Size: 46 KiB |
BIN
sbapp/kivymd/images/rec_shadow-1.png
Normal file
After Width: | Height: | Size: 43 KiB |
1
sbapp/kivymd/images/rec_shadow.atlas
Normal file
@ -0,0 +1 @@
|
||||
{"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]}}
|
BIN
sbapp/kivymd/images/rec_st_shadow-0.png
Normal file
After Width: | Height: | Size: 30 KiB |
BIN
sbapp/kivymd/images/rec_st_shadow-1.png
Normal file
After Width: | Height: | Size: 32 KiB |
BIN
sbapp/kivymd/images/rec_st_shadow-2.png
Normal file
After Width: | Height: | Size: 28 KiB |
1
sbapp/kivymd/images/rec_st_shadow.atlas
Normal file
@ -0,0 +1 @@
|
||||
{"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]}}
|
BIN
sbapp/kivymd/images/round_shadow-0.png
Normal file
After Width: | Height: | Size: 39 KiB |
BIN
sbapp/kivymd/images/round_shadow-1.png
Normal file
After Width: | Height: | Size: 40 KiB |
BIN
sbapp/kivymd/images/round_shadow-2.png
Normal file
After Width: | Height: | Size: 26 KiB |
1
sbapp/kivymd/images/round_shadow.atlas
Normal file
@ -0,0 +1 @@
|
||||
{"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,15 +35,8 @@ assert "Icons" in LabelBase._fonts.keys() # NOQA
|
||||
|
||||
images = os.listdir(kivymd.images_path)
|
||||
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 "transparent.png" in images
|
||||
assert "rec_shadow.atlas" in images
|
||||
"""
|
||||
)
|
||||
pyi_main.run(
|
||||
|
@ -1,13 +1,14 @@
|
||||
def test_create_project():
|
||||
import os
|
||||
import sys
|
||||
|
||||
os.system(
|
||||
f"python3.10 -m kivymd.tools.patterns.create_project "
|
||||
f"{sys.executable} -m kivymd.tools.patterns.create_project "
|
||||
f"MVC "
|
||||
f"{os.path.expanduser('~')} "
|
||||
f"TestProject "
|
||||
f"python3.10 "
|
||||
f"stable "
|
||||
f"{sys.executable} "
|
||||
f"master "
|
||||
f"--name_screen TestProjectScreen "
|
||||
f"--name_database restdb "
|
||||
f"--use_hotreload yes"
|
||||
|
@ -212,8 +212,9 @@ respects, the theming stays as documented.
|
||||
dictionary :attr:`kivymd.color_definition.colors`.
|
||||
"""
|
||||
|
||||
from kivy.animation import Animation
|
||||
|
||||
from kivy.app import App
|
||||
from kivy.atlas import Atlas
|
||||
from kivy.clock import Clock
|
||||
from kivy.core.window import Window
|
||||
from kivy.event import EventDispatcher
|
||||
@ -223,13 +224,13 @@ from kivy.properties import (
|
||||
BooleanProperty,
|
||||
ColorProperty,
|
||||
DictProperty,
|
||||
NumericProperty,
|
||||
ObjectProperty,
|
||||
OptionProperty,
|
||||
StringProperty,
|
||||
)
|
||||
from kivy.utils import get_color_from_hex
|
||||
|
||||
from kivymd import images_path
|
||||
from kivymd.color_definitions import colors, hue, palette
|
||||
from kivymd.font_definitions import theme_font_styles
|
||||
from kivymd.material_resources import DEVICE_IOS, DEVICE_TYPE
|
||||
@ -623,152 +624,6 @@ class ThemeManager(EventDispatcher):
|
||||
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"])
|
||||
"""
|
||||
App theme style.
|
||||
@ -1329,22 +1184,14 @@ class ThemeManager(EventDispatcher):
|
||||
):
|
||||
self.set_clearcolor_by_theme_style(theme_style)
|
||||
|
||||
_set_clearcolor = False
|
||||
set_clearcolor = BooleanProperty(True)
|
||||
|
||||
def set_clearcolor_by_theme_style(self, theme_style):
|
||||
if self.theme_style_switch_animation and self._set_clearcolor:
|
||||
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(
|
||||
self.colors[theme_style]["Background"]
|
||||
)
|
||||
self._set_clearcolor = True
|
||||
if not self.set_clearcolor:
|
||||
return
|
||||
Window.clearcolor = get_color_from_hex(
|
||||
self.colors[theme_style]["Background"]
|
||||
)
|
||||
|
||||
# Font name, size (sp), always caps, letter spacing (sp).
|
||||
font_styles = DictProperty(
|
||||
@ -1551,6 +1398,10 @@ class ThemeManager(EventDispatcher):
|
||||
|
||||
def __init__(self, **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))
|
||||
self._determine_device_orientation(None, Window.size)
|
||||
Window.bind(size=self._determine_device_orientation)
|
||||
@ -1636,16 +1487,6 @@ class ThemableBehavior(EventDispatcher):
|
||||
"""
|
||||
|
||||
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:
|
||||
pass
|
||||
else:
|
||||
@ -1666,24 +1507,3 @@ class ThemableBehavior(EventDispatcher):
|
||||
)
|
||||
self.theme_cls = App.get_running_app().theme_cls
|
||||
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,18 +13,6 @@ from pathlib import Path
|
||||
import kivymd
|
||||
|
||||
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.
|
||||
(
|
||||
kivymd.fonts_path,
|
||||
|
@ -35,8 +35,8 @@
|
||||
if not root.front_layer_color \
|
||||
else root.front_layer_color
|
||||
radius:
|
||||
[root.radius_left, root.radius_right,
|
||||
0, 0]
|
||||
[root.radius_left, root.radius_left,
|
||||
root.radius_right, root.radius_right]
|
||||
|
||||
OneLineListItem:
|
||||
id: header_button
|
||||
|
@ -202,6 +202,7 @@ from kivy.uix.boxlayout import BoxLayout
|
||||
|
||||
from kivymd import uix_path
|
||||
from kivymd.theming import ThemableBehavior
|
||||
from kivymd.uix.behaviors import FakeRectangularElevationBehavior
|
||||
from kivymd.uix.boxlayout import MDBoxLayout
|
||||
from kivymd.uix.card import MDCard
|
||||
from kivymd.uix.floatlayout import MDFloatLayout
|
||||
@ -527,5 +528,5 @@ class _BackLayer(BoxLayout):
|
||||
pass
|
||||
|
||||
|
||||
class _FrontLayer(MDCard):
|
||||
class _FrontLayer(MDCard, FakeRectangularElevationBehavior):
|
||||
pass
|
||||
|
@ -35,7 +35,7 @@ Usage
|
||||
MDTopAppBar:
|
||||
id: toolbar
|
||||
title: "Example Banners"
|
||||
elevation: 4
|
||||
elevation: 10
|
||||
pos_hint: {'top': 1}
|
||||
|
||||
MDBoxLayout:
|
||||
@ -157,6 +157,7 @@ from kivy.properties import (
|
||||
from kivy.uix.widget import Widget
|
||||
|
||||
from kivymd import uix_path
|
||||
from kivymd.uix.behaviors import FakeRectangularElevationBehavior
|
||||
from kivymd.uix.boxlayout import MDBoxLayout
|
||||
from kivymd.uix.button import MDFlatButton
|
||||
from kivymd.uix.card import MDCard
|
||||
@ -176,7 +177,7 @@ with open(
|
||||
Builder.load_string(kv_file.read())
|
||||
|
||||
|
||||
class MDBanner(MDCard):
|
||||
class MDBanner(MDCard, FakeRectangularElevationBehavior):
|
||||
vertical_pad = NumericProperty(dp(68))
|
||||
"""
|
||||
Indent the banner at the top of the screen.
|
||||
|
@ -11,20 +11,18 @@ from .backgroundcolor_behavior import (
|
||||
)
|
||||
|
||||
# flake8: NOQA
|
||||
from .declarative_behavior import DeclarativeBehavior
|
||||
from .declarative_bahavior import DeclarativeBehavior
|
||||
from .elevation import (
|
||||
CircularElevationBehavior,
|
||||
CommonElevationBehavior,
|
||||
FakeCircularElevationBehavior,
|
||||
FakeRectangularElevationBehavior,
|
||||
ObservableShadow,
|
||||
RectangularElevationBehavior,
|
||||
RoundedRectangularElevationBehavior,
|
||||
)
|
||||
from .magic_behavior import MagicBehavior
|
||||
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 .hover_behavior import HoverBehavior # isort:skip
|
||||
|
@ -7,9 +7,8 @@ Behaviors/Background Color
|
||||
|
||||
__all__ = ("BackgroundColorBehavior", "SpecificBackgroundColorBehavior")
|
||||
|
||||
from typing import List, Union
|
||||
from typing import List
|
||||
|
||||
from kivy.animation import Animation
|
||||
from kivy.lang import Builder
|
||||
from kivy.properties import (
|
||||
ColorProperty,
|
||||
@ -25,6 +24,8 @@ from kivy.utils import get_color_from_hex
|
||||
from kivymd.color_definitions import hue, palette, text_colors
|
||||
from kivymd.theming import ThemeManager
|
||||
|
||||
from .elevation import CommonElevationBehavior
|
||||
|
||||
Builder.load_string(
|
||||
"""
|
||||
#:import RelativeLayout kivy.uix.relativelayout.RelativeLayout
|
||||
@ -37,7 +38,7 @@ Builder.load_string(
|
||||
angle: self.angle
|
||||
origin: self._background_origin
|
||||
Color:
|
||||
rgba: self._md_bg_color
|
||||
rgba: self.md_bg_color
|
||||
RoundedRectangle:
|
||||
group: "Background_instruction"
|
||||
size: self.size
|
||||
@ -66,7 +67,7 @@ Builder.load_string(
|
||||
)
|
||||
|
||||
|
||||
class BackgroundColorBehavior:
|
||||
class BackgroundColorBehavior(CommonElevationBehavior):
|
||||
background = StringProperty()
|
||||
"""
|
||||
Background image path.
|
||||
@ -152,26 +153,15 @@ class BackgroundColorBehavior:
|
||||
|
||||
_background_x = NumericProperty(0)
|
||||
_background_y = NumericProperty(0)
|
||||
_background_origin = ReferenceListProperty(_background_x, _background_y)
|
||||
_md_bg_color = ColorProperty([0, 0, 0, 0])
|
||||
_background_origin = ReferenceListProperty(
|
||||
_background_x,
|
||||
_background_y,
|
||||
)
|
||||
|
||||
def __init__(self, **kwarg):
|
||||
super().__init__(**kwarg)
|
||||
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(
|
||||
self, instance_md_widget, pos: List[float]
|
||||
) -> None:
|
||||
@ -216,14 +206,12 @@ class SpecificBackgroundColorBehavior(BackgroundColorBehavior):
|
||||
super().__init__(**kwargs)
|
||||
if hasattr(self, "theme_cls"):
|
||||
self.theme_cls.bind(
|
||||
primary_palette=self._update_specific_text_color,
|
||||
accent_palette=self._update_specific_text_color,
|
||||
theme_style=self._update_specific_text_color,
|
||||
primary_palette=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)
|
||||
|
||||
def _update_specific_text_color(
|
||||
@ -246,17 +234,5 @@ class SpecificBackgroundColorBehavior(BackgroundColorBehavior):
|
||||
secondary_color[3] = 0.54
|
||||
else:
|
||||
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_secondary_text_color = secondary_color
|
||||
self.specific_text_color = color
|
||||
self.specific_secondary_text_color = secondary_color
|
||||
|
@ -111,7 +111,7 @@ from kivy.properties import (
|
||||
from kivy.uix.behaviors import ToggleButtonBehavior
|
||||
|
||||
|
||||
class CommonRipple:
|
||||
class CommonRipple(object):
|
||||
"""Base class for ripple effect."""
|
||||
|
||||
ripple_rad_default = NumericProperty(1)
|
||||
|
@ -1,133 +0,0 @@
|
||||
"""
|
||||
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)`.
|
||||
"""
|
@ -1,156 +0,0 @@
|
||||
"""
|
||||
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`.
|
||||
"""
|
@ -1,134 +0,0 @@
|
||||
"""
|
||||
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,104 +14,61 @@ example:
|
||||
pass
|
||||
|
||||
|
||||
.. tabs::
|
||||
.. code-block:: python
|
||||
|
||||
.. tab:: Declarative KV style
|
||||
from kivy.lang import Builder
|
||||
|
||||
.. code-block:: python
|
||||
from kivymd.app import MDApp
|
||||
from kivymd.uix.behaviors.toggle_behavior import MDToggleButton
|
||||
from kivymd.uix.button import MDRectangleFlatButton
|
||||
|
||||
from kivy.lang import Builder
|
||||
KV = '''
|
||||
Screen:
|
||||
|
||||
from kivymd.app import MDApp
|
||||
from kivymd.uix.behaviors.toggle_behavior import MDToggleButton
|
||||
from kivymd.uix.button import MDFlatButton
|
||||
MDBoxLayout:
|
||||
adaptive_size: True
|
||||
pos_hint: {"center_x": .5, "center_y": .5}
|
||||
|
||||
KV = '''
|
||||
MDScreen:
|
||||
MyToggleButton:
|
||||
text: "Show ads"
|
||||
group: "x"
|
||||
|
||||
MDBoxLayout:
|
||||
adaptive_size: True
|
||||
spacing: "12dp"
|
||||
pos_hint: {"center_x": .5, "center_y": .5}
|
||||
MyToggleButton:
|
||||
text: "Do not show ads"
|
||||
group: "x"
|
||||
|
||||
MyToggleButton:
|
||||
text: "Show ads"
|
||||
group: "x"
|
||||
|
||||
MyToggleButton:
|
||||
text: "Do not show ads"
|
||||
group: "x"
|
||||
|
||||
MyToggleButton:
|
||||
text: "Does not matter"
|
||||
group: "x"
|
||||
'''
|
||||
MyToggleButton:
|
||||
text: "Does not matter"
|
||||
group: "x"
|
||||
'''
|
||||
|
||||
|
||||
class MyToggleButton(MDFlatButton, MDToggleButton):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.background_down = self.theme_cls.primary_color
|
||||
class MyToggleButton(MDRectangleFlatButton, MDToggleButton):
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
self.background_down = self.theme_cls.primary_light
|
||||
|
||||
|
||||
class Test(MDApp):
|
||||
def build(self):
|
||||
self.theme_cls.theme_style = "Dark"
|
||||
self.theme_cls.primary_palette = "Orange"
|
||||
return Builder.load_string(KV)
|
||||
class Test(MDApp):
|
||||
def build(self):
|
||||
return Builder.load_string(KV)
|
||||
|
||||
|
||||
Test().run()
|
||||
|
||||
.. tab:: Declarative python style
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from kivymd.app import MDApp
|
||||
from kivymd.uix.behaviors.toggle_behavior import MDToggleButton
|
||||
from kivymd.uix.boxlayout import MDBoxLayout
|
||||
from kivymd.uix.button import MDFlatButton
|
||||
from kivymd.uix.screen import MDScreen
|
||||
|
||||
|
||||
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()
|
||||
Test().run()
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/toggle-button-1.gif
|
||||
:align: center
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
class MyToggleButton(MDFillRoundFlatButton, MDToggleButton):
|
||||
def __init__(self, **kwargs):
|
||||
self.background_down = MDApp.get_running_app().theme_cls.primary_dark
|
||||
super().__init__(**kwargs)
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/toggle-button-2.gif
|
||||
:align: center
|
||||
|
||||
You can inherit the ``MyToggleButton`` class only from the following classes
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
@ -131,7 +88,6 @@ from kivy.properties import BooleanProperty, ColorProperty
|
||||
from kivy.uix.behaviors import ToggleButtonBehavior
|
||||
|
||||
from kivymd.uix.button import (
|
||||
ButtonContentsIconText,
|
||||
MDFillRoundFlatButton,
|
||||
MDFillRoundFlatIconButton,
|
||||
MDFlatButton,
|
||||
@ -193,8 +149,7 @@ class MDToggleButton(ToggleButtonBehavior):
|
||||
# Do the object inherited from the "supported" buttons?
|
||||
if not issubclass(self.__class__, classinfo):
|
||||
raise ValueError(
|
||||
f"Class {self.__class__} must be inherited from one of the "
|
||||
f"classes in the list {classinfo}"
|
||||
f"Class {self.__class__} must be inherited from one of the classes in the list {classinfo}"
|
||||
)
|
||||
if (
|
||||
not self.background_normal
|
||||
@ -210,12 +165,10 @@ class MDToggleButton(ToggleButtonBehavior):
|
||||
):
|
||||
self.__is_filled = True
|
||||
self.background_normal = self.theme_cls.primary_color
|
||||
# If not background_normal must be the same as the inherited one.
|
||||
# If not the background_normal must be the same as the inherited one:
|
||||
else:
|
||||
self.background_normal = (
|
||||
self.md_bg_color[:] if self.md_bg_color else (0, 0, 0, 0)
|
||||
)
|
||||
# If no background_down is setter.
|
||||
self.background_normal = self.md_bg_color[:]
|
||||
# If no background_down is setted:
|
||||
if (
|
||||
not self.background_down
|
||||
): # This means that if the value == [] or None will return True.
|
||||
@ -247,6 +200,3 @@ class MDToggleButton(ToggleButtonBehavior):
|
||||
): # If the background is transparent, the font color must be the
|
||||
# primary color.
|
||||
self.text_color = self.font_color_normal
|
||||
|
||||
if issubclass(self.__class__, ButtonContentsIconText):
|
||||
self.icon_color = self.text_color
|
||||
|
@ -1,3 +1,4 @@
|
||||
#:import sm kivy.uix.screenmanager
|
||||
#:import STANDARD_INCREMENT kivymd.material_resources.STANDARD_INCREMENT
|
||||
|
||||
|
||||
@ -6,9 +7,9 @@
|
||||
height:
|
||||
STANDARD_INCREMENT if app.theme_cls.material_style == "M2" else "80dp"
|
||||
|
||||
ScreenManager:
|
||||
MDScreenManager:
|
||||
id: tab_manager
|
||||
transition: root.transition(duration=root.transition_duration)
|
||||
transition: sm.FadeTransition(duration=.2)
|
||||
on_current:
|
||||
root.dispatch( \
|
||||
"on_switch_tabs", \
|
||||
@ -95,7 +96,7 @@
|
||||
radius: [16,]
|
||||
size: root._selected_region_width, dp(32)
|
||||
pos:
|
||||
self.center_x - root._selected_region_width / 2, \
|
||||
self.center_x - self.width - dp(8), \
|
||||
self.center_y - (dp(16))
|
||||
|
||||
MDLabel:
|
||||
|
@ -62,120 +62,59 @@ For ease of understanding, this code works like this:
|
||||
Example
|
||||
-------
|
||||
|
||||
.. tabs::
|
||||
.. code-block:: python
|
||||
|
||||
.. tab:: Declarative KV style
|
||||
from kivy.lang import Builder
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from kivy.lang import Builder
|
||||
|
||||
from kivymd.app import MDApp
|
||||
from kivymd.app import MDApp
|
||||
|
||||
|
||||
class Test(MDApp):
|
||||
class Test(MDApp):
|
||||
|
||||
def build(self):
|
||||
self.theme_cls.material_style = "M3"
|
||||
self.theme_cls.theme_style = "Dark"
|
||||
return Builder.load_string(
|
||||
'''
|
||||
MDScreen:
|
||||
def build(self):
|
||||
self.theme_cls.material_style = "M3"
|
||||
return Builder.load_string(
|
||||
'''
|
||||
MDScreen:
|
||||
|
||||
MDBottomNavigation:
|
||||
#panel_color: "#eeeaea"
|
||||
selected_color_background: "orange"
|
||||
text_color_active: "lightgrey"
|
||||
MDBottomNavigation:
|
||||
panel_color: "#eeeaea"
|
||||
selected_color_background: "#97ecf8"
|
||||
text_color_active: 0, 0, 0, 1
|
||||
|
||||
MDBottomNavigationItem:
|
||||
name: 'screen 1'
|
||||
text: 'Mail'
|
||||
icon: 'gmail'
|
||||
badge_icon: "numeric-10"
|
||||
MDBottomNavigationItem:
|
||||
name: 'screen 1'
|
||||
text: 'Mail'
|
||||
icon: 'gmail'
|
||||
badge_icon: "numeric-10"
|
||||
|
||||
MDLabel:
|
||||
text: 'Mail'
|
||||
halign: 'center'
|
||||
MDLabel:
|
||||
text: 'Mail'
|
||||
halign: 'center'
|
||||
|
||||
MDBottomNavigationItem:
|
||||
name: 'screen 2'
|
||||
text: 'Twitter'
|
||||
icon: 'twitter'
|
||||
badge_icon: "numeric-5"
|
||||
MDBottomNavigationItem:
|
||||
name: 'screen 2'
|
||||
text: 'Discord'
|
||||
icon: 'discord'
|
||||
badge_icon: "numeric-5"
|
||||
|
||||
MDLabel:
|
||||
text: 'Twitter'
|
||||
halign: 'center'
|
||||
MDLabel:
|
||||
text: 'Discord'
|
||||
halign: 'center'
|
||||
|
||||
MDBottomNavigationItem:
|
||||
name: 'screen 3'
|
||||
text: 'LinkedIN'
|
||||
icon: 'linkedin'
|
||||
MDBottomNavigationItem:
|
||||
name: 'screen 3'
|
||||
text: 'LinkedIN'
|
||||
icon: 'linkedin'
|
||||
|
||||
MDLabel:
|
||||
text: 'LinkedIN'
|
||||
halign: 'center'
|
||||
'''
|
||||
)
|
||||
MDLabel:
|
||||
text: 'LinkedIN'
|
||||
halign: 'center'
|
||||
'''
|
||||
)
|
||||
|
||||
|
||||
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()
|
||||
Test().run()
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/bottom-navigation.gif
|
||||
:align: center
|
||||
@ -253,13 +192,16 @@ from kivy.properties import (
|
||||
)
|
||||
from kivy.uix.behaviors import ButtonBehavior
|
||||
from kivy.uix.boxlayout import BoxLayout
|
||||
from kivy.uix.screenmanager import FadeTransition, ScreenManagerException
|
||||
from kivy.uix.screenmanager import ScreenManagerException
|
||||
|
||||
from kivymd import uix_path
|
||||
from kivymd.material_resources import STANDARD_INCREMENT
|
||||
from kivymd.theming import ThemableBehavior, ThemeManager
|
||||
from kivymd.uix.anchorlayout import MDAnchorLayout
|
||||
from kivymd.uix.behaviors import CommonElevationBehavior, DeclarativeBehavior
|
||||
from kivymd.uix.behaviors import (
|
||||
DeclarativeBehavior,
|
||||
FakeRectangularElevationBehavior,
|
||||
)
|
||||
from kivymd.uix.behaviors.backgroundcolor_behavior import (
|
||||
SpecificBackgroundColorBehavior,
|
||||
)
|
||||
@ -471,28 +413,6 @@ class MDBottomNavigationItem(MDTab):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
def animate_header(
|
||||
self, bottom_navigation_object, bottom_navigation_header_object
|
||||
) -> None:
|
||||
if bottom_navigation_object.use_text:
|
||||
Animation(_label_font_size=sp(12), d=0.1).start(
|
||||
bottom_navigation_object.previous_tab.header
|
||||
)
|
||||
Animation(
|
||||
_selected_region_width=0,
|
||||
t="in_out_sine",
|
||||
d=0,
|
||||
).start(bottom_navigation_header_object)
|
||||
Animation(
|
||||
_text_color_normal=bottom_navigation_header_object.text_color_normal
|
||||
if bottom_navigation_object.previous_tab.header.text_color_normal
|
||||
!= [1, 1, 1, 1]
|
||||
else self.theme_cls.disabled_hint_text_color,
|
||||
d=0.1,
|
||||
).start(bottom_navigation_object.previous_tab.header)
|
||||
bottom_navigation_object.previous_tab.header.active = False
|
||||
self.header.active = True
|
||||
|
||||
def on_tab_press(self, *args) -> None:
|
||||
"""Called when clicking on a panel item."""
|
||||
|
||||
@ -500,13 +420,28 @@ class MDBottomNavigationItem(MDTab):
|
||||
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:
|
||||
self.animate_header(
|
||||
bottom_navigation_object, bottom_navigation_header_object
|
||||
)
|
||||
|
||||
super().on_tab_press(*args)
|
||||
if bottom_navigation_object.use_text:
|
||||
Animation(_label_font_size=sp(12), d=0.1).start(
|
||||
bottom_navigation_object.previous_tab.header
|
||||
)
|
||||
Animation(
|
||||
_selected_region_width=0,
|
||||
t="in_out_sine",
|
||||
d=0,
|
||||
).start(bottom_navigation_header_object)
|
||||
Animation(
|
||||
_text_color_normal=bottom_navigation_header_object.text_color_normal
|
||||
if bottom_navigation_object.previous_tab.header.text_color_normal
|
||||
!= [1, 1, 1, 1]
|
||||
else self.theme_cls.disabled_hint_text_color,
|
||||
d=0.1,
|
||||
).start(bottom_navigation_object.previous_tab.header)
|
||||
bottom_navigation_object.previous_tab.header.active = False
|
||||
self.header.active = True
|
||||
bottom_navigation_object.previous_tab = self
|
||||
|
||||
def on_disabled(
|
||||
self, instance_bottom_navigation_item, disabled_value: bool
|
||||
@ -563,26 +498,6 @@ class MDBottomNavigation(DeclarativeBehavior, TabbedPanelBase):
|
||||
.. 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 of the label when it is not selected.
|
||||
@ -857,6 +772,8 @@ class MDBottomNavigation(DeclarativeBehavior, TabbedPanelBase):
|
||||
|
||||
|
||||
class MDBottomNavigationBar(
|
||||
ThemableBehavior, CommonElevationBehavior, MDFloatLayout
|
||||
ThemableBehavior,
|
||||
FakeRectangularElevationBehavior,
|
||||
MDFloatLayout,
|
||||
):
|
||||
pass
|
||||
|
@ -34,7 +34,7 @@ Usage :class:`~MDListBottomSheet`
|
||||
MDTopAppBar:
|
||||
title: "Example BottomSheet"
|
||||
pos_hint: {"top": 1}
|
||||
elevation: 4
|
||||
elevation: 10
|
||||
|
||||
MDRaisedButton:
|
||||
text: "Open list bottom sheet"
|
||||
@ -94,7 +94,7 @@ which will be used as an icon to the left of the item:
|
||||
MDTopAppBar:
|
||||
title: 'Example BottomSheet'
|
||||
pos_hint: {"top": 1}
|
||||
elevation: 4
|
||||
elevation: 10
|
||||
|
||||
MDRaisedButton:
|
||||
text: "Open grid bottom sheet"
|
||||
@ -180,7 +180,7 @@ which will be used as an icon to the left of the item:
|
||||
MDTopAppBar:
|
||||
title: 'Example BottomSheet'
|
||||
pos_hint: {"top": 1}
|
||||
elevation: 4
|
||||
elevation: 10
|
||||
|
||||
MDRaisedButton:
|
||||
text: "Open custom bottom sheet"
|
||||
|
@ -93,8 +93,6 @@ from kivymd.uix.behaviors import DeclarativeBehavior
|
||||
|
||||
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.
|
||||
"""
|
||||
|
@ -1,7 +1,6 @@
|
||||
# NOQA F401
|
||||
from .button import (
|
||||
BaseButton,
|
||||
ButtonContentsIconText,
|
||||
MDFillRoundFlatButton,
|
||||
MDFillRoundFlatIconButton,
|
||||
MDFlatButton,
|
||||
|
@ -3,9 +3,9 @@
|
||||
Clear
|
||||
Color:
|
||||
rgba:
|
||||
self._md_bg_color \
|
||||
(self._md_bg_color or [0.0, 0.0, 0.0, 0.0]) \
|
||||
if not self.disabled else \
|
||||
self._md_bg_color_disabled
|
||||
(self._md_bg_color_disabled or [0.0, 0.0, 0.0, 0.0])
|
||||
RoundedRectangle:
|
||||
size: self.size
|
||||
pos: self.pos
|
||||
@ -13,17 +13,19 @@
|
||||
radius: [root._radius, ]
|
||||
Color:
|
||||
rgba:
|
||||
root._line_color \
|
||||
root._line_color or [0.0, 0.0, 0.0, 0.0] \
|
||||
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:
|
||||
width: root.line_width
|
||||
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, \
|
||||
self.height \
|
||||
)
|
||||
self.height)
|
||||
|
||||
size_hint: None, None
|
||||
anchor_x: root.halign
|
||||
@ -31,28 +33,21 @@
|
||||
_round_rad: [self._radius] * 4
|
||||
|
||||
|
||||
|
||||
<ButtonContentsText>
|
||||
lbl_txt: lbl_txt
|
||||
width:
|
||||
max( \
|
||||
root._min_width, \
|
||||
root.padding[0] + lbl_txt.texture_size[0] + root.padding[2] \
|
||||
)
|
||||
max(root._min_width, \
|
||||
root.padding[0] + lbl_txt.texture_size[0] + root.padding[2])
|
||||
size_hint_min_x:
|
||||
max( \
|
||||
root._min_width, \
|
||||
root.padding[0] + lbl_txt.texture_size[0] + root.padding[2] \
|
||||
)
|
||||
max(root._min_width, \
|
||||
root.padding[0] + lbl_txt.texture_size[0] + root.padding[2])
|
||||
height:
|
||||
max( \
|
||||
root._min_height, \
|
||||
root.padding[1] + lbl_txt.texture_size[1] + root.padding[3] \
|
||||
)
|
||||
max(root._min_height, \
|
||||
root.padding[1] + lbl_txt.texture_size[1] + root.padding[3])
|
||||
size_hint_min_y:
|
||||
max( \
|
||||
root._min_height, \
|
||||
root.padding[1] + lbl_txt.texture_size[1] + root.padding[3] \
|
||||
)
|
||||
max(root._min_height, \
|
||||
root.padding[1] + lbl_txt.texture_size[1] + root.padding[3])
|
||||
|
||||
MDLabel:
|
||||
id: lbl_txt
|
||||
@ -89,10 +84,7 @@
|
||||
# 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) \
|
||||
if not root.disabled else \
|
||||
root.theme_cls.disabled_hint_text_color \
|
||||
if not root.disabled_color else \
|
||||
root.disabled_color
|
||||
|
||||
root.theme_cls.disabled_hint_text_color
|
||||
on_icon:
|
||||
if self.icon not in md_icons.keys(): self.size_hint = (1, 1)
|
||||
theme_text_color: root._theme_icon_color
|
||||
@ -139,7 +131,7 @@
|
||||
id: box
|
||||
adaptive_size: True
|
||||
padding: 0
|
||||
spacing: "8dp"
|
||||
spacing: "4dp"
|
||||
|
||||
MDIcon:
|
||||
id: lbl_ic
|
||||
@ -201,21 +193,48 @@
|
||||
radius: [self.height / 2]
|
||||
|
||||
|
||||
<MDFloatingRootButton>
|
||||
<BaseFloatingRootButton>
|
||||
theme_text_color: "Custom"
|
||||
md_bg_color: self.theme_cls.primary_color
|
||||
|
||||
|
||||
<MDFloatingLabel>
|
||||
padding_x: "8dp"
|
||||
padding_y: "8dp"
|
||||
adaptive_size: True
|
||||
theme_text_color: "Custom"
|
||||
|
||||
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:
|
||||
rgba: self.bg_color
|
||||
rgba:
|
||||
self.theme_cls.primary_color \
|
||||
if not root.bg_color else \
|
||||
root.bg_color
|
||||
RoundedRectangle:
|
||||
size: self.size
|
||||
pos: self.pos
|
||||
radius: self.radius
|
||||
size: self.size
|
||||
radius: [5]
|
||||
|
||||
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,6 +2,17 @@
|
||||
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>
|
||||
md_bg_color:
|
||||
self.theme_cls.divider_color \
|
||||
|
@ -26,6 +26,26 @@ Components/Card
|
||||
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
|
||||
------------------------------------------------------------------------------------
|
||||
|
||||
@ -39,6 +59,7 @@ An example of the implementation of a card in the style of material design versi
|
||||
from kivy.properties import StringProperty
|
||||
|
||||
from kivymd.app import MDApp
|
||||
from kivymd.uix.behaviors import RoundedRectangularElevationBehavior
|
||||
from kivymd.uix.card import MDCard
|
||||
|
||||
KV = '''
|
||||
@ -72,7 +93,7 @@ An example of the implementation of a card in the style of material design versi
|
||||
'''
|
||||
|
||||
|
||||
class MD3Card(MDCard):
|
||||
class MD3Card(MDCard, RoundedRectangularElevationBehavior):
|
||||
'''Implements a material design v3 card.'''
|
||||
|
||||
text = StringProperty()
|
||||
@ -105,6 +126,7 @@ An example of the implementation of a card in the style of material design versi
|
||||
.. code-block:: python
|
||||
|
||||
from kivymd.app import MDApp
|
||||
from kivymd.uix.behaviors import RoundedRectangularElevationBehavior
|
||||
from kivymd.uix.boxlayout import MDBoxLayout
|
||||
from kivymd.uix.button import MDIconButton
|
||||
from kivymd.uix.card import MDCard
|
||||
@ -113,7 +135,7 @@ An example of the implementation of a card in the style of material design versi
|
||||
from kivymd.uix.screen import MDScreen
|
||||
|
||||
|
||||
class MD3Card(MDCard):
|
||||
class MD3Card(MDCard, RoundedRectangularElevationBehavior):
|
||||
'''Implements a material design v3 card.'''
|
||||
|
||||
|
||||
@ -148,6 +170,7 @@ An example of the implementation of a card in the style of material design versi
|
||||
adaptive_size=True,
|
||||
color="grey",
|
||||
pos=("12dp", "12dp"),
|
||||
bold=True,
|
||||
),
|
||||
),
|
||||
line_color=(0.2, 0.2, 0.2, 0.8),
|
||||
@ -232,9 +255,10 @@ End full code
|
||||
|
||||
MDBoxLayout:
|
||||
orientation: "vertical"
|
||||
spacing: "10dp"
|
||||
|
||||
MDTopAppBar:
|
||||
elevation: 4
|
||||
elevation: 10
|
||||
title: "MDCardSwipe"
|
||||
|
||||
MDScrollView:
|
||||
@ -262,7 +286,7 @@ End full code
|
||||
'''Creates a list of cards.'''
|
||||
|
||||
for i in range(20):
|
||||
self.root.ids.md_list.add_widget(
|
||||
self.screen.ids.md_list.add_widget(
|
||||
SwipeToDeleteItem(text=f"One-line item {i}")
|
||||
)
|
||||
|
||||
@ -292,7 +316,7 @@ End full code
|
||||
MDScreen(
|
||||
MDBoxLayout(
|
||||
MDTopAppBar(
|
||||
elevation=4,
|
||||
elevation=10,
|
||||
title="MDCardSwipe",
|
||||
),
|
||||
MDScrollView(
|
||||
@ -304,6 +328,7 @@ End full code
|
||||
),
|
||||
id="box",
|
||||
orientation="vertical",
|
||||
spacing="10dp",
|
||||
),
|
||||
)
|
||||
)
|
||||
@ -401,7 +426,7 @@ You can use this event to remove items from a list:
|
||||
.. code-block:: python
|
||||
|
||||
def on_swipe_complete(self, instance):
|
||||
self.root.ids.md_list.remove_widget(instance)
|
||||
self.screen.ids.md_list.remove_widget(instance)
|
||||
|
||||
.. tab:: Decralative python styles
|
||||
|
||||
@ -471,9 +496,10 @@ End full code
|
||||
|
||||
MDBoxLayout:
|
||||
orientation: "vertical"
|
||||
spacing: "10dp"
|
||||
|
||||
MDTopAppBar:
|
||||
elevation: 4
|
||||
elevation: 10
|
||||
title: "MDCardSwipe"
|
||||
|
||||
MDScrollView:
|
||||
@ -534,7 +560,7 @@ End full code
|
||||
MDScreen(
|
||||
MDBoxLayout(
|
||||
MDTopAppBar(
|
||||
elevation=4,
|
||||
elevation=10,
|
||||
title="MDCardSwipe",
|
||||
),
|
||||
MDScrollView(
|
||||
@ -546,6 +572,7 @@ End full code
|
||||
),
|
||||
id="box",
|
||||
orientation="vertical",
|
||||
spacing="10dp",
|
||||
),
|
||||
)
|
||||
)
|
||||
@ -603,21 +630,26 @@ Focus behavior
|
||||
from kivy.lang import Builder
|
||||
|
||||
from kivymd.app import MDApp
|
||||
from kivymd.uix.behaviors import FakeRectangularElevationBehavior
|
||||
from kivymd.uix.card import MDCard
|
||||
|
||||
KV = '''
|
||||
MDScreen:
|
||||
|
||||
MDCard:
|
||||
ElevationCard:
|
||||
size_hint: .7, .4
|
||||
focus_behavior: True
|
||||
pos_hint: {"center_x": .5, "center_y": .5}
|
||||
md_bg_color: "darkgrey"
|
||||
unfocus_color: "darkgrey"
|
||||
focus_color: "grey"
|
||||
elevation: 6
|
||||
'''
|
||||
|
||||
|
||||
class ElevationCard(MDCard, FakeRectangularElevationBehavior):
|
||||
pass
|
||||
|
||||
|
||||
class Example(MDApp):
|
||||
def build(self):
|
||||
self.theme_cls.theme_style = "Dark"
|
||||
@ -631,23 +663,27 @@ Focus behavior
|
||||
.. code-block:: python
|
||||
|
||||
from kivymd.app import MDApp
|
||||
from kivymd.uix.behaviors import FakeRectangularElevationBehavior
|
||||
from kivymd.uix.card import MDCard
|
||||
from kivymd.uix.screen import MDScreen
|
||||
|
||||
|
||||
class ElevationCard(MDCard, FakeRectangularElevationBehavior):
|
||||
pass
|
||||
|
||||
|
||||
class Example(MDApp):
|
||||
def build(self):
|
||||
self.theme_cls.theme_style = "Dark"
|
||||
return (
|
||||
MDScreen(
|
||||
MDCard(
|
||||
ElevationCard(
|
||||
size_hint=(0.7, 0.4),
|
||||
focus_behavior=True,
|
||||
pos_hint={"center_x": 0.5, "center_y": 0.5},
|
||||
md_bg_color="darkgrey",
|
||||
unfocus_color="darkgrey",
|
||||
focus_color="grey",
|
||||
elevation=6,
|
||||
),
|
||||
)
|
||||
)
|
||||
@ -655,6 +691,7 @@ Focus behavior
|
||||
|
||||
Example().run()
|
||||
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/card-focus.gif
|
||||
:align: center
|
||||
|
||||
@ -695,14 +732,12 @@ from kivy.properties import (
|
||||
VariableListProperty,
|
||||
)
|
||||
from kivy.uix.boxlayout import BoxLayout
|
||||
from kivy.utils import get_color_from_hex
|
||||
|
||||
from kivymd import uix_path
|
||||
from kivymd.color_definitions import colors
|
||||
from kivymd.theming import ThemableBehavior
|
||||
from kivymd.uix.behaviors import (
|
||||
BackgroundColorBehavior,
|
||||
CommonElevationBehavior,
|
||||
DeclarativeBehavior,
|
||||
RectangularRippleBehavior,
|
||||
)
|
||||
@ -746,7 +781,6 @@ class MDCard(
|
||||
ThemableBehavior,
|
||||
BackgroundColorBehavior,
|
||||
RectangularRippleBehavior,
|
||||
CommonElevationBehavior,
|
||||
FocusBehavior,
|
||||
BoxLayout,
|
||||
):
|
||||
@ -766,6 +800,14 @@ class MDCard(
|
||||
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)])
|
||||
"""
|
||||
Card radius by default.
|
||||
@ -789,16 +831,15 @@ class MDCard(
|
||||
"""
|
||||
|
||||
_bg_color_map = (
|
||||
get_color_from_hex(colors["Light"]["CardsDialogs"]),
|
||||
get_color_from_hex(colors["Dark"]["CardsDialogs"]),
|
||||
colors["Light"]["CardsDialogs"],
|
||||
colors["Dark"]["CardsDialogs"],
|
||||
[1.0, 1.0, 1.0, 0.0],
|
||||
)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.theme_cls.bind(
|
||||
material_style=self.set_style, theme_style=self.update_md_bg_color
|
||||
)
|
||||
self.theme_cls.bind(theme_style=self.update_md_bg_color)
|
||||
self.theme_cls.bind(material_style=self.set_style)
|
||||
Clock.schedule_once(self.set_style)
|
||||
Clock.schedule_once(
|
||||
lambda x: self.on_ripple_behavior(0, self.ripple_behavior)
|
||||
@ -807,9 +848,7 @@ class MDCard(
|
||||
|
||||
def update_md_bg_color(self, instance_card, theme_style: str) -> None:
|
||||
if self.md_bg_color in self._bg_color_map:
|
||||
self.md_bg_color = get_color_from_hex(
|
||||
colors[theme_style]["CardsDialogs"]
|
||||
)
|
||||
self.md_bg_color = colors[theme_style]["CardsDialogs"]
|
||||
|
||||
def set_style(self, *args) -> None:
|
||||
self.set_radius()
|
||||
@ -826,7 +865,7 @@ class MDCard(
|
||||
if self.style == "outlined" or self.style == "filled":
|
||||
self.elevation = 0
|
||||
elif self.style == "elevated":
|
||||
self.elevation = 2
|
||||
self.elevation = 1
|
||||
|
||||
def set_radius(self) -> None:
|
||||
if (
|
||||
|
@ -132,7 +132,7 @@ Use with elevation
|
||||
icon_right: "close-circle-outline"
|
||||
line_color: app.theme_cls.disabled_hint_text_color
|
||||
md_bg_color: 1, 0, 0, .5
|
||||
elevation: 4
|
||||
elevation: 12
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/chip-with-elevation.png
|
||||
:align: center
|
||||
@ -304,6 +304,7 @@ __all__ = ("MDChip",)
|
||||
|
||||
import os
|
||||
|
||||
from kivy import Logger
|
||||
from kivy.animation import Animation
|
||||
from kivy.lang import Builder
|
||||
from kivy.metrics import dp
|
||||
@ -313,13 +314,14 @@ from kivy.uix.behaviors import ButtonBehavior
|
||||
from kivymd import uix_path
|
||||
from kivymd.theming import ThemableBehavior
|
||||
from kivymd.uix.behaviors import (
|
||||
CommonElevationBehavior,
|
||||
FakeRectangularElevationBehavior,
|
||||
RectangularRippleBehavior,
|
||||
ScaleBehavior,
|
||||
TouchBehavior,
|
||||
)
|
||||
from kivymd.uix.boxlayout import MDBoxLayout
|
||||
from kivymd.uix.label import MDIcon
|
||||
from kivymd.uix.stacklayout import MDStackLayout
|
||||
from kivymd.uix.templates import ScaleWidget
|
||||
|
||||
with open(
|
||||
os.path.join(uix_path, "chip", "chip.kv"), encoding="utf-8"
|
||||
@ -328,12 +330,12 @@ with open(
|
||||
|
||||
|
||||
class MDChip(
|
||||
MDBoxLayout,
|
||||
ThemableBehavior,
|
||||
RectangularRippleBehavior,
|
||||
ButtonBehavior,
|
||||
CommonElevationBehavior,
|
||||
FakeRectangularElevationBehavior,
|
||||
TouchBehavior,
|
||||
ButtonBehavior,
|
||||
MDBoxLayout,
|
||||
):
|
||||
text = StringProperty()
|
||||
"""
|
||||
@ -454,7 +456,7 @@ class MDChip(
|
||||
self.active = False
|
||||
|
||||
|
||||
class MDScalableCheckIcon(MDIcon, ScaleBehavior):
|
||||
class MDScalableCheckIcon(MDIcon, ScaleWidget):
|
||||
pos_hint = {"center_y": 0.5}
|
||||
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
#:import DEVICE_TYPE kivymd.material_resources.DEVICE_TYPE
|
||||
#:import FakeRectangularElevationBehavior kivymd.uix.behaviors.FakeRectangularElevationBehavior
|
||||
|
||||
|
||||
<CellRow>
|
||||
@ -65,7 +66,7 @@
|
||||
size_hint_y: None
|
||||
height: self.minimum_height
|
||||
spacing: "4dp"
|
||||
tooltip_text: root.tooltip if root.tooltip else root.text
|
||||
tooltip_text: root.text
|
||||
|
||||
BoxLayout:
|
||||
id: box
|
||||
@ -174,11 +175,7 @@
|
||||
font_size: "14sp"
|
||||
on_release: root.table_data.open_pagination_menu()
|
||||
text:
|
||||
"{}".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) \
|
||||
)
|
||||
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)}"
|
||||
|
||||
Widget:
|
||||
size_hint_x: None
|
||||
@ -195,11 +192,9 @@
|
||||
if root.theme_cls.theme_style == "Dark" else \
|
||||
(0, 0, 0, 1)
|
||||
text:
|
||||
"1-{} of {}".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), len(root.table_data.row_data) \
|
||||
)
|
||||
f"1-" \
|
||||
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)} " \
|
||||
f"of {len(root.table_data.row_data)}"
|
||||
|
||||
MDIconButton:
|
||||
id: button_back
|
||||
@ -222,7 +217,7 @@
|
||||
on_release: root.table_data.set_next_row_data_parts("forward")
|
||||
|
||||
|
||||
<TableContainer@MDCard>
|
||||
<TableContainer@MDCard+FakeRectangularElevationBehavior>
|
||||
|
||||
|
||||
<MDDataTable>
|
||||
|
@ -11,6 +11,19 @@ Components/DataTables
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/data-tables-previous.png
|
||||
: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.
|
||||
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
|
||||
@ -146,15 +159,6 @@ class CellHeader(MDTooltip, BoxLayout):
|
||||
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.
|
||||
sort_action = ObjectProperty()
|
||||
"""
|
||||
@ -336,19 +340,11 @@ class TableHeader(ThemableBehavior, ScrollView):
|
||||
CellHeader(
|
||||
text=col_heading[0],
|
||||
sort_action=col_heading[2],
|
||||
tooltip=col_heading[3],
|
||||
width=self.cols_minimum[i],
|
||||
table_data=self.table_data,
|
||||
is_sorted=(col_heading[0] == self.sorted_on),
|
||||
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
|
||||
else CellHeader(
|
||||
text=col_heading[0],
|
||||
@ -360,9 +356,6 @@ class TableHeader(ThemableBehavior, ScrollView):
|
||||
else:
|
||||
# Sets the text in the first cell.
|
||||
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.width = self.cols_minimum[i]
|
||||
|
||||
@ -772,9 +765,6 @@ class TablePagination(ThemableBehavior, MDBoxLayout):
|
||||
|
||||
class MDDataTable(ThemableBehavior, AnchorLayout):
|
||||
"""
|
||||
See :class:`~kivy.uix.anchorlayout.AnchorLayout` class documentation for
|
||||
more information.
|
||||
|
||||
:Events:
|
||||
:attr:`on_row_press`
|
||||
Called when a table row is clicked.
|
||||
@ -785,6 +775,7 @@ class MDDataTable(ThemableBehavior, AnchorLayout):
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
|
||||
from kivy.metrics import dp
|
||||
|
||||
from kivymd.app import MDApp
|
||||
@ -923,82 +914,38 @@ class MDDataTable(ThemableBehavior, AnchorLayout):
|
||||
"""
|
||||
Data for header columns.
|
||||
|
||||
.. tabs::
|
||||
.. code-block:: python
|
||||
|
||||
.. tab:: Imperative python style
|
||||
from kivy.metrics import dp
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from kivy.metrics import dp
|
||||
|
||||
from kivymd.app import MDApp
|
||||
from kivymd.uix.datatables import MDDataTable
|
||||
from kivy.uix.anchorlayout import AnchorLayout
|
||||
from kivymd.app import MDApp
|
||||
from kivymd.uix.datatables import MDDataTable
|
||||
from kivy.uix.anchorlayout import AnchorLayout
|
||||
|
||||
|
||||
class Example(MDApp):
|
||||
def build(self):
|
||||
self.theme_cls.theme_style = "Dark"
|
||||
self.theme_cls.primary_palette = "Orange"
|
||||
|
||||
layout = AnchorLayout()
|
||||
self.data_tables = MDDataTable(
|
||||
size_hint=(0.7, 0.6),
|
||||
use_pagination=True,
|
||||
check=True,
|
||||
# name column, width column, sorting function column(optional), custom tooltip
|
||||
column_data=[
|
||||
("No.", dp(30), None, "Custom tooltip"),
|
||||
("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)),
|
||||
],
|
||||
)
|
||||
layout.add_widget(self.data_tables)
|
||||
return layout
|
||||
class Example(MDApp):
|
||||
def build(self):
|
||||
layout = AnchorLayout()
|
||||
self.data_tables = 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)),
|
||||
],
|
||||
)
|
||||
layout.add_widget(self.data_tables)
|
||||
return layout
|
||||
|
||||
|
||||
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()
|
||||
Example().run()
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/data-tables-column-data.png
|
||||
:align: center
|
||||
@ -1113,9 +1060,6 @@ class MDDataTable(ThemableBehavior, AnchorLayout):
|
||||
|
||||
class Example(MDApp):
|
||||
def build(self):
|
||||
self.theme_cls.theme_style = "Dark"
|
||||
self.theme_cls.primary_palette = "Orange"
|
||||
|
||||
layout = AnchorLayout()
|
||||
data_tables = MDDataTable(
|
||||
size_hint=(0.9, 0.6),
|
||||
@ -1243,7 +1187,7 @@ class MDDataTable(ThemableBehavior, AnchorLayout):
|
||||
"""
|
||||
Use or not use checkboxes for rows.
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/data-tables-check.png
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/data-tables-check.gif
|
||||
:align: center
|
||||
|
||||
:attr:`check` is an :class:`~kivy.properties.BooleanProperty`
|
||||
@ -1265,9 +1209,6 @@ class MDDataTable(ThemableBehavior, AnchorLayout):
|
||||
|
||||
class Example(MDApp):
|
||||
def build(self):
|
||||
self.theme_cls.theme_style = "Dark"
|
||||
self.theme_cls.primary_palette = "Orange"
|
||||
|
||||
layout = AnchorLayout()
|
||||
data_tables = MDDataTable(
|
||||
size_hint=(0.9, 0.6),
|
||||
@ -1297,19 +1238,19 @@ class MDDataTable(ThemableBehavior, AnchorLayout):
|
||||
and defaults to `False`.
|
||||
"""
|
||||
|
||||
elevation = NumericProperty(4)
|
||||
elevation = NumericProperty(8)
|
||||
"""
|
||||
Table elevation.
|
||||
|
||||
:attr:`elevation` is an :class:`~kivy.properties.NumericProperty`
|
||||
and defaults to `4`.
|
||||
and defaults to `8`.
|
||||
"""
|
||||
|
||||
rows_num = NumericProperty(5)
|
||||
"""
|
||||
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-rows-num.png
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/data-tables-use-pagination.gif
|
||||
:align: center
|
||||
|
||||
:attr:`rows_num` is an :class:`~kivy.properties.NumericProperty`
|
||||
@ -1325,7 +1266,7 @@ class MDDataTable(ThemableBehavior, AnchorLayout):
|
||||
|
||||
.. rubric:: Center
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/data-tables-menu-pos-top.png
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/data-tables-menu-pos-center.png
|
||||
:align: center
|
||||
|
||||
.. rubric:: Auto
|
||||
@ -1341,6 +1282,11 @@ class MDDataTable(ThemableBehavior, AnchorLayout):
|
||||
"""
|
||||
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
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/data-tables-menu-height-240.png
|
||||
@ -1352,7 +1298,7 @@ class MDDataTable(ThemableBehavior, AnchorLayout):
|
||||
|
||||
background_color = ColorProperty([0, 0, 0, 0])
|
||||
"""
|
||||
Background color in the format (r, g, b, a) or string format.
|
||||
Background color in the format (r, g, b, a).
|
||||
See :attr:`~kivy.uix.modalview.ModalView.background_color`.
|
||||
|
||||
Use markup strings
|
||||
@ -1369,9 +1315,6 @@ class MDDataTable(ThemableBehavior, AnchorLayout):
|
||||
|
||||
class Example(MDApp):
|
||||
def build(self):
|
||||
self.theme_cls.theme_style = "Dark"
|
||||
self.theme_cls.primary_palette = "Orange"
|
||||
|
||||
layout = AnchorLayout()
|
||||
data_tables = MDDataTable(
|
||||
size_hint=(0.9, 0.6),
|
||||
@ -1411,8 +1354,7 @@ class MDDataTable(ThemableBehavior, AnchorLayout):
|
||||
|
||||
background_color_header = ColorProperty(None)
|
||||
"""
|
||||
Background color in the format (r, g, b, a) or string format for
|
||||
:class:`~TableHeader` class.
|
||||
Background color for :class:`~TableHeader` class.
|
||||
|
||||
.. versionadded:: 1.0.0
|
||||
|
||||
@ -1432,8 +1374,7 @@ class MDDataTable(ThemableBehavior, AnchorLayout):
|
||||
|
||||
background_color_cell = ColorProperty(None)
|
||||
"""
|
||||
Background color in the format (r, g, b, a) or string format for
|
||||
:class:`~CellRow` class.
|
||||
Background color for :class:`~CellRow` class.
|
||||
|
||||
.. versionadded:: 1.0.0
|
||||
|
||||
@ -1454,8 +1395,7 @@ class MDDataTable(ThemableBehavior, AnchorLayout):
|
||||
|
||||
background_color_selected_cell = ColorProperty(None)
|
||||
"""
|
||||
Background selected color in the format (r, g, b, a) or string format for
|
||||
:class:`~CellRow` class.
|
||||
Background selected color for :class:`~CellRow` class.
|
||||
|
||||
.. versionadded:: 1.0.0
|
||||
|
||||
@ -1468,7 +1408,7 @@ class MDDataTable(ThemableBehavior, AnchorLayout):
|
||||
background_color_selected_cell="e4514f",
|
||||
)
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/data-tables-background-color-selected-cell.png
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/data-tables-background-color-selected-cell.gif
|
||||
:align: center
|
||||
|
||||
:attr:`background_color_selected_cell` is a :class:`~kivy.properties.ColorProperty` and
|
||||
@ -1563,9 +1503,6 @@ class MDDataTable(ThemableBehavior, AnchorLayout):
|
||||
data_tables = None
|
||||
|
||||
def build(self):
|
||||
self.theme_cls.theme_style = "Dark"
|
||||
self.theme_cls.primary_palette = "Orange"
|
||||
|
||||
layout = MDFloatLayout() # root layout
|
||||
# Creating control buttons.
|
||||
button_box = MDBoxLayout(
|
||||
@ -1667,9 +1604,6 @@ class MDDataTable(ThemableBehavior, AnchorLayout):
|
||||
data_tables = None
|
||||
|
||||
def build(self):
|
||||
self.theme_cls.theme_style = "Dark"
|
||||
self.theme_cls.primary_palette = "Orange"
|
||||
|
||||
layout = MDFloatLayout()
|
||||
layout.add_widget(
|
||||
MDRaisedButton(
|
||||
|
@ -18,11 +18,7 @@
|
||||
PopMatrix
|
||||
|
||||
|
||||
<DialogContainer@MDCard>
|
||||
shadow_color: 0.0, 0.0, 0.0, 0.0
|
||||
elevation: 0
|
||||
shadow_softness: 0
|
||||
shadow_offset: 0, 0
|
||||
<DialogContainer@MDCard+FakeRectangularElevationBehavior>
|
||||
|
||||
|
||||
<MDDialog>
|
||||
@ -32,6 +28,7 @@
|
||||
orientation: "vertical"
|
||||
size_hint_y: None
|
||||
height: self.minimum_height
|
||||
elevation: 24
|
||||
padding: "24dp", "24dp", "8dp", "8dp"
|
||||
radius: root.radius
|
||||
md_bg_color:
|
||||
|
@ -38,8 +38,6 @@ Usage
|
||||
dialog = None
|
||||
|
||||
def build(self):
|
||||
self.theme_cls.theme_style = "Dark"
|
||||
self.theme_cls.primary_palette = "Orange"
|
||||
return Builder.load_string(KV)
|
||||
|
||||
def show_alert_dialog(self):
|
||||
@ -89,7 +87,6 @@ from kivy.uix.modalview import ModalView
|
||||
from kivymd import uix_path
|
||||
from kivymd.material_resources import DEVICE_TYPE
|
||||
from kivymd.theming import ThemableBehavior
|
||||
from kivymd.uix.behaviors import CommonElevationBehavior
|
||||
from kivymd.uix.button import BaseButton
|
||||
from kivymd.uix.card import MDSeparator
|
||||
from kivymd.uix.list import BaseListItem
|
||||
@ -100,40 +97,7 @@ with open(
|
||||
Builder.load_string(kv_file.read())
|
||||
|
||||
|
||||
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]`.
|
||||
"""
|
||||
|
||||
class BaseDialog(ThemableBehavior, ModalView):
|
||||
radius = ListProperty([dp(7), dp(7), dp(7), dp(7)])
|
||||
"""
|
||||
Dialog corners rounding value.
|
||||
@ -286,22 +250,21 @@ class MDDialog(BaseDialog):
|
||||
class Example(MDApp):
|
||||
dialog = None
|
||||
|
||||
def build(self):
|
||||
self.theme_cls.theme_style = "Dark"
|
||||
self.theme_cls.primary_palette = "Orange"
|
||||
return Builder.load_string(KV)
|
||||
def build(self):
|
||||
return Builder.load_string(KV)
|
||||
|
||||
def show_simple_dialog(self):
|
||||
if not self.dialog:
|
||||
self.dialog = MDDialog(
|
||||
title="Set backup account",
|
||||
type="simple",
|
||||
items=[
|
||||
Item(text="user01@gmail.com", source="kivymd/images/logo/kivymd-icon-128.png"),
|
||||
Item(text="user02@gmail.com", source="data/logo/kivy-icon-128.png"),
|
||||
],
|
||||
)
|
||||
self.dialog.open()
|
||||
def show_simple_dialog(self):
|
||||
if not self.dialog:
|
||||
self.dialog = MDDialog(
|
||||
title="Set backup account",
|
||||
type="simple",
|
||||
items=[
|
||||
Item(text="user01@gmail.com", source="user-1.png"),
|
||||
Item(text="user02@gmail.com", source="user-2.png"),
|
||||
Item(text="Add account", source="add-icon.png"),
|
||||
],
|
||||
)
|
||||
self.dialog.open()
|
||||
|
||||
|
||||
Example().run()
|
||||
@ -354,8 +317,6 @@ class MDDialog(BaseDialog):
|
||||
dialog = None
|
||||
|
||||
def build(self):
|
||||
self.theme_cls.theme_style = "Dark"
|
||||
self.theme_cls.primary_palette = "Orange"
|
||||
return Builder.load_string(KV)
|
||||
|
||||
def show_confirmation_dialog(self):
|
||||
@ -424,140 +385,71 @@ class MDDialog(BaseDialog):
|
||||
"""
|
||||
Custom content class.
|
||||
|
||||
.. tabs::
|
||||
.. code-block:: python
|
||||
|
||||
.. tab:: Declarative KV style
|
||||
from kivy.lang import Builder
|
||||
from kivy.uix.boxlayout import BoxLayout
|
||||
|
||||
.. code-block:: python
|
||||
from kivymd.app import MDApp
|
||||
from kivymd.uix.button import MDFlatButton
|
||||
from kivymd.uix.dialog import MDDialog
|
||||
|
||||
from kivy.lang import Builder
|
||||
from kivy.uix.boxlayout import BoxLayout
|
||||
KV = '''
|
||||
<Content>
|
||||
orientation: "vertical"
|
||||
spacing: "12dp"
|
||||
size_hint_y: None
|
||||
height: "120dp"
|
||||
|
||||
from kivymd.app import MDApp
|
||||
from kivymd.uix.button import MDFlatButton
|
||||
from kivymd.uix.dialog import MDDialog
|
||||
MDTextField:
|
||||
hint_text: "City"
|
||||
|
||||
KV = '''
|
||||
<Content>
|
||||
orientation: "vertical"
|
||||
spacing: "12dp"
|
||||
size_hint_y: None
|
||||
height: "120dp"
|
||||
|
||||
MDTextField:
|
||||
hint_text: "City"
|
||||
|
||||
MDTextField:
|
||||
hint_text: "Street"
|
||||
MDTextField:
|
||||
hint_text: "Street"
|
||||
|
||||
|
||||
MDFloatLayout:
|
||||
MDFloatLayout:
|
||||
|
||||
MDFlatButton:
|
||||
text: "ALERT DIALOG"
|
||||
pos_hint: {'center_x': .5, 'center_y': .5}
|
||||
on_release: app.show_confirmation_dialog()
|
||||
'''
|
||||
MDFlatButton:
|
||||
text: "ALERT DIALOG"
|
||||
pos_hint: {'center_x': .5, 'center_y': .5}
|
||||
on_release: app.show_confirmation_dialog()
|
||||
'''
|
||||
|
||||
|
||||
class Content(BoxLayout):
|
||||
pass
|
||||
class Content(BoxLayout):
|
||||
pass
|
||||
|
||||
|
||||
class Example(MDApp):
|
||||
dialog = None
|
||||
class Example(MDApp):
|
||||
dialog = None
|
||||
|
||||
def build(self):
|
||||
self.theme_cls.theme_style = "Dark"
|
||||
self.theme_cls.primary_palette = "Orange"
|
||||
return Builder.load_string(KV)
|
||||
def build(self):
|
||||
return Builder.load_string(KV)
|
||||
|
||||
def show_confirmation_dialog(self):
|
||||
if not self.dialog:
|
||||
self.dialog = MDDialog(
|
||||
title="Address:",
|
||||
type="custom",
|
||||
content_cls=Content(),
|
||||
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()
|
||||
def show_confirmation_dialog(self):
|
||||
if not self.dialog:
|
||||
self.dialog = MDDialog(
|
||||
title="Address:",
|
||||
type="custom",
|
||||
content_cls=Content(),
|
||||
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()
|
||||
|
||||
.. 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()
|
||||
Example().run()
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/dialog-custom.png
|
||||
:align: center
|
||||
@ -568,7 +460,7 @@ class MDDialog(BaseDialog):
|
||||
|
||||
md_bg_color = ColorProperty(None)
|
||||
"""
|
||||
Background color in the (r, g, b, a) or string format.
|
||||
Background color in the format (r, g, b, a).
|
||||
|
||||
:attr:`md_bg_color` is an :class:`~kivy.properties.ColorProperty`
|
||||
and defaults to `None`.
|
||||
|
@ -1,7 +1,7 @@
|
||||
<_Triangle>:
|
||||
canvas:
|
||||
Color:
|
||||
rgba: app.theme_cls.text_color
|
||||
rgba: root.theme_cls.text_color
|
||||
Triangle:
|
||||
points:
|
||||
[ \
|
||||
@ -13,8 +13,7 @@
|
||||
|
||||
<MDDropDownItem>
|
||||
orientation: "vertical"
|
||||
size_hint: None, None
|
||||
size: self.minimum_size
|
||||
adaptive_size: True
|
||||
spacing: "5dp"
|
||||
padding: "5dp", "5dp", "5dp", 0
|
||||
|
||||
|
@ -15,13 +15,13 @@ Usage
|
||||
from kivymd.app import MDApp
|
||||
|
||||
KV = '''
|
||||
MDScreen
|
||||
Screen
|
||||
|
||||
MDDropDownItem:
|
||||
id: drop_item
|
||||
pos_hint: {'center_x': .5, 'center_y': .5}
|
||||
text: 'Item'
|
||||
on_release: print("Press item")
|
||||
on_release: self.set_item("New Item")
|
||||
'''
|
||||
|
||||
|
||||
@ -48,12 +48,12 @@ import os
|
||||
from kivy.lang import Builder
|
||||
from kivy.properties import NumericProperty, StringProperty
|
||||
from kivy.uix.behaviors import ButtonBehavior
|
||||
from kivy.uix.boxlayout import BoxLayout
|
||||
from kivy.uix.widget import Widget
|
||||
|
||||
from kivymd import uix_path
|
||||
from kivymd.theming import ThemableBehavior
|
||||
from kivymd.uix.behaviors import DeclarativeBehavior
|
||||
from kivymd.uix.behaviors import FakeRectangularElevationBehavior
|
||||
from kivymd.uix.boxlayout import MDBoxLayout
|
||||
|
||||
with open(
|
||||
os.path.join(uix_path, "dropdownitem", "dropdownitem.kv"), encoding="utf-8"
|
||||
@ -61,12 +61,15 @@ with open(
|
||||
Builder.load_string(kv_file.read())
|
||||
|
||||
|
||||
class _Triangle(Widget):
|
||||
class _Triangle(ThemableBehavior, Widget):
|
||||
pass
|
||||
|
||||
|
||||
class MDDropDownItem(
|
||||
DeclarativeBehavior, ThemableBehavior, ButtonBehavior, BoxLayout
|
||||
ThemableBehavior,
|
||||
FakeRectangularElevationBehavior,
|
||||
ButtonBehavior,
|
||||
MDBoxLayout,
|
||||
):
|
||||
text = StringProperty()
|
||||
"""
|
||||
|
@ -6,29 +6,28 @@
|
||||
background_normal: ""
|
||||
background_down: ""
|
||||
dir_or_file_name: ""
|
||||
icon_color: 0, 0, 0, 0
|
||||
_selected: False
|
||||
events_callback: lambda x: None
|
||||
orientation: "vertical"
|
||||
|
||||
ModifiedOneLineIconListItem:
|
||||
text: root.dir_or_file_name
|
||||
on_release: root.events_callback(root.path, root)
|
||||
bg_color:
|
||||
self.theme_cls.bg_darkest \
|
||||
if root._selected else \
|
||||
self.theme_cls.bg_normal
|
||||
if root._selected else self.theme_cls.bg_normal
|
||||
on_release: root.events_callback(root.path, root)
|
||||
|
||||
IconLeftWidget:
|
||||
icon: root.icon
|
||||
theme_icon_color: "Custom"
|
||||
icon_color: root.icon_color
|
||||
theme_text_color: "Custom"
|
||||
text_color: self.theme_cls.primary_color
|
||||
|
||||
MDSeparator:
|
||||
|
||||
|
||||
<LabelContent@MDLabel>
|
||||
adaptive_height: True
|
||||
size_hint_y: None
|
||||
height: self.texture_size[1]
|
||||
shorten: True
|
||||
shorten_from: "center"
|
||||
halign: "center"
|
||||
@ -62,6 +61,23 @@
|
||||
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>
|
||||
md_bg_color: root.theme_cls.bg_normal
|
||||
|
||||
@ -74,11 +90,7 @@
|
||||
title: root.current_path
|
||||
right_action_items: [["close-box", lambda x: root.exit_manager(1)]]
|
||||
left_action_items: [["chevron-left", lambda x: root.back()]]
|
||||
elevation: 3
|
||||
md_bg_color:
|
||||
app.theme_cls.primary_color \
|
||||
if not root.background_color_toolbar else \
|
||||
root.background_color_toolbar
|
||||
elevation: 10
|
||||
|
||||
RecycleView:
|
||||
id: rv
|
||||
|
@ -9,7 +9,7 @@ Usage
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
path = os.path.expanduser("~") # path to the directory that will be opened in the file manager
|
||||
path = '/' # path to the directory that will be opened in the file manager
|
||||
file_manager = MDFileManager(
|
||||
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
|
||||
@ -19,7 +19,7 @@ Usage
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/file-manager.png
|
||||
: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.
|
||||
|
||||
Or with ``preview`` mode:
|
||||
@ -32,7 +32,7 @@ Or with ``preview`` mode:
|
||||
preview=True,
|
||||
)
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/file-manager-preview.png
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/file-manager-previous.png
|
||||
:align: center
|
||||
|
||||
.. warning:: The `preview` mode is intended only for viewing images and will
|
||||
@ -43,8 +43,6 @@ Example
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import os
|
||||
|
||||
from kivy.core.window import Window
|
||||
from kivy.lang import Builder
|
||||
|
||||
@ -55,19 +53,19 @@ Example
|
||||
|
||||
KV = '''
|
||||
MDBoxLayout:
|
||||
orientation: "vertical"
|
||||
orientation: 'vertical'
|
||||
|
||||
MDTopAppBar:
|
||||
title: "MDFileManager"
|
||||
left_action_items: [["menu", lambda x: None]]
|
||||
elevation: 3
|
||||
left_action_items: [['menu', lambda x: None]]
|
||||
elevation: 10
|
||||
|
||||
MDFloatLayout:
|
||||
|
||||
MDRoundFlatIconButton:
|
||||
text: "Open manager"
|
||||
icon: "folder"
|
||||
pos_hint: {"center_x": .5, "center_y": .5}
|
||||
pos_hint: {'center_x': .5, 'center_y': .6}
|
||||
on_release: app.file_manager_open()
|
||||
'''
|
||||
|
||||
@ -78,23 +76,23 @@ Example
|
||||
Window.bind(on_keyboard=self.events)
|
||||
self.manager_open = False
|
||||
self.file_manager = MDFileManager(
|
||||
exit_manager=self.exit_manager, select_path=self.select_path
|
||||
exit_manager=self.exit_manager,
|
||||
select_path=self.select_path,
|
||||
preview=True,
|
||||
)
|
||||
|
||||
def build(self):
|
||||
self.theme_cls.theme_style = "Dark"
|
||||
self.theme_cls.primary_palette = "Orange"
|
||||
return Builder.load_string(KV)
|
||||
|
||||
def file_manager_open(self):
|
||||
self.file_manager.show(os.path.expanduser("~")) # output manager to the screen
|
||||
self.file_manager.show('/') # output manager to the screen
|
||||
self.manager_open = True
|
||||
|
||||
def select_path(self, path: str):
|
||||
'''
|
||||
It will be called when you click on the file name
|
||||
def select_path(self, path):
|
||||
'''It will be called when you click on the file name
|
||||
or the catalog selection button.
|
||||
|
||||
:type path: str;
|
||||
:param path: path to the selected directory or file;
|
||||
'''
|
||||
|
||||
@ -128,9 +126,6 @@ Not tested on `iOS`.
|
||||
|
||||
def file_manager_open(self):
|
||||
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",)
|
||||
@ -141,7 +136,6 @@ import re
|
||||
from typing import List, Tuple, Union
|
||||
|
||||
from kivy import platform
|
||||
from kivy.clock import Clock
|
||||
from kivy.factory import Factory
|
||||
from kivy.lang import Builder
|
||||
from kivy.metrics import dp
|
||||
@ -154,6 +148,7 @@ from kivy.properties import (
|
||||
OptionProperty,
|
||||
StringProperty,
|
||||
)
|
||||
from kivy.uix.anchorlayout import AnchorLayout
|
||||
from kivy.uix.behaviors import ButtonBehavior
|
||||
from kivy.uix.modalview import ModalView
|
||||
|
||||
@ -161,7 +156,6 @@ from kivymd import images_path, uix_path
|
||||
from kivymd.theming import ThemableBehavior
|
||||
from kivymd.uix.behaviors import CircularRippleBehavior
|
||||
from kivymd.uix.boxlayout import MDBoxLayout
|
||||
from kivymd.uix.button import MDFloatingActionButton
|
||||
from kivymd.uix.fitimage import FitImage
|
||||
from kivymd.uix.list import BaseListItem
|
||||
from kivymd.uix.relativelayout import MDRelativeLayout
|
||||
@ -173,7 +167,9 @@ with open(
|
||||
|
||||
|
||||
class BodyManager(MDBoxLayout):
|
||||
"""Base class for folders and files icons."""
|
||||
"""
|
||||
Base class for folders and files icons.
|
||||
"""
|
||||
|
||||
|
||||
class BodyManagerWithPreview(MDBoxLayout):
|
||||
@ -186,146 +182,47 @@ class IconButton(CircularRippleBehavior, ButtonBehavior, FitImage):
|
||||
"""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):
|
||||
_txt_left_pad = NumericProperty("72dp")
|
||||
_txt_top_pad = NumericProperty("16dp")
|
||||
_txt_bot_pad = NumericProperty("15dp")
|
||||
_num_lines = 1
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
self.height = dp(48)
|
||||
|
||||
|
||||
class MDFileManager(MDRelativeLayout, ThemableBehavior):
|
||||
class MDFileManager(ThemableBehavior, MDRelativeLayout):
|
||||
icon = StringProperty("check")
|
||||
"""
|
||||
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.
|
||||
The icon that will be used on the directory selection button.
|
||||
|
||||
:attr:`icon` is an :class:`~kivy.properties.StringProperty`
|
||||
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 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
|
||||
The icon that will be used for folder icons when using ``preview = True``.
|
||||
|
||||
:attr:`icon` is an :class:`~kivy.properties.StringProperty`
|
||||
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)
|
||||
"""
|
||||
Function called when the user reaches directory tree root.
|
||||
@ -362,12 +259,12 @@ class MDFileManager(MDRelativeLayout, ThemableBehavior):
|
||||
and defaults to `all`.
|
||||
"""
|
||||
|
||||
current_path = StringProperty(os.path.expanduser("~"))
|
||||
current_path = StringProperty(os.getcwd())
|
||||
"""
|
||||
Current directory.
|
||||
|
||||
:attr:`current_path` is an :class:`~kivy.properties.StringProperty`
|
||||
and defaults to `os.path.expanduser("~")`.
|
||||
and defaults to `/`.
|
||||
"""
|
||||
|
||||
use_access = BooleanProperty(True)
|
||||
@ -398,9 +295,9 @@ class MDFileManager(MDRelativeLayout, ThemableBehavior):
|
||||
"name", options=["nothing", "name", "date", "size", "type"]
|
||||
)
|
||||
"""
|
||||
It can take the values 'nothing' 'name' 'date' 'size' 'type' - sorts files
|
||||
by option. By default, sort by name. Available options are:
|
||||
`'nothing'`, `'name'`, `'date'`, `'size'`, `'type'`.
|
||||
It can take the values 'nothing' 'name' 'date' 'size' 'type' - sorts files by option
|
||||
By default, sort by name.
|
||||
Available options are: `'nothing'`, `'name'`, `'date'`, `'size'`, `'type'`.
|
||||
|
||||
:attr:`sort_by` is an :class:`~kivy.properties.OptionProperty`
|
||||
and defaults to `name`.
|
||||
@ -428,33 +325,29 @@ class MDFileManager(MDRelativeLayout, ThemableBehavior):
|
||||
"""
|
||||
Contains the list of files that are currently selected.
|
||||
|
||||
:attr:`selection` is a read-only :class:`~kivy.properties.ListProperty`
|
||||
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`.
|
||||
:attr:`selection` is a read-only :class:`~kivy.properties.ListProperty` and
|
||||
defaults to `[]`.
|
||||
"""
|
||||
|
||||
_window_manager = None
|
||||
_window_manager_open = False
|
||||
|
||||
def __init__(self, *args, **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")
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
toolbar_label = self.ids.toolbar.children[1].children[0]
|
||||
toolbar_label.font_style = "Subtitle1"
|
||||
Clock.schedule_once(self._create_selection_button)
|
||||
if (
|
||||
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:
|
||||
self.ext = [".png", ".jpg", ".jpeg"]
|
||||
@ -507,7 +400,15 @@ class MDFileManager(MDRelativeLayout, ThemableBehavior):
|
||||
}
|
||||
)
|
||||
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:
|
||||
"""
|
||||
@ -573,9 +474,6 @@ class MDFileManager(MDRelativeLayout, ThemableBehavior):
|
||||
"icon": icon,
|
||||
"dir_or_file_name": name,
|
||||
"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,
|
||||
}
|
||||
)
|
||||
@ -590,14 +488,19 @@ class MDFileManager(MDRelativeLayout, ThemableBehavior):
|
||||
"icon": "file-outline",
|
||||
"dir_or_file_name": os.path.split(name)[1],
|
||||
"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,
|
||||
}
|
||||
)
|
||||
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:
|
||||
access_string = ""
|
||||
@ -654,9 +557,7 @@ class MDFileManager(MDRelativeLayout, ThemableBehavior):
|
||||
def close(self) -> None:
|
||||
"""Closes the file manager window."""
|
||||
|
||||
self.dispatch("on_pre_dismiss")
|
||||
self._window_manager.dismiss()
|
||||
self.dispatch("on_dismiss")
|
||||
self._window_manager_open = False
|
||||
|
||||
def select_dir_or_file(
|
||||
@ -708,84 +609,6 @@ class MDFileManager(MDRelativeLayout, ThemableBehavior):
|
||||
if self.selector == "folder" or self.selector == "any":
|
||||
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_by_name(files):
|
||||
files.sort(key=locale.strxfrm)
|
||||
|
@ -132,11 +132,11 @@ from kivy.properties import BooleanProperty, ObjectProperty
|
||||
from kivy.uix.image import AsyncImage
|
||||
from kivy.uix.widget import Widget
|
||||
|
||||
from kivymd.uix.behaviors import StencilBehavior
|
||||
from kivymd.uix.boxlayout import MDBoxLayout
|
||||
from kivymd.uix.templates import StencilWidget
|
||||
|
||||
|
||||
class FitImage(MDBoxLayout, StencilBehavior):
|
||||
class FitImage(MDBoxLayout, StencilWidget):
|
||||
source = ObjectProperty()
|
||||
"""
|
||||
Filename/source of your image.
|
||||
|
@ -90,7 +90,4 @@ from kivymd.uix.behaviors import DeclarativeBehavior
|
||||
|
||||
|
||||
class MDGridLayout(DeclarativeBehavior, GridLayout, MDAdaptiveWidget):
|
||||
"""
|
||||
Grid layout class. For more information, see in the
|
||||
:class:`~kivy.uix.gridlayout.GridLayout` class documentation.
|
||||
"""
|
||||
pass
|
||||
|
@ -63,7 +63,7 @@ Base example
|
||||
x: 24
|
||||
|
||||
FitImage:
|
||||
source: "kivymd/images/logo/kivymd-icon-512.png"
|
||||
source: "https://github.com/kivymd/internal/raw/main/logo/kivymd_logo_blue.png"
|
||||
size_hint: None, None
|
||||
size: hero_from.size
|
||||
|
||||
@ -72,7 +72,7 @@ Base example
|
||||
pos_hint: {"center_x": .5}
|
||||
y: "36dp"
|
||||
on_release:
|
||||
root.current_heroes = ["hero"]
|
||||
root.current_hero = "hero"
|
||||
root.current = "screen B"
|
||||
|
||||
MDScreen:
|
||||
@ -82,7 +82,6 @@ Base example
|
||||
|
||||
MDHeroTo:
|
||||
id: hero_to
|
||||
tag: "hero"
|
||||
size_hint: None, None
|
||||
size: "220dp", "220dp"
|
||||
pos_hint: {"center_x": .5, "center_y": .5}
|
||||
@ -92,7 +91,7 @@ Base example
|
||||
pos_hint: {"center_x": .5}
|
||||
y: "36dp"
|
||||
on_release:
|
||||
root.current_heroes = ["hero"]
|
||||
root.current_hero = "hero"
|
||||
root.current = "screen A"
|
||||
'''
|
||||
|
||||
@ -114,7 +113,6 @@ Note that the child of the :class:`~MDHeroFrom` widget must have the size of the
|
||||
|
||||
MDHeroFrom:
|
||||
id: hero_from
|
||||
tag: "hero"
|
||||
|
||||
FitImage:
|
||||
size_hint: None, None
|
||||
@ -129,7 +127,7 @@ container in which the hero is located:
|
||||
MDRaisedButton:
|
||||
text: "Move Hero To Screen B"
|
||||
on_release:
|
||||
root.current_heroes = ["hero"]
|
||||
root.current_hero = "hero"
|
||||
root.current = "screen 2"
|
||||
|
||||
If you need to switch to a screen that does not contain heroes, set the
|
||||
@ -140,7 +138,7 @@ If you need to switch to a screen that does not contain heroes, set the
|
||||
MDRaisedButton:
|
||||
text: "Go To Another Screen"
|
||||
on_release:
|
||||
root.current_heroes = []
|
||||
root.current_hero = ""
|
||||
root.current = "another screen"
|
||||
|
||||
Example
|
||||
@ -168,7 +166,7 @@ Example
|
||||
x: 24
|
||||
|
||||
FitImage:
|
||||
source: "kivymd/images/logo/kivymd-icon-512.png"
|
||||
source: "https://github.com/kivymd/internal/raw/main/logo/kivymd_logo_blue.png"
|
||||
size_hint: None, None
|
||||
size: hero_from.size
|
||||
|
||||
@ -177,7 +175,7 @@ Example
|
||||
pos_hint: {"center_x": .5}
|
||||
y: "36dp"
|
||||
on_release:
|
||||
root.current_heroes = ["hero"]
|
||||
root.current_hero = "hero"
|
||||
root.current = "screen B"
|
||||
|
||||
MDScreen:
|
||||
@ -187,7 +185,6 @@ Example
|
||||
|
||||
MDHeroTo:
|
||||
id: hero_to
|
||||
tag: "hero"
|
||||
size_hint: None, None
|
||||
size: "220dp", "220dp"
|
||||
pos_hint: {"center_x": .5, "center_y": .5}
|
||||
@ -197,7 +194,7 @@ Example
|
||||
pos_hint: {"center_x": .5}
|
||||
y: "52dp"
|
||||
on_release:
|
||||
root.current_heroes = []
|
||||
root.current_hero = ""
|
||||
root.current = "screen C"
|
||||
|
||||
MDRaisedButton:
|
||||
@ -205,7 +202,7 @@ Example
|
||||
pos_hint: {"center_x": .5}
|
||||
y: "8dp"
|
||||
on_release:
|
||||
root.current_heroes = ["hero"]
|
||||
root.current_hero = "hero"
|
||||
root.current = "screen A"
|
||||
|
||||
MDScreen:
|
||||
@ -286,7 +283,7 @@ background color of the hero during the flight between the screens:
|
||||
pos_hint: {"center_x": .5}
|
||||
y: "36dp"
|
||||
on_release:
|
||||
root.current_heroes = ["hero"]
|
||||
root.current_hero = "hero"
|
||||
root.current = "screen B"
|
||||
|
||||
MDScreen:
|
||||
@ -296,7 +293,6 @@ background color of the hero during the flight between the screens:
|
||||
|
||||
MDHeroTo:
|
||||
id: hero_to
|
||||
tag: "hero"
|
||||
size_hint: None, None
|
||||
size: "220dp", "220dp"
|
||||
pos_hint: {"center_x": .5, "center_y": .5}
|
||||
@ -306,7 +302,7 @@ background color of the hero during the flight between the screens:
|
||||
pos_hint: {"center_x": .5}
|
||||
y: "36dp"
|
||||
on_release:
|
||||
root.current_heroes = ["hero"]
|
||||
root.current_hero = "hero"
|
||||
root.current = "screen A"
|
||||
'''
|
||||
|
||||
@ -374,7 +370,7 @@ Usage with ScrollView
|
||||
radius: 24
|
||||
box_radius: 0, 0, 24, 24
|
||||
box_color: 0, 0, 0, .5
|
||||
source: "kivymd/images/logo/kivymd-icon-512.png"
|
||||
source: "image.jpg"
|
||||
size_hint: None, None
|
||||
size: root.size
|
||||
mipmap: True
|
||||
@ -403,7 +399,7 @@ Usage with ScrollView
|
||||
|
||||
MDScreen:
|
||||
name: "screen B"
|
||||
heroes_to: [hero_to]
|
||||
hero_to: hero_to
|
||||
|
||||
MDHeroTo:
|
||||
id: hero_to
|
||||
@ -416,7 +412,7 @@ Usage with ScrollView
|
||||
pos_hint: {"center_x": .5}
|
||||
y: "36dp"
|
||||
on_release:
|
||||
root.current_heroes = [hero_to.tag]
|
||||
root.current_hero = "hero"
|
||||
root.current = "screen A"
|
||||
'''
|
||||
|
||||
@ -445,8 +441,7 @@ Usage with ScrollView
|
||||
|
||||
def on_release(self):
|
||||
def switch_screen(*args):
|
||||
self.manager.current_heroes = [self.tag]
|
||||
self.manager.ids.hero_to.tag = self.tag
|
||||
self.manager.current_hero = self.tag
|
||||
self.manager.current = "screen B"
|
||||
|
||||
Clock.schedule_once(switch_screen, 0.2)
|
||||
@ -470,93 +465,6 @@ Usage with ScrollView
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/hero-usage-with-scrollview.gif
|
||||
: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
|
||||
@ -568,9 +476,6 @@ class MDHeroFrom(MDBoxLayout):
|
||||
"""
|
||||
The container from which the hero begins his flight.
|
||||
|
||||
For more information, see in the
|
||||
:class:`~kivymd.uix.boxlayout.MDBoxLayout` class documentation.
|
||||
|
||||
:Events:
|
||||
`on_transform_in`
|
||||
when the hero flies from screen **A** to screen **B**.
|
||||
@ -582,7 +487,7 @@ class MDHeroFrom(MDBoxLayout):
|
||||
"""
|
||||
Tag ID for heroes.
|
||||
|
||||
:attr:`tag` is an :class:`~kivy.properties.StringProperty`
|
||||
:attr:`shift_right` is an :class:`~kivy.properties.StringProperty`
|
||||
and defaults to `''`.
|
||||
"""
|
||||
|
||||
@ -599,17 +504,4 @@ class MDHeroFrom(MDBoxLayout):
|
||||
|
||||
|
||||
class MDHeroTo(MDBoxLayout):
|
||||
"""
|
||||
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 `''`.
|
||||
"""
|
||||
"""The container in which the hero comes."""
|
||||
|
@ -65,13 +65,12 @@ Implementation
|
||||
:align: center
|
||||
"""
|
||||
|
||||
__all__ = [
|
||||
"MDSmartTile",
|
||||
]
|
||||
__all__ = "MDSmartTile"
|
||||
|
||||
import os
|
||||
|
||||
from kivy.lang import Builder
|
||||
from kivy.logger import Logger
|
||||
from kivy.properties import (
|
||||
BooleanProperty,
|
||||
ColorProperty,
|
||||
|
@ -17,14 +17,8 @@
|
||||
rgba: (1, 1, 1, 1) if self.source else (0, 0, 0, 0)
|
||||
Rectangle:
|
||||
source: self.source if self.source else None
|
||||
pos:
|
||||
self.pos \
|
||||
if not self.source else \
|
||||
(self.x - self._size[0] / 2, self.y)
|
||||
size:
|
||||
self._size \
|
||||
if self.source else \
|
||||
self.size
|
||||
pos: self.pos
|
||||
size: self.size
|
||||
|
||||
font_style: "Icon"
|
||||
text: u"{}".format(md_icons[root.icon]) if root.icon in md_icons else "blank"
|
||||
|
@ -222,18 +222,14 @@ __all__ = ("MDLabel", "MDIcon")
|
||||
import os
|
||||
from typing import Union
|
||||
|
||||
from kivy.animation import Animation
|
||||
from kivy.clock import Clock
|
||||
from kivy.graphics import Color, Rectangle
|
||||
from kivy.lang import Builder
|
||||
from kivy.metrics import sp
|
||||
from kivy.properties import (
|
||||
AliasProperty,
|
||||
BooleanProperty,
|
||||
ColorProperty,
|
||||
ListProperty,
|
||||
NumericProperty,
|
||||
ObjectProperty,
|
||||
OptionProperty,
|
||||
StringProperty,
|
||||
)
|
||||
@ -326,7 +322,6 @@ class MDLabel(DeclarativeBehavior, ThemableBehavior, Label, MDAdaptiveWidget):
|
||||
|
||||
parent_background = ColorProperty(None)
|
||||
can_capitalize = BooleanProperty(True)
|
||||
canvas_bg = ObjectProperty()
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
@ -354,7 +349,6 @@ class MDLabel(DeclarativeBehavior, ThemableBehavior, Label, MDAdaptiveWidget):
|
||||
font_info = self.theme_cls.font_styles[self.font_style]
|
||||
self.font_name = font_info[0]
|
||||
self.font_size = sp(font_info[1])
|
||||
|
||||
if font_info[2] and self.can_capitalize:
|
||||
self._capitalizing = True
|
||||
else:
|
||||
@ -380,68 +374,29 @@ class MDLabel(DeclarativeBehavior, ThemableBehavior, Label, MDAdaptiveWidget):
|
||||
# generic None value it's not yet been set
|
||||
self._text_color_str = ""
|
||||
if theme_text_color == "Custom" and self.text_color:
|
||||
color = self.text_color
|
||||
self.color = self.text_color
|
||||
elif (
|
||||
theme_text_color == "ContrastParentBackground"
|
||||
and self.parent_background
|
||||
):
|
||||
color = get_contrast_text_color(self.parent_background)
|
||||
self.color = get_contrast_text_color(self.parent_background)
|
||||
else:
|
||||
color = [0, 0, 0, 1]
|
||||
self.color = [0, 0, 0, 1]
|
||||
|
||||
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:
|
||||
def on_text_color(self, instance_label, color: list) -> None:
|
||||
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:
|
||||
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):
|
||||
if self._text_color_str:
|
||||
self.color = getattr(self.theme_cls, self._text_color_str)
|
||||
if not self.disabled:
|
||||
color = getattr(self.theme_cls, self._text_color_str)
|
||||
self.color = getattr(self.theme_cls, self._text_color_str)
|
||||
else:
|
||||
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
|
||||
self.color = getattr(self.theme_cls, "disabled_hint_text_color")
|
||||
|
||||
|
||||
class MDIcon(MDFloatLayout, MDLabel):
|
||||
@ -501,16 +456,11 @@ class MDIcon(MDFloatLayout, MDLabel):
|
||||
and defaults to `None`.
|
||||
"""
|
||||
|
||||
_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:
|
||||
def __init__(self, **kwargs):
|
||||
from kivymd.uix.selectioncontrol import MDCheckbox
|
||||
|
||||
super().__init__(**kwargs)
|
||||
if not isinstance(self, MDCheckbox):
|
||||
self.size_hint = (None, None)
|
||||
self._size = self.texture_size[1], self.texture_size[1]
|
||||
self.size = self.texture_size
|
||||
self.adaptive_size = True
|
||||
|
@ -1,4 +1,4 @@
|
||||
#:import STANDARD_INCREMENT kivymd.material_resources.STANDARD_INCREMENT
|
||||
#:import STD_INC kivymd.material_resources.STANDARD_INCREMENT
|
||||
|
||||
|
||||
<RightContent>
|
||||
@ -14,7 +14,7 @@
|
||||
|
||||
<MDMenu>
|
||||
size_hint: None, None
|
||||
width: root.width_mult * STANDARD_INCREMENT
|
||||
width: root.width_mult * STD_INC
|
||||
bar_width: 0
|
||||
key_viewclass: "viewclass"
|
||||
key_size: "height"
|
||||
@ -28,7 +28,7 @@
|
||||
orientation: "vertical"
|
||||
|
||||
|
||||
<MenuContainer@MDCard>
|
||||
<MenuContainer@MDCard+FakeRectangularElevationBehavior>
|
||||
|
||||
|
||||
<MDDropdownMenu>
|
||||
|
@ -781,7 +781,7 @@ class MDDropdownMenu(ThemableBehavior, FloatLayout):
|
||||
and defaults to `'[dp(7)]'`.
|
||||
"""
|
||||
|
||||
elevation = NumericProperty(4)
|
||||
elevation = NumericProperty(10)
|
||||
"""
|
||||
Elevation value of menu dialog.
|
||||
|
||||
@ -790,7 +790,7 @@ class MDDropdownMenu(ThemableBehavior, FloatLayout):
|
||||
.. code-block:: python
|
||||
|
||||
self.menu = MDDropdownMenu(
|
||||
elevation=4,
|
||||
elevation=16,
|
||||
...,
|
||||
)
|
||||
|
||||
@ -798,7 +798,7 @@ class MDDropdownMenu(ThemableBehavior, FloatLayout):
|
||||
:align: center
|
||||
|
||||
:attr:`elevation` is an :class:`~kivy.properties.NumericProperty`
|
||||
and defaults to `4`.
|
||||
and defaults to `10`.
|
||||
"""
|
||||
|
||||
_start_coords = []
|
||||
|
@ -61,7 +61,7 @@ A simple example
|
||||
|
||||
MDTopAppBar:
|
||||
title: "Navigation Drawer"
|
||||
elevation: 4
|
||||
elevation: 10
|
||||
pos_hint: {"top": 1}
|
||||
md_bg_color: "#e7e4c0"
|
||||
specific_text_color: "#4a4939"
|
||||
@ -115,7 +115,7 @@ A simple example
|
||||
MDScreen(
|
||||
MDTopAppBar(
|
||||
title="Navigation Drawer",
|
||||
elevation=4,
|
||||
elevation=10,
|
||||
pos_hint={"top": 1},
|
||||
md_bg_color="#e7e4c0",
|
||||
specific_text_color="#4a4939",
|
||||
@ -188,7 +188,7 @@ Standard content for the navigation bar
|
||||
|
||||
MDTopAppBar:
|
||||
title: "Navigation Drawer"
|
||||
elevation: 4
|
||||
elevation: 10
|
||||
pos_hint: {"top": 1}
|
||||
md_bg_color: "#e7e4c0"
|
||||
specific_text_color: "#4a4939"
|
||||
@ -296,7 +296,7 @@ Standard content for the navigation bar
|
||||
MDScreen(
|
||||
MDTopAppBar(
|
||||
title="Navigation Drawer",
|
||||
elevation=4,
|
||||
elevation=10,
|
||||
pos_hint={"top": 1},
|
||||
md_bg_color="#e7e4c0",
|
||||
specific_text_color="#4a4939",
|
||||
@ -396,7 +396,7 @@ Switching screens in the ``ScreenManager`` and using the common ``MDTopAppBar``
|
||||
|
||||
MDTopAppBar:
|
||||
pos_hint: {"top": 1}
|
||||
elevation: 4
|
||||
elevation: 10
|
||||
title: "MDNavigationDrawer"
|
||||
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(
|
||||
MDTopAppBar(
|
||||
pos_hint={"top": 1},
|
||||
elevation=4,
|
||||
elevation=10,
|
||||
title="MDNavigationDrawer",
|
||||
left_action_items=[["menu", lambda x: self.nav_drawer_open()]],
|
||||
),
|
||||
@ -551,9 +551,14 @@ from kivy.properties import (
|
||||
StringProperty,
|
||||
VariableListProperty,
|
||||
)
|
||||
from kivy.uix.floatlayout import FloatLayout
|
||||
from kivy.uix.screenmanager import ScreenManager
|
||||
|
||||
from kivymd import uix_path
|
||||
from kivymd.uix.behaviors import (
|
||||
DeclarativeBehavior,
|
||||
FakeRectangularElevationBehavior,
|
||||
)
|
||||
from kivymd.uix.behaviors.focus_behavior import FocusBehavior
|
||||
from kivymd.uix.boxlayout import MDBoxLayout
|
||||
from kivymd.uix.card import MDCard
|
||||
@ -1024,7 +1029,7 @@ class MDNavigationDrawerMenu(MDScrollView):
|
||||
widget.text_color = widget._text_color
|
||||
|
||||
|
||||
class MDNavigationDrawer(MDCard):
|
||||
class MDNavigationDrawer(MDCard, FakeRectangularElevationBehavior):
|
||||
type = OptionProperty("modal", options=("standard", "modal"))
|
||||
"""
|
||||
Type of drawer. Modal type will be on top of screen. Standard type will be
|
||||
|
@ -29,86 +29,45 @@ Usage
|
||||
|
||||
MDNavigationRailItem:
|
||||
|
||||
.. tabs::
|
||||
.. code-block:: python
|
||||
|
||||
.. tab:: Declarative KV style
|
||||
from kivy.lang import Builder
|
||||
|
||||
.. code-block:: python
|
||||
from kivymd.app import MDApp
|
||||
|
||||
from kivy.lang import Builder
|
||||
|
||||
from kivymd.app import MDApp
|
||||
|
||||
KV = '''
|
||||
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"
|
||||
|
||||
MDScreen:
|
||||
'''
|
||||
KV = '''
|
||||
|
||||
|
||||
class Example(MDApp):
|
||||
def build(self):
|
||||
return Builder.load_string(KV)
|
||||
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"
|
||||
|
||||
MDScreen:
|
||||
'''
|
||||
|
||||
|
||||
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):
|
||||
return Builder.load_string(KV)
|
||||
|
||||
|
||||
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()
|
||||
Example().run()
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/navigation-rail-usage.png
|
||||
:align: center
|
||||
@ -116,412 +75,202 @@ Usage
|
||||
Example
|
||||
=======
|
||||
|
||||
.. tabs::
|
||||
.. code-block:: python
|
||||
|
||||
.. tab:: Declarative KV and imperative python styles
|
||||
from kivy.clock import Clock
|
||||
from kivy.lang import Builder
|
||||
|
||||
.. code-block:: python
|
||||
from kivymd.app import MDApp
|
||||
from kivymd.uix.behaviors import RoundedRectangularElevationBehavior
|
||||
from kivymd.uix.boxlayout import MDBoxLayout
|
||||
from kivymd.uix.button import MDFillRoundFlatIconButton
|
||||
from kivymd.uix.label import MDLabel
|
||||
from kivymd.uix.screen import MDScreen
|
||||
|
||||
from kivy.clock import Clock
|
||||
from kivy.lang import Builder
|
||||
|
||||
from kivymd.app import MDApp
|
||||
from kivymd.uix.behaviors import CommonElevationBehavior
|
||||
from kivymd.uix.boxlayout import MDBoxLayout
|
||||
from kivymd.uix.button import MDFillRoundFlatIconButton
|
||||
from kivymd.uix.label import MDLabel
|
||||
from kivymd.uix.screen import MDScreen
|
||||
|
||||
KV = '''
|
||||
#:import FadeTransition kivy.uix.screenmanager.FadeTransition
|
||||
KV = '''
|
||||
#:import FadeTransition kivy.uix.screenmanager.FadeTransition
|
||||
|
||||
|
||||
<ExtendedButton>
|
||||
elevation: 3.5
|
||||
shadow_radius: 12
|
||||
shadow_softness: 4
|
||||
-height: "56dp"
|
||||
<ExtendedButton>
|
||||
elevation: 3
|
||||
-height: "56dp"
|
||||
|
||||
|
||||
<DrawerClickableItem@MDNavigationDrawerItem>
|
||||
focus_color: "#e7e4c0"
|
||||
unfocus_color: "#fffcf4"
|
||||
<DrawerClickableItem@MDNavigationDrawerItem>
|
||||
focus_color: "#e7e4c0"
|
||||
unfocus_color: "#fffcf4"
|
||||
|
||||
|
||||
MDScreen:
|
||||
MDScreen:
|
||||
|
||||
MDNavigationLayout:
|
||||
MDNavigationLayout:
|
||||
|
||||
ScreenManager:
|
||||
ScreenManager:
|
||||
|
||||
MDScreen:
|
||||
MDScreen:
|
||||
|
||||
MDBoxLayout:
|
||||
orientation: "vertical"
|
||||
|
||||
MDBoxLayout:
|
||||
adaptive_height: True
|
||||
md_bg_color: "#fffcf4"
|
||||
padding: "12dp"
|
||||
|
||||
MDLabel:
|
||||
text: "12:00"
|
||||
adaptive_height: True
|
||||
pos_hint: {"center_y": .5}
|
||||
|
||||
MDBoxLayout:
|
||||
|
||||
MDNavigationRail:
|
||||
id: navigation_rail
|
||||
md_bg_color: "#fffcf4"
|
||||
selected_color_background: "#e7e4c0"
|
||||
ripple_color_item: "#e7e4c0"
|
||||
on_item_release: app.switch_screen(*args)
|
||||
|
||||
MDNavigationRailMenuButton:
|
||||
on_release: nav_drawer.set_state("open")
|
||||
|
||||
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"
|
||||
|
||||
ScreenManager:
|
||||
id: screen_manager
|
||||
transition:
|
||||
FadeTransition(duration=.2, clearcolor=app.theme_cls.bg_dark)
|
||||
|
||||
MDNavigationDrawer:
|
||||
id: nav_drawer
|
||||
radius: (0, 16, 16, 0)
|
||||
md_bg_color: "#fffcf4"
|
||||
elevation: 4
|
||||
width: "240dp"
|
||||
|
||||
MDNavigationDrawerMenu:
|
||||
MDBoxLayout:
|
||||
orientation: "vertical"
|
||||
|
||||
MDBoxLayout:
|
||||
orientation: "vertical"
|
||||
adaptive_height: True
|
||||
spacing: "12dp"
|
||||
padding: "3dp", 0, 0, "12dp"
|
||||
md_bg_color: "#fffcf4"
|
||||
padding: "12dp"
|
||||
|
||||
MDIconButton:
|
||||
icon: "menu"
|
||||
MDLabel:
|
||||
text: "12:00"
|
||||
adaptive_height: True
|
||||
pos_hint: {"center_y": .5}
|
||||
|
||||
ExtendedButton:
|
||||
text: "Compose"
|
||||
icon: "pencil"
|
||||
MDBoxLayout:
|
||||
|
||||
DrawerClickableItem:
|
||||
text: "Python"
|
||||
icon: "language-python"
|
||||
MDNavigationRail:
|
||||
id: navigation_rail
|
||||
md_bg_color: "#fffcf4"
|
||||
selected_color_background: "#e7e4c0"
|
||||
ripple_color_item: "#e7e4c0"
|
||||
on_item_release: app.switch_screen(*args)
|
||||
|
||||
DrawerClickableItem:
|
||||
text: "JavaScript"
|
||||
icon: "language-javascript"
|
||||
MDNavigationRailMenuButton:
|
||||
on_release: nav_drawer.set_state("open")
|
||||
|
||||
DrawerClickableItem:
|
||||
text: "CPP"
|
||||
icon: "language-cpp"
|
||||
MDNavigationRailFabButton:
|
||||
md_bg_color: "#b0f0d6"
|
||||
|
||||
DrawerClickableItem:
|
||||
text: "Swift"
|
||||
icon: "language-swift"
|
||||
MDNavigationRailItem:
|
||||
text: "Python"
|
||||
icon: "language-python"
|
||||
|
||||
MDNavigationRailItem:
|
||||
text: "JavaScript"
|
||||
icon: "language-javascript"
|
||||
|
||||
MDNavigationRailItem:
|
||||
text: "CPP"
|
||||
icon: "language-cpp"
|
||||
|
||||
MDNavigationRailItem:
|
||||
text: "Swift"
|
||||
icon: "language-swift"
|
||||
|
||||
ScreenManager:
|
||||
id: screen_manager
|
||||
transition:
|
||||
FadeTransition(duration=.2, clearcolor=app.theme_cls.bg_dark)
|
||||
|
||||
MDNavigationDrawer:
|
||||
id: nav_drawer
|
||||
radius: (0, 16, 16, 0)
|
||||
md_bg_color: "#fffcf4"
|
||||
elevation: 12
|
||||
width: "240dp"
|
||||
|
||||
MDNavigationDrawerMenu:
|
||||
|
||||
MDBoxLayout:
|
||||
orientation: "vertical"
|
||||
adaptive_height: True
|
||||
spacing: "12dp"
|
||||
padding: 0, 0, 0, "12dp"
|
||||
|
||||
MDIconButton:
|
||||
icon: "menu"
|
||||
|
||||
ExtendedButton:
|
||||
text: "Compose"
|
||||
icon: "pencil"
|
||||
|
||||
DrawerClickableItem:
|
||||
text: "Python"
|
||||
icon: "language-python"
|
||||
|
||||
DrawerClickableItem:
|
||||
text: "JavaScript"
|
||||
icon: "language-javascript"
|
||||
|
||||
DrawerClickableItem:
|
||||
text: "CPP"
|
||||
icon: "language-cpp"
|
||||
|
||||
DrawerClickableItem:
|
||||
text: "Swift"
|
||||
icon: "language-swift"
|
||||
'''
|
||||
|
||||
|
||||
class ExtendedButton(
|
||||
RoundedRectangularElevationBehavior, MDFillRoundFlatIconButton
|
||||
):
|
||||
'''
|
||||
Implements a button of type
|
||||
`Extended FAB <https://m3.material.io/components/extended-fab/overview>`_.
|
||||
|
||||
.. rubric::
|
||||
Extended FABs help people take primary actions.
|
||||
They're wider than FABs to accommodate a text label and larger target
|
||||
area.
|
||||
|
||||
This type of buttons is not yet implemented in the standard widget set
|
||||
of the KivyMD library, so we will implement it ourselves in this class.
|
||||
'''
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
self.padding = "16dp"
|
||||
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 Builder.load_string(KV)
|
||||
|
||||
def switch_screen(
|
||||
self, instance_navigation_rail, instance_navigation_rail_item
|
||||
):
|
||||
'''
|
||||
Called when tapping on rail menu items. Switches application screens.
|
||||
'''
|
||||
|
||||
|
||||
class ExtendedButton(MDFillRoundFlatIconButton, CommonElevationBehavior):
|
||||
'''
|
||||
Implements a button of type
|
||||
`Extended FAB <https://m3.material.io/components/extended-fab/overview>`_.
|
||||
|
||||
.. rubric::
|
||||
Extended FABs help people take primary actions.
|
||||
They're wider than FABs to accommodate a text label and larger target
|
||||
area.
|
||||
|
||||
This type of buttons is not yet implemented in the standard widget set
|
||||
of the KivyMD library, so we will implement it ourselves in this class.
|
||||
'''
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.padding = "16dp"
|
||||
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 Builder.load_string(KV)
|
||||
|
||||
def switch_screen(
|
||||
self, instance_navigation_rail, instance_navigation_rail_item
|
||||
):
|
||||
'''
|
||||
Called when tapping on rail menu items. Switches application screens.
|
||||
'''
|
||||
|
||||
self.root.ids.screen_manager.current = (
|
||||
instance_navigation_rail_item.icon.split("-")[1].lower()
|
||||
)
|
||||
|
||||
def on_start(self):
|
||||
'''Creates application screens.'''
|
||||
|
||||
navigation_rail_items = self.root.ids.navigation_rail.get_items()[:]
|
||||
navigation_rail_items.reverse()
|
||||
|
||||
for widget in navigation_rail_items:
|
||||
name_screen = widget.icon.split("-")[1].lower()
|
||||
screen = MDScreen(
|
||||
name=name_screen,
|
||||
md_bg_color="#edd769",
|
||||
radius=[18, 0, 0, 0],
|
||||
)
|
||||
box = MDBoxLayout(padding="12dp")
|
||||
label = MDLabel(
|
||||
text=name_screen.capitalize(),
|
||||
font_style="H1",
|
||||
halign="right",
|
||||
adaptive_height=True,
|
||||
shorten=True,
|
||||
)
|
||||
box.add_widget(label)
|
||||
screen.add_widget(box)
|
||||
self.root.ids.screen_manager.add_widget(screen)
|
||||
|
||||
|
||||
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,
|
||||
self.root.ids.screen_manager.current = (
|
||||
instance_navigation_rail_item.icon.split("-")[1].lower()
|
||||
)
|
||||
from kivymd.uix.navigationrail import (
|
||||
MDNavigationRail,
|
||||
MDNavigationRailMenuButton,
|
||||
MDNavigationRailFabButton,
|
||||
MDNavigationRailItem,
|
||||
)
|
||||
from kivymd.uix.screen import MDScreen
|
||||
from kivymd.uix.screenmanager import MDScreenManager
|
||||
|
||||
def on_start(self):
|
||||
'''Creates application screens.'''
|
||||
|
||||
navigation_rail_items = self.root.ids.navigation_rail.get_items()[:]
|
||||
navigation_rail_items.reverse()
|
||||
|
||||
for widget in navigation_rail_items:
|
||||
name_screen = widget.icon.split("-")[1].lower()
|
||||
screen = MDScreen(
|
||||
name=name_screen,
|
||||
md_bg_color="#edd769",
|
||||
radius=[18, 0, 0, 0],
|
||||
)
|
||||
box = MDBoxLayout(padding="12dp")
|
||||
label = MDLabel(
|
||||
text=name_screen.capitalize(),
|
||||
font_style="H1",
|
||||
halign="right",
|
||||
adaptive_height=True,
|
||||
shorten=True,
|
||||
)
|
||||
box.add_widget(label)
|
||||
screen.add_widget(box)
|
||||
self.root.ids.screen_manager.add_widget(screen)
|
||||
|
||||
|
||||
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()
|
||||
Example().run()
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/navigation-rail-example.gif
|
||||
:align: center
|
||||
@ -557,11 +306,12 @@ from kivy.uix.behaviors import ButtonBehavior
|
||||
|
||||
from kivymd import uix_path
|
||||
from kivymd.theming import ThemableBehavior
|
||||
from kivymd.uix.behaviors import ScaleBehavior
|
||||
from kivymd.uix.behaviors import FakeRectangularElevationBehavior
|
||||
from kivymd.uix.boxlayout import MDBoxLayout
|
||||
from kivymd.uix.button import MDFloatingActionButton, MDIconButton
|
||||
from kivymd.uix.card import MDCard
|
||||
from kivymd.uix.floatlayout import MDFloatLayout
|
||||
from kivymd.uix.templates import ScaleWidget
|
||||
from kivymd.uix.widget import MDWidget
|
||||
|
||||
with open(
|
||||
@ -583,7 +333,7 @@ class PanelItems(MDBoxLayout):
|
||||
"""Box for menu items."""
|
||||
|
||||
|
||||
class RippleWidget(MDWidget, ScaleBehavior):
|
||||
class RippleWidget(MDWidget, ScaleWidget):
|
||||
"""
|
||||
Implements a background color for a menu item -
|
||||
(:class:`~MDNavigationRailItem`).
|
||||
@ -812,7 +562,7 @@ class MDNavigationRailItem(ThemableBehavior, ButtonBehavior, MDBoxLayout):
|
||||
self.navigation_rail.dispatch("on_item_release", self)
|
||||
|
||||
|
||||
class MDNavigationRail(MDCard):
|
||||
class MDNavigationRail(MDCard, FakeRectangularElevationBehavior):
|
||||
"""
|
||||
:Events:
|
||||
:attr:`on_item_press`
|
||||
|
@ -11,110 +11,65 @@ Components/DatePicker
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/picker-previous.png
|
||||
: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
|
||||
|
||||
.. tabs::
|
||||
.. code-block:: python
|
||||
|
||||
.. tab:: Declarative KV style
|
||||
from kivy.lang import Builder
|
||||
|
||||
.. code-block:: python
|
||||
from kivymd.app import MDApp
|
||||
from kivymd.uix.pickers import MDDatePicker
|
||||
|
||||
from kivy.lang import Builder
|
||||
KV = '''
|
||||
MDFloatLayout:
|
||||
|
||||
from kivymd.app import MDApp
|
||||
from kivymd.uix.pickers import MDDatePicker
|
||||
MDTopAppBar:
|
||||
title: "MDDatePicker"
|
||||
pos_hint: {"top": 1}
|
||||
elevation: 10
|
||||
|
||||
KV = '''
|
||||
MDFloatLayout:
|
||||
MDRaisedButton:
|
||||
text: "Open date picker"
|
||||
pos_hint: {'center_x': .5, 'center_y': .5}
|
||||
on_release: app.show_date_picker()
|
||||
'''
|
||||
|
||||
MDRaisedButton:
|
||||
text: "Open date picker"
|
||||
pos_hint: {'center_x': .5, 'center_y': .5}
|
||||
on_release: app.show_date_picker()
|
||||
|
||||
class Test(MDApp):
|
||||
def build(self):
|
||||
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)
|
||||
|
||||
class Test(MDApp):
|
||||
def build(self):
|
||||
self.theme_cls.theme_style = "Dark"
|
||||
self.theme_cls.primary_palette = "Orange"
|
||||
return Builder.load_string(KV)
|
||||
def on_cancel(self, instance, value):
|
||||
'''Events called when the "CANCEL" dialog box button is clicked.'''
|
||||
|
||||
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()
|
||||
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
|
||||
Test().run()
|
||||
|
||||
|
||||
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):
|
||||
'''
|
||||
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, *args):
|
||||
date_dialog = MDDatePicker()
|
||||
date_dialog.bind(on_save=self.on_save, on_cancel=self.on_cancel)
|
||||
date_dialog.open()
|
||||
|
||||
|
||||
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
|
||||
|
||||
Open date dialog with the specified date
|
||||
@ -126,7 +81,7 @@ Open date dialog with the specified date
|
||||
date_dialog = MDDatePicker(year=1983, month=4, day=12)
|
||||
date_dialog.open()
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/specified-date.png
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/previous-date.png
|
||||
:align: center
|
||||
|
||||
Interval date
|
||||
@ -139,16 +94,12 @@ that are not included in this range will have the status `disabled`.
|
||||
|
||||
def show_date_picker(self):
|
||||
date_dialog = MDDatePicker(
|
||||
min_date=datetime.date.today(),
|
||||
max_date=datetime.date(
|
||||
datetime.date.today().year,
|
||||
datetime.date.today().month,
|
||||
datetime.date.today().day + 2,
|
||||
),
|
||||
min_date=datetime.date(2021, 2, 15),
|
||||
max_date=datetime.date(2021, 3, 27),
|
||||
)
|
||||
date_dialog.open()
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/range-date.png
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/range-date.gif
|
||||
:align: center
|
||||
|
||||
The range of available dates can be changed in the picker dialog:
|
||||
@ -171,7 +122,7 @@ You can set the range of years using the :attr:`~kivymd.uix.picker.MDDatePicker.
|
||||
.. code-block:: python
|
||||
|
||||
def show_date_picker(self):
|
||||
date_dialog = MDDatePicker(min_year=2022, max_year=2030)
|
||||
date_dialog = MDDatePicker(min_year=2021, max_year=2030)
|
||||
date_dialog.open()
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/min-max-year-date.png
|
||||
@ -190,8 +141,6 @@ Set and select a date range
|
||||
:align: center
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
__all__ = ("MDDatePicker", "BaseDialogPicker", "DatePickerInputField")
|
||||
|
||||
import calendar
|
||||
@ -203,6 +152,7 @@ from typing import Union
|
||||
|
||||
from kivy import Logger
|
||||
from kivy.animation import Animation
|
||||
from kivy.clock import Clock
|
||||
from kivy.lang import Builder
|
||||
from kivy.metrics import dp
|
||||
from kivy.properties import (
|
||||
@ -225,7 +175,7 @@ from kivymd.theming import ThemableBehavior, ThemeManager
|
||||
from kivymd.toast import toast
|
||||
from kivymd.uix.behaviors import (
|
||||
CircularRippleBehavior,
|
||||
CommonElevationBehavior,
|
||||
FakeRectangularElevationBehavior,
|
||||
SpecificBackgroundColorBehavior,
|
||||
)
|
||||
from kivymd.uix.boxlayout import MDBoxLayout
|
||||
@ -244,7 +194,7 @@ with open(
|
||||
|
||||
class BaseDialogPicker(
|
||||
BaseDialog,
|
||||
CommonElevationBehavior,
|
||||
FakeRectangularElevationBehavior,
|
||||
SpecificBackgroundColorBehavior,
|
||||
):
|
||||
"""
|
||||
@ -305,11 +255,11 @@ class BaseDialogPicker(
|
||||
|
||||
primary_color = ColorProperty(None)
|
||||
"""
|
||||
Background color of toolbar in (r, g, b, a) or string format.
|
||||
Background color of toolbar in (r, g, b, a) format.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
MDDatePicker(primary_color="brown")
|
||||
MDDatePicker(primary_color=get_color_from_hex("#72225b"))
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/primary-color-date.png
|
||||
:align: center
|
||||
@ -320,13 +270,13 @@ class BaseDialogPicker(
|
||||
|
||||
accent_color = ColorProperty(None)
|
||||
"""
|
||||
Background color of calendar/clock face in (r, g, b, a) or string format.
|
||||
Background color of calendar/clock face in (r, g, b, a) format.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
MDDatePicker(
|
||||
primary_color="brown",
|
||||
accent_color="darkred",
|
||||
primary_color=get_color_from_hex("#72225b"),
|
||||
accent_color=get_color_from_hex("#5d1a4a"),
|
||||
)
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/accent-color-date.png
|
||||
@ -338,15 +288,14 @@ class BaseDialogPicker(
|
||||
|
||||
selector_color = ColorProperty(None)
|
||||
"""
|
||||
Background color of the selected day of the month or hour in (r, g, b, a)
|
||||
or string format.
|
||||
Background color of the selected day of the month or hour in (r, g, b, a) format.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
MDDatePicker(
|
||||
primary_color="brown",
|
||||
accent_color="darkred",
|
||||
selector_color="red",
|
||||
primary_color=get_color_from_hex("#72225b"),
|
||||
accent_color=get_color_from_hex("#5d1a4a"),
|
||||
selector_color=get_color_from_hex("#e93f39"),
|
||||
)
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/selector-color-date.png
|
||||
@ -358,15 +307,15 @@ class BaseDialogPicker(
|
||||
|
||||
text_toolbar_color = ColorProperty(None)
|
||||
"""
|
||||
Color of labels for text on a toolbar in (r, g, b, a) or string format.
|
||||
Color of labels for text on a toolbar in (r, g, b, a) format.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
MDDatePicker(
|
||||
primary_color="brown",
|
||||
accent_color="darkred",
|
||||
selector_color="red",
|
||||
text_toolbar_color="lightgrey",
|
||||
primary_color=get_color_from_hex("#72225b"),
|
||||
accent_color=get_color_from_hex("#5d1a4a"),
|
||||
selector_color=get_color_from_hex("#e93f39"),
|
||||
text_toolbar_color=get_color_from_hex("#cccccc"),
|
||||
)
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-toolbar-color-date.png
|
||||
@ -378,16 +327,16 @@ class BaseDialogPicker(
|
||||
|
||||
text_color = ColorProperty(None)
|
||||
"""
|
||||
Color of text labels in calendar/clock face in (r, g, b, a) or string format.
|
||||
Color of text labels in calendar/clock face in (r, g, b, a) format.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
MDDatePicker(
|
||||
primary_color="brown",
|
||||
accent_color="darkred",
|
||||
selector_color="red",
|
||||
text_toolbar_color="lightgrey",
|
||||
text_color="orange",
|
||||
primary_color=get_color_from_hex("#72225b"),
|
||||
accent_color=get_color_from_hex("#5d1a4a"),
|
||||
selector_color=get_color_from_hex("#e93f39"),
|
||||
text_toolbar_color=get_color_from_hex("#cccccc"),
|
||||
text_color=("#ffffff"),
|
||||
)
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-color-date.png
|
||||
@ -399,18 +348,17 @@ class BaseDialogPicker(
|
||||
|
||||
text_current_color = ColorProperty(None)
|
||||
"""
|
||||
Color of the text of the current day of the month/hour in (r, g, b, a)
|
||||
or string format.
|
||||
Color of the text of the current day of the month/hour in (r, g, b, a) format.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
MDDatePicker(
|
||||
primary_color="brown",
|
||||
accent_color="darkred",
|
||||
selector_color="red",
|
||||
text_toolbar_color="lightgrey",
|
||||
text_color="orange",
|
||||
text_current_color="white",
|
||||
primary_color=get_color_from_hex("#72225b"),
|
||||
accent_color=get_color_from_hex("#5d1a4a"),
|
||||
selector_color=get_color_from_hex("#e93f39"),
|
||||
text_toolbar_color=get_color_from_hex("#cccccc"),
|
||||
text_color=("#ffffff"),
|
||||
text_current_color=get_color_from_hex("#e93f39"),
|
||||
)
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-current-color-date.png
|
||||
@ -427,13 +375,13 @@ class BaseDialogPicker(
|
||||
.. 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",
|
||||
primary_color=get_color_from_hex("#72225b"),
|
||||
accent_color=get_color_from_hex("#5d1a4a"),
|
||||
selector_color=get_color_from_hex("#e93f39"),
|
||||
text_toolbar_color=get_color_from_hex("#cccccc"),
|
||||
text_color=("#ffffff"),
|
||||
text_current_color=get_color_from_hex("#e93f39"),
|
||||
text_button_color=(1, 1, 1, .5),
|
||||
)
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-button-color-date.png
|
||||
@ -443,124 +391,52 @@ class BaseDialogPicker(
|
||||
and defaults to `None`.
|
||||
"""
|
||||
|
||||
input_field_background_color_normal = ColorProperty(None)
|
||||
input_field_background_color = ColorProperty(None)
|
||||
"""
|
||||
Background color normal of input fields in (r, g, b, a) or string format.
|
||||
|
||||
.. versionadded:: 1.1.0
|
||||
Background color of input fields in (r, g, b, a) format.
|
||||
|
||||
.. 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",
|
||||
primary_color=get_color_from_hex("#72225b"),
|
||||
accent_color=get_color_from_hex("#5d1a4a"),
|
||||
selector_color=get_color_from_hex("#e93f39"),
|
||||
text_toolbar_color=get_color_from_hex("#cccccc"),
|
||||
text_color=("#ffffff"),
|
||||
text_current_color=get_color_from_hex("#e93f39"),
|
||||
input_field_background_color=(1, 1, 1, 0.2),
|
||||
)
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/input-field-background-color-date.png
|
||||
:align: center
|
||||
|
||||
:attr:`input_field_background_color_normal` is an :class:`~kivy.properties.ColorProperty`
|
||||
:attr:`input_field_background_color` is an :class:`~kivy.properties.ColorProperty`
|
||||
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)
|
||||
"""
|
||||
.. deprecated:: 1.1.0
|
||||
Use :attr:`input_field_text_color_normal` instead.
|
||||
"""
|
||||
Text color of input fields in (r, g, b, a) format.
|
||||
|
||||
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
|
||||
Background color of input fields.
|
||||
|
||||
.. 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",
|
||||
primary_color=get_color_from_hex("#72225b"),
|
||||
accent_color=get_color_from_hex("#5d1a4a"),
|
||||
selector_color=get_color_from_hex("#e93f39"),
|
||||
text_toolbar_color=get_color_from_hex("#cccccc"),
|
||||
text_color=("#ffffff"),
|
||||
text_current_color=get_color_from_hex("#e93f39"),
|
||||
input_field_background_color=(1, 1, 1, 0.2),
|
||||
input_field_text_color=(1, 1, 1, 1),
|
||||
)
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/input-field-text-color-normal-date.png
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/input-field-background-color-date.png
|
||||
:align: center
|
||||
|
||||
: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`
|
||||
:attr:`input_field_text_color` is an :class:`~kivy.properties.ColorProperty`
|
||||
and defaults to `None`.
|
||||
"""
|
||||
|
||||
@ -571,18 +447,16 @@ class BaseDialogPicker(
|
||||
.. 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",
|
||||
input_field_text_color_focus="lightgrey",
|
||||
font_name="nasalization.ttf",
|
||||
primary_color=get_color_from_hex("#72225b"),
|
||||
accent_color=get_color_from_hex("#5d1a4a"),
|
||||
selector_color=get_color_from_hex("#e93f39"),
|
||||
text_toolbar_color=get_color_from_hex("#cccccc"),
|
||||
text_color=("#ffffff"),
|
||||
text_current_color=get_color_from_hex("#e93f39"),
|
||||
input_field_background_color=(1, 1, 1, 0.2),
|
||||
input_field_text_color=(1, 1, 1, 1),
|
||||
font_name="Weather.ttf",
|
||||
|
||||
)
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/font-name-date.png
|
||||
@ -597,20 +471,6 @@ class BaseDialogPicker(
|
||||
self.register_event_type("on_save")
|
||||
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:
|
||||
"""Events called when the "OK" dialog box button is clicked."""
|
||||
|
||||
@ -746,13 +606,6 @@ class DatePickerDaySelectableItem(
|
||||
|
||||
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):
|
||||
"""Implements an item for a pick list of the year."""
|
||||
@ -808,7 +661,7 @@ class DatePickerYearSelectableItem(RecycleDataViewBehavior, MDLabel):
|
||||
class MDDatePicker(BaseDialogPicker):
|
||||
text_weekday_color = ColorProperty(None)
|
||||
"""
|
||||
Text color of weekday names in (r, g, b, a) or string format.
|
||||
Text color of weekday names in (r, g, b, a) format.
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/md-date-picker-text-weekday-color.png
|
||||
:align: center
|
||||
@ -1347,39 +1200,19 @@ class MDDatePicker(BaseDialogPicker):
|
||||
"""Creates and returns a text field object used to enter dates."""
|
||||
|
||||
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(
|
||||
owner=self,
|
||||
helper_text=self.helper_text,
|
||||
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,
|
||||
line_color_normal=self.theme_cls.divider_color,
|
||||
)
|
||||
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
|
||||
else:
|
||||
raise TypeError(
|
||||
|
@ -16,73 +16,35 @@ Components/TimePicker
|
||||
|
||||
.. rubric:: Usage
|
||||
|
||||
.. tabs::
|
||||
.. code-block::
|
||||
|
||||
.. tab:: Declarative KV style
|
||||
from kivy.lang import Builder
|
||||
|
||||
.. code-block:: python
|
||||
from kivymd.app import MDApp
|
||||
from kivymd.uix.pickers import MDTimePicker
|
||||
|
||||
from kivy.lang import Builder
|
||||
KV = '''
|
||||
MDFloatLayout:
|
||||
|
||||
from kivymd.app import MDApp
|
||||
from kivymd.uix.pickers import MDTimePicker
|
||||
|
||||
KV = '''
|
||||
MDFloatLayout:
|
||||
|
||||
MDRaisedButton:
|
||||
text: "Open time picker"
|
||||
pos_hint: {'center_x': .5, 'center_y': .5}
|
||||
on_release: app.show_time_picker()
|
||||
'''
|
||||
MDRaisedButton:
|
||||
text: "Open time picker"
|
||||
pos_hint: {'center_x': .5, 'center_y': .5}
|
||||
on_release: app.show_time_picker()
|
||||
'''
|
||||
|
||||
|
||||
class Test(MDApp):
|
||||
def build(self):
|
||||
self.theme_cls.theme_style = "Dark"
|
||||
self.theme_cls.primary_palette = "Orange"
|
||||
return Builder.load_string(KV)
|
||||
class Test(MDApp):
|
||||
def build(self):
|
||||
return Builder.load_string(KV)
|
||||
|
||||
def show_time_picker(self):
|
||||
'''Open time picker dialog.'''
|
||||
def show_time_picker(self):
|
||||
'''Open time picker dialog.'''
|
||||
|
||||
time_dialog = MDTimePicker()
|
||||
time_dialog.open()
|
||||
time_dialog = MDTimePicker()
|
||||
time_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 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()
|
||||
Test().run()
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/MDTimePicker.png
|
||||
:align: center
|
||||
@ -129,14 +91,14 @@ Use the :attr:`~MDTimePicker.set_time` method of the
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
MDTimePicker(
|
||||
primary_color="brown",
|
||||
accent_color="red",
|
||||
text_button_color="white",
|
||||
).open()
|
||||
time_dialog = MDTimePicker(
|
||||
primary_color=get_color_from_hex("#72225b"),
|
||||
accent_color=get_color_from_hex("#5d1a4a"),
|
||||
text_button_color=(1, 1, 1, 1),
|
||||
)
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/time-picker-customization.png
|
||||
:align: center
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/time-picker-customization.png
|
||||
:align: center
|
||||
"""
|
||||
|
||||
__all__ = ("MDTimePicker",)
|
||||
@ -232,8 +194,8 @@ class TimeInputTextField(MDTextField):
|
||||
hour_regx = "^[0-9]$|^0[1-9]$|^1[0-2]$"
|
||||
minute_regx = "^[0-9]$|^0[0-9]$|^[1-5][0-9]$"
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
Clock.schedule_once(self.set_text)
|
||||
self.register_event_type("on_select")
|
||||
self.bind(text_color_focus=self.setter("hint_text_color_normal"))
|
||||
@ -255,20 +217,17 @@ class TimeInputTextField(MDTextField):
|
||||
to somehow make them aligned.
|
||||
"""
|
||||
|
||||
def set_text(*args):
|
||||
if not self.text:
|
||||
self.text = " "
|
||||
if not self.text:
|
||||
self.text = " "
|
||||
|
||||
self._refresh_text(self.text)
|
||||
max_size = max(self._lines_rects, key=lambda r: r.size[0]).size
|
||||
dx = (self.width - max_size[0]) / 2.0
|
||||
dy = (self.height - max_size[1]) / 2.0
|
||||
self.padding = [dx, dy, dx, dy]
|
||||
self._refresh_text(self.text)
|
||||
max_size = max(self._lines_rects, key=lambda r: r.size[0]).size
|
||||
dx = (self.width - max_size[0]) / 2.0
|
||||
dy = (self.height - max_size[1]) / 2.0
|
||||
self.padding = [dx, dy, dx, dy]
|
||||
|
||||
if len(self.text) > 1:
|
||||
self.text = self.text.replace(" ", "")
|
||||
|
||||
Clock.schedule_once(set_text)
|
||||
if len(self.text) > 1:
|
||||
self.text = self.text.replace(" ", "")
|
||||
|
||||
def on_focus(self, *args) -> None:
|
||||
super().on_focus(*args)
|
||||
|
@ -36,7 +36,7 @@ Example
|
||||
title: app.title
|
||||
md_bg_color: app.theme_cls.primary_color
|
||||
background_palette: 'Primary'
|
||||
elevation: 4
|
||||
elevation: 10
|
||||
left_action_items: [['menu', lambda x: x]]
|
||||
|
||||
MDScrollViewRefreshLayout:
|
||||
|
@ -29,7 +29,7 @@ MDScreen
|
||||
md_bg_color: app.theme_cls.primary_color
|
||||
"""
|
||||
|
||||
from kivy.properties import ListProperty, ObjectProperty
|
||||
from kivy.properties import ObjectProperty
|
||||
from kivy.uix.screenmanager import Screen
|
||||
|
||||
from kivymd.uix import MDAdaptiveWidget
|
||||
@ -44,34 +44,20 @@ class MDScreen(DeclarativeBehavior, Screen, MDAdaptiveWidget):
|
||||
see in the :class:`~kivy.uix.screenmanager.Screen` class documentation.
|
||||
"""
|
||||
|
||||
hero_to = ObjectProperty(deprecated=True)
|
||||
hero_to = ObjectProperty()
|
||||
"""
|
||||
Must be a :class:`~kivymd.uix.hero.MDHeroTo` class.
|
||||
|
||||
Must be a :class:`~kivymd.uix.hero.MDHeroTo` class.
|
||||
See the documentation of the
|
||||
`MDHeroTo <https://kivymd.readthedocs.io/en/latest/components/hero/>`_
|
||||
widget for more detailed information.
|
||||
|
||||
.. deprecated:: 1.0.0
|
||||
Use attr:`heroes_to` attribute instead.
|
||||
.. versionchanged:: 1.0.0
|
||||
|
||||
:attr:`hero_to` is an :class:`~kivy.properties.ObjectProperty`
|
||||
and defaults to `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."""
|
||||
|
||||
def on_hero_to(self, screen, widget) -> None:
|
||||
if not isinstance(widget, MDHeroTo) or not issubclass(
|
||||
widget.__class__, MDHeroTo
|
||||
):
|
||||
@ -79,4 +65,3 @@ class MDScreen(DeclarativeBehavior, Screen, MDAdaptiveWidget):
|
||||
f"The `{widget}` widget must be an `kivymd.uix.hero.MDHeroTo` "
|
||||
f"class or inherited from this class"
|
||||
)
|
||||
self.heroes_to = [widget]
|
||||
|
@ -10,7 +10,6 @@ If you want to use Hero animations you need to use
|
||||
:class:`~kivy.uix.screenmanager.ScreenManager` class.
|
||||
"""
|
||||
|
||||
from kivy import Logger
|
||||
from kivy.clock import Clock
|
||||
from kivy.properties import ListProperty, StringProperty
|
||||
from kivy.uix.screenmanager import ScreenManager
|
||||
@ -22,22 +21,17 @@ from kivymd.uix.hero import MDHeroFrom
|
||||
class MDScreenManager(DeclarativeBehavior, ScreenManager):
|
||||
"""
|
||||
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`
|
||||
class documentation.
|
||||
"""
|
||||
|
||||
current_hero = StringProperty(None, deprecated=True)
|
||||
current_hero = StringProperty(None)
|
||||
"""
|
||||
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
|
||||
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/>`_
|
||||
module documentation for more information about creating and using Hero
|
||||
animations.
|
||||
@ -46,17 +40,6 @@ class MDScreenManager(DeclarativeBehavior, ScreenManager):
|
||||
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
|
||||
# screen manager.
|
||||
_heroes_data = ListProperty()
|
||||
@ -75,48 +58,28 @@ class MDScreenManager(DeclarativeBehavior, ScreenManager):
|
||||
|
||||
self.transition = MDSlideTransition()
|
||||
|
||||
def get_hero_from_widget(self) -> list:
|
||||
def get_hero_from_widget(self) -> None:
|
||||
"""
|
||||
Get a list of :class:`~kivymd.uix.hero.MDHeroFrom` objects according
|
||||
to the tag names specified in the :attr:`~current_heroes` list.
|
||||
Get an :class:`~kivymd.uix.hero.MDHeroTo` object with the
|
||||
:attr:`~current_hero` tag.
|
||||
"""
|
||||
|
||||
hero_from_widget = []
|
||||
hero_from_widget = None
|
||||
|
||||
for name_hero in self.current_heroes:
|
||||
for hero_widget in self._heroes_data:
|
||||
if isinstance(hero_widget, MDHeroFrom) or issubclass(
|
||||
hero_widget.__class__, MDHeroFrom
|
||||
):
|
||||
if hero_widget.tag == name_hero:
|
||||
hero_from_widget.append(hero_widget)
|
||||
for hero_widget in self._heroes_data:
|
||||
if isinstance(hero_widget, MDHeroFrom) or issubclass(
|
||||
hero_widget.__class__, MDHeroFrom
|
||||
):
|
||||
if hero_widget.tag == self.current_hero:
|
||||
hero_from_widget = hero_widget
|
||||
break
|
||||
|
||||
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):
|
||||
super().add_widget(widget, *args, **kwargs)
|
||||
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 find_hero_widget(child_widget):
|
||||
widget_hero = None
|
||||
|
@ -15,11 +15,8 @@
|
||||
pos_hint: {"center_y": .5}
|
||||
x: root._segment_switch_x
|
||||
md_bg_color: root.segment_color
|
||||
elevation: 2
|
||||
elevation: 6
|
||||
_radius: root.radius[0] - 4
|
||||
width:
|
||||
segment_panel.width / segment_panel.children_number \
|
||||
- segment_panel.spacing
|
||||
|
||||
SegmentPanel:
|
||||
id: segment_panel
|
||||
|
@ -10,77 +10,58 @@ Components/SegmentedControl
|
||||
Usage
|
||||
=====
|
||||
|
||||
.. tabs::
|
||||
.. code-block:: python
|
||||
|
||||
.. tab:: Declarative KV style
|
||||
from kivy.lang import Builder
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from kivy.lang import Builder
|
||||
|
||||
from kivymd.app import MDApp
|
||||
from kivymd.app import MDApp
|
||||
|
||||
|
||||
KV = '''
|
||||
MDScreen:
|
||||
KV = '''
|
||||
MDScreen:
|
||||
|
||||
MDSegmentedControl:
|
||||
pos_hint: {"center_x": .5, "center_y": .5}
|
||||
MDSegmentedControl:
|
||||
pos_hint: {"center_x": .5, "center_y": .5}
|
||||
|
||||
MDSegmentedControlItem:
|
||||
text: "Male"
|
||||
MDSegmentedControlItem:
|
||||
text: "Male"
|
||||
|
||||
MDSegmentedControlItem:
|
||||
text: "Female"
|
||||
MDSegmentedControlItem:
|
||||
text: "Female"
|
||||
|
||||
MDSegmentedControlItem:
|
||||
text: "All"
|
||||
'''
|
||||
MDSegmentedControlItem:
|
||||
text: "All"
|
||||
'''
|
||||
|
||||
|
||||
class Example(MDApp):
|
||||
def build(self):
|
||||
self.theme_cls.theme_style = "Dark"
|
||||
self.theme_cls.primary_palette = "Orange"
|
||||
return Builder.load_string(KV)
|
||||
class Test(MDApp):
|
||||
def build(self):
|
||||
return Builder.load_string(KV)
|
||||
|
||||
|
||||
Example().run()
|
||||
Test().run()
|
||||
|
||||
.. tab:: Declarative python style
|
||||
Or only in python code:
|
||||
|
||||
.. code-block:: python
|
||||
.. code-block:: python
|
||||
|
||||
from kivymd.app import MDApp
|
||||
from kivymd.uix.screen import MDScreen
|
||||
from kivymd.uix.segmentedcontrol import (
|
||||
MDSegmentedControl, MDSegmentedControlItem
|
||||
)
|
||||
from kivymd.app import MDApp
|
||||
from kivymd.uix.screen import MDScreen
|
||||
from kivymd.uix.segmentedcontrol import MDSegmentedControl, MDSegmentedControlItem
|
||||
|
||||
|
||||
class Example(MDApp):
|
||||
def build(self):
|
||||
self.theme_cls.theme_style = "Dark"
|
||||
self.theme_cls.primary_palette = "Orange"
|
||||
return (
|
||||
MDScreen(
|
||||
MDSegmentedControl(
|
||||
MDSegmentedControlItem(
|
||||
text="Male"
|
||||
),
|
||||
MDSegmentedControlItem(
|
||||
text="Female"
|
||||
),
|
||||
MDSegmentedControlItem(
|
||||
text="All"
|
||||
),
|
||||
pos_hint={"center_x": 0.5, "center_y": 0.5}
|
||||
)
|
||||
)
|
||||
)
|
||||
class Test(MDApp):
|
||||
def build(self):
|
||||
screen = MDScreen()
|
||||
segment_control = MDSegmentedControl(pos_hint={"center_x": .5, "center_y": .5})
|
||||
segment_control.add_widget(MDSegmentedControlItem(text="Male"))
|
||||
segment_control.add_widget(MDSegmentedControlItem(text="Female"))
|
||||
segment_control.add_widget(MDSegmentedControlItem(text="All"))
|
||||
screen.add_widget(segment_control)
|
||||
return screen
|
||||
|
||||
|
||||
Example().run()
|
||||
Test().run()
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/md-segmented-control-usage.gif
|
||||
:align: center
|
||||
@ -136,22 +117,12 @@ with open(
|
||||
|
||||
|
||||
class MDSegmentedControlItem(MDLabel):
|
||||
"""
|
||||
Implements a label to place on the :class:`~SegmentPanel` panel.
|
||||
|
||||
See :class:`~kivymd.uix.label.MDLabel` class documentation for more
|
||||
information.
|
||||
"""
|
||||
"""Implements a label to place on the :class:`~SegmentPanel` panel."""
|
||||
|
||||
|
||||
# TODO: Add an attribute for the color of the active segment label.
|
||||
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:
|
||||
`on_active`
|
||||
Called when the segment is activated.
|
||||
@ -164,7 +135,7 @@ class MDSegmentedControl(MDRelativeLayout, ThemableBehavior):
|
||||
.. code-block:: kv
|
||||
|
||||
MDSegmentedControl:
|
||||
md_bg_color: "brown"
|
||||
md_bg_color: "#451938"
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/md-segmented-control-md-bg-color.png
|
||||
:align: center
|
||||
@ -180,8 +151,8 @@ class MDSegmentedControl(MDRelativeLayout, ThemableBehavior):
|
||||
.. code-block:: kv
|
||||
|
||||
MDSegmentedControl:
|
||||
md_bg_color: "brown"
|
||||
segment_color: "red"
|
||||
md_bg_color: "#451938"
|
||||
segment_color: "#e4514f"
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/md-segmented-control-segment-color.png
|
||||
:align: center
|
||||
@ -189,8 +160,8 @@ class MDSegmentedControl(MDRelativeLayout, ThemableBehavior):
|
||||
.. code-block:: kv
|
||||
|
||||
MDSegmentedControl:
|
||||
md_bg_color: "brown"
|
||||
segment_color: "red"
|
||||
md_bg_color: "#451938"
|
||||
segment_color: "#e4514f"
|
||||
|
||||
MDSegmentedControlItem:
|
||||
text: "[color=fff]Male[/color]"
|
||||
@ -225,9 +196,9 @@ class MDSegmentedControl(MDRelativeLayout, ThemableBehavior):
|
||||
.. code-block:: kv
|
||||
|
||||
MDSegmentedControl:
|
||||
md_bg_color: "brown"
|
||||
segment_color: "red"
|
||||
separator_color: "white"
|
||||
md_bg_color: "#451938"
|
||||
segment_color: "#e4514f"
|
||||
separator_color: 1, 1, 1, 1
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/md-segmented-control-separator-color.png
|
||||
:align: center
|
||||
@ -284,6 +255,9 @@ class MDSegmentedControl(MDRelativeLayout, ThemableBehavior):
|
||||
|
||||
Clock.schedule_once(self.set_default_colors)
|
||||
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:
|
||||
"""
|
||||
@ -339,10 +313,6 @@ class MDSegmentedControl(MDRelativeLayout, ThemableBehavior):
|
||||
self.ids.segment_panel.add_widget(widget)
|
||||
separator = MDSeparator(orientation="vertical")
|
||||
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(
|
||||
lambda x: self.update_separator_color(separator)
|
||||
)
|
||||
@ -356,6 +326,15 @@ class MDSegmentedControl(MDRelativeLayout, ThemableBehavior):
|
||||
self.current_active_segment = 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):
|
||||
self.ids.segment_panel.remove_widget(self.ids.segment_panel.children[0])
|
||||
|
||||
@ -371,7 +350,3 @@ class SegmentPanel(MDBoxLayout):
|
||||
Implements a panel for placing items - :class:`~MDSegmentedControlItem`
|
||||
for the :class:`~MDSegmentedControl` class.
|
||||
"""
|
||||
|
||||
children_number = NumericProperty(1)
|
||||
|
||||
_started = BooleanProperty(defaultvalue=False)
|
||||
|
@ -101,7 +101,7 @@
|
||||
size_hint: None, None
|
||||
size: dp(24), dp(24)
|
||||
elevation:
|
||||
(2.5 if root.active else 1) \
|
||||
(8 if root.active else 5) \
|
||||
if app.theme_cls.material_style != "M3" else \
|
||||
0
|
||||
pos:
|
||||
|
@ -192,10 +192,15 @@ from kivy.properties import (
|
||||
)
|
||||
from kivy.uix.behaviors import ToggleButtonBehavior
|
||||
from kivy.uix.floatlayout import FloatLayout
|
||||
from kivy.utils import get_color_from_hex
|
||||
|
||||
from kivymd import uix_path
|
||||
from kivymd.color_definitions import colors
|
||||
from kivymd.theming import ThemableBehavior
|
||||
from kivymd.uix.behaviors import CircularRippleBehavior, CommonElevationBehavior
|
||||
from kivymd.uix.behaviors import (
|
||||
CircularRippleBehavior,
|
||||
FakeCircularElevationBehavior,
|
||||
)
|
||||
from kivymd.uix.floatlayout import MDFloatLayout
|
||||
from kivymd.uix.label import MDIcon
|
||||
|
||||
@ -356,10 +361,8 @@ class MDCheckbox(CircularRippleBehavior, ToggleButtonBehavior, MDIcon):
|
||||
disabled=self.update_color,
|
||||
state=self.update_color,
|
||||
)
|
||||
self.theme_cls.bind(
|
||||
theme_style=self.update_primary_color,
|
||||
primary_color=self.update_primary_color,
|
||||
)
|
||||
self.theme_cls.bind(primary_color=self.update_primary_color)
|
||||
self.theme_cls.bind(theme_style=self.update_primary_color)
|
||||
self.update_icon()
|
||||
self.update_color()
|
||||
|
||||
@ -420,7 +423,7 @@ class ThumbIcon(MDIcon):
|
||||
|
||||
|
||||
class Thumb(
|
||||
CommonElevationBehavior,
|
||||
FakeCircularElevationBehavior,
|
||||
CircularRippleBehavior,
|
||||
MDFloatLayout,
|
||||
):
|
||||
|
@ -3,7 +3,7 @@
|
||||
#:import colors kivymd.color_definitions.colors
|
||||
|
||||
|
||||
<HintBoxContainer@MDCard>
|
||||
<HintBoxContainer@MDCard+FakeRectangularElevationBehavior>
|
||||
|
||||
|
||||
<MDSlider>
|
||||
@ -131,20 +131,16 @@
|
||||
) \
|
||||
) \
|
||||
)
|
||||
elevation: 0 if root._is_off else (3 if root.active else 1)
|
||||
elevation: 0 if root._is_off else (4 if root.active else 2)
|
||||
|
||||
HintBoxContainer:
|
||||
id: hint_box
|
||||
size_hint: None, None
|
||||
md_bg_color: root.hint_bg_color if root.hint_bg_color else [0, 0, 0, 0]
|
||||
elevation: 1.5
|
||||
md_bg_color: root.hint_bg_color
|
||||
elevation: 0
|
||||
opacity: 1 if root.active else 0
|
||||
radius: root.hint_radius
|
||||
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:
|
||||
lbl_value.width + self.padding[0] * 2, \
|
||||
lbl_value.height + self.padding[0]
|
||||
|
@ -82,7 +82,7 @@ class MDSlider(ThemableBehavior, Slider):
|
||||
and defaults to `True`.
|
||||
"""
|
||||
|
||||
hint_bg_color = ColorProperty(None)
|
||||
hint_bg_color = ColorProperty([0, 0, 0, 0])
|
||||
"""
|
||||
Hint rectangle color in (r.g.b.a) format.
|
||||
|
||||
|
@ -38,8 +38,8 @@ Example
|
||||
|
||||
from kivy.lang.builder import Builder
|
||||
|
||||
from kivymd.app import MDApp
|
||||
from kivymd.uix.card import MDCard
|
||||
from kivymd.uix.behaviors import RoundedRectangularElevationBehavior
|
||||
|
||||
KV = '''
|
||||
<CardItem>
|
||||
@ -47,6 +47,7 @@ Example
|
||||
height: "86dp"
|
||||
padding: "4dp"
|
||||
radius: 12
|
||||
elevation: 4
|
||||
|
||||
FitImage:
|
||||
source: "avatar.jpg"
|
||||
@ -94,10 +95,8 @@ Example
|
||||
'''
|
||||
|
||||
|
||||
class CardItem(MDCard):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.elevation = 3
|
||||
class CardItem(MDCard, RoundedRectangularElevationBehavior):
|
||||
pass
|
||||
|
||||
|
||||
class Example(MDApp):
|
||||
@ -193,6 +192,7 @@ class MDSliverAppbar(MDBoxLayout, ThemableBehavior):
|
||||
|
||||
from kivymd.uix.card import MDCard
|
||||
from kivymd.uix.toolbar import MDTopAppBar
|
||||
from kivymd.uix.behaviors import RoundedRectangularElevationBehavior
|
||||
|
||||
KV = '''
|
||||
#:import SliverToolbar __main__.SliverToolbar
|
||||
@ -203,6 +203,7 @@ class MDSliverAppbar(MDBoxLayout, ThemableBehavior):
|
||||
height: "86dp"
|
||||
padding: "4dp"
|
||||
radius: 12
|
||||
elevation: 4
|
||||
|
||||
FitImage:
|
||||
source: "avatar.jpg"
|
||||
@ -251,16 +252,13 @@ class MDSliverAppbar(MDBoxLayout, ThemableBehavior):
|
||||
'''
|
||||
|
||||
|
||||
class CardItem(MDCard):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.elevation = 3
|
||||
class CardItem(MDCard, RoundedRectangularElevationBehavior):
|
||||
pass
|
||||
|
||||
|
||||
class SliverToolbar(MDTopAppBar):
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
self.shadow_color = (0, 0, 0, 0)
|
||||
self.type_height = "medium"
|
||||
self.headline_text = "Headline medium"
|
||||
self.left_action_items = [["arrow-left", lambda x: x]]
|
||||
@ -424,7 +422,6 @@ class MDSliverAppbar(MDBoxLayout, ThemableBehavior):
|
||||
# Adding a custom MDTopAppBar object.
|
||||
if issubclass(instance_toolbar_cls.__class__, MDTopAppBar):
|
||||
instance_toolbar_cls.pos_hint = {"top": 1}
|
||||
instance_toolbar_cls.elevation = 0
|
||||
self.ids.float_box.add_widget(instance_toolbar_cls)
|
||||
else:
|
||||
raise MDSliverAppbarException(
|
||||
|
@ -8,7 +8,7 @@
|
||||
padding: "10dp", "10dp", "10dp", "10dp"
|
||||
md_bg_color: "323232" if not root.bg_color else root.bg_color
|
||||
radius: root.radius
|
||||
elevation: 4 if root.padding else 0
|
||||
elevation: 11 if root.padding else 0
|
||||
|
||||
canvas:
|
||||
Color:
|
||||
|
@ -284,6 +284,7 @@ from kivy.properties import (
|
||||
)
|
||||
|
||||
from kivymd import uix_path
|
||||
from kivymd.uix.behaviors import FakeRectangularElevationBehavior
|
||||
from kivymd.uix.button import BaseButton
|
||||
from kivymd.uix.card import MDCard
|
||||
|
||||
@ -293,7 +294,7 @@ with open(
|
||||
Builder.load_string(kv_file.read())
|
||||
|
||||
|
||||
class BaseSnackbar(MDCard):
|
||||
class BaseSnackbar(MDCard, FakeRectangularElevationBehavior):
|
||||
"""
|
||||
:Events:
|
||||
:attr:`on_open`
|
||||
|
@ -38,7 +38,7 @@ Example
|
||||
MDTopAppBar:
|
||||
id: toolbar
|
||||
title: "MDSwiper"
|
||||
elevation: 4
|
||||
elevation: 10
|
||||
pos_hint: {"top": 1}
|
||||
|
||||
MDSwiper:
|
||||
@ -142,7 +142,7 @@ Example
|
||||
MDTopAppBar:
|
||||
id: toolbar
|
||||
title: "MDSwiper"
|
||||
elevation: 4
|
||||
elevation: 10
|
||||
pos_hint: {"top": 1}
|
||||
|
||||
MDSwiper:
|
||||
@ -203,6 +203,7 @@ from kivy.animation import Animation
|
||||
from kivy.clock import Clock
|
||||
from kivy.core.window import Window
|
||||
from kivy.effects.dampedscroll import DampedScrollEffect
|
||||
from kivy.event import EventDispatcher
|
||||
from kivy.lang.builder import Builder
|
||||
from kivy.properties import (
|
||||
BooleanProperty,
|
||||
@ -211,6 +212,7 @@ from kivy.properties import (
|
||||
StringProperty,
|
||||
)
|
||||
from kivy.uix.anchorlayout import AnchorLayout
|
||||
from kivy.uix.boxlayout import BoxLayout
|
||||
from kivy.utils import platform
|
||||
|
||||
from kivymd import uix_path
|
||||
@ -292,7 +294,7 @@ class MDSwiperItem(MDBoxLayout):
|
||||
anim.start(self)
|
||||
|
||||
|
||||
class MDSwiper(MDScrollView):
|
||||
class MDSwiper(MDScrollView, EventDispatcher):
|
||||
items_spacing = NumericProperty("20dp")
|
||||
"""
|
||||
The space between each :class:`MDSwiperItem`.
|
||||
|
@ -79,10 +79,6 @@
|
||||
layout: layout
|
||||
size_hint: 1, None
|
||||
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
|
||||
md_bg_color:
|
||||
self.theme_cls.primary_color \
|
||||
|
@ -944,6 +944,7 @@ from kivy.properties import (
|
||||
from kivy.uix.anchorlayout import AnchorLayout
|
||||
from kivy.uix.behaviors import ToggleButtonBehavior
|
||||
from kivy.uix.scrollview import ScrollView
|
||||
from kivy.uix.widget import Widget
|
||||
from kivy.utils import boundary
|
||||
|
||||
from kivymd import uix_path
|
||||
@ -952,11 +953,11 @@ from kivymd.icon_definitions import md_icons
|
||||
from kivymd.theming import ThemableBehavior, ThemeManager
|
||||
from kivymd.uix.behaviors import (
|
||||
DeclarativeBehavior,
|
||||
FakeRectangularElevationBehavior,
|
||||
RectangularRippleBehavior,
|
||||
SpecificBackgroundColorBehavior,
|
||||
)
|
||||
from kivymd.uix.boxlayout import MDBoxLayout
|
||||
from kivymd.uix.card import MDCard
|
||||
from kivymd.uix.carousel import MDCarousel
|
||||
from kivymd.uix.label import MDLabel
|
||||
|
||||
@ -1023,7 +1024,7 @@ class MDTabsLabel(ToggleButtonBehavior, RectangularRippleBehavior, MDLabel):
|
||||
Clock.schedule_once(self.tab_bar._label_request_indicator_update, 0)
|
||||
|
||||
|
||||
class MDTabsBase:
|
||||
class MDTabsBase(Widget):
|
||||
"""
|
||||
This class allow you to create a tab.
|
||||
You must create a new class that inherits from MDTabsBase.
|
||||
@ -1129,9 +1130,9 @@ class MDTabsBase:
|
||||
This property will affect the Tab's Title Label widget.
|
||||
"""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
def __init__(self, **kwargs):
|
||||
self.tab_label = MDTabsLabel(tab=self)
|
||||
super().__init__(*args, **kwargs)
|
||||
super().__init__(**kwargs)
|
||||
self.bind(
|
||||
icon=self._update_text,
|
||||
title=self._update_text,
|
||||
@ -1272,7 +1273,9 @@ class MDTabsScrollView(ScrollView):
|
||||
_update(self.effect_y, scroll_y)
|
||||
|
||||
|
||||
class MDTabsBar(MDCard):
|
||||
class MDTabsBar(
|
||||
ThemableBehavior, FakeRectangularElevationBehavior, MDBoxLayout
|
||||
):
|
||||
"""
|
||||
This class is just a boxlayout that contains the scroll view for tabs.
|
||||
It is also responsible for resizing the tab shortcut when necessary.
|
||||
@ -1548,43 +1551,13 @@ class MDTabs(
|
||||
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)
|
||||
"""
|
||||
See :attr:`kivymd.uix.behaviors.CommonElevationBehavior.elevation`
|
||||
attribute.
|
||||
Tab value elevation.
|
||||
|
||||
.. seealso::
|
||||
|
||||
`Behaviors/Elevation <https://kivymd.readthedocs.io/en/latest/behaviors/elevation/index.html>`_
|
||||
|
||||
:attr:`elevation` is an :class:`~kivy.properties.NumericProperty`
|
||||
and defaults to `0`.
|
||||
|
@ -487,8 +487,6 @@ class MDTapTargetView(ThemableBehavior, EventDispatcher):
|
||||
_outer_radius = NumericProperty(0)
|
||||
_target_radius = NumericProperty(0)
|
||||
|
||||
__elevation = 0
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
self.ripple_max_dist = dp(90)
|
||||
self.on_outer_radius(self, self.outer_radius)
|
||||
@ -516,89 +514,6 @@ class MDTapTargetView(ThemableBehavior, EventDispatcher):
|
||||
if not self.outer_circle_color:
|
||||
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):
|
||||
setattr(self.widget, "_outer_radius", 0)
|
||||
setattr(self.widget, "_target_radius", 0)
|
||||
@ -612,7 +527,7 @@ class MDTapTargetView(ThemableBehavior, EventDispatcher):
|
||||
|
||||
def _draw_canvas(self):
|
||||
_pos = self._ttv_pos()
|
||||
self.widget.canvas.before.remove_group("ttv_group")
|
||||
self.widget.canvas.before.clear()
|
||||
|
||||
with self.widget.canvas.before:
|
||||
# Outer circle.
|
||||
@ -673,14 +588,34 @@ class MDTapTargetView(ThemableBehavior, EventDispatcher):
|
||||
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):
|
||||
self.widget.canvas.before.remove_group("ttv_group")
|
||||
args[0].stop_all(self.widget)
|
||||
elev = getattr(self.widget, "elevation", None)
|
||||
|
||||
elevation = getattr(self.widget, "elevation", None)
|
||||
if elevation:
|
||||
self.widget.elevation = self.__elevation
|
||||
|
||||
if elev:
|
||||
self._fix_elev()
|
||||
self.dispatch("on_close")
|
||||
|
||||
# Don't forget to unbind the function or it'll mess
|
||||
@ -704,6 +639,16 @@ class MDTapTargetView(ThemableBehavior, EventDispatcher):
|
||||
)
|
||||
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):
|
||||
anim = Animation(
|
||||
d=0.2,
|
||||
@ -739,6 +684,53 @@ class MDTapTargetView(ThemableBehavior, EventDispatcher):
|
||||
setattr(self.widget, "target_ripple_alpha", 1)
|
||||
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):
|
||||
"""
|
||||
This function decides which one to dispatch based on the touch
|
||||
|
9
sbapp/kivymd/uix/templates/rotatewidget/rotatewidget.kv
Normal file
@ -0,0 +1,9 @@
|
||||
<RotateWidget>
|
||||
canvas.before:
|
||||
PushMatrix
|
||||
Rotate:
|
||||
angle: self.rotate_value_angle
|
||||
axis: tuple(self.rotate_value_axis)
|
||||
origin: self.center
|
||||
canvas.after:
|
||||
PopMatrix
|
@ -2,31 +2,127 @@
|
||||
Templates/RotateWidget
|
||||
======================
|
||||
|
||||
.. deprecated:: 1.0.0
|
||||
.. versionadded:: 1.0.0
|
||||
|
||||
.. note:: `RotateWidget` class has been deprecated. Please use
|
||||
`RotateBahavior <https://kivymd.readthedocs.io/en/latest/behaviors/rotate/>`_
|
||||
class instead.
|
||||
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 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",)
|
||||
|
||||
from kivy import Logger
|
||||
import os
|
||||
|
||||
from kivymd.uix.behaviors import RotateBehavior
|
||||
from kivy.lang import Builder
|
||||
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(RotateBehavior):
|
||||
class RotateWidget:
|
||||
"""Base class for controlling the rotate of the widget."""
|
||||
|
||||
rotate_value_angle = NumericProperty(0)
|
||||
"""
|
||||
.. deprecated:: 1.1.0
|
||||
Use :class:`~kivymd.uix.behaviors.rotate_behavior.RotateBehavior`
|
||||
class instead.
|
||||
Property for getting/setting the angle of the rotation.
|
||||
|
||||
:attr:`rotate_value_angle` is an :class:`~kivy.properties.NumericProperty`
|
||||
and defaults to `0`.
|
||||
"""
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
Logger.warning(
|
||||
"KivyMD: "
|
||||
"The `RotateWidget` class has been deprecated. "
|
||||
"Use the `RotateBehavior` class instead."
|
||||
)
|
||||
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.NumericProperty`
|
||||
and defaults to `(0, 0, 1)`.
|
||||
"""
|
||||
|
10
sbapp/kivymd/uix/templates/scalewidget/scalewidget.kv
Normal file
@ -0,0 +1,10 @@
|
||||
<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,33 +2,149 @@
|
||||
Templates/ScaleWidget
|
||||
=====================
|
||||
|
||||
.. deprecated:: 1.1.0
|
||||
.. versionadded:: 1.0.0
|
||||
|
||||
Base class for controlling the scale of the widget.
|
||||
|
||||
.. note:: `ScaleWidget` class has been deprecated. Please use
|
||||
`ScaleBehavior <https://kivymd.readthedocs.io/en/latest/behaviors/scale/>`_
|
||||
class instead.
|
||||
.. note:: See `kivy.graphics.Scale
|
||||
<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 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",)
|
||||
|
||||
from kivy import Logger
|
||||
import os
|
||||
|
||||
from kivymd.uix.behaviors import ScaleBehavior
|
||||
from kivy.lang import Builder
|
||||
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(ScaleBehavior):
|
||||
class ScaleWidget:
|
||||
"""Base class for controlling the scale of the widget."""
|
||||
|
||||
scale_value_x = NumericProperty(1)
|
||||
"""
|
||||
.. deprecated:: 1.1.0
|
||||
Use :class:`~kivymd.uix.behaviors.scale_behavior.ScaleBehavior`
|
||||
class instead.
|
||||
X-axis value.
|
||||
|
||||
:attr:`scale_value_x` is an :class:`~kivy.properties.NumericProperty`
|
||||
and defaults to `1`.
|
||||
"""
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
Logger.warning(
|
||||
"KivyMD: "
|
||||
"The `ScaleWidget` class has been deprecated. "
|
||||
"Use the `ScaleBehavior` class instead."
|
||||
)
|
||||
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`.
|
||||
"""
|
||||
|
19
sbapp/kivymd/uix/templates/stencilwidget/stencilwidget.kv
Normal file
@ -0,0 +1,19 @@
|
||||
<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,33 +2,115 @@
|
||||
Templates/StencilWidget
|
||||
=======================
|
||||
|
||||
.. deprecated:: 1.1.0
|
||||
.. versionadded:: 1.0.0
|
||||
|
||||
Base class for controlling the stencil instructions of the widget.
|
||||
|
||||
.. note:: `StencilWidget` class has been deprecated. Please use
|
||||
`StencilBehavior <https://kivymd.readthedocs.io/en/latest/behaviors/stencil/>`_
|
||||
class instead.
|
||||
.. 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.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",)
|
||||
|
||||
from kivy import Logger
|
||||
import os
|
||||
|
||||
from kivymd.uix.behaviors import StencilBehavior
|
||||
from kivy.lang import Builder
|
||||
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(StencilBehavior):
|
||||
"""
|
||||
.. deprecated:: 1.1.0
|
||||
Use :class:`~kivymd.uix.behaviors.scale_behavior.StencilBehavior`
|
||||
class instead.
|
||||
class StencilWidget:
|
||||
"""Base class for controlling the stencil instructions of the widget"""
|
||||
|
||||
radius = VariableListProperty([0], length=4)
|
||||
"""
|
||||
Canvas radius.
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
Logger.warning(
|
||||
"KivyMD: "
|
||||
"The `StencilWidget` class has been deprecated. "
|
||||
"Use the `StencilBehavior` class instead."
|
||||
)
|
||||
.. 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]`.
|
||||
"""
|
||||
|
@ -1,7 +1,4 @@
|
||||
<MDTextField>
|
||||
input_filter: self.field_filter
|
||||
do_backspace: self.do_backspace
|
||||
|
||||
canvas.before:
|
||||
Clear
|
||||
|
||||
|
@ -14,6 +14,7 @@ Components/TextField
|
||||
`KivyMD` provides the following field classes for use:
|
||||
|
||||
- MDTextField_
|
||||
- MDTextFieldRound_
|
||||
- MDTextFieldRect_
|
||||
|
||||
.. Note:: :class:`~MDTextField` inherited from
|
||||
@ -78,15 +79,15 @@ parameter to `True`:
|
||||
from kivymd.app import MDApp
|
||||
|
||||
KV = '''
|
||||
MDScreen:
|
||||
BoxLayout:
|
||||
padding: "10dp"
|
||||
|
||||
MDTextField:
|
||||
id: text_field_error
|
||||
hint_text: "Helper text on error (press 'Enter')"
|
||||
helper_text: "There will always be a mistake"
|
||||
helper_text_mode: "on_error"
|
||||
pos_hint: {"center_x": .5, "center_y": .5}
|
||||
size_hint_x: .5
|
||||
pos_hint: {"center_y": .5}
|
||||
'''
|
||||
|
||||
|
||||
@ -96,8 +97,6 @@ parameter to `True`:
|
||||
self.screen = Builder.load_string(KV)
|
||||
|
||||
def build(self):
|
||||
self.theme_cls.theme_style = "Dark"
|
||||
self.theme_cls.primary_palette = "Orange"
|
||||
self.screen.ids.text_field_error.bind(
|
||||
on_text_validate=self.set_error_message,
|
||||
on_focus=self.set_error_message,
|
||||
@ -120,7 +119,6 @@ Helper text mode `'on_error'` (with required)
|
||||
|
||||
MDTextField:
|
||||
hint_text: "required = True"
|
||||
text: "required = True"
|
||||
required: True
|
||||
helper_text_mode: "on_error"
|
||||
helper_text: "Enter text"
|
||||
@ -188,7 +186,7 @@ Round mode
|
||||
max_text_length: 15
|
||||
helper_text: "Massage"
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-field-round-mode.gif
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-field-round-mode.png
|
||||
:align: center
|
||||
|
||||
.. MDTextFieldRect:
|
||||
@ -205,7 +203,6 @@ MDTextFieldRect
|
||||
MDTextFieldRect:
|
||||
size_hint: 1, None
|
||||
height: "30dp"
|
||||
background_color: app.theme_cls.bg_normal
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-field-rect.gif
|
||||
:align: center
|
||||
@ -281,17 +278,18 @@ __all__ = ("MDTextField", "MDTextFieldRect")
|
||||
|
||||
import os
|
||||
import re
|
||||
from datetime import date
|
||||
from typing import Union
|
||||
|
||||
from kivy.animation import Animation
|
||||
from kivy.clock import Clock
|
||||
from kivy.lang import Builder
|
||||
from kivy.logger import Logger
|
||||
from kivy.metrics import dp, sp
|
||||
from kivy.properties import (
|
||||
AliasProperty,
|
||||
BooleanProperty,
|
||||
ColorProperty,
|
||||
DictProperty,
|
||||
ListProperty,
|
||||
NumericProperty,
|
||||
ObjectProperty,
|
||||
@ -313,220 +311,6 @@ with open(
|
||||
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):
|
||||
line_anim = BooleanProperty(True)
|
||||
"""
|
||||
@ -599,13 +383,7 @@ class TextfieldLabel(ThemableBehavior, Label):
|
||||
self.font_size = sp(self.theme_cls.font_styles[self.font_style][1])
|
||||
|
||||
|
||||
class MDTextField(
|
||||
DeclarativeBehavior,
|
||||
ThemableBehavior,
|
||||
TextInput,
|
||||
Validator,
|
||||
AutoFormatTelephoneNumber,
|
||||
):
|
||||
class MDTextField(DeclarativeBehavior, ThemableBehavior, TextInput):
|
||||
helper_text = StringProperty()
|
||||
"""
|
||||
Text for ``helper_text`` mode.
|
||||
@ -652,185 +430,17 @@ class MDTextField(
|
||||
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 (static underline line) in (r, g, b, a) or string format.
|
||||
Line color normal (static underline line) in ``rgba`` format.
|
||||
|
||||
.. code-block:: kv
|
||||
|
||||
MDTextField:
|
||||
hint_text: "line_color_normal"
|
||||
line_color_normal: "red"
|
||||
line_color_normal: 1, 0, 1, 1
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-field-line-color-normal.png
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-field-line-color-normal.gif
|
||||
:align: center
|
||||
|
||||
:attr:`line_color_normal` is an :class:`~kivy.properties.ColorProperty`
|
||||
@ -839,13 +449,13 @@ class MDTextField(
|
||||
|
||||
line_color_focus = ColorProperty([0, 0, 0, 0])
|
||||
"""
|
||||
Line color focus (active underline line) in (r, g, b, a) or string format.
|
||||
Line color focus (active underline line) in ``rgba`` format.
|
||||
|
||||
.. code-block:: kv
|
||||
|
||||
MDTextField:
|
||||
hint_text: "line_color_focus"
|
||||
line_color_focus: "red"
|
||||
line_color_focus: 0, 1, 0, 1
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-field-line-color-focus.gif
|
||||
:align: center
|
||||
@ -864,7 +474,7 @@ class MDTextField(
|
||||
|
||||
error_color = ColorProperty([0, 0, 0, 0])
|
||||
"""
|
||||
Error color in (r, g, b, a) or string format for ``required = True``.
|
||||
Error color in ``rgba`` format for ``required = True``.
|
||||
|
||||
:attr:`error_color` is an :class:`~kivy.properties.ColorProperty`
|
||||
and defaults to `[0, 0, 0, 0]`.
|
||||
@ -872,18 +482,7 @@ class MDTextField(
|
||||
|
||||
fill_color_normal = ColorProperty([0, 0, 0, 0])
|
||||
"""
|
||||
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
|
||||
Fill background color in 'fill' mode when text field is out of focus.
|
||||
|
||||
:attr:`fill_color_normal` is an :class:`~kivy.properties.ColorProperty`
|
||||
and defaults to `[0, 0, 0, 0]`.
|
||||
@ -891,18 +490,7 @@ class MDTextField(
|
||||
|
||||
fill_color_focus = ColorProperty([0, 0, 0, 0])
|
||||
"""
|
||||
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
|
||||
Fill background color in 'fill' mode when the text field has focus.
|
||||
|
||||
:attr:`fill_color_focus` is an :class:`~kivy.properties.ColorProperty`
|
||||
and defaults to `[0, 0, 0, 0]`.
|
||||
@ -926,8 +514,7 @@ class MDTextField(
|
||||
|
||||
hint_text_color_normal = ColorProperty([0, 0, 0, 0])
|
||||
"""
|
||||
Hint text color in (r, g, b, a) or string format when text field is out
|
||||
of focus.
|
||||
Hint text color when text field is out of focus.
|
||||
|
||||
.. versionadded:: 1.0.0
|
||||
|
||||
@ -935,9 +522,9 @@ class MDTextField(
|
||||
|
||||
MDTextField:
|
||||
hint_text: "hint_text_color_normal"
|
||||
hint_text_color_normal: "red"
|
||||
hint_text_color_normal: 0, 1, 0, 1
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-field-hint-text-color-normal.png
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-field-hint-text-color-normal.gif
|
||||
:align: center
|
||||
|
||||
:attr:`hint_text_color_normal` is an :class:`~kivy.properties.ColorProperty`
|
||||
@ -946,8 +533,7 @@ class MDTextField(
|
||||
|
||||
hint_text_color_focus = ColorProperty([0, 0, 0, 0])
|
||||
"""
|
||||
Hint text color in (r, g, b, a) or string format when the text field has
|
||||
focus.
|
||||
Hint text color when the text field has focus.
|
||||
|
||||
.. versionadded:: 1.0.0
|
||||
|
||||
@ -955,7 +541,7 @@ class MDTextField(
|
||||
|
||||
MDTextField:
|
||||
hint_text: "hint_text_color_focus"
|
||||
hint_text_color_focus: "red"
|
||||
hint_text_color_focus: 0, 1, 0, 1
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-field-hint-text-color-focus.gif
|
||||
:align: center
|
||||
@ -966,8 +552,7 @@ class MDTextField(
|
||||
|
||||
helper_text_color_normal = ColorProperty([0, 0, 0, 0])
|
||||
"""
|
||||
Helper text color in (r, g, b, a) or string format when text field is out
|
||||
of focus.
|
||||
Helper text color when text field is out of focus.
|
||||
|
||||
.. versionadded:: 1.0.0
|
||||
|
||||
@ -976,7 +561,7 @@ class MDTextField(
|
||||
MDTextField:
|
||||
helper_text: "helper_text_color_normal"
|
||||
helper_text_mode: "persistent"
|
||||
helper_text_color_normal: "red"
|
||||
helper_text_color_normal: 0, 1, 0, 1
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-field-helper-text-color-normal.png
|
||||
:align: center
|
||||
@ -987,8 +572,7 @@ class MDTextField(
|
||||
|
||||
helper_text_color_focus = ColorProperty([0, 0, 0, 0])
|
||||
"""
|
||||
Helper text color in (r, g, b, a) or string format when the text field has
|
||||
focus.
|
||||
Helper text color when the text field has focus.
|
||||
|
||||
.. versionadded:: 1.0.0
|
||||
|
||||
@ -997,7 +581,7 @@ class MDTextField(
|
||||
MDTextField:
|
||||
helper_text: "helper_text_color_focus"
|
||||
helper_text_mode: "persistent"
|
||||
helper_text_color_focus: "red"
|
||||
helper_text_color_focus: 0, 1, 0, 1
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-field-helper-text-color-focus.gif
|
||||
:align: center
|
||||
@ -1008,8 +592,7 @@ class MDTextField(
|
||||
|
||||
icon_right_color_normal = ColorProperty([0, 0, 0, 0])
|
||||
"""
|
||||
Color in (r, g, b, a) or string format of right icon when text field is out
|
||||
of focus.
|
||||
Color of right icon when text field is out of focus.
|
||||
|
||||
.. versionadded:: 1.0.0
|
||||
|
||||
@ -1018,9 +601,9 @@ class MDTextField(
|
||||
MDTextField:
|
||||
icon_right: "language-python"
|
||||
hint_text: "icon_right_color_normal"
|
||||
icon_right_color_normal: "red"
|
||||
icon_right_color_normal: 0, 1, 0, 1
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-field-icon-right-color-normal.png
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-field-icon-right-color-normal.gif
|
||||
:align: center
|
||||
|
||||
:attr:`icon_right_color_normal` is an :class:`~kivy.properties.ColorProperty`
|
||||
@ -1029,8 +612,7 @@ class MDTextField(
|
||||
|
||||
icon_right_color_focus = ColorProperty([0, 0, 0, 0])
|
||||
"""
|
||||
Color in (r, g, b, a) or string format of right icon when the text field
|
||||
has focus.
|
||||
Color of right icon when the text field has focus.
|
||||
|
||||
.. versionadded:: 1.0.0
|
||||
|
||||
@ -1039,7 +621,7 @@ class MDTextField(
|
||||
MDTextField:
|
||||
icon_right: "language-python"
|
||||
hint_text: "icon_right_color_focus"
|
||||
icon_right_color_focus: "red"
|
||||
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
|
||||
@ -1050,30 +632,47 @@ class MDTextField(
|
||||
|
||||
icon_left_color_normal = ColorProperty([0, 0, 0, 0])
|
||||
"""
|
||||
Color in (r, g, b, a) or string format of right icon when text field is out
|
||||
of focus.
|
||||
Color of right icon when text field is out of focus.
|
||||
|
||||
.. 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`
|
||||
and defaults to `[0, 0, 0, 0]`.
|
||||
"""
|
||||
|
||||
icon_left_color_focus = ColorProperty([0, 0, 0, 0])
|
||||
"""
|
||||
Color in (r, g, b, a) or string format of right icon when the text field
|
||||
has focus.
|
||||
Color of right icon when the text field has focus.
|
||||
|
||||
.. 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`
|
||||
and defaults to `[0, 0, 0, 0]`.
|
||||
"""
|
||||
|
||||
max_length_text_color = ColorProperty([0, 0, 0, 0])
|
||||
"""
|
||||
Text color in (r, g, b, a) or string format of the maximum length of
|
||||
characters to be input.
|
||||
Text color of the maximum length of characters to be input.
|
||||
|
||||
.. versionadded:: 1.0.0
|
||||
|
||||
@ -1081,10 +680,10 @@ class MDTextField(
|
||||
|
||||
MDTextField:
|
||||
hint_text: "max_length_text_color"
|
||||
max_length_text_color: "red"
|
||||
max_length_text_color: 0, 1, 0, 1
|
||||
max_text_length: 5
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-field-max-length-text-color.png
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-field-max-length-text-color.gif
|
||||
:align: center
|
||||
|
||||
:attr:`max_length_text_color` is an :class:`~kivy.properties.ColorProperty`
|
||||
@ -1119,7 +718,7 @@ class MDTextField(
|
||||
|
||||
text_color_normal = ColorProperty([0, 0, 0, 0])
|
||||
"""
|
||||
Text color in (r, g, b, a) or string format when text field is out of focus.
|
||||
Text color in ``rgba`` format when text field is out of focus.
|
||||
|
||||
.. versionadded:: 1.0.0
|
||||
|
||||
@ -1127,9 +726,9 @@ class MDTextField(
|
||||
|
||||
MDTextField:
|
||||
hint_text: "text_color_normal"
|
||||
text_color_normal: "red"
|
||||
text_color_normal: 0, 1, 0, 1
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-field-text-color-normal.png
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-field-text-color-normal.gif
|
||||
:align: center
|
||||
|
||||
:attr:`text_color_normal` is an :class:`~kivy.properties.ColorProperty`
|
||||
@ -1138,7 +737,7 @@ class MDTextField(
|
||||
|
||||
text_color_focus = ColorProperty([0, 0, 0, 0])
|
||||
"""
|
||||
Text color in (r, g, b, a) or string format when text field has focus.
|
||||
Text color in ``rgba`` format when text field has focus.
|
||||
|
||||
.. versionadded:: 1.0.0
|
||||
|
||||
@ -1146,7 +745,7 @@ class MDTextField(
|
||||
|
||||
MDTextField:
|
||||
hint_text: "text_color_focus"
|
||||
text_color_focus: "red"
|
||||
text_color_focus: 0, 1, 0, 1
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-field-text-color-focus.gif
|
||||
:align: center
|
||||
@ -1280,8 +879,8 @@ class MDTextField(
|
||||
text=self.set_text,
|
||||
)
|
||||
self.theme_cls.bind(
|
||||
primary_color=self.set_default_colors,
|
||||
theme_style=self.set_default_colors,
|
||||
primary_color=lambda x, y: self.set_default_colors(0, True),
|
||||
theme_style=lambda x, y: self.set_default_colors(0, True),
|
||||
)
|
||||
Clock.schedule_once(self.check_text)
|
||||
|
||||
@ -1331,17 +930,9 @@ class MDTextField(
|
||||
)
|
||||
|
||||
if self.error_color == [0, 0, 0, 0] or updated:
|
||||
self.error_color = (
|
||||
self.theme_cls.error_color
|
||||
if self.error_color == [0, 0, 0, 0]
|
||||
else self.error_color
|
||||
)
|
||||
self.error_color = self.theme_cls.error_color
|
||||
if self.max_length_text_color == [0, 0, 0, 0] or updated:
|
||||
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.max_length_text_color = self.theme_cls.disabled_hint_text_color
|
||||
|
||||
self._hint_text_color = self.hint_text_color_normal
|
||||
self._text_color_normal = self.text_color_normal
|
||||
@ -1510,11 +1101,8 @@ class MDTextField(
|
||||
|
||||
self.text = re.sub("\n", " ", text) if not self.multiline else text
|
||||
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) or self._get_has_error():
|
||||
if self.text and self.max_length_text_color and self._get_has_error():
|
||||
self.error = True
|
||||
if (
|
||||
self.text
|
||||
@ -1713,34 +1301,22 @@ class MDTextField(
|
||||
if value_height >= self.max_height and self.max_height:
|
||||
self.height = self.max_height
|
||||
|
||||
def on_text_color_normal(
|
||||
self, instance_text_field, color: Union[list, str]
|
||||
):
|
||||
def on_text_color_normal(self, instance_text_field, color: list):
|
||||
self._text_color_normal = color
|
||||
|
||||
def on_hint_text_color_normal(
|
||||
self, instance_text_field, color: Union[list, str]
|
||||
):
|
||||
def on_hint_text_color_normal(self, instance_text_field, color: list):
|
||||
self._hint_text_color = color
|
||||
|
||||
def on_helper_text_color_normal(
|
||||
self, instance_text_field, color: Union[list, str]
|
||||
):
|
||||
def on_helper_text_color_normal(self, instance_text_field, color: list):
|
||||
self._helper_text_color = color
|
||||
|
||||
def on_icon_right_color_normal(
|
||||
self, instance_text_field, color: Union[list, str]
|
||||
):
|
||||
def on_icon_right_color_normal(self, instance_text_field, color: list):
|
||||
self._icon_right_color = color
|
||||
|
||||
def on_line_color_normal(
|
||||
self, instance_text_field, color: Union[list, str]
|
||||
):
|
||||
def on_line_color_normal(self, instance_text_field, color: list):
|
||||
self._line_color_normal = color
|
||||
|
||||
def on_max_length_text_color(
|
||||
self, instance_text_field, color: Union[list, str]
|
||||
):
|
||||
def on_max_length_text_color(self, instance_text_field, color: list):
|
||||
self._max_length_text_color = color
|
||||
|
||||
def _set_color(self, attr_name: str, color: str, updated: bool) -> None:
|
||||
@ -1777,13 +1353,6 @@ class MDTextField(
|
||||
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:
|
||||
has_error = True
|
||||
else:
|
||||
@ -1798,12 +1367,9 @@ class MDTextField(
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
from kivy.core.window import Window
|
||||
from kivy.lang import Builder
|
||||
from kivy.uix.textinput import TextInput
|
||||
|
||||
Window.size = (800, 750)
|
||||
|
||||
from kivymd.app import MDApp
|
||||
|
||||
KV = """
|
||||
@ -1819,53 +1385,41 @@ MDScreen:
|
||||
|
||||
MDTextField:
|
||||
hint_text: "Label"
|
||||
helper_text: "Error message"
|
||||
helper_text: "Error massage"
|
||||
mode: "rectangle"
|
||||
max_text_length: 5
|
||||
|
||||
MDTextField:
|
||||
icon_left: "git"
|
||||
hint_text: "Label"
|
||||
helper_text: "Error message"
|
||||
helper_text: "Error massage"
|
||||
mode: "rectangle"
|
||||
|
||||
MDTextField:
|
||||
icon_left: "git"
|
||||
hint_text: "Label"
|
||||
helper_text: "Error message"
|
||||
helper_text: "Error massage"
|
||||
mode: "fill"
|
||||
|
||||
MDTextField:
|
||||
hint_text: "Label"
|
||||
helper_text: "Error message"
|
||||
helper_text: "Error massage"
|
||||
mode: "fill"
|
||||
|
||||
MDTextField:
|
||||
hint_text: "Label"
|
||||
helper_text: "Error message"
|
||||
helper_text: "Error massage"
|
||||
|
||||
MDTextField:
|
||||
icon_left: "git"
|
||||
hint_text: "Label"
|
||||
helper_text: "Error message"
|
||||
helper_text: "Error massage"
|
||||
|
||||
MDTextField:
|
||||
hint_text: "Round mode"
|
||||
mode: "round"
|
||||
max_text_length: 15
|
||||
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"
|
||||
helper_text: "Massage"
|
||||
|
||||
MDFlatButton:
|
||||
text: "SET TEXT"
|
||||
@ -1875,8 +1429,6 @@ MDScreen:
|
||||
|
||||
class Test(MDApp):
|
||||
def build(self):
|
||||
self.theme_cls.theme_style = "Dark"
|
||||
self.theme_cls.primary_palette = "Orange"
|
||||
return Builder.load_string(KV)
|
||||
|
||||
def set_text(self):
|
||||
|
@ -121,8 +121,8 @@ Shadow elevation control
|
||||
.. code-block:: kv
|
||||
|
||||
MDTopAppBar:
|
||||
title: "Elevation 4"
|
||||
elevation: 4
|
||||
title: "Elevation 10"
|
||||
elevation: 10
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/toolbar-7.png
|
||||
:align: center
|
||||
@ -327,7 +327,7 @@ Material design 3 style
|
||||
:align: center
|
||||
"""
|
||||
|
||||
__all__ = ("MDTopAppBar", "MDBottomAppBar", "ActionTopAppBarButton")
|
||||
__all__ = ("MDTopAppBar", "MDBottomAppBar")
|
||||
|
||||
import os
|
||||
from math import cos, radians, sin
|
||||
@ -337,8 +337,10 @@ from kivy.animation import Animation
|
||||
from kivy.clock import Clock
|
||||
from kivy.core.window import Window
|
||||
from kivy.lang import Builder
|
||||
from kivy.logger import Logger
|
||||
from kivy.metrics import dp
|
||||
from kivy.properties import (
|
||||
AliasProperty,
|
||||
BooleanProperty,
|
||||
ColorProperty,
|
||||
ListProperty,
|
||||
@ -354,15 +356,15 @@ from kivymd import uix_path
|
||||
from kivymd.color_definitions import text_colors
|
||||
from kivymd.theming import ThemableBehavior
|
||||
from kivymd.uix.behaviors import (
|
||||
CommonElevationBehavior,
|
||||
DeclarativeBehavior,
|
||||
ScaleBehavior,
|
||||
FakeRectangularElevationBehavior,
|
||||
SpecificBackgroundColorBehavior,
|
||||
)
|
||||
from kivymd.uix.button import MDFloatingActionButton, MDIconButton
|
||||
from kivymd.uix.controllers import WindowController
|
||||
from kivymd.uix.list import OneLineIconListItem
|
||||
from kivymd.uix.menu import MDDropdownMenu
|
||||
from kivymd.uix.templates import ScaleWidget
|
||||
from kivymd.uix.tooltip import MDTooltip
|
||||
from kivymd.utils.set_bars_colors import set_bars_colors
|
||||
|
||||
@ -372,7 +374,7 @@ with open(
|
||||
Builder.load_string(kv_file.read())
|
||||
|
||||
|
||||
class ActionBottomAppBarButton(MDFloatingActionButton, ScaleBehavior):
|
||||
class ActionBottomAppBarButton(MDFloatingActionButton, ScaleWidget):
|
||||
"""
|
||||
Implements a floating action button (FAB) for a toolbar with type 'bottom'.
|
||||
"""
|
||||
@ -407,11 +409,11 @@ class OverFlowMenuItem(OneLineIconListItem):
|
||||
|
||||
class NotchedBox(
|
||||
ThemableBehavior,
|
||||
CommonElevationBehavior,
|
||||
FakeRectangularElevationBehavior,
|
||||
SpecificBackgroundColorBehavior,
|
||||
BoxLayout,
|
||||
):
|
||||
elevation = NumericProperty(4)
|
||||
elevation = NumericProperty(6)
|
||||
notch_radius = NumericProperty()
|
||||
notch_center_x = NumericProperty("100dp")
|
||||
|
||||
@ -959,10 +961,8 @@ class MDTopAppBar(DeclarativeBehavior, NotchedBox, WindowController):
|
||||
self.icon_color = self.theme_cls.primary_color
|
||||
|
||||
self.bind(specific_text_color=self.update_action_bar_text_colors)
|
||||
self.theme_cls.bind(
|
||||
material_style=self.update_bar_height,
|
||||
primary_palette=self.update_md_bg_color,
|
||||
)
|
||||
self.theme_cls.bind(material_style=self.update_bar_height)
|
||||
self.theme_cls.bind(primary_palette=self.update_md_bg_color)
|
||||
|
||||
Clock.schedule_once(
|
||||
lambda x: self.on_left_action_items(0, self.left_action_items)
|
||||
@ -1103,7 +1103,6 @@ class MDTopAppBar(DeclarativeBehavior, NotchedBox, WindowController):
|
||||
+ self.theme_cls.standard_increment / 2
|
||||
+ self._shift
|
||||
)
|
||||
self.shadow_offset = [0, 30]
|
||||
self.on_mode(None, self.mode)
|
||||
|
||||
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)
|
||||
|
||||
def on_show(self) -> None:
|
||||
"""Default display event handler."""
|
||||
"""Default dismiss event handler."""
|
||||
|
||||
def on_dismiss(self) -> None:
|
||||
"""
|
||||
|
@ -35,9 +35,7 @@ __all__ = (
|
||||
"MDTransitionBase",
|
||||
)
|
||||
|
||||
from kivy import Logger
|
||||
from kivy.animation import Animation, AnimationTransition
|
||||
from kivy.properties import DictProperty
|
||||
from kivy.uix.screenmanager import (
|
||||
ScreenManagerException,
|
||||
SlideTransition,
|
||||
@ -45,41 +43,13 @@ from kivy.uix.screenmanager import (
|
||||
TransitionBase,
|
||||
)
|
||||
|
||||
from kivymd.uix.hero import MDHeroFrom, MDHeroTo
|
||||
from kivymd.uix.screenmanager import MDScreenManager
|
||||
|
||||
|
||||
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"
|
||||
# Collection of child widgets of all 'MDHeroFrom' widgets that are
|
||||
# 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()
|
||||
hero_widget = None
|
||||
hero_from_widget = None # kivymd.uix.hero.MDHeroFrom object
|
||||
|
||||
def start(self, instance_screen_manager: MDScreenManager) -> None:
|
||||
super().start(instance_screen_manager)
|
||||
@ -89,160 +59,67 @@ class MDTransitionBase(TransitionBase):
|
||||
]()
|
||||
|
||||
def animated_hero_in(self) -> None:
|
||||
"""Animates the flight of heroes from screen **A** to screen **B**."""
|
||||
if self.manager._heroes_data and self.manager.current_hero:
|
||||
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)
|
||||
|
||||
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:
|
||||
self._check_widget_properties(hero_from_widget)
|
||||
self.hero_widget.pos = self.screen_out.to_widget(
|
||||
*self.hero_from_widget.to_window(*self.hero_from_widget.pos)
|
||||
)
|
||||
self.hero_widget.size = self.hero_from_widget.size
|
||||
self.manager.get_root_window().add_widget(self.hero_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)
|
||||
)
|
||||
hero_widget.size = hero_from_widget.size
|
||||
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(
|
||||
size=hero_to_widget.size,
|
||||
d=self.duration,
|
||||
pos=hero_to_widget.pos,
|
||||
).start(hero_widget)
|
||||
hero_from_widget.dispatch(
|
||||
"on_transform_in",
|
||||
hero_widget,
|
||||
self.duration,
|
||||
)
|
||||
Animation(
|
||||
size=self.screen_in.hero_to.size,
|
||||
d=self.duration,
|
||||
pos=self.screen_in.hero_to.pos,
|
||||
).start(self.hero_widget)
|
||||
self.hero_from_widget.dispatch(
|
||||
"on_transform_in", self.hero_widget, self.duration
|
||||
)
|
||||
|
||||
def animated_hero_out(self) -> None:
|
||||
"""Animates the flight of heroes from screen **B** to screen **A**."""
|
||||
if self.manager._heroes_data and self.manager.current_hero:
|
||||
self.screen_out.hero_to.remove_widget(self.hero_widget)
|
||||
self.manager.get_root_window().add_widget(self.hero_widget)
|
||||
|
||||
if (
|
||||
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(
|
||||
pos=self.screen_in.to_widget(
|
||||
*hero_from_widget.to_window(
|
||||
*hero_from_widget.pos
|
||||
)
|
||||
),
|
||||
size=hero_from_widget.size,
|
||||
d=self.duration,
|
||||
).start(
|
||||
self._hero_from_widget_children[
|
||||
hero_from_widget.tag
|
||||
]
|
||||
)
|
||||
self.hero_from_widget.dispatch(
|
||||
"on_transform_out", self.hero_widget, self.duration
|
||||
)
|
||||
Animation(
|
||||
pos=self.screen_in.to_widget(
|
||||
*self.hero_from_widget.to_window(*self.hero_from_widget.pos)
|
||||
),
|
||||
size=self.hero_from_widget.size,
|
||||
d=self.duration,
|
||||
).start(self.hero_widget)
|
||||
|
||||
def on_complete(self) -> None:
|
||||
"""
|
||||
Override method.
|
||||
See :attr:`kivy.uix.screenmanager.TransitionBase.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":
|
||||
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:
|
||||
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)
|
||||
|
||||
# Checks the attributes for the 'self.screen_in' screen.
|
||||
# Called from the animated_hero_in method.
|
||||
def _check_widget_properties(self, hero_from_widget: MDHeroFrom):
|
||||
if not self.screen_in.heroes_to:
|
||||
def _check_widget_properties(self):
|
||||
if not self.screen_in.hero_to:
|
||||
raise Exception(
|
||||
f"The `heroes_to` attribute is not specified for screen "
|
||||
f"{self.screen_in}"
|
||||
f"The `hero_to` attribute is not specified for screen {self.screen_in}"
|
||||
)
|
||||
# The 'MDHeroFrom' widget allows you to place only one widget in
|
||||
# itself.
|
||||
if len(hero_from_widget.children) > 1:
|
||||
if len(self.hero_from_widget.children) > 1:
|
||||
raise Exception(
|
||||
f"{hero_from_widget.__class__} accept only one widget"
|
||||
f"{self.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):
|
||||
pass
|
||||
|
@ -36,13 +36,11 @@ MDWidget
|
||||
|
||||
__all__ = ("MDWidget",)
|
||||
|
||||
from kivy.uix.widget import Widget
|
||||
|
||||
from kivymd.uix import MDAdaptiveWidget
|
||||
from kivymd.uix.behaviors import DeclarativeBehavior
|
||||
|
||||
|
||||
class MDWidget(DeclarativeBehavior, MDAdaptiveWidget, Widget):
|
||||
class MDWidget(DeclarativeBehavior, MDAdaptiveWidget):
|
||||
"""
|
||||
See :class:`~kivy.uix.Widget` class documentation for more information.
|
||||
|
||||
|