【问题标题】:Dynamically adding Widget to ScrollView - Kivy将 Widget 动态添加到 ScrollView - Kivy
【发布时间】:2020-05-09 22:25:26
【问题描述】:

我正在尝试将小部件添加到 kivy 滚动视图。滚动视图工作正常,但是当我尝试在滚动视图底部添加小部件时,滚动视图会自动调整其 scroll_y。由于滚动视图跳跃,这看起来很糟糕!在我看来,这是滚动视图的常见行为。我如何编辑或设置滚动视图,以便用户可以在滚动视图不改变位置的情况下继续滚动。 提前致谢!

【问题讨论】:

    标签: scroll kivy scrollview kivy-language


    【解决方案1】:

    是的,这是正常的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 滚动。

    【讨论】:

    • 谢谢。哇,太好了,完美运行。我希望你欢迎更多的问题,因为我目前卡在我的项目中。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-03-18
    • 2017-01-01
    • 2018-03-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多