赞
踩
QML中TabBar要实现标签移动效果比较麻烦,不像QTabBar控件那样可以设置属性后就能移动,虽然在父类Container中提供了moveItem接口,但是要实现拖拽交换的视觉效果还是没那么容易。
本demo使用QML的ListView来实现该功能,并动态切换对应的page内容。demo提供了动态添加页、删除页、移动交换标签位置功能。
先来看效果图:
Demo说明:
本文Demo在这里
点击下载
ListView{
id:tabBar
anchors.left: parent.left
anchors.right: parent.right
interactive: false
anchors.leftMargin: 20
z:15
height: 30
spacing: 1
orientation:ListView.Horizontal
currentIndex: 0
move: Transition {
NumberAnimation { property: "x"; duration: 150 }
}
moveDisplaced: Transition {
NumberAnimation { property: "x"; duration: 150 }
}
model:ListModel{
id:tabModel
}
delegate: TabButton{
id:tabButton
height: 30
width: 120
contentItem: Text {
font.pixelSize: 14
font.family: "微软雅黑"
text: name
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
color: tabBar.currentIndex === index ? "#3692F0" :"#525252"
elide: Text.ElideMiddle
}
background:Item{
Rectangle {
color: tabBar.currentIndex === index ? "#171717" : "transparent"
border.width: tabBar.currentIndex === index ? 1 : 0
border.color: "#404040"
height: parent.height+3
width: parent.width
x:-1;y:-2
Rectangle{
y:parent.height-1
width: parent.width
height: 3
color: "#171717"
visible: tabBar.currentIndex === index
z:20
}
}
}
Image {
id: closeBtn
source: "qrc:/icon/close.png"
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
anchors.rightMargin: 8
visible: tabBar.currentIndex === index
width: 10;height: 10
smooth: true
z:20
MouseArea{
anchors.fill: parent
onClicked: {
removeData(name)
}
}
}
MouseArea{
id:ma2
anchors.fill: parent
preventStealing: true
hoverEnabled: true
onPositionChanged: {
var _index= tabBar.indexAt(ma2.mouseX + tabButton.x, ma2.mouseY + tabButton.y);
if (_index!== -1 && pressed) {
if (index !== _index) {
tabModel.move(index, _index,1);
tabBar.positionViewAtIndex(_index,ListView.Center)
}
}
}
onClicked: {
tabBar.currentIndex = index
}
}
}
}
ListView中每一项Item使用TabButton来实现,而拖拽交换位置是在MouseArea中onPositionChanged进行。
动画效果:
move: Transition {
NumberAnimation { property: "x"; duration: 150 }
}
moveDisplaced: Transition {
NumberAnimation { property: "x"; duration: 150 }
}
可设定动画时间。
而tab对应的页面是放在栈布局中,通过Repeater结合ObjectModel来填充对应内容:
StackLayout{
id:stackLayout
anchors.top: tabBar.top
anchors.topMargin: 1
anchors.bottom: parent.bottom
width: parent.width
Repeater{
model:ObjectModel{
id:itemModel
}
}
}
model 数据填充是动态创建并添加
let _name = "Panel #" + panelIndex++
let component = Qt.createComponent("CusPanel.qml")
if(component.status === Component.Ready){
var panel = component.createObject(stackLayout)
panel.name = _name
itemModel.append(panel)
}
需要注意的是,这里tabModel
是标签对应的model,而itemModel
是页面item的model,这两个model的当前索引不一样,因为移动tab标签时itemModel并没有改变。所以在tabModel的当前索引变化时,需要动态找到对应的页面并实时切换itemModel的当前索引。二者的联系是通过属性name来查找。
本文Demo在这里
点击下载
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。