【问题标题】:QML Staggered (Masonry) GridView or FlowQML 交错(砌体)GridView 或 Flow
【发布时间】:2021-10-20 06:43:28
【问题描述】:

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

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}
            }
        }
    }

【问题讨论】:

  • 对我的“hacky”解决方案的轻微更新 - 使用滚动视图导致我的应用程序不再加载测试(我认为这是由于一次加载太多);在页面加载时将我的 Row{AppListView{} AppListView{}} 放入加载器 (Component.onCompleted{}) 可以解决问题,但也只需将 ScrollView 更改为 Flickable 即可!

标签: javascript gridview qml grid-layout masonry


【解决方案1】:

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

 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 都需要禁用它的交互功能,否则有时滚动可能会仅捕获其中一列并使它们不同步。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-05-09
    • 2015-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多