反转ListView而不从底部填充ListView

Invert ListView without filling the ListView from the bottom

我希望 ListView 反转其项目的顺序,以便最新的项目位于顶部。 我尝试使用 verticalLayoutDirection: ListView.BottomToTop 来实现这一点,但它使 ListView 从底部填满(我猜这是预料之中的)。

我用红色标记了所述ListView的实际边界。

我怎样才能颠倒 ListView 的项目顺序并仍然让它从上到下填充?越干净越好

应要求,提供更多信息:

ListView
{
    id: theList

    anchors
    {
        left: parent.left
        top: theAboveList.bottom
        right: parent.right
        bottom: parent.bottom
    }

    model: theModel
    delegate: theDelegate {}
    verticalLayoutDirection: ListView.BottomToTop
    clip: true
}

我需要将其反转的原因是委托实例知道它们何时位于最底部(我可以在委托中执行 index === 0),以设置特定状态。

如果我没理解错的话, 我想到的第一个想法是使用模型并操纵来自 C++ Qt side 的模型。但是这个任务需要更多的耐心并且会产生一点开销。

另一种方法是将您的模型作为典型的 JavaScript 列表进行操作——填充它,然后手动反转。

代码很简单:

function swap(a, b) {
    if (a < b) {
        move(a, b, 1)
        move (b-1, a, 1)
    } else if (a > b) {
        move(b, a, 1)
        move (a-1, b, 1)
    }
}

function reverse() {
    for (var i = 0; i < Math.floor(count/2); ++i) {
        swap(i, count-i-1)
    }
}

在这里你可以找到我写的 AdvancedListModel 的源代码 -- https://github.com/troyane/Whosebug-pro/tree/master/AdvModel_qml.

我现在通过将 ListView 的高度 属性 设置为 contentHeight 解决了这个问题。由于可能的布局问题(绑定循环等),我最初想避免使用此解决方案,但现在必须这样做。

另一个解决方案是使用 ListModelinsert method。在已经存在的索引中插入一个值不会压缩以前的值。它改变了它。

这是一个例子:

myModel.append({myValue: "Hello"})
myModel.insert(0, {myValue: "Goodbye"})

输出:

Goodbye
Hello

建立在 的基础上,但遵循它以便它适用于任何大小的模型,如果有的话,使用 header 组件中的间隔将代表推到顶部不足以填满视图。

import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.0

ApplicationWindow {
    visible: true
    width: 640
    height: 480

    property var theModel: 2

    Component {
        id: theDelegate
        Rectangle {
            height: 100
            border.width: 2
            border.color: "black"
            color: "red"
            width: ListView.view.width
            Text {
                width: parent.width
                text: index
                font.pointSize: 30
            }
        }
    }

    Item {
        id: theAboveList
        // component exists only to complete the example supplied in the question
    }

    ListView {
        id: theList

        anchors
        {
            left: parent.left
            top: theAboveList.bottom
            right: parent.right
            bottom: parent.bottom
        }

        model: theModel
        delegate: theDelegate
        verticalLayoutDirection: ListView.BottomToTop
        clip: true

        header: Item {}
        onContentHeightChanged: {
            if (contentHeight < height) {
                headerItem.height += (height - contentHeight)
            }
            currentIndex = count-1
            positionViewAtEnd()
        }
    }
}