Layout, ListView e schede
Disporre i contenuti
Ora che abbiamo capito come funzionano le pagine, è il momento di aggiungervi qualcosa. Esamineremo una serie di importanti componenti ed elementi di layout che saranno utili durante la progettazione della nostra app.
Alla fine di questa sezione avrai un'applicazione dall'aspetto ordinato.
Viste a elenco
Se hai mai utilizzato Discover, NeoChat o le Impostazioni di sistema di Plasma, ti sarai imbattuto in una ListView. Molto semplicemente, ti consente di visualizzare i dati in un elenco.
pageStack.initialPage: Kirigami.ScrollablePage {
// ...
Kirigami.CardsListView {
id: cardsView
model: kountdownModel
delegate: kountdownDelegate
}
}Sembra criptico, ma non preoccuparti. Cominciamo dall'inizio.
Aggiungiamo questo componente all'interno del nostro Kirigami.ScrollablePage dall'ultimo tutorial.
Stiamo utilizzando Kirigami.CardsListView, che è un ListView che ci consente di visualizzare facilmente le schede in un elenco. Tuttavia, i ListView sono progettati per mostrare i dati presi da un modello, per popolarsi automaticamente da un insieme di dati a cui li indichiamo. È qui che entra in gioco la proprietà model: in questo esempio punta a "kountdownModel".
Modello
Kirigami.ApplicationWindow {
// ...
ListModel {
id: kountdownModel
// Ciascun ListElement è un elemento della lista, contenente le informazioni
ListElement {
name: "Dog birthday!!"
description: "Big doggo birthday blowout."
date: 100
}
}
// ...
}Aggiungiamo il nostro kountdownModel all'interno di Kirigami.ApplicationWindow dall'ultimo tutorial.
Un modello definisce il modo in cui è strutturata l'immissione di dati. Il nostro kountdownModel sarà composto da un solo elemento per ora. Osservando il nostro ListElement sopra, possiamo vedere come sono strutturati i dati del nostro kountdownModel: contiene un nome, una descrizione e una data. Questo non è scolpito nella pietra e potresti avere diversi tipi di dati nel tuo modello. I primi due sono solo stringhe e il terzo è un numero che utilizziamo come segnaposto.
Nota
Poiché QML è basato su JavaScript, molte delle funzionalità di questo linguaggio sono disponibili per l'uso nei file QML. Tuttavia, le variabili QML devono avere il prefisso "property", a meno che non si trovino all'interno di un blocco di codice JS. Puoi leggere ulteriori informazioni a riguardo in questa pagina.I modelli sono utili anche nel modo in cui possono essere modificati mediante l'uso di diversi metodi. Alcuni importanti sono:
- ListModel.append(yourobject: jsobject) aggiunge un oggetto JavaScript (JSObject) "yourobject" al ListModel e lo posiziona dopo l'ultimo elemento nel modello. Affinché ciò avvenga correttamente, è necessario fornire un JSObject con le proprietà corrette e i tipi di dati corrispondenti.
- ListModel.get(index: int) restituisce JSObject nella posizione dell'indice fornita.
- ListModel.remove(index: int, count: int) rimuove il JSObject nella posizione "index" fornita e tanti dopo tale posizione dell'indice quanti ne hai inseriti in "count" (1 include solo JSObject nell'indice fornito)
- ListModel.set(index: int, yourobject: jsobject) modifica l'elemento nella posizione
indexfornita con i valori forniti inyourobject. Stesse regole diappend().
Delegati
Mentre il nostro kountdownModel contiene i dati che saranno visualizzati, il nostro kountdownDelegate gestirà il modo in cui i dati saranno visualizzati in ListView. Per questo usiamo un Kirigami.CardsListView progettato per visualizzare i delegati di tipo scheda e tali delegati saranno rappresentati visivamente per mezzo di un Kirigami.AbstractCard.
I delegati ricevono automaticamente le proprietà delle istanze ListElement che abbiamo specificato nel nostro modello. Possiamo quindi semplicemente fare riferimento alle loro proprietà "nome", "descrizione" e "data" come se fossero variabili convenzionali all'interno del nostro delegato.
Costruire la tessera del delegato
Il Componente che rappresenterà il nostro delegato può essere aggiunto all'interno della nostra Kirigami.ApplicationWindow. Controlleremo quindi cosa fa ciascuna parte del nostro componente delegato.
Kirigami.ApplicationWindow {
// ...
Component {
id: kountdownDelegate
Kirigami.AbstractCard {
contentItem: Item {
// implicitWidth /Height definiscono la larghezza e l'altezza naturali di un
// elemento, se queste non vengono specificate. L'impostazione qui sotto definisce
// la dimensione preferita del componente in base al suo contenuto.
implicitWidth: delegateLayout.implicitWidth
implicitHeight: delegateLayout.implicitHeight
GridLayout {
id: delegateLayout
anchors {
left: parent.left
top: parent.top
right: parent.right
}
rowSpacing: Kirigami.Units.largeSpacing
columnSpacing: Kirigami.Units.largeSpacing
columns: root.wideScreen ? 4 : 2
Kirigami.Heading {
level: 1
text: date
}
ColumnLayout {
Kirigami.Heading {
Layout.fillWidth: true
level: 2
text: name
}
Kirigami.Separator {
Layout.fillWidth: true
visible: description.length > 0
}
Controls.Label {
Layout.fillWidth: true
wrapMode: Text.WordWrap
text: description
visible: description.length > 0
}
}
Controls.Button {
Layout.alignment: Qt.AlignRight
Layout.columnSpan: 2
text: i18n("Edit")
// onClicked: da fare... presto!!
}
}
}
}
}
// ...
}implicitWidth e implicitHeight
La prima parte a cui daremo un'occhiata è come gestire la larghezza e l'altezza del nostro componente:
Kirigami.AbstractCard {
contentItem: Item {
implicitWidth: delegateLayout.implicitWidth
implicitHeight: delegateLayout.implicitHeight
GridLayout {
id: delegateLayout
// ...
}
}
}Osservando la nostra Kirigami.AbstractCard, le prime proprietà che impostiamo sono implicitWidth e ImplicitHeight. Li abbiamo impostati su delegateLayout.implicitWidth e delegateLayout.implicitHeight, ovvero implicitWidth e implicitHeight dell'elemento GridLayout.
Le larghezze e le altezze implicite sono proprietà disponibili in qualsiasi Item che funzionano come suggerimenti e sono impostate come predefinite o come fallback, se non esiste una larghezza o un'altezza esplicita impostata per questi componenti. Questi valori sono 0x0 per impostazione predefinita, quindi è molto importante definirli nei componenti grezzi dell'articolo come fatto sopra.
Qui abbiamo impostato implicitWidth e implicitHeight della nostra Kirigami.AbstractCard su quella del GridLayout di seguito per garantire che non fuoriesca dalla scheda. In questo modo la scheda occupa tutto lo spazio necessario per il suo contenuto.
Disposizioni
Il GridLayout è all'interno del componente Item che abbiamo fornito per la proprietà contentItem. Questo è l'Articolo che contiene ciò che sarà visualizzato nella tua scheda.
Dobbiamo anche scegliere un layout per i nostri componenti in modo che non si accumulino uno sopra l'altro. Esistono tre tipologie principali tra cui possiamo scegliere:
- ColumnLayout dispone i componenti verticalmente, in un'unica colonna
- RowLayout dispone i componenti orizzontalmente, in un'unica riga
- GridLayout dispone i tuoi componenti in una griglia con una composizione a tua scelta
With ColumnLayout and RowLayout, all we have to do is write our components inside the Layout component. Come puoi vedere, abbiamo optato per un GridLayout, che comporta un po' più di lavoro manuale.
GridLayout {
id: delegateLayout
anchors {
left: parent.left
top: parent.top
right: parent.right
}
rowSpacing: Kirigami.Units.largeSpacing
columnSpacing: Kirigami.Units.largeSpacing
columns: root.wideScreen ? 4 : 2
// ...
}La prima cosa che vedi sono le nostre "ancore". Il sistema di ancoraggio di QtQuick fornisce un modo utile per assicurarsi che i componenti siano posizionati in determinate parti di un componente principale. Abbiamo ancorato il nostro GridLayout a sinistra, in alto e a destra della scheda principale, assicurando che i nostri contenuti si estendano su tutta la scheda.
Successivamente specifichiamo la spaziatura tra le righe e le colonne all'interno della nostra griglia, in modo che i nostri componenti non si accumulino. Kirigami fornisce una serie di utili unità predefinite da utilizzare per questo scopo:
| Unità in Kirigami | Pixel |
|---|---|
| smallSpacing | 4px |
| largeSpacing | 8px |
| gridUnit | 18px |
Nota
Il Visual Design Group (VDG) di KDE ha molte più informazioni sulle diverse unità definite in Plasma e Kirigami nelle Linee guida per l'interfaccia umana.Come forse ricorderete, root è l'id della nostra Kirigami.ApplicationWindow. Fornisce la proprietà wideScreen, utilizzata per determinare se lo schermo del dispositivo corrente è widescreen (cioè il monitor di un computer o un telefono in orizzontale). Usiamo un condizionale ternario qui per variare il numero di colonne nella nostra griglia a seconda dello schermo che stiamo utilizzando: se è un widescreen, la griglia avrà 4 colonne, altrimenti ne avrà 2.
Componenti interni
Potremmo semplicemente creare tre etichette all'interno del nostro componente delegato e concludere la giornata, ma non sembrerebbe particolarmente carino. Utilizzeremo alcuni componenti più convenienti:
GridLayout {
// ...
Kirigami.Heading {
Layout.fillHeight: true
level: 1
text: date
}
ColumnLayout {
Kirigami.Heading {
Layout.fillWidth: true
level: 2
text: name
}
Kirigami.Separator {
Layout.fillWidth: true
visible: description.length > 0
}
Controls.Label {
Layout.fillWidth: true
wrapMode: Text.WordWrap
text: description
visible: description.length > 0
}
}
Controls.Button {
Layout.alignment: Qt.AlignRight
Layout.columnSpan: 2
text: i18n("Edit")
}
}
Come appare la scheda personalizzata
- A sinistra, Kirigami.Heading: utilizza la "data" di "ListElement" come intestazione di livello 1.
- Al centro, ColumnLayout: ha un Kirigami.Heading che visualizza il nome dell'attività; un Kirigami.Separator, che fornisce la linea orizzontale; e un Controls.Label, che visualizza la descrizione facoltativa di un'attività. Gli ultimi due componenti hanno una proprietà visible, che controlla se la descrizione è vuota o meno e visualizza i componenti in base al risultato di
description.length > 0. - Giusto, Controls.Button: un pulsante che farà qualcosa... presto!
Il nostro programma finora
Main.qml:
| |

Ecco quindi una scheda basilare!
Con questi passaggi, adesso abbiamo gettato le basi per aggiungere tutte le funzionalità al nostro programma.