唉,简单的答案是:这是一个古怪的 RecycleGridLayout 问题! https://github.com/kivy/kivy/issues/7255
显示单行数据的一个糟糕的解决方法是为另一行添加虚拟数据。
main.py 中的代码基础是 PalimPalim 对这个问题的回答稍作修改的版本:Kivy - python - multiple widgets in recycleview row
from kivy.app import App
from kivy.lang import Builder
from kivy.properties import NumericProperty, ListProperty
from kivy.uix.recycleview import RecycleView
from kivy.uix.recycleview.views import RecycleDataViewBehavior
from kivy.uix.label import Label
from kivy.properties import BooleanProperty
from kivy.uix.behaviors import FocusBehavior
from customRecyclegridlayout import CustomRecycleGridLayout
from Examples.RecycleGridLayout_Palim.customlayout import CustomLayoutSelectionBehavior
Builder.load_string('''
<SelectableLabel>:
# Draw a background to indicate selection
canvas.before:
Color:
rgba: (.0, 0.9, .1, .3) if self.selected else (0, 0, 0, 1)
Rectangle:
pos: self.pos
size: self.size
<RV>:
viewclass: 'SelectableLabel'
data: root.data
SelectableRecycleGridLayout:
id: recycle_grid
default_size: None, dp(56)
default_size_hint: 1, None
size_hint_y: None
height: self.minimum_height
orientation: 'lr-tb'
multiselect: True
touch_multiselect: True
cols: root.rv_columns
''')
class SelectableRecycleGridLayout(FocusBehavior, CustomLayoutSelectionBehavior, CustomRecycleGridLayout):
''' Adds selection and focus behaviour to the view. '''
class SelectableLabel(RecycleDataViewBehavior, Label):
''' 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(SelectableLabel, self).refresh_view_attrs(
rv, index, data)
def on_touch_down(self, touch):
''' Add selection on touch down '''
if super(SelectableLabel, 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):
rv_columns = NumericProperty(3) # set number of columns in RecycleView
items = ListProperty()
data = ListProperty([])
def __init__(self, **kwargs):
super(RV, self).__init__(**kwargs)
items_entity_0 = []
items_entity_1 = [0, "apple", "fox"]
items_entity_2 = [0, "apple", "fox", 1, "bone", "dog"]
items_entity_3 = [0, "apple", "fox", 1, "bone", "dog", 2, 'milk', "cat"]
self.data = self._get_formatted_data(self._check_itemsList(items_entity_1))
self.app_info = App.get_running_app()
def _check_itemsList(self, item_list):
i_list = item_list
if self.rv_columns == len(i_list):
print('single row detected!')
for element in range(self.rv_columns):
i_list.append('dummy')
return i_list
@staticmethod
def _get_formatted_data(item_list):
data = [{'text': str(x)} for x in item_list]
return data
class TestApp(App):
def build(self):
return RV()
if __name__ == '__main__':
TestApp().run()