elParaguayo
elParaguayo

Reputation: 1318

Dynamically sizing widgets depending on size of children

I've seen this question and answer which is very close to what I'm trying to achieve.

I'm looking to have a ScrollView which shows upcoming recordings on my MythTV box. There is a header widget (fixed size) which shows the day and a separate widget (BoxLayout) for the details of recording (shown in Label child widgets).

I need to size the BoxLayout depending on the height of the text. The issue here is that it isn't always the same Label that has the most text so the maximum height needs to take account of all children.

I have this in my KV language file:

<MythRecordingHeader>
    text: root.rec_date
    height: 25
    size_hint_y: None
    halign: "left"

<MythRecording>
    orientation: "horizontal"
    #height: 60
    height: max(mrec_desc.texture_size[1], mrec_time.texture_size[1], mrec_title.texture_size[1])
    size_hint_y: None

    BGLabel:
        id: mrec_time
        size_hint: 0.2, None
        text_size: self.width, None
        height: max(self.texture_size[1], mrec_title.texture_size[1], mrec_desc.texture_size[1])
        #size_hint_x: 0.2
        text: root.rec["time"]
        bgcolour: root.bg

    BGLabel:
        id: mrec_title
        size_hint: 0.3, None
        text_size: self.width, None
        height: max(self.texture_size[1], mrec_time.texture_size[1], mrec_desc.texture_size[1])
        #size_hint_x: 0.3
        text: "{}\n{}".format(root.rec["title"], root.rec["subtitle"])
        halign: "left"
        bgcolour: root.bg

    BGLabel:
        id: mrec_desc
        text: root.rec["desc"]
        size_hint: 0.5, None
        text_size: self.width, None
        height: max(self.texture_size[1], mrec_time.texture_size[1], mrec_title.texture_size[1])
        halign: "left"
        bgcolour: root.bg

(BGLabel is a custom widget that just adds a solid background colour to a Label via the bgcolour property).

and in my python file:

class MythRecording(BoxLayout):
    rec = DictProperty({})
    bg = ListProperty([0.1, 0.15, 0.15, 1])

    def __init__(self, **kwargs):
        super(MythRecording, self).__init__(**kwargs)
        self.rec = kwargs["rec"]

class MythRecordingHeader(BGLabel):
    rec_date = StringProperty("")

    def __init__(self, **kwargs):
        super(MythRecordingHeader, self).__init__(**kwargs)
        self.bgcolour = [0.1, 0.1, 0.4, 1]
        self.rec_date = kwargs["rec_date"]

This works almost as I expect - the BoxLayouts' heights do vary and, on the whole, show all the text but one or two times there's some clipping. It's not clear to me if that's due to the horizontal alignment.

I'm currently putting all of these children in a single BoxLayout.

However, my real problem is I need to get this inside a ScrollView (hence the link I referred to). To get the scrolling to work I think I need to set the height of the BoxLayout but I'm really struggling to calculate the height of this.

Looping over the children of the BoxLayout and looking at the height property just shows that MythRecordings have a height of 0.

Is there a way I can get the total height of all the children and set the BoxLayout's height so my scrollview will work correctly?

Upvotes: 1

Views: 433

Answers (1)

inclement
inclement

Reputation: 29450

Replace the BoxLayout with a GridLayout, and set:

size: self.minimum_size

The GridLayout's minimum_size property automatically tracks the size of its children.

Upvotes: 2

Related Questions