vertical AND horizontal scrolling in ListView?

328 views
Skip to first unread message

Bill Eaton

unread,
Sep 11, 2015, 12:36:57 AM9/11/15
to Kivy users support
I have data in a ListView that spills of the right edge of the screen. So I'd like to be able to scroll both vertically AND horizontally. In the documentation, it says that the ListView provides a "...vertical, scrollable,pannable list..."

In previous versions of Kivy (<= 1.8.0), I was able to put a ListView inside of a ScrollView to get horizontal scrolling. I'm up to 1.9.0 now and that strategy no longer works. I've been fooling around with it off and one for a few months now with no luck.

Would there be a straightforward way to roll my own version of a ListView that has horizontal scrolling built in? I see that there is a listview.py file in the dist-packages/kivy/uix directory of my Python install directory. Presumably I could copy this to make my own custom ListView. Honestly, that seems a little intimidating to me, but I'm desperate enough to try it at this point.

Here's an example of a ListView inside of a ScrollView that scrolls horizontally in 1.8.0, but not 1.9.0:

listview5.kv:
#:kivy 1.7
#:set fs '20sp'
#:set mfont 'DroidSansMono.ttf'

<Screen1>:
  id
: s1
  bottom_label
: bottom_label
  mylistview
: mylistview
  filter_text
: filter_text
 
BoxLayout:
    orientation
: 'vertical'
   
BoxLayout:
      orientation
: 'horizontal'
      size_hint_y
: 0.05
     
Button
        id
: clear_filter_button
        text
: 'X'
        halign
: 'center'
        size_hint_x
: 0.05
        on_press
: s1.clear_filter_button_press()
     
TextInput:
        id
: filter_text
        text
: ''
        halign
: 'center'
        size_hint_x
: 0.65
     
Button
        id
: filter_button
        text
: 'filter'
        halign
: 'center'
        size_hint_x
: 0.30
        on_press
: s1.filter_button_press()
   
ScrollView:
      size_hint_y
: 0.85
     
MyListView:
        id
: mylistview
        width
: 1.5*s1.width
        size_hint
: None, None
   
Label:
      id
: bottom_label
      size_hint_y
: 0.1
      text
: 'Bottom Label'


<TextInput>:
  text_size
: self.size
  auto_indent
: False
  multiline
: False
  padding
: [0,0,0,0]
  use_bubble
: False
  use_handles
: False
  font_name
: mfont
  font_size
: fs
  valign
: 'middle'
 
<Label>:
  text_size
: self.size
  font_name
: mfont
  font_size
: fs
  halign
: 'left'
  valign
: 'middle'

listview5.py:
from kivy.app import App
from kivy.core.window import Window
from kivy.properties import ObjectProperty
from kivy.uix.listview import ListView
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.utils import platform

states
= ['Alabama ', 'Alaska ', 'Arizona ', 'Arkansas ', 'California ',
         
'Colorado ', 'Connecticut ', 'Delaware ', 'Florida ', 'Georgia ',
         
'Hawaii ', 'Idaho ', 'Illinois ', 'Indiana ', 'Iowa ', 'Kansas ',
         
'Kentucky ', 'Louisiana ', 'Maine ', 'Maryland ', 'Massachusetts ',
         
'Michigan ', 'Minnesota ', 'Mississippi ', 'Missouri ','Montana ',
         
'Nebraska ', 'Nevada ', 'New Hampshire ', 'New Jersey ', 'New Mexico ',
         
'New York ', 'North Carolina ', 'North Dakota ', 'Ohio ', 'Oklahoma ',
         
'Oregon ', 'Pennsylvania ', 'Rhode Island ', 'South Carolina ',
         
'South Dakota ', 'Tennessee ', 'Texas ', 'Utah ', 'Vermont ',
         
'Virginia ', 'Washington ', 'West Virginia ', 'Wisconsin ', 'Wyoming ']

sm
= ScreenManager() # they say globals are evil, but avoiding them is hard in kivy


class MyListView(ListView):
 
#~ def __init__(self, **kwargs):
   
#~ super(MyListView, self).__init__(
       
#~ item_strings=states)
 
def update(self, filter = ''):
   
   
if filter == '':    
      mylist
= states
   
else:
      result
= []
     
for item in states:
       
if filter.lower() in item.lower():
          result
.append(item)
      mylist
= result
   
   
self.height = len(mylist)*25.4*1.2
   
self.item_strings = mylist
   
print('set list............................')

   
class Screen1(Screen):
 
def on_enter(self):
    filter_text
= ObjectProperty()
    mylistview
= ObjectProperty()
    bottom_label
= ObjectProperty()
   
self.filter_text.text = 'filter'
         
   
self.mylistview.update()
   
 
def filter_button_press(self):
    filter_text
= ObjectProperty()
    filter
= self.filter_text.text
   
self.mylistview.update(filter)
   
 
def clear_filter_button_press(self):
    filter_text
= ObjectProperty()
   
self.filter_text.text = ''
   
self.mylistview.update()

class ListView5App(App):
 
def build(self):
   
if platform == 'android':
     
pass
   
else:
     
Window.size = (364,596)
     
     
   
# Create the screen manager
   
global sm
    sm
.add_widget(Screen1(name='Screen1'))

   
return sm
   
if __name__ == '__main__':
   
ListView5App().run()




Bill Eaton

unread,
Sep 18, 2015, 12:05:03 AM9/18/15
to Kivy users support
I wonder if there is a way to make sure scroll events fall through some widgets and reach others? What if I could make sure my ListView gets y scroll events and it's container gets x scroll events? Would that work?

On a different note, I managed to get some scrolling in both axes, but it's not really usable.
If I set
  do_scroll_x: False
  do_scrolly_y: False
For the ListView, and the true for a ScrollView container. Then I can get the Scrollview to scroll x and y. But the only way to make it work is to scroll x first so the ListVIew hangs off the screen and there is a small gap on the left. Then mouse/touch down on that gap and scroll in y.

I can't really do anything useful with this.
Reply all
Reply to author
Forward
0 new messages