Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Disable swiping multi items on SwipeDelegate

By default SwipeDelegate allows for swiping multi items like below image:

enter image description here

As you can see, multi swipe items are open at a time and i want only one open item at a time, means if you open item #1, by opening item #2, item #1 should close. how can i achieve this?

Sample code for a ListView with SwipeDelegate:

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 { }
}
like image 719
Elsiete Avatar asked Mar 08 '23 23:03

Elsiete


2 Answers

Here's how I would do this:

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 is derived from AbstractButton) can be checked at a time. SwipeDelegate has no visual effects to represent the checked state, so we can safely use it to keep track of which one should be open. We still need to close the previously open delegate though, so that's where the

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

comes in.

swipedelegate

like image 151
Mitch Avatar answered Mar 25 '23 00:03

Mitch


Inspired by the answer with the ButtonGroup, here's my solution which does not require to modify the delegates:

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();
                        }
                    })
                }
            }
        }
    }
}

Then just put this into the ListView like this:

ListView {

    SwipeDelegateGroup {}

    delegate: SwipeDelegate {
        ...
    }
}
like image 26
Michael Zanetti Avatar answered Mar 24 '23 23:03

Michael Zanetti