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