我试图在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()
我如何编译它们并使其工作?
答案 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_hint
将ScrollView
居中放在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", })
滚动视图上的小部件将居中。