0
votes

I have a ListView with a simple model which in turn also has a model which is actually displayed:

ListView {
    Component.onCompleted: console.log("ListView height: " + height)
    model: ["1"]
    delegate: Column {
        Component.onCompleted: console.log("Inner delegate height: " + height)
        Repeater {
            model: ["A", "B"]
            delegate: Text {
                Component.onCompleted: console.log("Text height: " + height)
                text: modelData
            }
        }
    }
}

I can get the Text and the Column height. Even though ListModel knows the Column height, it still has zero height.

My question is: how to properly assign ListView the given size?

The program outputs:

qml: Text height: 14
qml: Text height: 14
qml: Inner delegate height: 28
qml: ListView height: 0
1
I don't think ListView adjusts its height to fit content. Since ListView derived from Flickable it have to be contentHeight, not height. So you have to set size of ListView manually, with anchors or layoutsfolibis
By the way, why using ListView here? Just put the Column in a Flickable. Shorter, simpler code with the same visual outcome.BaCaRoZzo
Thank you very much for your suggestions. Inspired by them, I expanded the code and posted it below.szotsaki
@BaCaRoZzo: in the real-world scenario I need many nested loops and I think implementing the solution with a ListView will be easier. The example in the question was a bit unfortunate to show only one item, 1, in the outer model.szotsaki
I see. Well, I've underestimated the problem and that's my fault. Good to know that you solved the issue. :)BaCaRoZzo

1 Answers

1
votes

Based on @folibis' suggestion, I changed the contentHeight and contentWidth properties when the delegate's height or width changes. After adding anchors to ListView, it perfectly works together with the encompassing item.

Here is the code:

ListView {
    anchors.fill: parent
    model: ["1", "2"]
    delegate: Column {
        onHeightChanged: ListView.view.contentHeight = height
        onWidthChanged: ListView.view.contentWidth = width
        Repeater {
            model: ["A", "B", "C", "D"]
            delegate: Text {
                text: modelData
            }
        }
    }
}

Inspired by @BaCaRoZzo's comment, if one would not need a ListView, the problem can solved without it:

Flickable {
    id: flickable
    anchors.fill: parent
    Column {
        Repeater {
            model: ["1", "2"]
            Column {
                onHeightChanged: flickable.contentHeight = height
                onWidthChanged: flickable.contentWidth = width
                Repeater {
                    model: ["A", "B", "C", "D"]
                    delegate: Text {
                        text: modelData
                    }
                }
            }
        }
    }
}