Rearranging List with DisclosureGroups in edit mode
Asked Answered
I

1

7

I am trying to rearrange List rows when in edit mode.

Quick summary: I want DisclosureGroup rows like Second to not be inserted into their own children's hierarchy. It's fine if they go into any other hierarchy/level.

Below is some example code:

struct ContentView: View {
    var body: some View {
        List {
            ForEach(0 ..< 1) { _ in
                DisclosureGroup("First", isExpanded: .constant(true)) {
                    ForEach(0 ..< 1) { _ in
                        Text("Item 1")
                        Text("Item 2")

                        DisclosureGroup("Second", isExpanded: .constant(true)) {
                            // Individual
                            Text("Item 3")
                            Text("Item 4")

                            // Grouped
//                            ForEach(0 ..< 1) { _ in
//                                Text("Item 3")
//                                Text("Item 4")
//                            }
                        }
                    }
                }
            }
            .onMove(perform: { _, _ in })
        }
        .listStyle(.sidebar)
        .environment(\.editMode, .constant(.active))
    }
}

This is what the line comments mean:

  • Individual: this will allow the rows to move freely within the current level, but also means the DisclosureGroup row can move between these elements (not wanted)
  • Grouped: this will 'lock' these views into this level of the hierarchy. For example Item 3 and Item 4 can be swapped rows, however these rows can no longer be dragged somewhere else such as between Item 1 and Item 2.

When a DisclosureGroup row is dragged, either:

  1. All the children should be dragged along with it.
  2. This DisclosureGroup row should not be inserted between any of its own children.

We are purely focusing on visual UI for now, hence why the onMove(perform:) method is not completed.

Individual method Grouped method
individual grouped

Notes:

  • Individual method: The Second row can be moved to the same layer as Item 3 and Item 4, which should not be allowed. However, it does allow Item 3 and Item 4 to be between Item 1 and Item 2.

  • Grouped method: Item 3 and Item 4 are 'locked' into their own level - no views can be inserted between, nor can they move to the same level as Item 1 and Item 2 (bad). However, in this case Second cannot move into its own children's hierarchy (good).

How can I fix this, so I basically have the 'individual method', but DisclosureGroup rows like Second cannot be inserted into their own children's hierarchy? It's fine if they go into any other hierarchy/level.

I realise this is quite a complex question - so try the code for yourself and watch the GIFs to understand.

If it functions correctly, I'll accept a UIKit solution too (such as with UICollectionView?).

Idioblast answered 5/9, 2021 at 20:31 Comment(1)
@MihaiFratu Nope, sorry - I still am looking for a solution too.Idioblast
V
0

Unfortunately, .onMove does not currently work with nested ForEach. I've been working on this as well, and the only thing I've found is flattening the array, and writing functions for handling the movement of nested items:

Flattened List Gif.

Vina answered 11/6, 2023 at 22:28 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.