DisclosureGroup with Swipe Actions and Contextual Menu

I have created a simple case to make my point as follows.

import SwiftUI

struct ContentView: View {
	var body: some View {
		ZStack {
			Color.yellow.ignoresSafeArea()
			VStack(alignment: .leading) {
				ForEach(Fruit.allCases, id: \.self) { fruit in
					DisclosureGroup(fruit.rawValue) {
						VStack {
							Text("1")
							Text("2")
							Text("3")
						}
					}
					.contextMenu {
						Button("Hello", action: {

						})
					}
				}
			}.padding(.horizontal, 20)
		}
	}
}

enum Fruit: String, CaseIterable {
	case apple = "Apple"
	case grape = "Grape"
	case lemon = "Lemon"
	case orange = "Orange"
	case peach = "Peach"
	case pineapple = "Pineapple"
	case watermelon = "Watermelon"
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

What I want to do is show the contextual menu when the user long-presses a fruit name, which works. Yet, if I long-press a child inside the disclosure view, I also get the contextual menu, which is unintentional. Is there a simple way by which I can stop the contextual menu to appear if long-press a child inside the disclosure view?

Muchos thankos

Accepted Reply

You can apply the context menu to the label of the disclosure group instead of the whole thing. Something like this works:

DisclosureGroup {
    VStack {
        Text("1")
        Text("2")
        Text("3")
    }
} label: {
    Text(fruit.rawValue)
        .contextMenu {
            Button("Hello", action: {

            })
        }
}

You will have to long press on the text itself to show the context menu instead of anywhere on the row. You can just change the bounds of the text label if you want that behaviour.

  • Thanks. I'll take a look.

  • Yes, that's exactly what I need. That's excellent! Thanks a lot.

Add a Comment

Replies

You can apply the context menu to the label of the disclosure group instead of the whole thing. Something like this works:

DisclosureGroup {
    VStack {
        Text("1")
        Text("2")
        Text("3")
    }
} label: {
    Text(fruit.rawValue)
        .contextMenu {
            Button("Hello", action: {

            })
        }
}

You will have to long press on the text itself to show the context menu instead of anywhere on the row. You can just change the bounds of the text label if you want that behaviour.

  • Thanks. I'll take a look.

  • Yes, that's exactly what I need. That's excellent! Thanks a lot.

Add a Comment