Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Normal Tap & Swipe actions while in EditMode?

I'm developing an app, one view of which has the primary goal of allowing users to reorder a List of NavigationLinks, but which I would also like to allow navigation & a few other things. I want users to be able to:

  1. Reorder by dragging on the reorder control.
  2. Navigate to the link by tapping elsewhere on the row.
  3. Swipe from the leading edge to activate a swipe action.

At the moment, enabling EditMode (to allow reordering) disables navigation & swipe actions; I haven't been able to find a workaround that allows all 3 functions simultaneously. Is there a good way to do this?

Here's an example:

struct ReorderableListView: View {
    var items: [X] // List of custom objects
    var body: some View {
       NavigationView {
           List {
               ForEach(items) { item in
                   NavigationLink(destination: CustomView(item)) { // winds up disabled by edit mode
                      Text(item.name)
                   }
                   .swipeActions(edge: .leading) { Button("Swipe") {print("swipe")} } // winds up disabled by edit mode
               }
               .onMove { from, to in
                   print("move \(from)  to \(to)")
               }
           }
           .environment(\.editMode, .constant(.active)) // always in edit mode for reordering
       }
    }
}

Update:

Based on the accepted answer, it looks like this behavior got updated in iOS 16: Now, if onMove is implemented, you can reorder with a long press even when not in edit mode, which allows these three actions to coexist. I've added custom drag-handles to make this behavior obvious to the user, but otherwise I'm going with exactly the solution given in the accepted answer, below.

like image 242
lelandpaul Avatar asked Mar 23 '26 06:03

lelandpaul


1 Answers

I am not sure that the .environment is necessary in this case (I could be wrong). You can remove that piece.

Additionally, you should add an ID to each item in your foreach. This should ideally come from your model when you create new items (for example, your model can contain an ID variable = UUID()), but for the time being we can add it inline in your foreach.

I had to write some code on my end to get this up and running, so my solution is based on the code I spun up (very similar to yours, but missing your custom items object):

    struct ReorderableListView: View {
    var items: [X] // List of custom objects
    var body: some View {
       NavigationView {
           List {
                    // added ID here
               ForEach(items, id: \.self) { item in
                   NavigationLink(destination: CustomView(item)) { // winds up disabled by edit mode
                      Text(item.name)
                   }
                   .swipeActions(edge: .leading) { Button("Swipe") {print("swipe")} } // winds up disabled by edit mode
               }
               .onMove { from, to in
                   print("move \(from)  to \(to)")
               }
           }
          // REMOVED .environment(\.editMode, .constant(.active)) // always in edit mode for reordering
       }
    }
}

For reference, here is the code I wrote locally to fill in the gaps. This is what worked & what I implemented within your code:

    struct ReorderableListView: View {
    @State var items = [1, 2, 3] // List of custom objects
    var body: some View {
        NavigationView {
            List {
                ForEach(items, id: \.self) { item in
                    NavigationLink(destination: ContentView2()) { // winds up disabled by edit mode
                        Text("\(item)")
                    }
                    .swipeActions(edge: .leading) { Button("Swipe") {print("swipe")} } // winds up disabled by edit mode
                }
                .onMove { from, to in
                    print("move \(from)  to \(to)")
                }
            }
         //   .environment(\.editMode, .constant(.active)) // always in edit mode for reordering
        }
    }
}
like image 185
nickreps Avatar answered Mar 25 '26 03:03

nickreps



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!