909 lines
29 KiB
Python
909 lines
29 KiB
Python
|
"""
|
|||
|
Themes/Theming
|
|||
|
==============
|
|||
|
|
|||
|
.. seealso::
|
|||
|
|
|||
|
`Material Design spec, Material theming <https://material.io/design/material-theming>`_
|
|||
|
|
|||
|
Material App
|
|||
|
------------
|
|||
|
|
|||
|
The main class of your application, which in `Kivy` inherits from the App class,
|
|||
|
in `KivyMD` must inherit from the `MDApp` class. The `MDApp` class has
|
|||
|
properties that allow you to control application properties
|
|||
|
such as :attr:`color/style/font` of interface elements and much more.
|
|||
|
|
|||
|
Control material properties
|
|||
|
---------------------------
|
|||
|
|
|||
|
The main application class inherited from the `MDApp` class has the :attr:`theme_cls`
|
|||
|
attribute, with which you control the material properties of your application.
|
|||
|
"""
|
|||
|
|
|||
|
from kivy.app import App
|
|||
|
from kivy.atlas import Atlas
|
|||
|
from kivy.clock import Clock
|
|||
|
from kivy.core.window import Window
|
|||
|
from kivy.event import EventDispatcher
|
|||
|
from kivy.metrics import dp
|
|||
|
from kivy.properties import (
|
|||
|
AliasProperty,
|
|||
|
BooleanProperty,
|
|||
|
DictProperty,
|
|||
|
ListProperty,
|
|||
|
ObjectProperty,
|
|||
|
OptionProperty,
|
|||
|
StringProperty,
|
|||
|
)
|
|||
|
from kivy.utils import get_color_from_hex
|
|||
|
|
|||
|
from kivymd import images_path
|
|||
|
from kivymd.color_definitions import colors, hue, palette
|
|||
|
from kivymd.material_resources import DEVICE_IOS, DEVICE_TYPE
|
|||
|
|
|||
|
from kivymd.font_definitions import theme_font_styles # NOQA: F401
|
|||
|
|
|||
|
|
|||
|
class ThemeManager(EventDispatcher):
|
|||
|
primary_palette = OptionProperty("Blue", options=palette)
|
|||
|
"""
|
|||
|
The name of the color scheme that the application will use.
|
|||
|
All major `material` components will have the color
|
|||
|
of the specified color theme.
|
|||
|
|
|||
|
Available options are: `'Red'`, `'Pink'`, `'Purple'`, `'DeepPurple'`,
|
|||
|
`'Indigo'`, `'Blue'`, `'LightBlue'`, `'Cyan'`, `'Teal'`, `'Green'`,
|
|||
|
`'LightGreen'`, `'Lime'`, `'Yellow'`, `'Amber'`, `'Orange'`, `'DeepOrange'`,
|
|||
|
`'Brown'`, `'Gray'`, `'BlueGray'`.
|
|||
|
|
|||
|
To change the color scheme of an application:
|
|||
|
|
|||
|
.. code-block:: python
|
|||
|
|
|||
|
from kivy.uix.screenmanager import Screen
|
|||
|
|
|||
|
from kivymd.app import MDApp
|
|||
|
from kivymd.uix.button import MDRectangleFlatButton
|
|||
|
|
|||
|
|
|||
|
class MainApp(MDApp):
|
|||
|
def build(self):
|
|||
|
self.theme_cls.primary_palette = "Green" # "Purple", "Red"
|
|||
|
|
|||
|
screen = Screen()
|
|||
|
screen.add_widget(
|
|||
|
MDRectangleFlatButton(
|
|||
|
text="Hello, World",
|
|||
|
pos_hint={"center_x": 0.5, "center_y": 0.5},
|
|||
|
)
|
|||
|
)
|
|||
|
return screen
|
|||
|
|
|||
|
|
|||
|
MainApp().run()
|
|||
|
|
|||
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/primary-palette.png
|
|||
|
|
|||
|
:attr:`primary_palette` is an :class:`~kivy.properties.OptionProperty`
|
|||
|
and defaults to `'Blue'`.
|
|||
|
"""
|
|||
|
|
|||
|
primary_hue = OptionProperty("500", options=hue)
|
|||
|
"""
|
|||
|
The color hue of the application.
|
|||
|
|
|||
|
Available options are: `'50'`, `'100'`, `'200'`, `'300'`, `'400'`, `'500'`,
|
|||
|
`'600'`, `'700'`, `'800'`, `'900'`, `'A100'`, `'A200'`, `'A400'`, `'A700'`.
|
|||
|
|
|||
|
To change the hue color scheme of an application:
|
|||
|
|
|||
|
.. code-block:: python
|
|||
|
|
|||
|
from kivy.uix.screenmanager import Screen
|
|||
|
|
|||
|
from kivymd.app import MDApp
|
|||
|
from kivymd.uix.button import MDRectangleFlatButton
|
|||
|
|
|||
|
|
|||
|
class MainApp(MDApp):
|
|||
|
def build(self):
|
|||
|
self.theme_cls.primary_palette = "Green" # "Purple", "Red"
|
|||
|
self.theme_cls.primary_hue = "200" # "500"
|
|||
|
|
|||
|
screen = Screen()
|
|||
|
screen.add_widget(
|
|||
|
MDRectangleFlatButton(
|
|||
|
text="Hello, World",
|
|||
|
pos_hint={"center_x": 0.5, "center_y": 0.5},
|
|||
|
)
|
|||
|
)
|
|||
|
return screen
|
|||
|
|
|||
|
|
|||
|
MainApp().run()
|
|||
|
|
|||
|
With a value of ``self.theme_cls.primary_hue = "500"``:
|
|||
|
|
|||
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/primary-palette.png
|
|||
|
|
|||
|
With a value of ``self.theme_cls.primary_hue = "200"``:
|
|||
|
|
|||
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/primary-hue.png
|
|||
|
|
|||
|
:attr:`primary_hue` is an :class:`~kivy.properties.OptionProperty`
|
|||
|
and defaults to `'500'`.
|
|||
|
"""
|
|||
|
|
|||
|
primary_light_hue = OptionProperty("200", options=hue)
|
|||
|
"""
|
|||
|
Hue value for :attr:`primary_light`.
|
|||
|
|
|||
|
:attr:`primary_light_hue` is an :class:`~kivy.properties.OptionProperty`
|
|||
|
and defaults to `'200'`.
|
|||
|
"""
|
|||
|
|
|||
|
primary_dark_hue = OptionProperty("700", options=hue)
|
|||
|
"""
|
|||
|
Hue value for :attr:`primary_dark`.
|
|||
|
|
|||
|
:attr:`primary_light_hue` is an :class:`~kivy.properties.OptionProperty`
|
|||
|
and defaults to `'700'`.
|
|||
|
"""
|
|||
|
|
|||
|
def _get_primary_color(self):
|
|||
|
return get_color_from_hex(
|
|||
|
colors[self.primary_palette][self.primary_hue]
|
|||
|
)
|
|||
|
|
|||
|
primary_color = AliasProperty(
|
|||
|
_get_primary_color, bind=("primary_palette", "primary_hue")
|
|||
|
)
|
|||
|
"""
|
|||
|
The color of the current application theme in ``rgba`` format.
|
|||
|
|
|||
|
:attr:`primary_color` is an :class:`~kivy.properties.AliasProperty` that
|
|||
|
returns the value of the current application theme, property is readonly.
|
|||
|
"""
|
|||
|
|
|||
|
def _get_primary_light(self):
|
|||
|
return get_color_from_hex(
|
|||
|
colors[self.primary_palette][self.primary_light_hue]
|
|||
|
)
|
|||
|
|
|||
|
primary_light = AliasProperty(
|
|||
|
_get_primary_light, bind=("primary_palette", "primary_light_hue")
|
|||
|
)
|
|||
|
"""
|
|||
|
Colors of the current application color theme in ``rgba`` format
|
|||
|
(in lighter color).
|
|||
|
|
|||
|
.. code-block:: python
|
|||
|
|
|||
|
from kivy.lang import Builder
|
|||
|
|
|||
|
from kivymd.app import MDApp
|
|||
|
|
|||
|
|
|||
|
KV = '''
|
|||
|
Screen:
|
|||
|
|
|||
|
MDRaisedButton:
|
|||
|
text: "primary_light"
|
|||
|
pos_hint: {"center_x": 0.5, "center_y": 0.7}
|
|||
|
md_bg_color: app.theme_cls.primary_light
|
|||
|
|
|||
|
MDRaisedButton:
|
|||
|
text: "primary_color"
|
|||
|
pos_hint: {"center_x": 0.5, "center_y": 0.5}
|
|||
|
|
|||
|
MDRaisedButton:
|
|||
|
text: "primary_dark"
|
|||
|
pos_hint: {"center_x": 0.5, "center_y": 0.3}
|
|||
|
md_bg_color: app.theme_cls.primary_dark
|
|||
|
'''
|
|||
|
|
|||
|
|
|||
|
class MainApp(MDApp):
|
|||
|
def build(self):
|
|||
|
self.theme_cls.primary_palette = "Green"
|
|||
|
return Builder.load_string(KV)
|
|||
|
|
|||
|
|
|||
|
MainApp().run()
|
|||
|
|
|||
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/primary-colors-light-dark.png
|
|||
|
:align: center
|
|||
|
|
|||
|
:attr:`primary_light` is an :class:`~kivy.properties.AliasProperty` that
|
|||
|
returns the value of the current application theme (in lighter color),
|
|||
|
property is readonly.
|
|||
|
"""
|
|||
|
|
|||
|
def _get_primary_dark(self):
|
|||
|
return get_color_from_hex(
|
|||
|
colors[self.primary_palette][self.primary_dark_hue]
|
|||
|
)
|
|||
|
|
|||
|
primary_dark = AliasProperty(
|
|||
|
_get_primary_dark, bind=("primary_palette", "primary_dark_hue")
|
|||
|
)
|
|||
|
"""
|
|||
|
Colors of the current application color theme
|
|||
|
in ``rgba`` format (in darker color).
|
|||
|
|
|||
|
:attr:`primary_dark` is an :class:`~kivy.properties.AliasProperty` that
|
|||
|
returns the value of the current application theme (in darker color),
|
|||
|
property is readonly.
|
|||
|
"""
|
|||
|
|
|||
|
accent_palette = OptionProperty("Amber", options=palette)
|
|||
|
"""
|
|||
|
The application color palette used for items such as the tab indicator
|
|||
|
in the :attr:`MDTabsBar` class and so on...
|
|||
|
|
|||
|
The image below shows the color schemes with the values
|
|||
|
``self.theme_cls.accent_palette = 'Blue'``, ``Red'`` and ``Yellow'``:
|
|||
|
|
|||
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/accent-palette.png
|
|||
|
|
|||
|
:attr:`primary_hue` is an :class:`~kivy.properties.OptionProperty`
|
|||
|
and defaults to `'Amber'`.
|
|||
|
"""
|
|||
|
|
|||
|
accent_hue = OptionProperty("500", options=hue)
|
|||
|
"""Similar to :attr:`primary_hue`,
|
|||
|
but returns a value for :attr:`accent_palette`.
|
|||
|
|
|||
|
:attr:`accent_hue` is an :class:`~kivy.properties.OptionProperty`
|
|||
|
and defaults to `'500'`.
|
|||
|
"""
|
|||
|
|
|||
|
accent_light_hue = OptionProperty("200", options=hue)
|
|||
|
"""
|
|||
|
Hue value for :attr:`accent_light`.
|
|||
|
|
|||
|
:attr:`accent_light_hue` is an :class:`~kivy.properties.OptionProperty`
|
|||
|
and defaults to `'200'`.
|
|||
|
"""
|
|||
|
|
|||
|
accent_dark_hue = OptionProperty("700", options=hue)
|
|||
|
"""
|
|||
|
Hue value for :attr:`accent_dark`.
|
|||
|
|
|||
|
:attr:`accent_dark_hue` is an :class:`~kivy.properties.OptionProperty`
|
|||
|
and defaults to `'700'`.
|
|||
|
"""
|
|||
|
|
|||
|
def _get_accent_color(self):
|
|||
|
return get_color_from_hex(colors[self.accent_palette][self.accent_hue])
|
|||
|
|
|||
|
accent_color = AliasProperty(
|
|||
|
_get_accent_color, bind=["accent_palette", "accent_hue"]
|
|||
|
)
|
|||
|
"""Similar to :attr:`primary_color`,
|
|||
|
but returns a value for :attr:`accent_color`.
|
|||
|
|
|||
|
:attr:`accent_color` is an :class:`~kivy.properties.AliasProperty` that
|
|||
|
returns the value in ``rgba`` format for :attr:`accent_color`,
|
|||
|
property is readonly.
|
|||
|
"""
|
|||
|
|
|||
|
def _get_accent_light(self):
|
|||
|
return get_color_from_hex(
|
|||
|
colors[self.accent_palette][self.accent_light_hue]
|
|||
|
)
|
|||
|
|
|||
|
accent_light = AliasProperty(
|
|||
|
_get_accent_light, bind=["accent_palette", "accent_light_hue"]
|
|||
|
)
|
|||
|
"""Similar to :attr:`primary_light`,
|
|||
|
but returns a value for :attr:`accent_light`.
|
|||
|
|
|||
|
:attr:`accent_light` is an :class:`~kivy.properties.AliasProperty` that
|
|||
|
returns the value in ``rgba`` format for :attr:`accent_light`,
|
|||
|
property is readonly.
|
|||
|
"""
|
|||
|
|
|||
|
def _get_accent_dark(self):
|
|||
|
return get_color_from_hex(
|
|||
|
colors[self.accent_palette][self.accent_dark_hue]
|
|||
|
)
|
|||
|
|
|||
|
accent_dark = AliasProperty(
|
|||
|
_get_accent_dark, bind=["accent_palette", "accent_dark_hue"]
|
|||
|
)
|
|||
|
"""Similar to :attr:`primary_dark`,
|
|||
|
but returns a value for :attr:`accent_dark`.
|
|||
|
|
|||
|
:attr:`accent_dark` is an :class:`~kivy.properties.AliasProperty` that
|
|||
|
returns the value in ``rgba`` format for :attr:`accent_dark`,
|
|||
|
property is readonly.
|
|||
|
"""
|
|||
|
|
|||
|
theme_style = OptionProperty("Light", options=["Light", "Dark"])
|
|||
|
"""App theme style.
|
|||
|
|
|||
|
.. code-block:: python
|
|||
|
|
|||
|
from kivy.uix.screenmanager import Screen
|
|||
|
|
|||
|
from kivymd.app import MDApp
|
|||
|
from kivymd.uix.button import MDRectangleFlatButton
|
|||
|
|
|||
|
|
|||
|
class MainApp(MDApp):
|
|||
|
def build(self):
|
|||
|
self.theme_cls.theme_style = "Dark" # "Light"
|
|||
|
|
|||
|
screen = Screen()
|
|||
|
screen.add_widget(
|
|||
|
MDRectangleFlatButton(
|
|||
|
text="Hello, World",
|
|||
|
pos_hint={"center_x": 0.5, "center_y": 0.5},
|
|||
|
)
|
|||
|
)
|
|||
|
return screen
|
|||
|
|
|||
|
|
|||
|
MainApp().run()
|
|||
|
|
|||
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/theme-style.png
|
|||
|
|
|||
|
:attr:`theme_style` is an :class:`~kivy.properties.OptionProperty`
|
|||
|
and defaults to `'Light'`.
|
|||
|
"""
|
|||
|
|
|||
|
def _get_theme_style(self, opposite):
|
|||
|
if opposite:
|
|||
|
return "Light" if self.theme_style == "Dark" else "Dark"
|
|||
|
else:
|
|||
|
return self.theme_style
|
|||
|
|
|||
|
def _get_bg_darkest(self, opposite=False):
|
|||
|
theme_style = self._get_theme_style(opposite)
|
|||
|
if theme_style == "Light":
|
|||
|
return get_color_from_hex(colors["Light"]["StatusBar"])
|
|||
|
elif theme_style == "Dark":
|
|||
|
return get_color_from_hex(colors["Dark"]["StatusBar"])
|
|||
|
|
|||
|
bg_darkest = AliasProperty(_get_bg_darkest, bind=["theme_style"])
|
|||
|
"""
|
|||
|
Similar to :attr:`bg_dark`,
|
|||
|
but the color values are a tone lower (darker) than :attr:`bg_dark`.
|
|||
|
|
|||
|
.. code-block:: python
|
|||
|
|
|||
|
KV = '''
|
|||
|
<Box@BoxLayout>:
|
|||
|
bg: 0, 0, 0, 0
|
|||
|
|
|||
|
canvas:
|
|||
|
Color:
|
|||
|
rgba: root.bg
|
|||
|
Rectangle:
|
|||
|
pos: self.pos
|
|||
|
size: self.size
|
|||
|
|
|||
|
BoxLayout:
|
|||
|
|
|||
|
Box:
|
|||
|
bg: app.theme_cls.bg_light
|
|||
|
Box:
|
|||
|
bg: app.theme_cls.bg_normal
|
|||
|
Box:
|
|||
|
bg: app.theme_cls.bg_dark
|
|||
|
Box:
|
|||
|
bg: app.theme_cls.bg_darkest
|
|||
|
'''
|
|||
|
|
|||
|
from kivy.lang import Builder
|
|||
|
|
|||
|
from kivymd.app import MDApp
|
|||
|
|
|||
|
|
|||
|
class MainApp(MDApp):
|
|||
|
def build(self):
|
|||
|
self.theme_cls.theme_style = "Dark" # "Light"
|
|||
|
return Builder.load_string(KV)
|
|||
|
|
|||
|
|
|||
|
MainApp().run()
|
|||
|
|
|||
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/bg-normal-dark-darkest.png
|
|||
|
|
|||
|
:attr:`bg_darkest` is an :class:`~kivy.properties.AliasProperty` that
|
|||
|
returns the value in ``rgba`` format for :attr:`bg_darkest`,
|
|||
|
property is readonly.
|
|||
|
"""
|
|||
|
|
|||
|
def _get_op_bg_darkest(self):
|
|||
|
return self._get_bg_darkest(True)
|
|||
|
|
|||
|
opposite_bg_darkest = AliasProperty(
|
|||
|
_get_op_bg_darkest, bind=["theme_style"]
|
|||
|
)
|
|||
|
"""
|
|||
|
The opposite value of color in the :attr:`bg_darkest`.
|
|||
|
|
|||
|
:attr:`opposite_bg_darkest` is an :class:`~kivy.properties.AliasProperty`
|
|||
|
that returns the value in ``rgba`` format for :attr:`opposite_bg_darkest`,
|
|||
|
property is readonly.
|
|||
|
"""
|
|||
|
|
|||
|
def _get_bg_dark(self, opposite=False):
|
|||
|
theme_style = self._get_theme_style(opposite)
|
|||
|
if theme_style == "Light":
|
|||
|
return get_color_from_hex(colors["Light"]["AppBar"])
|
|||
|
elif theme_style == "Dark":
|
|||
|
return get_color_from_hex(colors["Dark"]["AppBar"])
|
|||
|
|
|||
|
bg_dark = AliasProperty(_get_bg_dark, bind=["theme_style"])
|
|||
|
"""
|
|||
|
Similar to :attr:`bg_normal`,
|
|||
|
but the color values are one tone lower (darker) than :attr:`bg_normal`.
|
|||
|
|
|||
|
:attr:`bg_dark` is an :class:`~kivy.properties.AliasProperty` that
|
|||
|
returns the value in ``rgba`` format for :attr:`bg_dark`,
|
|||
|
property is readonly.
|
|||
|
"""
|
|||
|
|
|||
|
def _get_op_bg_dark(self):
|
|||
|
return self._get_bg_dark(True)
|
|||
|
|
|||
|
opposite_bg_dark = AliasProperty(_get_op_bg_dark, bind=["theme_style"])
|
|||
|
"""
|
|||
|
The opposite value of color in the :attr:`bg_dark`.
|
|||
|
|
|||
|
:attr:`opposite_bg_dark` is an :class:`~kivy.properties.AliasProperty` that
|
|||
|
returns the value in ``rgba`` format for :attr:`opposite_bg_dark`,
|
|||
|
property is readonly.
|
|||
|
"""
|
|||
|
|
|||
|
def _get_bg_normal(self, opposite=False):
|
|||
|
theme_style = self._get_theme_style(opposite)
|
|||
|
if theme_style == "Light":
|
|||
|
return get_color_from_hex(colors["Light"]["Background"])
|
|||
|
elif theme_style == "Dark":
|
|||
|
return get_color_from_hex(colors["Dark"]["Background"])
|
|||
|
|
|||
|
bg_normal = AliasProperty(_get_bg_normal, bind=["theme_style"])
|
|||
|
"""
|
|||
|
Similar to :attr:`bg_light`,
|
|||
|
but the color values are one tone lower (darker) than :attr:`bg_light`.
|
|||
|
|
|||
|
:attr:`bg_normal` is an :class:`~kivy.properties.AliasProperty` that
|
|||
|
returns the value in ``rgba`` format for :attr:`bg_normal`,
|
|||
|
property is readonly.
|
|||
|
"""
|
|||
|
|
|||
|
def _get_op_bg_normal(self):
|
|||
|
return self._get_bg_normal(True)
|
|||
|
|
|||
|
opposite_bg_normal = AliasProperty(_get_op_bg_normal, bind=["theme_style"])
|
|||
|
"""
|
|||
|
The opposite value of color in the :attr:`bg_normal`.
|
|||
|
|
|||
|
:attr:`opposite_bg_normal` is an :class:`~kivy.properties.AliasProperty`
|
|||
|
that returns the value in ``rgba`` format for :attr:`opposite_bg_normal`,
|
|||
|
property is readonly.
|
|||
|
"""
|
|||
|
|
|||
|
def _get_bg_light(self, opposite=False):
|
|||
|
theme_style = self._get_theme_style(opposite)
|
|||
|
if theme_style == "Light":
|
|||
|
return get_color_from_hex(colors["Light"]["CardsDialogs"])
|
|||
|
elif theme_style == "Dark":
|
|||
|
return get_color_from_hex(colors["Dark"]["CardsDialogs"])
|
|||
|
|
|||
|
bg_light = AliasProperty(_get_bg_light, bind=["theme_style"])
|
|||
|
""""
|
|||
|
Depending on the style of the theme (`'Dark'` or `'Light`')
|
|||
|
that the application uses, :attr:`bg_light` contains the color value
|
|||
|
in ``rgba`` format for the widgets background.
|
|||
|
|
|||
|
:attr:`bg_light` is an :class:`~kivy.properties.AliasProperty` that
|
|||
|
returns the value in ``rgba`` format for :attr:`bg_light`,
|
|||
|
property is readonly.
|
|||
|
"""
|
|||
|
|
|||
|
def _get_op_bg_light(self):
|
|||
|
return self._get_bg_light(True)
|
|||
|
|
|||
|
opposite_bg_light = AliasProperty(_get_op_bg_light, bind=["theme_style"])
|
|||
|
"""
|
|||
|
The opposite value of color in the :attr:`bg_light`.
|
|||
|
|
|||
|
:attr:`opposite_bg_light` is an :class:`~kivy.properties.AliasProperty`
|
|||
|
that returns the value in ``rgba`` format for :attr:`opposite_bg_light`,
|
|||
|
property is readonly.
|
|||
|
"""
|
|||
|
|
|||
|
def _get_divider_color(self, opposite=False):
|
|||
|
theme_style = self._get_theme_style(opposite)
|
|||
|
if theme_style == "Light":
|
|||
|
color = get_color_from_hex("000000")
|
|||
|
elif theme_style == "Dark":
|
|||
|
color = get_color_from_hex("FFFFFF")
|
|||
|
color[3] = 0.12
|
|||
|
return color
|
|||
|
|
|||
|
divider_color = AliasProperty(_get_divider_color, bind=["theme_style"])
|
|||
|
"""
|
|||
|
Color for dividing lines such as :class:`~kivymd.uix.card.MDSeparator`.
|
|||
|
|
|||
|
:attr:`divider_color` is an :class:`~kivy.properties.AliasProperty` that
|
|||
|
returns the value in ``rgba`` format for :attr:`divider_color`,
|
|||
|
property is readonly.
|
|||
|
"""
|
|||
|
|
|||
|
def _get_op_divider_color(self):
|
|||
|
return self._get_divider_color(True)
|
|||
|
|
|||
|
opposite_divider_color = AliasProperty(
|
|||
|
_get_op_divider_color, bind=["theme_style"]
|
|||
|
)
|
|||
|
"""
|
|||
|
The opposite value of color in the :attr:`divider_color`.
|
|||
|
|
|||
|
:attr:`opposite_divider_color` is an :class:`~kivy.properties.AliasProperty`
|
|||
|
that returns the value in ``rgba`` format for :attr:`opposite_divider_color`,
|
|||
|
property is readonly.
|
|||
|
"""
|
|||
|
|
|||
|
def _get_text_color(self, opposite=False):
|
|||
|
theme_style = self._get_theme_style(opposite)
|
|||
|
if theme_style == "Light":
|
|||
|
color = get_color_from_hex("000000")
|
|||
|
color[3] = 0.87
|
|||
|
elif theme_style == "Dark":
|
|||
|
color = get_color_from_hex("FFFFFF")
|
|||
|
return color
|
|||
|
|
|||
|
text_color = AliasProperty(_get_text_color, bind=["theme_style"])
|
|||
|
"""
|
|||
|
Color of the text used in the :class:`~kivymd.uix.label.MDLabel`.
|
|||
|
|
|||
|
:attr:`text_color` is an :class:`~kivy.properties.AliasProperty` that
|
|||
|
returns the value in ``rgba`` format for :attr:`text_color`,
|
|||
|
property is readonly.
|
|||
|
"""
|
|||
|
|
|||
|
def _get_op_text_color(self):
|
|||
|
return self._get_text_color(True)
|
|||
|
|
|||
|
opposite_text_color = AliasProperty(
|
|||
|
_get_op_text_color, bind=["theme_style"]
|
|||
|
)
|
|||
|
"""
|
|||
|
The opposite value of color in the :attr:`text_color`.
|
|||
|
|
|||
|
:attr:`opposite_text_color` is an :class:`~kivy.properties.AliasProperty`
|
|||
|
that returns the value in ``rgba`` format for :attr:`opposite_text_color`,
|
|||
|
property is readonly.
|
|||
|
"""
|
|||
|
|
|||
|
def _get_secondary_text_color(self, opposite=False):
|
|||
|
theme_style = self._get_theme_style(opposite)
|
|||
|
if theme_style == "Light":
|
|||
|
color = get_color_from_hex("000000")
|
|||
|
color[3] = 0.54
|
|||
|
elif theme_style == "Dark":
|
|||
|
color = get_color_from_hex("FFFFFF")
|
|||
|
color[3] = 0.70
|
|||
|
return color
|
|||
|
|
|||
|
secondary_text_color = AliasProperty(
|
|||
|
_get_secondary_text_color, bind=["theme_style"]
|
|||
|
)
|
|||
|
"""
|
|||
|
The color for the secondary text that is used in classes
|
|||
|
from the module :class:`~kivymd/uix/list.TwoLineListItem`.
|
|||
|
|
|||
|
:attr:`secondary_text_color` is an :class:`~kivy.properties.AliasProperty`
|
|||
|
that returns the value in ``rgba`` format for :attr:`secondary_text_color`,
|
|||
|
property is readonly.
|
|||
|
"""
|
|||
|
|
|||
|
def _get_op_secondary_text_color(self):
|
|||
|
return self._get_secondary_text_color(True)
|
|||
|
|
|||
|
opposite_secondary_text_color = AliasProperty(
|
|||
|
_get_op_secondary_text_color, bind=["theme_style"]
|
|||
|
)
|
|||
|
"""
|
|||
|
The opposite value of color in the :attr:`secondary_text_color`.
|
|||
|
|
|||
|
:attr:`opposite_secondary_text_color`
|
|||
|
is an :class:`~kivy.properties.AliasProperty` that returns the value
|
|||
|
in ``rgba`` format for :attr:`opposite_secondary_text_color`,
|
|||
|
property is readonly.
|
|||
|
"""
|
|||
|
|
|||
|
def _get_icon_color(self, opposite=False):
|
|||
|
theme_style = self._get_theme_style(opposite)
|
|||
|
if theme_style == "Light":
|
|||
|
color = get_color_from_hex("000000")
|
|||
|
color[3] = 0.54
|
|||
|
elif theme_style == "Dark":
|
|||
|
color = get_color_from_hex("FFFFFF")
|
|||
|
return color
|
|||
|
|
|||
|
icon_color = AliasProperty(_get_icon_color, bind=["theme_style"])
|
|||
|
"""
|
|||
|
Color of the icon used in the :class:`~kivymd.uix.button.MDIconButton`.
|
|||
|
|
|||
|
:attr:`icon_color` is an :class:`~kivy.properties.AliasProperty` that
|
|||
|
returns the value in ``rgba`` format for :attr:`icon_color`,
|
|||
|
property is readonly.
|
|||
|
"""
|
|||
|
|
|||
|
def _get_op_icon_color(self):
|
|||
|
return self._get_icon_color(True)
|
|||
|
|
|||
|
opposite_icon_color = AliasProperty(
|
|||
|
_get_op_icon_color, bind=["theme_style"]
|
|||
|
)
|
|||
|
"""
|
|||
|
The opposite value of color in the :attr:`icon_color`.
|
|||
|
|
|||
|
:attr:`opposite_icon_color` is an :class:`~kivy.properties.AliasProperty`
|
|||
|
that returns the value in ``rgba`` format for :attr:`opposite_icon_color`,
|
|||
|
property is readonly.
|
|||
|
"""
|
|||
|
|
|||
|
def _get_disabled_hint_text_color(self, opposite=False):
|
|||
|
theme_style = self._get_theme_style(opposite)
|
|||
|
if theme_style == "Light":
|
|||
|
color = get_color_from_hex("000000")
|
|||
|
color[3] = 0.38
|
|||
|
elif theme_style == "Dark":
|
|||
|
color = get_color_from_hex("FFFFFF")
|
|||
|
color[3] = 0.50
|
|||
|
return color
|
|||
|
|
|||
|
disabled_hint_text_color = AliasProperty(
|
|||
|
_get_disabled_hint_text_color, bind=["theme_style"]
|
|||
|
)
|
|||
|
"""
|
|||
|
Color of the disabled text used in the :class:`~kivymd.uix.textfield.MDTextField`.
|
|||
|
|
|||
|
:attr:`disabled_hint_text_color`
|
|||
|
is an :class:`~kivy.properties.AliasProperty` that returns the value
|
|||
|
in ``rgba`` format for :attr:`disabled_hint_text_color`,
|
|||
|
property is readonly.
|
|||
|
"""
|
|||
|
|
|||
|
def _get_op_disabled_hint_text_color(self):
|
|||
|
return self._get_disabled_hint_text_color(True)
|
|||
|
|
|||
|
opposite_disabled_hint_text_color = AliasProperty(
|
|||
|
_get_op_disabled_hint_text_color, bind=["theme_style"]
|
|||
|
)
|
|||
|
"""
|
|||
|
The opposite value of color in the :attr:`disabled_hint_text_color`.
|
|||
|
|
|||
|
:attr:`opposite_disabled_hint_text_color`
|
|||
|
is an :class:`~kivy.properties.AliasProperty` that returns the value
|
|||
|
in ``rgba`` format for :attr:`opposite_disabled_hint_text_color`,
|
|||
|
property is readonly.
|
|||
|
"""
|
|||
|
|
|||
|
# Hardcoded because muh standard
|
|||
|
def _get_error_color(self):
|
|||
|
return get_color_from_hex(colors["Red"]["A700"])
|
|||
|
|
|||
|
error_color = AliasProperty(_get_error_color)
|
|||
|
"""
|
|||
|
Color of the error text used
|
|||
|
in the :class:`~kivymd.uix.textfield.MDTextField`.
|
|||
|
|
|||
|
:attr:`error_color` is an :class:`~kivy.properties.AliasProperty` that
|
|||
|
returns the value in ``rgba`` format for :attr:`error_color`,
|
|||
|
property is readonly.
|
|||
|
"""
|
|||
|
|
|||
|
def _get_ripple_color(self):
|
|||
|
return self._ripple_color
|
|||
|
|
|||
|
def _set_ripple_color(self, value):
|
|||
|
self._ripple_color = value
|
|||
|
|
|||
|
_ripple_color = ListProperty(get_color_from_hex(colors["Gray"]["400"]))
|
|||
|
"""Private value."""
|
|||
|
|
|||
|
ripple_color = AliasProperty(
|
|||
|
_get_ripple_color, _set_ripple_color, bind=["_ripple_color"]
|
|||
|
)
|
|||
|
"""
|
|||
|
Color of ripple effects.
|
|||
|
|
|||
|
:attr:`ripple_color` is an :class:`~kivy.properties.AliasProperty` that
|
|||
|
returns the value in ``rgba`` format for :attr:`ripple_color`,
|
|||
|
property is readonly.
|
|||
|
"""
|
|||
|
|
|||
|
def _determine_device_orientation(self, _, window_size):
|
|||
|
if window_size[0] > window_size[1]:
|
|||
|
self.device_orientation = "landscape"
|
|||
|
elif window_size[1] >= window_size[0]:
|
|||
|
self.device_orientation = "portrait"
|
|||
|
|
|||
|
device_orientation = StringProperty("")
|
|||
|
"""
|
|||
|
Device orientation.
|
|||
|
|
|||
|
:attr:`device_orientation` is an :class:`~kivy.properties.StringProperty`.
|
|||
|
"""
|
|||
|
|
|||
|
def _get_standard_increment(self):
|
|||
|
if DEVICE_TYPE == "mobile":
|
|||
|
if self.device_orientation == "landscape":
|
|||
|
return dp(48)
|
|||
|
else:
|
|||
|
return dp(56)
|
|||
|
else:
|
|||
|
return dp(64)
|
|||
|
|
|||
|
standard_increment = AliasProperty(
|
|||
|
_get_standard_increment, bind=["device_orientation"]
|
|||
|
)
|
|||
|
"""
|
|||
|
Value of standard increment.
|
|||
|
|
|||
|
:attr:`standard_increment` is an :class:`~kivy.properties.AliasProperty`
|
|||
|
that returns the value in ``rgba`` format for :attr:`standard_increment`,
|
|||
|
property is readonly.
|
|||
|
"""
|
|||
|
|
|||
|
def _get_horizontal_margins(self):
|
|||
|
if DEVICE_TYPE == "mobile":
|
|||
|
return dp(16)
|
|||
|
else:
|
|||
|
return dp(24)
|
|||
|
|
|||
|
horizontal_margins = AliasProperty(_get_horizontal_margins)
|
|||
|
"""
|
|||
|
Value of horizontal margins.
|
|||
|
|
|||
|
:attr:`horizontal_margins` is an :class:`~kivy.properties.AliasProperty`
|
|||
|
that returns the value in ``rgba`` format for :attr:`horizontal_margins`,
|
|||
|
property is readonly.
|
|||
|
"""
|
|||
|
|
|||
|
def on_theme_style(self, instance, value):
|
|||
|
if (
|
|||
|
hasattr(App.get_running_app(), "theme_cls")
|
|||
|
and App.get_running_app().theme_cls == self
|
|||
|
):
|
|||
|
self.set_clearcolor_by_theme_style(value)
|
|||
|
|
|||
|
set_clearcolor = BooleanProperty(True)
|
|||
|
|
|||
|
def set_clearcolor_by_theme_style(self, theme_style):
|
|||
|
if not self.set_clearcolor:
|
|||
|
return
|
|||
|
if theme_style == "Light":
|
|||
|
Window.clearcolor = get_color_from_hex(
|
|||
|
colors["Light"]["Background"]
|
|||
|
)
|
|||
|
elif theme_style == "Dark":
|
|||
|
Window.clearcolor = get_color_from_hex(colors["Dark"]["Background"])
|
|||
|
|
|||
|
# font name, size (sp), always caps, letter spacing (sp)
|
|||
|
font_styles = DictProperty(
|
|||
|
{
|
|||
|
"H1": ["RobotoLight", 96, False, -1.5],
|
|||
|
"H2": ["RobotoLight", 60, False, -0.5],
|
|||
|
"H3": ["Roboto", 48, False, 0],
|
|||
|
"H4": ["Roboto", 34, False, 0.25],
|
|||
|
"H5": ["Roboto", 24, False, 0],
|
|||
|
"H6": ["RobotoMedium", 20, False, 0.15],
|
|||
|
"Subtitle1": ["Roboto", 16, False, 0.15],
|
|||
|
"Subtitle2": ["RobotoMedium", 14, False, 0.1],
|
|||
|
"Body1": ["Roboto", 16, False, 0.5],
|
|||
|
"Body2": ["Roboto", 14, False, 0.25],
|
|||
|
"Button": ["RobotoMedium", 14, True, 1.25],
|
|||
|
"Caption": ["Roboto", 12, False, 0.4],
|
|||
|
"Overline": ["Roboto", 10, True, 1.5],
|
|||
|
"Icon": ["Icons", 24, False, 0],
|
|||
|
}
|
|||
|
)
|
|||
|
"""
|
|||
|
Data of default font styles.
|
|||
|
|
|||
|
Add custom font:
|
|||
|
|
|||
|
.. code-block:: python
|
|||
|
|
|||
|
KV = '''
|
|||
|
Screen:
|
|||
|
|
|||
|
MDLabel:
|
|||
|
text: "JetBrainsMono"
|
|||
|
halign: "center"
|
|||
|
font_style: "JetBrainsMono"
|
|||
|
'''
|
|||
|
|
|||
|
from kivy.core.text import LabelBase
|
|||
|
|
|||
|
from kivy.lang import Builder
|
|||
|
|
|||
|
from kivymd.app import MDApp
|
|||
|
from kivymd.font_definitions import theme_font_styles
|
|||
|
|
|||
|
|
|||
|
class MainApp(MDApp):
|
|||
|
def build(self):
|
|||
|
LabelBase.register(
|
|||
|
name="JetBrainsMono",
|
|||
|
fn_regular="JetBrainsMono-Regular.ttf")
|
|||
|
|
|||
|
theme_font_styles.append('JetBrainsMono')
|
|||
|
self.theme_cls.font_styles["JetBrainsMono"] = [
|
|||
|
"JetBrainsMono",
|
|||
|
16,
|
|||
|
False,
|
|||
|
0.15,
|
|||
|
]
|
|||
|
return Builder.load_string(KV)
|
|||
|
|
|||
|
|
|||
|
MainApp().run()
|
|||
|
|
|||
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/font-styles.png
|
|||
|
|
|||
|
:attr:`font_styles` is an :class:`~kivy.properties.DictProperty`.
|
|||
|
"""
|
|||
|
|
|||
|
def __init__(self, **kwargs):
|
|||
|
super().__init__(**kwargs)
|
|||
|
self.rec_shadow = Atlas(f"{images_path}rec_shadow.atlas")
|
|||
|
self.rec_st_shadow = Atlas(f"{images_path}rec_st_shadow.atlas")
|
|||
|
self.quad_shadow = Atlas(f"{images_path}quad_shadow.atlas")
|
|||
|
self.round_shadow = Atlas(f"{images_path}round_shadow.atlas")
|
|||
|
Clock.schedule_once(lambda x: self.on_theme_style(0, self.theme_style))
|
|||
|
self._determine_device_orientation(None, Window.size)
|
|||
|
Window.bind(size=self._determine_device_orientation)
|
|||
|
|
|||
|
|
|||
|
class ThemableBehavior(EventDispatcher):
|
|||
|
theme_cls = ObjectProperty()
|
|||
|
"""
|
|||
|
Instance of :class:`~ThemeManager` class.
|
|||
|
|
|||
|
:attr:`theme_cls` is an :class:`~kivy.properties.ObjectProperty`.
|
|||
|
"""
|
|||
|
|
|||
|
device_ios = BooleanProperty(DEVICE_IOS)
|
|||
|
"""
|
|||
|
``True`` if device is ``iOS``.
|
|||
|
|
|||
|
:attr:`device_ios` is an :class:`~kivy.properties.BooleanProperty`.
|
|||
|
"""
|
|||
|
|
|||
|
opposite_colors = BooleanProperty(False)
|
|||
|
|
|||
|
def __init__(self, **kwargs):
|
|||
|
if self.theme_cls is not None:
|
|||
|
pass
|
|||
|
else:
|
|||
|
try:
|
|||
|
if not isinstance(
|
|||
|
App.get_running_app().property("theme_cls", True),
|
|||
|
ObjectProperty,
|
|||
|
):
|
|||
|
raise ValueError(
|
|||
|
"KivyMD: App object must be inherited from "
|
|||
|
"`kivymd.app.MDApp`. See "
|
|||
|
"https://github.com/kivymd/KivyMD/blob/master/README.md#api-breaking-changes"
|
|||
|
)
|
|||
|
except AttributeError:
|
|||
|
raise ValueError(
|
|||
|
"KivyMD: App object must be initialized before loading "
|
|||
|
"root widget. See "
|
|||
|
"https://github.com/kivymd/KivyMD/wiki/Modules-Material-App#exceptions"
|
|||
|
)
|
|||
|
self.theme_cls = App.get_running_app().theme_cls
|
|||
|
super().__init__(**kwargs)
|