From d1596704828e55dd2d6463b41cd0730c5e15f91f Mon Sep 17 00:00:00 2001 From: Gabriel Pettier Date: Fri, 16 Oct 2020 21:13:43 +0200 Subject: [PATCH] Recycleview Pull to refresh example --- .../widgets/recycleview/pull_to_refresh.py | 91 +++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 examples/widgets/recycleview/pull_to_refresh.py diff --git a/examples/widgets/recycleview/pull_to_refresh.py b/examples/widgets/recycleview/pull_to_refresh.py new file mode 100644 index 000000000..fd868e943 --- /dev/null +++ b/examples/widgets/recycleview/pull_to_refresh.py @@ -0,0 +1,91 @@ +"""Detecting and acting upon "Pull down actions" in a RecycleView +- When using overscroll or being at the to, a "pull down to refresh" message appears +- if the user pulls down far enough, then a refresh is triggered, which adds new elements at the top of the list. + +""" +from threading import Thread +from time import sleep +from datetime import datetime + +from kivy.app import App +from kivy.lang import Builder +from kivy.properties import ListProperty, BooleanProperty +from kivy.metrics import dp + + +KV = r''' +FloatLayout: + Label: + opacity: 1 if app.refreshing or rv.scroll_y > 1 else 0 + size_hint_y: None + pos_hint: {'top': 1} + text: 'Refreshing…' if app.refreshing else 'Pull down to refresh' + + RecycleView: + id: rv + data: app.data + viewclass: 'Row' + do_scroll_y: True + do_scroll_x: False + on_scroll_y: app.check_pull_refresh(self, grid) + + RecycleGridLayout: + id: grid + cols: 1 + size_hint_y: None + height: self.minimum_height + default_size: 0, 36 + default_size_hint: 1, None + + +: + _id: 0 + text: '' + canvas: + Line: + rectangle: self.pos + self.size + width: 0.6 +''' + + +class Application(App): + data = ListProperty([]) + refreshing = BooleanProperty() + + def build(self): + self.refresh_data() + return Builder.load_string(KV) + + def check_pull_refresh(self, view, grid): + """Check the amount of overscroll to decide if we want to trigger the + refresh or not. + """ + max_pixel = dp(200) + to_relative = max_pixel / (grid.height - view.height) + if view.scroll_y <= 1.0 + to_relative or self.refreshing: + return + + self.refresh_data() + + def refresh_data(self): + # using a Thread to do a potentially long operation without blocking + # the UI. + Thread(target=self._refresh_data).start() + + def _refresh_data(self): + self.refreshing = True + sleep(2) + update_time = datetime.now().strftime("%H:%M:%S") + + self.prepend_data([ + {'_id': i, 'text': '[{}] hello {}'.format(update_time, i)} + for i in range(len(self.data) + 10, len(self.data), -1) + ]) + self.refreshing = False + + def prepend_data(self, data): + self.data = data + self.data + + +if __name__ == "__main__": + Application().run()