1. 程式人生 > >QML ListView幾個常用且非常重要的屬性

QML ListView幾個常用且非常重要的屬性

前言

用 QML 開發介面的好處想必就不用多說了吧,可以總結為一個字:爽。
的確如此,用 QML 可以快速的開發出一些非常酷炫和複雜的介面,並且程式碼還非常簡潔,可讀性很強,容易理解。
今天要總結的是關於 ListView 中的一些常用的屬性,非常實用,不過如果是剛接觸 ListView 的話,可能會有些陌生(本人剛開始用的時候也是,然後翻遍了 Qt 幫助文件),所以這裡彙總一些最常用的屬性並介紹其用法。

正文

類似相片瀏覽

相片瀏覽的場景相信大家都非常熟悉了,在手機中開啟相簿瀏覽相片的時候,通過左右滑動可以一張張的瀏覽相片,那麼如果用ListView如何來實現呢,來看個簡單的 demo

import QtQuick.Window 2.2
import QtQuick.Controls 2.2

Window {
    visible: true
    width: 300
    height: 450
    title: qsTr("Hello World")

    ListView{
        id:listView
        anchors.fill: parent
        model: 10
        snapMode: ListView.SnapOneItem
        orientation:ListView.Horizontal
        delegate: Rectangle{
              width: listView.width
              height: listView.height
              color: index%2 ? "red":"yellow"
              Label{
                  anchors.centerIn: parent
                  font.pointSize: 100
                  text: index
              }
        }
    }
}

效果圖:
在這裡插入圖片描述
程式碼很簡單,最重要的兩句話:

snapMode: ListView.SnapOneItem
orientation:ListView.Horizontal

第一句是將切換模式設定為單張切換;
第二句是將列表改成水平瀏覽模式。

currentIndex動態切換

不知道大家有沒有遇到過這種情況,當切換ListView的item的時候,currentIndex並不會跟隨著變化,來看個示例:

在這裡插入圖片描述

那麼,如何將在我們切換 item 的時候將 currentIndex 也跟隨著變化呢?只需要新增一句:

highlightRangeMode: ListView.StrictlyEnforceRange

再看看效果圖:
在這裡插入圖片描述
為什麼要特意將 currentIndex動態切換提出來單獨說呢,有時候這個功能會特別有用,特別是我在開發相片瀏覽功能的時候,比如我們在切換 item 後需要用到當前的 currentIndex,這時候如果 index 不跟隨變化那就麻煩了。之前網上有人的做法是,在 delegate 中新增 MouseAera中,響應點選事件然後手動currentIndex ,這種方法存在很多弊端。

禁止列表首尾滑動

這個標題可能有些拗口,意思其實就是,當列表在首頁或尾頁的時候,如果再繼續滑動會有回彈的效果。
先看個效果圖:

在這裡插入圖片描述
但是有些設計中可能並不需要這種預設的設定,那麼該如何修改呢,其實很簡單,加上這句話:

boundsBehavior:Flickable.StopAtBounds

這其實就是設定在邊緣的時候不能再滑動,再看一下效果:
在這裡插入圖片描述

設定最大滑動速度

不知道大家在做 QML for Android 開發的時候有沒有遇到過這種問題,特別是前幾年 Qt 低版本的時候,使用 ListView 編譯到 Android 手機上,列表滑動特別不自然,滑動速度特別快(也和手機螢幕畫素有關),和平臺的相容性沒有做得很好,幸好隨著 Qt 版本的升級,解決了這個問題,不過有時候還是需要自己控制最大的滑動速度,設定屬性如下:

maximumFlickVelocity:7000  //設定滑動的最大速度

這裡的數值單位是: 畫素/秒
如果不做設定,會預設跟隨平臺特性來執行。如果要自己定義這個滑動速度,需要多除錯一下,找到適合的滑動效果。

新增 header

ListView 可以設定 headerItem,話不多說,直接看效果圖吧
在這裡插入圖片描述

ListView{
        id:listView
        anchors.fill: parent
        model: 10
        headerPositioning: ListView.PullBackHeader

        header: Rectangle{
            width: listView.width
            height: 70
            color: "green"
            Label{
                anchors.centerIn: parent
                text: "this is header"
            }
        }

        onCurrentIndexChanged: {
            console.log("current index = ",currentIndex)
        }

        delegate: Rectangle{
              width: listView.width
              height: 280
              color: index%2 ? "red":"yellow"
              Label{
                  id:txt
                  anchors.centerIn: parent
                  font.pointSize: 100
                  text: index
              }
              Label{
                  anchors.top: txt.bottom
                  font.pointSize: 30
                  text: "currentIndex = " + listView.currentIndex
                  anchors.horizontalCenter: parent.horizontalCenter
              }
        }
    }

和 header 對應的還有一個 footer,原理是一樣的,只是顯示的位置是在底部。這裡就不多介紹了。

下拉重新整理

ListView列表下拉重新整理是最常見的 場景了吧,這裡為了演示做了一個簡單的 demo,先來看看效果

在這裡插入圖片描述
原始碼:

import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Controls 2.2

Window {
    visible: true
    width: 250
    height: 350
    title: qsTr("ListView")
    property bool refreshFlag: false

    Rectangle{
        width: parent.width
        height: -listView.contentY
        color: "cyan"
        Label{
            anchors.centerIn: parent
            text:"下拉重新整理"
            visible: listView.contentYr
        }
    }

    BusyIndicator{
        id:busy
        z:4
        running: false
        anchors.horizontalCenter: parent.horizontalCenter
        anchors.top: parent.top
        anchors.topMargin: parent.height/3.
        Timer{
            interval: 2000
            running: busy.running
            onTriggered: {
                busy.running = false
            }
        }
    }

    ListView{
        id:listView
        anchors.fill: parent
        model: 30

        onContentYChanged: {
            if(-contentY > 40){
                refreshFlag = true
            }
        }
        onMovementEnded: {
            if(refreshFlag){
                refreshFlag = false
                busy.running = true
            }
        }

        onCurrentIndexChanged: {
            console.log("current index = ",currentIndex)
        }

        delegate: Rectangle{
              width: listView.width
              height: 70
              color: index%2 ? "red":"yellow"
              Label{
                  id:txt
                  anchors.centerIn: parent
                  font.pointSize: 20
                  text: index
              }
        }
    }
}

OK,暫且介紹這幾種最常用的功能,寫得不好的地方請多指出。