Skip to content

Instantly share code, notes, and snippets.

@el3
Created May 26, 2020 13:37
Show Gist options
  • Save el3/9a9ffc2b893c0fa6ba201e2e4f8f0997 to your computer and use it in GitHub Desktop.
Save el3/9a9ffc2b893c0fa6ba201e2e4f8f0997 to your computer and use it in GitHub Desktop.
A multi column recycleview with selectable rows.
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.recycleview import RecycleView
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.recycleview.views import RecycleDataViewBehavior
from kivy.uix.label import Label
from kivy.properties import BooleanProperty
from kivy.uix.recycleboxlayout import RecycleBoxLayout
from kivy.uix.behaviors import FocusBehavior
from kivy.uix.recycleview.layout import LayoutSelectionBehavior
Builder.load_string('''
<MyBL>:
canvas.before:
Color:
rgba: (.0, 0.9, .1, .3) if self.selected else (0, 0, 0, 1)
Rectangle:
pos: self.pos
size: self.size
t1: ""
t2: ""
orientation: "horizontal"
Label:
text: root.t1
Label:
text: root.t2
<RV>:
viewclass: 'MyBL'
SelectableRecycleBoxLayout:
default_size: None, dp(56)
default_size_hint: 1, None
size_hint_y: None
height: self.minimum_height
orientation: 'vertical'
multiselect: True
touch_multiselect: True
''')
class SelectableRecycleBoxLayout(FocusBehavior, LayoutSelectionBehavior,RecycleBoxLayout):
pass
class MyBL(RecycleDataViewBehavior, BoxLayout):
''' Add selection support to the Label '''
index = None
selected = BooleanProperty(False)
selectable = BooleanProperty(True)
def refresh_view_attrs(self, rv, index, data):
''' Catch and handle the view changes '''
self.index = index
return super(MyBL, self).refresh_view_attrs(
rv, index, data)
def on_touch_down(self, touch):
''' Add selection on touch down '''
if super(MyBL, self).on_touch_down(touch):
return True
if self.collide_point(*touch.pos) and self.selectable:
return self.parent.select_with_touch(self.index, touch)
def apply_selection(self, rv, index, is_selected):
''' Respond to the selection of items in the view. '''
self.selected = is_selected
if is_selected:
print("selection changed to {0}".format(rv.data[index]))
else:
print("selection removed for {0}".format(rv.data[index]))
class RV(RecycleView):
def __init__(self, **kwargs):
super(RV, self).__init__(**kwargs)
self.data = [{"t1": str(x), "t2":"hello"} for x in range(100)]
class TestApp(App):
def build(self):
return RV()
if __name__ == '__main__':
TestApp().run()
@kc3soc
Copy link

kc3soc commented Aug 27, 2021

Beautiful code. Thanks for writing this. It will help me understand RecycleViews better.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment