在ScrollView中居中布局。 Kivy / KivyMD

时间:2019-11-09 22:24:12

标签: python-3.x kivy kivy-language

我试图在Kivy / KivyMD中创建一个响应式,居中且可滚动的布局。到目前为止,我已经开发了两种布局,一种布局将BoxLayout放置在FloatLayout中,并且可以精美地调整大小,但是它不会滚动。 我还开发了一个在ScrollView中为GridLayout的布局,它的尺寸调整得很漂亮,但是在大窗口尺寸下,它无法正确居中GridLayout。

我试图将BoxLayout放在ScrollView的FloatLayout中,但它的尺寸很好,但是滚动条不起作用。

到目前为止,我无法将居中的可调整大小的Layout组合在正常工作的scrollview中。我该怎么做?

这是我的滚动视图示例:

from kivymd.app import MDApp
from kivy.lang import Builder
from kivy.uix.scrollview import ScrollView
from kivy.uix.floatlayout import FloatLayout


LIPSUM = """Very long lipsum..."""


Builder.load_string("""
<ExampleScroll@ScrollView>:
    do_scroll_x: False

    bar_width: 10
    bar_color: app.theme_cls.primary_color
    bar_color_acrive: app.theme_cls.accent_color
    effect_cls: "DampedScrollEffect"
    scroll_type: ['bars']

    GridLayout:  # If FloatLayout and BoxLayout, doesn't scroll!
        cols: 1
        size_hint_y: None
        height: self.minimum_height

        size_hint_x: .75
        size_hint_max_x: dp(800)
        size_hint_min_x: min(dp(400), root.width)

        pos_hint: {'center_x': .5}  # Fails to center layout
        padding: 0, dp(16), 0, 0

        MDLabel:
            text: app.label_text + app.label_text
            halign: 'justify'
            padding: dp(16), dp(16)
            markup: True
            font_style: 'Body1'
            theme_text_color: 'Primary'
            size_hint_y: None
            height: self.texture_size[1]

            text_size: self.size
        MDLabel:
            text: app.label_text + app.label_text
            halign: 'justify'
            padding: dp(16), dp(16)
            markup: True
            font_style: 'Body1'
            theme_text_color: 'Primary'
            size_hint_y: None
            height: self.texture_size[1]

            text_size: self.size
        Widget
""")


class ExampleScroll(ScrollView):
    pass


class Example(MDApp):
    title = "Dialogs"
    label_text = LIPSUM

    def build(self):
        return ExampleScroll()


Example().run()

这是我居中的例子:

from kivymd.app import MDApp
from kivy.lang import Builder
from kivy.uix.scrollview import ScrollView
from kivy.uix.floatlayout import FloatLayout


LIPSUM = """Very long lipsum..."""


Builder.load_string("""
<ExampleCenter@FloatLayout>:
    BoxLayout:
        orientation: 'vertical'

        # Gives the BoxLayout a max and min width that is responsive
        size_hint_x: .75
        size_hint_max_x: dp(800)
        size_hint_min_x: min(dp(400), root.width)

        # Centers the BoxLayout horizontally responsively
        pos_hint: {'center_x': .5}
        padding: 0, dp(16), 0, 0

        MDLabel:
            text: app.label_text + app.label_text
            halign: 'justify'
            padding: dp(16), dp(16)
            markup: True
            font_style: 'Body1'
            theme_text_color: 'Primary'
            size_hint_y: None
            height: self.texture_size[1]
        MDLabel:
            text: app.label_text + app.label_text
            halign: 'justify'
            padding: dp(16), dp(16)
            markup: True
            font_style: 'Body1'
            theme_text_color: 'Primary'
            size_hint_y: None
            height: self.texture_size[1]
        Widget
""")


class ExampleCenter(FloatLayout):
    pass


class Example(MDApp):
    title = "Dialogs"
    label_text = LIPSUM

    def build(self):
        return ExampleCenter()


Example().run()

我如何编译它们并使其工作?

3 个答案:

答案 0 :(得分:0)

问题是您试图在pos_hint的子项中使用ScrollView(这不支持该属性)。因此,与其尝试居中ScrollView的孩子,不如居中ScrollView本身。这意味着ScrollView必须放在Layout内部。因此,如果您使用FloatLayout,则可以执行以下操作:

<ExampleFL>:
    ScrollView:
        pos_hint: {'center_x': .5}
        size_hint_x: None
        width: grid.width

        do_scroll_x: False
        bar_width: 10
        bar_color: app.theme_cls.primary_color
        bar_color_acrive: app.theme_cls.accent_color
        effect_cls: "DampedScrollEffect"
        scroll_type: ['bars']

        GridLayout:  # If FloatLayout and BoxLayout, doesn't scroll!
            id: grid
        .
        .
        .

并创建ExampleFL类:

class ExampleFL(FloatLayout):
    pass

这会将ScrollView的宽度设置为其子GridLayout的宽度,并使用pos_hintScrollView居中放在ExampleFL中。然后,您的build方法当然会返回ExamplFL()

答案 1 :(得分:0)

在ScrollView中操作填充的居中视图的程序实现。这给了我想要的结果。

from kivymd.app import MDApp
from kivy.lang import Builder
from kivy.metrics import dp
from kivy.properties import NumericProperty
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.gridlayout import GridLayout


LIPSUM = """Very long lipsum..."""


Builder.load_string("""
<ExampleScroll@FloatLayout>:
    ScrollView:
        do_scroll_x: False
        bar_width: 10
        bar_color: app.theme_cls.primary_color
        bar_color_acrive: app.theme_cls.accent_color
        effect_cls: "DampedScrollEffect"
        scroll_type: ['bars']

        ScrollCenterLayout:
            cols: 1
            rel_max: dp(800)
            rel_min: dp(400)
            orientation: 'vertical'
            size_hint_y: None
            height: self.minimum_height

            MDLabel:
                text: app.label_text + app.label_text
                halign: 'justify'
                padding: dp(16), dp(16)
                markup: True
                font_style: 'Body1'
                theme_text_color: 'Primary'
                size_hint_y: None
                height: self.texture_size[1]
            MDLabel:
                text: app.label_text + app.label_text
                halign: 'justify'
                padding: dp(16), dp(16)
                markup: True
                font_style: 'Body1'
                theme_text_color: 'Primary'
                size_hint_y: None
                height: self.texture_size[1]
            Widget
""")


class ScrollCenterLayout(GridLayout):
    rel_max = NumericProperty(dp(800))
    rel_min = NumericProperty(dp(400))

    def __init__(self, **kwargs):
        super(ScrollCenterLayout, self).__init__(**kwargs)

        self.rel_max = kwargs.get('rel_max', dp(800))
        self.rel_min = kwargs.get('rel_min', dp(400))

    def on_width(self, instance, value):
        if self.rel_max < value:
            padding = max(value * .125, (value - self.rel_max) / 2)
        elif self.rel_min < value:
            padding = min(value * .125, (value - self.rel_min) / 2)
        elif self.rel_min < value:
            padding = (value - self.rel_min) / 2
        else:
            padding = 0

        self.padding[0] = self.padding[2] = padding


class ExampleScroll(FloatLayout):
    pass


class Example(MDApp):
    label_text = LIPSUM

    def build(self):
        self.theme_cls.primary_palette = "LightGreen"
        self.theme_cls.accent_palette = "Green"
        self.theme_cls.theme_style = "Dark"
        return ExampleScroll()


Example().run()

答案 2 :(得分:0)

首先要做的是创建一个滚动视图,如果可能的话,可以使用RecycleView,以便您可以轻松地将窗口小部件添加为已定义为窗口小部件的类:

示例:

class Thing1(AnchorLayout):
    pass

Kv ="""
<Thing1>:
    anchor_x: "center"
    MDIconButton:
        icon: "hi.png"


"""

现在,无论在何处定义了滚动视图或回收视图小部件ID,请执行以下操作:

app.root.ids.scrollview_id_of_your_widget.add_widget(Thing1())

或者如果您使用的是RecycleView

app.root.ids.scrollview_id_of_your_widget.data.append({"viewclass": "Thing1", })

滚动视图上的小部件将居中。