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 ForEach 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 ForEach 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 onDelete 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.