In this article we’ll see the different use of the lists that is a very most used components in the mobile apps. We starting with SwiftUI, code the example show how create a simple list and the right swipe action to delete a row.
struct ContentView: View {
@State var names = ["Albert", "Tom", "Jeff", "Jennifer", "Steve", "Bob"]
var body: some View {
List {
ForEach(names.indices, id: \.self) { index in
Text(self.names[index]) // Delegate
}
.onDelete { (indexSet) in
self.names.remove(atOffsets: indexSet)
}
}
}
}
The list is created with the keyword List, with For each for every elements of the array names is created an object Text that show the single name. If the model is more complex that a simple list of name and we have to show also an image we can add in the For each block the Image object.
The instruction “id: .self” is necessary to identify every single row in unique way, in this case this identifier is the index of the array. Other important keyword is “@State” with this we say to SwiftUi to monitoring the variable names and update the ui when it changes.
In the on Delete function we do the action the we want doing the right swipe, in this case delete the element. Before to switch to QML, we see an example a bit more complex:
struct People: Identifiable {
var id = UUID()
var name: String
var image: String
}struct ContentView: View {
@State var peoples = [People(name:"Albert", image: "albert.png"), People(name: "Tom", image: "tom.png"),People(name: "Jeff", image:"jeff.png"),People(name: "Jennifer",image: "jennifer.png"), People(name: "Steve", image: "steve.png"), People(name: "Bob", image: "bob.png")]
var body: some View {
List {
ForEach(peoples, id: \.id) { people in
HStack {
Text(people.name)
Image(people.image)
}
}
.onDelete { (indexSet) in
self.peoples.remove(atOffsets: indexSet)
}
}
}
}
In this case we have the struct People that implements the protocol Identifiable, so we have am unique identifier for any instance of the struct. In the ForEach we now use it do identify the row also added a horizonthal stack to create a row with text and image. Now see that same example in QML:
ListView {
id: listView
anchors.fill: parent
model: ListModel {
ListElement { img: "bob.png"; name: "Bob" }
ListElement { img: "jennifer.png"; name: "Jennifer" }
ListElement { img: "tom.png"; name: "Tom" }
ListElement { img: "denise.png"; name: "Denise" }
}
delegate: SwipeDelegate {
id: swipeDelegate
text: model.name
width: parent.width
ListView.onRemove: SequentialAnimation {
PropertyAction {
target: swipeDelegate
property: "ListView.delayRemove"
value: true
}
NumberAnimation {
target: swipeDelegate
property: "height"
to: 0
easing.type: Easing.InOutQuad
}
PropertyAction {
target: swipeDelegate
property: "ListView.delayRemove"
value: false
}
}
contentItem: Item {
RowLayout {
Text {
text: swipeDelegate.text
font: swipeDelegate.font
elide: Text.ElideRight
visible: swipeDelegate.text
horizontalAlignment: Text.AlignLeft
verticalAlignment: Text.AlignVCenter
}
Image {
source: model.img
visible: swipeDelegate.text
horizontalAlignment: Text.AlignLeft
verticalAlignment: Text.AlignVCenter
}
}
}
swipe.right: Label {
id: deleteLabel
text: qsTr("Delete")
color: "white"
verticalAlignment: Label.AlignVCenter
padding: 12
height: parent.height
anchors.right: parent.right
SwipeDelegate.onClicked: listView.model.remove(index)
background: Rectangle {
color: deleteLabel.SwipeDelegate.pressed ? Qt.darker("tomato", 1.1) : "tomato"
}
}
}
}
In this case the QML is a bit more complex because we have to customize the label to have the same look & feel of iOS but in QML we don’t need to use any “@State” keyword to force the gui update.
At the end I think that it’s simple for QML developer to use SwiftUI, a lot of things are similar and both the languages are declaratives. Instead I think that for iOS developer is not simple to use both, is necessary more experience in the declarative world.