动态添加 Widget 到 ScrollView - Kivy
Dynamically adding Widget to ScrollView - Kivy
我正在尝试将小部件添加到 kivy 滚动视图。滚动视图工作正常,但是当我尝试在滚动视图底部添加一个小部件时,滚动视图会自动调整其 scroll_y。这看起来很糟糕,因为滚动视图会跳转!在我看来,这是滚动视图的常见行为。我如何编辑或设置滚动视图,以便用户可以在滚动视图不改变位置的情况下继续滚动。
提前致谢!
是的,这是正常的 ScrollView
行为。该行为是因为 ScrollView
不调整 scroll_y
值,这在大多数情况下会导致滚动。您可以通过计算一个新的 scroll_y
值来避免这种行为,该值旨在使视口的相同部分在 ScrollView
中保持可见。如果添加的 Widget
具有已知的 height
,这很容易完成。这是一个这样做的例子:
from functools import partial
from kivy.app import App
from kivy.clock import Clock
from kivy.lang import Builder
from kivy.uix.label import Label
kv = '''
BoxLayout:
orientation: 'vertical'
Button:
text: 'add'
on_release: app.add_new_widget()
ScrollView:
id: scroll
BoxLayout:
id: box
orientation: 'vertical'
size_hint_y: None
height: self.minimum_height
'''
class TestApp(App):
def build(self):
self.count = 0
return Builder.load_string(kv)
def add_new_widget(self):
vp_height = self.root.ids.scroll.viewport_size[1]
sv_height = self.root.ids.scroll.height
# add a new widget (must have preset height)
label = Label(text='Widget #' + str(self.count), size_hint=(1, None), height=50)
self.root.ids.box.add_widget(label)
self.count += 1
if vp_height > sv_height: # otherwise there is no scrolling
# calculate y value of bottom of scrollview in the viewport
scroll = self.root.ids.scroll.scroll_y
bottom = scroll * (vp_height - sv_height)
# use Clock.schedule_once because we need updated viewport height
# this assumes that new widgets are added at the bottom
# so the current bottom must increase by the widget height to maintain position
Clock.schedule_once(partial(self.adjust_scroll, bottom+label.height), -1)
def adjust_scroll(self, bottom, dt):
vp_height = self.root.ids.scroll.viewport_size[1]
sv_height = self.root.ids.scroll.height
self.root.ids.scroll.scroll_y = bottom / (vp_height - sv_height)
TestApp().run()
add_new_widget()
方法每次调用都会添加另一个Label
,新的Label
有指定的height
(本例中为50)。如有必要,将调用 adjust_scroll()
方法,并计算新的 scroll_y
以防止 ScrollView
滚动。
我正在尝试将小部件添加到 kivy 滚动视图。滚动视图工作正常,但是当我尝试在滚动视图底部添加一个小部件时,滚动视图会自动调整其 scroll_y。这看起来很糟糕,因为滚动视图会跳转!在我看来,这是滚动视图的常见行为。我如何编辑或设置滚动视图,以便用户可以在滚动视图不改变位置的情况下继续滚动。 提前致谢!
是的,这是正常的 ScrollView
行为。该行为是因为 ScrollView
不调整 scroll_y
值,这在大多数情况下会导致滚动。您可以通过计算一个新的 scroll_y
值来避免这种行为,该值旨在使视口的相同部分在 ScrollView
中保持可见。如果添加的 Widget
具有已知的 height
,这很容易完成。这是一个这样做的例子:
from functools import partial
from kivy.app import App
from kivy.clock import Clock
from kivy.lang import Builder
from kivy.uix.label import Label
kv = '''
BoxLayout:
orientation: 'vertical'
Button:
text: 'add'
on_release: app.add_new_widget()
ScrollView:
id: scroll
BoxLayout:
id: box
orientation: 'vertical'
size_hint_y: None
height: self.minimum_height
'''
class TestApp(App):
def build(self):
self.count = 0
return Builder.load_string(kv)
def add_new_widget(self):
vp_height = self.root.ids.scroll.viewport_size[1]
sv_height = self.root.ids.scroll.height
# add a new widget (must have preset height)
label = Label(text='Widget #' + str(self.count), size_hint=(1, None), height=50)
self.root.ids.box.add_widget(label)
self.count += 1
if vp_height > sv_height: # otherwise there is no scrolling
# calculate y value of bottom of scrollview in the viewport
scroll = self.root.ids.scroll.scroll_y
bottom = scroll * (vp_height - sv_height)
# use Clock.schedule_once because we need updated viewport height
# this assumes that new widgets are added at the bottom
# so the current bottom must increase by the widget height to maintain position
Clock.schedule_once(partial(self.adjust_scroll, bottom+label.height), -1)
def adjust_scroll(self, bottom, dt):
vp_height = self.root.ids.scroll.viewport_size[1]
sv_height = self.root.ids.scroll.height
self.root.ids.scroll.scroll_y = bottom / (vp_height - sv_height)
TestApp().run()
add_new_widget()
方法每次调用都会添加另一个Label
,新的Label
有指定的height
(本例中为50)。如有必要,将调用 adjust_scroll()
方法,并计算新的 scroll_y
以防止 ScrollView
滚动。