0

我正在使用 Kivy 和 KivyMD开发一个 android Prominent Top Bar :

在此处输入图像描述

但是,我的内容区域(ScrollView/RecycledView 或 RstDocument)不再滚动。

我最好的猜测是事件没有被正确地重新调度。

代码:

from kivy.uix.anchorlayout import AnchorLayout
from kivy.properties import NumericProperty
from kivy.lang import Builder
from kivy.core.window import Window
from kivymd.app import MDApp
from kivy.clock import Clock
from kivy.graphics import Rectangle, Color

from kivy.uix.rst import RstDocument

Window.size = (450, 900)


kv = '''
<ExtendedToolbar@AnchorLayout>
    anchor_y: 'top'

    MDToolbar:
        id: toolbar
        title: 'Extended Toolbar'
        left_action_items: [["chevron-left", lambda x: app.switch_to('menu', 'right')]]
        right_action_items: [['information-outline', lambda x: x]]
        md_bg_color: 0,0,0,0

    MDBoxLayout:
        orientation: 'vertical'

        MDBoxLayout:
            id: spacer
            orientation: 'vertical'
            size_hint_y: None

        MDBoxLayout:
            id: content

Screen:
    ExtendedToolbar:
        id: toolbar

'''

example_text = """
Scrollable Content
==================

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce vehicula nibh eget massa iaculis lacinia. Mauris at mi ornare, eleifend sem ac, tristique ipsum. Integer placerat sed nibh ac scelerisque. Duis lobortis vitae ipsum sed varius. Sed tristique efficitur consequat. Nullam molestie ex rutrum, egestas neque cursus, mollis urna. Nam neque nibh, aliquam in mattis nec, pretium a dolor. Integer mollis, odio sit amet luctus pulvinar, neque justo semper magna, quis finibus magna risus et elit. Praesent vel nunc vitae ligula vehicula eleifend. Aliquam lobortis purus lacus, sed varius ligula efficitur a. In ultrices nisi vulputate elit aliquam, eu varius ante faucibus. Vestibulum venenatis justo sit amet justo efficitur ullamcorper. Praesent a orci nisi. Morbi consequat augue at diam posuere posuere. In eros erat, iaculis ut cursus a, tempus sed sapien. Pellentesque eu eros eu est porta efficitur.

Maecenas pulvinar porta felis, id semper orci malesuada ut. Nulla efficitur nisl sit amet consequat scelerisque. Maecenas laoreet id nisl eget pellentesque. Phasellus iaculis, nibh ut suscipit scelerisque, arcu mauris hendrerit sem, nec dictum augue mi quis lorem. Etiam feugiat volutpat massa. Quisque sed posuere tortor. Ut ultricies, lectus eu ultricies ullamcorper, dolor ex tincidunt mauris, a porta magna mauris ut enim. Maecenas id mollis tellus. Suspendisse ornare tempor risus sit amet suscipit. Cras sed posuere neque. In vitae quam laoreet, convallis nulla id, dictum libero. Integer suscipit lorem dolor, cursus pulvinar mi lacinia et. Phasellus id luctus lorem.

Suspendisse neque nibh, pharetra sed tincidunt sed, euismod sed nunc. Praesent id suscipit leo. In facilisis massa vel fermentum blandit. Aenean ac nibh ex. Etiam sed tortor a turpis rutrum eleifend eget sed mauris. Proin porta ultrices dolor sed ultrices. Pellentesque luctus cursus nulla, quis dapibus nisl. Nam semper lacus magna, consectetur euismod nisi aliquam vel. Nunc ullamcorper pellentesque nibh vel condimentum. Etiam faucibus fermentum condimentum. Sed scelerisque, augue non ornare accumsan, est neque mollis dolor, pellentesque gravida libero dolor in urna.

Nam non libero ex. Integer pulvinar elit aliquam, euismod augue sed, lobortis quam. Sed nec congue quam, non posuere leo. Donec elementum ipsum interdum, sodales quam id, maximus leo. Donec auctor, enim sit amet sagittis iaculis, quam sapien tincidunt ipsum, ut congue mauris ante eget lacus. Nullam gravida gravida ligula ut gravida. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Pellentesque sem dolor, ullamcorper et finibus et, porttitor quis odio. Aliquam sit amet tortor est. Vivamus eu enim ante. Integer mattis tempus ullamcorper. Maecenas fringilla ligula nisl, vitae maximus orci semper non. Sed vulputate suscipit mi sed sodales.

Vestibulum ac lectus odio. Duis vel rhoncus turpis. Aliquam vulputate sed sapien at blandit. Nulla eu magna sit amet mauris aliquam laoreet. Sed elementum malesuada sagittis. In in eleifend quam, a euismod arcu. Curabitur at rhoncus eros. Nulla venenatis sodales felis, eget semper ligula finibus elementum. Nulla suscipit iaculis ligula. Nam sed eros eleifend, volutpat nibh id, tincidunt turpis. Nullam vitae porta dolor, ac vehicula felis. In hac habitasse platea dictumst. In sit amet purus vehicula, viverra eros eu, congue leo. Pellentesque sodales porttitor lobortis. Quisque in tellus at velit cursus ultrices eu ut erat.


"""


class ExtendedToolbar(AnchorLayout):

    def __init__(self, **kwargs):
        p_size_x = Window.size[0]
        p_size_y = Window.size[1] / 3
        self.prominence_pos = (0, Window.size[1]- p_size_y)

        super(AnchorLayout, self).__init__(size=(p_size_x, p_size_y), **kwargs)

        app = MDApp.get_running_app()
        with self.canvas:
            color = Color(rgba = app.theme_cls.primary_color)
            self.rectangle = Rectangle(id='prominence',
                                       pos=self.prominence_pos,
                                       size=self.size)

        Clock.schedule_once(self.post_init, 1)

    def post_init(self, *args):
        """ Post init function to grab the toolbar's label by id """
        self.label = self.ids.toolbar.ids.label_title

        # copy original values for defaulting
        self.label_org_pos = [self.label.pos[0], self.label.pos[1]]
        self.label_org_font_size = self.label.font_size

        self.label.pos = [25, self.rectangle.pos[1]]
        self.label.font_size = 30

        self.ids.spacer.height = Window.size[1] - self.rectangle.pos[1]


    def on_touch_down(self, touch):
        """Dispatch scroll up and down events to animation() and children"""
        if 'button' in touch.profile:
            if touch.button in ['scrollup', 'scrolldown']:
                dist = 1 if touch.button == 'scrollup' else -1
                self.animate_scroll(dist)
                return True
        # for children
        return super(AnchorLayout, self).on_touch_down(touch)

    def on_touch_up(self, touch):
        """Ungrab the widget"""
        if touch.grab_current == self:
            touch.ungrab(self)
            return True

        return super(AnchorLayout, self).on_touch_up(touch)

    def animate_scroll(self, dist):
        new_pos_y = self.rectangle.pos[1] + dist * 15
        break_pos = Window.size[1] - self.prominence_pos[1]/4
        stop_pos = Window.size[1]-self.ids.toolbar.height-14

        if new_pos_y > self.prominence_pos[1] and new_pos_y < stop_pos:
            self.rectangle.pos = [self.rectangle.pos[0] , new_pos_y]

            label_x = 25
            label_y = self.rectangle.pos[1]
            if new_pos_y > break_pos:
                label_x = self.label.pos[0] + dist*10

            self.label.pos = [label_x, label_y]

            new_font_size = self.label.font_size - dist
            if new_font_size > self.label_org_font_size:
                if new_font_size <= 30 and new_pos_y <  break_pos:
                    self.label.font_size = new_font_size
            else:
                self.label.font_size = self.label_org_font_size

        elif new_pos_y >= stop_pos:
            self.rectangle.pos = [0, Window.size[1]-self.ids.toolbar.height]
            self.label.pos = self.label_org_pos

        self.ids.spacer.height = Window.size[1] - self.rectangle.pos[1]


class ExtendedToolbarDemo(MDApp):

    def build(self):
        Clock.schedule_once(self.post_init, 1)
        return Builder.load_string(kv)

    def post_init(self, *args):
        text_content = RstDocument(text=example_text)
        self.root.ids.toolbar.ids.content.add_widget(text_content)


if __name__ == "__main__":
    ExtendedToolbarDemo().run()

你需要安装 kivy 和 kivyMD 来运行这个演示。

4

1 回答 1

0

这就是我最终的结果;

    def on_touch_down(self, touch):
        """Dispatch scroll up and down events to animation() and children"""

        if 'button' in touch.profile:
            dist = 1 if touch.button == 'scrollup' else -1

            if touch.button == 'scrollup':
                if self.label.pos == self.label_org_pos:
                    return super(AnchorLayout, self).on_touch_down(touch)
                else:
                    self.animate_scroll(dist)

            if touch.button == 'scrolldown':
                if self.ids.content.vbar[0] > 0.28:     # 0.28 because the top_bar is 30% of the window
                    self.animate_scroll(dist)
                return super(AnchorLayout, self).on_touch_down(touch)
于 2021-05-28T20:19:41.227 回答