QML Book 第六章 模型、視圖及代理 2

6.3 動態(tài)視圖

Repeater 適用于有限和靜態(tài)數(shù)據(jù)集,但在現(xiàn)實世界中,模型通常更復(fù)雜和更大。 在這里,需要一個更智能的解決方案。為此,Qt Quick 提供了 ListView 和 GridView 元素。 這些都是基于 Flickable 的元素,因此用戶可以在較大的數(shù)據(jù)集中滑動查看視圖中的內(nèi)容。 同時,它們限制了同時實例化的 delegate 的數(shù)量。對于大型的數(shù)據(jù)模型,這意味著場景中一次加載的元素將變得更少。

listview-basic
gridview-basic

兩個元素的用法相似。 因此,我們將從 ListView 開始,然后再介紹 GridView,前者相對比較基礎(chǔ)。ListView 類似于 Repeater元素。 它使用一個模型,實例化一個delegate 并且在代理展示的內(nèi)容之間,可以有間距(spacing)屬性。下面的列表顯示了一個簡單的設(shè)置如何實現(xiàn)這些。

import QtQuick 2.5
import "../common"

Background {
    width: 80
    height: 300

    ListView {
        anchors.fill: parent
        anchors.margins: 20

        clip: true

        model: 100

        delegate: numberDelegate
        spacing: 5
    }

    Component {
        id: numberDelegate

        GreenBox {
            width: 40
            height: 40
            text: index
        }
    }
}
listview-basic

如果模型包含的數(shù)據(jù)超出了屏幕窗口可以用于展示數(shù)據(jù)的范圍,則 ListView 將僅顯示列表項中的一部分。但是,由于 Qt Quick 的默認(rèn)行為,列表視圖不會限制顯示代理的區(qū)域。 這意味著代理可能在列表視圖之外可見,并且在列表視圖之外的代理的動態(tài)創(chuàng)建和銷毀對用戶是可見的。為了防止這種情況,必須通過將 clip 屬性設(shè)置為true 的方式在 ListView 元素上激活裁剪。下圖顯示了與 clip 屬性默認(rèn)為 false 時相比較的結(jié)果。

listview-clip

對于用戶來說,ListView 是一個可滾動區(qū)域。它支持動態(tài)滾動,這意味著它可以快速滑動屏幕實現(xiàn)快速移動內(nèi)容的目的。默認(rèn)情況下,它也可以通過到達視圖內(nèi)容結(jié)束位置的回彈效果,使用戶意識到已經(jīng)到達視圖的結(jié)束位置。

視圖滾動結(jié)束時的行為是使用 boundsBehavior 屬性控制的。這是一個枚舉值,可以配置默認(rèn)值 Flickable.DragAndOvershootBounds,這意味著的視圖可以在其邊界之外拖動并自動回彈到視圖結(jié)束位置,值 Flickable.StopAtBounds 則意味著該視圖永遠不會移動到其邊界之外。介于以上兩者之間的值,F(xiàn)lickable.DragOverBounds,讓用戶可以拖動視圖超出其邊界,但輕擊將返回視圖結(jié)束位置。

可以限制視圖被允許停止的位置。 這是使用 snapMode 屬性控制的。 默認(rèn)行為 ListView.NoSnap 允許視圖在任何位置停止。通過將 snapMode 屬性設(shè)置為 ListView.SnapToItem,視圖將始終將項的頂部與其頂部對齊。 最后,ListView.SnapOneItem,當(dāng)鼠標(biāo)按鈕或觸摸被釋放時,視圖將從第一個可見項目停止不超過一個項目。 最后一個模式在翻頁時非常方便。

6.3.1 視圖方向

列表視圖默認(rèn)提供了一個垂直滾動列表,但是水平滾動有時也同樣有用。列表視圖的方向通過 orientation 屬性進行控制。 它可以設(shè)置為默認(rèn)值 ListView.Vertical 或 ListView.Horizontal。水平列表視圖如下所示。

import QtQuick 2.5
import "../common"

Background {
    width: 480
    height: 80

    ListView {
        anchors.fill: parent
        anchors.margins: 20
        spacing: 4
        clip: true
        model: 100
        orientation: ListView.Horizontal
        delegate: numberDelegate
    }

    Component {
        id: numberDelegate

        GreenBox {
            width: 40
            height: 40
            text: index
        }
    }
}
listview-horizontal

如你所知,水平方向默認(rèn)從左到右流動。 這可以通過 layoutDirection 屬性進行控制,該屬性可以設(shè)置為 Qt.LeftToRight 或 Qt.RightToLeft,具體取決于視圖方向。

6.3.2 鍵盤導(dǎo)航和高亮

在基于觸摸的設(shè)置中使用 ListView 時,視圖本身就足夠了。 在具有鍵盤的場景中,或者甚至只需用箭頭鍵選擇項目,就需要一個指示當(dāng)前項目的機制。 在 QML 中,這稱為高亮顯示。

視圖支持與代理一起顯示在視圖中的高亮代理 。它可以被認(rèn)為是一個額外的代理,但是它只被實例化一次,并被移動到與當(dāng)前項目相同的位置顯示。

下面的例子,將用于展示上述內(nèi)容。有兩個屬性涉及這個工作。首先,focus 屬性要設(shè)置為 true。這給了 ListView 的鍵盤焦點。其次,highlight 屬性設(shè)置為指出要使用的高亮代理。高亮代理被賦予當(dāng)前項的 x,y 和 height 值。如果未指定 width,則也使用當(dāng)前項的寬度。

在示例中,ListView.view.width 附加屬性用于 width 值。代理可以使用的附加屬性將在本章的代理部分進一步討論,但是很高興我們可以提前知道同樣的屬性也可以用于高亮代理之中。

import QtQuick 2.5
import "../common"

Background {
    width: 240
    height: 300

    ListView {
        id: view
        anchors.fill: parent
        anchors.margins: 20

        clip: true

        model: 100

        delegate: numberDelegate
        spacing: 5

        highlight: highlightComponent
        focus: true
    }

    Component {
        id: highlightComponent

        GreenBox {
            width: ListView.view.width
        }
    }

    Component {
        id: numberDelegate

        Item {
            width: ListView.view.width
            height: 40

            Text {
                anchors.centerIn: parent

                font.pixelSize: 10

                text: index
            }
        }
    }
}
listview-highlight

當(dāng)與 ListView 結(jié)合使用高亮?xí)r,可以使用許多屬性來控制其行為。 highlightRangeMode 控制高亮顯示在視圖中顯示的內(nèi)容。默認(rèn)設(shè)置 ListView.NoHighlightRange 意味著視圖中的項目的高亮和可見范圍根本不相關(guān)。

ListView.StrictlyEnforceRange 的值確保高亮顯示始終可見。如果操作嘗試將突出顯示區(qū)域移動到視圖的可見部分之外,則當(dāng)前項目將相應(yīng)更改,以使突出顯示保持可見。

比較中性的值是 ListView.ApplyRange。它試圖保持高亮顯示可見,但不會更改當(dāng)前項以執(zhí)行此操作。 相反,如果需要,高亮顯示可以移出視圖的可視范圍。

在默認(rèn)配置中,視圖負責(zé)將高亮移動到當(dāng)前元素的位置??梢砸运俣然虺掷m(xù)時間來控制移動和調(diào)整大小的速度。涉及的屬性是 highlightMoveSpeed,highlightMoveDuration,highlightResizeSpeed 和 highlightResizeDuration。 默認(rèn)情況下,速度設(shè)置為每秒400像素,持續(xù)時間設(shè)置為-1,表示速度和距離控制持續(xù)時間。 如果同時設(shè)置了速度和持續(xù)時間,則產(chǎn)生最快動畫的設(shè)置生效。

要更加精確地控制高亮的移動,可以將 highlightFollowCurrentItem 屬性設(shè)置為 false。這意味著視圖不再對高亮代理的移動負責(zé)。此時,高亮代理的運動可以通過我們的自定義的 Behavior 或動畫來進行控制。

在下面的示例中,高亮代理的 y 屬性綁定到 ListView.view.currentItem.y 附加屬性。 這樣可確保突出顯示符合當(dāng)前項目。然而,由于我們不讓視圖本身來移動高亮,我們可以控制高亮元素的移動方式。這是通 Behavior on y 的方法完成的。在下面的例子中,移動分為三個步驟:淡出,移動,淡入。請注意 SequentialAnimation 元素如何與 PropertyAnimation 和 NumberAnimation 組合使用,以創(chuàng)建更復(fù)雜的運動動畫效果。

Component {
        id: highlightComponent

        Item {
            width: ListView.view.width
            height: ListView.view.currentItem.height

            y: ListView.view.currentItem.y

            Behavior on y {
                SequentialAnimation {
                    PropertyAnimation { target: highlightRectangle; property: "opacity"; to: 0; duration: 200 }
                    NumberAnimation { duration: 1 }
                    PropertyAnimation { target: highlightRectangle; property: "opacity"; to: 1; duration: 200 }
                }
            }

            GreenBox {
                id: highlightRectangle
                anchors.fill: parent
            }
        }
    }

6.3.3 頁眉和頁腳屬性

在 ListView 內(nèi)容的最后,可以介紹一下 header 和 footer 屬性。這些可以被認(rèn)為是列表開頭或末尾的特殊代理位置。對于水平列表,這些不會出現(xiàn)在頭部或尾部,而是在開始或結(jié)束時顯示,具體取決于所使用的 layoutDirection 屬性的值。

下面的示例說明了如何使用頁眉和頁腳來增強對列表的開始和結(jié)束的感知。這些特殊列表元素還有其他用途。例如,它們可以用于安放一個用于加載更多的內(nèi)容的按鈕。

import QtQuick 2.5
import "../common"

Background {
    width: 240
    height: 300

    ListView {
        anchors.fill: parent
        anchors.margins: 20

        clip: true

        model: 4

        delegate: numberDelegate
        spacing: 2

        header: headerComponent
        footer: footerComponent
    }

    Component {
        id: headerComponent

        YellowBox {
            width: ListView.view.width
            height: 20
            text: 'Header'

        }
    }

    Component {
        id: footerComponent

        YellowBox {
            width: ListView.view.width
            height: 20
            text: 'Footer'
        }
    }

    Component {
        id: numberDelegate

        GreenBox {
            width: ListView.view.width
            height: 40
            text: 'Item #' + index
        }
    }
}

** 注意: **
頁眉和頁腳代理不會實現(xiàn) ListView 的 spacing 屬性,而是緊挨著顯示在列表中的代理。這意味著如果有必要我們必須自己來實現(xiàn)頁眉和頁腳項的 spacing 的效果。

listview-header-footer

6.3.4 網(wǎng)格視圖

使用 GridView 非常類似于使用 ListView。唯一的區(qū)別是網(wǎng)格視圖將代理放置在二維網(wǎng)格而不是線性列表中。

gridview-basic

與列表視圖相比,網(wǎng)格視圖不依賴于間距和其代理的大小。相反,它使用 cellWidth 和 cellHeight 屬性來控制代理內(nèi)容的大小。然后,默認(rèn)情況下每個代理項目都放在每個這樣的單元格的左上角。

import QtQuick 2.5
import "../common"

Background {
    width: 220
    height: 300

    GridView {
        id: view
        anchors.fill: parent
        anchors.margins: 20

        clip: true

        model: 100

        cellWidth: 45
        cellHeight: 45

        delegate: numberDelegate
    }

    Component {
        id: numberDelegate

        GreenBox {
            width: 40
            height: 40
            text: index
        }
    }
}

GridView 包含頁眉和頁腳,可以使用高亮顯示代理,并支持快照模式以及各種邊界行為。它也可以在不同的方向和方向上定向。

使用 flow 屬性控制網(wǎng)格視圖內(nèi)的元素的方向。它可以設(shè)置為 GridView.LeftToRight 或 GridView.TopToBottom。 前一個值從左到右填充網(wǎng)格,從頂部到底部添加行。 視圖可在垂直方向上滾動。 后一個值從頂部到底部添加項目,從左到右填充視圖。 在這種情況下,滾動方向是水平的。

除了 flow 屬性之外,layoutDirection 屬性可以根據(jù)所使用的值,將網(wǎng)格的方向調(diào)整為從左到右或從右到左的視圖。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 翻譯自“Collection View Programming Guide for iOS” 0 關(guān)于iOS集合視...
    lakerszhy閱讀 4,076評論 1 22
  • 6.5 視圖知識進階 6.5.1 PathView PathView 元素是 Qt Quick 中最強大的,也是最...
    趙者也閱讀 1,398評論 0 1
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,616評論 19 139
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,150評論 25 708
  • 最近公司項目有WiFi定位這塊需求,查看一些資料后,看到知乎上有一個回答貌似很正確,貼出來,有哪些不對的地方可以提...
    soulDxl閱讀 5,140評論 1 4

友情鏈接更多精彩內(nèi)容