QtQuick手機滑動介面Demo

westlife_28發表於2015-10-27

此Demo是剛學習QtQuick時寫的,看了下qml的文件後嘗試的。第一次接觸QtQuick是下載Qt5的時候在官網看到一個UI開發的演示,當時覺得Qt用C++還能把UI做的這麼好看?花了4天時間認真學發現和介面上和C++關係不大,使用的是qml語言,取名qtquick意味快速開發出產品,所以我嘗試這個Demo看看有多快。

功能需求

這個Demo實現類似iPhone的介面,僅僅類似,主螢幕可放置4x4數量的應用圖示且三屏可滑動。底部可以放置單行4個應用圖示,也可以左右滑動。主螢幕當前頁的page indicator可以指示當前頁,也可以觸控小白點翻頁。以及下拉選單。
示例圖1

主螢幕實現

因為是初學,所以遇到的第一個問題就是螢幕滑動的問題,想了很久的辦法又是查文件又是科學谷歌。最後有一些思路:如果僅僅是能切換螢幕,就很簡單,根據滑鼠(手勢)動作(比如在螢幕左邊檢測到滑鼠左鍵按下,在螢幕右邊檢測到滑鼠按鍵釋放,可以判斷該滑鼠手勢動作為向右滑動),實現隱藏或顯示螢幕。但是這裡需要的是滑動螢幕,滑動過程必須順滑,並且在滑鼠釋放按鍵後頁面必須剛好在顯示範圍內。在科學谷歌和查詢文件之後,發現了自帶的ListView可以完美實現主螢幕的功能。

這個功能可以不需要Listview,但是我嘗試實現的效果實在不好,所以沒有繼續嘗試。先使用現成的功能。

Listview設定如下:

ListView{
    id: pageView
    anchors.fill: parent
    model: pageModel//資料模型
    orientation: ListView.Horizontal//水平方向
    snapMode: ListView.SnapOneItem//每次顯示一個Item
    highlightRangeMode: ListView.StrictlyEnforceRange
    highlightMoveDuration: 400
    cacheBuffer: 3 //cacheBuffer is not a pixel buffer,it only maintains additional instantiated delegate
}    

上面那段程式碼功能就是將Listview水平放置,然後,snapMode屬性的意思就是每滑動一次,剛好顯示一個Item,也就是完整顯示一個頁面。如果繼續用Listview再實現底部的應用欄,設定完全一樣。所以,我們這裡把這一塊Listview的屬性設定獨立出來做成一個控制元件,在qml裡面非常方便,只需要單獨建立一個qml檔案,然後檔名就能作為控制元件名,在其他qml檔案中import路勁或者放在同一目錄,就能直接呼叫,比如現在在同一目錄我們建立一個PageView.qml,檔案內容:

import QtQuick 
ListView{
    id: pageView
    anchors.fill: parent
    model: pageModel
    orientation: ListView.Horizontal
    snapMode: ListView.SnapOneItem
    highlightRangeMode: ListView.StrictlyEnforceRange
    highlightMoveDuration: 400
    cacheBuffer: 3 //cacheBuffer is not a pixel buffer,it only maintains additional instantiated delegate
}

之後,我們在main.qml裡就不需要使用Listview,直接使用PageView:示例圖2

這一步就完成了UI的大體框架,完成這一步就實現了螢幕兩個可滑動部分,下一步在View中顯示model,就要用到對初學者來說有點難的重點內容了,model/view,以及delegate(去這個網站學習,很全面,比起中文的相關資料來說全面多了,而且其實非常好理解http://qmlbook.github.io/en/ch06/index.html)。view表示檢視,就是程式碼最後呈現出來的視覺上的效果,比如listview:
ListView示例
如圖所示,listview的顯示效果就是這樣單列多行的表,其基本單位就是一行,而model就是依託在這個view上顯示,model中每一份資料都會使用listview的一行來顯示。view和model相互獨立,你可以把listview換成gridview,那樣資料就會以下圖右邊的方式呈現:
gridview示例

model的用法不再多說,首先考慮在這裡需要顯示的資料,是應用圖示,所以資料內容就有圖示檔案路徑,應用名文字。因此可以單獨再定義一個控制元件Button,新建Button.qml

import QtQuick 2.2

Rectangle {
    id: button
    property real buttonScale: 1
    property bool pressed: false
    width: 128*buttonScale
    height: 144*buttonScale


    color:"transparent"
    //border.width: 3

    property string label: ""
    property string imageSource:""
    signal buttonClick()
    onButtonClick: {
        buttonEvent.getButtonEvent(buttonLabel.text)
    }


    Image {
        id:buttonImage
        z:2
        width: 120*buttonScale; height: 120*buttonScale
        anchors.top: parent.top
        anchors.topMargin: 8*buttonScale
        anchors.horizontalCenter: parent.horizontalCenter
        source: imageSource
        MouseArea {
            id: buttonMouseArea
            hoverEnabled: true
            anchors.fill: buttonImage
            //onClicked: buttonClick()
            onPressed: {
                buttonClick()
            }         
        }
    }

    Text {
        id: buttonLabel
        anchors.top: buttonImage.bottom
        anchors.topMargin: 0
        anchors.horizontalCenter: parent.horizontalCenter
        font.pixelSize: 20*buttonScale;font.bold: true
        color: "white"
        text: label
    }
}

然後將自定義的Button元素作為model的資料存放,設定delegate讓model內資料以4X4格式顯示。那麼最後主頁面呈現效果就示例圖1所示了。並且每個Button(即應用圖示)點選都會立馬響應,格式統一。

page indicator(主屏上三個小白點)

直接上程式碼了:

Row {
            id: mainPageIndicator
            property ListView target: mainPageView
            anchors.horizontalCenter: mainPageView.horizontalCenter
            anchors.bottom: mainPageView.bottom
            anchors.bottomMargin: 209 *windowScale
            z: 1
            spacing: 20*windowScale
            Repeater {
                opacity: 0.8
                model: mainPageView.model.count
                Rectangle {
                    width: 16*windowScale ; height: 16*windowScale
                    radius: 8*windowScale
                    color: mainPageView.currentIndex == index ? "white" : "grey"
                    MouseArea {
                        width: 20*windowScale ; height: 20*windowScale
                        anchors.centerIn: parent
                        onClicked: mainPageView.currentIndex = index
                    }
                }
            }
        }

總結

博文寫的沒有條理,因為Demo雖然簡單,但是涉及到的東西還是很多,作為初學者,還沒有將這些知識系統化,所以,前言不搭後語。
Demo中用的知識技巧都是文件裡面可以查詢到的,個人感覺重要的事情就是一定要耐心看文件。當然google更少不了。

相關文章