在 SwipeDelegate 上禁用滑动多个项目

Disable swiping multi items on SwipeDelegate

默认情况下,SwipeDelegate 允许滑动多个项目,如下图所示:

如您所见,一次可以打开多个滑动项目,而我一次只想打开一个项目,这意味着如果您打开项目 #1,通过打开项目 #2,项目 #1 应该关闭。我怎样才能做到这一点?

带有 SwipeDelegate 的 ListView 的示例代码:

ListView {
    id: listView
    anchors.fill: parent

    delegate: SwipeDelegate {
        id: delegate

        text: modelData
        width: parent.width

        swipe.right: Rectangle {
            width: parent.width
            height: parent.height

            Label {
                text: qsTr("SOME ACTION BUTTON")

                padding: 20
                anchors.fill: parent
            }

        }
    }

    model: ListModel {
        id: listModel
        ListElement { text: "Lorem ipsum dolor sit amet" }
        ListElement { text: "Curabitur sit amet risus" }
        ListElement { text: "Suspendisse vehicula nisi" }
        ListElement { text: "Mauris imperdiet libero" }
        ListElement { text: "Sed vitae dui aliquet augue" }
        ListElement { text: "Praesent in elit eu nulla" }
        ListElement { text: "Etiam vitae magna" }
        ListElement { text: "Pellentesque eget elit euismod" }
        ListElement { text: "Nulla at enim porta" }
        ListElement { text: "Fusce tincidunt odio" }
        ListElement { text: "Ut non ex a ligula molestie" }
        ListElement { text: "Nam vitae justo scelerisque" }
        ListElement { text: "Vestibulum pulvinar tellus" }
        ListElement { text: "Quisque dignissim leo sed gravida" }
    }


    ScrollIndicator.vertical: ScrollIndicator { }
}

我会这样做:

import QtQuick 2.9
import QtQuick.Controls 2.3
import QtGraphicalEffects 1.0

ApplicationWindow {
    id: window
    width: 800
    height: 600
    visible: true

    ListView {
        id: listView
        anchors.fill: parent

        ButtonGroup {
            buttons: listView.contentItem.children
        }

        delegate: SwipeDelegate {
            id: delegate

            checkable: true
            text: modelData
            width: parent.width
            checked: swipe.complete
            onCheckedChanged: if (!checked) swipe.close()

            swipe.right: Rectangle {
                width: parent.width
                height: parent.height
                color: "#666"

                Label {
                    text: qsTr("SOME ACTION BUTTON")
                    color: "white"
                    leftPadding: 20
                    anchors.verticalCenter: parent.verticalCenter
                }
            }
        }

        model: ListModel {
            id: listModel
            ListElement { text: "Lorem ipsum dolor sit amet" }
            ListElement { text: "Curabitur sit amet risus" }
            ListElement { text: "Suspendisse vehicula nisi" }
            ListElement { text: "Mauris imperdiet libero" }
            ListElement { text: "Sed vitae dui aliquet augue" }
            ListElement { text: "Praesent in elit eu nulla" }
            ListElement { text: "Etiam vitae magna" }
            ListElement { text: "Pellentesque eget elit euismod" }
            ListElement { text: "Nulla at enim porta" }
            ListElement { text: "Fusce tincidunt odio" }
            ListElement { text: "Ut non ex a ligula molestie" }
            ListElement { text: "Nam vitae justo scelerisque" }
            ListElement { text: "Vestibulum pulvinar tellus" }
            ListElement { text: "Quisque dignissim leo sed gravida" }
        }


        ScrollIndicator.vertical: ScrollIndicator { }
    }
}

ButtonGroup ensures that only one "button" (SwipeDelegate 派生自AbstractButton) 可以一次检查。 SwipeDelegate 没有表示选中状态的视觉效果,因此我们可以安全地使用它来跟踪应该打开哪个。我们仍然需要关闭之前打开的委托,所以这就是

onCheckedChanged: if (!checked) swipe.close()

进来了。

受 ButtonGroup 答案的启发,这是我不需要修改委托的解决方案:

SwipeDelegateGroup.qml

import QtQuick 2.9
import QtQuick.Controls 2.2

Item {
    id: swipeGroup

    property ListView listView: parent
    QtObject {
        id: d
        property var delegates: swipeGroup.listView.contentItem.children
        property var delegateCache: []

        onDelegatesChanged: {
            for (var i = 0; i < d.delegates.length; i++) {
                var thisItem = d.delegates[i];
                if (!thisItem.hasOwnProperty("swipe")) {
                    continue;
                }
                if (d.delegateCache.indexOf(thisItem) < 0) {
                    d.delegateCache.push(thisItem);

                    thisItem.Component.destruction.connect(function() {
                        d.delegateCache.splice(d.delegateCache.indexOf(thisItem), 1)
                    })

                    thisItem.swipe.opened.connect(function() {
                        for (var j = 0; j < d.delegates.length; j++) {
                            var otherItem = d.delegates[j];
                            if (thisItem === otherItem) {
                                continue;
                            }
                            if (!otherItem.hasOwnProperty("swipe")) {
                                continue;
                            }
                            otherItem.swipe.close();
                        }
                    })
                }
            }
        }
    }
}

然后像这样将其放入 ListView 中:

ListView {

    SwipeDelegateGroup {}

    delegate: SwipeDelegate {
        ...
    }
}