Search code examples
pythonkivykivymd

Is it possible to set the radius value in a ScrollView in Python/Kivy?


I need a rounded scrollview that rounds along with the children, I did a lot of research on this but failed, I didn't find anything about it.

Something like:

ScrollView:
    do_scroll: [False, True]
    radius: [dp(30),]
    MDList:
        id: list

This does not round the scrollview. Any idea how I can do thiswithout adding the RoundedRectangle chart?

Edit:

Adding the RoundedRectangle graph looks good, but it doesn't solve my problem. It is as if the children of the ScrollView exceeds the radius, the children do not fit in the radius.

ScrollView Code:

<RoundedScrollView@ScrollView>:
    canvas.before:
        Color:
            rgba: 1, 0, 0, 1
        RoundedRectangle:
            pos: self.pos
            size: self.size
            radius: [0, 0, dp(80), 0]

Where I used ScrollView:

Screen:
    RoundedSrollView:
        MDList:
            id: list
            radius: [0, 0, dp(80), 0] #does not work

Result:

enter image description here


Solution

  • Well... After a long time (literally) I found a solution to define a radius to a ScrollView that automatically cuts the child. The solution is to redraw the ScrollView clipping using the canvas instructions StencilPush , StencilUse , StencilUnUse and StencilPop.

    main.py

    from kivymd.app import MDApp
    from kivy.lang import Builder
    
    KV = """
    MDScreen:
        MDScrollView:
            do_scroll: [False, True]
            size_hint: .5, .5
            pos_hint: {"center":[.5, .5]}
    
            canvas.before:
                StencilPush
                RoundedRectangle:
                    pos: self.pos
                    size: self.size
                    radius: [dp(50),]
                StencilUse
    
            canvas.after:
                StencilUnUse
                StencilPop
    
            MDBoxLayout:
                adaptive_height: True
                size_hint_y: None
    
                MDLabel:
                    text:
                        'The ScrollView accepts only one child and applies a viewport' \
                        '/window to it according to the scroll_x and scroll_y properties.' \
                        ' Touches are analyzed to determine if the user wants to scroll or' \
                        ' control the child in some other manner: you cannot do both at the' \
                        ' same time. To determine if interaction is a scrolling gesture,' \
                        ' these properties are used:'
                    adaptive_height: True
    """
    
    class MyApp(MDApp):
        def build(self):
            return Builder.load_string(KV)
    
    MyApp().run()
    

    StencilPush is being used to save the current state of the Stencil and below it a rounded rectangle with the same dimensions and size as the ScrollView is being drawn.

    StencilUse defines that this rounded rectangle will be the current Stencil.

    After all the modifications have been made it is necessary to clean the "old" Stencil and set the modified Stencil as the default that was made under StencilPush. This is done using the StencilUnUse instruction and then the finalization, StencilPop, it is not mandatory but this ensures that all states are cleared and that performance is not affected.