Help with recycleview

59 views
Skip to first unread message

Matheus Baumgarten

unread,
Jun 20, 2020, 11:50:29 PM6/20/20
to Kivy users support
Hey group,

Is there an easy way of finding some specific nodes in the recycleview? Like iterating through some list or something? (The recycleview could have loads of data, so using loops would freeze the app? Maybe?)

I would like to have a textInput so the user could search for specific data in the recycleview. When the user validates text or clicks a button the nodes with corresponding text should come to the top of the list.

I was using a boxlayout with labels and buttons instead of recycleview but generating all those widgets was causing the app to freeze, so I looked around a bit and found out about recycleview, tested it a little and it worked great. But still I don't really know how the recycleview stuff properly works...

Any help is greatly appreciated!

Thanks,
Matheus Baumgarten.

Elliot Garbus

unread,
Jun 21, 2020, 8:18:50 AM6/21/20
to kivy-...@googlegroups.com

The recycle view will only create as many widgets as you can see at once, then creates the illusion of scrolling through them by recycling those widgets by reusing the widgets with new data applied.

 

The data for the recycle view is a list of dicts.  Search and sort, I suggest the following: 

Sort the recycleview data list based on the user search criteria. 

Call refresh_from_data.  https://kivy.org/doc/stable/api-kivy.uix.recycleview.html?highlight=refresh_from_data#kivy.uix.recycleview.RecycleViewBehavior.refresh_from_data

Use scroll_y to move the widgets to the top (set to 1 to move to the top) : https://kivy.org/doc/stable/api-kivy.uix.scrollview.html?highlight=scroll_y#kivy.uix.scrollview.ScrollView.scroll_y

 

Below is an example I put together to help another user that uses the keys up, down and delete to manipulate a Recycle view.  This does not do what you are looking for – but shows how the pieces are used, so should be a useful start.

 

"""
Use up, down and delete keys to navigate a RecycleView
"""

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import StringProperty, ListProperty
from kivy.uix.recycleview import RecycleView
from kivy.core.window import Window

kv =
"""
<ThreeLabel>:
    canvas:
        Color:
            rgba: root.highlight_color
        Rectangle:
            size: self.size
            pos: self.pos
    padding: 20,0
    Label:
        text: root.song
    Label:
        text: root.album
    Label:
        text: root.artist

TestBox:
    orientation: 'vertical'
    Label:
        text: 'Song List'
        size_hint_y: .1
    TextInput:
        hint_text: 'Click here and the keyboard is released'
        size_hint_y: None
        height: 30
        multiline: False
    BoxLayout:
        Label:
            text: 'Preview art here'  # Just a place holder, note keyboard is released when clicking on a TextInput
        TouchRecycleView:
            id:rv
            viewclass: 'ThreeLabel'
            data: root.rv_data_list
            scroll_type: ['bars','content']
            bar_inactive_color: 1,1,1,1
            bar_width: dp(20)
            do_scroll_x: False
            RecycleBoxLayout:
                id: rbl
                key_selection: 'song'
                default_size: None, dp(56)
                default_size_hint: 1, None
                size_hint_y: None
                height: self.minimum_height
                orientation: 'vertical'
"""


class TouchRecycleView(RecycleView):
   
def __init__(self, **kwargs):
       
super().__init__(**kwargs)
       
self._keyboard = None
       
self.index = None  # the index into self.data

   
def on_touch_up(self, touch):
        app = App.get_running_app()
       
if self.collide_point(*touch.pos):
           
if not self._keyboard:
               
self._keyboard = Window.request_keyboard(self._keyboard_closed, self)
               
self._keyboard.bind(on_key_down=self._on_keyboard_down)
           
self.index = app.root.ids.rbl.get_view_index_at(self.to_local(*touch.pos))  # index based on touch
           
self.highlight()
       
return super().on_touch_up(touch)

   
def _keyboard_closed(self):
       
print('keyboard closed!')
       
self._keyboard.unbind(on_key_down=self._on_keyboard_down)
       
self._keyboard = None
       
self.remove_highlight()

   
def _on_keyboard_down(self, keyboard, keycode, text, modifiers):
       
# self.view_adapter.views dict k is index, v is widget of visible widgets
       
if self.index not in list(self.view_adapter.views):
           
return  # if selected widget out of view, ignore keys
       
if keycode[1] == 'down':
           
self.next_item()
       
elif keycode[1] == 'up':
           
self.prev_item()
       
elif keycode[1] == 'delete':
           
self.delete_song()

   
def next_item(self):
        view_widgets =
list(self.view_adapter.views)  # the indices in the current view
       
pos_in_view = view_widgets.index(self.index)  # position in the current view
       
if self.index > len(self.data) - len(view_widgets):  # if in last page of data go to bottom
           
self.scroll_y = 0
       
elif pos_in_view > len(view_widgets) - 3# if near the bottom of the list, scroll
           
self.scroll_y -= len(view_widgets) / len(self.data)
       
self.index = min(self.index + 1, len(self.data) - 1# increment, but not past the end
       
self.highlight()

   
def prev_item(self):
        view_widgets =
list(self.view_adapter.views)
        pos_in_view = view_widgets.index(
self.index)
       
if self.index < len(view_widgets):
           
self.scroll_y = # if in first page of data go to top
       
elif pos_in_view < 2# if near top of visible list, scroll
           
self.scroll_y += len(view_widgets) / len(self.data)
       
self.index = max(0, self.index - 1) # decrement, but not lower that zero
       
self.highlight()

   
def delete_song(self):
       
if not self.data:  # if the list is empty, do nothing
           
return
        del
self.data[self.index]
       
self.refresh_from_data()
       
self.index = max(0, self.index - 1)
       
self.highlight()

   
def highlight(self):
       
if not self.data:   # if the list is empty, do nothing
           
return
        for
d in self.data:
            d[
'highlight_color'] = (0, 0, 0, 1)
       
self.data[self.index]['highlight_color'] = (.8, .8, .8, 1)
       
self.refresh_from_data()

   
def remove_highlight(self):
       
for d in self.data:
            d[
'highlight_color'] = (0, 0, 0, 1)
       
self.refresh_from_data()

class ThreeLabel(BoxLayout):
    song = StringProperty()
    album = StringProperty()
    artist = StringProperty()
    highlight_color = ListProperty()


class TestBox(BoxLayout):
    rv_data_list = ListProperty([{
'song': f'song_{n}',
                                 
'album': f'album_{n}',
                                 
'artist': f'artist_{n}',
                                 
'highlight_color': [0, 0, 0, 1]} for n in range(50)])


class RVTestApp(App):
   
def build(self):
       
return Builder.load_string(kv)


RVTestApp().run()

--

You received this message because you are subscribed to the Google Groups "Kivy users support" group.

To unsubscribe from this group and stop receiving emails from it, send an email to kivy-users+...@googlegroups.com.

To view this discussion on the web visit https://groups.google.com/d/msgid/kivy-users/9f54230c-bd42-4f42-8f8f-4237736d7414o%40googlegroups.com.

 

Matheus Baumgarten

unread,
Jun 21, 2020, 9:56:54 AM6/21/20
to Kivy users support
Thank you very much! I think I understand it now.

So, I just have to sort the data list of dicts and call refresh_from_data() then set the scroll to the top. That seems to be a very good approach and since its a list of dictionaries it won't take that long to traverse.

Thanks again, you helped a lot!

Best regards,
Matheus Baumgarten.

vishnu vijay

unread,
Aug 26, 2020, 1:58:55 PM8/26/20
to Kivy users support
Hi, 

Could we bind keyboard up, down, right, left keys with the widget: TextInput for focusing in recycleview. I tired to replicate the above example with receiving super attribute error. 

please suggest with an example. 


thanks! 
Reply all
Reply to author
Forward
0 new messages