Search code examples
kivykivy-language

Can't alter size of BoxLayouts in ScrollView Kivy


I'm having trouble spacing my BoxLayouts out on the below screen. I have to put size_hint_y: None for each of the BoxLayouts otherwise everything overlaps each other. However, I can't work out how to change the size so I have just set them all to None or 1. The image is also overlapping the MDTextField first name.

I'm not sure what I'm doing wrong

import kivy
from kivymd.app import MDApp
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.lang import Builder
from kivymd.uix.selectioncontrol import MDCheckbox
from kivy.uix.gridlayout import GridLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.image import Image
from kivy.uix.label import Label
from kivymd.uix.label import MDLabel
from kivymd.uix.button import MDRaisedButton
from kivy.core.window import Window

Window.size = (381, 470)
Window.clearcolor = (1,1,1,1)

class UserDetails(Screen):
    pass


class WindowManager(ScreenManager):
    pass


class MyApp(MDApp):
    def build(self):
        kv = Builder.load_file("kivy.kv")
        self.sm = WindowManager()

        screens = [UserDetails(name="user_details")]
        for screen in screens:
            self.sm.add_widget(screen)

        self.sm.current = "user_details"
        return self.sm
<UserDetails>
    name: "user_details"

    GridLayout:
        cols: 1
        ScrollView:
            id: grid
            BoxLayout:
                orientation: 'vertical'
                id: layout
                padding: 15
                spacing: 15
                size_hint: 1, None
                height: self.minimum_height
                BoxLayout:
                    size_hint_y: None
                    orientation: "vertical"
                    MDLabel:
                        size_hint_y: 1
                        halign: "center"
                        text: "PERSONAL DETAILS"
                        canvas.before:
                            Color:
                                rgba: 1,0,0,1
                            Rectangle:
                                size: self.size
                                pos: self.pos
                BoxLayout:
                    size_hint_y: None
                    AsyncImage:
                        source: "image.png"
                BoxLayout:
                    size_hint_y: 1
                BoxLayout:
                    size_hint_y: None
                    cols: 1
                    orientation: "vertical"
                    padding: 15
                    MDTextField:
                        id: first_name
                        hint_text: "First Name"
                    MDTextField:
                        id: last_name
                        hint_text: "Last Name"
                    MDTextField:
                        id: date_of_birth
                        hint_text: "Date of Birth"
                BoxLayout:
                    size_hint_y: None
                    MDCheckbox:
                        group: "gender"
                        id: male
                    MDCheckbox:
                        group: "gender"
                        id: female
                    MDCheckbox:
                        group: "gender"
                        id: unknown
                BoxLayout:
                    size_hint_y: None
                    cols: 1
                    Label:
                    MDRaisedButton:
                        pos_hint: {"top": 0.8}
                        md_bg_color: 1,0,0,1
                        text: "Submit"
                    Label:

Solution

  • When you use size_hint_y: None and height: self.minimum_height for a BoxLayout, then the height of the BoxLayout is calculated by summing the heights of the children. A child with size_hint_y: None and no value set for height will get counted as 0 toward the minimum height of the BoxLayout. So you need to set heights for all the children.

    Also, you have several case where you have a Layout with just one child. You can normally replace that arrangement with just the child.

    Here is how I would modify your kv:

    <UserDetails>
        name: "user_details"
        
        ScrollView:
            id: grid
            BoxLayout:
                orientation: 'vertical'
                id: layout
                padding: 15
                spacing: 15
                size_hint: 1, None
                height: self.minimum_height
                MDLabel:
                    size_hint_y: None
                    height: self.texture_size[1]
                    halign: "center"
                    text: "PERSONAL DETAILS"
                    canvas.before:
                        Color:
                            rgba: 1,0,0,1
                        Rectangle:
                            size: self.size
                            pos: self.pos
                AsyncImage:
                    size_hint_y: None
                    height: 100
                    source: "image.png"
                BoxLayout:
                    size_hint_y: None
                    height: self.minimum_height
                    cols: 1
                    orientation: "vertical"
                    padding: 15
                    MDTextField:
                        id: first_name
                        hint_text: "First Name"
                        size_hint_y: None
                        height: 50
                    MDTextField:
                        id: last_name
                        hint_text: "Last Name"
                        size_hint_y: None
                        height: 50
                    MDTextField:
                        id: date_of_birth
                        hint_text: "Date of Birth"
                        size_hint_y: None
                        height: 50
                BoxLayout:
                    size_hint_y: None
                    height: 40
                    MDCheckbox:
                        group: "gender"
                        id: male
                    MDCheckbox:
                        group: "gender"
                        id: female
                    MDCheckbox:
                        group: "gender"
                        id: unknown
                MDRaisedButton:
                    size_hint_y: None
                    height: 40
                    pos_hint: {'center_x':0.5}
                    md_bg_color: 1,0,0,1
                    text: "Submit"