Статьи

Списки и таблицы для отображения данных в Sailfish OS

Эта статья была рецензирована Марком Таулером . Спасибо всем рецензентам SitePoint за то, что сделали контент SitePoint как можно лучше!


Списки и Сетка являются одним из основных строительных блоков любого мобильного приложения.

В этой статье я собираюсь представить дизайн SilicaListView и SilicaGridView , реализацию Silica этих общих компонентов. Мы увидим несколько примеров того, как отображать типы данных, обрабатывать клики и многое другое, делая код максимально простым.

Дизайн МВД

Интерфейсы Sailfish OS основаны на QML , декларативном языке, предоставляемом QT Framework . Чтобы предоставить разработчику или разработчику контроль над различными аспектами приложения, QT использует шаблон проектирования Model-View-Delegate для модульной визуализации данных.

Шаблон QML Design

Модель содержит данные и их структуру, а представление — это контейнер, который отображает данные. В нашем случае представлением будет список или сетка. Наконец, делегат диктует, как отдельный элемент данных будет отображаться в представлении.

SilicaListView

Давайте начнем с простого примера:

 import QtQuick 2.0 import Sailfish.Silica 1.0 Page { id: page SilicaListView { width: parent.width; height: parent.height model: ListModel { ListElement { name: "Paul"; telephone: "342342341" } ListElement { name: "Laura"; telephone: "343241" } ListElement { name: "Luca"; telephone: "6454341" } ListElement { name: "Daniel"; telephone: "23431231" } ListElement { name: "Seb"; telephone: "666342342341" } ListElement { name: "Carl"; telephone: "55342342341" } } delegate: Item { width: parent.width height: Theme.itemSizeMedium Label { text: name font.pixelSize: Theme.fontSizeMedium anchors { left: parent.left right: parent.right margins: Theme.paddingLarge } } } } } 

Помимо компонентов страницы ( SilicaListView с этой статьей для ознакомления с компонентами Silica), мы объявили SilicaListView с жестко закодированной моделью. Список будет выглядеть так:

Основной список

Каждый ListElement — это объект с двумя свойствами — именем и номером телефона.

Делегат — это просто Item (базовый компонент QML) со свойством width, установленным для заполнения ширины ListView и значением height, установленным с помощью объекта Theme Фактический размер вычисляется во время выполнения, адаптируя его к используемому отображению. ,

Делегат содержит Label с именем контакта. Чтобы показать номер телефона, я могу добавить еще одну метку делегату:

 Item { width: parent.width height: Theme.itemSizeMedium anchors { left: parent.left right: parent.right margins: Theme.paddingLarge } Label { id: cName text: name font.pixelSize: Theme.fontSizeMedium anchors { left: parent.left right: parent.right } } Label { text: "Tel: " + telephone font.pixelSize: Theme.fontSizeSmall anchors { left: parent.left + Theme.paddingSmall right: parent.right top: cName.bottom } } 

Показывается также номер телефона

Модель и Делегат могут быть определены встроенными, но по мере того, как модели становятся больше, лучше переместить их в другой файл QML.

Например, вы можете создать файл ContactsModel.qml с таким содержимым:

 import QtQuick 2.0 ListModel { ListElement { name: "Paul"; telephone: "342342341"; team: "IT" } ListElement { name: "Laura"; telephone: "343241"; team: "IT"} ListElement { name: "Luca"; telephone: "6454341"; team: "IT" } ListElement { name: "Daniel"; telephone: "23431231"; team: "Sales" } ListElement { name: "Seb"; telephone: "666342342341"; team: "Sales" } ListElement { name: "Carl"; telephone: "55342342341"; team: "Sales" } } 

И использовать его в качестве модели списка:

  model: ContactsModel {} 

Я добавил свойство команды для использования в следующем примере.

List иногда необходимо разделить на разделы. Сделайте это, используя свойство section чтобы определить ключ модели, используемый в качестве элемента группировки, и делегат для использования в качестве заголовка раздела.

Определите свойство раздела в SilicaListView :

  section { property: "team" criteria: ViewSection.FullString delegate: SectionHeader { text: section } } 

Список с разделом

Теперь пришло время обрабатывать события кликов и реагировать на них.

  MouseArea { anchors.fill: parent onClicked: { var name = list.model.get(index).name console.log(name); } 

Мы определили элемент MouseArea заполняющий наш делегат. Таким образом, мы можем отловить и обработать событие click и получить элемент clicked, используя свойство list get и index .

Каждый список может иметь верхний и нижний колонтитулы, прикрепленные к соответствующему свойству списка. Это полезно, поскольку вы не должны включать SilicaListView или GridView в другой элемент Scrollable. Если вам нужно содержимое до или после списка / сетки, используйте эти свойства.

 SilicaListView { id:list width: parent.width; height: parent.height model: ContactModel {} header: MyHeader {} footer: Button { width: parent.width anchors.margins: Theme.paddingSmall text: "Load more..." onClicked: console.log("clicked!") } section { property: "team" criteria: ViewSection.FullString delegate: SectionHeader { text: section } } delegate: Item { width: parent.width height: Theme.itemSizeMedium anchors { left: parent.left right: parent.right margins: Theme.paddingLarge } Label { id: cName text: name font.pixelSize: Theme.fontSizeMedium anchors { left: parent.left right: parent.right } } Label { text: "Tel: " + telephone font.pixelSize: Theme.fontSizeSmall anchors { left: parent.left right: parent.right top: cName.bottom } } MouseArea { anchors.fill: parent onClicked: { var name = list.model.get(index).name console.log(name); } } } } 

Мы можем объявить объекты встроенными или в отдельном файле. В качестве примера я создал файл MyHeader.qml с этим содержимым и объявил нижний колонтитул встроенным:

 import QtQuick 2.0 import Sailfish.Silica 1.0 PageHeader { title: "Numbers" } 

Наш список с колонтитулами

модели

Чтобы упростить жизнь разработчика QML, определите набор готовых к использованию моделей, таких как SqliteModel , XmlListModel и SparqlModel . Вы можете определить свои собственные модели, используя C ++ QT API .

Например, мы можем отобразить последние новости Sitepoint, используя RSS-канал сайта. Давайте определим нашу модель, используя предопределенный XmlListModel :

 XmlListModel { id: feedModel source: "http://www.sitepoint.com/feed/" query: "/rss/channel/item" XmlRole { name: "title"; query: "title/string()" } XmlRole { name: "link"; query: "link/string()" } XmlRole { name: "description"; query: "description/string()" } XmlRole { name: "pubDate"; query: "pubDate/string()" } } 

Здесь мы определяем источник канала и свойство запроса, которые устанавливают область для модели. Будут использоваться только дочерние <item> , а три XmlRole действуют как свойство внутри ListElement .

Теперь мы можем сделать наше представление списка, используя эту модель, полный пример выглядит следующим образом:

 import QtQuick 2.0 import Sailfish.Silica 1.0 import QtQuick.XmlListModel 2.0 Page { id: page SilicaListView { id:list width: parent.width; height: parent.height model: XmlListModel { id: feedModel source: "http://www.sitepoint.com/feed/" query: "/rss/channel/item" XmlRole { name: "title"; query: "title/string()" } XmlRole { name: "link"; query: "link/string()" } XmlRole { name: "description"; query: "description/string()" } XmlRole { name: "pubDate"; query: "pubDate/string()" } } header: MyHeader {} footer: Button { width: parent.width anchors.margins: Theme.paddingSmall text: "Load more..." onClicked: console.log("clicked!") } delegate: Item { width: parent.width height: Theme.itemSizeMedium anchors { left: parent.left right: parent.right margins: Theme.paddingLarge } Label { id: cName text: title font.pixelSize: Theme.fontSizeSmall anchors { left: parent.left right: parent.right } } MouseArea { anchors.fill: parent onClicked: { var name = list.model.get(index).name console.log(title); } } } } } 

Модель XmlList

Нам нужно обратиться к ситуациям, когда у нас нет элементов для отображения, например, когда канал все еще загружается.

Мы можем использовать элемент ViewPlaceholder для обработки этого, ViewPlaceholder его видимость к свойству count представления списка:

 ViewPlaceholder { enabled: list.count == 0 text: "Loading..." hintText: "Be patient my friend" } 

Пустой список

Модели в Js

Если вам нужно сгенерировать модель точно в срок , вы можете использовать javascript. Мы получаем и отображаем список чисел от 1 до 100 следующим образом:

 import QtQuick 2.0 import Sailfish.Silica 1.0 Page { id: page SilicaListView { id:list width: parent.width; height: parent.height model: ListModel { id: myJSModel } header: MyHeader {} footer: Button { width: parent.width anchors.margins: Theme.paddingSmall text: "Load more..." onClicked: console.log("clicked!") } delegate: Item { width: parent.width height: Theme.itemSizeMedium Label { text: value font.pixelSize: Theme.fontSizeMedium anchors { left: parent.left right: parent.right margins: Theme.paddingLarge } } MouseArea { anchors.fill: parent onClicked: { var value = list.model.get(index).value console.log(value); } } } Component.onCompleted: { for(var i=0;i<=100;i++) { var myElement = { "value" : i } myJSModel.append(element) } } } } 

myElement может быть произвольным объектом javascript, и мы можем добавить столько свойств, сколько необходимо, и использовать их в нашем делегате.

Мы определили модель JavaScript в событии Component.onCompleted . При этом наш код вызывается, когда связанные компоненты готовы и отображаются.

GridViews

GridView действует аналогично списку, разделяя большинство свойств.

 import QtQuick 2.0 import Sailfish.Silica 1.0 Page { id: page SilicaGridView { id:list width: parent.width; height: parent.height cellWidth: width / 2 cellHeight: width / 2 model: ListModel { id: myJSModel } header: MyHeader {} delegate: Item { width: list.cellWidth height: list.cellHeight Label { text: value font.pixelSize: Theme.fontSizeMedium anchors { left: parent.left right: parent.right margins: Theme.paddingLarge } } MouseArea { anchors.fill: parent onClicked: { var value = list.model.get(index).value console.log(value); } } } Component.onCompleted: { for(var i=0;i<=100;i++) { var element = { "value" : i } myJSModel.append(element) } } } } 

Список JS

JS Grid

Мы должны определить еще два свойства, такие как представление списка, cellWidth и cellHeight , которые cellHeight сами за себя.

Вывод

Списки и таблицы популярны, но их не всегда легко реализовать.

Благодаря QML Sailfish имеет один из самых чистых и удобных API-интерфейсов, касающихся этих двух важнейших компонентов, что позволяет разработчику без особых усилий создать удобный пользовательский интерфейс.

Я хотел бы услышать ваши мысли и комментарии, и если вы уже пробовали какую-либо разработку Sailfish.