203 lines
6.7 KiB
QML
203 lines
6.7 KiB
QML
|
|
// =============================================
|
|||
|
|
// =============== 重叠选项卡面板 ===============
|
|||
|
|
// =============================================
|
|||
|
|
|
|||
|
|
import QtQuick 2.15
|
|||
|
|
import QtQuick.Controls 2.15
|
|||
|
|
import QtGraphicalEffects 1.15
|
|||
|
|
|
|||
|
|
Item {
|
|||
|
|
property alias currentIndex: bar.currentIndex // 当前下标
|
|||
|
|
property int indexChangeNum: 0 // 下标变化次数
|
|||
|
|
property bool isMenuTop: true // t时控制菜单在顶部,f时在底部
|
|||
|
|
property real menuHeight: size_.line * 2 // 菜单栏高度
|
|||
|
|
|
|||
|
|
onCurrentIndexChanged: indexChangeNum++
|
|||
|
|
|
|||
|
|
// 模型选项卡
|
|||
|
|
/* 每一项:
|
|||
|
|
{ "key": 标识,
|
|||
|
|
"title": 标题,
|
|||
|
|
"component": 选项卡组件
|
|||
|
|
选项卡组件中可有一个属性ctrlBar,指向一个控制栏子组件。这个子组件将会父级移动到选项卡的控制栏。
|
|||
|
|
} */
|
|||
|
|
property var tabsModel: []
|
|||
|
|
clip: true
|
|||
|
|
id: tabPanel
|
|||
|
|
|
|||
|
|
function updateMenuTop() {
|
|||
|
|
// 菜单在顶部模式
|
|||
|
|
if(isMenuTop) {
|
|||
|
|
menuContainer.anchors.top = tabPanel.top
|
|||
|
|
menuContainer.anchors.bottom = undefined
|
|||
|
|
menuContainer.height = menuHeight
|
|||
|
|
swipeView.anchors.top = menuContainer.bottom
|
|||
|
|
swipeView.anchors.bottom = tabPanel.bottom
|
|||
|
|
swipeView.anchors.topMargin = size_.smallSpacing
|
|||
|
|
swipeView.anchors.bottomMargin = 0
|
|||
|
|
}
|
|||
|
|
// 菜单在底部模式
|
|||
|
|
else {
|
|||
|
|
menuContainer.anchors.top = undefined
|
|||
|
|
menuContainer.anchors.bottom = tabPanel.bottom
|
|||
|
|
menuContainer.height = menuHeight
|
|||
|
|
swipeView.anchors.top = tabPanel.top
|
|||
|
|
swipeView.anchors.bottom = menuContainer.top
|
|||
|
|
swipeView.anchors.topMargin = 0
|
|||
|
|
swipeView.anchors.bottomMargin = size_.smallSpacing
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
onIsMenuTopChanged: updateMenuTop()
|
|||
|
|
Component.onCompleted: updateMenuTop()
|
|||
|
|
|
|||
|
|
// 下方 选项页
|
|||
|
|
SwipeView {
|
|||
|
|
id: swipeView
|
|||
|
|
anchors.left: parent.left
|
|||
|
|
anchors.right: parent.right
|
|||
|
|
currentIndex: bar.currentIndex
|
|||
|
|
interactive: false // 禁止直接滑动视图本身
|
|||
|
|
Component.onCompleted: {
|
|||
|
|
if(!qmlapp.enabledEffect) // 关闭动画
|
|||
|
|
contentItem.highlightMoveDuration = 0
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
Repeater {
|
|||
|
|
model: tabsModel
|
|||
|
|
|
|||
|
|
Item {
|
|||
|
|
visible: SwipeView.isCurrentItem
|
|||
|
|
Component.onCompleted: {
|
|||
|
|
modelData.component.parent = this
|
|||
|
|
modelData.component.visible = true
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 选项栏
|
|||
|
|
Item {
|
|||
|
|
id: menuContainer
|
|||
|
|
anchors.left: parent.left
|
|||
|
|
anchors.right: parent.right
|
|||
|
|
// 在 updateMenuTop 中重设高度
|
|||
|
|
|
|||
|
|
Rectangle { // 背景色
|
|||
|
|
anchors.fill: parent
|
|||
|
|
color: theme.bgColor
|
|||
|
|
Rectangle {
|
|||
|
|
anchors.fill: parent
|
|||
|
|
color: theme.coverColor1
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 左:选项栏
|
|||
|
|
TabBar {
|
|||
|
|
id: bar
|
|||
|
|
anchors.left: parent.left
|
|||
|
|
anchors.top: parent.top
|
|||
|
|
anchors.bottom: parent.bottom
|
|||
|
|
|
|||
|
|
background: Rectangle {
|
|||
|
|
color: theme.bgColor
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
Repeater {
|
|||
|
|
model: tabsModel
|
|||
|
|
|
|||
|
|
TabButton {
|
|||
|
|
property string text_: modelData.title
|
|||
|
|
anchors.top: parent.top
|
|||
|
|
anchors.bottom: parent.bottom
|
|||
|
|
checkable: true
|
|||
|
|
width: contentText.contentWidth + size_.line*2
|
|||
|
|
|
|||
|
|
contentItem: Text_ {
|
|||
|
|
id: contentText
|
|||
|
|
text: parent.text_
|
|||
|
|
horizontalAlignment: Text.AlignHCenter
|
|||
|
|
verticalAlignment: Text.AlignVCenter
|
|||
|
|
color: parent.checked ? theme.textColor : theme.subTextColor
|
|||
|
|
font.bold: parent.checked
|
|||
|
|
}
|
|||
|
|
background: MouseAreaBackgroud {
|
|||
|
|
anchors.fill: parent
|
|||
|
|
radius_: 0
|
|||
|
|
cursorShape: Qt.PointingHandCursor
|
|||
|
|
|
|||
|
|
Rectangle {
|
|||
|
|
anchors.fill: parent
|
|||
|
|
color: parent.parent.checked ? theme.coverColor3 : theme.coverColor2
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 选中的动画
|
|||
|
|
property bool runAni: false
|
|||
|
|
onCheckedChanged: {
|
|||
|
|
runAni = checked
|
|||
|
|
}
|
|||
|
|
SequentialAnimation{ // 串行动画
|
|||
|
|
running: qmlapp.enabledEffect && runAni
|
|||
|
|
// 动画1:放大
|
|||
|
|
NumberAnimation{
|
|||
|
|
target: contentText
|
|||
|
|
property: "scale"
|
|||
|
|
to: 1.3
|
|||
|
|
duration: 80
|
|||
|
|
easing.type: Easing.OutCubic
|
|||
|
|
}
|
|||
|
|
// 动画2:缩小
|
|||
|
|
NumberAnimation{
|
|||
|
|
target: contentText
|
|||
|
|
property: "scale"
|
|||
|
|
to: 1
|
|||
|
|
duration: 150
|
|||
|
|
easing.type: Easing.InCubic
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 内圆角裁切
|
|||
|
|
layer.enabled: true
|
|||
|
|
layer.effect: OpacityMask {
|
|||
|
|
maskSource: Rectangle {
|
|||
|
|
radius: size_.btnRadius
|
|||
|
|
width: bar.width
|
|||
|
|
height: bar.height
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
// 右:每个卡的控制栏
|
|||
|
|
SwipeView {
|
|||
|
|
id: ctrlSwipeView
|
|||
|
|
anchors.left: bar.right
|
|||
|
|
anchors.right: parent.right
|
|||
|
|
anchors.top: parent.top
|
|||
|
|
anchors.bottom: parent.bottom
|
|||
|
|
clip: true
|
|||
|
|
|
|||
|
|
currentIndex: bar.currentIndex
|
|||
|
|
interactive: false // 禁止直接滑动视图本身
|
|||
|
|
Component.onCompleted:{
|
|||
|
|
if(!qmlapp.enabledEffect) // 关闭动画
|
|||
|
|
contentItem.highlightMoveDuration = 0
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
Repeater {
|
|||
|
|
model: tabsModel
|
|||
|
|
|
|||
|
|
Item { // 控制栏子组件父级重定向
|
|||
|
|
visible: SwipeView.isCurrentItem
|
|||
|
|
Component.onCompleted: {
|
|||
|
|
if(modelData.component.ctrlBar) {
|
|||
|
|
modelData.component.ctrlBar.parent = this
|
|||
|
|
modelData.component.ctrlBar.anchors.fill = this
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|