""" Components/Chip =============== .. seealso:: `Material Design spec, Chips `_ .. rubric:: Chips are compact elements that represent an input, attribute, or action. .. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/chips.png :align: center Usage ----- .. code-block:: python from kivy.lang import Builder from kivymd.app import MDApp KV = ''' MDScreen: MDChip: text: "Portland" pos_hint: {"center_x": .5, "center_y": .5} on_release: app.on_release_chip(self) ''' class Test(MDApp): def build(self): return Builder.load_string(KV) def on_release_chip(self, instance_check): print(instance_check) Test().run() .. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/ordinary-chip.png :align: center Use with right icon ------------------- .. code-block:: kv MDChip: text: "Portland" icon_right: "close-circle-outline" .. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/chip-with-right-icon.png :align: center Use with left icon ------------------ .. code-block:: kv MDChip: text: "Portland" icon_left: "map-marker" .. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/chip-with-left-icon.png :align: center Use with custom left icon ------------------------- .. code-block:: kv MDChip: text: "Portland" icon_left: "avatar.png" .. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/chip-with-custom-left-icon.png :align: center Use with left and right icon ---------------------------- .. code-block:: kv MDChip: text: "Portland" icon_left: "avatar.png" icon_right: "close-circle-outline" .. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/chip-with-left-right-icon.png :align: center Use with outline ---------------- .. code-block:: kv MDChip: text: "Portland" icon_left: "avatar.png" icon_right: "close-circle-outline" line_color: app.theme_cls.disabled_hint_text_color .. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/chip-with-outline.png :align: center Use with custom color --------------------- .. code-block:: kv MDChip: text: "Portland" icon_left: "avatar.png" icon_right: "close-circle-outline" line_color: app.theme_cls.disabled_hint_text_color md_bg_color: 1, 0, 0, .5 .. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/chip-with-custom-color.png :align: center Use with elevation ------------------ .. code-block:: kv MDChip: text: "Portland" icon_left: "avatar.png" icon_right: "close-circle-outline" line_color: app.theme_cls.disabled_hint_text_color md_bg_color: 1, 0, 0, .5 elevation: 12 .. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/chip-with-elevation.png :align: center Behavior ======== Long press on the chip, it will be marked. When you click on the marked chip, the mark will be removed: .. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/chip-activate.gif :align: center Examples ======== Multiple choose --------------- Selecting a single choice chip automatically deselects all other chips in the set. .. code-block:: python from kivy.animation import Animation from kivy.lang import Builder from kivymd.uix.screen import MDScreen from kivymd.uix.chip import MDChip from kivymd.app import MDApp KV = ''' MDBoxLayout: orientation: "vertical" adaptive_size: True spacing: "12dp" padding: "56dp" pos_hint: {"center_x": .5, "center_y": .5} MDLabel: text: "Multiple choice" bold: True font_style: "H5" adaptive_size: True MDBoxLayout: id: chip_box adaptive_size: True spacing: "8dp" MyChip: text: "Elevator" on_press: if self.active: root.removes_marks_all_chips() MyChip: text: "Washer / Dryer" on_press: if self.active: root.removes_marks_all_chips() MyChip: text: "Fireplace" on_press: if self.active: root.removes_marks_all_chips() ScreenManager: MyScreen: ''' class MyChip(MDChip): icon_check_color = (0, 0, 0, 1) text_color = (0, 0, 0, 0.5) _no_ripple_effect = True def __init__(self, **kwargs): super().__init__(**kwargs) self.bind(active=self.set_chip_bg_color) self.bind(active=self.set_chip_text_color) def set_chip_bg_color(self, instance_chip, active_value: int): ''' Will be called every time the chip is activated/deactivated. Sets the background color of the chip. ''' self.md_bg_color = ( (0, 0, 0, 0.4) if active_value else ( self.theme_cls.bg_darkest if self.theme_cls.theme_style == "Light" else ( self.theme_cls.bg_light if not self.disabled else self.theme_cls.disabled_hint_text_color ) ) ) def set_chip_text_color(self, instance_chip, active_value: int): Animation( color=(0, 0, 0, 1) if active_value else (0, 0, 0, 0.5), d=0.2 ).start(self.ids.label) class MyScreen(MDScreen): def removes_marks_all_chips(self): for instance_chip in self.ids.chip_box.children: if instance_chip.active: instance_chip.active = False class Test(MDApp): def build(self): return Builder.load_string(KV) Test().run() .. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/chip-multiple-choose.gif :align: center Only choose ----------- Only one chip will be selected. .. code-block:: python KV = ''' [...] MDBoxLayout: id: chip_box adaptive_size: True spacing: "8dp" MyChip: text: "Elevator" on_active: if self.active: root.removes_marks_all_chips(self) MyChip: text: "Washer / Dryer" on_active: if self.active: root.removes_marks_all_chips(self) MyChip: text: "Fireplace" on_active: if self.active: root.removes_marks_all_chips(self) [...] ''' class MyScreen(MDScreen): def removes_marks_all_chips(self, selected_instance_chip): for instance_chip in self.ids.chip_box.children: if instance_chip != selected_instance_chip: instance_chip.active = False .. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/chip-only-choose.gif :align: center """ __all__ = ("MDChip",) import os from kivy import Logger from kivy.animation import Animation from kivy.lang import Builder from kivy.metrics import dp from kivy.properties import BooleanProperty, ColorProperty, StringProperty from kivy.uix.behaviors import ButtonBehavior from kivymd import uix_path from kivymd.theming import ThemableBehavior from kivymd.uix.behaviors import ( FakeRectangularElevationBehavior, RectangularRippleBehavior, TouchBehavior, ) from kivymd.uix.boxlayout import MDBoxLayout from kivymd.uix.label import MDIcon from kivymd.uix.stacklayout import MDStackLayout from kivymd.uix.templates import ScaleWidget with open( os.path.join(uix_path, "chip", "chip.kv"), encoding="utf-8" ) as kv_file: Builder.load_string(kv_file.read()) class MDChip( ThemableBehavior, RectangularRippleBehavior, FakeRectangularElevationBehavior, TouchBehavior, ButtonBehavior, MDBoxLayout, ): text = StringProperty() """ Chip text. :attr:`text` is an :class:`~kivy.properties.StringProperty` and defaults to `''`. """ icon = StringProperty("checkbox-blank-circle", deprecated=True) """ Chip icon. .. deprecated:: 1.0.0 Use :attr:`icon_right` and :attr:`icon_left` instead. :attr:`icon` is an :class:`~kivy.properties.StringProperty` and defaults to `'checkbox-blank-circle'`. """ icon_left = StringProperty() """ Chip left icon. .. versionadded:: 1.0.0 :attr:`icon_left` is an :class:`~kivy.properties.StringProperty` and defaults to `''`. """ icon_right = StringProperty() """ Chip right icon. .. versionadded:: 1.0.0 :attr:`icon_right` is an :class:`~kivy.properties.StringProperty` and defaults to `''`. """ color = ColorProperty(None, deprecated=True) """ Chip color in ``rgba`` format. .. deprecated:: 1.0.0 :attr:`color` is an :class:`~kivy.properties.ColorProperty` and defaults to `None`. """ text_color = ColorProperty(None) """ Chip's text color in ``rgba`` format. :attr:`text_color` is an :class:`~kivy.properties.ColorProperty` and defaults to `None`. """ icon_color = ColorProperty(None, deprecated=True) """ Chip's icon color in ``rgba`` format. .. deprecated:: 1.0.0 Use :attr:`icon_right_color` and :attr:`icon_left_color` instead. :attr:`icon_color` is an :class:`~kivy.properties.ColorProperty` and defaults to `None`. """ icon_right_color = ColorProperty(None) """ Chip's right icon color in ``rgba`` format. .. versionadded:: 1.0.0 :attr:`icon_right_color` is an :class:`~kivy.properties.ColorProperty` and defaults to `None`. """ icon_left_color = ColorProperty(None) """ Chip's left icon color in ``rgba`` format. .. versionadded:: 1.0.0 :attr:`icon_left_color` is an :class:`~kivy.properties.ColorProperty` and defaults to `None`. """ icon_check_color = ColorProperty(None) """ Chip's check icon color in ``rgba`` format. .. versionadded:: 1.0.0 :attr:`icon_check_color` is an :class:`~kivy.properties.ColorProperty` and defaults to `None`. """ check = BooleanProperty(False, deprecated=True) """ If `True`, a checkmark is added to the left when touch to the chip. .. deprecated:: 1.0.0 :attr:`check` is an :class:`~kivy.properties.BooleanProperty` and defaults to `False`. """ selected_chip_color = ColorProperty(None, deprecated=True) """ The color of the chip that is currently selected in ``rgba`` format. .. deprecated:: 1.0.0 :attr:`selected_chip_color` is an :class:`~kivy.properties.ColorProperty` and defaults to `None`. """ active = BooleanProperty(False) """ Whether the check is marked or not. .. versionadded:: 1.0.0 :attr:`active` is an :class:`~kivy.properties.BooleanProperty` and defaults to `False`. """ def __init__(self, **kwargs): super().__init__(**kwargs) def on_long_touch(self, *args) -> None: if self.active: return self.active = True if not self.active else False def on_active(self, instance_check, active_value: bool) -> None: if active_value: self.do_animation_check((0, 0, 0, 0.4), 1) else: self.do_animation_check((0, 0, 0, 0), 0) def do_animation_check(self, md_bg_color: list, scale_value: int) -> None: Animation(md_bg_color=md_bg_color, t="out_sine", d=0.1).start( self.ids.icon_left_box ) Animation( scale_value_x=scale_value, scale_value_y=scale_value, scale_value_z=scale_value, t="out_sine", d=0.1, ).start(self.ids.check_icon) if not self.icon_left: if scale_value: self.ids.check_icon.x = -dp(4) Animation(size=(dp(24), dp(24)), t="out_sine", d=0.1).start( self.ids.relative_box ) else: self.ids.check_icon.x = 0 Animation(size=(0, 0), t="out_sine", d=0.1).start( self.ids.relative_box ) def on_press(self, *args): if self.active: self.active = False class MDChooseChip(MDStackLayout): def __init__(self, **kwargs): super().__init__(**kwargs) Logger.warning( "MDChooseChip: " "class is deprecated and will be removed in a future version" ) class MDScalableCheckIcon(MDIcon, ScaleWidget): pos_hint = {"center_y": 0.5} if __name__ == "__main__": from kivymd.app import MDApp from kivymd.uix.screen import MDScreen KV = """ MDBoxLayout: orientation: "vertical" adaptive_size: True spacing: "12dp" padding: "56dp" pos_hint: {"center_x": .5, "center_y": .5} MDLabel: text: "Multiple choose" bold: True font_style: "H5" adaptive_size: True MDBoxLayout: id: chip_box adaptive_size: True spacing: "8dp" MyChip: text: "Elevator" on_press: if self.active: root.removes_marks_all_chips() MyChip: text: "Washer / Dryer" on_press: if self.active: root.removes_marks_all_chips() MyChip: text: "Fireplace" on_press: if self.active: root.removes_marks_all_chips() MDSeparator: MDLabel: text: "Only choose" bold: True font_style: "H5" adaptive_size: True MDBoxLayout: id: chip_only_box adaptive_size: True spacing: "8dp" MyChip: text: "Elevator" on_active: if self.active: root.removes_marks_all_chips(self, False) MyChip: text: "Washer / Dryer" on_active: if self.active: root.removes_marks_all_chips(self, False) MyChip: text: "Fireplace" on_active: if self.active: root.removes_marks_all_chips(self, False) ScreenManager: MyScreen: """ class MyChip(MDChip): icon_check_color = (0, 0, 0, 1) text_color = (0, 0, 0, 0.5) _no_ripple_effect = True def __init__(self, **kwargs): super().__init__(**kwargs) self.bind(active=self.set_chip_bg_color) self.bind(active=self.set_chip_text_color) def set_chip_bg_color(self, instance_chip, active_value: int): """ Will be called every time the chip is activated/deactivated. Sets the background color of the chip. """ self.md_bg_color = ( (0, 0, 0, 0.4) if active_value else ( self.theme_cls.bg_darkest if self.theme_cls.theme_style == "Light" else ( self.theme_cls.bg_light if not self.disabled else self.theme_cls.disabled_hint_text_color ) ) ) def set_chip_text_color(self, instance_chip, active_value: int): Animation( color=(0, 0, 0, 1) if active_value else (0, 0, 0, 0.5), d=0.2 ).start(self.ids.label) class MyScreen(MDScreen): def removes_marks_all_chips( self, selected_instance_chip=None, multiple=True ): if multiple: for instance_chip in self.ids.chip_box.children: if instance_chip.active: instance_chip.active = False else: for instance_chip in self.ids.chip_only_box.children: if instance_chip != selected_instance_chip: instance_chip.active = False class Test(MDApp): def build(self): return Builder.load_string(KV) Test().run()