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