2024-09-15 12:12:16 +00:00
|
|
|
|
"""
|
2024-09-15 17:57:02 +00:00
|
|
|
|
Components/Text fields
|
|
|
|
|
======================
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
|
|
|
|
.. seealso::
|
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
`Material Design spec, Text fields <https://m3.material.io/components/text-fields/specs>`_
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
.. rubric:: Text fields let users enter text into a UI.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
|
|
|
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-fields.png
|
|
|
|
|
:align: center
|
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
- Make sure text fields look interactive
|
|
|
|
|
- Two types: filled and outlined
|
|
|
|
|
- The text field’s state (blank, with input, error, etc) should be visible at a glance
|
|
|
|
|
- Keep labels and error messages brief and easy to act on
|
|
|
|
|
- Text fields commonly appear in forms and dialogs
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/available-fields.png
|
2024-09-15 12:12:16 +00:00
|
|
|
|
:align: center
|
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
1. Filled text field
|
|
|
|
|
2. Outlined text field
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
Usage
|
|
|
|
|
-----
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
|
|
|
|
.. code-block:: kv
|
|
|
|
|
|
|
|
|
|
MDTextField:
|
2024-09-15 17:57:02 +00:00
|
|
|
|
mode: "filled"
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
MDTextFieldLeadingIcon:
|
|
|
|
|
icon: "magnify"
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
MDTextFieldHintText:
|
|
|
|
|
text: "Hint text"
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
MDTextFieldHelperText:
|
|
|
|
|
text: "Helper text"
|
|
|
|
|
mode: "persistent"
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
MDTextFieldTrailingIcon:
|
|
|
|
|
icon: "information"
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
MDTextFieldMaxLengthText:
|
|
|
|
|
max_text_length: 10
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
Anatomy
|
|
|
|
|
-------
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-fields-anatomy.png
|
2024-09-15 12:12:16 +00:00
|
|
|
|
:align: center
|
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
Available types of text fields
|
|
|
|
|
==============================
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
Filled mode
|
|
|
|
|
-----------
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
|
|
|
|
.. code-block:: kv
|
|
|
|
|
|
|
|
|
|
MDTextField:
|
2024-09-15 17:57:02 +00:00
|
|
|
|
mode: "filled"
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-fields-filled-mode.png
|
2024-09-15 12:12:16 +00:00
|
|
|
|
:align: center
|
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
Outlined mode
|
|
|
|
|
-------------
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
|
|
|
|
.. code-block:: kv
|
|
|
|
|
|
|
|
|
|
MDTextField:
|
2024-09-15 17:57:02 +00:00
|
|
|
|
mode: "outlined"
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-fields-outlined-mode.png
|
2024-09-15 12:12:16 +00:00
|
|
|
|
:align: center
|
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
Example
|
|
|
|
|
-------
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
.. tabs::
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
.. tab:: Declarative KV style
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
.. code-block:: python
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
from kivy.lang import Builder
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
from kivymd.app import MDApp
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
KV = '''
|
|
|
|
|
MDScreen:
|
|
|
|
|
md_bg_color: app.theme_cls.backgroundColor
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
MDTextField:
|
|
|
|
|
mode: "outlined"
|
|
|
|
|
size_hint_x: None
|
|
|
|
|
width: "240dp"
|
|
|
|
|
pos_hint: {"center_x": .5, "center_y": .5}
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
MDTextFieldLeadingIcon:
|
|
|
|
|
icon: "account"
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
MDTextFieldHintText:
|
|
|
|
|
text: "Outlined"
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
MDTextFieldHelperText:
|
|
|
|
|
text: "Helper text"
|
|
|
|
|
mode: "persistent"
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
MDTextFieldTrailingIcon:
|
|
|
|
|
icon: "information"
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
MDTextFieldMaxLengthText:
|
|
|
|
|
max_text_length: 10
|
|
|
|
|
'''
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
class Example(MDApp):
|
|
|
|
|
def build(self):
|
|
|
|
|
self.theme_cls.primary_palette = "Olive"
|
|
|
|
|
return Builder.load_string(KV)
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
Example().run()
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
.. tab:: Declarative Python style
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
.. code-block:: python
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
from kivymd.uix.textfield import (
|
|
|
|
|
MDTextField,
|
|
|
|
|
MDTextFieldLeadingIcon,
|
|
|
|
|
MDTextFieldHintText,
|
|
|
|
|
MDTextFieldHelperText,
|
|
|
|
|
MDTextFieldTrailingIcon,
|
|
|
|
|
MDTextFieldMaxLengthText,
|
|
|
|
|
)
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
from kivymd.uix.screen import MDScreen
|
|
|
|
|
from kivymd.app import MDApp
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Example(MDApp):
|
|
|
|
|
def build(self):
|
|
|
|
|
self.theme_cls.primary_palette = "Olive"
|
|
|
|
|
return MDScreen(
|
|
|
|
|
MDTextField(
|
|
|
|
|
MDTextFieldLeadingIcon(
|
|
|
|
|
icon="account",
|
|
|
|
|
),
|
|
|
|
|
MDTextFieldHintText(
|
|
|
|
|
text="Hint text",
|
|
|
|
|
),
|
|
|
|
|
MDTextFieldHelperText(
|
|
|
|
|
text="Helper text",
|
|
|
|
|
mode="persistent",
|
|
|
|
|
),
|
|
|
|
|
MDTextFieldTrailingIcon(
|
|
|
|
|
icon="information",
|
|
|
|
|
),
|
|
|
|
|
MDTextFieldMaxLengthText(
|
|
|
|
|
max_text_length=10,
|
|
|
|
|
),
|
|
|
|
|
mode="outlined",
|
|
|
|
|
size_hint_x=None,
|
|
|
|
|
width="240dp",
|
|
|
|
|
pos_hint={"center_x": 0.5, "center_y": 0.5},
|
|
|
|
|
),
|
|
|
|
|
md_bg_color=self.theme_cls.backgroundColor,
|
|
|
|
|
)
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
Example().run()
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-fields-example.png
|
|
|
|
|
:align: center
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
API break
|
|
|
|
|
=========
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
1.2.0 version
|
|
|
|
|
-------------
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
.. code-block:: kv
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
MDTextField:
|
|
|
|
|
mode: "rectangle"
|
|
|
|
|
hint_text: "Hint text"
|
|
|
|
|
helper_text: "Helper text"
|
|
|
|
|
helper_text_mode: "persistent"
|
|
|
|
|
max_text_length: 10
|
|
|
|
|
icon_right: "information"
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
2.0.0 version
|
|
|
|
|
-------------
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
.. note:: The text field with the `round` type was removed in version `2.0.0`.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
.. code-block:: kv
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
MDTextField:
|
|
|
|
|
mode: "outlined"
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
MDTextFieldLeadingIcon:
|
|
|
|
|
icon: "phone"
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
MDTextFieldTrailingIcon:
|
|
|
|
|
icon: "information"
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
MDTextFieldHintText:
|
|
|
|
|
text: "Hint text"
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
MDTextFieldHelperText:
|
|
|
|
|
text: "Helper text"
|
|
|
|
|
mode: "persistent"
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
MDTextFieldMaxLengthText:
|
|
|
|
|
max_text_length: 10
|
2024-09-15 12:12:16 +00:00
|
|
|
|
"""
|
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
|
|
|
__all__ = (
|
|
|
|
|
"BaseTextFieldIcon",
|
|
|
|
|
"BaseTextFieldLabel",
|
|
|
|
|
"Validator",
|
|
|
|
|
"AutoFormatTelephoneNumber",
|
|
|
|
|
"MDTextField",
|
|
|
|
|
"MDTextFieldHelperText",
|
|
|
|
|
"MDTextFieldMaxLengthText",
|
|
|
|
|
"MDTextFieldHintText",
|
|
|
|
|
"MDTextFieldLeadingIcon",
|
|
|
|
|
"MDTextFieldTrailingIcon",
|
|
|
|
|
)
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
|
|
|
|
import os
|
|
|
|
|
import re
|
|
|
|
|
from datetime import date
|
|
|
|
|
|
|
|
|
|
from kivy.animation import Animation
|
|
|
|
|
from kivy.clock import Clock
|
|
|
|
|
from kivy.lang import Builder
|
2024-09-15 17:57:02 +00:00
|
|
|
|
from kivy.metrics import dp
|
2024-09-15 12:12:16 +00:00
|
|
|
|
from kivy.properties import (
|
|
|
|
|
BooleanProperty,
|
|
|
|
|
ColorProperty,
|
|
|
|
|
ListProperty,
|
|
|
|
|
NumericProperty,
|
|
|
|
|
ObjectProperty,
|
|
|
|
|
OptionProperty,
|
|
|
|
|
StringProperty,
|
2024-09-15 17:57:02 +00:00
|
|
|
|
VariableListProperty,
|
2024-09-15 12:12:16 +00:00
|
|
|
|
)
|
|
|
|
|
from kivy.uix.textinput import TextInput
|
|
|
|
|
|
|
|
|
|
from kivymd import uix_path
|
|
|
|
|
from kivymd.font_definitions import theme_font_styles
|
2024-09-15 17:57:02 +00:00
|
|
|
|
from kivymd.theming import ThemableBehavior, ThemeManager
|
|
|
|
|
from kivymd.uix.behaviors import DeclarativeBehavior, BackgroundColorBehavior
|
|
|
|
|
from kivymd.uix.behaviors.state_layer_behavior import StateLayerBehavior
|
|
|
|
|
from kivymd.uix.label import MDIcon, MDLabel
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
|
|
|
|
with open(
|
|
|
|
|
os.path.join(uix_path, "textfield", "textfield.kv"), encoding="utf-8"
|
|
|
|
|
) as kv_file:
|
|
|
|
|
Builder.load_string(kv_file.read())
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# TODO: Add a class to work with the phone number mask.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class AutoFormatTelephoneNumber:
|
|
|
|
|
"""
|
|
|
|
|
Implements automatic formatting of the text entered in the text field
|
|
|
|
|
according to the mask, for example '+38 (###) ### ## ##'.
|
2024-09-15 17:57:02 +00:00
|
|
|
|
|
|
|
|
|
.. warning:: This class has not yet been implemented and it is not
|
|
|
|
|
recommended to use it yet.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
def __init__(self):
|
|
|
|
|
self._backspace = False
|
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
def isnumeric(self, value) -> bool:
|
2024-09-15 12:12:16 +00:00
|
|
|
|
try:
|
|
|
|
|
int(value)
|
|
|
|
|
return True
|
|
|
|
|
except ValueError:
|
|
|
|
|
return False
|
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
def do_backspace(self, *args) -> None:
|
|
|
|
|
"""Do backspace operation from the current cursor position."""
|
|
|
|
|
|
2024-09-15 12:12:16 +00:00
|
|
|
|
if self.validator and self.validator == "phone":
|
|
|
|
|
self._backspace = True
|
|
|
|
|
text = self.text
|
|
|
|
|
text = text[:-1]
|
|
|
|
|
self.text = text
|
|
|
|
|
self._backspace = False
|
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
def field_filter(self, value, boolean) -> None:
|
2024-09-15 12:12:16 +00:00
|
|
|
|
if self.validator and self.validator == "phone":
|
|
|
|
|
if len(self.text) == 14:
|
|
|
|
|
return
|
|
|
|
|
if self.isnumeric(value):
|
|
|
|
|
return value
|
|
|
|
|
return value
|
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
def format(self, value) -> None:
|
2024-09-15 12:12:16 +00:00
|
|
|
|
if value != "" and not value.isspace() and not self._backspace:
|
|
|
|
|
if len(value) <= 1 and self.focus:
|
|
|
|
|
self.text = value
|
|
|
|
|
self._check_cursor()
|
|
|
|
|
elif len(value) == 4:
|
|
|
|
|
start = self.text[:-1]
|
|
|
|
|
end = self.text[-1]
|
|
|
|
|
self.text = "%s) %s" % (start, end)
|
|
|
|
|
self._check_cursor()
|
|
|
|
|
elif len(value) == 8:
|
|
|
|
|
self.text += "-"
|
|
|
|
|
self._check_cursor()
|
|
|
|
|
elif len(value) in [12, 16]:
|
|
|
|
|
start = self.text[:-1]
|
|
|
|
|
end = self.text[-1]
|
|
|
|
|
self.text = "%s-%s" % (start, end)
|
|
|
|
|
self._check_cursor()
|
|
|
|
|
|
|
|
|
|
def _check_cursor(self):
|
|
|
|
|
def set_pos_cursor(pos_corsor, interval=0.5):
|
|
|
|
|
self.cursor = (pos_corsor, 0)
|
|
|
|
|
|
|
|
|
|
if self.focus:
|
|
|
|
|
Clock.schedule_once(lambda x: set_pos_cursor(len(self.text)), 0.1)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Validator:
|
|
|
|
|
"""Container class for various validation methods."""
|
|
|
|
|
|
|
|
|
|
datetime_date = ObjectProperty()
|
|
|
|
|
"""
|
|
|
|
|
The last valid date as a <class 'datetime.date'> object.
|
|
|
|
|
|
|
|
|
|
:attr:`datetime_date` is an :class:`~kivy.properties.ObjectProperty`
|
|
|
|
|
and defaults to `None`.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
date_interval = ListProperty([None, None])
|
|
|
|
|
"""
|
|
|
|
|
The date interval that is valid for input.
|
|
|
|
|
Can be entered as <class 'datetime.date'> objects or a string format.
|
|
|
|
|
Both values or just one value can be entered.
|
|
|
|
|
|
|
|
|
|
In string format, must follow the current date_format.
|
|
|
|
|
Example: Given date_format -> "mm/dd/yyyy"
|
|
|
|
|
Input examples -> "12/31/1900", "12/31/2100" or "12/31/1900", None.
|
|
|
|
|
|
|
|
|
|
:attr:`date_interval` is an :class:`~kivy.properties.ListProperty`
|
|
|
|
|
and defaults to `[None, None]`.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
date_format = OptionProperty(
|
|
|
|
|
None,
|
|
|
|
|
options=[
|
|
|
|
|
"dd/mm/yyyy",
|
|
|
|
|
"mm/dd/yyyy",
|
|
|
|
|
"yyyy/mm/dd",
|
|
|
|
|
],
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
Format of date strings that will be entered.
|
|
|
|
|
Available options are: `'dd/mm/yyyy'`, `'mm/dd/yyyy'`, `'yyyy/mm/dd'`.
|
|
|
|
|
|
|
|
|
|
:attr:`date_format` is an :class:`~kivy.properties.OptionProperty`
|
|
|
|
|
and defaults to `None`.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
def is_email_valid(self, text: str) -> bool:
|
2024-09-15 17:57:02 +00:00
|
|
|
|
"""Checks the validity of the email."""
|
|
|
|
|
|
2024-09-15 12:12:16 +00:00
|
|
|
|
if not re.match(r"[^@]+@[^@]+\.[^@]+", text):
|
|
|
|
|
return True
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
def is_time_valid(self, text: str) -> bool:
|
2024-09-15 17:57:02 +00:00
|
|
|
|
"""Checks the validity of the time."""
|
|
|
|
|
|
2024-09-15 12:12:16 +00:00
|
|
|
|
if re.match(r"^(2[0-3]|[01]?[0-9]):([0-5]?[0-9])$", text) or re.match(
|
|
|
|
|
r"^(2[0-3]|[01]?[0-9]):([0-5]?[0-9]):([0-5]?[0-9])$", text
|
|
|
|
|
):
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
def is_date_valid(self, text: str) -> bool:
|
2024-09-15 17:57:02 +00:00
|
|
|
|
"""Checks the validity of the date."""
|
|
|
|
|
|
2024-09-15 12:12:16 +00:00
|
|
|
|
if not self.date_format:
|
|
|
|
|
raise Exception("TextInput date_format was not defined.")
|
|
|
|
|
|
|
|
|
|
# Regex strings.
|
|
|
|
|
dd = "[0][1-9]|[1-2][0-9]|[3][0-1]"
|
|
|
|
|
mm = "[0][1-9]|[1][0-2]"
|
|
|
|
|
yyyy = "[0-9][0-9][0-9][0-9]"
|
|
|
|
|
fmt = self.date_format.split("/")
|
2024-09-15 17:57:02 +00:00
|
|
|
|
args = locals()
|
2024-09-15 12:12:16 +00:00
|
|
|
|
# Access the local variables dict in the correct format based on
|
|
|
|
|
# date_format split. Example: "mm/dd/yyyy" -> ["mm", "dd", "yyyy"]
|
2024-09-15 17:57:02 +00:00
|
|
|
|
# args[fmt[0]] would be args["mm"] so the month regex string.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
if re.match(
|
2024-09-15 17:57:02 +00:00
|
|
|
|
f"^({args[fmt[0]]})/({args[fmt[1]]})/({args[fmt[2]]})$", text
|
2024-09-15 12:12:16 +00:00
|
|
|
|
):
|
|
|
|
|
input_split = text.split("/")
|
2024-09-15 17:57:02 +00:00
|
|
|
|
args[fmt[0]] = input_split[0]
|
|
|
|
|
args[fmt[1]] = input_split[1]
|
|
|
|
|
args[fmt[2]] = input_split[2]
|
2024-09-15 12:12:16 +00:00
|
|
|
|
# Organize input into correct slots and try to convert
|
|
|
|
|
# to datetime object. This way February exceptions are
|
|
|
|
|
# tested. Also tests with the date_interval are simpler
|
|
|
|
|
# using datetime objects.
|
|
|
|
|
try:
|
|
|
|
|
datetime = date(
|
2024-09-15 17:57:02 +00:00
|
|
|
|
int(args["yyyy"]), int(args["mm"]), int(args["dd"])
|
2024-09-15 12:12:16 +00:00
|
|
|
|
)
|
|
|
|
|
except ValueError:
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
if self.date_interval:
|
|
|
|
|
if (
|
|
|
|
|
self.date_interval[0]
|
|
|
|
|
and not self.date_interval[0] <= datetime
|
|
|
|
|
or self.date_interval[1]
|
|
|
|
|
and not datetime <= self.date_interval[1]
|
|
|
|
|
):
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
self.datetime_date = datetime
|
|
|
|
|
return False
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
def on_date_interval(self, *args) -> None:
|
|
|
|
|
"""Default event handler for date_interval input."""
|
|
|
|
|
|
|
|
|
|
def on_date_interval():
|
|
|
|
|
if not self.date_format:
|
|
|
|
|
raise Exception("TextInput date_format was not defined.")
|
|
|
|
|
|
|
|
|
|
fmt = self.date_format.split("/")
|
2024-09-15 17:57:02 +00:00
|
|
|
|
args = {}
|
2024-09-15 12:12:16 +00:00
|
|
|
|
# Convert string inputs into datetime.date objects and store
|
|
|
|
|
# them back into self.date_interval.
|
|
|
|
|
try:
|
|
|
|
|
if self.date_interval[0] and not isinstance(
|
|
|
|
|
self.date_interval[0], date
|
|
|
|
|
):
|
|
|
|
|
split = self.date_interval[0].split("/")
|
2024-09-15 17:57:02 +00:00
|
|
|
|
args[fmt[0]] = split[0]
|
|
|
|
|
args[fmt[1]] = split[1]
|
|
|
|
|
args[fmt[2]] = split[2]
|
2024-09-15 12:12:16 +00:00
|
|
|
|
self.date_interval[0] = date(
|
2024-09-15 17:57:02 +00:00
|
|
|
|
int(args["yyyy"]), int(args["mm"]), int(args["dd"])
|
2024-09-15 12:12:16 +00:00
|
|
|
|
)
|
|
|
|
|
if self.date_interval[1] and not isinstance(
|
|
|
|
|
self.date_interval[1], date
|
|
|
|
|
):
|
|
|
|
|
split = self.date_interval[1].split("/")
|
2024-09-15 17:57:02 +00:00
|
|
|
|
args[fmt[0]] = split[0]
|
|
|
|
|
args[fmt[1]] = split[1]
|
|
|
|
|
args[fmt[2]] = split[2]
|
2024-09-15 12:12:16 +00:00
|
|
|
|
self.date_interval[1] = date(
|
2024-09-15 17:57:02 +00:00
|
|
|
|
int(args["yyyy"]), int(args["mm"]), int(args["dd"])
|
2024-09-15 12:12:16 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
except Exception:
|
|
|
|
|
raise Exception(
|
2024-09-15 17:57:02 +00:00
|
|
|
|
r"TextInput date_interval was defined incorrectly, "
|
|
|
|
|
r"it must be composed of <class 'datetime.date'> objects "
|
|
|
|
|
r"or strings following current date_format."
|
2024-09-15 12:12:16 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
# Test if the interval is valid.
|
|
|
|
|
if isinstance(self.date_interval[0], date) and isinstance(
|
|
|
|
|
self.date_interval[1], date
|
|
|
|
|
):
|
|
|
|
|
if self.date_interval[0] >= self.date_interval[1]:
|
|
|
|
|
raise Exception(
|
2024-09-15 17:57:02 +00:00
|
|
|
|
"TextInput date_interval last date must be greater "
|
|
|
|
|
"than the first date or set to None."
|
2024-09-15 12:12:16 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
Clock.schedule_once(lambda x: on_date_interval())
|
|
|
|
|
|
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
class BaseTextFieldLabel(MDLabel):
|
2024-09-15 12:12:16 +00:00
|
|
|
|
"""
|
2024-09-15 17:57:02 +00:00
|
|
|
|
Base texture for :class:`~MDTextField` class (helper text, max length,
|
|
|
|
|
hint text).
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
|
|
|
|
For more information, see in the
|
2024-09-15 17:57:02 +00:00
|
|
|
|
:class:`~kivymd.uix.label.label.MDLabel` class documentation.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
.. versionadded:: 2.0.0
|
2024-09-15 12:12:16 +00:00
|
|
|
|
"""
|
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
text_color_normal = ColorProperty(None)
|
2024-09-15 12:12:16 +00:00
|
|
|
|
"""
|
2024-09-15 17:57:02 +00:00
|
|
|
|
Text color in (r, g, b, a) or string format when text field is out
|
|
|
|
|
of focus.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
.. versionadded:: 1.0.0
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
.. versionchanged:: 2.0.0
|
|
|
|
|
The property was moved from class:`~MDTextField` class and renamed
|
|
|
|
|
from `helper_text_color_normal` to `text_color_normal`.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
.. code-block:: kv
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
MDTextField:
|
|
|
|
|
mode: "filled"
|
|
|
|
|
|
|
|
|
|
MDTextFieldHintText:
|
|
|
|
|
text: "Hint text color normal"
|
|
|
|
|
text_color_normal: "brown"
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-fields-text-color-normal.png
|
|
|
|
|
:align: center
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
:attr:`text_color_normal` is an :class:`~kivy.properties.ColorProperty`
|
|
|
|
|
and defaults to `None`.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
"""
|
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
text_color_focus = ColorProperty(None)
|
|
|
|
|
"""
|
|
|
|
|
Text color in (r, g, b, a) or string format when the text field has
|
|
|
|
|
focus.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
.. versionadded:: 1.0.0
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
.. versionchanged:: 2.0.0
|
|
|
|
|
The property was moved from class:`~MDTextField` class and renamed
|
|
|
|
|
from `helper_text_color_focus` to `text_color_focus`.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
.. code-block:: kv
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
MDTextField:
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
MDTextFieldHelperText:
|
|
|
|
|
text: "Helper text color focus"
|
|
|
|
|
text_color_focus: "brown"
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-fields-text-color-focus.png
|
|
|
|
|
:align: center
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
:attr:`text_color_focus` is an :class:`~kivy.properties.ColorProperty`
|
|
|
|
|
and defaults to `None`.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
class MDTextFieldHelperText(BaseTextFieldLabel):
|
2024-09-15 12:12:16 +00:00
|
|
|
|
"""
|
2024-09-15 17:57:02 +00:00
|
|
|
|
Implements the helper text label.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
For more information, see in the :class:`~BaseTextFieldLabel`
|
|
|
|
|
class documentation.
|
|
|
|
|
|
|
|
|
|
.. versionadded:: 2.0.0
|
2024-09-15 12:12:16 +00:00
|
|
|
|
"""
|
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
mode = OptionProperty(
|
2024-09-15 12:12:16 +00:00
|
|
|
|
"on_focus", options=["on_error", "persistent", "on_focus"]
|
|
|
|
|
)
|
|
|
|
|
"""
|
|
|
|
|
Helper text mode. Available options are: `'on_error'`, `'persistent'`,
|
|
|
|
|
`'on_focus'`.
|
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
.. versionchanged:: 2.0.0
|
|
|
|
|
The property was moved from class:`~MDTextField` class and renamed
|
|
|
|
|
from `helper_text_mode` to `mode`.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
On focus
|
|
|
|
|
--------
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
.. code-block:: kv
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
|
|
|
|
MDTextField:
|
2024-09-15 17:57:02 +00:00
|
|
|
|
mode: "filled"
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
MDTextFieldHelperText:
|
|
|
|
|
text: "Helper text"
|
|
|
|
|
mode: "on_focus"
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-fields-helper-text-mode-on-focus.gif
|
2024-09-15 12:12:16 +00:00
|
|
|
|
:align: center
|
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
On error
|
|
|
|
|
--------
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
|
|
|
|
.. code-block:: kv
|
|
|
|
|
|
|
|
|
|
MDTextField:
|
2024-09-15 17:57:02 +00:00
|
|
|
|
mode: "filled"
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
MDTextFieldHelperText:
|
|
|
|
|
text: "Helper text"
|
|
|
|
|
mode: "on_error"
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
MDTextFieldMaxLengthText:
|
|
|
|
|
max_text_length: 5
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-fields-helper-text-mode-on-error.gif
|
|
|
|
|
:align: center
|
|
|
|
|
|
|
|
|
|
Persistent
|
|
|
|
|
----------
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
|
|
|
|
.. code-block:: kv
|
|
|
|
|
|
|
|
|
|
MDTextField:
|
2024-09-15 17:57:02 +00:00
|
|
|
|
mode: "filled"
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
MDTextFieldHelperText:
|
|
|
|
|
text: "Helper text"
|
|
|
|
|
mode: "persistent"
|
|
|
|
|
|
|
|
|
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-fields-helper-text-mode-persistent.gif
|
2024-09-15 12:12:16 +00:00
|
|
|
|
:align: center
|
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
:attr:`mode` is an :class:`~kivy.properties.OptionProperty`
|
|
|
|
|
and defaults to `'on_focus'`.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
class MDTextFieldMaxLengthText(BaseTextFieldLabel):
|
2024-09-15 12:12:16 +00:00
|
|
|
|
"""
|
2024-09-15 17:57:02 +00:00
|
|
|
|
Implements the max length text label.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
For more information, see in the :class:`~BaseTextFieldLabel`
|
|
|
|
|
class documentation.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
.. versionadded:: 2.0.0
|
2024-09-15 12:12:16 +00:00
|
|
|
|
"""
|
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
max_text_length = NumericProperty(None)
|
2024-09-15 12:12:16 +00:00
|
|
|
|
"""
|
2024-09-15 17:57:02 +00:00
|
|
|
|
Maximum allowed value of characters in a text field.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
.. versionchanged:: 2.0.0
|
|
|
|
|
The property was moved from class:`~MDTextField`.
|
|
|
|
|
|
|
|
|
|
.. code-block:: kv
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
|
|
|
|
MDTextField:
|
2024-09-15 17:57:02 +00:00
|
|
|
|
mode: "filled"
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
MDTextFieldMaxLengthText:
|
|
|
|
|
max_text_length: 10
|
|
|
|
|
|
|
|
|
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-fields-max-text-length.png
|
2024-09-15 12:12:16 +00:00
|
|
|
|
:align: center
|
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
:attr:`max_text_length` is an :class:`~kivy.properties.NumericProperty`
|
|
|
|
|
and defaults to `None`.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
"""
|
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
|
|
|
|
|
class MDTextFieldHintText(BaseTextFieldLabel):
|
2024-09-15 12:12:16 +00:00
|
|
|
|
"""
|
2024-09-15 17:57:02 +00:00
|
|
|
|
Implements the hint text label.
|
|
|
|
|
|
|
|
|
|
For more information, see in the :class:`~BaseTextFieldLabel`
|
|
|
|
|
class documentation.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
.. versionadded:: 2.0.0
|
|
|
|
|
|
|
|
|
|
.. code-block:: kv
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
|
|
|
|
MDTextField:
|
2024-09-15 17:57:02 +00:00
|
|
|
|
mode: "filled"
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
MDTextFieldHintText:
|
|
|
|
|
text: "Hint text"
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-fields-hint-text.gif
|
|
|
|
|
:align: center
|
2024-09-15 12:12:16 +00:00
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
class BaseTextFieldIcon(MDIcon):
|
2024-09-15 12:12:16 +00:00
|
|
|
|
"""
|
2024-09-15 17:57:02 +00:00
|
|
|
|
Base texture for :class:`~MDTextField` class (helper text, max length,
|
|
|
|
|
hint text).
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
For more information, see in the :class:`~kivymd.uix.label.label.MDIcon`
|
|
|
|
|
class documentation.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
.. versionchanged:: 2.0.0
|
2024-09-15 12:12:16 +00:00
|
|
|
|
"""
|
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
icon_color_normal = ColorProperty(None)
|
2024-09-15 12:12:16 +00:00
|
|
|
|
"""
|
2024-09-15 17:57:02 +00:00
|
|
|
|
Icon color in (r, g, b, a) or string format when text field is out
|
2024-09-15 12:12:16 +00:00
|
|
|
|
of focus.
|
|
|
|
|
|
|
|
|
|
.. versionadded:: 1.0.0
|
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
.. versionchanged:: 2.0.0
|
|
|
|
|
The property was moved from class:`~MDTextField` class and renamed
|
|
|
|
|
from `icon_right_color_normal/icon_left_color_normal`
|
|
|
|
|
to `icon_color_normal`.
|
|
|
|
|
|
2024-09-15 12:12:16 +00:00
|
|
|
|
.. code-block:: kv
|
|
|
|
|
|
|
|
|
|
MDTextField:
|
2024-09-15 17:57:02 +00:00
|
|
|
|
mode: "filled"
|
|
|
|
|
|
|
|
|
|
MDTextFieldLeadingIcon:
|
|
|
|
|
icon: "phone"
|
|
|
|
|
theme_icon_color: "Custom"
|
|
|
|
|
icon_color_normal: "lightgreen"
|
|
|
|
|
|
|
|
|
|
MDTextFieldHintText:
|
|
|
|
|
text: "Leading icon color normal"
|
|
|
|
|
|
|
|
|
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-fields-leading-icon-color-normal.png
|
2024-09-15 12:12:16 +00:00
|
|
|
|
:align: center
|
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
:attr:`icon_color_normal` is an :class:`~kivy.properties.ColorProperty`
|
|
|
|
|
and defaults to `None`.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
"""
|
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
icon_color_focus = ColorProperty(None)
|
2024-09-15 12:12:16 +00:00
|
|
|
|
"""
|
2024-09-15 17:57:02 +00:00
|
|
|
|
Icon color in (r, g, b, a) or string format when the text field has
|
2024-09-15 12:12:16 +00:00
|
|
|
|
focus.
|
|
|
|
|
|
|
|
|
|
.. versionadded:: 1.0.0
|
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
.. versionchanged:: 2.0.0
|
|
|
|
|
The property was moved from class:`~MDTextField` class and renamed
|
|
|
|
|
from `icon_right_color_focus/icon_left_color_focus `
|
|
|
|
|
to `icon_color_focus`.
|
|
|
|
|
|
2024-09-15 12:12:16 +00:00
|
|
|
|
.. code-block:: kv
|
|
|
|
|
|
|
|
|
|
MDTextField:
|
2024-09-15 17:57:02 +00:00
|
|
|
|
mode: "filled"
|
|
|
|
|
|
|
|
|
|
MDTextFieldLeadingIcon:
|
|
|
|
|
icon: "phone"
|
|
|
|
|
theme_icon_color: "Custom"
|
|
|
|
|
icon_color_focus: "lightgreen"
|
|
|
|
|
|
|
|
|
|
MDTextFieldHintText:
|
|
|
|
|
text: "Leading icon color focus"
|
|
|
|
|
|
|
|
|
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-fields-leading-icon-color-focus.png
|
2024-09-15 12:12:16 +00:00
|
|
|
|
:align: center
|
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
:attr:`icon_color_focus` is an :class:`~kivy.properties.ColorProperty`
|
|
|
|
|
and defaults to `None`.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
"""
|
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
|
|
|
|
|
class MDTextFieldLeadingIcon(BaseTextFieldIcon):
|
2024-09-15 12:12:16 +00:00
|
|
|
|
"""
|
2024-09-15 17:57:02 +00:00
|
|
|
|
Implements the leading icon.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
For more information, see in the :class:`~BaseTextFieldIcon`
|
|
|
|
|
class documentation.
|
|
|
|
|
|
|
|
|
|
.. versionadded:: 2.0.0
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
|
|
|
|
.. code-block:: kv
|
|
|
|
|
|
|
|
|
|
MDTextField:
|
2024-09-15 17:57:02 +00:00
|
|
|
|
mode: "filled"
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
MDTextFieldLeadingIcon:
|
|
|
|
|
icon: "phone"
|
|
|
|
|
|
|
|
|
|
MDTextFieldHintText:
|
|
|
|
|
text: "Field with leading icon"
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-fields-leading-icon.png
|
|
|
|
|
:align: center
|
2024-09-15 12:12:16 +00:00
|
|
|
|
"""
|
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
|
|
|
|
|
class MDTextFieldTrailingIcon(BaseTextFieldIcon):
|
2024-09-15 12:12:16 +00:00
|
|
|
|
"""
|
2024-09-15 17:57:02 +00:00
|
|
|
|
Implements the trailing icon.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
For more information, see in the :class:`~BaseTextFieldIcon`
|
|
|
|
|
class documentation.
|
|
|
|
|
|
|
|
|
|
.. versionadded:: 2.0.0
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
|
|
|
|
.. code-block:: kv
|
|
|
|
|
|
|
|
|
|
MDTextField:
|
2024-09-15 17:57:02 +00:00
|
|
|
|
mode: "filled"
|
|
|
|
|
|
|
|
|
|
MDTextFieldTrailingIcon:
|
|
|
|
|
icon: "phone"
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
MDTextFieldHintText:
|
|
|
|
|
text: "Field with trailing icon"
|
|
|
|
|
|
|
|
|
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-fields-trailing-icon.png
|
2024-09-15 12:12:16 +00:00
|
|
|
|
:align: center
|
2024-09-15 17:57:02 +00:00
|
|
|
|
"""
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
|
|
|
|
|
# TODO: Add a custom color for the disabled state of the text field.
|
|
|
|
|
class MDTextField(
|
|
|
|
|
DeclarativeBehavior,
|
|
|
|
|
StateLayerBehavior,
|
|
|
|
|
ThemableBehavior,
|
|
|
|
|
TextInput,
|
|
|
|
|
Validator,
|
|
|
|
|
AutoFormatTelephoneNumber,
|
|
|
|
|
BackgroundColorBehavior,
|
|
|
|
|
):
|
2024-09-15 12:12:16 +00:00
|
|
|
|
"""
|
2024-09-15 17:57:02 +00:00
|
|
|
|
Textfield class.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
For more information, see in the
|
|
|
|
|
:class:`~kivymd.uix.behaviors.declarative_behavior.DeclarativeBehavior` and
|
|
|
|
|
:class:`~kivymd.uix.behaviors.backgroundcolor_behavior.BackgroundColorBehavior` and
|
|
|
|
|
:class:`~kivymd.theming.ThemableBehavior` and
|
|
|
|
|
:class:`~kivy.uix.textinput.TextInput` and
|
|
|
|
|
:class:`~Validator` and
|
|
|
|
|
:class:`~AutoFormatTelephoneNumber` and
|
|
|
|
|
:class:`~kivymd.uix.behaviors.state_layer_behavior.StateLayerBehavior`
|
|
|
|
|
classes documentation.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
"""
|
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
font_style = StringProperty("Body")
|
|
|
|
|
"""
|
|
|
|
|
Name of the style for the input text.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
.. versionadded:: 2.0.0
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
.. seealso::
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
`Font style names <https://kivymd.readthedocs.io/en/latest/components/label/#all-styles>`_
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
:attr:`font_style` is an :class:`~kivy.properties.StringProperty`
|
|
|
|
|
and defaults to `'Body'`.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
"""
|
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
role = StringProperty("large")
|
2024-09-15 12:12:16 +00:00
|
|
|
|
"""
|
2024-09-15 17:57:02 +00:00
|
|
|
|
Role of font style.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
.. versionadded:: 2.0.0
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
.. seealso::
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
`Font style roles <https://kivymd.readthedocs.io/en/latest/components/label/#all-styles>`_
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
:attr:`role` is an :class:`~kivy.properties.StringProperty`
|
|
|
|
|
and defaults to `'large'`.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
"""
|
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
mode = OptionProperty("outlined", options=["outlined", "filled"])
|
2024-09-15 12:12:16 +00:00
|
|
|
|
"""
|
2024-09-15 17:57:02 +00:00
|
|
|
|
Text field mode. Available options are: `'outlined'`, `'filled'`.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
:attr:`mode` is an :class:`~kivy.properties.OptionProperty`
|
|
|
|
|
and defaults to `'outlined'`.
|
|
|
|
|
"""
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
error_color = ColorProperty(None)
|
2024-09-15 12:12:16 +00:00
|
|
|
|
"""
|
2024-09-15 17:57:02 +00:00
|
|
|
|
Error color in (r, g, b, a) or string format for `required = True`
|
|
|
|
|
or when the text field is in `error` state.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
:attr:`error_color` is an :class:`~kivy.properties.ColorProperty`
|
|
|
|
|
and defaults to `None`.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
"""
|
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
error = BooleanProperty(False)
|
|
|
|
|
"""
|
|
|
|
|
If True, then the text field goes into `error` mode.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
:attr:`error` is an :class:`~kivy.properties.BooleanProperty`
|
|
|
|
|
and defaults to `False`.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
"""
|
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
text_color_normal = ColorProperty(None)
|
2024-09-15 12:12:16 +00:00
|
|
|
|
"""
|
2024-09-15 17:57:02 +00:00
|
|
|
|
Text color in (r, g, b, a) or string format when text field is out of focus.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
|
|
|
|
.. versionadded:: 1.0.0
|
|
|
|
|
|
|
|
|
|
.. code-block:: kv
|
|
|
|
|
|
|
|
|
|
MDTextField:
|
2024-09-15 17:57:02 +00:00
|
|
|
|
theme_text_color: "Custom"
|
|
|
|
|
text_color_normal: "green"
|
|
|
|
|
text: "Text color normal"
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-field-text-color-normal.png
|
2024-09-15 12:12:16 +00:00
|
|
|
|
:align: center
|
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
:attr:`text_color_normal` is an :class:`~kivy.properties.ColorProperty`
|
|
|
|
|
and defaults to `None`.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
"""
|
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
text_color_focus = ColorProperty(None)
|
2024-09-15 12:12:16 +00:00
|
|
|
|
"""
|
2024-09-15 17:57:02 +00:00
|
|
|
|
Text color in (r, g, b, a) or string format when text field has focus.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
.. versionadded:: 1.0.0
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
.. code-block:: kv
|
|
|
|
|
|
|
|
|
|
MDTextField:
|
|
|
|
|
theme_text_color: "Custom"
|
|
|
|
|
text_color_focus: "green"
|
|
|
|
|
text: "Text color focus"
|
|
|
|
|
|
|
|
|
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-field-text-color-focus.png
|
|
|
|
|
:align: center
|
|
|
|
|
|
|
|
|
|
:attr:`text_color_focus` is an :class:`~kivy.properties.ColorProperty`
|
|
|
|
|
and defaults to `None`.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
"""
|
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
radius = VariableListProperty([dp(4), dp(4), dp(4), dp(4)])
|
2024-09-15 12:12:16 +00:00
|
|
|
|
"""
|
2024-09-15 17:57:02 +00:00
|
|
|
|
The corner radius for a text field in `filled/outlined` mode.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
:attr:`radius` is a :class:`~kivy.properties.VariableListProperty` and
|
|
|
|
|
defaults to `[dp(4), dp(4), 0, 0]`.
|
|
|
|
|
"""
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
required = BooleanProperty(False)
|
|
|
|
|
"""
|
|
|
|
|
Required text. If True then the text field requires text.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
:attr:`required` is an :class:`~kivy.properties.BooleanProperty`
|
|
|
|
|
and defaults to `False`.
|
|
|
|
|
"""
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
line_color_normal = ColorProperty(None)
|
2024-09-15 12:12:16 +00:00
|
|
|
|
"""
|
2024-09-15 17:57:02 +00:00
|
|
|
|
Line color normal (active indicator) in (r, g, b, a) or string format.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
.. code-block:: kv
|
|
|
|
|
|
|
|
|
|
MDTextField:
|
|
|
|
|
mode: "filled"
|
|
|
|
|
theme_line_color: "Custom"
|
|
|
|
|
line_color_normal: "green"
|
|
|
|
|
|
|
|
|
|
MDTextFieldHelperText:
|
|
|
|
|
text: "Line color normal"
|
|
|
|
|
mode: "persistent"
|
|
|
|
|
|
|
|
|
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-fields-line-color-normal.png
|
|
|
|
|
:align: center
|
|
|
|
|
|
|
|
|
|
:attr:`line_color_normal` is an :class:`~kivy.properties.ColorProperty`
|
|
|
|
|
and defaults to `None`.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
"""
|
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
line_color_focus = ColorProperty(None)
|
|
|
|
|
"""
|
|
|
|
|
Line color focus (active indicator) in (r, g, b, a) or string format.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
|
|
|
|
.. code-block:: kv
|
|
|
|
|
|
|
|
|
|
MDTextField:
|
2024-09-15 17:57:02 +00:00
|
|
|
|
mode: "filled"
|
|
|
|
|
theme_line_color: "Custom"
|
|
|
|
|
line_color_focus: "green"
|
|
|
|
|
|
|
|
|
|
MDTextFieldHelperText:
|
|
|
|
|
text: "Line color focus"
|
|
|
|
|
mode: "persistent"
|
|
|
|
|
|
|
|
|
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-fields-line-color-focus.png
|
2024-09-15 12:12:16 +00:00
|
|
|
|
:align: center
|
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
:attr:`line_color_focus` is an :class:`~kivy.properties.ColorProperty`
|
|
|
|
|
and defaults to `None`.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
"""
|
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
fill_color_normal = ColorProperty(None)
|
2024-09-15 12:12:16 +00:00
|
|
|
|
"""
|
2024-09-15 17:57:02 +00:00
|
|
|
|
Fill background color in (r, g, b, a) or string format in 'fill' mode when]
|
|
|
|
|
text field is out of focus.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
|
|
|
|
.. code-block:: kv
|
|
|
|
|
|
|
|
|
|
MDTextField:
|
2024-09-15 17:57:02 +00:00
|
|
|
|
mode: "filled"
|
|
|
|
|
theme_bg_color: "Custom"
|
|
|
|
|
fill_color_normal: 0, 1, 0, .2
|
|
|
|
|
|
|
|
|
|
MDTextFieldHelperText:
|
|
|
|
|
text: "Fill color normal"
|
|
|
|
|
mode: "persistent"
|
|
|
|
|
|
|
|
|
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-fields-fill-color-normal.png
|
2024-09-15 12:12:16 +00:00
|
|
|
|
:align: center
|
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
:attr:`fill_color_normal` is an :class:`~kivy.properties.ColorProperty`
|
|
|
|
|
and defaults to `None`.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
"""
|
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
fill_color_focus = ColorProperty(None)
|
2024-09-15 12:12:16 +00:00
|
|
|
|
"""
|
2024-09-15 17:57:02 +00:00
|
|
|
|
Fill background color in (r, g, b, a) or string format in 'fill' mode when
|
|
|
|
|
the text field has focus.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
.. code-block:: kv
|
|
|
|
|
|
|
|
|
|
MDTextField:
|
|
|
|
|
mode: "filled"
|
|
|
|
|
theme_bg_color: "Custom"
|
|
|
|
|
fill_color_focus: 0, 1, 0, .2
|
|
|
|
|
|
|
|
|
|
MDTextFieldHelperText:
|
|
|
|
|
text: "Fill color focus"
|
|
|
|
|
mode: "persistent"
|
|
|
|
|
|
|
|
|
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-fields-fill-color-focus.png
|
|
|
|
|
:align: center
|
|
|
|
|
|
|
|
|
|
:attr:`fill_color_focus` is an :class:`~kivy.properties.ColorProperty`
|
|
|
|
|
and defaults to `None`.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
# TODO: Add minimum allowed height. Otherwise, if the value is,
|
|
|
|
|
# for example, 20, the text field will simply be lessened.
|
|
|
|
|
max_height = NumericProperty(0)
|
|
|
|
|
"""
|
|
|
|
|
Maximum height of the text box when `multiline = True`.
|
|
|
|
|
|
|
|
|
|
.. code-block:: kv
|
|
|
|
|
|
|
|
|
|
MDTextField:
|
2024-09-15 17:57:02 +00:00
|
|
|
|
mode: "filled"
|
2024-09-15 12:12:16 +00:00
|
|
|
|
max_height: "200dp"
|
|
|
|
|
multiline: True
|
2024-09-15 17:57:02 +00:00
|
|
|
|
|
|
|
|
|
MDTextFieldHelperText:
|
|
|
|
|
text: "multiline=True"
|
|
|
|
|
mode: "persistent"
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-fields-multiline.gif
|
2024-09-15 12:12:16 +00:00
|
|
|
|
:align: center
|
|
|
|
|
|
|
|
|
|
:attr:`max_height` is a :class:`~kivy.properties.NumericProperty` and
|
|
|
|
|
defaults to `0`.
|
|
|
|
|
"""
|
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
phone_mask = StringProperty("")
|
2024-09-15 12:12:16 +00:00
|
|
|
|
"""
|
2024-09-15 17:57:02 +00:00
|
|
|
|
This property has not yet been implemented and it is not recommended to
|
|
|
|
|
use it yet.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
:attr:`phone_mask` is a :class:`~kivy.properties.StringProperty` and
|
|
|
|
|
defaults to ''.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
"""
|
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
validator = OptionProperty(None, options=["date", "email", "time", "phone"])
|
2024-09-15 12:12:16 +00:00
|
|
|
|
"""
|
2024-09-15 17:57:02 +00:00
|
|
|
|
The type of text field for entering Email, time, etc.
|
|
|
|
|
Automatically sets the type of the text field as "error" if the user input
|
|
|
|
|
does not match any of the set validation types.
|
|
|
|
|
Available options are: `'date'`, `'email'`, `'time'`.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
When using `'date'`, :attr:`date_format` must be defined.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
.. versionadded:: 1.1.0
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
.. code-block:: kv
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
MDTextField:
|
|
|
|
|
mode: "filled"
|
|
|
|
|
validator: "email"
|
|
|
|
|
|
|
|
|
|
MDTextFieldHintText:
|
|
|
|
|
text: "Email"
|
|
|
|
|
|
|
|
|
|
MDTextFieldHelperText:
|
|
|
|
|
text: "user@gmail.com"
|
|
|
|
|
mode: "persistent"
|
|
|
|
|
|
|
|
|
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-fields-email-validator.png
|
|
|
|
|
:align: center
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
.. code-block:: python
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
from kivy.lang import Builder
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
from kivymd.app import MDApp
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
KV = '''
|
|
|
|
|
MDScreen:
|
|
|
|
|
md_bg_color: self.theme_cls.backgroundColor
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
MDBoxLayout:
|
|
|
|
|
orientation: "vertical"
|
|
|
|
|
spacing: "20dp"
|
|
|
|
|
adaptive_height: True
|
|
|
|
|
size_hint_x: .8
|
|
|
|
|
pos_hint: {"center_x": .5, "center_y": .5}
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
MDTextField:
|
|
|
|
|
validator: "date"
|
|
|
|
|
date_format: "dd/mm/yyyy"
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
MDTextFieldHintText:
|
|
|
|
|
text: "Date dd/mm/yyyy without limits"
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
MDTextFieldHelperText:
|
|
|
|
|
text: "Enter a valid dd/mm/yyyy date"
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
MDTextField:
|
|
|
|
|
validator: "date"
|
|
|
|
|
date_format: "mm/dd/yyyy"
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
MDTextFieldHintText:
|
|
|
|
|
text: "Date mm/dd/yyyy without limits"
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
MDTextFieldHelperText:
|
|
|
|
|
text: "Enter a valid mm/dd/yyyy date"
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
MDTextField:
|
|
|
|
|
validator: "date"
|
|
|
|
|
date_format: "yyyy/mm/dd"
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
MDTextFieldHintText:
|
|
|
|
|
text: "Date yyyy/mm/dd without limits"
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
MDTextFieldHelperText:
|
|
|
|
|
text: "Enter a valid yyyy/mm/dd date"
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
MDTextField:
|
|
|
|
|
validator: "date"
|
|
|
|
|
date_format: "dd/mm/yyyy"
|
|
|
|
|
date_interval: "01/01/1900", "01/01/2100"
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
MDTextFieldHintText:
|
|
|
|
|
text: "Date dd/mm/yyyy in [01/01/1900, 01/01/2100] interval"
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
MDTextFieldHelperText:
|
|
|
|
|
text: "Enter a valid dd/mm/yyyy date"
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
MDTextField:
|
|
|
|
|
validator: "date"
|
|
|
|
|
date_format: "dd/mm/yyyy"
|
|
|
|
|
date_interval: "01/01/1900", None
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
MDTextFieldHintText:
|
|
|
|
|
text: "Date dd/mm/yyyy in [01/01/1900, None] interval"
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
MDTextFieldHelperText:
|
|
|
|
|
text: "Enter a valid dd/mm/yyyy date"
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
MDTextField:
|
|
|
|
|
validator: "date"
|
|
|
|
|
date_format: "dd/mm/yyyy"
|
|
|
|
|
date_interval: None, "01/01/2100"
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
MDTextFieldHintText:
|
|
|
|
|
text: "Date dd/mm/yyyy in [None, 01/01/2100] interval"
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
MDTextFieldHelperText:
|
|
|
|
|
text: "Enter a valid dd/mm/yyyy date"
|
|
|
|
|
'''
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
class Example(MDApp):
|
|
|
|
|
def build(self):
|
|
|
|
|
self.theme_cls.primary_palette = "Olive"
|
|
|
|
|
return Builder.load_string(KV)
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
Example().run()
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/text-fields-validator-date.png
|
|
|
|
|
:align: center
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
:attr:`validator` is an :class:`~kivy.properties.OptionProperty`
|
|
|
|
|
and defaults to `None`.
|
|
|
|
|
"""
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
# Helper text label object.
|
|
|
|
|
_helper_text_label = ObjectProperty()
|
|
|
|
|
# Hint text label object.
|
|
|
|
|
_hint_text_label = ObjectProperty()
|
|
|
|
|
# Leading icon object.
|
|
|
|
|
_leading_icon = ObjectProperty()
|
|
|
|
|
# Trailing icon object.
|
|
|
|
|
_trailing_icon = ObjectProperty()
|
|
|
|
|
# Max length label object.
|
|
|
|
|
_max_length_label = ObjectProperty()
|
|
|
|
|
# Maximum length of characters to be input.
|
|
|
|
|
_max_length = "0"
|
|
|
|
|
# Active indicator height.
|
|
|
|
|
_indicator_height = NumericProperty(dp(1))
|
|
|
|
|
# Outline height.
|
|
|
|
|
_outline_height = NumericProperty(dp(1))
|
|
|
|
|
# The x-axis position of the hint text in the text field.
|
|
|
|
|
_hint_x = NumericProperty(0)
|
|
|
|
|
# The y-axis position of the hint text in the text field.
|
|
|
|
|
_hint_y = NumericProperty(0)
|
|
|
|
|
# The right/left lines coordinates of the text field in 'outlined' mode.
|
|
|
|
|
_left_x_axis_pos = NumericProperty(dp(32))
|
|
|
|
|
_right_x_axis_pos = NumericProperty(dp(32))
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
|
|
|
super().__init__(*args, **kwargs)
|
|
|
|
|
self.bind(text=self.set_text)
|
|
|
|
|
self.theme_cls.bind(
|
|
|
|
|
primary_palette=self.update_colors,
|
|
|
|
|
theme_style=self.update_colors,
|
2024-09-15 12:12:16 +00:00
|
|
|
|
)
|
2024-09-15 17:57:02 +00:00
|
|
|
|
Clock.schedule_once(self._check_text)
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
def update_colors(
|
|
|
|
|
self, theme_manager: ThemeManager, theme_color: str
|
|
|
|
|
) -> None:
|
|
|
|
|
"""Fired when the `primary_palette` or `theme_style` value changes."""
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
def update_colors(*args):
|
|
|
|
|
if not self.disabled:
|
|
|
|
|
self.on_focus(self, self.focus)
|
|
|
|
|
else:
|
|
|
|
|
self.on_disabled(self, self.disabled)
|
|
|
|
|
|
|
|
|
|
Clock.schedule_once(update_colors, 1)
|
|
|
|
|
|
|
|
|
|
def add_widget(self, widget, index=0, canvas=None):
|
|
|
|
|
if isinstance(widget, MDTextFieldHelperText):
|
|
|
|
|
self._helper_text_label = widget
|
|
|
|
|
if isinstance(widget, MDTextFieldHintText):
|
|
|
|
|
self._hint_text_label = widget
|
|
|
|
|
if isinstance(widget, MDTextFieldLeadingIcon):
|
|
|
|
|
self._leading_icon = widget
|
|
|
|
|
if isinstance(widget, MDTextFieldTrailingIcon):
|
|
|
|
|
self._trailing_icon = widget
|
|
|
|
|
if isinstance(widget, MDTextFieldMaxLengthText):
|
|
|
|
|
self._max_length_label = widget
|
|
|
|
|
else:
|
|
|
|
|
return super().add_widget(widget)
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
def set_texture_color(
|
|
|
|
|
self, texture, canvas_group, color: list, error: bool = False
|
|
|
|
|
) -> None:
|
|
|
|
|
"""
|
|
|
|
|
Animates the color of the
|
|
|
|
|
leading/trailing icons/hint/helper/max length text.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
def update_hint_text_rectangle(*args):
|
|
|
|
|
hint_text_rectangle = self.canvas.after.get_group(
|
|
|
|
|
"hint-text-rectangle"
|
|
|
|
|
)[0]
|
|
|
|
|
hint_text_rectangle.texture = None
|
|
|
|
|
texture.texture_update()
|
|
|
|
|
hint_text_rectangle.texture = texture.texture
|
|
|
|
|
|
|
|
|
|
if texture:
|
|
|
|
|
Animation(rgba=color, d=0).start(canvas_group)
|
|
|
|
|
a = Animation(color=color, d=0)
|
|
|
|
|
if texture is self._hint_text_label:
|
|
|
|
|
a.bind(on_complete=update_hint_text_rectangle)
|
|
|
|
|
a.start(texture)
|
|
|
|
|
|
|
|
|
|
def set_pos_hint_text(self, y: float, x: float) -> None:
|
2024-09-15 12:12:16 +00:00
|
|
|
|
"""Animates the x-axis width and y-axis height of the hint text."""
|
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
Animation(_hint_y=y, _hint_x=x, d=0.2, t="out_quad").start(self)
|
|
|
|
|
|
|
|
|
|
def set_hint_text_font_size(self) -> None:
|
2024-09-15 12:12:16 +00:00
|
|
|
|
"""Animates the font size of the hint text."""
|
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
Animation(
|
|
|
|
|
size=self._hint_text_label.texture_size, d=0.2, t="out_quad"
|
|
|
|
|
).start(self.canvas.after.get_group("hint-text-rectangle")[0])
|
|
|
|
|
|
|
|
|
|
def set_space_in_line(
|
|
|
|
|
self, left_width: float | int, right_width: float | int
|
|
|
|
|
) -> None:
|
|
|
|
|
"""
|
|
|
|
|
Animates the length of the right line of the text field for the
|
|
|
|
|
hint text.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
Animation(_left_x_axis_pos=left_width, d=0.2, t="out_quad").start(self)
|
|
|
|
|
Animation(_right_x_axis_pos=right_width, d=0.2, t="out_quad").start(
|
|
|
|
|
self
|
|
|
|
|
)
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
|
|
|
|
def set_max_text_length(self) -> None:
|
2024-09-15 17:57:02 +00:00
|
|
|
|
"""
|
|
|
|
|
Fired when text is entered into a text field.
|
|
|
|
|
Set max length text and updated max length texture.
|
|
|
|
|
"""
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
if self._max_length_label:
|
|
|
|
|
self._max_length_label.text = ""
|
2024-09-15 12:12:16 +00:00
|
|
|
|
self._max_length_label.text = (
|
2024-09-15 17:57:02 +00:00
|
|
|
|
f"{len(self.text)}/{self._max_length_label.max_text_length}"
|
2024-09-15 12:12:16 +00:00
|
|
|
|
)
|
2024-09-15 17:57:02 +00:00
|
|
|
|
self._max_length_label.texture_update()
|
|
|
|
|
max_length_rect = self.canvas.before.get_group("max-length-rect")[0]
|
|
|
|
|
max_length_rect.texture = None
|
|
|
|
|
max_length_rect.texture = self._max_length_label.texture
|
|
|
|
|
max_length_rect.size = self._max_length_label.texture_size
|
|
|
|
|
max_length_rect.pos = (
|
|
|
|
|
(self.x + self.width)
|
|
|
|
|
- (self._max_length_label.texture_size[0] + dp(16)),
|
|
|
|
|
self.y - dp(18),
|
2024-09-15 12:12:16 +00:00
|
|
|
|
)
|
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
def set_text(self, instance, text: str) -> None:
|
|
|
|
|
"""Fired when text is entered into a text field."""
|
|
|
|
|
|
|
|
|
|
def set_text(*args):
|
|
|
|
|
self.text = re.sub("\n", " ", text) if not self.multiline else text
|
|
|
|
|
self.set_max_text_length()
|
|
|
|
|
|
|
|
|
|
if self.text and self._get_has_error() or self._get_has_error():
|
|
|
|
|
self.error = True
|
|
|
|
|
elif self.text and not self._get_has_error():
|
|
|
|
|
self.error = False
|
|
|
|
|
|
|
|
|
|
# Start the appropriate texture animations when programmatically
|
|
|
|
|
# pasting text into a text field.
|
|
|
|
|
if len(self.text) != 0 and not self.focus:
|
|
|
|
|
if self._hint_text_label:
|
|
|
|
|
self._hint_text_label.font_size = theme_font_styles[
|
|
|
|
|
self._hint_text_label.font_style
|
|
|
|
|
]["small"]["font-size"]
|
|
|
|
|
self._hint_text_label.texture_update()
|
|
|
|
|
self.set_hint_text_font_size()
|
|
|
|
|
|
|
|
|
|
if (not self.text and not self.focus) or (
|
|
|
|
|
self.text and not self.focus
|
|
|
|
|
):
|
|
|
|
|
self.on_focus(instance, False)
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
set_text()
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
def on_focus(self, instance, focus: bool) -> None:
|
|
|
|
|
"""Fired when the `focus` value changes."""
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
|
|
|
|
if focus:
|
2024-09-15 17:57:02 +00:00
|
|
|
|
if self.mode == "filled":
|
|
|
|
|
Animation(_indicator_height=dp(1.25), d=0).start(self)
|
|
|
|
|
else:
|
|
|
|
|
Animation(_outline_height=dp(1.25), d=0).start(self)
|
|
|
|
|
|
|
|
|
|
if self._trailing_icon:
|
2024-09-15 12:12:16 +00:00
|
|
|
|
Clock.schedule_once(
|
2024-09-15 17:57:02 +00:00
|
|
|
|
lambda x: self.set_texture_color(
|
|
|
|
|
self._trailing_icon,
|
|
|
|
|
self.canvas.before.get_group("trailing-icons-color")[0],
|
|
|
|
|
(
|
|
|
|
|
self.theme_cls.onSurfaceVariantColor
|
|
|
|
|
if self._trailing_icon.theme_icon_color == "Primary"
|
|
|
|
|
or not self._trailing_icon.icon_color_focus
|
|
|
|
|
else self._trailing_icon.icon_color_focus
|
|
|
|
|
)
|
|
|
|
|
if not self.error
|
|
|
|
|
else self._get_error_color(),
|
2024-09-15 12:12:16 +00:00
|
|
|
|
)
|
|
|
|
|
)
|
2024-09-15 17:57:02 +00:00
|
|
|
|
if self._leading_icon:
|
2024-09-15 12:12:16 +00:00
|
|
|
|
Clock.schedule_once(
|
2024-09-15 17:57:02 +00:00
|
|
|
|
lambda x: self.set_texture_color(
|
|
|
|
|
self._leading_icon,
|
|
|
|
|
self.canvas.before.get_group("leading-icons-color")[0],
|
|
|
|
|
self.theme_cls.onSurfaceVariantColor
|
|
|
|
|
if self._leading_icon.theme_icon_color == "Primary"
|
|
|
|
|
or not self._leading_icon.icon_color_focus
|
|
|
|
|
else self._leading_icon.icon_color_focus,
|
|
|
|
|
)
|
2024-09-15 12:12:16 +00:00
|
|
|
|
)
|
2024-09-15 17:57:02 +00:00
|
|
|
|
if self._max_length_label and not self.error:
|
2024-09-15 12:12:16 +00:00
|
|
|
|
Clock.schedule_once(
|
2024-09-15 17:57:02 +00:00
|
|
|
|
lambda x: self.set_texture_color(
|
|
|
|
|
self._max_length_label,
|
|
|
|
|
self.canvas.before.get_group("max-length-color")[0],
|
|
|
|
|
self.theme_cls.onSurfaceVariantColor
|
|
|
|
|
if not self._max_length_label.text_color_focus
|
|
|
|
|
else self._max_length_label.text_color_focus,
|
2024-09-15 12:12:16 +00:00
|
|
|
|
)
|
|
|
|
|
)
|
2024-09-15 17:57:02 +00:00
|
|
|
|
|
|
|
|
|
if self._helper_text_label and self._helper_text_label.mode in (
|
|
|
|
|
"on_focus",
|
|
|
|
|
"persistent",
|
|
|
|
|
):
|
2024-09-15 12:12:16 +00:00
|
|
|
|
Clock.schedule_once(
|
2024-09-15 17:57:02 +00:00
|
|
|
|
lambda x: self.set_texture_color(
|
|
|
|
|
self._helper_text_label,
|
|
|
|
|
self.canvas.before.get_group("helper-text-color")[0],
|
|
|
|
|
(
|
|
|
|
|
self.theme_cls.onSurfaceVariantColor
|
|
|
|
|
if not self._helper_text_label.text_color_focus
|
|
|
|
|
else self._helper_text_label.text_color_focus
|
|
|
|
|
)
|
|
|
|
|
if not self.error
|
|
|
|
|
else self._get_error_color(),
|
2024-09-15 12:12:16 +00:00
|
|
|
|
)
|
|
|
|
|
)
|
2024-09-15 17:57:02 +00:00
|
|
|
|
if (
|
|
|
|
|
self._helper_text_label
|
|
|
|
|
and self._helper_text_label.mode == "on_error"
|
|
|
|
|
and not self.error
|
|
|
|
|
):
|
2024-09-15 12:12:16 +00:00
|
|
|
|
Clock.schedule_once(
|
2024-09-15 17:57:02 +00:00
|
|
|
|
lambda x: self.set_texture_color(
|
|
|
|
|
self._helper_text_label,
|
|
|
|
|
self.canvas.before.get_group("helper-text-color")[0],
|
|
|
|
|
self.theme_cls.transparentColor,
|
2024-09-15 12:12:16 +00:00
|
|
|
|
)
|
|
|
|
|
)
|
2024-09-15 17:57:02 +00:00
|
|
|
|
if self._hint_text_label:
|
|
|
|
|
Clock.schedule_once(
|
|
|
|
|
lambda x: self.set_texture_color(
|
|
|
|
|
self._hint_text_label,
|
|
|
|
|
self.canvas.after.get_group("hint-text-color")[0],
|
|
|
|
|
(
|
|
|
|
|
self.theme_cls.primaryColor
|
|
|
|
|
if not self._hint_text_label.text_color_focus
|
|
|
|
|
else self._hint_text_label.text_color_focus
|
2024-09-15 12:12:16 +00:00
|
|
|
|
)
|
2024-09-15 17:57:02 +00:00
|
|
|
|
if not self.error
|
|
|
|
|
else self._get_error_color(),
|
2024-09-15 12:12:16 +00:00
|
|
|
|
)
|
2024-09-15 17:57:02 +00:00
|
|
|
|
)
|
|
|
|
|
self.set_pos_hint_text(
|
|
|
|
|
0 if self.mode != "outlined" else dp(-14),
|
|
|
|
|
(
|
|
|
|
|
-(
|
|
|
|
|
(
|
|
|
|
|
self._leading_icon.texture_size[0]
|
|
|
|
|
if self._leading_icon
|
|
|
|
|
else 0
|
|
|
|
|
)
|
|
|
|
|
+ dp(12)
|
|
|
|
|
)
|
|
|
|
|
if self._leading_icon
|
|
|
|
|
else 0
|
2024-09-15 12:12:16 +00:00
|
|
|
|
)
|
2024-09-15 17:57:02 +00:00
|
|
|
|
if self.mode == "outlined"
|
|
|
|
|
else -(
|
|
|
|
|
(
|
|
|
|
|
self._leading_icon.texture_size[0]
|
|
|
|
|
if self._leading_icon
|
|
|
|
|
else 0
|
|
|
|
|
)
|
|
|
|
|
- dp(24)
|
|
|
|
|
),
|
|
|
|
|
)
|
|
|
|
|
self._hint_text_label.font_size = theme_font_styles[
|
|
|
|
|
self._hint_text_label.font_style
|
|
|
|
|
]["small"]["font-size"]
|
|
|
|
|
self._hint_text_label.texture_update()
|
|
|
|
|
self.set_hint_text_font_size()
|
|
|
|
|
if self.mode == "outlined":
|
|
|
|
|
self.set_space_in_line(
|
|
|
|
|
dp(14), self._hint_text_label.texture_size[0] + dp(18)
|
2024-09-15 12:12:16 +00:00
|
|
|
|
)
|
|
|
|
|
else:
|
2024-09-15 17:57:02 +00:00
|
|
|
|
if self.mode == "filled":
|
|
|
|
|
Animation(_indicator_height=dp(1), d=0).start(self)
|
|
|
|
|
else:
|
|
|
|
|
Animation(_outline_height=dp(1), d=0).start(self)
|
|
|
|
|
|
|
|
|
|
if self._leading_icon:
|
2024-09-15 12:12:16 +00:00
|
|
|
|
Clock.schedule_once(
|
2024-09-15 17:57:02 +00:00
|
|
|
|
lambda x: self.set_texture_color(
|
|
|
|
|
self._leading_icon,
|
|
|
|
|
self.canvas.before.get_group("leading-icons-color")[0],
|
|
|
|
|
self.theme_cls.onSurfaceVariantColor
|
|
|
|
|
if self._leading_icon.theme_icon_color == "Primary"
|
|
|
|
|
or not self._leading_icon.icon_color_normal
|
|
|
|
|
else self._leading_icon.icon_color_normal,
|
2024-09-15 12:12:16 +00:00
|
|
|
|
)
|
|
|
|
|
)
|
2024-09-15 17:57:02 +00:00
|
|
|
|
if self._trailing_icon:
|
2024-09-15 12:12:16 +00:00
|
|
|
|
Clock.schedule_once(
|
2024-09-15 17:57:02 +00:00
|
|
|
|
lambda x: self.set_texture_color(
|
|
|
|
|
self._trailing_icon,
|
|
|
|
|
self.canvas.before.get_group("trailing-icons-color")[0],
|
|
|
|
|
(
|
|
|
|
|
self.theme_cls.onSurfaceVariantColor
|
|
|
|
|
if self._trailing_icon.theme_icon_color == "Primary"
|
|
|
|
|
or not self._trailing_icon.icon_color_normal
|
|
|
|
|
else self._trailing_icon.icon_color_normal
|
|
|
|
|
)
|
|
|
|
|
if not self.error
|
|
|
|
|
else self._get_error_color(),
|
|
|
|
|
)
|
2024-09-15 12:12:16 +00:00
|
|
|
|
)
|
2024-09-15 17:57:02 +00:00
|
|
|
|
if self._max_length_label and not self.error:
|
2024-09-15 12:12:16 +00:00
|
|
|
|
Clock.schedule_once(
|
2024-09-15 17:57:02 +00:00
|
|
|
|
lambda x: self.set_texture_color(
|
|
|
|
|
self._max_length_label,
|
|
|
|
|
self.canvas.before.get_group("max-length-color")[0],
|
|
|
|
|
self.theme_cls.onSurfaceVariantColor
|
|
|
|
|
if not self._max_length_label.text_color_normal
|
|
|
|
|
else self._max_length_label.text_color_normal,
|
2024-09-15 12:12:16 +00:00
|
|
|
|
)
|
|
|
|
|
)
|
2024-09-15 17:57:02 +00:00
|
|
|
|
if (
|
|
|
|
|
self._helper_text_label
|
|
|
|
|
and self._helper_text_label.mode == "on_focus"
|
|
|
|
|
):
|
2024-09-15 12:12:16 +00:00
|
|
|
|
Clock.schedule_once(
|
2024-09-15 17:57:02 +00:00
|
|
|
|
lambda x: self.set_texture_color(
|
|
|
|
|
self._helper_text_label,
|
|
|
|
|
self.canvas.before.get_group("helper-text-color")[0],
|
|
|
|
|
self.theme_cls.transparentColor,
|
2024-09-15 12:12:16 +00:00
|
|
|
|
)
|
|
|
|
|
)
|
2024-09-15 17:57:02 +00:00
|
|
|
|
elif (
|
|
|
|
|
self._helper_text_label
|
|
|
|
|
and self._helper_text_label.mode == "persistent"
|
|
|
|
|
):
|
2024-09-15 12:12:16 +00:00
|
|
|
|
Clock.schedule_once(
|
2024-09-15 17:57:02 +00:00
|
|
|
|
lambda x: self.set_texture_color(
|
|
|
|
|
self._helper_text_label,
|
|
|
|
|
self.canvas.before.get_group("helper-text-color")[0],
|
|
|
|
|
(
|
|
|
|
|
self.theme_cls.onSurfaceVariantColor
|
|
|
|
|
if not self._helper_text_label.text_color_normal
|
|
|
|
|
else self._helper_text_label.text_color_normal
|
|
|
|
|
)
|
|
|
|
|
if not self.error
|
|
|
|
|
else self._get_error_color(),
|
|
|
|
|
)
|
2024-09-15 12:12:16 +00:00
|
|
|
|
)
|
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
if not self.text:
|
|
|
|
|
if self._hint_text_label:
|
|
|
|
|
if self.mode == "outlined":
|
|
|
|
|
self.set_space_in_line(dp(32), dp(32))
|
|
|
|
|
self._hint_text_label.font_size = theme_font_styles[
|
|
|
|
|
self._hint_text_label.font_style
|
|
|
|
|
]["large"]["font-size"]
|
|
|
|
|
self._hint_text_label.texture_update()
|
|
|
|
|
self.set_hint_text_font_size()
|
|
|
|
|
self.set_pos_hint_text(
|
|
|
|
|
(self.height / 2)
|
|
|
|
|
- (self._hint_text_label.texture_size[1] / 2),
|
|
|
|
|
0,
|
|
|
|
|
)
|
|
|
|
|
else:
|
|
|
|
|
if self._hint_text_label:
|
|
|
|
|
if self.mode == "outlined":
|
|
|
|
|
self.set_space_in_line(
|
|
|
|
|
dp(14),
|
|
|
|
|
self._hint_text_label.texture_size[0] + dp(18),
|
|
|
|
|
)
|
|
|
|
|
self.set_pos_hint_text(
|
|
|
|
|
0 if self.mode != "outlined" else dp(-14),
|
|
|
|
|
(
|
|
|
|
|
-(
|
|
|
|
|
(
|
|
|
|
|
self._leading_icon.texture_size[0]
|
|
|
|
|
if self._leading_icon
|
|
|
|
|
else 0
|
|
|
|
|
)
|
|
|
|
|
+ dp(12)
|
|
|
|
|
)
|
|
|
|
|
if self._leading_icon
|
|
|
|
|
else 0
|
|
|
|
|
)
|
|
|
|
|
if self.mode == "outlined"
|
|
|
|
|
else -(
|
|
|
|
|
(
|
|
|
|
|
self._leading_icon.texture_size[0]
|
|
|
|
|
if self._leading_icon
|
|
|
|
|
else 0
|
|
|
|
|
)
|
|
|
|
|
- dp(24)
|
|
|
|
|
),
|
|
|
|
|
)
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
if self._hint_text_label:
|
2024-09-15 12:12:16 +00:00
|
|
|
|
Clock.schedule_once(
|
2024-09-15 17:57:02 +00:00
|
|
|
|
lambda x: self.set_texture_color(
|
|
|
|
|
self._hint_text_label,
|
|
|
|
|
self.canvas.after.get_group("hint-text-color")[0],
|
|
|
|
|
(
|
|
|
|
|
self.theme_cls.onSurfaceVariantColor
|
|
|
|
|
if not self._hint_text_label.text_color_normal
|
|
|
|
|
else self._hint_text_label.text_color_normal
|
|
|
|
|
)
|
|
|
|
|
if not self.error
|
|
|
|
|
else self._get_error_color(),
|
|
|
|
|
),
|
2024-09-15 12:12:16 +00:00
|
|
|
|
)
|
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
def on_disabled(self, instance, disabled: bool) -> None:
|
|
|
|
|
"""Fired when the `disabled` value changes."""
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
super().on_disabled(instance, disabled)
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
def on_disabled(*args):
|
|
|
|
|
if disabled:
|
|
|
|
|
self._set_disabled_colors()
|
|
|
|
|
else:
|
|
|
|
|
self._set_enabled_colors()
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
Clock.schedule_once(on_disabled, 0.2)
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
def on_error(self, instance, error: bool) -> None:
|
2024-09-15 12:12:16 +00:00
|
|
|
|
"""
|
|
|
|
|
Changes the primary colors of the text box to match the `error` value
|
|
|
|
|
(text field is in an error state or not).
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
if error:
|
2024-09-15 17:57:02 +00:00
|
|
|
|
if self._max_length_label:
|
2024-09-15 12:12:16 +00:00
|
|
|
|
Clock.schedule_once(
|
2024-09-15 17:57:02 +00:00
|
|
|
|
lambda x: self.set_texture_color(
|
|
|
|
|
self._max_length_label,
|
|
|
|
|
self.canvas.before.get_group("max-length-color")[0],
|
|
|
|
|
self._get_error_color(),
|
2024-09-15 12:12:16 +00:00
|
|
|
|
)
|
|
|
|
|
)
|
2024-09-15 17:57:02 +00:00
|
|
|
|
if self._hint_text_label:
|
2024-09-15 12:12:16 +00:00
|
|
|
|
Clock.schedule_once(
|
2024-09-15 17:57:02 +00:00
|
|
|
|
lambda x: self.set_texture_color(
|
|
|
|
|
self._hint_text_label,
|
|
|
|
|
self.canvas.after.get_group("hint-text-color")[0],
|
|
|
|
|
self._get_error_color(),
|
|
|
|
|
),
|
2024-09-15 12:12:16 +00:00
|
|
|
|
)
|
2024-09-15 17:57:02 +00:00
|
|
|
|
if self._helper_text_label and self._helper_text_label.mode in (
|
|
|
|
|
"persistent",
|
|
|
|
|
"on_error",
|
|
|
|
|
):
|
2024-09-15 12:12:16 +00:00
|
|
|
|
Clock.schedule_once(
|
2024-09-15 17:57:02 +00:00
|
|
|
|
lambda x: self.set_texture_color(
|
|
|
|
|
self._helper_text_label,
|
|
|
|
|
self.canvas.before.get_group("helper-text-color")[0],
|
|
|
|
|
self._get_error_color(),
|
2024-09-15 12:12:16 +00:00
|
|
|
|
)
|
|
|
|
|
)
|
2024-09-15 17:57:02 +00:00
|
|
|
|
if self._trailing_icon:
|
2024-09-15 12:12:16 +00:00
|
|
|
|
Clock.schedule_once(
|
2024-09-15 17:57:02 +00:00
|
|
|
|
lambda x: self.set_texture_color(
|
|
|
|
|
self._trailing_icon,
|
|
|
|
|
self.canvas.before.get_group("trailing-icons-color")[0],
|
|
|
|
|
self._get_error_color(),
|
2024-09-15 12:12:16 +00:00
|
|
|
|
)
|
|
|
|
|
)
|
2024-09-15 17:57:02 +00:00
|
|
|
|
else:
|
|
|
|
|
self.on_focus(self, self.focus)
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
def on_height(self, instance, value_height: float) -> None:
|
2024-09-15 12:12:16 +00:00
|
|
|
|
if value_height >= self.max_height and self.max_height:
|
|
|
|
|
self.height = self.max_height
|
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
def _set_enabled_colors(self):
|
|
|
|
|
def schedule_set_texture_color(widget, group_name, color):
|
|
|
|
|
Clock.schedule_once(
|
|
|
|
|
lambda x: self.set_texture_color(widget, group_name, color)
|
|
|
|
|
)
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
max_length_label_group = self.canvas.before.get_group(
|
|
|
|
|
"max-length-color"
|
|
|
|
|
)
|
|
|
|
|
helper_text_label_group = self.canvas.before.get_group(
|
|
|
|
|
"helper-text-color"
|
|
|
|
|
)
|
|
|
|
|
hint_text_label_group = self.canvas.after.get_group("hint-text-color")
|
|
|
|
|
leading_icon_group = self.canvas.before.get_group("leading-icons-color")
|
|
|
|
|
trailing_icon_group = self.canvas.before.get_group(
|
|
|
|
|
"trailing-icons-color"
|
|
|
|
|
)
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
error_color = self._get_error_color()
|
|
|
|
|
on_surface_variant_color = self.theme_cls.onSurfaceVariantColor
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
if self._max_length_label:
|
|
|
|
|
schedule_set_texture_color(
|
|
|
|
|
self._max_length_label,
|
|
|
|
|
max_length_label_group[0],
|
|
|
|
|
self._max_length_label.color[:-1] + [1]
|
|
|
|
|
if not self.error
|
|
|
|
|
else error_color,
|
|
|
|
|
)
|
|
|
|
|
if self._helper_text_label:
|
|
|
|
|
schedule_set_texture_color(
|
|
|
|
|
self._helper_text_label,
|
|
|
|
|
helper_text_label_group[0],
|
|
|
|
|
on_surface_variant_color
|
|
|
|
|
if not self._helper_text_label.text_color_focus
|
|
|
|
|
else self._helper_text_label.text_color_focus
|
|
|
|
|
if not self.error
|
|
|
|
|
else error_color,
|
|
|
|
|
)
|
|
|
|
|
if self._hint_text_label:
|
|
|
|
|
schedule_set_texture_color(
|
|
|
|
|
self._hint_text_label,
|
|
|
|
|
hint_text_label_group[0],
|
|
|
|
|
on_surface_variant_color
|
|
|
|
|
if not self._hint_text_label.text_color_normal
|
|
|
|
|
else self._hint_text_label.text_color_normal
|
|
|
|
|
if not self.error
|
|
|
|
|
else error_color,
|
|
|
|
|
)
|
|
|
|
|
if self._leading_icon:
|
|
|
|
|
schedule_set_texture_color(
|
|
|
|
|
self._leading_icon,
|
|
|
|
|
leading_icon_group[0],
|
|
|
|
|
on_surface_variant_color
|
|
|
|
|
if self._leading_icon.theme_icon_color == "Primary"
|
|
|
|
|
or not self._leading_icon.icon_color_normal
|
|
|
|
|
else self._leading_icon.icon_color_normal,
|
|
|
|
|
)
|
|
|
|
|
if self._trailing_icon:
|
|
|
|
|
schedule_set_texture_color(
|
|
|
|
|
self._trailing_icon,
|
|
|
|
|
trailing_icon_group[0],
|
|
|
|
|
on_surface_variant_color
|
|
|
|
|
if self._trailing_icon.theme_icon_color == "Primary"
|
|
|
|
|
or not self._trailing_icon.icon_color_normal
|
|
|
|
|
else self._trailing_icon.icon_color_normal
|
|
|
|
|
if not self.error
|
|
|
|
|
else error_color,
|
|
|
|
|
)
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
def _set_disabled_colors(self):
|
|
|
|
|
def schedule_set_texture_color(widget, group_name, color, opacity):
|
|
|
|
|
Clock.schedule_once(
|
|
|
|
|
lambda x: self.set_texture_color(
|
|
|
|
|
widget, group_name, color + [opacity]
|
|
|
|
|
)
|
|
|
|
|
)
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
max_length_label_group = self.canvas.before.get_group(
|
|
|
|
|
"max-length-color"
|
|
|
|
|
)
|
|
|
|
|
helper_text_label_group = self.canvas.before.get_group(
|
|
|
|
|
"helper-text-color"
|
|
|
|
|
)
|
|
|
|
|
hint_text_label_group = self.canvas.after.get_group("hint-text-color")
|
|
|
|
|
leading_icon_group = self.canvas.before.get_group("leading-icons-color")
|
|
|
|
|
trailing_icon_group = self.canvas.before.get_group(
|
|
|
|
|
"trailing-icons-color"
|
|
|
|
|
)
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
disabled_color = self.theme_cls.disabledTextColor[:-1]
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
if self._max_length_label:
|
|
|
|
|
schedule_set_texture_color(
|
|
|
|
|
self._max_length_label,
|
|
|
|
|
max_length_label_group[0],
|
|
|
|
|
disabled_color,
|
|
|
|
|
self.text_field_opacity_value_disabled_max_length_label,
|
|
|
|
|
)
|
|
|
|
|
if self._helper_text_label:
|
|
|
|
|
schedule_set_texture_color(
|
|
|
|
|
self._helper_text_label,
|
|
|
|
|
helper_text_label_group[0],
|
|
|
|
|
disabled_color,
|
|
|
|
|
self.text_field_opacity_value_disabled_helper_text_label,
|
|
|
|
|
)
|
|
|
|
|
if self._hint_text_label:
|
|
|
|
|
schedule_set_texture_color(
|
|
|
|
|
self._hint_text_label,
|
|
|
|
|
hint_text_label_group[0],
|
|
|
|
|
disabled_color,
|
|
|
|
|
self.text_field_opacity_value_disabled_hint_text_label,
|
|
|
|
|
)
|
|
|
|
|
if self._leading_icon:
|
|
|
|
|
schedule_set_texture_color(
|
|
|
|
|
self._leading_icon,
|
|
|
|
|
leading_icon_group[0],
|
|
|
|
|
disabled_color,
|
|
|
|
|
self.text_field_opacity_value_disabled_leading_icon,
|
|
|
|
|
)
|
|
|
|
|
if self._trailing_icon:
|
|
|
|
|
schedule_set_texture_color(
|
|
|
|
|
self._trailing_icon,
|
|
|
|
|
trailing_icon_group[0],
|
|
|
|
|
disabled_color,
|
|
|
|
|
self.text_field_opacity_value_disabled_trailing_icon,
|
|
|
|
|
)
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
|
|
|
|
def _get_has_error(self) -> bool:
|
|
|
|
|
"""
|
|
|
|
|
Returns `False` or `True` depending on the state of the text field,
|
|
|
|
|
for example when the allowed character limit has been exceeded or when
|
|
|
|
|
the :attr:`~MDTextField.required` parameter is set to `True`.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
if self.validator and self.validator != "phone":
|
|
|
|
|
has_error = {
|
|
|
|
|
"date": self.is_date_valid,
|
|
|
|
|
"email": self.is_email_valid,
|
|
|
|
|
"time": self.is_time_valid,
|
|
|
|
|
}[self.validator](self.text)
|
|
|
|
|
return has_error
|
2024-09-15 17:57:02 +00:00
|
|
|
|
if (
|
|
|
|
|
self._max_length_label
|
|
|
|
|
and len(self.text) > self._max_length_label.max_text_length
|
|
|
|
|
):
|
2024-09-15 12:12:16 +00:00
|
|
|
|
has_error = True
|
|
|
|
|
else:
|
|
|
|
|
if all((self.required, len(self.text) == 0)):
|
|
|
|
|
has_error = True
|
|
|
|
|
else:
|
|
|
|
|
has_error = False
|
|
|
|
|
return has_error
|
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
def _get_error_color(self):
|
|
|
|
|
return (
|
|
|
|
|
self.theme_cls.errorColor
|
|
|
|
|
if not self.error_color
|
|
|
|
|
else self.error_color
|
|
|
|
|
)
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
def _check_text(self, *args) -> None:
|
|
|
|
|
self.set_text(self, self.text)
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
|
def _refresh_hint_text(self):
|
|
|
|
|
"""Method override to avoid duplicate hint text texture."""
|