RecycleViewの項目を複数選択する
RecycleViewでは複数の項目(ノード)を選択可能であり、複数選択した項目のデータを取得することができます。今回は、RecycleViewで複数項目の選択・選択データの取得をおこなう方法を紹介します。
RecycleViewで複数の項目を選択可能にする
RecycleViewで複数の項目を選択可能にするには、multiselectとtouch_multiselectの値にTrueと指定します。
multiselect: 複数の項目を選択できるかどうかを指定する。
touch_multiselect: 複数の項目をタッチするだけで選択できるよにする。
RecycleView:
id: rv
viewclass: 'RVBox'
SelectableRecycleBoxLayout:
id: selectablervl
default_size: None, None
size_hint: 1, None
height: self.minimum_height
orientation: 'vertical'
multiselect: True
touch_multiselect: True
Recycleviewで選択した項目を取得する
RecycleViewでは選択した項目の番号は、selected_nodesにリスト形式で保存されます。そのため、複数の項目を選択可能な場合は、以下のようにして、選択中の項目の番号を取得します。また、その番号を使用して、self.ids.rv.dataよりそのデータを得ることができます。
def on_button_press(self):
select_index = self.ids.selectablervl.selected_nodes
for index in select_index:
print(f"{index}: {self.ids.rv.data[index]}")
サンプルプログラム
以下のサンプルプログラムは、実行すると左図のようなRecycleViewとその下にボタンが配置された画面が表示されます。RecycleView上の項目はマウスでクリックすることで選択でき、複数選択することが可能です。選択したデータの背景は、右図のように青色になります。
また、データを選択した状態でボタンを押すと、ターミナルに選択中の項目をすべて出力します。
# -*- coding: utf-8 -*-
import kivy
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.lang import Builder
from kivy.config import Config
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.recycleview.views import RecycleDataViewBehavior
from kivy.properties import BooleanProperty
kivy.require('2.2.0')
Config.set('graphics', 'width', '450')
Config.set('graphics', 'height', '400')
Builder.load_string('''
<MainD>
BoxLayout:
orientation: 'vertical'
size: root.size
padding: 10
RecycleView:
id: rv
viewclass: 'RVBox'
SelectableRecycleBoxLayout:
id: selectablervl
default_size: None, None
size_hint: 1, None
height: self.minimum_height
orientation: 'vertical'
multiselect: True
touch_multiselect: True
Button:
text: 'Get Data'
size_y: None
size_hint_y: 0.2
on_press: root.on_button_press()
<SelectableRecycleBoxLayout@FocusBehavior+LayoutSelectionBehavior+RecycleBoxLayout>
<RVBox>:
text1: ''
text2: ''
id: rv
size_hint: None, None
width: self.ids.text1.width + self.ids.text2.width
height: self.ids.text1.height
canvas.before:
Color:
rgba: (0.0, 0.2, 0.9, 0.5) if self.selected else (0, 0, 0, 0)
Rectangle:
pos: self.pos
size: self.size
Label:
id: text1
size_hint: None, None
size: 200, 60
text: root.text1
Label:
id: text2
size_hint: None, None
size: 200, 60
text: root.text2
''')
class RVBox(RecycleDataViewBehavior, BoxLayout):
index = None
selected = BooleanProperty(False)
selectable = BooleanProperty(True)
def refresh_view_attrs(self, rv, index, data):
self.index = index
return super(RVBox, self).refresh_view_attrs(
rv, index, data)
def on_touch_down(self, touch):
if super(RVBox, 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):
self.selected = is_selected
class MainD(Widget):
def __init__(self, **kwargs):
super(MainD, self).__init__(**kwargs)
self.ids.rv.data = [
{'text1': 'text1 = 1', 'text2': 'text2 = 4'},
{'text1': 'text1 = 2', 'text2': 'text2 = 3'},
{'text1': 'text1 = 3', 'text2': 'text2 = 2'},
{'text1': 'text1 = 4', 'text2': 'text2 = 1'},
{'text1': 'text1 = 1', 'text2': 'text2 = 4'},
{'text1': 'text1 = 2', 'text2': 'text2 = 3'},
{'text1': 'text1 = 3', 'text2': 'text2 = 2'},
{'text1': 'text1 = 4', 'text2': 'text2 = 1'},
]
def on_button_press(self):
select_index = self.ids.selectablervl.selected_nodes
for index in select_index:
print(f"{index}: {self.ids.rv.data[index]}")
print("以上です。")
class MainDApp(App):
def __init__(self, **kwargs):
super(MainDApp, self).__init__(**kwargs)
self.title = 'RecycleView Test5'
def build(self):
return MainD()
if __name__ == '__main__':
app = MainDApp()
app.run()