QML学习笔记(八)— QML实现列表侧滑覆盖按钮
QML实现列表右边滑动删除按钮,并覆盖原有的操作按钮,点击可实现删除当前项
本文链接:QML实现列表侧滑覆盖按钮
作者:狐狸家的鱼
GitHub:八至
列表实现在另一篇博客已经提及,列表可选中、拖拽、编辑,现在优化一下,实现滑动删除效果,并覆盖原有的操作按钮。
主要就是对操作按钮与删除按钮之间做一个动态切换效果。
管制按钮一开始就是默认显示的,代码如下:
//管制按钮 Rectangle{ id: controlBtn anchors.verticalCenter: parent.verticalCenter height: controlRect.height - 1 width: controlRect.width - 1 radius: 3 color:"#42A5F5" Text { id:btnTex font.family: "microsoft yahei" font.pointSize: 10 anchors.centerIn: parent text: ctrBtn color: Global.GlobalVar.whiteColor } MouseArea{ anchors.fill: parent } }
删除按钮一开始是不显示的,宽度设置为0,这样在动态切换的时候对宽度进行设置即可
//删除按钮 Rectangle{ id:delBtn anchors.verticalCenter: parent.verticalCenter height: controlRect.height-1 width: 0 radius: 3 color: Global.GlobalVar.remindColor Text { id:delTex font.family: "microsoft yahei" font.pointSize: 10 anchors.centerIn: parent color: Global.GlobalVar.whiteColor } MouseArea{ anchors.fill: parent onClicked: { sstpModel.remove(sstpView.currentIndex) } } }
因为要滑动覆盖按钮,所有这里存在四个动画,第一是删除按钮需要滑动设置宽度大于0,显示出来,第二是管制按钮的宽度设置为0,被删除按钮覆盖隐藏掉,第三是点击当前项的其他地方,将已经显示的删除按钮隐藏,宽度设为0,第四是管制按钮再次显示,宽度设为大于0:
//滑动显示删除按钮,覆盖管制按钮 PropertyAnimation{ id: delBtnShow target: delBtn property: "width" duration: 150 from: 0 to: controlRect.width - 1 } PropertyAnimation{ id: delBtnHide target: delBtn property: "width" duration: 150 from: controlRect.width - 1 to: 0 } //点击隐藏删除按钮,显示管制按钮 PropertyAnimation{ id: ctrBtnShow target: controlBtn property: "width" duration: 150 from: 0 to: controlRect.width - 1 } PropertyAnimation{ id: ctrBtnHide target: controlBtn property: "width" duration: 150 from: controlRect.width - 1 to: 0 }
动态效果如何触发呢,滑动是鼠标按压->拖动->鼠标释放实现的,逻辑处理如下:
在代理的当前项鼠标可操作区域MouseArea{}声明点击的坐标点
property point clickPos: "0,0"
然后在鼠标按压事件里获取当前坐标点:
onPressed: { ... clickPos = Qt.point(mouse.x,mouse.y) }
鼠标释放完成滑动覆盖:
onReleased: { var delta = Qt.point(mouse.x-clickPos.x, mouse.y-clickPos.y) console.debug("delta.x: " + delta.x); if ( (delta.x < 0) && (delBtnShow.running === false && ctrBtnHide.running === false) && (delBtn.width == 0) ){ delBtnShow.start(); delTex.text = "删除" ctrBtnHide.start(); }else if ( (delBtnHide.running === false && ctrBtnShow.running === false) && (delBtn.width > 0) ){ delBtnHide.start(); delTex.text = "" ctrBtnShow.start(); } }
这样就实现效果啦。
完整代码如下,作为参考:
import QtQuick 2.7 import QtQuick.Window 2.3 import QtQuick.Layouts 1.3 import QtQuick.Controls 2.2 import Qt.an.qobjectSingleton 1.0 as Global import "../../Component" Window{ id:sstpWind width: 580 height: 420 minimumWidth: 520 minimumHeight: 420 title: "Sttp SetUp Window" color: Global.GlobalVar.windowBg visible: true ListView{ id:sstpView property bool isClicked: false //初始化没有点击事件 anchors.fill: parent clip:true interactive: !isClicked focus: true flickableDirection: Flickable.VerticalFlick boundsBehavior: Flickable.StopAtBounds ScrollBar.vertical: ScrollBar {id:scrollBar;active: true;} Keys.onUpPressed: scrollBar.decrease() Keys.onDownPressed: scrollBar.increase() move:Transition { NumberAnimation{ properties: "x,y"; duration: 300 } } anchors { left: parent.left; top: parent.top; right: parent.right; margins: 2 } spacing: 4 cacheBuffer: 50 //model: anAirModel model: ListModel{ id:sstpModel; ListElement{ num_1:1 num_2:'-020' ssr:'A5010'//应答机编码 air_iden:"CES5401"//呼号 航班号 vip:true//是否为vip type:"B737-800"//机型 status:"放行"//状态 el:"16"//机场标高 ALT-高度 ctrBtn:"滑行"// 管制按钮 HANDOVER-移交 CLR-放行 TAI-滑行 OFF-起飞 DESCENT-降落 DISENGAGE-脱离 time:"1215"//时间 airport:"ZPPP"//机场 runway:"01"// 跑道 procedure:"LUM-01D"//进离场程序 } ListElement{ num_1:1 num_2:'-020' ssr:'A5610'//应答机编码 air_iden:"CES5401"//呼号 航班号 vip:true//是否为vip type:"B737-800"//机型 status:"五边"//状态 el:"16"//机场标高 ALT-高度 ctrBtn:"脱离"// 管制按钮 HANDOVER-移交 CLR-放行 TAI-滑行 OFF-起飞 DESCENT-降落 DISENGAGE-脱离 time:"1215"//时间 airport:"ZPMS"//机场 runway:"01"// 跑道 procedure:"LUM-09A"//进离场程序 } ListElement{ num_1:1 num_2:'-020' ssr:'A0026'//应答机编码 air_iden:"CES5401"//呼号 航班号 vip:false//是否为vip type:"B737-"//机型 status:"穿越"//状态 el:"16"//机场标高 ALT-高度 ctrBtn:"移交"// 管制按钮 HANDOVER-移交 CLR-放行 TAI-滑行 OFF-起飞 DESCENT-降落 DISENGAGE-脱离 time:"1215"//时间 airport:"ZPLJ"//机场 runway:"01"// 跑道 procedure:"LUM-06A"//进离场程序 } ListElement{ num_1:1 num_2:'-020' ssr:'A0026'//应答机编码 air_iden:"CES5401"//呼号 航班号 vip:true//是否为vip type:"B737-0"//机型 status:"穿越"//状态 el:"16"//机场标高 ALT-高度 ctrBtn:"移交"// 管制按钮 HANDOVER-移交 CLR-放行 TAI-滑行 OFF-起飞 DESCENT-降落 DISENGAGE-脱离 time:"1215"//时间 airport:"ZPLJ"//机场 runway:"01"// 跑道 procedure:"LUM-06A"//进离场程序 } ListElement{ num_1:1 num_2:'-020' ssr:'A0026'//应答机编码 air_iden:"CES5401"//呼号 航班号 vip:false//是否为vip type:"B737-800"//机型 status:"穿越"//状态 el:"16"//机场标高 ALT-高度 ctrBtn:"移交"// 管制按钮 HANDOVER-移交 CLR-放行 TAI-滑行 OFF-起飞 DESCENT-降落 DISENGAGE-脱离 time:"1215"//时间 airport:"ZPLJ"//机场 runway:"01"// 跑道 procedure:"LUM-06A"//进离场程序 } ListElement{ num_1:1 num_2:'-020' ssr:'A0026'//应答机编码 air_iden:"CES5401"//呼号 航班号 vip:true//是否为vip type:"A357"//机型 status:"穿越"//状态 el:"16"//机场标高 ALT-高度 ctrBtn:"移交"// 管制按钮 HANDOVER-移交 CLR-放行 TAI-滑行 OFF-起飞 DESCENT-降落 DISENGAGE-脱离 time:"1215"//时间 airport:"ZPLJ"//机场 runway:"01"// 跑道 procedure:"LUM-06A"//进离场程序 } ListElement{ num_1:1 num_2:'-020' ssr:'A0026'//应答机编码 air_iden:"CES5401"//呼号 航班号 vip:true//是否为vip type:"A737"//机型 status:"穿越"//状态 el:"16"//机场标高 ALT-高度 ctrBtn:"移交"// 管制按钮 HANDOVER-移交 CLR-放行 TAI-滑行 OFF-起飞 DESCENT-降落 DISENGAGE-脱离 time:"1215"//时间 airport:"ZPLJ"//机场 runway:"01"// 跑道 procedure:"LUM-06A"//进离场程序 } } delegate:Rectangle{ id:sstpDelegate property int fromIndex:0 property int toIndex:0 property var controlColor:["#00C9FD", "#DB0058", "#FF7400", "#81EE8E"] width: parent.width height: 60 MouseArea { id:mousearea property point clickPos: "0,0" anchors.fill: parent onClicked: { sstpView.currentIndex = index } onPressed: { sstpView.currentIndex = index sstpDelegate.fromIndex = index sstpView.isClicked = true //每项按钮点击就true clickPos = Qt.point(mouse.x,mouse.y) } onReleased: { sstpView.isClicked = false //每项按钮点击就false console.log("fromIndex:",sstpDelegate.fromIndex,"toIndex:",sstpDelegate.toIndex) var delta = Qt.point(mouse.x-clickPos.x, mouse.y-clickPos.y) console.debug("delta.x: " + delta.x); if ( (delta.x < 0) && (delBtnShow.running === false && ctrBtnHide.running === false) && (delBtn.width == 0) ){ delBtnShow.start(); delTex.text = "删除" ctrBtnHide.start(); }else if ( (delBtnHide.running === false && ctrBtnShow.running === false) && (delBtn.width > 0) ){ delBtnHide.start(); delTex.text = "" ctrBtnShow.start(); } } onPositionChanged: { var lastIndex = sstpView.indexAt(mousearea.mouseX + sstpDelegate.x,mousearea.mouseY + sstpDelegate.y); if ((lastIndex < 0) || (lastIndex > sstpModel.rowCount())) return; if (index !== lastIndex){ sstpModel.move(index, lastIndex, 1); } sstpDelegate.toIndex = lastIndex; } } Row{ Rectangle{//选中当前 颜色高亮 id:curRect width: 5 height: sstpDelegate.height color: index===sstpView.currentIndex ? Global.GlobalVar.sstpCurIndex : Global.GlobalVar.mainFontColor//选中颜色设置 } //进程单信息 Rectangle{ id:infoRect width: sstpDelegate.width - controlRect.width - 5 height: sstpDelegate.height Row{ Rectangle{ width: infoRect.width/6 height: infoRect.height ColumnLayout{ anchors.verticalCenter: parent.verticalCenter anchors.horizontalCenter: parent.horizontalCenter MyText{//num_1 text: num_1 fontColor: b1; fontSize: m; } Rectangle{ implicitWidth: 28 implicitHeight: 28 radius: 28; color: controlColor[3] MyText{//num_2 anchors.centerIn: parent text:num_2 fontColor:b1 } } } } Rectangle{ width: infoRect.width/6 height: infoRect.height //第二列 ColumnLayout{ anchors.verticalCenter: parent.verticalCenter MyText{//航班呼号 text: air_iden fontColor: b1 fontSize: xl } MyText{//状态 text:status; fontColor: b1 fontSize: l } } } Rectangle{ width: infoRect.width/6 height: infoRect.height //第三列 ColumnLayout{ anchors.verticalCenter: parent.verticalCenter anchors.left: parent.left anchors.leftMargin: parent.width/6 //anchors.horizontalCenter: parent.horizontalCenter Rectangle{ width: 15 height: 15 radius: 15 color: vip ? controlColor[0]: "transparent" MyText{//vip anchors.centerIn: parent text: vip ? "V" :''//判断布尔值 color: "#FFF" fontColor:color fontSize: s } } MyText{ text: type; fontColor: b1 fontSize: m } } } Rectangle{ width: infoRect.width/6 height: infoRect.height //第四列 ColumnLayout{ anchors.verticalCenter: parent.verticalCenter anchors.horizontalCenter: parent.horizontalCenter TextInput{//机场 text: airport; color: Global.GlobalVar.mainFontColor font.pointSize: 12 onEditingFinished: { } } MyText{//标高 text: el; fontColor: b1 fontSize: m } } } Rectangle{ width: infoRect.width/6 height: infoRect.height //第五列 ColumnLayout{ anchors.verticalCenter: parent.verticalCenter anchors.horizontalCenter: parent.horizontalCenter TextInput{//进离场程序 text: procedure; color: Global.GlobalVar.mainFontColor font.pointSize: 12 } MyText{//应答机编码 text: ssr; fontColor: b1 fontSize: m } } } Rectangle{ width: infoRect.width/6 height: infoRect.height //第六列 ColumnLayout{ anchors.verticalCenter: parent.verticalCenter anchors.horizontalCenter: parent.horizontalCenter TextInput{//时间 text: time; color: controlColor[2]; font.pointSize: 12 onEditingFinished: { } } TextInput{//降落跑道 text: runway; color: Global.GlobalVar.mainFontColor font.pointSize: 12 onEditingFinished: { } } } } } } RecLine{id:recLine;direction:false} Rectangle{ id:controlRect width: 80 height: sstpDelegate.height Row{ //管制按钮 Rectangle{ id: controlBtn anchors.verticalCenter: parent.verticalCenter height: controlRect.height - 1 width: controlRect.width - 1 radius: 3 //color: Global.GlobalVar.btnBorderColor color:"#42A5F5" //color: ctrBtn == "滑行" ? controlColor[0] : (ctrBtn == "脱离" ? controlColor[1] : (ctrBtn == "移交" ? controlColor[2] : Global.GlobalVar.mainColor)) Text { id:btnTex font.family: "microsoft yahei" font.pointSize: 10 anchors.centerIn: parent text: ctrBtn color: Global.GlobalVar.whiteColor } MouseArea{ anchors.fill: parent } } //删除按钮 Rectangle{ id:delBtn anchors.verticalCenter: parent.verticalCenter height: controlRect.height-1 width: 0 radius: 3 color: Global.GlobalVar.remindColor //color: ctrBtn == "滑行" ? controlColor[0] : (ctrBtn == "脱离" ? controlColor[1] : (ctrBtn == "移交" ? controlColor[2] : Global.GlobalVar.mainColor)) Text { id:delTex font.family: "microsoft yahei" font.pointSize: 10 anchors.centerIn: parent color: Global.GlobalVar.whiteColor } MouseArea{ anchors.fill: parent onClicked: { sstpModel.remove(sstpView.currentIndex) } } } //滑动显示删除按钮,覆盖管制按钮 PropertyAnimation{ id: delBtnShow target: delBtn property: "width" duration: 150 from: 0 to: controlRect.width - 1 } PropertyAnimation{ id: delBtnHide target: delBtn property: "width" duration: 150 from: controlRect.width - 1 to: 0 } //点击隐藏删除按钮,显示管制按钮 PropertyAnimation{ id: ctrBtnShow target: controlBtn property: "width" duration: 150 from: 0 to: controlRect.width - 1 } PropertyAnimation{ id: ctrBtnHide target: controlBtn property: "width" duration: 150 from: controlRect.width - 1 to: 0 } } } } } }