qml 长按GridView拖动改变控件位置(可直接拖到不可见区域)

import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Layouts 1.14
import QtQuick.Controls 2.4
import QtGraphicalEffects 1.14
import QtQuick.XmlListModel 2.14

ApplicationWindow {
    visible: true
    width: 480
    height: 360
    title: qsTr("GridView")
    //flags: Qt.Window | Qt.FramelessWindowHint
    objectName: "rootObject"
    id : root


    property bool longPress: false
    property var  item

    property ListModel dataModel: ListModel {
        ListElement { title: qsTr("电话") }
        ListElement { title: qsTr("相册") }
        ListElement { title: qsTr("短信") }
        ListElement { title: qsTr("网络") }
        ListElement { title: qsTr("微信") }
        ListElement { title: qsTr("设置") }
        ListElement { title: qsTr("日历") }
        ListElement { title: qsTr("天气") }
        ListElement { title: qsTr("百度") }
        ListElement { title: qsTr("时间") }
        ListElement { title: qsTr("生活") }
    }

    QtObject {
        id: d

        readonly property int cellWidth: 160
        readonly property int cellHeight: 120
        readonly property int iconWidth: 96
        readonly property int iconHeight: 96

        property int dragIndex: -1
        property bool dragBehavior: false
    }

    GridView {
        id: gridView
        anchors.fill: parent
        cellWidth: d.cellWidth
        cellHeight: d.cellHeight
        move: Transition {
            NumberAnimation { properties: "x"; duration: 1000; easing.type: Easing.OutCubic }
            NumberAnimation { properties: "y"; duration: 1000; easing.type: Easing.OutCubic }
        }
        moveDisplaced: Transition {
            NumberAnimation { properties: "x"; duration: 3000; easing.type: Easing.OutCubic}
            NumberAnimation { properties: "y"; duration: 1000;  easing.type: Easing.OutCubic }
        }
        model: dataModel
        delegate: Item {
            width: d.cellWidth
            height: d.cellHeight
            z: mouseArea.pressed ? 1000 : 1
            Rectangle {
                id: btnIconArea
                anchors.centerIn: parent
                width: d.iconWidth
                height: d.iconWidth
                //radius: 8
                color: "transparent"
                //border.color: "gray"
                Rectangle {
                    Timer{
                        id : timer
                        interval : 500
                        repeat :false
                        running: false
                        onTriggered: {
                            console.log("longPress")
                            longPress = true

                            d.dragBehavior = false;
                            var pos = gridView.mapFromItem(btnIcon, 0, 0);
                            d.dragIndex = model.index;
                            btnIcon.parent = gridView;
                            btnIcon.x = pos.x - 10
                            btnIcon.y = pos.y - 10
                            mouseArea.drag.target = parent

                            btnIcon.width += 20
                            btnIcon.height += 20

                            btnIcon.state = "rotated"
                            anim.restart()
                        }
                    }

                    SequentialAnimation on rotation {
                        id : anim
                        NumberAnimation { to: 20; duration: 100 }
                        NumberAnimation { to: -20; duration: 120 }
                        NumberAnimation { to: 0; duration: 100 }
                        running: btnIcon.state === "rotated"
                        alwaysRunToEnd: true
                    }

                    id: btnIcon
                    width: d.iconWidth
                    height: d.iconWidth
                    radius: 8
                    color: "blue"
                    border.color: "black"
                    Behavior on x { enabled: d.dragBehavior; NumberAnimation { duration: 200 } }
                    Behavior on y { enabled: d.dragBehavior; NumberAnimation { duration: 200 } }
                    Text {
                        anchors.centerIn: parent
                        color: "white"
                        text: model.title
                        font.pixelSize: 25
                    }
                    MouseArea {
                        id: mouseArea
                        anchors.fill: parent
                        //drag.target: parent
                        propagateComposedEvents: true
                        onPressed: {
                            //console.log("press")
                            drag.target = null
                            timer.restart()
                        }

                        onReleased: {
                            console.log("release")
                            drag.target = null
                            if(longPress){
                                d.dragIndex = -1;
                                var pos = gridView.mapToItem(btnIconArea, btnIcon.x, btnIcon.y);
                                btnIcon.parent = btnIconArea;
                                btnIcon.x = pos.x;
                                btnIcon.y = pos.y;
                                d.dragBehavior = true;
                                btnIcon.x = 0;
                                btnIcon.y = 0;

                                btnIcon.width = d.iconWidth
                                btnIcon.height = d.iconHeight
                            }
                            else{
                                mouse.accepted = false
                            }

                            gridView.focus = true
                            longPress = false
                            timer.stop()
                        }

                        onPositionChanged: {
                            if(longPress){
                                var pos = gridView.mapFromItem(btnIcon, 0, 0);
                                var idx = gridView.indexAt(pos.x, pos.y + gridView.contentY);
                                if (idx > -1 && idx < gridView.count) {
                                    dataModel.move(d.dragIndex, idx, 1)
                                    d.dragIndex = idx;
                                }
                                console.log("long move:" + pos.x + " " + pos.y)
                                console.log("content : " + gridView.contentX + " " + gridView.contentY)
                                if(pos.y > 260){
                                    if(!gridView.atYEnd){
                                        gridView.contentY += 5
                                    }
                                }
                                else if(pos.y <= 0){
                                    if(!gridView.atYBeginning){
                                        gridView.contentY -= 5
                                    }
                                }
                            }
                            else{
                                //console.log("short move")
                                mouse.accepted = false
                                longPress = false
                                gridView.focus = true
                                timer.stop()
                            }
                        }
                    }
                }
            }
        }
    }
}

初始界面:
在这里插入图片描述
拖动后(“电话”放到下一个区域了):
在这里插入图片描述
参考博文:https://blog.csdn.net/zzs0829/article/details/121968341

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值