Making a layout that automaitcally has the correct spacing

Question:

How do I create a layout object (BoxLayout, GridLayout etc…) where If I pass it x objects and the layout object has a height of y then it automatically assigns a space between objects so that they are all evenly spaced out.

I tried to follow Kivy Layout height to adapt to child widgets's height but I wasn’t able to get it to work.

Though I should be able to calculate the space myself I a) couldn’t even get this to work and b) I want a layout that will be relatively flexible.

Each button I have is as follows:

class BoxButton(MDCard):
    """Button to click on that can take other objects"""

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.size_hint = (None, None)
        self.size = ("200dp", "100dp")
        self.pos_hint = {"center_x": 0.5}
        self.size_hint_y = None

And the layout box is being given the full size of the screen.

How can I get a layout that just auto-adjusts the spacing between objects?
Thanks

Asked By: Oliver Brace

||

Answers:

This works. You pass in the objects you want to display and then it adds in an object that does the spacing for you. Seems like a workaround but it does work.

from kivymd.app import MDApp
from kivymd.uix.boxlayout import MDBoxLayout
from kivymd.uix.card import MDCard

from kivy.metrics import dp


class GapLayout(MDBoxLayout):
    def __init__(self, widgets, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.orientation = "vertical"
        gap_height = 0

        widgets_height = 0
        for widget in widgets:
            widgets_height += widget.height

        def update_gap_height(instance, value):
            nonlocal gap_height
            available_height = self.height - widgets_height
            gap_height = (
                available_height / (len(widgets)+1)
            )  # Divide by the number of gaps
            update_layout()

        def update_layout():
            self.clear_widgets()
            for widget in widgets:
                self.add_widget(widget)

                # Add the gap between cards
                gap = MDBoxLayout(size_hint=(1, None), height=gap_height)
                self.add_widget(gap)

        self.bind(size=update_gap_height)

        update_gap_height(self, self.size)

So for example:

class TestApp(MDApp):
    def build(self):
        card1 = MDCard(size_hint=(1, None), height=dp(10), md_bg_color=[0, 0, 0, 1])
        card2 = MDCard(size_hint=(1, None), height=dp(10), md_bg_color=[0, 0, 0, 1])
        card3 = MDCard(size_hint=(1, None), height=dp(10), md_bg_color=[0, 0, 0, 1])
        card4 = MDCard(size_hint=(1, None), height=dp(10), md_bg_color=[0, 0, 0, 1])

        root = GapLayout([card1, card2, card3, card4])
        return root
Answered By: Oliver Brace
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.