""" 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: 4 .. 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.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 ( CommonElevationBehavior, RectangularRippleBehavior, ScaleBehavior, TouchBehavior, ) from kivymd.uix.boxlayout import MDBoxLayout from kivymd.uix.label import MDIcon with open( os.path.join(uix_path, "chip", "chip.kv"), encoding="utf-8" ) as kv_file: Builder.load_string(kv_file.read()) class MDChip( MDBoxLayout, ThemableBehavior, RectangularRippleBehavior, ButtonBehavior, CommonElevationBehavior, TouchBehavior, ): text = StringProperty() """ Chip text. :attr:`text` is an :class:`~kivy.properties.StringProperty` and defaults to `''`. """ 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 `''`. """ 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_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`. """ 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 MDScalableCheckIcon(MDIcon, ScaleBehavior): 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()