Search code examples
qtqmlqtquickcontrols2

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

Solution

  • 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