自定义控件实现QML侧边导航栏

1,000 阅读3分钟

本文已参加【新人创作礼】活动,一起开启掘金创作之路。


📒博客首页:何名取 的个人主页 - 文章 - 掘金 (juejin.cn)
🎉欢迎关注🔎点赞👍收藏⭐️留言📝
❤️期待一起交流!
🙏作者水平很有限,如果发现错误,求告知,多谢!
🌺有问题可私信交流!!!


自定义组件TabWidget

前言

实现QML侧边导航栏的最简方法 - 掘金 (juejin.cn)前面一篇文章介绍了实现QML侧边导航栏的最简方法,采用的是更改TabBar和其组成部分TabButton位置和排列的方法。本节介绍的另外一种稍微复杂,但是移植性非常强的方法来实现QML侧边导航栏。

实现原理

视图切换功能

导航栏的按钮与视图存在一一对应的关系。点击第一个按钮,出现的是第一个界面,点击第二个按钮,出现的是第二个界面,不同的按钮对应着不同的界面。

在本节介绍的方法中,我使用的是将界面透明化的操作。原理就是将所有界面一块展现出来,层层堆叠,所有的界面的透明度都设置为0,它们都存在,只是从界面上无法看到。当第一个按钮被点击时,将第一个界面的透明度设置为1,于是第一个界面就显示了出来。同理,其他的按钮对应的界面也是这样,当按钮被点击,对应界面的透明度被设置为1,显示到视图上,而没有被对应到的界面的透明度依然为0,静静潜藏在人们的视觉之下。

    function setOpacities() {
        for (var i = 0; i < stack.children.length; ++i) {
            stack.children[i].opacity = (i == current ? 1 : 0)
        }
    }

这个函数将会在每次按钮被点击时触发,进行遍历,实现上述隐藏其他界面,展示当前界面的操作。

导航栏垂直排列

导航栏垂直排列需要使用到Column类型来排列,Repeater类型来构造TabButton导航栏按钮。每个导航栏按钮的形状大小都是相同的,将Repeater类型的model属性设置为导航栏按钮的数量,delegate属性则是导航栏按钮的具体实现。以下是自定义组件TabWidget的完整代码。

import QtQuick 2.0

Item {
    id: tabWidget

    // Setting the default property to stack.children means any child items
    // of the TabWidget are actually added to the 'stack' item's children.
    // See the "Property Binding"
    // documentation for details on default properties.
    default property alias content: stack.children

    property int current: 0

    onCurrentChanged: setOpacities()
    Component.onCompleted: setOpacities()

    function setOpacities() {
        for (var i = 0; i < stack.children.length; ++i) {
            stack.children[i].opacity = (i == current ? 1 : 0)
        }
    }

    Column {
        id: side

        Repeater {
            model: stack.children.length
            delegate: Rectangle {
                height: tabWidget.height / stack.children.length; width: 80
                color: tabWidget.current == index ? "LightBlue" : "SkyBlue"

                Rectangle {
                    height: parent.height; width: 1
                    anchors { right: parent.right; rightMargin: 1 }
                    color: "SkyBlue"
                }
                Text {
                    horizontalAlignment: Qt.AlignHCenter; verticalAlignment: Qt.AlignVCenter
                    anchors.fill: parent
                    text: stack.children[index].title
                    elide: Text.ElideRight
                    font.bold: tabWidget.current == index
                }
                MouseArea {
                    anchors.fill: parent
                    onClicked: tabWidget.current = index
                }

            }
        }
    }

    Item {
        id: stack
        height: tabWidget.height
        anchors.left: side.right; anchors.right: tabWidget.right
    }
}

使用自定义组件

将自定义组件编写在另一个新的.qml文件中,保存后放在与main.qml文件同一路径下。在main.qml文件中引用。具体代码如下。

import QtQuick 2.15
import QtQuick.Window 2.15

Window {
    width: 640
    height: 480
    visible: true
    title: qsTr("Hello World")

    TabWidget {
        id: tabs
        anchors.fill: parent

        Rectangle {
            property string title: "Red"
            anchors.fill: parent

            Rectangle {
                anchors.fill: parent;
                color: "#ff7f7f"
                Text {
                    width: parent.width - 20
                    anchors.centerIn: parent; horizontalAlignment: Qt.AlignHCenter
                    text: "Roses are red"
                    font.pixelSize: 20
                    wrapMode: Text.WordWrap
                }
            }
        }

        Rectangle {
            property string title: "Green"
            anchors.fill: parent

            Rectangle {
                anchors.fill: parent;
                color: "#7fff7f"
                Text {
                    width: parent.width - 20
                    anchors.centerIn: parent; horizontalAlignment: Qt.AlignHCenter
                    text: "Flower stems are green"
                    font.pixelSize: 20
                    wrapMode: Text.WordWrap
                }
            }
        }

        Rectangle {
            property string title: "Blue"
            anchors.fill: parent;

            Rectangle {
                anchors.fill: parent;
                color: "#7f7fff"
                Text {
                    width: parent.width - 20
                    anchors.centerIn: parent; horizontalAlignment: Qt.AlignHCenter
                    text: "Violets are blue"
                    font.pixelSize: 20
                    wrapMode: Text.WordWrap
                }
            }
        }
    }
}

效果展示

image.png