QML 交错(砌体)GridView 或 Flow

QML Staggered (Masonry) GridView or Flow

我遇到了以下问题中提出的相同问题:

How does one create a staggered grid view in QML?

我希望以 Masonry 风格实现 Flow GridLayoutGridView,请参阅当前输出和所需的附加图片。

当前:

期望:

我不想为此使用外部库;而是纯粹使用 QML 和 JavaScript.

我已经尝试过一些东西,比如 Flickable 中的 Flow:

Flickable
{
    anchors.fill: parent
    anchors.margins: 5
    contentHeight: flow.height

    Flow {
        id: flow
        width: parent.width
        height: 800
        spacing: 10
        flow: Flow.TopToBottom
        Repeater{
            model: [80,60,120,75,90,55,140,50,70,90,80,60,120,75,90]
            Rectangle {
                height: modelData
                width: 100
                border.color: "black"
            }
        }
    }
}

还有我的 GridLayout 使用 preferredHeightfillHeight:

Layout.fillWidth: true
Layout.fillHeight: true
Layout.preferredWidth: Layout.columnSpan
Layout.preferredHeight: Layout.rowSpan

然而,两者都存在将 rowHeight 设置为每行最高对象的问题。

我的问题是

如何在行未锁定到砖石视图的最高对象的网格中创建不相等的单元格大小?

想到的唯一 'hacky' 解决方案现在有两个列表,一个的模型是每个奇数索引,另一个每个偶数索引都附加到同一个 flickable 所以它们作为一个对象滚动,但肯定必须有更好的方法来实现没有空格的砌体视图吗?我已经测试过了,它确实有效; (见下文)但是,是否有更好的实施方式?

    function isEven(n) {
        return n % 2 == 0;
    }

    function isOdd(n) {
        return Math.abs(n % 2) == 1;
    }

    JsonListModel {
        id: jsonModel; source: userFeed; keyField: "id"
        fields: ["id", "owner", "downloadUrl","profile_Pic_URL", "tag", "timestamp","post_description", "team", "liked_by", "location"]
    }
    SortFilterProxyModel {
        id: sortedModelOdd;
        Component.onCompleted: {app.userFeedChanged();sourceModel = jsonModel}
        filters: [
            ExpressionFilter {expression: model.tag === exploreFilter},
            ExpressionFilter {expression: isOdd(index)}
        ]
        sorters: RoleSorter {roleName: "timestamp"; ascendingOrder: false}
    }
    SortFilterProxyModel {
        id: sortedModelEven;
        Component.onCompleted: {app.userFeedChanged();sourceModel = jsonModel}
        filters: [
            ExpressionFilter {expression: model.tag === exploreFilter},
            ExpressionFilter {expression: isEven(index)}
        ]
        sorters: RoleSorter {roleName: "timestamp"; ascendingOrder: false}
    }

// i create 2 versions of the same model by using my expressionFilter for odds/evens

    ScrollView {
        anchors.fill: parent
        Row {
            anchors.fill: parent
            spacing: dp(5)
            anchors.margins: dp(5)
            AppListView {
                id: evenModelView
                model: sortedModelEven; emptyText.text: qsTr("No posts yet!"); scale: 0.96
                width: parent.width/2; spacing: dp(5); scrollIndicatorVisible: false;
                delegate: AppImage {width: parent.width; fillMode: Image.PreserveAspectFit; source: model.downloadUrl}
            }
            AppListView {
                id: oddModelView
                model: sortedModelOdd; emptyText.text: qsTr("No posts yet!"); scale: 0.96
                width: parent.width/2; spacing: dp(5);scrollIndicatorVisible: false;
                delegate: AppImage {width: parent.width; fillMode: Image.PreserveAspectFit; source: model.downloadUrl}
            }
        }
    }

我已经找到了一个解决方案(我在我的问题中提到了它 - 并对其进行了改进)所以 post 作为答案,但仍然很高兴听到是否有人使用实际布局等实现了这个结果。

 AppFlickable {
        anchors.fill: parent
        contentHeight: scrollRow.height
        Row {
            id: scrollRow; width: explorePage.width; height: explorePage.height;
            AppListView {
                id: evenModelView; interactive: false; model: sortedModelEven; width: explorePage.width/2; scrollIndicatorVisible: false;
                delegate:AppImage {
                    id: evenImage; z: 1; width: parent.width; fillMode: Image.PreserveAspectFit; source: model.downloadUrl
                }
            }
            AppListView {
                id: oddModelView; interactive: false; model: sortedModelOdd; width: explorePage.width/2; scrollIndicatorVisible: false;
                delegate: AppImage {
                    id: oddImage; z: 1; width: parent.width; fillMode: Image.PreserveAspectFit; source: model.downloadUrl;
                }
            }
        }
    }

备注:

我最初使用 ScrollView 而不是 Flickable,但这导致了严重的性能问题。

我把它放在 Loader 中,它确实在一定程度上解决了问题,因为它不会在运行时破坏性能,然后我改为 Flickable,因此导致了 0 个问题远(尚未使用大型模型进行测试)。

每个 AppListView 都需要禁用交互功能,否则有时滚动只能抓住其中一列并使它们不同步。