Updated kivymd
|
@ -9,23 +9,16 @@ Is a collection of Material Design compliant widgets for use with,
|
|||
a framework for cross-platform, touch-enabled graphical applications.
|
||||
The project's goal is to approximate Google's `Material Design spec
|
||||
<https://material.io/design/introduction>`_ as close as possible without
|
||||
sacrificing ease of use or application performance.
|
||||
sacrificing ease of use.
|
||||
|
||||
This library is a fork of the `KivyMD project
|
||||
<https://gitlab.com/kivymd/KivyMD>`_ the author of which stopped supporting
|
||||
this project three years ago. We found the strength and brought this project
|
||||
to a new level. Currently we're in **beta** status, so things are changing
|
||||
all the time and we cannot promise any kind of API stability.
|
||||
However it is safe to vendor now and make use of what's currently available.
|
||||
<https://gitlab.com/kivymd/KivyMD>`_. We found the strength and brought this
|
||||
project to a new level.
|
||||
|
||||
Join the project! Just fork the project, branch out and submit a pull request
|
||||
when your patch is ready. If any changes are necessary, we'll guide you
|
||||
through the steps that need to be done via PR comments or access to your for
|
||||
may be requested to outright submit them. If you wish to become a project
|
||||
developer (permission to create branches on the project without forking for
|
||||
easier collaboration), have at least one PR approved and ask for it.
|
||||
If you contribute regularly to the project the role may be offered to you
|
||||
without asking too.
|
||||
If you wish to become a project developer (permission to create branches on the
|
||||
project without forking for easier collaboration), have at least one PR
|
||||
approved and ask for it. If you contribute regularly to the project the role
|
||||
may be offered to you without asking too.
|
||||
"""
|
||||
|
||||
import os
|
||||
|
@ -33,7 +26,7 @@ import os
|
|||
import kivy
|
||||
from kivy.logger import Logger
|
||||
|
||||
__version__ = "1.0.0.dev0"
|
||||
__version__ = "1.1.0.dev0"
|
||||
"""KivyMD version."""
|
||||
|
||||
release = False
|
||||
|
@ -56,6 +49,9 @@ 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 "")
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
# THIS FILE IS GENERATED FROM KIVYMD SETUP.PY
|
||||
__version__ = '1.0.0.dev0'
|
||||
__hash__ = '68ec8626a93b0e7f69e48d9755c4af70028f66a2'
|
||||
__short_hash__ = '68ec862'
|
||||
__date__ = '2022-07-07'
|
|
@ -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
|
||||
from kivy.properties import ObjectProperty, StringProperty
|
||||
|
||||
from kivymd.theming import ThemeManager
|
||||
|
||||
|
@ -71,6 +71,16 @@ 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(text=name_tab)
|
||||
tab = Tab(title=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],
|
||||
"text": value_color,
|
||||
"title": value_color,
|
||||
}
|
||||
)
|
||||
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
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);
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
#ifdef GL_ES
|
||||
precision highp float;
|
||||
#endif
|
||||
|
||||
uniform vec4 resolution;
|
||||
uniform vec4 mouse;
|
||||
uniform vec2 size;
|
||||
uniform vec4 shadow_radius;
|
||||
uniform float shadow_softness;
|
||||
uniform vec4 shadow_color;
|
|
@ -0,0 +1,10 @@
|
|||
vec2 gfc(in vec4 fc) {
|
||||
vec2 canvas_pos = resolution.zw;
|
||||
vec2 uv = fc.xy;
|
||||
uv.y -= canvas_pos.y;
|
||||
return uv;
|
||||
}
|
||||
|
||||
void main(void) {
|
||||
mainImage(gl_FragColor, gfc(gl_FragCoord));
|
||||
}
|
|
@ -5,11 +5,15 @@ Register KivyMD widgets to use without import.
|
|||
from kivy.factory import Factory
|
||||
|
||||
register = Factory.register
|
||||
register("MDScrollView", module="kivymd.uix.scrollview")
|
||||
register("MDRecycleView", module="kivymd.uix.recycleview")
|
||||
register("MDResponsiveLayout", module="kivymd.uix.responsivelayout")
|
||||
register("MDSegmentedControl", module="kivymd.uix.segmentedcontrol")
|
||||
register("MDSegmentedControlItem", module="kivymd.uix.segmentedcontrol")
|
||||
register("MDSliverAppbar", module="kivymd.uix.sliverappbar")
|
||||
register("MDSliverAppbarContent", module="kivymd.uix.sliverappbar")
|
||||
register("MDSliverAppbarHeader", module="kivymd.uix.sliverappbar")
|
||||
register("MDNavigationRailItem", module="kivymd.uix.navigationrail")
|
||||
register("MDNavigationRail", module="kivymd.uix.navigationrail")
|
||||
register("MDNavigationRailFabButton", module="kivymd.uix.navigationrail")
|
||||
register("MDNavigationRailMenuButton", module="kivymd.uix.navigationrail")
|
||||
|
@ -29,7 +33,7 @@ register("MDExpansionPanel", module="kivymd.uix.expansionpanel")
|
|||
register("MDExpansionPanelOneLine", module="kivymd.uix.expansionpanel")
|
||||
register("MDExpansionPanelTwoLine", module="kivymd.uix.expansionpanel")
|
||||
register("MDExpansionPanelThreeLine", module="kivymd.uix.expansionpanel")
|
||||
register("FitImage", module="kivymd.utils.fitimage")
|
||||
register("FitImage", module="kivymd.uix.fitimage")
|
||||
register("MDBackdrop", module="kivymd.uix.backdrop")
|
||||
register("MDBanner", module="kivymd.uix.banner")
|
||||
register("MDTooltip", module="kivymd.uix.tooltip")
|
||||
|
@ -54,10 +58,7 @@ register("MDCard", module="kivymd.uix.card")
|
|||
register("MDSeparator", module="kivymd.uix.card")
|
||||
register("MDSelectionList", module="kivymd.uix.selection")
|
||||
register("MDChip", module="kivymd.uix.chip")
|
||||
register("MDChooseChip", module="kivymd.uix.chip")
|
||||
register("MDSmartTile", module="kivymd.uix.imagelist")
|
||||
register("SmartTileWithLabel", module="kivymd.uix.imagelist")
|
||||
register("SmartTileWithStar", module="kivymd.uix.imagelist")
|
||||
register("MDLabel", module="kivymd.uix.label")
|
||||
register("MDIcon", module="kivymd.uix.label")
|
||||
register("MDList", module="kivymd.uix.list")
|
||||
|
@ -65,7 +66,6 @@ register("ILeftBody", module="kivymd.uix.list")
|
|||
register("ILeftBodyTouch", module="kivymd.uix.list")
|
||||
register("IRightBody", module="kivymd.uix.list")
|
||||
register("IRightBodyTouch", module="kivymd.uix.list")
|
||||
register("ContainerSupport", module="kivymd.uix.list")
|
||||
register("OneLineListItem", module="kivymd.uix.list")
|
||||
register("TwoLineListItem", module="kivymd.uix.list")
|
||||
register("ThreeLineListItem", module="kivymd.uix.list")
|
||||
|
@ -99,9 +99,7 @@ register("MDSlider", module="kivymd.uix.slider")
|
|||
register("MDSpinner", module="kivymd.uix.spinner")
|
||||
register("MDTabs", module="kivymd.uix.tab")
|
||||
register("MDTextField", module="kivymd.uix.textfield")
|
||||
register("MDTextFieldRound", module="kivymd.uix.textfield")
|
||||
register("MDTextFieldRect", module="kivymd.uix.textfield")
|
||||
register("MDToolbar", module="kivymd.uix.toolbar")
|
||||
register("MDTopAppBar", module="kivymd.uix.toolbar")
|
||||
register("MDBottomAppBar", module="kivymd.uix.toolbar")
|
||||
register("MDDropDownItem", module="kivymd.uix.dropdownitem")
|
||||
|
|
|
@ -12,7 +12,7 @@ Themes/Icon Definitions
|
|||
List of icons from materialdesignicons.com. These expanded material design
|
||||
icons are maintained by Austin Andrews (Templarian on Github).
|
||||
|
||||
LAST UPDATED: Version 6.9.96
|
||||
LAST UPDATED: Version 7.0.96
|
||||
|
||||
To preview the icons and their names, you can use the following application:
|
||||
----------------------------------------------------------------------------
|
||||
|
@ -154,6 +154,8 @@ md_icons = {
|
|||
"account-box-outline": "\U000F0007",
|
||||
"account-cancel": "\U000F12DF",
|
||||
"account-cancel-outline": "\U000F12E0",
|
||||
"account-card": "\U000F1BA4",
|
||||
"account-card-outline": "\U000F1BA5",
|
||||
"account-cash": "\U000F1097",
|
||||
"account-cash-outline": "\U000F1098",
|
||||
"account-check": "\U000F0008",
|
||||
|
@ -171,6 +173,8 @@ md_icons = {
|
|||
"account-convert-outline": "\U000F1301",
|
||||
"account-cowboy-hat": "\U000F0E9B",
|
||||
"account-cowboy-hat-outline": "\U000F17F3",
|
||||
"account-credit-card": "\U000F1BA6",
|
||||
"account-credit-card-outline": "\U000F1BA7",
|
||||
"account-details": "\U000F0631",
|
||||
"account-details-outline": "\U000F1372",
|
||||
"account-edit": "\U000F06BC",
|
||||
|
@ -260,6 +264,7 @@ md_icons = {
|
|||
"air-humidifier": "\U000F1099",
|
||||
"air-humidifier-off": "\U000F1466",
|
||||
"air-purifier": "\U000F0D44",
|
||||
"air-purifier-off": "\U000F1B57",
|
||||
"airbag": "\U000F0BE9",
|
||||
"airballoon": "\U000F001C",
|
||||
"airballoon-outline": "\U000F100B",
|
||||
|
@ -480,7 +485,6 @@ md_icons = {
|
|||
"amplifier-off": "\U000F11B5",
|
||||
"anchor": "\U000F0031",
|
||||
"android": "\U000F0032",
|
||||
"android-messages": "\U000F0D45",
|
||||
"android-studio": "\U000F0034",
|
||||
"angle-acute": "\U000F0937",
|
||||
"angle-obtuse": "\U000F0938",
|
||||
|
@ -745,6 +749,7 @@ md_icons = {
|
|||
"arrow-up-thin": "\U000F19B2",
|
||||
"arrow-up-thin-circle-outline": "\U000F1597",
|
||||
"arrow-vertical-lock": "\U000F115C",
|
||||
"artboard": "\U000F1B9A",
|
||||
"artstation": "\U000F0B5B",
|
||||
"aspect-ratio": "\U000F0A24",
|
||||
"assistant": "\U000F0064",
|
||||
|
@ -762,6 +767,7 @@ md_icons = {
|
|||
"attachment-off": "\U000F1AC3",
|
||||
"attachment-plus": "\U000F1AC4",
|
||||
"attachment-remove": "\U000F1AC5",
|
||||
"atv": "\U000F1B70",
|
||||
"audio-input-rca": "\U000F186B",
|
||||
"audio-input-stereo-minijack": "\U000F186C",
|
||||
"audio-input-xlr": "\U000F186D",
|
||||
|
@ -774,6 +780,8 @@ md_icons = {
|
|||
"autorenew": "\U000F006A",
|
||||
"autorenew-off": "\U000F19E7",
|
||||
"av-timer": "\U000F006B",
|
||||
"awning": "\U000F1B87",
|
||||
"awning-outline": "\U000F1B88",
|
||||
"aws": "\U000F0E0F",
|
||||
"axe": "\U000F08C8",
|
||||
"axe-battle": "\U000F1842",
|
||||
|
@ -987,6 +995,7 @@ md_icons = {
|
|||
"beaker-remove": "\U000F1233",
|
||||
"beaker-remove-outline": "\U000F1234",
|
||||
"bed": "\U000F02E3",
|
||||
"bed-clock": "\U000F1B94",
|
||||
"bed-double": "\U000F0FD4",
|
||||
"bed-double-outline": "\U000F0FD3",
|
||||
"bed-empty": "\U000F08A0",
|
||||
|
@ -1148,10 +1157,11 @@ md_icons = {
|
|||
"book-sync": "\U000F169C",
|
||||
"book-sync-outline": "\U000F16C8",
|
||||
"book-variant": "\U000F00BF",
|
||||
"book-variant-multiple": "\U000F00BC",
|
||||
"bookmark": "\U000F00C0",
|
||||
"bookmark-box": "\U000F1B75",
|
||||
"bookmark-box-multiple": "\U000F196C",
|
||||
"bookmark-box-multiple-outline": "\U000F196D",
|
||||
"bookmark-box-outline": "\U000F1B76",
|
||||
"bookmark-check": "\U000F00C1",
|
||||
"bookmark-check-outline": "\U000F137B",
|
||||
"bookmark-minus": "\U000F09CC",
|
||||
|
@ -1339,8 +1349,11 @@ md_icons = {
|
|||
"calendar-account": "\U000F0ED7",
|
||||
"calendar-account-outline": "\U000F0ED8",
|
||||
"calendar-alert": "\U000F0A31",
|
||||
"calendar-alert-outline": "\U000F1B62",
|
||||
"calendar-arrow-left": "\U000F1134",
|
||||
"calendar-arrow-right": "\U000F1135",
|
||||
"calendar-badge": "\U000F1B9D",
|
||||
"calendar-badge-outline": "\U000F1B9E",
|
||||
"calendar-blank": "\U000F00EE",
|
||||
"calendar-blank-multiple": "\U000F1073",
|
||||
"calendar-blank-outline": "\U000F0B66",
|
||||
|
@ -1349,26 +1362,40 @@ md_icons = {
|
|||
"calendar-clock": "\U000F00F0",
|
||||
"calendar-clock-outline": "\U000F16E1",
|
||||
"calendar-collapse-horizontal": "\U000F189D",
|
||||
"calendar-collapse-horizontal-outline": "\U000F1B63",
|
||||
"calendar-cursor": "\U000F157B",
|
||||
"calendar-cursor-outline": "\U000F1B64",
|
||||
"calendar-edit": "\U000F08A7",
|
||||
"calendar-edit-outline": "\U000F1B65",
|
||||
"calendar-end": "\U000F166C",
|
||||
"calendar-end-outline": "\U000F1B66",
|
||||
"calendar-expand-horizontal": "\U000F189E",
|
||||
"calendar-expand-horizontal-outline": "\U000F1B67",
|
||||
"calendar-export": "\U000F0B24",
|
||||
"calendar-export-outline": "\U000F1B68",
|
||||
"calendar-filter": "\U000F1A32",
|
||||
"calendar-filter-outline": "\U000F1A33",
|
||||
"calendar-heart": "\U000F09D2",
|
||||
"calendar-heart-outline": "\U000F1B69",
|
||||
"calendar-import": "\U000F0B25",
|
||||
"calendar-import-outline": "\U000F1B6A",
|
||||
"calendar-lock": "\U000F1641",
|
||||
"calendar-lock-open": "\U000F1B5B",
|
||||
"calendar-lock-open-outline": "\U000F1B5C",
|
||||
"calendar-lock-outline": "\U000F1642",
|
||||
"calendar-minus": "\U000F0D5C",
|
||||
"calendar-minus-outline": "\U000F1B6B",
|
||||
"calendar-month": "\U000F0E17",
|
||||
"calendar-month-outline": "\U000F0E18",
|
||||
"calendar-multiple": "\U000F00F1",
|
||||
"calendar-multiple-check": "\U000F00F2",
|
||||
"calendar-multiselect": "\U000F0A32",
|
||||
"calendar-multiselect-outline": "\U000F1B55",
|
||||
"calendar-outline": "\U000F0B67",
|
||||
"calendar-plus": "\U000F00F3",
|
||||
"calendar-plus-outline": "\U000F1B6C",
|
||||
"calendar-question": "\U000F0692",
|
||||
"calendar-question-outline": "\U000F1B6D",
|
||||
"calendar-range": "\U000F0679",
|
||||
"calendar-range-outline": "\U000F0B68",
|
||||
"calendar-refresh": "\U000F01E1",
|
||||
|
@ -1376,9 +1403,11 @@ md_icons = {
|
|||
"calendar-remove": "\U000F00F4",
|
||||
"calendar-remove-outline": "\U000F0C45",
|
||||
"calendar-search": "\U000F094C",
|
||||
"calendar-search-outline": "\U000F1B6E",
|
||||
"calendar-star": "\U000F09D3",
|
||||
"calendar-star-outline": "\U000F1B53",
|
||||
"calendar-start": "\U000F166D",
|
||||
"calendar-start-outline": "\U000F1B6F",
|
||||
"calendar-sync": "\U000F0E8E",
|
||||
"calendar-sync-outline": "\U000F0E8F",
|
||||
"calendar-text": "\U000F00F5",
|
||||
|
@ -1496,6 +1525,8 @@ md_icons = {
|
|||
"car-outline": "\U000F14ED",
|
||||
"car-parking-lights": "\U000F0D63",
|
||||
"car-pickup": "\U000F07AA",
|
||||
"car-search": "\U000F1B8D",
|
||||
"car-search-outline": "\U000F1B8E",
|
||||
"car-seat": "\U000F0FA4",
|
||||
"car-seat-cooler": "\U000F0FA5",
|
||||
"car-seat-heater": "\U000F0FA6",
|
||||
|
@ -1584,6 +1615,7 @@ md_icons = {
|
|||
"cart-minus": "\U000F0D68",
|
||||
"cart-off": "\U000F066B",
|
||||
"cart-outline": "\U000F0111",
|
||||
"cart-percent": "\U000F1BAE",
|
||||
"cart-plus": "\U000F0112",
|
||||
"cart-remove": "\U000F0D69",
|
||||
"cart-variant": "\U000F15EB",
|
||||
|
@ -1969,6 +2001,7 @@ md_icons = {
|
|||
"cloud-tags": "\U000F07B6",
|
||||
"cloud-upload": "\U000F0167",
|
||||
"cloud-upload-outline": "\U000F0B7E",
|
||||
"clouds": "\U000F1B95",
|
||||
"clover": "\U000F0816",
|
||||
"coach-lamp": "\U000F1020",
|
||||
"coach-lamp-variant": "\U000F1A37",
|
||||
|
@ -2128,8 +2161,10 @@ md_icons = {
|
|||
"contrast": "\U000F0195",
|
||||
"contrast-box": "\U000F0196",
|
||||
"contrast-circle": "\U000F0197",
|
||||
"controller": "\U000F02B4",
|
||||
"controller-classic": "\U000F0B82",
|
||||
"controller-classic-outline": "\U000F0B83",
|
||||
"controller-off": "\U000F02B5",
|
||||
"cookie": "\U000F0198",
|
||||
"cookie-alert": "\U000F16D0",
|
||||
"cookie-alert-outline": "\U000F16D1",
|
||||
|
@ -2278,6 +2313,7 @@ md_icons = {
|
|||
"currency-sign": "\U000F07BE",
|
||||
"currency-try": "\U000F01B2",
|
||||
"currency-twd": "\U000F07BF",
|
||||
"currency-uah": "\U000F1B9B",
|
||||
"currency-usd": "\U000F01C1",
|
||||
"currency-usd-off": "\U000F067A",
|
||||
"current-ac": "\U000F1480",
|
||||
|
@ -2391,8 +2427,6 @@ md_icons = {
|
|||
"desk-lamp-on": "\U000F1B20",
|
||||
"deskphone": "\U000F01C3",
|
||||
"desktop-classic": "\U000F07C0",
|
||||
"desktop-mac": "\U000F01C4",
|
||||
"desktop-mac-dashboard": "\U000F09E8",
|
||||
"desktop-tower": "\U000F01C5",
|
||||
"desktop-tower-monitor": "\U000F0AAB",
|
||||
"details": "\U000F01C6",
|
||||
|
@ -2442,7 +2476,6 @@ md_icons = {
|
|||
"disc": "\U000F05EE",
|
||||
"disc-alert": "\U000F01D1",
|
||||
"disc-player": "\U000F0960",
|
||||
"discord": "\U000F066F",
|
||||
"dishwasher": "\U000F0AAC",
|
||||
"dishwasher-alert": "\U000F11B8",
|
||||
"dishwasher-off": "\U000F11B9",
|
||||
|
@ -2457,8 +2490,9 @@ md_icons = {
|
|||
"diving": "\U000F1977",
|
||||
"diving-flippers": "\U000F0DBF",
|
||||
"diving-helmet": "\U000F0DC0",
|
||||
"diving-scuba": "\U000F0DC1",
|
||||
"diving-scuba": "\U000F1B77",
|
||||
"diving-scuba-flag": "\U000F0DC2",
|
||||
"diving-scuba-mask": "\U000F0DC1",
|
||||
"diving-scuba-tank": "\U000F0DC3",
|
||||
"diving-scuba-tank-multiple": "\U000F0DC4",
|
||||
"diving-snorkel": "\U000F0DC5",
|
||||
|
@ -2590,6 +2624,10 @@ md_icons = {
|
|||
"email": "\U000F01EE",
|
||||
"email-alert": "\U000F06CF",
|
||||
"email-alert-outline": "\U000F0D42",
|
||||
"email-arrow-left": "\U000F10DA",
|
||||
"email-arrow-left-outline": "\U000F10DB",
|
||||
"email-arrow-right": "\U000F10DC",
|
||||
"email-arrow-right-outline": "\U000F10DD",
|
||||
"email-box": "\U000F0D03",
|
||||
"email-check": "\U000F0AB1",
|
||||
"email-check-outline": "\U000F0AB2",
|
||||
|
@ -2598,6 +2636,7 @@ md_icons = {
|
|||
"email-fast": "\U000F186F",
|
||||
"email-fast-outline": "\U000F1870",
|
||||
"email-lock": "\U000F01F1",
|
||||
"email-lock-outline": "\U000F1B61",
|
||||
"email-mark-as-unread": "\U000F0B92",
|
||||
"email-minus": "\U000F0EE5",
|
||||
"email-minus-outline": "\U000F0EE6",
|
||||
|
@ -2613,16 +2652,12 @@ md_icons = {
|
|||
"email-outline": "\U000F01F0",
|
||||
"email-plus": "\U000F09EB",
|
||||
"email-plus-outline": "\U000F09EC",
|
||||
"email-receive": "\U000F10DA",
|
||||
"email-receive-outline": "\U000F10DB",
|
||||
"email-remove": "\U000F1661",
|
||||
"email-remove-outline": "\U000F1662",
|
||||
"email-seal": "\U000F195B",
|
||||
"email-seal-outline": "\U000F195C",
|
||||
"email-search": "\U000F0961",
|
||||
"email-search-outline": "\U000F0962",
|
||||
"email-send": "\U000F10DC",
|
||||
"email-send-outline": "\U000F10DD",
|
||||
"email-sync": "\U000F12C7",
|
||||
"email-sync-outline": "\U000F12C8",
|
||||
"email-variant": "\U000F05F0",
|
||||
|
@ -3013,7 +3048,15 @@ md_icons = {
|
|||
"flag-remove-outline": "\U000F10B4",
|
||||
"flag-triangle": "\U000F023F",
|
||||
"flag-variant": "\U000F0240",
|
||||
"flag-variant-minus": "\U000F1BB4",
|
||||
"flag-variant-minus-outline": "\U000F1BB5",
|
||||
"flag-variant-off": "\U000F1BB0",
|
||||
"flag-variant-off-outline": "\U000F1BB1",
|
||||
"flag-variant-outline": "\U000F023E",
|
||||
"flag-variant-plus": "\U000F1BB2",
|
||||
"flag-variant-plus-outline": "\U000F1BB3",
|
||||
"flag-variant-remove": "\U000F1BB6",
|
||||
"flag-variant-remove-outline": "\U000F1BB7",
|
||||
"flare": "\U000F0D72",
|
||||
"flash": "\U000F0241",
|
||||
"flash-alert": "\U000F0EF7",
|
||||
|
@ -3275,6 +3318,7 @@ md_icons = {
|
|||
"format-list-checkbox": "\U000F096A",
|
||||
"format-list-checks": "\U000F0756",
|
||||
"format-list-group": "\U000F1860",
|
||||
"format-list-group-plus": "\U000F1B56",
|
||||
"format-list-numbered": "\U000F027B",
|
||||
"format-list-numbered-rtl": "\U000F0D0D",
|
||||
"format-list-text": "\U000F126F",
|
||||
|
@ -3285,6 +3329,8 @@ md_icons = {
|
|||
"format-paragraph": "\U000F027D",
|
||||
"format-paragraph-spacing": "\U000F1AFD",
|
||||
"format-pilcrow": "\U000F06D8",
|
||||
"format-pilcrow-arrow-left": "\U000F0286",
|
||||
"format-pilcrow-arrow-right": "\U000F0285",
|
||||
"format-quote-close": "\U000F027E",
|
||||
"format-quote-close-outline": "\U000F11A8",
|
||||
"format-quote-open": "\U000F0757",
|
||||
|
@ -3310,8 +3356,6 @@ md_icons = {
|
|||
"format-text-wrapping-overflow": "\U000F0D0F",
|
||||
"format-text-wrapping-wrap": "\U000F0D10",
|
||||
"format-textbox": "\U000F0D11",
|
||||
"format-textdirection-l-to-r": "\U000F0285",
|
||||
"format-textdirection-r-to-l": "\U000F0286",
|
||||
"format-title": "\U000F05F4",
|
||||
"format-underline": "\U000F0287",
|
||||
"format-underline-wavy": "\U000F18E9",
|
||||
|
@ -3487,7 +3531,8 @@ md_icons = {
|
|||
"glass-tulip": "\U000F02A8",
|
||||
"glass-wine": "\U000F0876",
|
||||
"glasses": "\U000F02AA",
|
||||
"globe-light": "\U000F12D7",
|
||||
"globe-light": "\U000F066F",
|
||||
"globe-light-outline": "\U000F12D7",
|
||||
"globe-model": "\U000F08E9",
|
||||
"gmail": "\U000F02AB",
|
||||
"gnome": "\U000F02AC",
|
||||
|
@ -3512,15 +3557,12 @@ md_icons = {
|
|||
"google-circles-group": "\U000F02B3",
|
||||
"google-classroom": "\U000F02C0",
|
||||
"google-cloud": "\U000F11F6",
|
||||
"google-controller": "\U000F02B4",
|
||||
"google-controller-off": "\U000F02B5",
|
||||
"google-downasaur": "\U000F1362",
|
||||
"google-drive": "\U000F02B6",
|
||||
"google-earth": "\U000F02B7",
|
||||
"google-fit": "\U000F096C",
|
||||
"google-glass": "\U000F02B8",
|
||||
"google-hangouts": "\U000F02C9",
|
||||
"google-home": "\U000F0824",
|
||||
"google-keep": "\U000F06DC",
|
||||
"google-lens": "\U000F09F6",
|
||||
"google-maps": "\U000F05F5",
|
||||
|
@ -3582,6 +3624,7 @@ md_icons = {
|
|||
"hand-clap-off": "\U000F1A42",
|
||||
"hand-coin": "\U000F188F",
|
||||
"hand-coin-outline": "\U000F1890",
|
||||
"hand-cycle": "\U000F1B9C",
|
||||
"hand-extended": "\U000F18B6",
|
||||
"hand-extended-outline": "\U000F18B7",
|
||||
"hand-front-left": "\U000F182B",
|
||||
|
@ -3615,6 +3658,7 @@ md_icons = {
|
|||
"harddisk-remove": "\U000F104C",
|
||||
"hat-fedora": "\U000F0BA4",
|
||||
"hazard-lights": "\U000F0C89",
|
||||
"hdmi-port": "\U000F1BB8",
|
||||
"hdr": "\U000F0D7D",
|
||||
"hdr-off": "\U000F0D7E",
|
||||
"head": "\U000F135E",
|
||||
|
@ -3768,6 +3812,8 @@ md_icons = {
|
|||
"home-roof": "\U000F112B",
|
||||
"home-search": "\U000F13B0",
|
||||
"home-search-outline": "\U000F13B1",
|
||||
"home-silo": "\U000F1BA0",
|
||||
"home-silo-outline": "\U000F1BA1",
|
||||
"home-switch": "\U000F1794",
|
||||
"home-switch-outline": "\U000F1795",
|
||||
"home-thermometer": "\U000F0F54",
|
||||
|
@ -3827,6 +3873,7 @@ md_icons = {
|
|||
"human-pregnant": "\U000F05CF",
|
||||
"human-queue": "\U000F1571",
|
||||
"human-scooter": "\U000F11E9",
|
||||
"human-walker": "\U000F1B71",
|
||||
"human-wheelchair": "\U000F138D",
|
||||
"human-white-cane": "\U000F1981",
|
||||
"humble-bundle": "\U000F0744",
|
||||
|
@ -4005,6 +4052,7 @@ md_icons = {
|
|||
"klingon": "\U000F135B",
|
||||
"knife": "\U000F09FB",
|
||||
"knife-military": "\U000F09FC",
|
||||
"knob": "\U000F1B96",
|
||||
"koala": "\U000F173F",
|
||||
"kodi": "\U000F0314",
|
||||
"kubernetes": "\U000F10FE",
|
||||
|
@ -4092,7 +4140,7 @@ md_icons = {
|
|||
"leaf-off": "\U000F12D9",
|
||||
"leak": "\U000F0DD7",
|
||||
"leak-off": "\U000F0DD8",
|
||||
"lecturn": "\U000F1AF0",
|
||||
"lectern": "\U000F1AF0",
|
||||
"led-off": "\U000F032B",
|
||||
"led-on": "\U000F032C",
|
||||
"led-outline": "\U000F032D",
|
||||
|
@ -4182,6 +4230,8 @@ md_icons = {
|
|||
"lipstick": "\U000F13B5",
|
||||
"liquid-spot": "\U000F1826",
|
||||
"liquor": "\U000F191E",
|
||||
"list-box": "\U000F1B7B",
|
||||
"list-box-outline": "\U000F1B7C",
|
||||
"list-status": "\U000F15AB",
|
||||
"litecoin": "\U000F0A61",
|
||||
"loading": "\U000F0772",
|
||||
|
@ -4362,6 +4412,8 @@ md_icons = {
|
|||
"message-bookmark-outline": "\U000F15AD",
|
||||
"message-bulleted": "\U000F06A2",
|
||||
"message-bulleted-off": "\U000F06A3",
|
||||
"message-check": "\U000F1B8A",
|
||||
"message-check-outline": "\U000F1B8B",
|
||||
"message-cog": "\U000F06F1",
|
||||
"message-cog-outline": "\U000F1172",
|
||||
"message-draw": "\U000F0363",
|
||||
|
@ -4410,6 +4462,8 @@ md_icons = {
|
|||
"metronome-tick": "\U000F07DB",
|
||||
"micro-sd": "\U000F07DC",
|
||||
"microphone": "\U000F036C",
|
||||
"microphone-message": "\U000F050A",
|
||||
"microphone-message-off": "\U000F050B",
|
||||
"microphone-minus": "\U000F08B3",
|
||||
"microphone-off": "\U000F036D",
|
||||
"microphone-outline": "\U000F036E",
|
||||
|
@ -4519,7 +4573,8 @@ md_icons = {
|
|||
"more": "\U000F037B",
|
||||
"mortar-pestle": "\U000F1748",
|
||||
"mortar-pestle-plus": "\U000F03F1",
|
||||
"mosque": "\U000F1827",
|
||||
"mosque": "\U000F0D45",
|
||||
"mosque-outline": "\U000F1827",
|
||||
"mother-heart": "\U000F1314",
|
||||
"mother-nurse": "\U000F0D21",
|
||||
"motion": "\U000F15B2",
|
||||
|
@ -4594,8 +4649,11 @@ md_icons = {
|
|||
"movie-star-outline": "\U000F1718",
|
||||
"mower": "\U000F166F",
|
||||
"mower-bag": "\U000F1670",
|
||||
"mower-bag-on": "\U000F1B60",
|
||||
"mower-on": "\U000F1B5F",
|
||||
"muffin": "\U000F098C",
|
||||
"multicast": "\U000F1893",
|
||||
"multimedia": "\U000F1B97",
|
||||
"multiplication": "\U000F0382",
|
||||
"multiplication-box": "\U000F0383",
|
||||
"mushroom": "\U000F07DF",
|
||||
|
@ -4624,6 +4682,7 @@ md_icons = {
|
|||
"music-note-eighth-dotted": "\U000F0F71",
|
||||
"music-note-half": "\U000F0389",
|
||||
"music-note-half-dotted": "\U000F0F72",
|
||||
"music-note-minus": "\U000F1B89",
|
||||
"music-note-off": "\U000F038A",
|
||||
"music-note-off-outline": "\U000F0F73",
|
||||
"music-note-outline": "\U000F0F74",
|
||||
|
@ -4846,7 +4905,13 @@ md_icons = {
|
|||
"office-building-cog-outline": "\U000F194A",
|
||||
"office-building-marker": "\U000F1520",
|
||||
"office-building-marker-outline": "\U000F1521",
|
||||
"office-building-minus": "\U000F1BAA",
|
||||
"office-building-minus-outline": "\U000F1BAB",
|
||||
"office-building-outline": "\U000F151F",
|
||||
"office-building-plus": "\U000F1BA8",
|
||||
"office-building-plus-outline": "\U000F1BA9",
|
||||
"office-building-remove": "\U000F1BAC",
|
||||
"office-building-remove-outline": "\U000F1BAD",
|
||||
"oil": "\U000F03C7",
|
||||
"oil-lamp": "\U000F0F19",
|
||||
"oil-level": "\U000F1053",
|
||||
|
@ -4967,6 +5032,8 @@ md_icons = {
|
|||
"patio-heater": "\U000F0F80",
|
||||
"patreon": "\U000F0882",
|
||||
"pause": "\U000F03E4",
|
||||
"pause-box": "\U000F00BC",
|
||||
"pause-box-outline": "\U000F1B7A",
|
||||
"pause-circle": "\U000F03E5",
|
||||
"pause-circle-outline": "\U000F03E6",
|
||||
"pause-octagon": "\U000F03E7",
|
||||
|
@ -5253,6 +5320,7 @@ md_icons = {
|
|||
"progress-clock": "\U000F0996",
|
||||
"progress-close": "\U000F110A",
|
||||
"progress-download": "\U000F0997",
|
||||
"progress-helper": "\U000F1BA2",
|
||||
"progress-pencil": "\U000F1787",
|
||||
"progress-question": "\U000F1522",
|
||||
"progress-star": "\U000F1788",
|
||||
|
@ -5351,12 +5419,14 @@ md_icons = {
|
|||
"razor-single-edge": "\U000F1998",
|
||||
"react": "\U000F0708",
|
||||
"read": "\U000F0447",
|
||||
"receipt": "\U000F0449",
|
||||
"receipt-outline": "\U000F19DC",
|
||||
"receipt": "\U000F0824",
|
||||
"receipt-outline": "\U000F04F7",
|
||||
"receipt-text": "\U000F0449",
|
||||
"receipt-text-check": "\U000F1A63",
|
||||
"receipt-text-check-outline": "\U000F1A64",
|
||||
"receipt-text-minus": "\U000F1A65",
|
||||
"receipt-text-minus-outline": "\U000F1A66",
|
||||
"receipt-text-outline": "\U000F19DC",
|
||||
"receipt-text-plus": "\U000F1A67",
|
||||
"receipt-text-plus-outline": "\U000F1A68",
|
||||
"receipt-text-remove": "\U000F1A69",
|
||||
|
@ -5495,7 +5565,9 @@ md_icons = {
|
|||
"robot-off-outline": "\U000F167B",
|
||||
"robot-outline": "\U000F167A",
|
||||
"robot-vacuum": "\U000F070D",
|
||||
"robot-vacuum-alert": "\U000F1B5D",
|
||||
"robot-vacuum-variant": "\U000F0908",
|
||||
"robot-vacuum-variant-alert": "\U000F1B5E",
|
||||
"rocket": "\U000F0463",
|
||||
"rocket-launch": "\U000F14DE",
|
||||
"rocket-launch-outline": "\U000F14DF",
|
||||
|
@ -5633,6 +5705,8 @@ md_icons = {
|
|||
"segment": "\U000F0ECB",
|
||||
"select": "\U000F0485",
|
||||
"select-all": "\U000F0486",
|
||||
"select-arrow-down": "\U000F1B59",
|
||||
"select-arrow-up": "\U000F1B58",
|
||||
"select-color": "\U000F0D31",
|
||||
"select-compare": "\U000F0AD9",
|
||||
"select-drag": "\U000F0A6C",
|
||||
|
@ -5803,6 +5877,7 @@ md_icons = {
|
|||
"sign-pole": "\U000F14F8",
|
||||
"sign-real-estate": "\U000F1118",
|
||||
"sign-text": "\U000F0782",
|
||||
"sign-yield": "\U000F1BAF",
|
||||
"signal": "\U000F04A2",
|
||||
"signal-2g": "\U000F0712",
|
||||
"signal-3g": "\U000F0713",
|
||||
|
@ -5821,7 +5896,8 @@ md_icons = {
|
|||
"signature-freehand": "\U000F0DFC",
|
||||
"signature-image": "\U000F0DFD",
|
||||
"signature-text": "\U000F0DFE",
|
||||
"silo": "\U000F0B49",
|
||||
"silo": "\U000F1B9F",
|
||||
"silo-outline": "\U000F0B49",
|
||||
"silverware": "\U000F04A3",
|
||||
"silverware-clean": "\U000F0FDE",
|
||||
"silverware-fork": "\U000F04A4",
|
||||
|
@ -6000,6 +6076,9 @@ md_icons = {
|
|||
"speaker-message": "\U000F1B11",
|
||||
"speaker-multiple": "\U000F0D38",
|
||||
"speaker-off": "\U000F04C4",
|
||||
"speaker-pause": "\U000F1B73",
|
||||
"speaker-play": "\U000F1B72",
|
||||
"speaker-stop": "\U000F1B74",
|
||||
"speaker-wireless": "\U000F071F",
|
||||
"spear": "\U000F1845",
|
||||
"speedometer": "\U000F04C5",
|
||||
|
@ -6149,7 +6228,17 @@ md_icons = {
|
|||
"store-settings": "\U000F18D4",
|
||||
"store-settings-outline": "\U000F18D5",
|
||||
"storefront": "\U000F07C7",
|
||||
"storefront-check": "\U000F1B7D",
|
||||
"storefront-check-outline": "\U000F1B7E",
|
||||
"storefront-edit": "\U000F1B7F",
|
||||
"storefront-edit-outline": "\U000F1B80",
|
||||
"storefront-minus": "\U000F1B83",
|
||||
"storefront-minus-outline": "\U000F1B84",
|
||||
"storefront-outline": "\U000F10C1",
|
||||
"storefront-plus": "\U000F1B81",
|
||||
"storefront-plus-outline": "\U000F1B82",
|
||||
"storefront-remove": "\U000F1B85",
|
||||
"storefront-remove-outline": "\U000F1B86",
|
||||
"stove": "\U000F04DE",
|
||||
"strategy": "\U000F11D6",
|
||||
"stretch-to-page": "\U000F0F2B",
|
||||
|
@ -6239,6 +6328,7 @@ md_icons = {
|
|||
"table-edit": "\U000F04F0",
|
||||
"table-eye": "\U000F1094",
|
||||
"table-eye-off": "\U000F13C3",
|
||||
"table-filter": "\U000F1B8C",
|
||||
"table-furniture": "\U000F05BC",
|
||||
"table-headers-eye": "\U000F121D",
|
||||
"table-headers-eye-off": "\U000F121E",
|
||||
|
@ -6272,7 +6362,6 @@ md_icons = {
|
|||
"table-sync": "\U000F13A1",
|
||||
"table-tennis": "\U000F0E68",
|
||||
"tablet": "\U000F04F6",
|
||||
"tablet-android": "\U000F04F7",
|
||||
"tablet-cellphone": "\U000F09A7",
|
||||
"tablet-dashboard": "\U000F0ECE",
|
||||
"taco": "\U000F0762",
|
||||
|
@ -6377,8 +6466,6 @@ md_icons = {
|
|||
"text-search-variant": "\U000F1A7E",
|
||||
"text-shadow": "\U000F0669",
|
||||
"text-short": "\U000F09A9",
|
||||
"text-to-speech": "\U000F050A",
|
||||
"text-to-speech-off": "\U000F050B",
|
||||
"texture": "\U000F050C",
|
||||
"texture-box": "\U000F0FE6",
|
||||
"theater": "\U000F050D",
|
||||
|
@ -6429,13 +6516,13 @@ md_icons = {
|
|||
"timeline-check-outline": "\U000F1533",
|
||||
"timeline-clock": "\U000F11FB",
|
||||
"timeline-clock-outline": "\U000F11FC",
|
||||
"timeline-help": "\U000F0F99",
|
||||
"timeline-help-outline": "\U000F0F9A",
|
||||
"timeline-minus": "\U000F1534",
|
||||
"timeline-minus-outline": "\U000F1535",
|
||||
"timeline-outline": "\U000F0BD2",
|
||||
"timeline-plus": "\U000F0F96",
|
||||
"timeline-plus-outline": "\U000F0F97",
|
||||
"timeline-question": "\U000F0F99",
|
||||
"timeline-question-outline": "\U000F0F9A",
|
||||
"timeline-remove": "\U000F1536",
|
||||
"timeline-remove-outline": "\U000F1537",
|
||||
"timeline-text": "\U000F0BD3",
|
||||
|
@ -6601,6 +6688,7 @@ md_icons = {
|
|||
"transition-masked": "\U000F0916",
|
||||
"translate": "\U000F05CA",
|
||||
"translate-off": "\U000F0E06",
|
||||
"translate-variant": "\U000F1B99",
|
||||
"transmission-tower": "\U000F0D3E",
|
||||
"transmission-tower-export": "\U000F192C",
|
||||
"transmission-tower-import": "\U000F192D",
|
||||
|
@ -6744,7 +6832,11 @@ md_icons = {
|
|||
"vector-intersection": "\U000F055D",
|
||||
"vector-line": "\U000F055E",
|
||||
"vector-link": "\U000F0FE8",
|
||||
"vector-point": "\U000F055F",
|
||||
"vector-point": "\U000F01C4",
|
||||
"vector-point-edit": "\U000F09E8",
|
||||
"vector-point-minus": "\U000F1B78",
|
||||
"vector-point-plus": "\U000F1B79",
|
||||
"vector-point-select": "\U000F055F",
|
||||
"vector-polygon": "\U000F0560",
|
||||
"vector-polygon-variant": "\U000F1856",
|
||||
"vector-polyline": "\U000F0561",
|
||||
|
@ -6912,6 +7004,7 @@ md_icons = {
|
|||
"water-alert-outline": "\U000F1503",
|
||||
"water-boiler": "\U000F0F92",
|
||||
"water-boiler-alert": "\U000F11B3",
|
||||
"water-boiler-auto": "\U000F1B98",
|
||||
"water-boiler-off": "\U000F11B4",
|
||||
"water-check": "\U000F1504",
|
||||
"water-check-outline": "\U000F1505",
|
||||
|
@ -6951,6 +7044,7 @@ md_icons = {
|
|||
"weather-cloudy-alert": "\U000F0F2F",
|
||||
"weather-cloudy-arrow-right": "\U000F0E6E",
|
||||
"weather-cloudy-clock": "\U000F18F6",
|
||||
"weather-dust": "\U000F1B5A",
|
||||
"weather-fog": "\U000F0591",
|
||||
"weather-hail": "\U000F0592",
|
||||
"weather-hazy": "\U000F0F30",
|
||||
|
@ -7072,6 +7166,7 @@ md_icons = {
|
|||
"window-restore": "\U000F05B2",
|
||||
"window-shutter": "\U000F111C",
|
||||
"window-shutter-alert": "\U000F111D",
|
||||
"window-shutter-auto": "\U000F1BA3",
|
||||
"window-shutter-cog": "\U000F1A8A",
|
||||
"window-shutter-open": "\U000F111E",
|
||||
"window-shutter-settings": "\U000F1A8B",
|
||||
|
@ -7084,7 +7179,12 @@ md_icons = {
|
|||
"wrap": "\U000F05B6",
|
||||
"wrap-disabled": "\U000F0BDF",
|
||||
"wrench": "\U000F05B7",
|
||||
"wrench-check": "\U000F1B8F",
|
||||
"wrench-check-outline": "\U000F1B90",
|
||||
"wrench-clock": "\U000F19A3",
|
||||
"wrench-clock-outline": "\U000F1B93",
|
||||
"wrench-cog": "\U000F1B91",
|
||||
"wrench-cog-outline": "\U000F1B92",
|
||||
"wrench-outline": "\U000F0BE0",
|
||||
"xamarin": "\U000F0845",
|
||||
"xml": "\U000F05C0",
|
||||
|
|
Before Width: | Height: | Size: 5.3 KiB |
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 19 KiB |
After Width: | Height: | Size: 31 KiB |
After Width: | Height: | Size: 53 KiB |
Before Width: | Height: | Size: 31 KiB |
Before Width: | Height: | Size: 31 KiB |
Before Width: | Height: | Size: 21 KiB |
|
@ -1 +0,0 @@
|
|||
{"quad_shadow-1.png": {"20": [2, 136, 128, 128], "21": [132, 136, 128, 128], "22": [262, 136, 128, 128], "23": [2, 6, 128, 128], "19": [132, 266, 128, 128], "18": [2, 266, 128, 128], "1": [262, 266, 128, 128], "3": [262, 6, 128, 128], "2": [132, 6, 128, 128]}, "quad_shadow-0.png": {"11": [262, 266, 128, 128], "10": [132, 266, 128, 128], "13": [132, 136, 128, 128], "12": [2, 136, 128, 128], "15": [2, 6, 128, 128], "14": [262, 136, 128, 128], "17": [262, 6, 128, 128], "16": [132, 6, 128, 128], "0": [2, 266, 128, 128]}, "quad_shadow-2.png": {"5": [132, 266, 128, 128], "4": [2, 266, 128, 128], "7": [2, 136, 128, 128], "6": [262, 266, 128, 128], "9": [262, 136, 128, 128], "8": [132, 136, 128, 128]}}
|
Before Width: | Height: | Size: 46 KiB |
Before Width: | Height: | Size: 43 KiB |
|
@ -1 +0,0 @@
|
|||
{"rec_shadow-1.png": {"20": [2, 266, 256, 128], "21": [260, 266, 256, 128], "22": [518, 266, 256, 128], "23": [776, 266, 256, 128], "3": [260, 136, 256, 128], "2": [2, 136, 256, 128], "5": [776, 136, 256, 128], "4": [518, 136, 256, 128], "7": [260, 6, 256, 128], "6": [2, 6, 256, 128], "9": [776, 6, 256, 128], "8": [518, 6, 256, 128]}, "rec_shadow-0.png": {"11": [518, 266, 256, 128], "10": [260, 266, 256, 128], "13": [2, 136, 256, 128], "12": [776, 266, 256, 128], "15": [518, 136, 256, 128], "14": [260, 136, 256, 128], "17": [2, 6, 256, 128], "16": [776, 136, 256, 128], "19": [518, 6, 256, 128], "18": [260, 6, 256, 128], "1": [776, 6, 256, 128], "0": [2, 266, 256, 128]}}
|
Before Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 32 KiB |
Before Width: | Height: | Size: 28 KiB |
|
@ -1 +0,0 @@
|
|||
{"rec_st_shadow-0.png": {"11": [262, 138, 128, 256], "10": [132, 138, 128, 256], "13": [522, 138, 128, 256], "12": [392, 138, 128, 256], "15": [782, 138, 128, 256], "14": [652, 138, 128, 256], "16": [912, 138, 128, 256], "0": [2, 138, 128, 256]}, "rec_st_shadow-1.png": {"20": [522, 138, 128, 256], "21": [652, 138, 128, 256], "17": [2, 138, 128, 256], "23": [912, 138, 128, 256], "19": [262, 138, 128, 256], "18": [132, 138, 128, 256], "22": [782, 138, 128, 256], "1": [392, 138, 128, 256]}, "rec_st_shadow-2.png": {"3": [132, 138, 128, 256], "2": [2, 138, 128, 256], "5": [392, 138, 128, 256], "4": [262, 138, 128, 256], "7": [652, 138, 128, 256], "6": [522, 138, 128, 256], "9": [912, 138, 128, 256], "8": [782, 138, 128, 256]}}
|
Before Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 39 KiB |
Before Width: | Height: | Size: 40 KiB |
Before Width: | Height: | Size: 26 KiB |
|
@ -1 +0,0 @@
|
|||
{"round_shadow-1.png": {"20": [2, 136, 128, 128], "21": [132, 136, 128, 128], "22": [262, 136, 128, 128], "23": [2, 6, 128, 128], "19": [132, 266, 128, 128], "18": [2, 266, 128, 128], "1": [262, 266, 128, 128], "3": [262, 6, 128, 128], "2": [132, 6, 128, 128]}, "round_shadow-0.png": {"11": [262, 266, 128, 128], "10": [132, 266, 128, 128], "13": [132, 136, 128, 128], "12": [2, 136, 128, 128], "15": [2, 6, 128, 128], "14": [262, 136, 128, 128], "17": [262, 6, 128, 128], "16": [132, 6, 128, 128], "0": [2, 266, 128, 128]}, "round_shadow-2.png": {"5": [132, 266, 128, 128], "4": [2, 266, 128, 128], "7": [2, 136, 128, 128], "6": [262, 266, 128, 128], "9": [262, 136, 128, 128], "8": [132, 136, 128, 128]}}
|
|
@ -0,0 +1,9 @@
|
|||
from kivy.tests.common import GraphicUnitTest
|
||||
|
||||
from kivymd.app import MDApp
|
||||
|
||||
|
||||
class BaseTest(GraphicUnitTest):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.app = MDApp() # NOQA
|
|
@ -35,8 +35,15 @@ 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 "rec_shadow.atlas" in images
|
||||
assert "transparent.png" in images
|
||||
"""
|
||||
)
|
||||
pyi_main.run(
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
from kivymd.tests.base_test import BaseTest
|
||||
|
||||
|
||||
class BackdropTest(BaseTest):
|
||||
def test_backdrop_raw_app(self):
|
||||
from kivymd.uix.backdrop import MDBackdrop
|
||||
from kivymd.uix.backdrop.backdrop import (
|
||||
MDBackdropBackLayer,
|
||||
MDBackdropFrontLayer,
|
||||
)
|
||||
from kivymd.uix.screen import MDScreen
|
||||
from kivymd.uix.widget import MDWidget
|
||||
|
||||
self.render(
|
||||
MDScreen(
|
||||
MDBackdrop(
|
||||
MDBackdropBackLayer(MDWidget()),
|
||||
MDBackdropFrontLayer(MDWidget()),
|
||||
id="backdrop",
|
||||
title="Example Backdrop",
|
||||
header_text="Menu:",
|
||||
)
|
||||
)
|
||||
)
|
|
@ -0,0 +1,32 @@
|
|||
from kivymd.tests.base_test import BaseTest
|
||||
|
||||
|
||||
class BottomNavigationTest(BaseTest):
|
||||
def test_bottom_navigation_m3_style_raw_app(self):
|
||||
from kivymd.uix.bottomnavigation import (
|
||||
MDBottomNavigation,
|
||||
MDBottomNavigationItem,
|
||||
)
|
||||
from kivymd.uix.screen import MDScreen
|
||||
|
||||
self.app.theme_cls.material_style = "M3"
|
||||
self.render(
|
||||
MDScreen(
|
||||
MDBottomNavigation(
|
||||
MDBottomNavigationItem(
|
||||
name="screen 1",
|
||||
text="Mail",
|
||||
icon="gmail",
|
||||
),
|
||||
MDBottomNavigationItem(
|
||||
name="screen 2",
|
||||
text="Twitter",
|
||||
icon="twitter",
|
||||
badge_icon="numeric-10",
|
||||
),
|
||||
panel_color="#eeeaea",
|
||||
selected_color_background="#97ecf8",
|
||||
text_color_active="red",
|
||||
)
|
||||
)
|
||||
)
|
|
@ -0,0 +1,25 @@
|
|||
from kivymd.tests.base_test import BaseTest
|
||||
|
||||
|
||||
class CardTest(BaseTest):
|
||||
def test_card_m3_style_raw_app(self):
|
||||
from kivymd.uix.behaviors import RoundedRectangularElevationBehavior
|
||||
from kivymd.uix.card import MDCard
|
||||
from kivymd.uix.screen import MDScreen
|
||||
|
||||
class MD3Card(MDCard, RoundedRectangularElevationBehavior):
|
||||
pass
|
||||
|
||||
self.app.theme_cls.material_style = "M3"
|
||||
self.render(
|
||||
MDScreen(
|
||||
MD3Card(
|
||||
size_hint=(None, None),
|
||||
pos_hint={"center_x": 0.5, "center_y": 0.5},
|
||||
size=("200dp", "100dp"),
|
||||
line_color=(0.2, 0.2, 0.2, 0.8),
|
||||
style="elevated",
|
||||
md_bg_color="lightblue",
|
||||
)
|
||||
)
|
||||
)
|
|
@ -0,0 +1,16 @@
|
|||
from kivymd.tests.base_test import BaseTest
|
||||
|
||||
|
||||
class ChipTest(BaseTest):
|
||||
def test_chip_raw_app(self):
|
||||
from kivymd.uix.chip import MDChip
|
||||
from kivymd.uix.screen import MDScreen
|
||||
|
||||
self.render(
|
||||
MDScreen(
|
||||
MDChip(
|
||||
text="Portland",
|
||||
pos_hint={"center_x": 0.5, "center_y": 0.5},
|
||||
)
|
||||
)
|
||||
)
|
|
@ -1,14 +1,13 @@
|
|||
def test_create_project():
|
||||
import os
|
||||
import sys
|
||||
|
||||
os.system(
|
||||
f"{sys.executable} -m kivymd.tools.patterns.create_project "
|
||||
f"python3.10 -m kivymd.tools.patterns.create_project "
|
||||
f"MVC "
|
||||
f"{os.path.expanduser('~')} "
|
||||
f"TestProject "
|
||||
f"{sys.executable} "
|
||||
f"master "
|
||||
f"python3.10 "
|
||||
f"stable "
|
||||
f"--name_screen TestProjectScreen "
|
||||
f"--name_database restdb "
|
||||
f"--use_hotreload yes"
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
from kivymd.tests.base_test import BaseTest
|
||||
|
||||
|
||||
class FitImageTest(BaseTest):
|
||||
def test_fitimage_raw_app(self):
|
||||
import os
|
||||
|
||||
from kivymd import images_path
|
||||
from kivymd.uix.fitimage import FitImage
|
||||
from kivymd.uix.screen import MDScreen
|
||||
|
||||
self.render(
|
||||
MDScreen(
|
||||
FitImage(
|
||||
source=os.path.join(
|
||||
images_path, "logo", "kivymd-icon-512.png"
|
||||
),
|
||||
size_hint=(0.5, 0.5),
|
||||
pos_hint={"center_x": 0.5, "center_y": 0.5},
|
||||
radius=[36, 36, 0, 0],
|
||||
mipmap=True,
|
||||
)
|
||||
)
|
||||
)
|
|
@ -0,0 +1,39 @@
|
|||
from kivymd.tests.base_test import BaseTest
|
||||
|
||||
|
||||
class ImageListTest(BaseTest):
|
||||
def test_imagelist_raw_app(self):
|
||||
import os
|
||||
|
||||
from kivymd import images_path
|
||||
from kivymd.uix.button import MDIconButton
|
||||
from kivymd.uix.imagelist import MDSmartTile
|
||||
from kivymd.uix.label import MDLabel
|
||||
from kivymd.uix.screen import MDScreen
|
||||
|
||||
self.render(
|
||||
MDScreen(
|
||||
MDSmartTile(
|
||||
MDIconButton(
|
||||
icon="heart-outline",
|
||||
theme_icon_color="Custom",
|
||||
icon_color="red",
|
||||
pos_hint={"center_y": 0.5},
|
||||
),
|
||||
MDLabel(
|
||||
text="Julia and Julie",
|
||||
bold=True,
|
||||
color="white",
|
||||
),
|
||||
radius=24,
|
||||
box_radius=[0, 0, 24, 24],
|
||||
box_color="grey",
|
||||
source=os.path.join(
|
||||
images_path, "logo", "kivymd-icon-512.png"
|
||||
),
|
||||
pos_hint={"center_x": 0.5, "center_y": 0.5},
|
||||
size_hint=(None, None),
|
||||
size=("320dp", "320dp"),
|
||||
)
|
||||
)
|
||||
)
|
|
@ -0,0 +1,67 @@
|
|||
from kivymd.tests.base_test import BaseTest
|
||||
|
||||
|
||||
class ListTest(BaseTest):
|
||||
def test_list_raw_app(self):
|
||||
import os
|
||||
|
||||
from kivymd import images_path
|
||||
from kivymd.uix.list import (
|
||||
IconLeftWidget,
|
||||
IconRightWidget,
|
||||
ImageLeftWidget,
|
||||
IRightBodyTouch,
|
||||
MDList,
|
||||
OneLineAvatarIconListItem,
|
||||
OneLineAvatarListItem,
|
||||
OneLineIconListItem,
|
||||
OneLineListItem,
|
||||
ThreeLineListItem,
|
||||
TwoLineListItem,
|
||||
)
|
||||
from kivymd.uix.screen import MDScreen
|
||||
from kivymd.uix.scrollview import MDScrollView
|
||||
from kivymd.uix.selectioncontrol import MDCheckbox
|
||||
|
||||
class RightCheckbox(IRightBodyTouch, MDCheckbox):
|
||||
pass
|
||||
|
||||
self.render(
|
||||
MDScreen(
|
||||
MDScrollView(
|
||||
MDList(
|
||||
OneLineListItem(text="Text"),
|
||||
TwoLineListItem(
|
||||
text="Text", secondary_text="secondary text"
|
||||
),
|
||||
ThreeLineListItem(
|
||||
text="Text",
|
||||
secondary_text="secondary text",
|
||||
tertiary_text="tertiary text",
|
||||
),
|
||||
OneLineAvatarListItem(
|
||||
ImageLeftWidget(
|
||||
source=os.path.join(
|
||||
images_path, "logo", "kivymd-icon-512.png"
|
||||
)
|
||||
),
|
||||
text="Text",
|
||||
),
|
||||
OneLineIconListItem(
|
||||
IconLeftWidget(icon="plus"),
|
||||
text="Text",
|
||||
),
|
||||
OneLineAvatarIconListItem(
|
||||
IconLeftWidget(icon="plus"),
|
||||
IconRightWidget(icon="minus"),
|
||||
text="Text",
|
||||
),
|
||||
OneLineAvatarIconListItem(
|
||||
IconLeftWidget(icon="plus"),
|
||||
RightCheckbox(),
|
||||
text="Text",
|
||||
),
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
|
@ -0,0 +1,94 @@
|
|||
from kivymd.tests.base_test import BaseTest
|
||||
|
||||
|
||||
class NavigationDrawerTest(BaseTest):
|
||||
def test_navigationdrawer_raw_app(self):
|
||||
from kivymd.uix.navigationdrawer import (
|
||||
MDNavigationDrawer,
|
||||
MDNavigationDrawerDivider,
|
||||
MDNavigationDrawerHeader,
|
||||
MDNavigationDrawerItem,
|
||||
MDNavigationDrawerLabel,
|
||||
MDNavigationDrawerMenu,
|
||||
MDNavigationLayout,
|
||||
)
|
||||
from kivymd.uix.screen import MDScreen
|
||||
from kivymd.uix.screenmanager import MDScreenManager
|
||||
from kivymd.uix.toolbar import MDTopAppBar
|
||||
|
||||
class DrawerClickableItem(MDNavigationDrawerItem):
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
self.focus_color = "#e7e4c0"
|
||||
self.unfocus_color = "#f7f4e7"
|
||||
self.text_color = "#4a4939"
|
||||
self.icon_color = "#4a4939"
|
||||
self.ripple_color = "#c5bdd2"
|
||||
self.selected_color = "#0c6c4d"
|
||||
|
||||
class DrawerLabelItem(MDNavigationDrawerItem):
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
self.bg_color = "#f7f4e7"
|
||||
self.text_color = "#4a4939"
|
||||
self.icon_color = "#4a4939"
|
||||
_no_ripple_effect = True # NOQA
|
||||
|
||||
self.app.theme_cls.material_style = "M3"
|
||||
self.render(
|
||||
MDNavigationLayout(
|
||||
MDScreenManager(
|
||||
MDScreen(
|
||||
MDTopAppBar(
|
||||
title="Navigation Drawer",
|
||||
elevation=10,
|
||||
pos_hint={"top": 1},
|
||||
md_bg_color="#e7e4c0",
|
||||
specific_text_color="#4a4939",
|
||||
left_action_items=[
|
||||
["menu", lambda x: self.nav_drawer_open()]
|
||||
],
|
||||
)
|
||||
)
|
||||
),
|
||||
MDNavigationDrawer(
|
||||
MDNavigationDrawerMenu(
|
||||
MDNavigationDrawerHeader(
|
||||
title="Header title",
|
||||
title_color="#4a4939",
|
||||
text="Header text",
|
||||
spacing="4dp",
|
||||
padding=("12dp", 0, 0, "56dp"),
|
||||
),
|
||||
MDNavigationDrawerLabel(
|
||||
text="Mail",
|
||||
),
|
||||
DrawerClickableItem(
|
||||
icon="gmail",
|
||||
right_text="+99",
|
||||
text_right_color="#4a4939",
|
||||
text="Inbox",
|
||||
radius=24,
|
||||
),
|
||||
DrawerClickableItem(
|
||||
icon="send",
|
||||
text="Outbox",
|
||||
radius=24,
|
||||
),
|
||||
MDNavigationDrawerDivider(),
|
||||
MDNavigationDrawerLabel(
|
||||
text="Labels",
|
||||
),
|
||||
DrawerLabelItem(
|
||||
icon="information-outline",
|
||||
text="Label",
|
||||
),
|
||||
DrawerLabelItem(
|
||||
icon="information-outline",
|
||||
text="Label",
|
||||
),
|
||||
),
|
||||
id="nav_drawer",
|
||||
),
|
||||
)
|
||||
)
|
|
@ -0,0 +1,14 @@
|
|||
from kivymd.tests.base_test import BaseTest
|
||||
|
||||
|
||||
class TabTest(BaseTest):
|
||||
def test_tab_raw_app(self):
|
||||
from kivymd.uix.floatlayout import MDFloatLayout
|
||||
from kivymd.uix.tab import MDTabs, MDTabsBase
|
||||
|
||||
class Tab(MDFloatLayout, MDTabsBase):
|
||||
pass
|
||||
|
||||
tab = MDTabs()
|
||||
tab.add_widget(Tab(title="Tab"))
|
||||
self.render(tab)
|
|
@ -0,0 +1,72 @@
|
|||
# from kivy.clock import Clock
|
||||
# from kivy.uix.textinput import TextInput
|
||||
|
||||
from kivymd.tests.base_test import BaseTest
|
||||
|
||||
|
||||
class TextFieldTest(BaseTest):
|
||||
def test_textfield_raw_app(self):
|
||||
from kivymd.uix.boxlayout import MDBoxLayout
|
||||
from kivymd.uix.button import MDFlatButton
|
||||
from kivymd.uix.screen import MDScreen
|
||||
from kivymd.uix.textfield import MDTextField
|
||||
|
||||
# def set_text():
|
||||
# for widget in self.screen.ids.box.children:
|
||||
# if issubclass(widget.__class__, TextInput):
|
||||
# widget.text = "Input text"
|
||||
|
||||
self.render(
|
||||
MDScreen(
|
||||
MDBoxLayout(
|
||||
MDTextField(
|
||||
hint_text="Label",
|
||||
helper_text="Error massage",
|
||||
mode="rectangle",
|
||||
max_text_length=5,
|
||||
),
|
||||
MDTextField(
|
||||
icon_left="git",
|
||||
hint_text="Label",
|
||||
helper_text="Error massage",
|
||||
mode="rectangle",
|
||||
),
|
||||
MDTextField(
|
||||
icon_left="git",
|
||||
hint_text="Label",
|
||||
helper_text="Error massage",
|
||||
mode="fill",
|
||||
),
|
||||
MDTextField(
|
||||
hint_text="Label",
|
||||
helper_text="Error massage",
|
||||
mode="fill",
|
||||
),
|
||||
MDTextField(
|
||||
hint_text="Label",
|
||||
helper_text="Error massage",
|
||||
),
|
||||
MDTextField(
|
||||
icon_left="git",
|
||||
hint_text="Label",
|
||||
helper_text="Error massage",
|
||||
),
|
||||
MDTextField(
|
||||
hint_text="Round mode",
|
||||
mode="round",
|
||||
max_text_length=15,
|
||||
helper_text="Massage",
|
||||
),
|
||||
MDFlatButton(
|
||||
text="SET TEXT",
|
||||
pos_hint={"center_x": 0.5},
|
||||
),
|
||||
id="box",
|
||||
orientation="vertical",
|
||||
spacing="20dp",
|
||||
adaptive_height=True,
|
||||
size_hint_x=0.8,
|
||||
pos_hint={"center_x": 0.5, "center_y": 0.5},
|
||||
)
|
||||
)
|
||||
)
|
|
@ -298,8 +298,9 @@ class MDApp(BaseApp):
|
|||
from kivy.core.window import Window
|
||||
from kivy.utils import get_color_from_hex
|
||||
|
||||
Window.clearcolor = get_color_from_hex("#e50000")
|
||||
scroll = Factory.ScrollView(scroll_y=0)
|
||||
scroll = Factory.MDScrollView(
|
||||
scroll_y=0, md_bg_color=get_color_from_hex("#e50000")
|
||||
)
|
||||
lbl = Factory.Label(
|
||||
text_size=(Window.width - 100, None),
|
||||
size_hint_y=None,
|
||||
|
|
|
@ -13,6 +13,18 @@ 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,
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
%s
|
||||
def get_view(self) -> %s:
|
||||
return self.view
|
|
@ -1,26 +0,0 @@
|
|||
# FILE TO FIND AND CREATE LOCALIZATION FILES FOR YOUR APPLICATION. \
|
||||
\
|
||||
In this file, you can specify in which files of your project to search for \
|
||||
localization strings. \
|
||||
These files should be listed in the below command: \
|
||||
\
|
||||
\
|
||||
xgettext -Lpython --output=messages.pot --from-code=utf-8 \
|
||||
path/to/file-1 \
|
||||
path/to/file-2 \
|
||||
...
|
||||
|
||||
.PHONY: po mo
|
||||
|
||||
po:
|
||||
xgettext -Lpython --output=messages.pot --from-code=utf-8 \
|
||||
View/%s/%s.kv \
|
||||
View/%s/%s.py
|
||||
msgmerge --update --no-fuzzy-matching --backup=off data/locales/po/en.po messages.pot
|
||||
msgmerge --update --no-fuzzy-matching --backup=off data/locales/po/ru.po messages.pot
|
||||
|
||||
mo:
|
||||
mkdir -p data/locales/en/LC_MESSAGES
|
||||
mkdir -p data/locales/ru/LC_MESSAGES
|
||||
msgfmt -c -o data/locales/en/LC_MESSAGES/%s.mo data/locales/po/en.po
|
||||
msgfmt -c -o data/locales/ru/LC_MESSAGES/%s.mo data/locales/po/ru.po
|
|
@ -1,33 +0,0 @@
|
|||
# The model implements the observer pattern. This means that the class must
|
||||
# support adding, removing, and alerting observers. In this case, the model is
|
||||
# completely independent of controllers and views. It is important that all
|
||||
# registered observers implement a specific method that will be called by the
|
||||
# model when they are notified (in this case, it is the `model_is_changed`
|
||||
# method). For this, observers must be descendants of an abstract class,
|
||||
# inheriting which, the `model_is_changed` method must be overridden.
|
||||
|
||||
|
||||
class BaseScreenModel:
|
||||
"""Implements a base class for model modules."""
|
||||
|
||||
_observers = []
|
||||
|
||||
def add_observer(self, observer) -> None:
|
||||
self._observers.append(observer)
|
||||
|
||||
def remove_observer(self, observer) -> None:
|
||||
self._observers.remove(observer)
|
||||
|
||||
def notify_observers(self, name_screen: str) -> None:
|
||||
"""
|
||||
Method that will be called by the observer when the model data changes.
|
||||
|
||||
:param name_screen:
|
||||
name of the view for which the method should be called
|
||||
:meth:`model_is_changed`.
|
||||
"""
|
||||
|
||||
for observer in self._observers:
|
||||
if observer.name == name_screen:
|
||||
observer.model_is_changed()
|
||||
break
|
|
@ -1 +0,0 @@
|
|||
%s
|
|
@ -1,16 +0,0 @@
|
|||
# Of course, "very flexible Python" allows you to do without an abstract
|
||||
# superclass at all or use the clever exception `NotImplementedError`. In my
|
||||
# opinion, this can negatively affect the architecture of the application.
|
||||
# I would like to point out that using Kivy, one could use the on-signaling
|
||||
# model. In this case, when the state changes, the model will send a signal
|
||||
# that can be received by all attached observers. This approach seems less
|
||||
# universal - you may want to use a different library in the future.
|
||||
|
||||
|
||||
class Observer:
|
||||
"""Abstract superclass for all observers."""
|
||||
|
||||
def model_is_changed(self):
|
||||
"""
|
||||
The method that will be called on the observer when the model changes.
|
||||
"""
|
|
@ -1,72 +0,0 @@
|
|||
#:import images_path kivymd.images_path
|
||||
#:import colors kivymd.color_definitions.colors
|
||||
#:import get_color_from_hex kivy.utils.get_color_from_hex
|
||||
|
||||
|
||||
<%s>
|
||||
|
||||
FitImage:
|
||||
source:
|
||||
( \
|
||||
f"{images_path}restdb-logo.png" \
|
||||
if root.model.database.name == "RestDB" else \
|
||||
f"{images_path}firebase-logo.png" \
|
||||
) \
|
||||
if hasattr(root.model, "database") else \
|
||||
f"{images_path}transparent.png"
|
||||
|
||||
MDBoxLayout:
|
||||
orientation: "vertical"
|
||||
|
||||
MDToolbar:
|
||||
id: toolbar
|
||||
title: "%s"
|
||||
right_action_items: [["web", lambda x: %s]]
|
||||
md_bg_color:
|
||||
( \
|
||||
get_color_from_hex(colors["Yellow"]["700"]) \
|
||||
if root.model.database.name == "Firebase" else \
|
||||
get_color_from_hex(colors["Blue"]["300"]) \
|
||||
) \
|
||||
if hasattr(root.model, "database") else \
|
||||
app.theme_cls.primary_color
|
||||
|
||||
MDFloatLayout:
|
||||
|
||||
MDBoxLayout:
|
||||
orientation: "vertical"
|
||||
adaptive_height: True
|
||||
size_hint_x: None
|
||||
width: root.width - dp(72)
|
||||
radius: 12
|
||||
padding: "12dp"
|
||||
md_bg_color: 1, 1, 1, .5
|
||||
pos_hint: {"center_x": .5, "center_y": .5}
|
||||
|
||||
MDLabel:
|
||||
id: prev_label
|
||||
text: %s
|
||||
font_style: "H6"
|
||||
adaptive_height: True
|
||||
halign: "center"
|
||||
color: 1, 1, 1, 1
|
||||
|
||||
MDBoxLayout:
|
||||
orientation: "vertical"
|
||||
adaptive_height: True
|
||||
padding: "50dp"
|
||||
spacing: "20dp"
|
||||
|
||||
MDTextField:
|
||||
hint_text: %s
|
||||
on_text: root.controller.set_user_data("login", self.text)
|
||||
|
||||
MDTextField:
|
||||
hint_text: %s
|
||||
on_text: root.controller.set_user_data("password", self.text)
|
||||
|
||||
MDFillRoundFlatButton:
|
||||
text: %s
|
||||
on_release: root.controller.on_tap_button_login()
|
||||
pos_hint: {"center_x": .5, "center_y": .1}
|
||||
md_bg_color: toolbar.md_bg_color
|
|
@ -1,15 +0,0 @@
|
|||
%s
|
||||
from View.base_screen import BaseScreenView
|
||||
|
||||
|
||||
class %s(BaseScreenView):
|
||||
"""Implements the login start screen in the user application."""
|
||||
%s
|
||||
def model_is_changed(self) -> None:
|
||||
"""
|
||||
Called whenever any change has occurred in the data model.
|
||||
The view in this method tracks these changes and updates the UI
|
||||
according to these changes.
|
||||
"""
|
||||
|
||||
%s
|
|
@ -1,47 +0,0 @@
|
|||
from kivy.properties import ObjectProperty
|
||||
|
||||
from kivymd.app import MDApp
|
||||
from kivymd.theming import ThemableBehavior
|
||||
from kivymd.uix.screen import MDScreen
|
||||
|
||||
from Utility.observer import Observer
|
||||
|
||||
|
||||
class BaseScreenView(ThemableBehavior, MDScreen, Observer):
|
||||
"""
|
||||
A base class that implements a visual representation of the model data
|
||||
:class:`~Model.%s.%s`.
|
||||
The view class must be inherited from this class.
|
||||
"""
|
||||
|
||||
controller = ObjectProperty()
|
||||
"""
|
||||
Controller object - :class:`~Controller.%s.%s`.
|
||||
|
||||
:attr:`controller` is an :class:`~kivy.properties.ObjectProperty`
|
||||
and defaults to `None`.
|
||||
"""
|
||||
|
||||
model = ObjectProperty()
|
||||
"""
|
||||
Model object - :class:`~Model.%s.%s`.
|
||||
|
||||
:attr:`model` is an :class:`~kivy.properties.ObjectProperty`
|
||||
and defaults to `None`.
|
||||
"""
|
||||
|
||||
manager_screens = ObjectProperty()
|
||||
"""
|
||||
Screen manager object - :class:`~kivy.uix.screenmanager.ScreenManager`.
|
||||
|
||||
:attr:`manager_screens` is an :class:`~kivy.properties.ObjectProperty`
|
||||
and defaults to `None`.
|
||||
"""
|
||||
|
||||
def __init__(self, **kw):
|
||||
super().__init__(**kw)
|
||||
# Often you need to get access to the application object from the view
|
||||
# class. You can do this using this attribute.
|
||||
self.app = MDApp.get_running_app()
|
||||
# Adding a view class as observer.
|
||||
self.model.add_observer(self)
|
|
@ -1,13 +0,0 @@
|
|||
# The screens dictionary contains the objects of the models and controllers
|
||||
# of the screens of the application.
|
||||
|
||||
from Model.%s import %s
|
||||
|
||||
from Controller.%s import %s
|
||||
|
||||
screens = {
|
||||
%s: {
|
||||
"model": %s,
|
||||
"controller": %s,
|
||||
},
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
"""
|
||||
The entry point to the application.
|
||||
|
||||
The application uses the MVC template. Adhering to the principles of clean
|
||||
architecture means ensuring that your application is easy to test, maintain,
|
||||
and modernize.
|
||||
|
||||
You can read more about this template at the links below:
|
||||
|
||||
https://github.com/HeaTTheatR/LoginAppMVC
|
||||
https://en.wikipedia.org/wiki/Model–view–controller
|
||||
"""
|
||||
|
||||
from typing import NoReturn
|
||||
|
||||
from kivy.uix.screenmanager import ScreenManager%s
|
||||
|
||||
from kivymd.app import MDApp
|
||||
|
||||
from View.screens import screens%s
|
||||
%s
|
||||
|
||||
class %s(MDApp):%s
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)%s
|
||||
self.load_all_kv_files(self.directory)
|
||||
# This is the screen manager that will contain all the screens of your
|
||||
# application.
|
||||
self.manager_screens = ScreenManager()
|
||||
%s
|
||||
def build(self) -> ScreenManager:
|
||||
self.generate_application_screens()
|
||||
return self.manager_screens
|
||||
|
||||
def generate_application_screens(self) -> NoReturn:
|
||||
"""
|
||||
Creating and adding screens to the screen manager.
|
||||
You should not change this cycle unnecessarily. He is self-sufficient.
|
||||
|
||||
If you need to add any screen, open the `View.screens.py` module and
|
||||
see how new screens are added according to the given application
|
||||
architecture.
|
||||
"""
|
||||
|
||||
for i, name_screen in enumerate(screens.keys()):
|
||||
model = screens[name_screen]["model"](%s)
|
||||
controller = screens[name_screen]["controller"](model)
|
||||
view = controller.get_view()
|
||||
view.manager_screens = self.manager_screens
|
||||
view.name = name_screen
|
||||
self.manager_screens.add_widget(view)
|
||||
%s%s
|
||||
|
||||
%s().run()
|
|
@ -0,0 +1,210 @@
|
|||
"""
|
||||
The script creates a new View package
|
||||
=====================================
|
||||
|
||||
The script creates a new View package in an existing project with an MVC
|
||||
template created using the create_project utility.
|
||||
|
||||
.. versionadded:: 1.0.0
|
||||
|
||||
.. seealso::
|
||||
|
||||
`Utility create_project <https://kivymd.readthedocs.io/en/latest/api/kivymd/tools/patterns/create_project/>`_
|
||||
|
||||
.. rubric:: Use a clean architecture for your applications.
|
||||
|
||||
To add a new view to an existing project that was created using the
|
||||
`create_project` utility, use the following command::
|
||||
|
||||
kivymd.add_view \\
|
||||
name_pattern \\
|
||||
path_to_project \\
|
||||
name_view
|
||||
|
||||
Example command::
|
||||
|
||||
kivymd.add_view \\
|
||||
MVC \\
|
||||
/Users/macbookair/Projects \\
|
||||
NewScreen
|
||||
|
||||
You can also add new views with responsive behavior to an existing project::
|
||||
|
||||
kivymd.add_view \\
|
||||
MVC \\
|
||||
/Users/macbookair/Projects \\
|
||||
NewScreen \\
|
||||
--use_responsive yes
|
||||
|
||||
For more information about adaptive design,
|
||||
`see here <https://kivymd.readthedocs.io/en/latest/components/responsivelayout/>`_.
|
||||
"""
|
||||
|
||||
__all__ = [
|
||||
"main",
|
||||
]
|
||||
|
||||
import os
|
||||
import re
|
||||
|
||||
from kivy import Logger
|
||||
|
||||
from kivymd.tools.argument_parser import ArgumentParserWithHelp
|
||||
from kivymd.tools.patterns.create_project import (
|
||||
chek_camel_case_name_project,
|
||||
create_common_responsive_module,
|
||||
create_controller,
|
||||
create_model,
|
||||
create_view,
|
||||
)
|
||||
|
||||
screens_data = """%s
|
||||
|
||||
screens = {%s
|
||||
}"""
|
||||
|
||||
screns_comment = """# The screen's dictionary contains the objects of the models and controllers
|
||||
# of the screens of the application.
|
||||
"""
|
||||
|
||||
|
||||
def main():
|
||||
"""The function of adding a new view to the project."""
|
||||
|
||||
global screens_data
|
||||
|
||||
parser = create_argument_parser()
|
||||
args = parser.parse_args()
|
||||
|
||||
# pattern_name isn't used currently, will be used if new patterns is added in future
|
||||
pattern_name = args.pattern # noqa F841
|
||||
path_to_project = args.directory
|
||||
name_view = args.name
|
||||
use_responsive = args.use_responsive
|
||||
|
||||
if not os.path.exists(path_to_project):
|
||||
parser.error(f"Project <{path_to_project}> does not exist...")
|
||||
|
||||
if name_view[-6:] != "Screen":
|
||||
parser.error(
|
||||
f"The name of the <{name_view}> screen should contain the word "
|
||||
f"'Screen' at the end.\n"
|
||||
"For example - '--name_screen MyFirstScreen ...'"
|
||||
)
|
||||
|
||||
if name_view in os.listdir(os.path.join(path_to_project, "View")):
|
||||
parser.error(
|
||||
f"The <{name_view}> view also exists in the <{path_to_project}> project..."
|
||||
)
|
||||
|
||||
# Create model.
|
||||
name_database = (
|
||||
"yes"
|
||||
if "database.py" in os.listdir(os.path.join(path_to_project, "Model"))
|
||||
else "no"
|
||||
)
|
||||
module_name = chek_camel_case_name_project(name_view)
|
||||
if not module_name:
|
||||
parser.error(
|
||||
"The name of the screen should be written in camel case style. "
|
||||
"\nFor example - 'MyFirstScreen'"
|
||||
)
|
||||
module_name = "_".join([name.lower() for name in module_name])
|
||||
path_to_project = path_to_project
|
||||
create_model(name_view, module_name, name_database, path_to_project)
|
||||
|
||||
# Create controller.
|
||||
# FIXME: This is not a very good solution in order to understand whether
|
||||
# a project uses a hot reload or not. Because the string
|
||||
# 'from kivymd.tools.hotreload.app import MDApp' in the project can just
|
||||
# be commented out and the project does not actually use hot reload.
|
||||
with open(os.path.join(path_to_project, "main.py")) as main_module:
|
||||
if "from kivymd.tools.hotreload.app import MDApp" in main_module.read():
|
||||
use_hotreload = "yes"
|
||||
else:
|
||||
use_hotreload = "no"
|
||||
create_controller(
|
||||
name_view, module_name, use_hotreload, path_to_project
|
||||
)
|
||||
# Create View.
|
||||
if use_responsive == "no":
|
||||
create_view(name_view, module_name, [], path_to_project)
|
||||
else:
|
||||
create_view(name_view, module_name, [name_view], path_to_project)
|
||||
create_common_responsive_module([name_view], path_to_project)
|
||||
# Create 'View.screens.py module'.
|
||||
create_screens_data(name_view, module_name, path_to_project)
|
||||
Logger.info(
|
||||
f"KivyMD: The {name_view} view has been added to the project..."
|
||||
)
|
||||
|
||||
|
||||
def create_screens_data(
|
||||
name_view: str, module_name: str, path_to_project: str
|
||||
) -> None:
|
||||
with open(
|
||||
os.path.join(path_to_project, "View", "screens.py")
|
||||
) as screen_module:
|
||||
screen_module = screen_module.read()
|
||||
imports = re.findall(
|
||||
"from Model.*Model|from Controller.*Controller", screen_module
|
||||
)
|
||||
screens = ""
|
||||
path_to_view = os.path.join(path_to_project, "View")
|
||||
|
||||
for name in os.listdir(path_to_view):
|
||||
if os.path.isdir(os.path.join(path_to_view, name)):
|
||||
res = re.findall("[A-Z][a-z]*", name)
|
||||
if res and len(res) == 2 and res[-1] == "Screen":
|
||||
screens += (
|
||||
"\n '%s': {"
|
||||
"\n 'model': %s,"
|
||||
"\n 'controller': %s,"
|
||||
"\n },"
|
||||
% (
|
||||
f"{res[0].lower()} {res[1].lower()}",
|
||||
f'{"".join(res)}Model',
|
||||
f'{"".join(res)}Controller',
|
||||
)
|
||||
)
|
||||
|
||||
imports.append(f"from Model.{module_name} import {name_view}Model")
|
||||
imports.append(
|
||||
f"from Controller.{module_name} import {name_view}Controller"
|
||||
)
|
||||
imports.insert(0, screns_comment)
|
||||
screens = screens_data % ("\n".join(imports), screens)
|
||||
|
||||
with open(
|
||||
os.path.join(path_to_project, "View", "screens.py"), "w"
|
||||
) as screen_module:
|
||||
screen_module.write(screens)
|
||||
|
||||
|
||||
def create_argument_parser() -> ArgumentParserWithHelp:
|
||||
parser = ArgumentParserWithHelp(
|
||||
prog="create_project.py",
|
||||
allow_abbrev=False,
|
||||
)
|
||||
parser.add_argument(
|
||||
"pattern",
|
||||
help="the name of the pattern with which the project will be created.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"directory",
|
||||
help="the directory of the project to which you want to add a new view.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"name",
|
||||
help="the name of the view to add to an existing project.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--use_responsive",
|
||||
default="no",
|
||||
help="whether to create a view with responsive behavior.",
|
||||
)
|
||||
return parser
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright (c) 2019-2021 Artem Bulgakov
|
||||
# Copyright (c) 2019-2022 Artem Bulgakov
|
||||
#
|
||||
# This file is distributed under the terms of the same license,
|
||||
# as the Kivy framework.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright (c) 2019-2021 Artem Bulgakov
|
||||
# Copyright (c) 2019-2022 Artem Bulgakov
|
||||
#
|
||||
# This file is distributed under the terms of the same license,
|
||||
# as the Kivy framework.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright (c) 2019-2021 Artem Bulgakov
|
||||
# Copyright (c) 2019-2022 Artem Bulgakov
|
||||
#
|
||||
# This file is distributed under the terms of the same license,
|
||||
# as the Kivy framework.
|
||||
|
|
|
@ -10,7 +10,7 @@ with some widget properties. For example:
|
|||
AnchorLayout
|
||||
------------
|
||||
|
||||
.. code-block::
|
||||
.. code-block:: kv
|
||||
|
||||
AnchorLayout:
|
||||
canvas:
|
||||
|
@ -20,65 +20,13 @@ AnchorLayout
|
|||
pos: self.pos
|
||||
size: self.size
|
||||
|
||||
AnchorLayout
|
||||
------------
|
||||
|
||||
.. code-block::
|
||||
|
||||
MDBoxLayout:
|
||||
md_bg_color: app.theme_cls.primary_color
|
||||
|
||||
Available options are:
|
||||
----------------------
|
||||
|
||||
- adaptive_height_
|
||||
- adaptive_width_
|
||||
- adaptive_size_
|
||||
|
||||
.. adaptive_height:
|
||||
adaptive_height
|
||||
---------------
|
||||
|
||||
.. code-block:: kv
|
||||
|
||||
adaptive_height: True
|
||||
|
||||
Equivalent
|
||||
|
||||
.. code-block:: kv
|
||||
|
||||
size_hint_y: None
|
||||
height: self.minimum_height
|
||||
|
||||
.. adaptive_width:
|
||||
adaptive_width
|
||||
MDAnchorLayout
|
||||
--------------
|
||||
|
||||
.. code-block:: kv
|
||||
|
||||
adaptive_width: True
|
||||
|
||||
Equivalent
|
||||
|
||||
.. code-block:: kv
|
||||
|
||||
size_hint_x: None
|
||||
height: self.minimum_width
|
||||
|
||||
.. adaptive_size:
|
||||
adaptive_size
|
||||
-------------
|
||||
|
||||
.. code-block:: kv
|
||||
|
||||
adaptive_size: True
|
||||
|
||||
Equivalent
|
||||
|
||||
.. code-block:: kv
|
||||
|
||||
size_hint: None, None
|
||||
size: self.minimum_size
|
||||
MDAnchorLayout:
|
||||
md_bg_color: app.theme_cls.primary_color
|
||||
"""
|
||||
|
||||
__all__ = ("MDAnchorLayout",)
|
||||
|
@ -86,7 +34,11 @@ __all__ = ("MDAnchorLayout",)
|
|||
from kivy.uix.anchorlayout import AnchorLayout
|
||||
|
||||
from kivymd.uix import MDAdaptiveWidget
|
||||
from kivymd.uix.behaviors import DeclarativeBehavior
|
||||
|
||||
|
||||
class MDAnchorLayout(AnchorLayout, MDAdaptiveWidget):
|
||||
pass
|
||||
class MDAnchorLayout(DeclarativeBehavior, AnchorLayout, MDAdaptiveWidget):
|
||||
"""
|
||||
Anchor layout class. For more information, see in the
|
||||
:class:`~kivy.uix.anchorlayout.AnchorLayout` class documentation.
|
||||
"""
|
||||
|
|
|
@ -35,8 +35,8 @@
|
|||
if not root.front_layer_color \
|
||||
else root.front_layer_color
|
||||
radius:
|
||||
[root.radius_left, root.radius_left,
|
||||
root.radius_right, root.radius_right]
|
||||
[root.radius_left, root.radius_right,
|
||||
0, 0]
|
||||
|
||||
OneLineListItem:
|
||||
id: header_button
|
||||
|
|
|
@ -31,6 +31,10 @@ Usage
|
|||
Example
|
||||
-------
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. tab:: Declarative KV styles
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from kivy.lang import Builder
|
||||
|
@ -41,8 +45,10 @@ Example
|
|||
# Your layouts.
|
||||
Builder.load_string(
|
||||
'''
|
||||
#:import os os
|
||||
#:import Window kivy.core.window.Window
|
||||
#:import IconLeftWidget kivymd.uix.list.IconLeftWidget
|
||||
#:import images_path kivymd.images_path
|
||||
|
||||
|
||||
<ItemBackdropFrontLayer@TwoLineAvatarListItem>
|
||||
|
@ -64,7 +70,7 @@ Example
|
|||
|
||||
<MyBackdropBackLayer@Image>
|
||||
size_hint: .8, .8
|
||||
source: "data/logo/kivy-icon-512.png"
|
||||
source: os.path.join(images_path, "logo", "kivymd-icon-512.png")
|
||||
pos_hint: {"center_x": .5, "center_y": .6}
|
||||
'''
|
||||
)
|
||||
|
@ -97,18 +103,75 @@ Example
|
|||
pass
|
||||
|
||||
|
||||
class TestBackdrop(MDApp):
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
|
||||
class Example(MDApp):
|
||||
def build(self):
|
||||
self.theme_cls.theme_style = "Dark"
|
||||
self.theme_cls.primary_palette = "Orange"
|
||||
return ExampleBackdrop()
|
||||
|
||||
|
||||
TestBackdrop().run()
|
||||
Example().run()
|
||||
|
||||
.. tab:: Declarative python styles
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import os
|
||||
|
||||
from kivy.core.window import Window
|
||||
from kivy.uix.image import Image
|
||||
|
||||
from kivymd import images_path
|
||||
from kivymd.uix.backdrop import MDBackdrop
|
||||
from kivymd.uix.backdrop.backdrop import (
|
||||
MDBackdropBackLayer, MDBackdropFrontLayer
|
||||
)
|
||||
from kivymd.uix.list import TwoLineAvatarListItem, IconLeftWidget
|
||||
from kivymd.uix.screen import MDScreen
|
||||
from kivymd.app import MDApp
|
||||
|
||||
|
||||
class Example(MDApp):
|
||||
def build(self):
|
||||
self.theme_cls.theme_style = "Dark"
|
||||
self.theme_cls.primary_palette = "Orange"
|
||||
|
||||
return (
|
||||
MDScreen(
|
||||
MDBackdrop(
|
||||
MDBackdropBackLayer(
|
||||
Image(
|
||||
size_hint=(0.8, 0.8),
|
||||
source=os.path.join(images_path, "logo", "kivymd-icon-512.png"),
|
||||
pos_hint={"center_x": 0.5, "center_y": 0.6},
|
||||
)
|
||||
),
|
||||
MDBackdropFrontLayer(
|
||||
TwoLineAvatarListItem(
|
||||
IconLeftWidget(icon="transfer-down"),
|
||||
text="Lower the front layer",
|
||||
secondary_text=" by 50 %",
|
||||
on_press=self.backdrop_open_by_50_percent,
|
||||
pos_hint={"top": 1},
|
||||
_no_ripple_effect=True,
|
||||
),
|
||||
),
|
||||
id="backdrop",
|
||||
title="Example Backdrop",
|
||||
radius_left="25dp",
|
||||
radius_right="0dp",
|
||||
header_text="Menu:",
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
def backdrop_open_by_50_percent(self, *args):
|
||||
self.root.ids.backdrop.open(-Window.height / 2)
|
||||
|
||||
|
||||
Example().run()
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/backdrop.gif
|
||||
:width: 280 px
|
||||
:align: center
|
||||
|
||||
.. Note:: `See full example <https://github.com/kivymd/KivyMD/wiki/Components-Backdrop>`_
|
||||
|
@ -139,7 +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
|
||||
from kivymd.uix.toolbar.toolbar import ActionTopAppBarButton, MDTopAppBar
|
||||
|
@ -151,7 +214,7 @@ with open(
|
|||
Builder.load_string(kv_file.read())
|
||||
|
||||
|
||||
class MDBackdrop(ThemableBehavior, MDFloatLayout):
|
||||
class MDBackdrop(MDFloatLayout, ThemableBehavior):
|
||||
"""
|
||||
:Events:
|
||||
:attr:`on_open`
|
||||
|
@ -167,6 +230,9 @@ class MDBackdrop(ThemableBehavior, MDFloatLayout):
|
|||
|
||||
.. versionadded:: 1.0.0
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/backdrop-anchor-title.png
|
||||
:align: center
|
||||
|
||||
:attr:`anchor_title` is an :class:`~kivy.properties.OptionProperty`
|
||||
and defaults to `'left'`.
|
||||
"""
|
||||
|
@ -175,6 +241,9 @@ class MDBackdrop(ThemableBehavior, MDFloatLayout):
|
|||
"""
|
||||
Padding for contents of the front layer.
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/backdrop-padding.png
|
||||
:align: center
|
||||
|
||||
:attr:`padding` is an :class:`~kivy.properties.ListProperty`
|
||||
and defaults to `[0, 0, 0, 0]`.
|
||||
"""
|
||||
|
@ -210,6 +279,9 @@ class MDBackdrop(ThemableBehavior, MDFloatLayout):
|
|||
"""
|
||||
Background color of back layer.
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/backdrop-back-layer-color.png
|
||||
:align: center
|
||||
|
||||
:attr:`back_layer_color` is an :class:`~kivy.properties.ColorProperty`
|
||||
and defaults to `None`.
|
||||
"""
|
||||
|
@ -218,6 +290,9 @@ class MDBackdrop(ThemableBehavior, MDFloatLayout):
|
|||
"""
|
||||
Background color of front layer.
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/backdrop-front-layer-color.png
|
||||
:align: center
|
||||
|
||||
:attr:`front_layer_color` is an :class:`~kivy.properties.ColorProperty`
|
||||
and defaults to `None`.
|
||||
"""
|
||||
|
@ -227,6 +302,9 @@ class MDBackdrop(ThemableBehavior, MDFloatLayout):
|
|||
The value of the rounding radius of the upper left corner
|
||||
of the front layer.
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/backdrop-radius-left.png
|
||||
:align: center
|
||||
|
||||
:attr:`radius_left` is an :class:`~kivy.properties.NumericProperty`
|
||||
and defaults to `16dp`.
|
||||
"""
|
||||
|
@ -244,6 +322,9 @@ class MDBackdrop(ThemableBehavior, MDFloatLayout):
|
|||
"""
|
||||
Whether to use a header above the contents of the front layer.
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/backdrop-header.png
|
||||
:align: center
|
||||
|
||||
:attr:`header` is an :class:`~kivy.properties.BooleanProperty`
|
||||
and defaults to `True`.
|
||||
"""
|
||||
|
@ -252,6 +333,9 @@ class MDBackdrop(ThemableBehavior, MDFloatLayout):
|
|||
"""
|
||||
Text of header.
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/backdrop-header-text.png
|
||||
:align: center
|
||||
|
||||
:attr:`header_text` is an :class:`~kivy.properties.StringProperty`
|
||||
and defaults to `'Header'`.
|
||||
"""
|
||||
|
@ -261,6 +345,9 @@ class MDBackdrop(ThemableBehavior, MDFloatLayout):
|
|||
The name of the icon that will be installed on the toolbar
|
||||
on the left when opening the front layer.
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/backdrop-close-icon.png
|
||||
:align: center
|
||||
|
||||
:attr:`close_icon` is an :class:`~kivy.properties.StringProperty`
|
||||
and defaults to `'close'`.
|
||||
"""
|
||||
|
@ -310,8 +397,8 @@ class MDBackdrop(ThemableBehavior, MDFloatLayout):
|
|||
_open_icon = ""
|
||||
_front_layer_open = False
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.register_event_type("on_open")
|
||||
self.register_event_type("on_close")
|
||||
Clock.schedule_once(
|
||||
|
@ -332,9 +419,12 @@ class MDBackdrop(ThemableBehavior, MDFloatLayout):
|
|||
self._open_icon = self.left_action_items[0][0]
|
||||
|
||||
def on_header(self, instance_backdrop, value: bool) -> None:
|
||||
def on_header(*args):
|
||||
if not value:
|
||||
self.ids._front_layer.remove_widget(self.ids.header_button)
|
||||
|
||||
Clock.schedule_once(on_header)
|
||||
|
||||
def open(self, open_up_to: int = 0) -> None:
|
||||
"""
|
||||
Opens the front layer.
|
||||
|
@ -425,11 +515,11 @@ class MDBackdropToolbar(MDTopAppBar):
|
|||
"""Implements a toolbar for back content."""
|
||||
|
||||
|
||||
class MDBackdropFrontLayer(BoxLayout):
|
||||
class MDBackdropFrontLayer(MDBoxLayout):
|
||||
"""Container for front content."""
|
||||
|
||||
|
||||
class MDBackdropBackLayer(BoxLayout):
|
||||
class MDBackdropBackLayer(MDBoxLayout):
|
||||
"""Container for back content."""
|
||||
|
||||
|
||||
|
@ -437,5 +527,5 @@ class _BackLayer(BoxLayout):
|
|||
pass
|
||||
|
||||
|
||||
class _FrontLayer(MDCard, FakeRectangularElevationBehavior):
|
||||
class _FrontLayer(MDCard):
|
||||
pass
|
||||
|
|
|
@ -35,7 +35,7 @@ Usage
|
|||
MDTopAppBar:
|
||||
id: toolbar
|
||||
title: "Example Banners"
|
||||
elevation: 10
|
||||
elevation: 4
|
||||
pos_hint: {'top': 1}
|
||||
|
||||
MDBoxLayout:
|
||||
|
@ -157,7 +157,6 @@ 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
|
||||
|
@ -177,7 +176,7 @@ with open(
|
|||
Builder.load_string(kv_file.read())
|
||||
|
||||
|
||||
class MDBanner(MDCard, FakeRectangularElevationBehavior):
|
||||
class MDBanner(MDCard):
|
||||
vertical_pad = NumericProperty(dp(68))
|
||||
"""
|
||||
Indent the banner at the top of the screen.
|
||||
|
|
|
@ -5,22 +5,26 @@ Behaviors
|
|||
Modules and classes implementing various behaviors for buttons etc.
|
||||
"""
|
||||
|
||||
# flake8: NOQA
|
||||
from .hover_behavior import HoverBehavior # isort:skip
|
||||
from .backgroundcolor_behavior import (
|
||||
BackgroundColorBehavior,
|
||||
SpecificBackgroundColorBehavior,
|
||||
)
|
||||
|
||||
# flake8: NOQA
|
||||
from .declarative_behavior import DeclarativeBehavior
|
||||
from .elevation import (
|
||||
CircularElevationBehavior,
|
||||
CommonElevationBehavior,
|
||||
FakeCircularElevationBehavior,
|
||||
FakeRectangularElevationBehavior,
|
||||
ObservableShadow,
|
||||
RectangularElevationBehavior,
|
||||
RoundedRectangularElevationBehavior,
|
||||
)
|
||||
from .focus_behavior import FocusBehavior
|
||||
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,8 +7,9 @@ Behaviors/Background Color
|
|||
|
||||
__all__ = ("BackgroundColorBehavior", "SpecificBackgroundColorBehavior")
|
||||
|
||||
from typing import List
|
||||
from typing import List, Union
|
||||
|
||||
from kivy.animation import Animation
|
||||
from kivy.lang import Builder
|
||||
from kivy.properties import (
|
||||
ColorProperty,
|
||||
|
@ -24,8 +25,6 @@ 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
|
||||
|
@ -38,7 +37,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
|
||||
|
@ -67,7 +66,7 @@ Builder.load_string(
|
|||
)
|
||||
|
||||
|
||||
class BackgroundColorBehavior(CommonElevationBehavior):
|
||||
class BackgroundColorBehavior:
|
||||
background = StringProperty()
|
||||
"""
|
||||
Background image path.
|
||||
|
@ -153,15 +152,26 @@ class BackgroundColorBehavior(CommonElevationBehavior):
|
|||
|
||||
_background_x = NumericProperty(0)
|
||||
_background_y = NumericProperty(0)
|
||||
_background_origin = ReferenceListProperty(
|
||||
_background_x,
|
||||
_background_y,
|
||||
)
|
||||
_background_origin = ReferenceListProperty(_background_x, _background_y)
|
||||
_md_bg_color = ColorProperty([0, 0, 0, 0])
|
||||
|
||||
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:
|
||||
|
@ -206,12 +216,14 @@ class SpecificBackgroundColorBehavior(BackgroundColorBehavior):
|
|||
super().__init__(**kwargs)
|
||||
if hasattr(self, "theme_cls"):
|
||||
self.theme_cls.bind(
|
||||
primary_palette=self._update_specific_text_color
|
||||
primary_palette=self._update_specific_text_color,
|
||||
accent_palette=self._update_specific_text_color,
|
||||
theme_style=self._update_specific_text_color,
|
||||
)
|
||||
self.bind(
|
||||
background_hue=self._update_specific_text_color,
|
||||
background_palette=self._update_specific_text_color,
|
||||
)
|
||||
self.theme_cls.bind(accent_palette=self._update_specific_text_color)
|
||||
self.theme_cls.bind(theme_style=self._update_specific_text_color)
|
||||
self.bind(background_hue=self._update_specific_text_color)
|
||||
self.bind(background_palette=self._update_specific_text_color)
|
||||
self._update_specific_text_color(None, None)
|
||||
|
||||
def _update_specific_text_color(
|
||||
|
@ -234,5 +246,17 @@ 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
|
||||
|
|
|
@ -0,0 +1,317 @@
|
|||
"""
|
||||
Behaviors/Declarative
|
||||
=====================
|
||||
|
||||
.. versionadded:: 1.0.0
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden; max-width: 100%; height: auto;">
|
||||
<iframe
|
||||
src="https://www.youtube.com/embed/_kiaJacLz8o"
|
||||
frameborder="0"
|
||||
allowfullscreen
|
||||
style="position: absolute; top: 0; left: 0; width: 100%; height: 100%;">
|
||||
</iframe>
|
||||
</div>
|
||||
|
||||
As you already know, the Kivy framework provides the best/simplest/modern
|
||||
UI creation tool that allows you to separate the logic of your application
|
||||
from the description of the properties of widgets/GUI components.
|
||||
This tool is named `KV Language <https://kivy.org/doc/stable/guide/lang.html>`_.
|
||||
|
||||
But in addition to creating a user interface using the KV Language Kivy allows
|
||||
you to create user interface elements directly in the Python code.
|
||||
And if you've ever created a user interface in Python code, you know how ugly
|
||||
it looks. Even in the simplest user interface design, which was created using
|
||||
Python code it is impossible to trace the widget tree, because in Python code
|
||||
you build the user interface in an imperative style.
|
||||
|
||||
Imperative 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 Example(MDApp):
|
||||
def build(self):
|
||||
screen = MDScreen()
|
||||
bottom_navigation = MDBottomNavigation(
|
||||
panel_color="#eeeaea",
|
||||
selected_color_background="#97ecf8",
|
||||
text_color_active="white",
|
||||
)
|
||||
|
||||
data = {
|
||||
"screen 1": {"text": "Mail", "icon": "gmail"},
|
||||
"screen 2": {"text": "Discord", "icon": "discord"},
|
||||
"screen 3": {"text": "LinkedIN", "icon": "linkedin"},
|
||||
}
|
||||
for key in data.keys():
|
||||
text = data[key]["text"]
|
||||
navigation_item = MDBottomNavigationItem(
|
||||
name=key, text=text, icon=data[key]["icon"]
|
||||
)
|
||||
navigation_item.add_widget(MDLabel(text=text, halign="center"))
|
||||
bottom_navigation.add_widget(navigation_item)
|
||||
|
||||
screen.add_widget(bottom_navigation)
|
||||
return screen
|
||||
|
||||
|
||||
Example().run()
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/bottom-navigation-styles-programming.png
|
||||
:align: center
|
||||
|
||||
Take a look at the above code example. This is a very simple UI. But looking
|
||||
at this code, you will not be able to figure the widget tree and understand
|
||||
which UI this code implements. This is named imperative programming style,
|
||||
which is used in Kivy.
|
||||
|
||||
Now let's see how the same code is implemented using the KV language,
|
||||
which uses a declarative style of describing widget properties.
|
||||
|
||||
Declarative style with KV language
|
||||
----------------------------------
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from kivy.lang import Builder
|
||||
|
||||
from kivymd.app import MDApp
|
||||
|
||||
|
||||
class Test(MDApp):
|
||||
def build(self):
|
||||
return Builder.load_string(
|
||||
'''
|
||||
MDScreen:
|
||||
|
||||
MDBottomNavigation:
|
||||
panel_color: "#eeeaea"
|
||||
selected_color_background: "#97ecf8"
|
||||
text_color_active: "white"
|
||||
|
||||
MDBottomNavigationItem:
|
||||
name: "screen 1"
|
||||
text: "Mail"
|
||||
icon: "gmail"
|
||||
|
||||
MDLabel:
|
||||
text: "Mail"
|
||||
halign: "center"
|
||||
|
||||
MDBottomNavigationItem:
|
||||
name: "screen 2"
|
||||
text: "Discord"
|
||||
icon: "discord"
|
||||
|
||||
MDLabel:
|
||||
text: "Discord"
|
||||
halign: "center"
|
||||
|
||||
MDBottomNavigationItem:
|
||||
name: "screen 3"
|
||||
text: "LinkedIN"
|
||||
icon: "linkedin"
|
||||
|
||||
MDLabel:
|
||||
text: "LinkedIN"
|
||||
halign: "center"
|
||||
'''
|
||||
)
|
||||
|
||||
|
||||
Test().run()
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/bottom-navigation-styles-programming.png
|
||||
:align: center
|
||||
|
||||
Looking at this code, we can now clearly see the widget tree and their properties.
|
||||
We can quickly navigate through the components of the screen and quickly
|
||||
change/add new properties/widgets. This is named declarative UI creation style.
|
||||
|
||||
But now the KivyMD library allows you to write Python code in a declarative style.
|
||||
Just as it is implemented in Flutter/Jetpack Compose/SwiftUI.
|
||||
|
||||
Declarative style with Python code
|
||||
----------------------------------
|
||||
|
||||
.. 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 Example(MDApp):
|
||||
def build(self):
|
||||
return (
|
||||
MDScreen(
|
||||
MDBottomNavigation(
|
||||
MDBottomNavigationItem(
|
||||
MDLabel(
|
||||
text="Mail",
|
||||
halign="center",
|
||||
),
|
||||
name="screen 1",
|
||||
text="Mail",
|
||||
icon="gmail",
|
||||
),
|
||||
MDBottomNavigationItem(
|
||||
MDLabel(
|
||||
text="Discord",
|
||||
halign="center",
|
||||
),
|
||||
name="screen 2",
|
||||
text="Discord",
|
||||
icon="discord",
|
||||
),
|
||||
MDBottomNavigationItem(
|
||||
MDLabel(
|
||||
text="LinkedIN",
|
||||
halign="center",
|
||||
),
|
||||
name="screen 3",
|
||||
text="LinkedIN",
|
||||
icon="linkedin",
|
||||
),
|
||||
panel_color="#eeeaea",
|
||||
selected_color_background="#97ecf8",
|
||||
text_color_active="white",
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
Example().run()
|
||||
|
||||
.. note:: The KivyMD library does not support creating Kivy widgets in Python
|
||||
code in a declarative style.
|
||||
|
||||
But you can still use the declarative style of creating Kivy widgets in Python code.
|
||||
To do this, you need to create a new class that will be inherited from the Kivy
|
||||
widget and the :class:`~DeclarativeBehavior` class:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from kivy.uix.boxlayout import BoxLayout
|
||||
from kivy.uix.button import Button
|
||||
|
||||
from kivymd.app import MDApp
|
||||
from kivymd.uix.behaviors import DeclarativeBehavior
|
||||
|
||||
|
||||
class DeclarativeStyleBoxLayout(DeclarativeBehavior, BoxLayout):
|
||||
pass
|
||||
|
||||
|
||||
class Example(MDApp):
|
||||
def build(self):
|
||||
return (
|
||||
DeclarativeStyleBoxLayout(
|
||||
Button(),
|
||||
Button(),
|
||||
orientation="vertical",
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
Example().run()
|
||||
|
||||
Get objects by identifiers
|
||||
--------------------------
|
||||
|
||||
In the declarative style in Python code, the ids parameter of the specified
|
||||
widget will return only the id of the child widget/container, ignoring other ids.
|
||||
Therefore, to get objects by identifiers in declarative style in Python code,
|
||||
you must specify all the container ids in which the widget is nested until you
|
||||
get to the desired id:
|
||||
|
||||
.. code-block::
|
||||
|
||||
from kivymd.app import MDApp
|
||||
from kivymd.uix.boxlayout import MDBoxLayout
|
||||
from kivymd.uix.button import MDRaisedButton
|
||||
from kivymd.uix.floatlayout import MDFloatLayout
|
||||
|
||||
|
||||
class Example(MDApp):
|
||||
def build(self):
|
||||
return (
|
||||
MDBoxLayout(
|
||||
MDFloatLayout(
|
||||
MDRaisedButton(
|
||||
id="button_1",
|
||||
text="Button 1",
|
||||
pos_hint={"center_x": 0.5, "center_y": 0.5},
|
||||
),
|
||||
id="box_container_1",
|
||||
),
|
||||
MDBoxLayout(
|
||||
MDFloatLayout(
|
||||
MDRaisedButton(
|
||||
id="button_2",
|
||||
text="Button 2",
|
||||
pos_hint={"center_x": 0.5, "center_y": 0.5},
|
||||
),
|
||||
id="float_container",
|
||||
),
|
||||
id="box_container_2",
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
def on_start(self):
|
||||
# {
|
||||
# 'box_container_1': <kivymd.uix.floatlayout.MDFloatLayout>,
|
||||
# 'box_container_2': <kivymd.uix.boxlayout.MDBoxLayout object>
|
||||
# }
|
||||
print(self.root.ids)
|
||||
|
||||
# <kivymd.uix.button.button.MDRaisedButton>
|
||||
print(self.root.ids.box_container_2.ids.float_container.ids.button_2)
|
||||
|
||||
|
||||
Example().run()
|
||||
|
||||
Yes, this is not a very good solution, but I think it will be fixed soon.
|
||||
|
||||
.. warning:: Declarative programming style in Python code in the KivyMD library
|
||||
is an experimental feature. Therefore, if you receive errors, do not hesitate
|
||||
to create new issue in the KivyMD repository.
|
||||
"""
|
||||
|
||||
from kivy.properties import StringProperty
|
||||
from kivy.uix.widget import Widget
|
||||
|
||||
|
||||
class DeclarativeBehavior:
|
||||
"""
|
||||
Implements the creation and addition of child widgets as declarative
|
||||
programming style.
|
||||
"""
|
||||
|
||||
id = StringProperty()
|
||||
"""
|
||||
Widget ID.
|
||||
|
||||
:attr:`id` is an :class:`~kivy.properties.StringProperty`
|
||||
and defaults to `''`.
|
||||
"""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
|
||||
for child in args:
|
||||
if issubclass(child.__class__, Widget):
|
||||
self.add_widget(child)
|
||||
if hasattr(child, "id") and child.id:
|
||||
self.ids[child.id] = child
|
|
@ -100,23 +100,35 @@ class FocusBehavior(HoverBehavior, ButtonBehavior):
|
|||
def on_enter(self):
|
||||
"""Called when mouse enter the bbox of the widget."""
|
||||
|
||||
if hasattr(self, "md_bg_color") and self.focus_behavior:
|
||||
if (
|
||||
hasattr(self, "md_bg_color") or hasattr(self, "bg_color")
|
||||
) and self.focus_behavior:
|
||||
if hasattr(self, "theme_cls") and not self.focus_color:
|
||||
self.md_bg_color = self.theme_cls.bg_normal
|
||||
color = self.theme_cls.bg_normal
|
||||
else:
|
||||
if not self.focus_color:
|
||||
self.md_bg_color = App.get_running_app().theme_cls.bg_normal
|
||||
color = App.get_running_app().theme_cls.bg_normal
|
||||
else:
|
||||
self.md_bg_color = self.focus_color
|
||||
color = self.focus_color
|
||||
self._set_bg_color(color)
|
||||
|
||||
def on_leave(self):
|
||||
"""Called when the mouse exit the widget."""
|
||||
|
||||
if hasattr(self, "md_bg_color") and self.focus_behavior:
|
||||
if (
|
||||
hasattr(self, "md_bg_color") or hasattr(self, "bg_color")
|
||||
) and self.focus_behavior:
|
||||
if hasattr(self, "theme_cls") and not self.unfocus_color:
|
||||
self.md_bg_color = self.theme_cls.bg_light
|
||||
color = self.theme_cls.bg_light
|
||||
else:
|
||||
if not self.unfocus_color:
|
||||
self.md_bg_color = App.get_running_app().theme_cls.bg_light
|
||||
color = App.get_running_app().theme_cls.bg_light
|
||||
else:
|
||||
self.md_bg_color = self.unfocus_color
|
||||
color = self.unfocus_color
|
||||
self._set_bg_color(color)
|
||||
|
||||
def _set_bg_color(self, color):
|
||||
if hasattr(self, "md_bg_color"):
|
||||
self.md_bg_color = color
|
||||
elif hasattr(self, "bg_color"):
|
||||
self.bg_color = color
|
||||
|
|
|
@ -111,7 +111,7 @@ from kivy.properties import (
|
|||
from kivy.uix.behaviors import ToggleButtonBehavior
|
||||
|
||||
|
||||
class CommonRipple(object):
|
||||
class CommonRipple:
|
||||
"""Base class for ripple effect."""
|
||||
|
||||
ripple_rad_default = NumericProperty(1)
|
||||
|
|
|
@ -0,0 +1,133 @@
|
|||
"""
|
||||
Behaviors/Rotate
|
||||
================
|
||||
|
||||
.. versionadded:: 1.1.0
|
||||
|
||||
Base class for controlling the rotate of the widget.
|
||||
|
||||
.. note:: See `kivy.graphics.Rotate
|
||||
<https://kivy.org/doc/stable/api-kivy.graphics.html#kivy.graphics.Rotate>`_
|
||||
for more information.
|
||||
|
||||
Kivy
|
||||
----
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from kivy.animation import Animation
|
||||
from kivy.lang import Builder
|
||||
from kivy.app import App
|
||||
from kivy.properties import NumericProperty
|
||||
from kivy.uix.button import Button
|
||||
|
||||
KV = '''
|
||||
Screen:
|
||||
|
||||
RotateButton:
|
||||
size_hint: .5, .5
|
||||
pos_hint: {"center_x": .5, "center_y": .5}
|
||||
on_release: app.change_rotate(self)
|
||||
|
||||
canvas.before:
|
||||
PushMatrix
|
||||
Rotate:
|
||||
angle: self.rotate_value_angle
|
||||
axis: 0, 0, 1
|
||||
origin: self.center
|
||||
canvas.after:
|
||||
PopMatrix
|
||||
'''
|
||||
|
||||
|
||||
class RotateButton(Button):
|
||||
rotate_value_angle = NumericProperty(0)
|
||||
|
||||
|
||||
class Test(App):
|
||||
def build(self):
|
||||
return Builder.load_string(KV)
|
||||
|
||||
def change_rotate(self, instance_button: Button) -> None:
|
||||
Animation(rotate_value_angle=45, d=0.3).start(instance_button)
|
||||
|
||||
|
||||
Test().run()
|
||||
|
||||
KivyMD
|
||||
------
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from kivy.animation import Animation
|
||||
from kivy.lang import Builder
|
||||
from kivy.uix.behaviors import ButtonBehavior
|
||||
|
||||
from kivymd.app import MDApp
|
||||
from kivymd.uix.behaviors import RotateBehavior
|
||||
from kivymd.uix.boxlayout import MDBoxLayout
|
||||
|
||||
KV = '''
|
||||
MDScreen:
|
||||
|
||||
RotateBox:
|
||||
size_hint: .5, .5
|
||||
pos_hint: {"center_x": .5, "center_y": .5}
|
||||
on_release: app.change_rotate(self)
|
||||
md_bg_color: "red"
|
||||
'''
|
||||
|
||||
|
||||
class RotateBox(ButtonBehavior, RotateBehavior, MDBoxLayout):
|
||||
pass
|
||||
|
||||
|
||||
class Test(MDApp):
|
||||
def build(self):
|
||||
return Builder.load_string(KV)
|
||||
|
||||
def change_rotate(self, instance_button: RotateBox) -> None:
|
||||
Animation(rotate_value_angle=45, d=0.3).start(instance_button)
|
||||
|
||||
|
||||
Test().run()
|
||||
"""
|
||||
|
||||
__all__ = ("RotateBehavior",)
|
||||
|
||||
from kivy.lang import Builder
|
||||
from kivy.properties import ListProperty, NumericProperty
|
||||
|
||||
Builder.load_string(
|
||||
"""
|
||||
<RotateBehavior>
|
||||
canvas.before:
|
||||
PushMatrix
|
||||
Rotate:
|
||||
angle: self.rotate_value_angle
|
||||
axis: tuple(self.rotate_value_axis)
|
||||
origin: self.center
|
||||
canvas.after:
|
||||
PopMatrix
|
||||
"""
|
||||
)
|
||||
|
||||
|
||||
class RotateBehavior:
|
||||
"""Base class for controlling the rotate of the widget."""
|
||||
|
||||
rotate_value_angle = NumericProperty(0)
|
||||
"""
|
||||
Property for getting/setting the angle of the rotation.
|
||||
|
||||
:attr:`rotate_value_angle` is an :class:`~kivy.properties.NumericProperty`
|
||||
and defaults to `0`.
|
||||
"""
|
||||
|
||||
rotate_value_axis = ListProperty((0, 0, 1))
|
||||
"""
|
||||
Property for getting/setting the axis of the rotation.
|
||||
|
||||
:attr:`rotate_value_axis` is an :class:`~kivy.properties.ListProperty`
|
||||
and defaults to `(0, 0, 1)`.
|
||||
"""
|
|
@ -0,0 +1,156 @@
|
|||
"""
|
||||
Behaviors/Scale
|
||||
===============
|
||||
|
||||
.. versionadded:: 1.1.0
|
||||
|
||||
Base class for controlling the scale of the widget.
|
||||
|
||||
.. note:: See `kivy.graphics.Rotate
|
||||
<https://kivy.org/doc/stable/api-kivy.graphics.html#kivy.graphics.Scale>`_
|
||||
for more information.
|
||||
|
||||
Kivy
|
||||
----
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from kivy.animation import Animation
|
||||
from kivy.lang import Builder
|
||||
from kivy.properties import NumericProperty
|
||||
from kivy.uix.button import Button
|
||||
from kivy.app import App
|
||||
|
||||
|
||||
KV = '''
|
||||
Screen:
|
||||
|
||||
ScaleButton:
|
||||
size_hint: .5, .5
|
||||
pos_hint: {"center_x": .5, "center_y": .5}
|
||||
on_release: app.change_scale(self)
|
||||
|
||||
canvas.before:
|
||||
PushMatrix
|
||||
Scale:
|
||||
x: self.scale_value_x
|
||||
y: self.scale_value_y
|
||||
z: self.scale_value_x
|
||||
origin: self.center
|
||||
canvas.after:
|
||||
PopMatrix
|
||||
'''
|
||||
|
||||
|
||||
class ScaleButton(Button):
|
||||
scale_value_x = NumericProperty(1)
|
||||
scale_value_y = NumericProperty(1)
|
||||
scale_value_z = NumericProperty(1)
|
||||
|
||||
|
||||
class Test(App):
|
||||
def build(self):
|
||||
return Builder.load_string(KV)
|
||||
|
||||
def change_scale(self, instance_button: Button) -> None:
|
||||
Animation(
|
||||
scale_value_x=0.5,
|
||||
scale_value_y=0.5,
|
||||
scale_value_z=0.5,
|
||||
d=0.3,
|
||||
).start(instance_button)
|
||||
|
||||
|
||||
Test().run()
|
||||
|
||||
KivyMD
|
||||
------
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from kivy.animation import Animation
|
||||
from kivy.lang import Builder
|
||||
from kivy.uix.behaviors import ButtonBehavior
|
||||
|
||||
from kivymd.app import MDApp
|
||||
from kivymd.uix.behaviors import ScaleBehavior
|
||||
from kivymd.uix.boxlayout import MDBoxLayout
|
||||
|
||||
KV = '''
|
||||
MDScreen:
|
||||
|
||||
ScaleBox:
|
||||
size_hint: .5, .5
|
||||
pos_hint: {"center_x": .5, "center_y": .5}
|
||||
on_release: app.change_scale(self)
|
||||
md_bg_color: "red"
|
||||
'''
|
||||
|
||||
|
||||
class ScaleBox(ButtonBehavior, ScaleBehavior, MDBoxLayout):
|
||||
pass
|
||||
|
||||
|
||||
class Test(MDApp):
|
||||
def build(self):
|
||||
return Builder.load_string(KV)
|
||||
|
||||
def change_scale(self, instance_button: ScaleBox) -> None:
|
||||
Animation(
|
||||
scale_value_x=0.5,
|
||||
scale_value_y=0.5,
|
||||
scale_value_z=0.5,
|
||||
d=0.3,
|
||||
).start(instance_button)
|
||||
|
||||
|
||||
Test().run()
|
||||
"""
|
||||
|
||||
__all__ = ("ScaleBehavior",)
|
||||
|
||||
from kivy.lang import Builder
|
||||
from kivy.properties import NumericProperty
|
||||
|
||||
Builder.load_string(
|
||||
"""
|
||||
<ScaleBehavior>
|
||||
canvas.before:
|
||||
PushMatrix
|
||||
Scale:
|
||||
x: self.scale_value_x
|
||||
y: self.scale_value_y
|
||||
z: self.scale_value_x
|
||||
origin: self.center
|
||||
canvas.after:
|
||||
PopMatrix
|
||||
"""
|
||||
)
|
||||
|
||||
|
||||
class ScaleBehavior:
|
||||
"""Base class for controlling the scale of the widget."""
|
||||
|
||||
scale_value_x = NumericProperty(1)
|
||||
"""
|
||||
X-axis value.
|
||||
|
||||
:attr:`scale_value_x` is an :class:`~kivy.properties.NumericProperty`
|
||||
and defaults to `1`.
|
||||
"""
|
||||
|
||||
scale_value_y = NumericProperty(1)
|
||||
"""
|
||||
Y-axis value.
|
||||
|
||||
:attr:`scale_value_y` is an :class:`~kivy.properties.NumericProperty`
|
||||
and defaults to `1`.
|
||||
"""
|
||||
|
||||
scale_value_z = NumericProperty(1)
|
||||
"""
|
||||
Z-axis value.
|
||||
|
||||
:attr:`scale_value_z` is an :class:`~kivy.properties.NumericProperty`
|
||||
and defaults to `1`.
|
||||
"""
|
|
@ -0,0 +1,134 @@
|
|||
"""
|
||||
Behaviors/Stencil
|
||||
=================
|
||||
|
||||
.. versionadded:: 1.1.0
|
||||
|
||||
Base class for controlling the stencil instructions of the widget.
|
||||
|
||||
.. note:: See `Stencil instructions
|
||||
<https://kivy.org/doc/stable/api-kivy.graphics.stencil_instructions.html>`_
|
||||
for more information.
|
||||
|
||||
Kivy
|
||||
----
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from kivy.lang import Builder
|
||||
from kivy.app import App
|
||||
|
||||
KV = '''
|
||||
Carousel:
|
||||
|
||||
Button:
|
||||
size_hint: .9, .8
|
||||
pos_hint: {"center_x": .5, "center_y": .5}
|
||||
|
||||
canvas.before:
|
||||
StencilPush
|
||||
RoundedRectangle:
|
||||
pos: root.pos
|
||||
size: root.size
|
||||
StencilUse
|
||||
canvas.after:
|
||||
StencilUnUse
|
||||
RoundedRectangle:
|
||||
pos: root.pos
|
||||
size: root.size
|
||||
StencilPop
|
||||
'''
|
||||
|
||||
|
||||
class Test(App):
|
||||
def build(self):
|
||||
return Builder.load_string(KV)
|
||||
|
||||
|
||||
Test().run()
|
||||
|
||||
KivyMD
|
||||
------
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from kivy.lang import Builder
|
||||
|
||||
from kivymd.app import MDApp
|
||||
from kivymd.uix.behaviors import StencilBehavior
|
||||
from kivymd.uix.fitimage import FitImage
|
||||
|
||||
KV = '''
|
||||
#:import os os
|
||||
#:import images_path kivymd.images_path
|
||||
|
||||
|
||||
MDCarousel:
|
||||
|
||||
StencilImage:
|
||||
size_hint: .9, .8
|
||||
pos_hint: {"center_x": .5, "center_y": .5}
|
||||
source: os.path.join(images_path, "logo", "kivymd-icon-512.png")
|
||||
'''
|
||||
|
||||
|
||||
class StencilImage(FitImage, StencilBehavior):
|
||||
pass
|
||||
|
||||
|
||||
class Test(MDApp):
|
||||
def build(self):
|
||||
return Builder.load_string(KV)
|
||||
|
||||
|
||||
Test().run()
|
||||
"""
|
||||
|
||||
__all__ = ("StencilBehavior",)
|
||||
|
||||
from kivy.lang import Builder
|
||||
from kivy.properties import VariableListProperty
|
||||
|
||||
Builder.load_string(
|
||||
"""
|
||||
<StencilBehavior>
|
||||
canvas.before:
|
||||
StencilPush
|
||||
RoundedRectangle:
|
||||
pos: root.pos
|
||||
size: root.size
|
||||
# FIXME: Sometimes the radius has the value [], which get a
|
||||
# `GraphicException: Invalid radius value, must be list of tuples/numerics` error
|
||||
radius: root.radius if root.radius else [0, 0, 0, 0]
|
||||
StencilUse
|
||||
canvas.after:
|
||||
StencilUnUse
|
||||
RoundedRectangle:
|
||||
pos: root.pos
|
||||
size: root.size
|
||||
# FIXME: Sometimes the radius has the value [], which get a
|
||||
# `GraphicException: Invalid radius value, must be list of tuples/numerics` error
|
||||
radius: root.radius if root.radius else [0, 0, 0, 0]
|
||||
StencilPop
|
||||
"""
|
||||
)
|
||||
|
||||
|
||||
class StencilBehavior:
|
||||
"""Base class for controlling the stencil instructions of the widget."""
|
||||
|
||||
radius = VariableListProperty([0], length=4)
|
||||
"""
|
||||
Canvas radius.
|
||||
|
||||
.. versionadded:: 1.0.0
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# Top left corner slice.
|
||||
MDWidget:
|
||||
radius: [25, 0, 0, 0]
|
||||
|
||||
:attr:`radius` is an :class:`~kivy.properties.VariableListProperty`
|
||||
and defaults to `[0, 0, 0, 0]`.
|
||||
"""
|
|
@ -14,19 +14,24 @@ example:
|
|||
pass
|
||||
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. tab:: Declarative KV style
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from kivy.lang import Builder
|
||||
|
||||
from kivymd.app import MDApp
|
||||
from kivymd.uix.behaviors.toggle_behavior import MDToggleButton
|
||||
from kivymd.uix.button import MDRectangleFlatButton
|
||||
from kivymd.uix.button import MDFlatButton
|
||||
|
||||
KV = '''
|
||||
Screen:
|
||||
MDScreen:
|
||||
|
||||
MDBoxLayout:
|
||||
adaptive_size: True
|
||||
spacing: "12dp"
|
||||
pos_hint: {"center_x": .5, "center_y": .5}
|
||||
|
||||
MyToggleButton:
|
||||
|
@ -43,30 +48,68 @@ example:
|
|||
'''
|
||||
|
||||
|
||||
class MyToggleButton(MDRectangleFlatButton, MDToggleButton):
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
self.background_down = self.theme_cls.primary_light
|
||||
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 Builder.load_string(KV)
|
||||
|
||||
|
||||
Test().run()
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/toggle-button-1.gif
|
||||
:align: center
|
||||
.. tab:: Declarative python style
|
||||
|
||||
.. 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)
|
||||
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
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/toggle-button-2.gif
|
||||
|
||||
class MyToggleButton(MDFlatButton, MDToggleButton):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.background_down = self.theme_cls.primary_color
|
||||
|
||||
|
||||
class Test(MDApp):
|
||||
def build(self):
|
||||
self.theme_cls.theme_style = "Dark"
|
||||
self.theme_cls.primary_palette = "Orange"
|
||||
return (
|
||||
MDScreen(
|
||||
MDBoxLayout(
|
||||
MyToggleButton(
|
||||
text="Show ads",
|
||||
group="x",
|
||||
),
|
||||
MyToggleButton(
|
||||
text="Do not show ads",
|
||||
group="x",
|
||||
),
|
||||
MyToggleButton(
|
||||
text="Does not matter",
|
||||
group="x",
|
||||
),
|
||||
adaptive_size=True,
|
||||
spacing="12dp",
|
||||
pos_hint={"center_x": .5, "center_y": .5},
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
Test().run()
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/toggle-button-1.gif
|
||||
:align: center
|
||||
|
||||
You can inherit the ``MyToggleButton`` class only from the following classes
|
||||
|
@ -88,6 +131,7 @@ from kivy.properties import BooleanProperty, ColorProperty
|
|||
from kivy.uix.behaviors import ToggleButtonBehavior
|
||||
|
||||
from kivymd.uix.button import (
|
||||
ButtonContentsIconText,
|
||||
MDFillRoundFlatButton,
|
||||
MDFillRoundFlatIconButton,
|
||||
MDFlatButton,
|
||||
|
@ -149,7 +193,8 @@ 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 classes in the list {classinfo}"
|
||||
f"Class {self.__class__} must be inherited from one of the "
|
||||
f"classes in the list {classinfo}"
|
||||
)
|
||||
if (
|
||||
not self.background_normal
|
||||
|
@ -165,10 +210,12 @@ class MDToggleButton(ToggleButtonBehavior):
|
|||
):
|
||||
self.__is_filled = True
|
||||
self.background_normal = self.theme_cls.primary_color
|
||||
# If not the background_normal must be the same as the inherited one:
|
||||
# If not background_normal must be the same as the inherited one.
|
||||
else:
|
||||
self.background_normal = self.md_bg_color[:]
|
||||
# If no background_down is setted:
|
||||
self.background_normal = (
|
||||
self.md_bg_color[:] if self.md_bg_color else (0, 0, 0, 0)
|
||||
)
|
||||
# If no background_down is setter.
|
||||
if (
|
||||
not self.background_down
|
||||
): # This means that if the value == [] or None will return True.
|
||||
|
@ -200,3 +247,6 @@ class MDToggleButton(ToggleButtonBehavior):
|
|||
): # If the background is transparent, the font color must be the
|
||||
# primary color.
|
||||
self.text_color = self.font_color_normal
|
||||
|
||||
if issubclass(self.__class__, ButtonContentsIconText):
|
||||
self.icon_color = self.text_color
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
#:import sm kivy.uix.screenmanager
|
||||
#:import STANDARD_INCREMENT kivymd.material_resources.STANDARD_INCREMENT
|
||||
|
||||
|
||||
|
@ -9,7 +8,7 @@
|
|||
|
||||
ScreenManager:
|
||||
id: tab_manager
|
||||
transition: sm.FadeTransition(duration=.2)
|
||||
transition: root.transition(duration=root.transition_duration)
|
||||
on_current:
|
||||
root.dispatch( \
|
||||
"on_switch_tabs", \
|
||||
|
@ -96,7 +95,7 @@
|
|||
radius: [16,]
|
||||
size: root._selected_region_width, dp(32)
|
||||
pos:
|
||||
self.center_x - self.width - dp(8), \
|
||||
self.center_x - root._selected_region_width / 2, \
|
||||
self.center_y - (dp(16))
|
||||
|
||||
MDLabel:
|
||||
|
|
|
@ -62,6 +62,10 @@ For ease of understanding, this code works like this:
|
|||
Example
|
||||
-------
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. tab:: Declarative KV style
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from kivy.lang import Builder
|
||||
|
@ -73,14 +77,15 @@ Example
|
|||
|
||||
def build(self):
|
||||
self.theme_cls.material_style = "M3"
|
||||
self.theme_cls.theme_style = "Dark"
|
||||
return Builder.load_string(
|
||||
'''
|
||||
MDScreen:
|
||||
|
||||
MDBottomNavigation:
|
||||
panel_color: "#eeeaea"
|
||||
selected_color_background: "#97ecf8"
|
||||
text_color_active: 0, 0, 0, 1
|
||||
#panel_color: "#eeeaea"
|
||||
selected_color_background: "orange"
|
||||
text_color_active: "lightgrey"
|
||||
|
||||
MDBottomNavigationItem:
|
||||
name: 'screen 1'
|
||||
|
@ -94,12 +99,12 @@ Example
|
|||
|
||||
MDBottomNavigationItem:
|
||||
name: 'screen 2'
|
||||
text: 'Discord'
|
||||
icon: 'discord'
|
||||
text: 'Twitter'
|
||||
icon: 'twitter'
|
||||
badge_icon: "numeric-5"
|
||||
|
||||
MDLabel:
|
||||
text: 'Discord'
|
||||
text: 'Twitter'
|
||||
halign: 'center'
|
||||
|
||||
MDBottomNavigationItem:
|
||||
|
@ -116,6 +121,62 @@ Example
|
|||
|
||||
Test().run()
|
||||
|
||||
.. tab:: Declarative python style
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from kivymd.app import MDApp
|
||||
from kivymd.uix.bottomnavigation import MDBottomNavigation, MDBottomNavigationItem
|
||||
from kivymd.uix.label import MDLabel
|
||||
from kivymd.uix.screen import MDScreen
|
||||
|
||||
|
||||
class Test(MDApp):
|
||||
def build(self):
|
||||
self.theme_cls.material_style = "M3"
|
||||
self.theme_cls.theme_style = "Dark"
|
||||
return (
|
||||
MDScreen(
|
||||
MDBottomNavigation(
|
||||
MDBottomNavigationItem(
|
||||
MDLabel(
|
||||
text='Mail',
|
||||
halign='center',
|
||||
),
|
||||
name='screen 1',
|
||||
text='Mail',
|
||||
icon='gmail',
|
||||
badge_icon="numeric-10",
|
||||
),
|
||||
MDBottomNavigationItem(
|
||||
MDLabel(
|
||||
text='Twitter',
|
||||
halign='center',
|
||||
),
|
||||
name='screen 1',
|
||||
text='Twitter',
|
||||
icon='twitter',
|
||||
badge_icon="numeric-10",
|
||||
),
|
||||
MDBottomNavigationItem(
|
||||
MDLabel(
|
||||
text='LinkedIN',
|
||||
halign='center',
|
||||
),
|
||||
name='screen 1',
|
||||
text='LinkedIN',
|
||||
icon='linkedin',
|
||||
badge_icon="numeric-10",
|
||||
),
|
||||
selected_color_background="orange",
|
||||
text_color_active="lightgrey",
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
Test().run()
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/bottom-navigation.gif
|
||||
:align: center
|
||||
|
||||
|
@ -192,13 +253,13 @@ from kivy.properties import (
|
|||
)
|
||||
from kivy.uix.behaviors import ButtonBehavior
|
||||
from kivy.uix.boxlayout import BoxLayout
|
||||
from kivy.uix.screenmanager import ScreenManagerException
|
||||
from kivy.uix.screenmanager import FadeTransition, ScreenManagerException
|
||||
|
||||
from kivymd import uix_path
|
||||
from kivymd.material_resources import STANDARD_INCREMENT
|
||||
from kivymd.theming import ThemableBehavior, ThemeManager
|
||||
from kivymd.uix.anchorlayout import MDAnchorLayout
|
||||
from kivymd.uix.behaviors import FakeRectangularElevationBehavior
|
||||
from kivymd.uix.behaviors import CommonElevationBehavior, DeclarativeBehavior
|
||||
from kivymd.uix.behaviors.backgroundcolor_behavior import (
|
||||
SpecificBackgroundColorBehavior,
|
||||
)
|
||||
|
@ -364,8 +425,8 @@ class MDTab(MDScreen, ThemableBehavior):
|
|||
and defaults to `''`.
|
||||
"""
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.index = 0
|
||||
self.parent_widget = None
|
||||
self.register_event_type("on_tab_touch_down")
|
||||
|
@ -407,16 +468,12 @@ class MDBottomNavigationItem(MDTab):
|
|||
and defaults to `None`.
|
||||
"""
|
||||
|
||||
def on_tab_press(self, *args) -> None:
|
||||
"""Called when clicking on a panel item."""
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
bottom_navigation_object = self.parent_widget
|
||||
bottom_navigation_header_object = (
|
||||
bottom_navigation_object.previous_tab.header
|
||||
)
|
||||
bottom_navigation_object.ids.tab_manager.current = self.name
|
||||
|
||||
if bottom_navigation_object.previous_tab is not self:
|
||||
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
|
||||
|
@ -435,7 +492,21 @@ class MDBottomNavigationItem(MDTab):
|
|||
).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_tab_press(self, *args) -> None:
|
||||
"""Called when clicking on a panel item."""
|
||||
|
||||
bottom_navigation_object = self.parent_widget
|
||||
bottom_navigation_header_object = (
|
||||
bottom_navigation_object.previous_tab.header
|
||||
)
|
||||
|
||||
if bottom_navigation_object.previous_tab is not self:
|
||||
self.animate_header(
|
||||
bottom_navigation_object, bottom_navigation_header_object
|
||||
)
|
||||
|
||||
super().on_tab_press(*args)
|
||||
|
||||
def on_disabled(
|
||||
self, instance_bottom_navigation_item, disabled_value: bool
|
||||
|
@ -463,7 +534,7 @@ class TabbedPanelBase(
|
|||
and defaults to `None`.
|
||||
"""
|
||||
|
||||
previous_tab = ObjectProperty()
|
||||
previous_tab = ObjectProperty(None, aloownone=True)
|
||||
"""
|
||||
:attr:`previous_tab` is an :class:`~MDTab` and defaults to `None`.
|
||||
"""
|
||||
|
@ -479,7 +550,7 @@ class TabbedPanelBase(
|
|||
tabs = ListProperty()
|
||||
|
||||
|
||||
class MDBottomNavigation(TabbedPanelBase):
|
||||
class MDBottomNavigation(DeclarativeBehavior, TabbedPanelBase):
|
||||
"""
|
||||
A bottom navigation that is implemented by delegating all items to a
|
||||
:class:`~kivy.uix.screenmanager.ScreenManager`.
|
||||
|
@ -492,6 +563,26 @@ class MDBottomNavigation(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.
|
||||
|
@ -594,14 +685,15 @@ class MDBottomNavigation(TabbedPanelBase):
|
|||
and defaults to `False`.
|
||||
"""
|
||||
|
||||
widget_index = NumericProperty(0)
|
||||
|
||||
# Text active color if it is selected.
|
||||
_active_color = ColorProperty([1, 1, 1, 1])
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
self.register_event_type("on_switch_tabs")
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.previous_tab = None
|
||||
self.widget_index = 0
|
||||
self.register_event_type("on_switch_tabs")
|
||||
super().__init__(*args, **kwargs)
|
||||
self.theme_cls.bind(material_style=self.refresh_tabs)
|
||||
Window.bind(on_resize=self.on_resize)
|
||||
Clock.schedule_once(lambda x: self.on_resize())
|
||||
|
@ -660,9 +752,12 @@ class MDBottomNavigation(TabbedPanelBase):
|
|||
def on_selected_color_background(
|
||||
self, instance_bottom_navigation, color: list
|
||||
) -> None:
|
||||
def on_selected_color_background(*args):
|
||||
for tab in self.ids.tab_bar.children:
|
||||
tab.selected_color_background = color
|
||||
|
||||
Clock.schedule_once(on_selected_color_background)
|
||||
|
||||
def on_use_text(
|
||||
self, instance_bottom_navigation, use_text_value: bool
|
||||
) -> None:
|
||||
|
@ -698,6 +793,7 @@ class MDBottomNavigation(TabbedPanelBase):
|
|||
def on_text_color_active(
|
||||
self, instance_bottom_navigation, color: list
|
||||
) -> None:
|
||||
def on_text_color_active(*args):
|
||||
MDBottomNavigationHeader.text_color_active = color
|
||||
self.text_color_active = color
|
||||
for tab in self.ids.tab_bar.children:
|
||||
|
@ -705,6 +801,8 @@ class MDBottomNavigation(TabbedPanelBase):
|
|||
if tab.active:
|
||||
tab._text_color_normal = color
|
||||
|
||||
Clock.schedule_once(on_text_color_active)
|
||||
|
||||
def on_switch_tabs(self, bottom_navigation_item, name_tab: str) -> None:
|
||||
"""
|
||||
Called when switching tabs. Returns the object of the tab to be opened.
|
||||
|
@ -759,8 +857,6 @@ class MDBottomNavigation(TabbedPanelBase):
|
|||
|
||||
|
||||
class MDBottomNavigationBar(
|
||||
ThemableBehavior,
|
||||
FakeRectangularElevationBehavior,
|
||||
MDFloatLayout,
|
||||
ThemableBehavior, CommonElevationBehavior, MDFloatLayout
|
||||
):
|
||||
pass
|
||||
|
|
|
@ -34,7 +34,7 @@ Usage :class:`~MDListBottomSheet`
|
|||
MDTopAppBar:
|
||||
title: "Example BottomSheet"
|
||||
pos_hint: {"top": 1}
|
||||
elevation: 10
|
||||
elevation: 4
|
||||
|
||||
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: 10
|
||||
elevation: 4
|
||||
|
||||
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: 10
|
||||
elevation: 4
|
||||
|
||||
MDRaisedButton:
|
||||
text: "Open custom bottom sheet"
|
||||
|
|
|
@ -8,7 +8,7 @@ with some widget properties. For example:
|
|||
BoxLayout
|
||||
---------
|
||||
|
||||
.. code-block::
|
||||
.. code-block:: kv
|
||||
|
||||
BoxLayout:
|
||||
size_hint_y: None
|
||||
|
@ -24,7 +24,7 @@ BoxLayout
|
|||
MDBoxLayout
|
||||
-----------
|
||||
|
||||
.. code-block::
|
||||
.. code-block:: kv
|
||||
|
||||
MDBoxLayout:
|
||||
adaptive_height: True
|
||||
|
@ -88,7 +88,13 @@ __all__ = ("MDBoxLayout",)
|
|||
from kivy.uix.boxlayout import BoxLayout
|
||||
|
||||
from kivymd.uix import MDAdaptiveWidget
|
||||
from kivymd.uix.behaviors import DeclarativeBehavior
|
||||
|
||||
|
||||
class MDBoxLayout(BoxLayout, MDAdaptiveWidget):
|
||||
pass
|
||||
class MDBoxLayout(DeclarativeBehavior, BoxLayout, MDAdaptiveWidget):
|
||||
"""
|
||||
Box layout class.
|
||||
|
||||
For more information, see in the
|
||||
:class:`~kivy.uix.boxlayout.BoxLayout` class documentation.
|
||||
"""
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
# NOQA F401
|
||||
from .button import (
|
||||
BaseButton,
|
||||
ButtonContentsIconText,
|
||||
MDFillRoundFlatButton,
|
||||
MDFillRoundFlatIconButton,
|
||||
MDFlatButton,
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
Clear
|
||||
Color:
|
||||
rgba:
|
||||
(self._md_bg_color or [0.0, 0.0, 0.0, 0.0]) \
|
||||
self._md_bg_color \
|
||||
if not self.disabled else \
|
||||
(self._md_bg_color_disabled or [0.0, 0.0, 0.0, 0.0])
|
||||
self._md_bg_color_disabled
|
||||
RoundedRectangle:
|
||||
size: self.size
|
||||
pos: self.pos
|
||||
|
@ -13,19 +13,17 @@
|
|||
radius: [root._radius, ]
|
||||
Color:
|
||||
rgba:
|
||||
root._line_color or [0.0, 0.0, 0.0, 0.0] \
|
||||
root._line_color \
|
||||
if not root.disabled else \
|
||||
( \
|
||||
root._line_color_disabled \
|
||||
or self._disabled_color \
|
||||
or [0.0, 0.0, 0.0, 0.0] \
|
||||
)
|
||||
(root._line_color_disabled or self._disabled_color)
|
||||
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
|
||||
|
@ -33,21 +31,28 @@
|
|||
_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
|
||||
|
@ -84,7 +89,10 @@
|
|||
# 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
|
||||
root.theme_cls.disabled_hint_text_color \
|
||||
if not root.disabled_color else \
|
||||
root.disabled_color
|
||||
|
||||
on_icon:
|
||||
if self.icon not in md_icons.keys(): self.size_hint = (1, 1)
|
||||
theme_text_color: root._theme_icon_color
|
||||
|
@ -131,7 +139,7 @@
|
|||
id: box
|
||||
adaptive_size: True
|
||||
padding: 0
|
||||
spacing: "4dp"
|
||||
spacing: "8dp"
|
||||
|
||||
MDIcon:
|
||||
id: lbl_ic
|
||||
|
@ -193,48 +201,21 @@
|
|||
radius: [self.height / 2]
|
||||
|
||||
|
||||
<BaseFloatingRootButton>
|
||||
<MDFloatingRootButton>
|
||||
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.theme_cls.primary_color \
|
||||
if not root.bg_color else \
|
||||
root.bg_color
|
||||
rgba: self.bg_color
|
||||
RoundedRectangle:
|
||||
pos: self.pos
|
||||
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
|
||||
pos: self.pos
|
||||
radius: self.radius
|
||||
|
|
|
@ -2,17 +2,6 @@
|
|||
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,58 +26,40 @@ Components/Card
|
|||
MDCard
|
||||
------
|
||||
|
||||
.. warning:: Starting from the KivyMD 1.0.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.'''
|
||||
|
||||
This may sound awkward to you, but 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
|
||||
------------------------------------------------------------------------------------
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. tab:: Declarative KV and imperative python styles
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from kivy.lang import Builder
|
||||
from kivy.properties import StringProperty
|
||||
|
||||
from kivymd.app import MDApp
|
||||
from kivymd.uix.behaviors import RoundedRectangularElevationBehavior
|
||||
from kivymd.uix.card import MDCard
|
||||
|
||||
KV = '''
|
||||
<MD3Card>
|
||||
padding: 16
|
||||
padding: 4
|
||||
size_hint: None, None
|
||||
size: "200dp", "100dp"
|
||||
|
||||
MDRelativeLayout:
|
||||
size_hint: None, None
|
||||
size: root.size
|
||||
|
||||
MDIconButton:
|
||||
icon: "dots-vertical"
|
||||
pos:
|
||||
root.width - (self.width + root.padding[0] + dp(4)), \
|
||||
root.height - (self.height + root.padding[0] + dp(4))
|
||||
pos_hint: {"top": 1, "right": 1}
|
||||
|
||||
MDLabel:
|
||||
id: label
|
||||
text: root.text
|
||||
adaptive_size: True
|
||||
color: .2, .2, .2, .8
|
||||
color: "grey"
|
||||
pos: "12dp", "12dp"
|
||||
bold: True
|
||||
|
||||
|
||||
MDScreen:
|
||||
|
@ -90,13 +72,13 @@ An example of the implementation of a card in the style of material design versi
|
|||
'''
|
||||
|
||||
|
||||
class MD3Card(MDCard, RoundedRectangularElevationBehavior):
|
||||
class MD3Card(MDCard):
|
||||
'''Implements a material design v3 card.'''
|
||||
|
||||
text = StringProperty()
|
||||
|
||||
|
||||
class TestCard(MDApp):
|
||||
class Example(MDApp):
|
||||
def build(self):
|
||||
self.theme_cls.material_style = "M3"
|
||||
return Builder.load_string(KV)
|
||||
|
@ -116,7 +98,69 @@ An example of the implementation of a card in the style of material design versi
|
|||
)
|
||||
|
||||
|
||||
TestCard().run()
|
||||
Example().run()
|
||||
|
||||
.. tab:: Declarative python styles
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from kivymd.app import MDApp
|
||||
from kivymd.uix.boxlayout import MDBoxLayout
|
||||
from kivymd.uix.button import MDIconButton
|
||||
from kivymd.uix.card import MDCard
|
||||
from kivymd.uix.label import MDLabel
|
||||
from kivymd.uix.relativelayout import MDRelativeLayout
|
||||
from kivymd.uix.screen import MDScreen
|
||||
|
||||
|
||||
class MD3Card(MDCard):
|
||||
'''Implements a material design v3 card.'''
|
||||
|
||||
|
||||
class Example(MDApp):
|
||||
def build(self):
|
||||
self.theme_cls.material_style = "M3"
|
||||
return (
|
||||
MDScreen(
|
||||
MDBoxLayout(
|
||||
id="box",
|
||||
adaptive_size=True,
|
||||
spacing="56dp",
|
||||
pos_hint={"center_x": 0.5, "center_y": 0.5},
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
def on_start(self):
|
||||
styles = {
|
||||
"elevated": "#f6eeee", "filled": "#f4dedc", "outlined": "#f8f5f4"
|
||||
}
|
||||
for style in styles.keys():
|
||||
self.root.ids.box.add_widget(
|
||||
MD3Card(
|
||||
MDRelativeLayout(
|
||||
MDIconButton(
|
||||
icon="dots-vertical",
|
||||
pos_hint={"top": 1, "right": 1}
|
||||
),
|
||||
MDLabel(
|
||||
text=style.capitalize(),
|
||||
adaptive_size=True,
|
||||
color="grey",
|
||||
pos=("12dp", "12dp"),
|
||||
),
|
||||
),
|
||||
line_color=(0.2, 0.2, 0.2, 0.8),
|
||||
style=style,
|
||||
padding="4dp",
|
||||
size_hint=(None, None),
|
||||
size=("200dp", "100dp"),
|
||||
md_bg_color=styles[style],
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
Example().run()
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/cards-m3.png
|
||||
:align: center
|
||||
|
@ -125,16 +169,13 @@ An example of the implementation of a card in the style of material design versi
|
|||
MDCardSwipe
|
||||
-----------
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/MDCardSwipe.gif
|
||||
:align: center
|
||||
|
||||
To create a card with `swipe-to-delete` behavior, you must create a new class
|
||||
that inherits from the :class:`~MDCardSwipe` class:
|
||||
|
||||
|
||||
.. code-block:: kv
|
||||
|
||||
<SwipeToDeleteItem>:
|
||||
<SwipeToDeleteItem>
|
||||
size_hint_y: None
|
||||
height: content.height
|
||||
|
||||
|
@ -152,12 +193,16 @@ that inherits from the :class:`~MDCardSwipe` class:
|
|||
class SwipeToDeleteItem(MDCardSwipe):
|
||||
text = StringProperty()
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/map-mdcard-swipr.png
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/sceleton-mdcard-swiper.png
|
||||
:align: center
|
||||
|
||||
End full code
|
||||
-------------
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. tab:: Declarative KV and imperative python styles
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from kivy.lang import Builder
|
||||
|
@ -167,7 +212,7 @@ End full code
|
|||
from kivymd.uix.card import MDCardSwipe
|
||||
|
||||
KV = '''
|
||||
<SwipeToDeleteItem>:
|
||||
<SwipeToDeleteItem>
|
||||
size_hint_y: None
|
||||
height: content.height
|
||||
|
||||
|
@ -187,13 +232,12 @@ End full code
|
|||
|
||||
MDBoxLayout:
|
||||
orientation: "vertical"
|
||||
spacing: "10dp"
|
||||
|
||||
MDTopAppBar:
|
||||
elevation: 10
|
||||
elevation: 4
|
||||
title: "MDCardSwipe"
|
||||
|
||||
ScrollView:
|
||||
MDScrollView:
|
||||
scroll_timeout : 100
|
||||
|
||||
MDList:
|
||||
|
@ -208,24 +252,83 @@ End full code
|
|||
text = StringProperty()
|
||||
|
||||
|
||||
class TestCard(MDApp):
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
self.screen = Builder.load_string(KV)
|
||||
|
||||
class Example(MDApp):
|
||||
def build(self):
|
||||
return self.screen
|
||||
self.theme_cls.theme_style = "Dark"
|
||||
self.theme_cls.primary_palette = "Orange"
|
||||
return Builder.load_string(KV)
|
||||
|
||||
def on_start(self):
|
||||
'''Creates a list of cards.'''
|
||||
|
||||
for i in range(20):
|
||||
self.screen.ids.md_list.add_widget(
|
||||
self.root.ids.md_list.add_widget(
|
||||
SwipeToDeleteItem(text=f"One-line item {i}")
|
||||
)
|
||||
|
||||
|
||||
TestCard().run()
|
||||
Example().run()
|
||||
|
||||
.. tab:: Declarative python styles
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from kivymd.app import MDApp
|
||||
from kivymd.uix.boxlayout import MDBoxLayout
|
||||
from kivymd.uix.card import (
|
||||
MDCardSwipe, MDCardSwipeLayerBox, MDCardSwipeFrontBox
|
||||
)
|
||||
from kivymd.uix.list import MDList, OneLineListItem
|
||||
from kivymd.uix.screen import MDScreen
|
||||
from kivymd.uix.scrollview import MDScrollView
|
||||
from kivymd.uix.toolbar import MDTopAppBar
|
||||
|
||||
|
||||
class Example(MDApp):
|
||||
def build(self):
|
||||
self.theme_cls.theme_style = "Dark"
|
||||
self.theme_cls.primary_palette = "Orange"
|
||||
return (
|
||||
MDScreen(
|
||||
MDBoxLayout(
|
||||
MDTopAppBar(
|
||||
elevation=4,
|
||||
title="MDCardSwipe",
|
||||
),
|
||||
MDScrollView(
|
||||
MDList(
|
||||
id="md_list",
|
||||
),
|
||||
id="scroll",
|
||||
scroll_timeout=100,
|
||||
),
|
||||
id="box",
|
||||
orientation="vertical",
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
def on_start(self):
|
||||
'''Creates a list of cards.'''
|
||||
|
||||
for i in range(20):
|
||||
self.root.ids.box.ids.scroll.ids.md_list.add_widget(
|
||||
MDCardSwipe(
|
||||
MDCardSwipeLayerBox(),
|
||||
MDCardSwipeFrontBox(
|
||||
OneLineListItem(
|
||||
id="content",
|
||||
text=f"One-line item {i}",
|
||||
_no_ripple_effect=True,
|
||||
)
|
||||
),
|
||||
size_hint_y=None,
|
||||
height="52dp",
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
Example().run()
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/list-mdcard-swipe.gif
|
||||
:align: center
|
||||
|
@ -235,7 +338,7 @@ Binding a swipe to one of the sides of the screen
|
|||
|
||||
.. code-block:: kv
|
||||
|
||||
<SwipeToDeleteItem>:
|
||||
<SwipeToDeleteItem>
|
||||
# By default, the parameter is "left"
|
||||
anchor: "right"
|
||||
|
||||
|
@ -250,7 +353,7 @@ Swipe behavior
|
|||
|
||||
.. code-block:: kv
|
||||
|
||||
<SwipeToDeleteItem>:
|
||||
<SwipeToDeleteItem>
|
||||
# By default, the parameter is "hand"
|
||||
type_swipe: "hand"
|
||||
|
||||
|
@ -271,85 +374,41 @@ Removing an item using the ``type_swipe = "auto"`` parameter
|
|||
The map provides the :attr:`MDCardSwipe.on_swipe_complete` event.
|
||||
You can use this event to remove items from a list:
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. tab:: Declarative KV styles
|
||||
|
||||
.. code-block:: kv
|
||||
|
||||
<SwipeToDeleteItem>:
|
||||
on_swipe_complete: app.on_swipe_complete(root)
|
||||
|
||||
.. code-block:: python
|
||||
.. tab:: Declarative python styles
|
||||
|
||||
def on_swipe_complete(self, instance):
|
||||
self.screen.ids.md_list.remove_widget(instance)
|
||||
|
||||
End full code
|
||||
-------------
|
||||
.. code-block:: kv
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from kivy.lang import Builder
|
||||
from kivy.properties import StringProperty
|
||||
|
||||
from kivymd.app import MDApp
|
||||
from kivymd.uix.card import MDCardSwipe
|
||||
|
||||
KV = '''
|
||||
<SwipeToDeleteItem>:
|
||||
size_hint_y: None
|
||||
height: content.height
|
||||
type_swipe: "auto"
|
||||
on_swipe_complete: app.on_swipe_complete(root)
|
||||
|
||||
MDCardSwipeLayerBox:
|
||||
|
||||
MDCardSwipeFrontBox:
|
||||
|
||||
OneLineListItem:
|
||||
id: content
|
||||
text: root.text
|
||||
_no_ripple_effect: True
|
||||
|
||||
|
||||
MDScreen:
|
||||
|
||||
MDBoxLayout:
|
||||
orientation: "vertical"
|
||||
spacing: "10dp"
|
||||
|
||||
MDTopAppBar:
|
||||
elevation: 10
|
||||
title: "MDCardSwipe"
|
||||
|
||||
ScrollView:
|
||||
|
||||
MDList:
|
||||
id: md_list
|
||||
padding: 0
|
||||
'''
|
||||
|
||||
|
||||
class SwipeToDeleteItem(MDCardSwipe):
|
||||
text = StringProperty()
|
||||
|
||||
|
||||
class TestCard(MDApp):
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
self.screen = Builder.load_string(KV)
|
||||
|
||||
def build(self):
|
||||
return self.screen
|
||||
|
||||
def on_swipe_complete(self, instance):
|
||||
self.screen.ids.md_list.remove_widget(instance)
|
||||
|
||||
def on_start(self):
|
||||
for i in range(20):
|
||||
self.screen.ids.md_list.add_widget(
|
||||
SwipeToDeleteItem(text=f"One-line item {i}")
|
||||
MDCardSwipe(
|
||||
...
|
||||
on_swipe_complete=self.on_swipe_complete,
|
||||
)
|
||||
|
||||
.. tabs::
|
||||
|
||||
TestCard().run()
|
||||
.. tab:: Imperative python styles
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
def on_swipe_complete(self, instance):
|
||||
self.root.ids.md_list.remove_widget(instance)
|
||||
|
||||
.. tab:: Decralative python styles
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
def on_swipe_complete(self, instance):
|
||||
self.root.ids.box.ids.scroll.ids.md_list.remove_widget(instance)
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/autodelete-mdcard-swipe.gif
|
||||
:align: center
|
||||
|
@ -375,6 +434,10 @@ use the :class:`~MDCardSwipeLayerBox` class.
|
|||
End full code
|
||||
-------------
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. tab:: Declarative KV styles
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from kivy.lang import Builder
|
||||
|
@ -408,13 +471,12 @@ End full code
|
|||
|
||||
MDBoxLayout:
|
||||
orientation: "vertical"
|
||||
spacing: "10dp"
|
||||
|
||||
MDTopAppBar:
|
||||
elevation: 10
|
||||
elevation: 4
|
||||
title: "MDCardSwipe"
|
||||
|
||||
ScrollView:
|
||||
MDScrollView:
|
||||
|
||||
MDList:
|
||||
id: md_list
|
||||
|
@ -426,9 +488,11 @@ End full code
|
|||
text = StringProperty()
|
||||
|
||||
|
||||
class TestCard(MDApp):
|
||||
class Example(MDApp):
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
self.theme_cls.theme_style = "Dark"
|
||||
self.theme_cls.primary_palette = "Orange"
|
||||
self.screen = Builder.load_string(KV)
|
||||
|
||||
def build(self):
|
||||
|
@ -444,7 +508,80 @@ End full code
|
|||
)
|
||||
|
||||
|
||||
TestCard().run()
|
||||
Example().run()
|
||||
|
||||
.. tab:: Decralative python styles
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from kivymd.app import MDApp
|
||||
from kivymd.uix.boxlayout import MDBoxLayout
|
||||
from kivymd.uix.button import MDIconButton
|
||||
from kivymd.uix.card import (
|
||||
MDCardSwipe, MDCardSwipeLayerBox, MDCardSwipeFrontBox
|
||||
)
|
||||
from kivymd.uix.list import MDList, OneLineListItem
|
||||
from kivymd.uix.screen import MDScreen
|
||||
from kivymd.uix.scrollview import MDScrollView
|
||||
from kivymd.uix.toolbar import MDTopAppBar
|
||||
|
||||
|
||||
class Example(MDApp):
|
||||
def build(self):
|
||||
self.theme_cls.theme_style = "Dark"
|
||||
self.theme_cls.primary_palette = "Orange"
|
||||
return (
|
||||
MDScreen(
|
||||
MDBoxLayout(
|
||||
MDTopAppBar(
|
||||
elevation=4,
|
||||
title="MDCardSwipe",
|
||||
),
|
||||
MDScrollView(
|
||||
MDList(
|
||||
id="md_list",
|
||||
),
|
||||
id="scroll",
|
||||
scroll_timeout=100,
|
||||
),
|
||||
id="box",
|
||||
orientation="vertical",
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
def on_start(self):
|
||||
'''Creates a list of cards.'''
|
||||
|
||||
for i in range(20):
|
||||
self.root.ids.box.ids.scroll.ids.md_list.add_widget(
|
||||
MDCardSwipe(
|
||||
MDCardSwipeLayerBox(
|
||||
MDIconButton(
|
||||
icon="trash-can",
|
||||
pos_hint={"center_y": 0.5},
|
||||
on_release=self.remove_item,
|
||||
),
|
||||
),
|
||||
MDCardSwipeFrontBox(
|
||||
OneLineListItem(
|
||||
id="content",
|
||||
text=f"One-line item {i}",
|
||||
_no_ripple_effect=True,
|
||||
)
|
||||
),
|
||||
size_hint_y=None,
|
||||
height="52dp",
|
||||
)
|
||||
)
|
||||
|
||||
def remove_item(self, instance):
|
||||
self.root.ids.box.ids.scroll.ids.md_list.remove_widget(
|
||||
instance.parent.parent
|
||||
)
|
||||
|
||||
|
||||
Example().run()
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/handdelete-mdcard-swipe.gif
|
||||
:align: center
|
||||
|
@ -457,6 +594,67 @@ Focus behavior
|
|||
MDCard:
|
||||
focus_behavior: True
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. tab:: Declarative KV styles
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from kivy.lang import Builder
|
||||
|
||||
from kivymd.app import MDApp
|
||||
|
||||
KV = '''
|
||||
MDScreen:
|
||||
|
||||
MDCard:
|
||||
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 Example(MDApp):
|
||||
def build(self):
|
||||
self.theme_cls.theme_style = "Dark"
|
||||
return Builder.load_string(KV)
|
||||
|
||||
|
||||
Example().run()
|
||||
|
||||
.. tab:: Declarative python styles
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from kivymd.app import MDApp
|
||||
from kivymd.uix.card import MDCard
|
||||
from kivymd.uix.screen import MDScreen
|
||||
|
||||
|
||||
class Example(MDApp):
|
||||
def build(self):
|
||||
self.theme_cls.theme_style = "Dark"
|
||||
return (
|
||||
MDScreen(
|
||||
MDCard(
|
||||
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,
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
Example().run()
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/card-focus.gif
|
||||
:align: center
|
||||
|
||||
|
@ -471,88 +669,6 @@ Ripple behavior
|
|||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/card-behavior.gif
|
||||
:align: center
|
||||
|
||||
End full code
|
||||
-------------
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from kivy.lang import Builder
|
||||
|
||||
from kivymd.app import MDApp
|
||||
|
||||
KV = '''
|
||||
<StarButton@MDIconButton>
|
||||
icon: "star"
|
||||
on_release: self.icon = "star-outline" if self.icon == "star" else "star"
|
||||
|
||||
|
||||
MDScreen:
|
||||
|
||||
MDCard:
|
||||
orientation: "vertical"
|
||||
size_hint: .5, None
|
||||
height: box_top.height + box_bottom.height
|
||||
focus_behavior: True
|
||||
ripple_behavior: True
|
||||
pos_hint: {"center_x": .5, "center_y": .5}
|
||||
|
||||
MDBoxLayout:
|
||||
id: box_top
|
||||
spacing: "20dp"
|
||||
adaptive_height: True
|
||||
|
||||
FitImage:
|
||||
source: "/Users/macbookair/album.jpeg"
|
||||
size_hint: .3, None
|
||||
height: text_box.height
|
||||
|
||||
MDBoxLayout:
|
||||
id: text_box
|
||||
orientation: "vertical"
|
||||
adaptive_height: True
|
||||
spacing: "10dp"
|
||||
padding: 0, "10dp", "10dp", "10dp"
|
||||
|
||||
MDLabel:
|
||||
text: "Ride the Lightning"
|
||||
theme_text_color: "Primary"
|
||||
font_style: "H5"
|
||||
bold: True
|
||||
adaptive_height: True
|
||||
|
||||
MDLabel:
|
||||
text: "July 27, 1984"
|
||||
adaptive_height: True
|
||||
theme_text_color: "Primary"
|
||||
|
||||
MDSeparator:
|
||||
|
||||
MDBoxLayout:
|
||||
id: box_bottom
|
||||
adaptive_height: True
|
||||
padding: "10dp", 0, 0, 0
|
||||
|
||||
MDLabel:
|
||||
text: "Rate this album"
|
||||
adaptive_height: True
|
||||
pos_hint: {"center_y": .5}
|
||||
theme_text_color: "Primary"
|
||||
|
||||
StarButton:
|
||||
StarButton:
|
||||
StarButton:
|
||||
StarButton:
|
||||
StarButton:
|
||||
'''
|
||||
|
||||
|
||||
class Test(MDApp):
|
||||
def build(self):
|
||||
self.theme_cls.theme_style = "Dark"
|
||||
return Builder.load_string(KV)
|
||||
|
||||
|
||||
Test().run()
|
||||
"""
|
||||
|
||||
__all__ = (
|
||||
|
@ -579,17 +695,20 @@ from kivy.properties import (
|
|||
VariableListProperty,
|
||||
)
|
||||
from kivy.uix.boxlayout import BoxLayout
|
||||
from kivy.uix.relativelayout import RelativeLayout
|
||||
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,
|
||||
FocusBehavior,
|
||||
CommonElevationBehavior,
|
||||
DeclarativeBehavior,
|
||||
RectangularRippleBehavior,
|
||||
)
|
||||
from kivymd.uix.behaviors.focus_behavior import FocusBehavior
|
||||
from kivymd.uix.boxlayout import MDBoxLayout
|
||||
from kivymd.uix.relativelayout import MDRelativeLayout
|
||||
|
||||
with open(
|
||||
os.path.join(uix_path, "card", "card.kv"), encoding="utf-8"
|
||||
|
@ -602,7 +721,7 @@ class MDSeparator(ThemableBehavior, MDBoxLayout):
|
|||
|
||||
color = ColorProperty(None)
|
||||
"""
|
||||
Separator color in ``rgba`` format.
|
||||
Separator color.
|
||||
|
||||
:attr:`color` is a :class:`~kivy.properties.ColorProperty`
|
||||
and defaults to `None`.
|
||||
|
@ -623,9 +742,11 @@ class MDSeparator(ThemableBehavior, MDBoxLayout):
|
|||
|
||||
|
||||
class MDCard(
|
||||
DeclarativeBehavior,
|
||||
ThemableBehavior,
|
||||
BackgroundColorBehavior,
|
||||
RectangularRippleBehavior,
|
||||
CommonElevationBehavior,
|
||||
FocusBehavior,
|
||||
BoxLayout,
|
||||
):
|
||||
|
@ -645,14 +766,6 @@ 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.
|
||||
|
@ -676,15 +789,16 @@ class MDCard(
|
|||
"""
|
||||
|
||||
_bg_color_map = (
|
||||
colors["Light"]["CardsDialogs"],
|
||||
colors["Dark"]["CardsDialogs"],
|
||||
get_color_from_hex(colors["Light"]["CardsDialogs"]),
|
||||
get_color_from_hex(colors["Dark"]["CardsDialogs"]),
|
||||
[1.0, 1.0, 1.0, 0.0],
|
||||
)
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
self.theme_cls.bind(theme_style=self.update_md_bg_color)
|
||||
self.theme_cls.bind(material_style=self.set_style)
|
||||
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
|
||||
)
|
||||
Clock.schedule_once(self.set_style)
|
||||
Clock.schedule_once(
|
||||
lambda x: self.on_ripple_behavior(0, self.ripple_behavior)
|
||||
|
@ -693,24 +807,26 @@ 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 = colors[theme_style]["CardsDialogs"]
|
||||
self.md_bg_color = get_color_from_hex(
|
||||
colors[theme_style]["CardsDialogs"]
|
||||
)
|
||||
|
||||
def set_style(self, *args) -> None:
|
||||
self.set_radius()
|
||||
self.set_elevation()
|
||||
self.set_line_color()
|
||||
|
||||
def set_line_color(self):
|
||||
def set_line_color(self) -> None:
|
||||
if self.theme_cls.material_style == "M3":
|
||||
if self.style == "elevated" or self.style == "filled":
|
||||
self.line_color = [0, 0, 0, 0]
|
||||
|
||||
def set_elevation(self):
|
||||
def set_elevation(self) -> None:
|
||||
if self.theme_cls.material_style == "M3":
|
||||
if self.style == "outlined" or self.style == "filled":
|
||||
self.elevation = 0
|
||||
elif self.style == "elevated":
|
||||
self.elevation = 1
|
||||
self.elevation = 2
|
||||
|
||||
def set_radius(self) -> None:
|
||||
if (
|
||||
|
@ -730,7 +846,7 @@ class MDCard(
|
|||
self._no_ripple_effect = False if value_behavior else True
|
||||
|
||||
|
||||
class MDCardSwipe(RelativeLayout):
|
||||
class MDCardSwipe(MDRelativeLayout):
|
||||
"""
|
||||
:Events:
|
||||
:attr:`on_swipe_complete`
|
||||
|
@ -765,6 +881,16 @@ class MDCardSwipe(RelativeLayout):
|
|||
and defaults to `'out_sine'`.
|
||||
"""
|
||||
|
||||
closing_interval = NumericProperty(0)
|
||||
"""
|
||||
Interval for closing the front layer.
|
||||
|
||||
.. versionadded:: 1.1.0
|
||||
|
||||
:attr:`closing_interval` is a :class:`~kivy.properties.NumericProperty`
|
||||
and defaults to `0`.
|
||||
"""
|
||||
|
||||
anchor = OptionProperty("left", options=("left", "right"))
|
||||
"""
|
||||
Anchoring screen edge for card. Available options are: `'left'`, `'right'`.
|
||||
|
@ -830,10 +956,11 @@ class MDCardSwipe(RelativeLayout):
|
|||
|
||||
_opens_process = False
|
||||
_to_closed = True
|
||||
_distance = 0
|
||||
|
||||
def __init__(self, **kw):
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.register_event_type("on_swipe_complete")
|
||||
super().__init__(**kw)
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
def add_widget(self, widget, index=0, canvas=None):
|
||||
if isinstance(widget, (MDCardSwipeFrontBox, MDCardSwipeLayerBox)):
|
||||
|
@ -853,18 +980,24 @@ class MDCardSwipe(RelativeLayout):
|
|||
def on_open_progress(
|
||||
self, instance_swipe_to_delete_item, progress_value: float
|
||||
) -> None:
|
||||
def on_open_progress(*args):
|
||||
if self.anchor == "left":
|
||||
self.children[0].x = self.width * progress_value
|
||||
else:
|
||||
self.children[0].x = self.width * progress_value - self.width
|
||||
|
||||
Clock.schedule_once(on_open_progress)
|
||||
|
||||
def on_touch_move(self, touch):
|
||||
if self.collide_point(touch.x, touch.y):
|
||||
expr = (
|
||||
touch.x < self.swipe_distance
|
||||
if self.anchor == "left"
|
||||
else touch.x > self.width - self.swipe_distance
|
||||
)
|
||||
self._distance += touch.dx
|
||||
expr = False
|
||||
|
||||
if self.anchor == "left" and touch.dx >= 0:
|
||||
expr = abs(self._distance) < self.swipe_distance
|
||||
elif self.anchor == "right" and touch.dx < 0:
|
||||
expr = abs(self._distance) > self.swipe_distance
|
||||
|
||||
if expr and not self._opens_process:
|
||||
self._opens_process = True
|
||||
self._to_closed = False
|
||||
|
@ -875,6 +1008,7 @@ class MDCardSwipe(RelativeLayout):
|
|||
return super().on_touch_move(touch)
|
||||
|
||||
def on_touch_up(self, touch):
|
||||
self._distance = 0
|
||||
if self.collide_point(touch.x, touch.y):
|
||||
if not self._to_closed:
|
||||
self._opens_process = False
|
||||
|
@ -885,7 +1019,7 @@ class MDCardSwipe(RelativeLayout):
|
|||
if self.collide_point(touch.x, touch.y):
|
||||
if self.state == "opened":
|
||||
self._to_closed = True
|
||||
self.close_card()
|
||||
Clock.schedule_once(self.close_card, self.closing_interval)
|
||||
return super().on_touch_down(touch)
|
||||
|
||||
def complete_swipe(self) -> None:
|
||||
|
@ -895,7 +1029,7 @@ class MDCardSwipe(RelativeLayout):
|
|||
else self.open_progress >= self.max_swipe_x
|
||||
)
|
||||
if expr:
|
||||
self.close_card()
|
||||
Clock.schedule_once(self.close_card, self.closing_interval)
|
||||
else:
|
||||
self.open_card()
|
||||
|
||||
|
@ -915,7 +1049,7 @@ class MDCardSwipe(RelativeLayout):
|
|||
anim.start(self.children[0])
|
||||
self.state = "opened"
|
||||
|
||||
def close_card(self) -> None:
|
||||
def close_card(self, *args) -> None:
|
||||
anim = Animation(x=0, t=self.closing_transition, d=self.opening_time)
|
||||
anim.bind(on_complete=self._reset_open_progress)
|
||||
anim.start(self.children[0])
|
||||
|
|
|
@ -57,8 +57,10 @@ MDCarousel
|
|||
from kivy.animation import Animation
|
||||
from kivy.uix.carousel import Carousel
|
||||
|
||||
from kivymd.uix.behaviors import DeclarativeBehavior
|
||||
|
||||
class MDCarousel(Carousel):
|
||||
|
||||
class MDCarousel(DeclarativeBehavior, Carousel):
|
||||
"""
|
||||
based on kivy's carousel.
|
||||
|
||||
|
@ -68,8 +70,8 @@ class MDCarousel(Carousel):
|
|||
|
||||
_scrolling = False
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.register_event_type("on_slide_progress")
|
||||
self.register_event_type("on_slide_complete")
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
from .chip import MDChip, MDChooseChip # NOQA F401
|
||||
from .chip import MDChip # NOQA F401
|
||||
|
|
|
@ -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: 12
|
||||
elevation: 4
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/chip-with-elevation.png
|
||||
:align: center
|
||||
|
@ -304,7 +304,6 @@ __all__ = ("MDChip",)
|
|||
|
||||
import os
|
||||
|
||||
from kivy import Logger
|
||||
from kivy.animation import Animation
|
||||
from kivy.lang import Builder
|
||||
from kivy.metrics import dp
|
||||
|
@ -314,14 +313,13 @@ from kivy.uix.behaviors import ButtonBehavior
|
|||
from kivymd import uix_path
|
||||
from kivymd.theming import ThemableBehavior
|
||||
from kivymd.uix.behaviors import (
|
||||
FakeRectangularElevationBehavior,
|
||||
CommonElevationBehavior,
|
||||
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"
|
||||
|
@ -330,12 +328,12 @@ with open(
|
|||
|
||||
|
||||
class MDChip(
|
||||
MDBoxLayout,
|
||||
ThemableBehavior,
|
||||
RectangularRippleBehavior,
|
||||
FakeRectangularElevationBehavior,
|
||||
TouchBehavior,
|
||||
ButtonBehavior,
|
||||
MDBoxLayout,
|
||||
CommonElevationBehavior,
|
||||
TouchBehavior,
|
||||
):
|
||||
text = StringProperty()
|
||||
"""
|
||||
|
@ -345,17 +343,6 @@ class MDChip(
|
|||
and defaults to `''`.
|
||||
"""
|
||||
|
||||
icon = StringProperty("checkbox-blank-circle", deprecated=True)
|
||||
"""
|
||||
Chip icon.
|
||||
|
||||
.. deprecated:: 1.0.0
|
||||
Use :attr:`icon_right` and :attr:`icon_left` instead.
|
||||
|
||||
:attr:`icon` is an :class:`~kivy.properties.StringProperty`
|
||||
and defaults to `'checkbox-blank-circle'`.
|
||||
"""
|
||||
|
||||
icon_left = StringProperty()
|
||||
"""
|
||||
Chip left icon.
|
||||
|
@ -376,16 +363,6 @@ class MDChip(
|
|||
and defaults to `''`.
|
||||
"""
|
||||
|
||||
color = ColorProperty(None, deprecated=True)
|
||||
"""
|
||||
Chip color in ``rgba`` format.
|
||||
|
||||
.. deprecated:: 1.0.0
|
||||
|
||||
:attr:`color` is an :class:`~kivy.properties.ColorProperty`
|
||||
and defaults to `None`.
|
||||
"""
|
||||
|
||||
text_color = ColorProperty(None)
|
||||
"""
|
||||
Chip's text color in ``rgba`` format.
|
||||
|
@ -394,17 +371,6 @@ class MDChip(
|
|||
and defaults to `None`.
|
||||
"""
|
||||
|
||||
icon_color = ColorProperty(None, deprecated=True)
|
||||
"""
|
||||
Chip's icon color in ``rgba`` format.
|
||||
|
||||
.. deprecated:: 1.0.0
|
||||
Use :attr:`icon_right_color` and :attr:`icon_left_color` instead.
|
||||
|
||||
:attr:`icon_color` is an :class:`~kivy.properties.ColorProperty`
|
||||
and defaults to `None`.
|
||||
"""
|
||||
|
||||
icon_right_color = ColorProperty(None)
|
||||
"""
|
||||
Chip's right icon color in ``rgba`` format.
|
||||
|
@ -435,26 +401,6 @@ class MDChip(
|
|||
and defaults to `None`.
|
||||
"""
|
||||
|
||||
check = BooleanProperty(False, deprecated=True)
|
||||
"""
|
||||
If `True`, a checkmark is added to the left when touch to the chip.
|
||||
|
||||
.. deprecated:: 1.0.0
|
||||
|
||||
:attr:`check` is an :class:`~kivy.properties.BooleanProperty`
|
||||
and defaults to `False`.
|
||||
"""
|
||||
|
||||
selected_chip_color = ColorProperty(None, deprecated=True)
|
||||
"""
|
||||
The color of the chip that is currently selected in ``rgba`` format.
|
||||
|
||||
.. deprecated:: 1.0.0
|
||||
|
||||
:attr:`selected_chip_color` is an :class:`~kivy.properties.ColorProperty`
|
||||
and defaults to `None`.
|
||||
"""
|
||||
|
||||
active = BooleanProperty(False)
|
||||
"""
|
||||
Whether the check is marked or not.
|
||||
|
@ -508,16 +454,7 @@ class MDChip(
|
|||
self.active = False
|
||||
|
||||
|
||||
class MDChooseChip(MDStackLayout):
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
Logger.warning(
|
||||
"MDChooseChip: "
|
||||
"class is deprecated and will be removed in a future version"
|
||||
)
|
||||
|
||||
|
||||
class MDScalableCheckIcon(MDIcon, ScaleWidget):
|
||||
class MDScalableCheckIcon(MDIcon, ScaleBehavior):
|
||||
pos_hint = {"center_y": 0.5}
|
||||
|
||||
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
Controllers/WindowController
|
||||
============================
|
||||
|
||||
.. versionadded:: 1.0.0
|
||||
|
||||
Modules and classes that implement useful methods for getting information
|
||||
about the state of the current application window.
|
||||
|
||||
|
@ -33,16 +35,35 @@ Controlling the resizing direction of the application window
|
|||
|
||||
from kivy.core.window import Window
|
||||
from kivy.core.window.window_sdl2 import WindowSDL
|
||||
from kivy.metrics import dp
|
||||
|
||||
|
||||
class WindowController:
|
||||
def __init__(self):
|
||||
self.window_resizing_direction = "unknown"
|
||||
self.real_device_type = "unknown"
|
||||
self.__width = Window.width
|
||||
Window.bind(on_resize=self._on_resize)
|
||||
|
||||
def on_size(self, instance, size: list) -> None:
|
||||
"""Called when the application screen size changes."""
|
||||
|
||||
window_width = size[0]
|
||||
|
||||
if window_width < dp(500):
|
||||
self.real_device_type = "mobile"
|
||||
elif window_width < dp(1100):
|
||||
self.real_device_type = "tablet"
|
||||
else:
|
||||
self.real_device_type = "desktop"
|
||||
|
||||
def get_real_device_type(self) -> str:
|
||||
"""Returns the device type - 'mobile', 'tablet' or 'desktop'."""
|
||||
|
||||
return self.real_device_type
|
||||
|
||||
def get_window_width_resizing_direction(self) -> str:
|
||||
"""Return window width resizing direction - 'left' or 'right'"""
|
||||
"""Return window width resizing direction - 'left' or 'right'."""
|
||||
|
||||
return self.window_resizing_direction
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
#:import DEVICE_TYPE kivymd.material_resources.DEVICE_TYPE
|
||||
#:import FakeRectangularElevationBehavior kivymd.uix.behaviors.FakeRectangularElevationBehavior
|
||||
|
||||
|
||||
<CellRow>
|
||||
|
@ -66,7 +65,7 @@
|
|||
size_hint_y: None
|
||||
height: self.minimum_height
|
||||
spacing: "4dp"
|
||||
tooltip_text: root.text
|
||||
tooltip_text: root.tooltip if root.tooltip else root.text
|
||||
|
||||
BoxLayout:
|
||||
id: box
|
||||
|
@ -175,7 +174,11 @@
|
|||
font_size: "14sp"
|
||||
on_release: root.table_data.open_pagination_menu()
|
||||
text:
|
||||
f"{root.table_data.rows_num if root.table_data.rows_num < len(root.table_data.row_data) else len(root.table_data.row_data)}"
|
||||
"{}".format( \
|
||||
root.table_data.rows_num \
|
||||
if root.table_data.rows_num < len(root.table_data.row_data) else \
|
||||
len(root.table_data.row_data) \
|
||||
)
|
||||
|
||||
Widget:
|
||||
size_hint_x: None
|
||||
|
@ -192,9 +195,11 @@
|
|||
if root.theme_cls.theme_style == "Dark" else \
|
||||
(0, 0, 0, 1)
|
||||
text:
|
||||
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)}"
|
||||
"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) \
|
||||
)
|
||||
|
||||
MDIconButton:
|
||||
id: button_back
|
||||
|
@ -217,7 +222,7 @@
|
|||
on_release: root.table_data.set_next_row_data_parts("forward")
|
||||
|
||||
|
||||
<TableContainer@MDCard+FakeRectangularElevationBehavior>
|
||||
<TableContainer@MDCard>
|
||||
|
||||
|
||||
<MDDataTable>
|
||||
|
|
|
@ -11,19 +11,6 @@ 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
|
||||
|
@ -159,6 +146,15 @@ 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()
|
||||
"""
|
||||
|
@ -340,11 +336,19 @@ 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],
|
||||
|
@ -356,6 +360,9 @@ 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]
|
||||
|
||||
|
@ -765,6 +772,9 @@ 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.
|
||||
|
@ -775,7 +785,6 @@ class MDDataTable(ThemableBehavior, AnchorLayout):
|
|||
|
||||
.. code-block:: python
|
||||
|
||||
|
||||
from kivy.metrics import dp
|
||||
|
||||
from kivymd.app import MDApp
|
||||
|
@ -914,6 +923,10 @@ class MDDataTable(ThemableBehavior, AnchorLayout):
|
|||
"""
|
||||
Data for header columns.
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. tab:: Imperative python style
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from kivy.metrics import dp
|
||||
|
@ -925,14 +938,17 @@ class MDDataTable(ThemableBehavior, 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)
|
||||
# name column, width column, sorting function column(optional), custom tooltip
|
||||
column_data=[
|
||||
("No.", dp(30)),
|
||||
("No.", dp(30), None, "Custom tooltip"),
|
||||
("Status", dp(30)),
|
||||
("Signal Name", dp(60)),
|
||||
("Severity", dp(30)),
|
||||
|
@ -947,6 +963,43 @@ class MDDataTable(ThemableBehavior, AnchorLayout):
|
|||
|
||||
Example().run()
|
||||
|
||||
.. tab:: Declarative python style
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from kivy.metrics import dp
|
||||
|
||||
from kivymd.app import MDApp
|
||||
from kivymd.uix.anchorlayout import MDAnchorLayout
|
||||
from kivymd.uix.datatables import MDDataTable
|
||||
|
||||
|
||||
class Example(MDApp):
|
||||
def build(self):
|
||||
self.theme_cls.theme_style = "Dark"
|
||||
self.theme_cls.primary_palette = "Orange"
|
||||
return MDAnchorLayout(
|
||||
MDDataTable(
|
||||
size_hint=(0.7, 0.6),
|
||||
use_pagination=True,
|
||||
check=True,
|
||||
# name column, width column, sorting function column(optional)
|
||||
column_data=[
|
||||
("No.", dp(30)),
|
||||
("Status", dp(30)),
|
||||
("Signal Name", dp(60)),
|
||||
("Severity", dp(30)),
|
||||
("Stage", dp(30)),
|
||||
("Schedule", dp(30),
|
||||
lambda *args: print("Sorted using Schedule")),
|
||||
("Team Lead", dp(30)),
|
||||
],
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
Example().run()
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/data-tables-column-data.png
|
||||
:align: center
|
||||
|
||||
|
@ -1060,6 +1113,9 @@ 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),
|
||||
|
@ -1187,7 +1243,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.gif
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/data-tables-check.png
|
||||
:align: center
|
||||
|
||||
:attr:`check` is an :class:`~kivy.properties.BooleanProperty`
|
||||
|
@ -1209,6 +1265,9 @@ 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),
|
||||
|
@ -1238,19 +1297,19 @@ class MDDataTable(ThemableBehavior, AnchorLayout):
|
|||
and defaults to `False`.
|
||||
"""
|
||||
|
||||
elevation = NumericProperty(8)
|
||||
elevation = NumericProperty(4)
|
||||
"""
|
||||
Table elevation.
|
||||
|
||||
:attr:`elevation` is an :class:`~kivy.properties.NumericProperty`
|
||||
and defaults to `8`.
|
||||
and defaults to `4`.
|
||||
"""
|
||||
|
||||
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.gif
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/data-tables-use-pagination-rows-num.png
|
||||
:align: center
|
||||
|
||||
:attr:`rows_num` is an :class:`~kivy.properties.NumericProperty`
|
||||
|
@ -1266,7 +1325,7 @@ class MDDataTable(ThemableBehavior, AnchorLayout):
|
|||
|
||||
.. rubric:: Center
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/data-tables-menu-pos-center.png
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/data-tables-menu-pos-top.png
|
||||
:align: center
|
||||
|
||||
.. rubric:: Auto
|
||||
|
@ -1282,11 +1341,6 @@ 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
|
||||
|
@ -1298,7 +1352,7 @@ class MDDataTable(ThemableBehavior, AnchorLayout):
|
|||
|
||||
background_color = ColorProperty([0, 0, 0, 0])
|
||||
"""
|
||||
Background color in the format (r, g, b, a).
|
||||
Background color in the format (r, g, b, a) or string format.
|
||||
See :attr:`~kivy.uix.modalview.ModalView.background_color`.
|
||||
|
||||
Use markup strings
|
||||
|
@ -1315,6 +1369,9 @@ 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),
|
||||
|
@ -1354,7 +1411,8 @@ class MDDataTable(ThemableBehavior, AnchorLayout):
|
|||
|
||||
background_color_header = ColorProperty(None)
|
||||
"""
|
||||
Background color for :class:`~TableHeader` class.
|
||||
Background color in the format (r, g, b, a) or string format for
|
||||
:class:`~TableHeader` class.
|
||||
|
||||
.. versionadded:: 1.0.0
|
||||
|
||||
|
@ -1374,7 +1432,8 @@ class MDDataTable(ThemableBehavior, AnchorLayout):
|
|||
|
||||
background_color_cell = ColorProperty(None)
|
||||
"""
|
||||
Background color for :class:`~CellRow` class.
|
||||
Background color in the format (r, g, b, a) or string format for
|
||||
:class:`~CellRow` class.
|
||||
|
||||
.. versionadded:: 1.0.0
|
||||
|
||||
|
@ -1395,7 +1454,8 @@ class MDDataTable(ThemableBehavior, AnchorLayout):
|
|||
|
||||
background_color_selected_cell = ColorProperty(None)
|
||||
"""
|
||||
Background selected color for :class:`~CellRow` class.
|
||||
Background selected color in the format (r, g, b, a) or string format for
|
||||
:class:`~CellRow` class.
|
||||
|
||||
.. versionadded:: 1.0.0
|
||||
|
||||
|
@ -1408,7 +1468,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.gif
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/data-tables-background-color-selected-cell.png
|
||||
:align: center
|
||||
|
||||
:attr:`background_color_selected_cell` is a :class:`~kivy.properties.ColorProperty` and
|
||||
|
@ -1503,6 +1563,9 @@ 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(
|
||||
|
@ -1604,6 +1667,9 @@ 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,7 +18,11 @@
|
|||
PopMatrix
|
||||
|
||||
|
||||
<DialogContainer@MDCard+FakeRectangularElevationBehavior>
|
||||
<DialogContainer@MDCard>
|
||||
shadow_color: 0.0, 0.0, 0.0, 0.0
|
||||
elevation: 0
|
||||
shadow_softness: 0
|
||||
shadow_offset: 0, 0
|
||||
|
||||
|
||||
<MDDialog>
|
||||
|
@ -28,7 +32,6 @@
|
|||
orientation: "vertical"
|
||||
size_hint_y: None
|
||||
height: self.minimum_height
|
||||
elevation: 24
|
||||
padding: "24dp", "24dp", "8dp", "8dp"
|
||||
radius: root.radius
|
||||
md_bg_color:
|
||||
|
|
|
@ -38,6 +38,8 @@ 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):
|
||||
|
@ -87,6 +89,7 @@ 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
|
||||
|
@ -97,7 +100,40 @@ with open(
|
|||
Builder.load_string(kv_file.read())
|
||||
|
||||
|
||||
class BaseDialog(ThemableBehavior, ModalView):
|
||||
class BaseDialog(ThemableBehavior, ModalView, CommonElevationBehavior):
|
||||
elevation = NumericProperty(3)
|
||||
"""
|
||||
See :attr:`kivymd.uix.behaviors.elevation.CommonElevationBehavior.elevation`
|
||||
attribute for more information.
|
||||
|
||||
.. versionadded:: 1.1.0
|
||||
|
||||
:attr:`elevation` is an :class:`~kivy.properties.NumericProperty`
|
||||
and defaults to `3`.
|
||||
"""
|
||||
|
||||
shadow_softness = NumericProperty(24)
|
||||
"""
|
||||
See :attr:`kivymd.uix.behaviors.elevation.CommonElevationBehavior.shadow_softness`
|
||||
attribute for more information.
|
||||
|
||||
.. versionadded:: 1.1.0
|
||||
|
||||
:attr:`shadow_softness` is an :class:`~kivy.properties.NumericProperty`
|
||||
and defaults to `24`.
|
||||
"""
|
||||
|
||||
shadow_offset = ListProperty((0, 4))
|
||||
"""
|
||||
See :attr:`kivymd.uix.behaviors.elevation.CommonElevationBehavior.shadow_offset`
|
||||
attribute for more information.
|
||||
|
||||
.. versionadded:: 1.1.0
|
||||
|
||||
:attr:`shadow_offset` is an :class:`~kivy.properties.ListProperty`
|
||||
and defaults to `[0, 4]`.
|
||||
"""
|
||||
|
||||
radius = ListProperty([dp(7), dp(7), dp(7), dp(7)])
|
||||
"""
|
||||
Dialog corners rounding value.
|
||||
|
@ -251,6 +287,8 @@ 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_simple_dialog(self):
|
||||
|
@ -259,9 +297,8 @@ class MDDialog(BaseDialog):
|
|||
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"),
|
||||
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()
|
||||
|
@ -317,6 +354,8 @@ 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):
|
||||
|
@ -385,6 +424,10 @@ class MDDialog(BaseDialog):
|
|||
"""
|
||||
Custom content class.
|
||||
|
||||
.. tabs::
|
||||
|
||||
.. tab:: Declarative KV style
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from kivy.lang import Builder
|
||||
|
@ -425,6 +468,8 @@ 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):
|
||||
|
@ -451,6 +496,69 @@ class MDDialog(BaseDialog):
|
|||
|
||||
Example().run()
|
||||
|
||||
.. tab:: Declarative Python style
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from kivymd.app import MDApp
|
||||
from kivymd.uix.boxlayout import MDBoxLayout
|
||||
from kivymd.uix.button import MDFlatButton
|
||||
from kivymd.uix.dialog import MDDialog
|
||||
from kivymd.uix.floatlayout import MDFloatLayout
|
||||
from kivymd.uix.textfield import MDTextField
|
||||
|
||||
|
||||
class Example(MDApp):
|
||||
dialog = None
|
||||
|
||||
def build(self):
|
||||
self.theme_cls.theme_style = "Dark"
|
||||
self.theme_cls.primary_palette = "Orange"
|
||||
return (
|
||||
MDFloatLayout(
|
||||
MDFlatButton(
|
||||
text="ALERT DIALOG",
|
||||
pos_hint={'center_x': 0.5, 'center_y': 0.5},
|
||||
on_release=self.show_confirmation_dialog,
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
def show_confirmation_dialog(self, *args):
|
||||
if not self.dialog:
|
||||
self.dialog = MDDialog(
|
||||
title="Address:",
|
||||
type="custom",
|
||||
content_cls=MDBoxLayout(
|
||||
MDTextField(
|
||||
hint_text="City",
|
||||
),
|
||||
MDTextField(
|
||||
hint_text="Street",
|
||||
),
|
||||
orientation="vertical",
|
||||
spacing="12dp",
|
||||
size_hint_y=None,
|
||||
height="120dp",
|
||||
),
|
||||
buttons=[
|
||||
MDFlatButton(
|
||||
text="CANCEL",
|
||||
theme_text_color="Custom",
|
||||
text_color=self.theme_cls.primary_color,
|
||||
),
|
||||
MDFlatButton(
|
||||
text="OK",
|
||||
theme_text_color="Custom",
|
||||
text_color=self.theme_cls.primary_color,
|
||||
),
|
||||
],
|
||||
)
|
||||
self.dialog.open()
|
||||
|
||||
|
||||
Example().run()
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/dialog-custom.png
|
||||
:align: center
|
||||
|
||||
|
@ -460,7 +568,7 @@ class MDDialog(BaseDialog):
|
|||
|
||||
md_bg_color = ColorProperty(None)
|
||||
"""
|
||||
Background color in the format (r, g, b, a).
|
||||
Background color in the (r, g, b, a) or string format.
|
||||
|
||||
:attr:`md_bg_color` is an :class:`~kivy.properties.ColorProperty`
|
||||
and defaults to `None`.
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<_Triangle>:
|
||||
canvas:
|
||||
Color:
|
||||
rgba: root.theme_cls.text_color
|
||||
rgba: app.theme_cls.text_color
|
||||
Triangle:
|
||||
points:
|
||||
[ \
|
||||
|
@ -13,7 +13,8 @@
|
|||
|
||||
<MDDropDownItem>
|
||||
orientation: "vertical"
|
||||
adaptive_size: True
|
||||
size_hint: None, None
|
||||
size: self.minimum_size
|
||||
spacing: "5dp"
|
||||
padding: "5dp", "5dp", "5dp", 0
|
||||
|
||||
|
|
|
@ -15,13 +15,13 @@ Usage
|
|||
from kivymd.app import MDApp
|
||||
|
||||
KV = '''
|
||||
Screen
|
||||
MDScreen
|
||||
|
||||
MDDropDownItem:
|
||||
id: drop_item
|
||||
pos_hint: {'center_x': .5, 'center_y': .5}
|
||||
text: 'Item'
|
||||
on_release: self.set_item("New Item")
|
||||
on_release: print("Press item")
|
||||
'''
|
||||
|
||||
|
||||
|
@ -48,12 +48,12 @@ import os
|
|||
from kivy.lang import Builder
|
||||
from kivy.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 FakeRectangularElevationBehavior
|
||||
from kivymd.uix.boxlayout import MDBoxLayout
|
||||
from kivymd.uix.behaviors import DeclarativeBehavior
|
||||
|
||||
with open(
|
||||
os.path.join(uix_path, "dropdownitem", "dropdownitem.kv"), encoding="utf-8"
|
||||
|
@ -61,15 +61,12 @@ with open(
|
|||
Builder.load_string(kv_file.read())
|
||||
|
||||
|
||||
class _Triangle(ThemableBehavior, Widget):
|
||||
class _Triangle(Widget):
|
||||
pass
|
||||
|
||||
|
||||
class MDDropDownItem(
|
||||
ThemableBehavior,
|
||||
FakeRectangularElevationBehavior,
|
||||
ButtonBehavior,
|
||||
MDBoxLayout,
|
||||
DeclarativeBehavior, ThemableBehavior, ButtonBehavior, BoxLayout
|
||||
):
|
||||
text = StringProperty()
|
||||
"""
|
||||
|
|
|
@ -56,6 +56,8 @@ Example
|
|||
|
||||
.. code-block:: python
|
||||
|
||||
import os
|
||||
|
||||
from kivy.lang import Builder
|
||||
|
||||
from kivymd.app import MDApp
|
||||
|
@ -75,7 +77,7 @@ Example
|
|||
icon: 'phone'
|
||||
|
||||
|
||||
ScrollView:
|
||||
MDScrollView:
|
||||
|
||||
MDGridLayout:
|
||||
id: box
|
||||
|
@ -96,7 +98,7 @@ Example
|
|||
for i in range(10):
|
||||
self.root.ids.box.add_widget(
|
||||
MDExpansionPanel(
|
||||
icon=f"{images_path}kivymd.png",
|
||||
icon=os.path.join(images_path, "logo", "kivymd-icon-128.png"),
|
||||
content=Content(),
|
||||
panel_cls=MDExpansionPanelThreeLine(
|
||||
text="Text",
|
||||
|
|
|
@ -6,28 +6,29 @@
|
|||
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
|
||||
on_release: root.events_callback(root.path, root)
|
||||
if root._selected else \
|
||||
self.theme_cls.bg_normal
|
||||
|
||||
IconLeftWidget:
|
||||
icon: root.icon
|
||||
theme_text_color: "Custom"
|
||||
text_color: self.theme_cls.primary_color
|
||||
theme_icon_color: "Custom"
|
||||
icon_color: root.icon_color
|
||||
|
||||
MDSeparator:
|
||||
|
||||
|
||||
<LabelContent@MDLabel>
|
||||
size_hint_y: None
|
||||
height: self.texture_size[1]
|
||||
adaptive_height: True
|
||||
shorten: True
|
||||
shorten_from: "center"
|
||||
halign: "center"
|
||||
|
@ -61,23 +62,6 @@
|
|||
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
|
||||
|
||||
|
@ -90,7 +74,11 @@
|
|||
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: 10
|
||||
elevation: 3
|
||||
md_bg_color:
|
||||
app.theme_cls.primary_color \
|
||||
if not root.background_color_toolbar else \
|
||||
root.background_color_toolbar
|
||||
|
||||
RecycleView:
|
||||
id: rv
|
||||
|
|