MacOS下Qt+qml+Android开发系列:2、切换页面

一、前言

上次了解了使用qml实现常见的一些控件,在设备上也做了测试,基本的简单页面已经可以开发出来了,但是实际使用中都是多个页面的,多个页面的切换也是必不可少的,这一次我们就再问一下trae如何进行qml的多页面开发,而且多个页面我们也通过多个qml文件来区分,保证可复用性。

二、qml常见页面切换方式

直接问trae:

在你的项目中,我建议使用 StackView 方式,因为它:

  1. 有完整的页面栈管理
  2. 支持前进/后退动画
  3. 内存管理更高效
  4. 与你的现有项目结构兼容性好

需要特别注意:

  1. 每个页面最好封装为单独的 Component 或 QML 文件
  2. 页面切换时要处理好数据传递
  3. 安卓/iOS 上有原生风格的过渡动画可用

在 QML 中,常见的页面切换方式有以下几种,我将结合你的当前项目结构为你详细介绍:

1. 使用 StackView(推荐方式)

StackView 是最常用的页面管理组件,适合大多数应用场景。

plain 复制代码
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12

Window {
    // ... existing code ...
    
    StackView {
        id: stackView
        anchors.fill: parent
        initialItem: Page1 {}
    }

    Component {
        id: page1
        Rectangle {
            color: "lightblue"
            Button {
                text: "去第二页"
                onClicked: stackView.push(page2)
            }
        }
    }

    Component {
        id: page2
        Rectangle {
            color: "lightgreen"
            Button {
                text: "返回"
                onClicked: stackView.pop()
            }
        }
    }
}

测试代码:

我们创建包括main.qml的三个qml文件:main.qml、home.qml、login.qml,main.qml用于控制切换,login.qml设计为登录页面,home.qml为进入后的主页,默认显示登录页面,点击登录按钮后进入home页面,点击home页面的返回则退出到登录页面。

javascript 复制代码
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12

Window {
    width: 720
    height: 1440
    visible: true
    title: qsTr("登录应用")

    StackView {
        id: stackView
        anchors.fill: parent
        initialItem: Qt.createComponent("login.qml").createObject(stackView, {"stackView": stackView})
    }
}
javascript 复制代码
import QtQuick 2.12
import QtQuick.Controls 2.12

Rectangle {
    id: loginPage
    property var stackView
    width: parent.width
    height: parent.height

    Column {
        anchors.centerIn: parent
        spacing: 20

        Label {
            text: "登录页面"
            font.pixelSize: 24
        }

        Button {
            text: "登录"
            onClicked: stackView.push(Qt.resolvedUrl("home.qml"), {"stackView": stackView})
        }
    }
}
javascript 复制代码
import QtQuick 2.12
import QtQuick.Controls 2.12

Rectangle {
    id: homePage
    property var stackView
    width: parent.width
    height: parent.height
    color: "lightgreen"
    
    Column {
        anchors.centerIn: parent
        spacing: 20
        
        Label {
            text: "欢迎来到主页"
            font.pixelSize: 24
        }
        
        Button {
            text: "返回登录页"
            onClicked: stackView.pop()
        }
    }
}

测试效果:

2. 使用 Loader 动态加载

适合需要频繁切换但不需要保留页面状态的场景。

plain 复制代码
// ... existing code ...
Loader {
    id: pageLoader
    anchors.fill: parent
    sourceComponent: page1
}

Button {
    text: "切换页面"
    onClicked: pageLoader.sourceComponent = 
        (pageLoader.sourceComponent == page1) ? page2 : page1
}
// ... existing code ...

测试代码:

也是三个qml文件,这种方式感觉简单很多,但是没有切换页面的效果:

javascript 复制代码
import QtQuick 2.12
import QtQuick.Controls 2.12

Window {
    width: 720
    height: 1440
    visible: true
    title: qsTr("Loader示例")

    property string currentPage: "login.qml"

    Loader {
        id: pageLoader
        anchors.fill: parent
        source: currentPage
    }

    Connections {
        target: pageLoader.item
        ignoreUnknownSignals: true
        function onChangePage(page) {
            currentPage = page
        }
    }
}
javascript 复制代码
import QtQuick 2.12
import QtQuick.Controls 2.12

Item {
    signal changePage(string page)

    Column {
        anchors.centerIn: parent
        spacing: 20
        
        Label {
            text: "登录页面"
            font.pixelSize: 24
        }
        
        Button {
            text: "登录"
            onClicked: changePage("home.qml")
        }
    }
}
javascript 复制代码
import QtQuick 2.12
import QtQuick.Controls 2.12

Item {
    signal changePage(string page)

    Column {
        anchors.centerIn: parent
        spacing: 20
        
        Label {
            text: "欢迎来到主页"
            font.pixelSize: 24
        }
        
        Button {
            text: "返回登录页"
            onClicked: changePage("login.qml")
        }
    }
}

测试效果:

3. 使用 SwipeView

适合需要左右滑动切换页面的场景。

plain 复制代码
// ... existing code ...
import QtQuick.Controls 2.12

SwipeView {
    id: swipeView
    anchors.fill: parent
    
    Page1 {}
    Page2 {}
    Page3 {}
}

PageIndicator {
    anchors.bottom: parent.bottom
    currentIndex: swipeView.currentIndex
    count: swipeView.count
}
// ... existing code ...

测试代码:

这种也是三个文件,用户左右滑动进行页面切换,很多app都是这种切换方式:

javascript 复制代码
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12

Window {
    width: 720
    height: 1440
    visible: true
    title: qsTr("滑动视图示例")

    SwipeView {
        id: swipeView
        anchors.fill: parent
        currentIndex: 0
        interactive: true

        Loader {
            source: "login.qml"
        }

        Loader {
            source: "home.qml"
        }
    }

    PageIndicator {
        anchors.bottom: parent.bottom
        anchors.horizontalCenter: parent.horizontalCenter
        count: swipeView.count
        currentIndex: swipeView.currentIndex
    }
}
javascript 复制代码
import QtQuick 2.12
import QtQuick.Controls 2.12

Rectangle {
    width: parent.width
    height: parent.height
    
    Column {
        anchors.centerIn: parent
        spacing: 20
        
        Label {
            text: "登录页面"
            font.pixelSize: 24
        }
        
        Button {
            text: "滑动到主页"
            onClicked: swipeView.currentIndex = 1
        }
    }
}
javascript 复制代码
import QtQuick 2.12
import QtQuick.Controls 2.12

Rectangle {
    width: parent.width
    height: parent.height
    
    Column {
        anchors.centerIn: parent
        spacing: 20
        
        Label {
            text: "欢迎来到主页"
            font.pixelSize: 24
        }
        
        Button {
            text: "滑动回登录页"
            onClicked: swipeView.currentIndex = 0
        }
    }
}

测试效果:

4. 使用 TabBar + StackLayout

适合需要标签页导航的场景。

plain 复制代码
// ... existing code ...
TabBar {
    id: tabBar
    TabButton { text: "首页" }
    TabButton { text: "设置" }
}

StackLayout {
    currentIndex: tabBar.currentIndex
    Page1 {}
    Page2 {}
}
// ... existing code ...

测试代码:

也是分为三个页面,这种方式也是用的比较多的:

javascript 复制代码
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12

Window {
    width: 720
    height: 1440
    visible: true
    title: qsTr("底部标签栏示例")

    // 主布局容器
    Column {
        anchors.fill: parent

        StackLayout {
            id: stackLayout
            width: parent.width
            height: parent.height - tabBar.height
            currentIndex: tabBar.currentIndex

            // 登录页面
            Loader {
                source: "login.qml"
            }

            // 主页
            Loader {
                source: "home.qml"
            }
        }

        // 底部标签栏
        TabBar {
            id: tabBar
            width: parent.width
            position: TabBar.Footer
            currentIndex: 0

            TabButton {
                text: qsTr("登录")
            }

            TabButton {
                text: qsTr("主页")
            }
        }
    }
}
javascript 复制代码
import QtQuick 2.12
import QtQuick.Controls 2.12

Item {
    width: parent.width
    height: parent.height
    
    Column {
        anchors.centerIn: parent
        spacing: 20
        
        Label {
            text: "登录页面"
            font.pixelSize: 24
        }
        
        Button {
            text: "滑动到主页"
            onClicked: swipeView.currentIndex = 1
        }
    }
}
javascript 复制代码
import QtQuick 2.12
import QtQuick.Controls 2.12

Item {
    width: parent.width
    height: parent.height
    
    Column {
        anchors.centerIn: parent
        spacing: 20
        
        Label {
            text: "欢迎来到主页"
            font.pixelSize: 24
        }
        
        Button {
            text: "滑动回登录页"
            onClicked: swipeView.currentIndex = 0
        }
    }
}

测试效果:

三、最后

这些页面切换方式其实没有绝对的好坏,主要还是要分场景去使用的。

相关推荐
钱彬 (Qian Bin)4 小时前
《使用Qt Quick从零构建AI螺丝瑕疵检测系统》——8. AI赋能(下):在Qt中部署YOLOv8模型
人工智能·qt·yolo·qml·qt quick·工业质检·螺丝瑕疵检测
giaoho5 小时前
Android 系统架构
android·系统架构
十盒半价7 小时前
React 牵手 Coze 工作流:打造高效开发魔法
react.js·coze·trae
m0_659394008 小时前
常见的cms框架的webshell方法
android
fatiaozhang95278 小时前
中兴云电脑W101D2-晶晨S905L3A-2G+8G-安卓9-线刷固件包
android·网络·电脑·电视盒子·刷机固件·机顶盒刷机
IT乐手10 小时前
java 或 安卓项目中耗时统计工具类
android·java
wang_hao..10 小时前
Day4.AndroidAudio初始化
android·音频
维尔切10 小时前
Linux中ssh远程登录原理与配置
android·linux·ssh
louisgeek11 小时前
Android Media3 PlayerView 监听 SurfaceTextureListener
android
哈市雪花11 小时前
添加捕捉吸附标识(使用QT+OpenGL开发三维CAD)
qt·教程·opengl·cad·绘制·工业软件·捕捉吸附