You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python Kivy中如何让ScrollView内动态添加的Widget从底部显示?

实现Kivy聊天式ScrollView(新Widget从底部加载)

不用PushMatrix/PopMatrix(会导致内容倒置),有两种简单方案实现类似WhatsApp的聊天布局:

方案一:反转布局顺序+自动滚动到底部

通过将新Widget添加到布局的最开头,再让ScrollView自动滚动到底部,实现新内容在底部显示的效果。

修改后的Python代码:

from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.widget import Widget
from kivy.lang import Builder
from kivy.core.window import Window


Builder.load_file('scrollview_modification.kv')

class MyLayout(Widget):

    def add_widgets(self):
        settings_label = SettingsLabel(text="Widget added")
        # 将新Widget添加到布局的最开头
        self.ids.widgets.add_widget(settings_label, index=0)
        # 滚动到ScrollView底部(scroll_y=0对应底部,1对应顶部)
        self.ids.scroll_view.scroll_y = 0

class SettingsLabel(Label):
    pass

class AwesomeApp(App):
    def build(self):
        Window.clearcolor = (0,1,1,1)
        return MyLayout()

if __name__ == '__main__':
    AwesomeApp().run()

修改后的KV文件:

<MyLayout>
BoxLayout:
    orientation:'vertical'
    size: root.width, root.height
    size_hint: 1, 0.6
    Button:
        text: "add_widgets"
        on_press: root.add_widgets()
        size_hint: 1, 0.25
    ScrollView:
        id: scroll_view  # 新增ScrollView的id,用于控制滚动
        do_scroll_x: False
        do_scroll_y: True
        BoxLayout:
            size_hint_y: None
            height: self.minimum_height
            orientation: 'vertical'
            id: widgets
            spacing: 3
            padding: 3

<SettingsLabel>
    markup: True
    bold: True
    size_hint: 1, None
    height: 50
    font_size: 16
    col: (179/255, 89/255, 0 , 1)
    canvas.before:
        Color:
            rgba: self.col
        RoundedRectangle:
            size: self.size
            pos: self.pos
            radius: [10]

方案二:用AnchorLayout固定布局在底部

通过AnchorLayout将消息容器固定在ScrollView底部,新添加的Widget会自动追加到容器底部,无需反转顺序。

修改后的KV文件(Python代码无需改动):

<MyLayout>
BoxLayout:
    orientation:'vertical'
    size: root.width, root.height
    size_hint: 1, 0.6
    Button:
        text: "add_widgets"
        on_press: root.add_widgets()
        size_hint: 1, 0.25
    ScrollView:
        do_scroll_x: False
        do_scroll_y: True
        AnchorLayout:
            anchor_y: 'bottom'  # 将内部布局固定在底部
            size_hint_y: None
            height: self.minimum_height
            BoxLayout:
                size_hint_y: None
                height: self.minimum_height
                orientation: 'vertical'
                id: widgets
                spacing: 3
                padding: 3

<SettingsLabel>
    markup: True
    bold: True
    size_hint: 1, None
    height: 50
    font_size: 16
    col: (179/255, 89/255, 0 , 1)
    canvas.before:
        Color:
            rgba: self.col
        RoundedRectangle:
            size: self.size
            pos: self.pos
            radius: [10]

两种方案对比:

  • 方案一适合消息按「旧→新」的顺序存储,通过反转布局让新消息显示在底部;
  • 方案二布局顺序正常,新消息直接追加到底部,更符合常规的消息存储逻辑。

内容的提问来源于stack exchange,提问作者f22daniel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 03:55:03