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,暫且介紹這幾種最常用的功能,寫得不好的地方請多指出。