-1

I have a nested horizontal scroll view inside a vertical scroll view, I followed many links, found nothing, I need a clear scrollview so that if I scroll nested horrizontal scrollview it will scroll without disturbing the parent vertical scrollview, and if I scroll the nested horrizontal scrollview vertically then only the parent vertical scroll view will scroll! any suggestions ? thanks in advance! (I want the scroll view to be same as any other modern app like facebook story horizontal scrollview,, etc..)

  • 2
    Can you please provide the code you have tried? So we can help you . – Fadi Abu Raid Oct 21 '20 at 19:48
  • I followed this code so far: https://github.com/glins97/ScrollView – Fadi Sadaka Oct 21 '20 at 20:01
  • Modern apps like facebook doesn't use scroll view it changes the screen with transition. refer to https://www.youtube.com/watch?v=u3Ue6IlzbOE – Fadi Abu Raid Oct 21 '20 at 20:02
  • then this link was a modification to .py I sent , they are discussing of fixing it! (https://github.com/kivy/kivy/pull/6252), say not modern apps, I just want the same type of nested scrollview all apps are using! – Fadi Sadaka Oct 21 '20 at 20:05
  • @FadiAbuRaid this link you sent is about screens and screen manager, I am asking about nested scrollviews (horrizontal scrollview inside vertical scrollview) – Fadi Sadaka Oct 21 '20 at 20:06
  • in the 1st link I provided in this scrollview.py, something must be done either on on_touch_move method or on_scroll_move method, but I believe must be on on_touch_move method, python language: if on_touch_move is done on the horrizontal scroll, if it is vertical then dont pass the touch to the child (nested horizontal scrollview) if it is horrizontal(then pass the touch to the child(nested horizontal scrollview) – Fadi Sadaka Oct 21 '20 at 20:10
  • you see how is he scrolling in this video: https://www.youtube.com/watch?v=ocvtvpU5AOI I want like that in python, if he pushes the mouse click down and up the nested scrollview(horizontal one) will not move, but if he pushes the click horizontally only the nested scroll view(horizontal) will move not the vertical parent scrollview – Fadi Sadaka Oct 21 '20 at 20:32

2 Answers2

0

This is how you can achieve what you are looking for.

Use KivyMD to get material design for your app. https://kivymd.readthedocs.io/en/latest/index.html

Then try this

scrollview.py

from kivymd.app import MDApp
from kivy.clock import Clock
from kivy.lang import Builder
from kivy.uix.button import Button
from kivy.uix.scrollview import ScrollView
from kivy.core.window import Window

class MyScrollView(ScrollView):
    def on_touch_down(self, touch):
        # get touch position in coordinates of the main_box (parent of inner_scroll)
        x,y = self.ids.main_box.to_widget(*self.to_window(*touch.pos))

        # if converted position is within the inner_scroll, send touch to the inner_scroll
        if self.ids.inner_scroll.collide_point(x,y):
            touch.pos = (x,y)   # change touch position to coordinates in main_box
            return self.ids.inner_scroll.on_touch_down(touch)   # call on_touch of inner_scroll
        else:
            return super(MyScrollView, self).on_touch_down(touch)

class ScrolltwoApp(MDApp):
    
    def build(self):
        app=MDApp.get_running_app()
        Clock.schedule_once(self.add_members)
        return app.root
    
    def add_members(self,dt):
        app=MDApp.get_running_app()
        for i in range(15):
            app.root.ids.main_box.add_widget(Button(text='button'+str(i), size_hint=(1.0, None), height=50,background_color=[0,0,1,1]))
            app.root.ids.horizontal_grid.add_widget(Button(text='button' + str(i), size_hint=(None, None),height=130,width=100,background_color=[0,0,1,1]))
            app.root.ids.horizontal_grid2.add_widget(Button(text='button' + str(i), size_hint=(None, None),height=130,width=100,background_color=[0,0,1,1]))

if __name__ == '__main__':
    Window.show_cursor = True
    Window.size = (360, 680)
    ScrolltwoApp().run()

scrolltwo.kv

#: import Window kivy.core.window.Window
MyScrollView:
    bar_width: 5
    scroll_type:['bars', 'content']
    do_scroll: (False, True)
    size_hint_y: None
    height: Window.height
    GridLayout:
        id: main_box
        size_hint_y: None
        cols: 1
        height: self.minimum_height
        ScrollView:
            id: inner_scroll
            bar_width: 5
            scroll_type: ['bars', 'content']
            do_scroll: (True, False)
            size_hint_y: None
            effect_cls: "ScrollEffect"
            height: Window.height/4.5
            GridLayout:
                id: horizontal_grid
                rows: 1
                padding: [10, 10]
                size: self.minimum_size
                size_hint: None, None
        ScrollView:
            id: inner_scroll2
            bar_width: 5
            scroll_type: ['bars', 'content']
            do_scroll: (True, False)
            size_hint_y: None
            effect_cls: "ScrollEffect"
            height: Window.height/4.5
            GridLayout:
                id: horizontal_grid2
                rows: 1
                padding: [10, 10]
                size: self.minimum_size
                size_hint: None, None

Output

enter image description here

Fadi Abu Raid
  • 831
  • 5
  • 13
  • in the file you sent, the 1st 2 rows buttons, I can horrizontally scroll, but I cannot vertically scroll such as the bottom buttons! , what I want is, a scrolling the screen horrizontally if scrolled down or up from these horrizontal buttons without disturbing them – Fadi Sadaka Oct 23 '20 at 08:00
  • Well this is not a coding service I have regenerated what you have shown in the video https://www.youtube.com/watch?v=ocvtvpU5AOI and you have to do your bit to customize it to your liking. – Fadi Abu Raid Oct 23 '20 at 09:34
  • wait in this code you sent, can I do scroll y from the top horrizontal scrollviews ? I tried in my program python 3.8 it is not – Fadi Sadaka Oct 28 '20 at 08:36
  • I will post a gif image to show you what does it do. – Fadi Abu Raid Oct 28 '20 at 12:25
  • yah so I got the same, , you see that 1st row, in this app you sent, these horizontal scrollview, you can smoothly scroll x right ? that is good, but I want that if you scroll y from it the window will scroll down while it will not scroll_x , I believe you understood me – Fadi Sadaka Oct 28 '20 at 19:06
  • I don't get you – Fadi Abu Raid Oct 28 '20 at 19:43
  • say the user wants to scrolldown in the screen, suppose he holds his finger on the horizontal scroll trying to scroll down, in your case it is not working, suppose it worked, how can I deactivate horizontal scrolling when the user scrolls parent vertical scrolling from that horizontal scroll position!, I dont think you will get me , go to any modern app and check their nested horizontal scrollviews – Fadi Sadaka Oct 29 '20 at 16:14
  • check this question, this is my issue!! https://stackoverflow.com/questions/57900718/how-to-have-nested-scrollviews-and-have-both-horizontal-and-vertical-work-in-kiv?noredirect=1&lq=1 – Fadi Sadaka Oct 29 '20 at 16:17
  • But also say it worked to scroll both sides, I want to disable horizontal scrolling if the user scrolls vertically, and versa vice! – Fadi Sadaka Oct 29 '20 at 16:23
0

I understand you and had the same problem trying to scroll horizontal scrollview vertically, which it should scroll the vertical parent scrollview instead.

I peeked into the source code of scrollview and found out the child scrollview stops propogating move event to parent when it receives touchmove.

Here's a demo of the solution (some hacks) that allows you to scroll horizontal scrollview vertically that affects parent scrollview.

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.lang.builder import Builder
from kivy.uix.scrollview import ScrollView
from kivy.properties import StringProperty

KV = """
<SomeText>
    id: some_text
    orientation: 'horizontal'
    ScrollText:
        Label:
            text: some_text.text
            max_lines: 1
            halign: 'left'
            padding_x: 20
            font_size: some_text.height
            width: self.texture_size[0]
            size_hint_x: None


<ScrollText>
    bar_color: (1,1,1,1)
    bar_width: 1

<VerticalScroll>
    some_text_list: some_text_list
    GridLayout:
        id: some_text_list
        cols: 1
        size_hint_y: None
        row_default_height: 80
        row_force_default: True
        height: self.minimum_height
"""

class SomeText(BoxLayout):
    text = StringProperty()
    

class ScrollText(ScrollView):
    # pass y-move event to parent instead of stopping
    def on_scroll_move(self, touch):
        super().on_scroll_move(touch)
        touch.ud['sv.handled']['y'] = False 

class VerticalScroll(ScrollView):
    def __init__(self, texts, **kwargs):
        super().__init__(**kwargs)
        for text in texts:
            self.some_text_list.add_widget(SomeText(text=text))

    # prevent stuck on overscroll
    def on_scroll_stop(self, touch, check_children=True):
        super().on_scroll_stop(touch, check_children=False)

if __name__ == "__main__":
    class TestApp(App):
        def build(self):
            Builder.load_string(KV)
            long_text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
            texts = [long_text for _ in range(20)]
            return VerticalScroll(texts)
    TestApp().run()

Pendechosen
  • 1
  • 1
  • 1