Search code examples
pythonkivykivy-languagekivymd

Adding ScrollView in MDCard Kivy


I am trying to add ScrollView in my First Screen but unfortunately I failed to do so.

I have tried many times by changing layouts, adding new layout etc etc..

I just want is to ScrollView to those ElementCard so that if I add more I can reach then by scrolling.

I am adding a piece of my code which will help you to how I have arranged the layouts..

Code:


from kivy.lang import Builder
from kivymd.app import MDApp
from kivy.uix.screenmanager import Screen,ScreenManager
from kivy.core.window import Window #You must import this
Window.size = (350, 600)
kv = '''
#:import get_color_from_hex kivy.utils.get_color_from_hex
ScreenManager:
    First:
    
<First>:
    name:'first'
    MDToolbar:
        title: "CATALYST"
        id:toolbar
        elevation: 10
        pos_hint: {'top':1.0}
        md_bg_color: 200/255,10/255,30/255,1

    MDBoxLayout:
        size_hint: 1, 0.9
        orientation : 'vertical'
        MDScreen:
            MDBottomNavigation:
                panel_color: 200/255,10/255,30/255,1
                text_color_active: 0,0,0,1
                pos_hint: {'x':0, 'y':0}
                text_color_normal: 0/255,0/255,0/255,0.4
                MDBottomNavigationItem:
                    name: 'screen 1'
                    text: 'Study'
                    icon: 'creation'
                    badge_icon: "numeric-10"
                    MDScreen:
                        md_bg_color:56/255,40/255,81/255,1
                        MDBoxLayout:
                            orientation:'vertical'
                            MDGridLayout:
                                cols:1
                                padding:[dp(15),dp(15),dp(15),dp(35)]
                                spacing:dp(15)
                                ElementCard:
                                    image: 'library-2.jpg'
                                    text:"Digital Library"
                                    subtext:""
                                    items_count:"Gov Of India"                                 
                                ElementCard:
                                    image : 'college.jpg'
                                    text:"Top Colleges"
                                    subtext:""
                                    items_count:"Worldwide"
                                ElementCard:
                                    image: 'settings.jpg'
                                    text:"Settings"
                                    subtext:""
                                    items_count:"4 Items"

                MDBottomNavigationItem:
                    name: 'screen 2'
                    text: 'Chat'
                    icon: 'chat'
                    badge_icon: "numeric-5"
                    MDLabel:
                        text: 'Chat'
                        halign: 'center'

<ElementCard@MDCard>:
    #md_bg_color:69/255,55/255,86/255,1
    padding:dp(15)
    spacing:dp(15)
    radius:dp(25)
    ripple_behavior: True
    image:''
    text:""
    items_count:""
    subtext:''
    orientation:'vertical'
    MDBoxLayout:
        Image:
            source:root.image
        MDBoxLayout:
            orientation:'vertical'
            MDLabel:
                halign:"center"
                text:root.text
                font_style:"H6"
            MDLabel:
                halign:"center"
                font_style:"Caption"
                text:root.subtext
            MDLabel:
                halign:"center"
                text:root.items_count

'''
class First(Screen):
    pass
    
sm = ScreenManager()
sm.add_widget(First(name='first'))

class Test(MDApp):
    def build(self):
        self.title = 'Catalyst'
        self.theme_cls.primary_palette = "Red"
        # self.theme_cls.theme_style = "Dark"
        self.root = Builder.load_string(kv)
        
Test().run()

Thanks in Advance :)


Solution

  • Your kv seems to be overly complicated. In your First Screen you have a MDBoxLayout containing a MDScreen, containing a MDBottomNavigation, containing a MDBottomNavigationItem, containing a MDScreen, containing a MDBoxLayout, containing a MDGridLayout. Unless there are reasons that are not apparent from your code, I would suggest simplifying that kv.

    And when you use ScrollView, you need its child to use adaptive_height: True (for vertical scrolling). And when using adaptive_height: True, the children of that widget must have explicit height values (size_hint_y set to None for vertical scrolling).

    So here is a simplified version of your kv with a ScrollView and explicit height values where needed:

    #:import get_color_from_hex kivy.utils.get_color_from_hex
    ScreenManager:
        First:
    
    <First>:
        name:'first'
        MDToolbar:
            title: "CATALYST"
            id:toolbar
            elevation: 10
            pos_hint: {'top':1.0}
            md_bg_color: 200/255,10/255,30/255,1
    
        MDBoxLayout:
            size_hint: 1, 0.9
            orientation : 'vertical'
            MDBottomNavigation:
                panel_color: 200/255,10/255,30/255,1
                text_color_active: 0,0,0,1
                pos_hint: {'x':0, 'y':0}
                text_color_normal: 0/255,0/255,0/255,0.4
                MDBottomNavigationItem:
                    md_bg_color:56/255,40/255,81/255,1
                    name: 'screen 1'
                    text: 'Study'
                    icon: 'creation'
                    badge_icon: "numeric-10"
                    ScrollView:
                        MDBoxLayout:
                            orientation:'vertical'
                            adaptive_height: True
                            padding:[dp(15),dp(15),dp(15),dp(35)]
                            spacing:dp(15)
                            ElementCard:
                                image: 'library-2.jpg'
                                text:"Digital Library"
                                subtext:""
                                items_count:"Gov Of India"                                 
                            ElementCard:
                                image : 'college.jpg'
                                text: "Top Colleges"
                                subtext:""
                                items_count:"Worldwide"
                            ElementCard:
                                image: 'settings.jpg'
                                text:"Settings"
                                subtext:""
                                items_count:"4 Items"
                MDBottomNavigationItem:
                    name: 'screen 2'
                    text: 'Chat'
                    icon: 'chat'
                    badge_icon: "numeric-5"
                    MDLabel:
                        text: 'Chat'
                        halign: 'center'
    
    <ElementCard@MDCard>:
        #md_bg_color:69/255,55/255,86/255,1
        padding:dp(15)
        spacing:dp(15)
        radius:dp(25)
        ripple_behavior: True
        image:''
        text:""
        items_count:""
        subtext:''
        orientation:'vertical'
        size_hint_y: None
        height: box.height + self.padding[1] + self.padding[3]
        MDBoxLayout:
            id: box
            adaptive_height: True
            Image:
                source:root.image
            MDBoxLayout:
                orientation:'vertical'
                adaptive_height: True
                MDLabel:
                    halign:"center"
                    text:root.text
                    font_style:"H6"
                MDLabel:
                    halign:"center"
                    font_style:"Caption"
                    text: root.subtext
                MDLabel:
                    halign:"center"
                    text: root.items_count
    

    Not part of the problem, but the lines:

    sm = ScreenManager()
    sm.add_widget(First(name='first'))
    

    should be eliminated. The ScreenManager and its child are build by the call to Builder.load)string().