Центрирование макета в ScrollView. Kivy / KivyMD - PullRequest
0 голосов
/ 10 ноября 2019

Я пытаюсь создать макет в Kivy / KivyMD, который будет отзывчивым, центрированным и прокручиваемым. До сих пор я разработал два макета, один, который центрирует BoxLayout в FloatLayout, и его можно красиво изменить, но он не прокручивается. Я также разработал макет, который представляет собой GridLayout в ScrollView, он прекрасно изменяет размеры, но при больших размерах окна он не центрирует GridLayout должным образом.

Я попытался поместить BoxLayout в FloatLayout вScrollView, он прекрасно изменяет размеры, НО полоса прокрутки не работает.

Я до сих пор не смог объединить центрированный макет с изменяемым размером в правильно работающем просмотре прокрутки. Как мне это сделать?

Вот мой пример 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()

Как я могу скомпилировать оба эти изаставить это работать?

Ответы [ 2 ]

0 голосов
/ 10 ноября 2019

Программная реализация центрирования в пределах отступа 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()
0 голосов
/ 10 ноября 2019

Проблема в том, что вы пытаетесь использовать 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_hint для центрирования ScrollView внутри ExampleFL. Тогда ваш build метод, конечно, вернет ExamplFL().

...