添加或删除小部件时的 Kivy boxlayout 动画

Kivy boxlayout animation when adding or removing widgets

我正在寻找一种在添加或删除小部件时为布局设置动画的方法?在我的示例中,当我单击我的 MDIconButton 时,我想要一个缓慢展开或折叠卡片的动画。 我知道有一个 MDExpansionsPanel 小部件,但现在我对使用它不感兴趣。有没有一种简单的方法可以实现类似于 ExpansionPanel 的动画?

main.kv

MDScreen:
    MDBoxLayout:
        orientation: "vertical"

        MDCard:
            id: card
            orientation: "vertical"
            md_bg_color: .7, .7, .7, 1
            padding: dp(20)
            size_hint: .5, None
            height: self.minimum_height
            pos_hint: {"center_x": .5}

            MDIconButton:
                icon: "chevron-down"
                on_press: app.on_chevron()

        Widget:

<Box>:
    orientation: "vertical"
    size_hint_y: None
    height: self.minimum_height

main.py

from kivymd.app import MDApp
from kivy.lang import Builder
from kivy.core.window import Window
from kivymd.uix.boxlayout import MDBoxLayout
from kivymd.uix.label import MDLabel

Window.size = {320, 600}

class Box(MDBoxLayout):
    pass

class MainApp(MDApp):
    def build(self):
        self.is_expanded = False
        return Builder.load_file("main.kv")

    def on_chevron(self):
        self.is_expanded = not self.is_expanded
        card_layout = self.root.ids.card

        if self.is_expanded:
            item = Box()
            for i in range(10):
                item.add_widget(MDLabel(text=f"Lbl: {i}", size_hint=(1, None), height=20))
            card_layout.add_widget(item)

        else:
            card_layout.remove_widget(card_layout.children[0])

if __name__ == "__main__":
    MainApp().run()

您可以使用 Animation 来做到这一点。这是使用 Animation:

on_chevron() 方法的修改版本
def on_chevron(self):
    self.is_expanded = not self.is_expanded
    card_layout = self.root.ids.card

    if self.is_expanded:
        item = Box()
        labels = []
        for i in range(10):
            # initialze Label with 0 height and font_size
            l = Label(text=f"Lbl: {i}", color=(0,0,0,1), font_size=0, size_hint=(1, None), height=0)
            item.add_widget(l)
            labels.append(l)
        card_layout.add_widget(item)
        self.animate_labels(labels)

    else:
        card_layout.remove_widget(card_layout.children[0])

def animate_labels(self, labels):
    anims = []
    for i in range(len(labels)):
        anims.append(Animation(height=20, font_size=15)) # animate height and font_size
    for i in range(len(labels)):
        anims[i].start(labels[i])  # start animations

我把你的 MDLabel 换成了 Label 只是因为 MDLabel 影响了尺码。 MDLabel.

可能有一种方法可以做到这一点