任何人都可以帮助我有关如何在RecycleView kivy中添加KivyMD扩展面板吗?因为我在kivy上添加带有“ add_widget”的MDExpansionPanel时性能缓慢,因此存在问题(在旧版android中运行)。
然后我有了将Expansion放入RecycleView的想法,但是扩展面板无法使用真实索引打开。
好,我已经制作了自定义的expanding.py文件
expansion.py
from kivy.animation import Animation
from kivy.lang import Builder
from kivy.metrics import dp
from kivy.properties import StringProperty, ObjectProperty, NumericProperty
from kivy.uix.boxlayout import BoxLayout
from kivymd.uix.button import MDIconButton
from kivymd.uix.list import (IRightBody, ILeftBody, TwoLineAvatarIconListItem)
from kivymd.uix.selectioncontrol import MDCheckbox
Builder.load_string(
"""
#:import images_path kivymd.images_path
#:import md_icons kivymd.icon_definitions.md_icons
<CustomExpansionPanel>
text: root.title
secondary_text: root.desc
_no_ripple_effect: True
IconRightSampleWidget:
id: check
disabled_color: [.2, .3, .6, .9]
disabled: True
ChevronRight:
id: chevron
icon: 'chevron-right'
disabled: True
canvas.before:
PushMatrix
Rotate:
angle: self.angle
axis: (0, 0, 1)
origin: self.center
canvas.after:
PopMatrix
<CustomMDExpansionPanel>
size_hint_y: None
height: dp(68)
padding:dp(0)
BoxLayout:
id: box_item
size_hint_y: None
height: root.height
orientation: 'vertical'
CustomExpansionPanel:
id: item_anim
title: root.title
desc: root.desc
on_press: root.check_open_box(self)
"""
)
class IconRightSampleWidget(ILeftBody, MDCheckbox):
pass
class ChevronRight(IRightBody, MDIconButton):
angle = NumericProperty(0)
class CustomExpansionPanel(TwoLineAvatarIconListItem):
title = StringProperty()
desc = StringProperty()
class CustomMDExpansionPanel(BoxLayout):
content = ObjectProperty()
title = StringProperty()
desc = StringProperty()
def __init__(self, **kwargs):
super(CustomMDExpansionPanel, self).__init__(**kwargs)
self.register_event_type("on_open")
self.register_event_type("on_close")
def on_open(self, *args):
pass
def on_close(self, *args):
pass
def check_open_box(self, instance,CloseAll=False):
press_current_item = False
for box in self.parent.children:
if isinstance(box, CustomMDExpansionPanel):
if len(box.ids.box_item.children) == 2:
if instance is box.ids.item_anim:
press_current_item = True
box.ids.box_item.remove_widget(box.ids.box_item.children[0])
chevron = box.ids.box_item.children[0].ids.chevron
self.anim_chevron_up(chevron)
self.anim_resize_close(box)
self.dispatch("on_close")
break
if not press_current_item and not CloseAll:
self.anim_chevron_down()
def anim_chevron_down(self):
chevron = self.ids.item_anim.ids.chevron
angle = -90
Animation(angle=angle, d=0.2).start(chevron)
self.anim_resize_open_item()
self.dispatch("on_open")
def anim_chevron_up(self, instance):
angle = 0
Animation(angle=angle, d=0.2).start(instance)
def anim_resize_close(self, box):
Animation(height=dp(68), d=0.1, t="in_cubic").start(box)
def anim_resize_open_item(self, *args):
self.content.name_item = self.title
anim = Animation(
height=self.content.height + dp(70), d=0.2, t="in_cubic"
)
anim.bind(on_complete=self.add_content)
anim.start(self)
def add_content(self, *args):
if self.content and len(self.ids.box_item.children) == 1:
self.ids.box_item.add_widget(self.content)
main.py
from kivymd.app import MDApp as App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.properties import ObjectProperty
from kivy.clock import Clock
from expansion import CustomMDExpansionPanel
from time import time
from kivy.uix.boxlayout import BoxLayout
Builder.load_string(
"""
<ListScreen>:
recycle_view: recycle_view
RecycleView:
id: recycle_view
size_hint: 1, 0.9
viewclass: "CustomMDExpansionPanel"
RecycleGridLayout:
id: items_box
cols:1
default_size_hint: 1, None
size_hint: 1, None
height:self.minimum_height
"""
)
class Container(BoxLayout):
def __init__(self,**kwargs):
super(Container,self).__init__()
class ListScreen(Screen):
recycle_view = ObjectProperty(None)
items_box = ObjectProperty(None)
def on_enter(self):
start = time()
container = []
for i in range(0,50):
container.append(Container(item='strrr'+str(i), index=i))
self.recycle_view.data.append(
{
'content':container[i],
'title':'title'+str(i),
'desc':'desc'+str(i)
}
)
def on_leave(self):
self.recycle_view.data = []
class ListApp(App):
sm = ScreenManager()
screens = {}
def build(self):
self.__create_screens()
ListApp.sm.add_widget(ListApp.screens['list1'])
return ListApp.sm
def __create_screens(self):
ListApp.screens['list1'] = ListScreen(name='list1')
if __name__ == '__main__':
ListApp().run()
谢谢
答案 0 :(得分:0)
根据我的理解,如果您尝试在 RecycleView 中添加扩展面板。
这是如何做到这一点的示例代码
from kivy.lang import Builder
from kivymd.app import MDApp
from kivymd.uix.boxlayout import MDBoxLayout
from kivymd.uix.expansionpanel import MDExpansionPanel, MDExpansionPanelThreeLine
from kivymd import images_path
KV = """
<Content>
adaptive_height: True
TwoLineIconListItem:
text: "(050)-123-45-67"
secondary_text: "Mobile"
RecycleView:
MDGridLayout:
id: box
cols: 1
adaptive_height: True
"""
class Content(MDBoxLayout):
"""Custom content."""
class Test(MDApp):
def build(self):
return Builder.load_string(KV)
def on_start(self):
for i in range(10):
self.root.ids.box.add_widget(
MDExpansionPanel(
icon=f"{images_path}kivymd.png",
content=Content(),
panel_cls=MDExpansionPanelThreeLine(
text="Text",
secondary_text="Secondary text",
tertiary_text="Tertiary text",
),
)
)
Test().run()
提问前请参考文档:) 因为它解决了您 90% 的问题<3
同时编辑您的问题并明确指出您的问题:)