Rearrange rows in a list in SwiftUI

In this tutorial, we will see how to rearrange rows in a list in SwiftUI.

Row movement within a list is simple with SwiftUI for iOS 16.0 or later, but older iOS versions require a more complicated technique.

Additionally, there’s the option to selectively disable row movement using the moveDisabled() modifier, allowing control over which rows users can or cannot rearrange within the list.

Simple Approach

This is a great way when we want to change the order of rows in a list without using complicated rules. To implement it, we need to bind our data to the list and utilize the editActions parameter.

Example

import SwiftUI

struct ContentView: View {
    @State private var userList = ["Sam", "Rayan", "Nick", "Jack"]

    var body: some View {
        NavigationStack {
            List($userList, id: \.self, editActions: .move) { $user in
                Text(user)
            }
            .toolbar {
                EditButton()
            }
        }
    }
}

In the above program, the editActions: .move part specifies the type of edit actions that are allowed on the list. In this case, it is set to .move, which means users can rearrange the items in the list by dragging them.

The toolbar is used to add an Edit button in our app. This Edit button is a standard SwiftUI component that toggles the edit mode for the list. When we tap this button it enables the edit mode in the list allowing users to rearrange or delete items.

Output:

Rearrange rows in a list in SwiftUI

Disabling Movement for Specific Rows

If we don’t want a particular row in our list to change places when we are rearranging rows, we can use the moveDisabled() modifier.

For example, if we want “Sam” to always be at the top of the list, then we can use this method to prevent it from being rearranged.

Example

import SwiftUI

struct ContentView: View {
    @State private var userList = ["Sam", "Rayan", "Nick", "Jack"]

    var body: some View {
        NavigationStack {
            List($userList, id: \.self, editActions: .move) { $user in
                Text(user)
                    // Specify moveDisabled to disable moving the item with the name "Sam" 
                    .moveDisabled(user == "Sam")
            }
            .toolbar {
                EditButton()
            }
        }
    }
}

In the above program, the .moveDisabled(user == "Sam") modifier stops the row with “Sam” from being moved in the list. Other rows can still be rearranged by dragging them, but the one with “Sam” stays where it is.

Output:

Rearrange rows in a list in SwiftUI

Using the onMove() modifier

The onMove() modifier allows us to enable the reordering of rows in a list. So, we can rearrange rows in a list using the onMove() modifier in combination with List.

Now, have a look at the example below.

import SwiftUI

struct ContentView: View {
    @State private var userList = ["Sam", "Rayan", "Nick", "Jack"]

    var body: some View {
        NavigationStack {
            List {
                ForEach(userList, id: \.self) { item in
                    Text(item)
                }
                // Enable the ability to rearrange rows
                .onMove { indices, newOffset in
                    // Rearrange the userList based on user interaction
                    userList.move(fromOffsets: indices, toOffset: newOffset)
                }
            }
            .toolbar {
                // Add an "Edit" button to the navigation bar
                EditButton()
            }
        }
    }
}

In the above program, the onMove() modifier is applied to the List, that will enable the ability to rearrange rows. When we move a row, the closure will be called, and it will rearrange the userList based on the provided indices and the new offset.

Output:

Rearrange rows in a list in SwiftUI

Leave a Reply

Your email address will not be published. Required fields are marked *