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

Kivy含ScrollView、StackLayout与Label的界面布局错位求助

解决Kivy中StackLayout+ScrollView的Label错位与滚动问题

我帮你搞定这个布局问题啦!你的代码里主要是几个布局参数设置、Label对齐配置的问题,导致内容错位和滚动异常。下面是修复后的完整代码,我会逐一解释关键修改点:

from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.scrollview import ScrollView
from kivy.uix.stacklayout import StackLayout
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.core.window import Window

Window.size = (350, 600)

class RootWindow(Screen):
    def __init__(self, **kwargs):
        super(RootWindow, self).__init__(**kwargs)
        self.searchButton = Button(text="Search", size_hint=(1,0.8))
        self.searchButton.bind(on_press=self.search)
        self.add_widget(self.searchButton)

    def search(self, instance):
        src = 'Lorem ipsum'
        ingsList = ['Lorem', 'ipsum', 'dolor', 'sit amet']
        steps = "Duis finibus risus tempor nisl scelerisque, quis facilisis augue pretium. Nullam sit amet nibh ex. Pellentesque lobortis eget ipsum a congue. Nunc luctus odio sit amet arcu interdum, id pharetra urna semper. Proin at turpis vel neque facilisis pretium ut sed massa. Phasellus elit diam, elementum at tempus non, eleifend quis libero. Integer convallis tortor eget mattis eleifend."
        
        # 改用App实例获取ScreenManager,避免全局变量依赖
        app = App.get_running_app()
        app.root.transition.direction = 'left'
        app.root.current = 'second'
        
        second_screen = app.root.get_screen('second')
        # 先清空之前的内容,避免重复添加
        second_screen.title.clear_widgets()
        second_screen.ingredients.clear_widgets()
        
        # 标题Label:居中对齐
        title_label = Label(text=src, size_hint=(1, None), height='30sp',
                           text_size=(second_screen.title.width, None),
                           halign='center', valign='middle')
        second_screen.title.add_widget(title_label)
        
        # "Ingredients:" 居中对齐
        ing_title = Label(text="Ingredients:", size_hint=(1, None), height='30sp',
                         text_size=(second_screen.ingredients.width, None),
                         halign='center', valign='middle')
        second_screen.ingredients.add_widget(ing_title)
        
        # 食材列表:左对齐
        for item in ingsList:
            ing_label = Label(text=item, size_hint=(1, None), height='20sp',
                             text_size=(second_screen.ingredients.width * 0.9, None),
                             halign='left', valign='middle')
            second_screen.ingredients.add_widget(ing_label)
        
        # "Steps:" 居中对齐
        steps_title = Label(text="Steps:", size_hint=(1, None), height='30sp',
                           text_size=(second_screen.ingredients.width, None),
                           halign='center', valign='middle')
        second_screen.ingredients.add_widget(steps_title)
        
        # 步骤文本:左对齐(自动换行+高度自适应)
        steps_label = Label(text=steps, size_hint=(1, None),
                           text_size=(second_screen.ingredients.width * 0.9, None),
                           halign='left', valign='top')
        # 绑定texture_size来自动调整高度,确保文本全部显示
        steps_label.bind(texture_size=lambda _, size: setattr(steps_label, 'height', size[1]))
        second_screen.ingredients.add_widget(steps_label)

class SecondWindow(Screen):
    def __init__(self, **kwargs):
        super(SecondWindow, self).__init__(**kwargs)
        
        # 标题区域:顶部居中,占屏幕上方20%
        self.title = StackLayout(pos_hint={"top":0.95}, size_hint=(0.9, 0.15),
                               pos=(self.width * 0.05, 0))
        self.add_widget(self.title)
        
        # 滚动区域:占屏幕下方80%,从顶部0.8位置开始
        self.scroll = ScrollView(size_hint=(1, 0.8), pos_hint={"top":0.8})
        
        # 内容容器:垂直排列(tb-lr),高度自适应内容
        self.ingredients = StackLayout(size_hint=(1, None), orientation='tb-lr', spacing=(0, 5))
        self.ingredients.bind(minimum_height=self.ingredients.setter('height'))
        
        self.scroll.add_widget(self.ingredients)
        self.add_widget(self.scroll)

WMan = ScreenManager()
WMan.add_widget(RootWindow(name='root'))
WMan.add_widget(SecondWindow(name='second'))

class MyApp(App):
    def build(self):
        return WMan

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

关键修改点说明:

  • 修复ScrollView与StackLayout的布局关系:

    • 移除了ingredients的pos_hint,因为ScrollView的子控件不需要手动定位,ScrollView会自动处理其位置。
    • 把StackLayout的orientation从lr-tb改成tb-lr,这样控件会从上到下垂直排列,符合滚动需求,避免横向错位。
    • 调整了ScrollView的size_hint为(1, 0.8),让它占据屏幕下方80%的区域,和顶部的标题区域不重叠。
  • Label对齐与自适应设置:

    • 所有Label都添加了halign(水平对齐)和valign(垂直对齐)参数,严格按照你的需求设置:标题、"Ingredients:"、"Steps:"用halign='center',食材列表和步骤文本用halign='left'。
    • 步骤文本通过绑定texture_size到height,实现了文本换行后高度自动适配,再也不会出现内容被截断或高度不够的问题。
    • 给Label设置了合适的text_size,确保文本在指定宽度内自动换行。
  • 代码规范优化:

    • 避免直接访问全局的WMan,改用App.get_running_app().root获取ScreenManager,减少全局变量依赖。
    • 添加了清空控件的代码,避免多次点击搜索按钮后内容重复叠加。

现在运行代码,你会看到所有Label都按要求对齐,内容可以正常滚动,步骤文本也能完整显示啦!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 16:03:10