如何在 BoxLayout 中垂直堆叠多行标签

How to stack multi-line labels vertically in BoxLayout

我正在尝试在 BoxLayout 内的 Kivy 上创建一堆多行标签。如何让 BoxLayout 根据其内容展开?现在 BoxLayout 正在挤压标签。

我不希望对多行标签大小进行硬编码,因为我希望每个标签都能够灵活地适应不同的文本行。

我的演示代码如下:

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.scrollview import ScrollView
from kivy.uix.label import Label
from kivy.graphics import Color, Rectangle


class MyApp(App):
    def build(self):
        self.root = GridLayout(rows=1)
        self.root.add_widget(Scroller())
        return self.root


class Scroller(ScrollView):
    def __init__(self):
        ScrollView.__init__(self)
        self.view = GridLayout(cols=1, size_hint=(1, None))
        self.add_widget(self.view)
        self.view.bind(minimum_height=self.view.setter("height"))
        for i in range(20):
            self.view.add_widget(MyWidget(i % 2 is 1))


class MyWidget(BoxLayout):
    def __init__(self, odd, **kwargs):
        super().__init__(**kwargs)
        self.orientation = "vertical"
        self.size_hint = (1, None)
        self.odd = odd
        for i in range(3):
            ll = Label(text=f"I am line\nNumber {i + 1}")
            self.add_widget(ll)
        self.bind(pos=self.format_background_color)
        self.bind(size=self.format_background_color)

    def format_background_color(self, *args):
        with self.canvas.before:
            if self.odd:
                Color(0.0, 0.0, 0.2, mode="rgb")
            else:
                Color(0.0, 0.0, 0.8, mode="rgb")
            Rectangle(pos=self.pos, size=self.size)


MyApp().run()

如果您添加到 MyWidgetLabel 具有固定数量的 text,您可以为 MyWidgetheight 设置一个特定值作为 self.height = "150dp"(根据您的需要进行调整)。

否则,如果您希望 MyWidgetheight 足以容纳其子项(此处为 Label),则将其设置为其 minimum_height。您还必须将每个 Labelheight 设置为其纹理高度。

因此,您修改后的 MyWidget class 现在应该看起来像,

class MyWidget(BoxLayout):
    def __init__(self, odd, **kwargs):
        super().__init__(**kwargs)
        self.orientation = "vertical"
        self.size_hint_y = None
        self.odd = odd
        self.bind(
            pos = self.format_background_color,
            size = self.format_background_color,
            minimum_height = self.setter("height")
        )
        for i in range(3):
            ll = Label(text=f"I am line\nNumber {i + 1}")
            ll.bind(texture_size=self.resize_label)
            self.add_widget(ll)

    def resize_label(self, instance, value):
        instance.size_hint_y = None
        instance.height = value[1]
    ...

您还可以利用 paddingspacing 作为,

class MyWidget(BoxLayout):
    def __init__(self, odd, **kwargs):
        super().__init__(**kwargs)
        self.orientation = "vertical"
        self.size_hint_y = None
        self.padding = "10dp"
        self.spacing = "10dp"
        ...