skip to Main Content

Simulator

#this is just an example of the code so when i longpress the "Text("Long press for menu")" and is showing the contextmenu to change the background color:

 struct ContentView: View {
   var body: some View {
        Text("Long press for menu")
            .contextMenu {
                Button {
                    print("Pills selected")
                } label: {
                    Label("Pills", systemImage: "pills")
                }

                Button {
                    print("Heart selected")
                } label: {
                    Label("Heart rate", systemImage: "heart")
                }

                Button {
                    print("ECG selected")
                } label: {
                    Label("ECG", systemImage: "waveform.path.ecg")
                }
            }
    }
}```

2

Answers


  1. The issue is the contextMnenu is creating a rectangle around the text, and this rectangle seems to hate transparency like Color.clear or opacity applied to white. As I’ve become accostumed to say "SwiftUI never cease to suprprise me (both in good and bad ways)". So you need to build your custom menu for that. You can get away with something like the following:

    struct ContextMenuDetectOpenClose: View {
    
    @State private var isContextMenuOpen = false
    private let items: [Item] = [
        .init(title: "Pills", icon: "pills"),
        .init(title: "Heart rate", icon: "heart"),
        .init(title: "ECG", icon: "waveform.path.ecg")
    ]
    
    var body: some View {
        ZStack {
            Text("Long press for menu")
                .padding(4)
                .background(isContextMenuOpen ? .gray : .clear, in: .rect(cornerRadius: 8))
                .foregroundStyle(.white)
                .background(.clear)
                .onLongPressGesture {
                    withAnimation {
                        isContextMenuOpen = true
                    }
                }
                .overlay(alignment: .top) {
                    if isContextMenuOpen {
                        MenuList()
                            .offset(y: 40)
                    }
                }
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .background(.black)
        .onTapGesture {
            withAnimation {
                isContextMenuOpen = false
            }
        }
    }
    
    @ViewBuilder
    func MenuList() -> some View {
        VStack {
            ForEach(items) { item in
                
                HStack {
                    Text(item.title)
                    Spacer(minLength: 0)
                    Image(systemName: item.icon)
                }
                .font(.title3)
                .fontWeight(.semibold)
                .frame(height: 50)
                .padding(.horizontal, 8)
                .clipShape(.rect)
                .onTapGesture {
                    print("On tap (item.title)")
                    withAnimation {
                        isContextMenuOpen = false
                    }
                }
                
            }
        }
        
        .frame(width: 250, height: 180)
        .background(.white.opacity(0.8), in: .rect(cornerRadius: 15, style: .continuous))
    }
    
    struct Item: Identifiable {
        let id = UUID()
        let title: String
        let icon: String
    }
    

    }

    Let me know if that helped!

    Login or Signup to reply.
  2. You can change the color using preview for the .contextMenu:

    struct ContentView: View {
        var body: some View {
            TextView()
                .contextMenu {
                    Button {
                        print("Pills selected")
                    } label: {
                        Label("Pills", systemImage: "pills")
                    }
                    
                    Button {
                        print("Heart selected")
                    } label: {
                        Label("Heart rate", systemImage: "heart")
                    }
                    
                    Button {
                        print("ECG selected")
                    } label: {
                        Label("ECG", systemImage: "waveform.path.ecg")
                    }
                } preview: {
                    TextView(isPreview: true)
                }
        }
    }
    
    struct TextView: View {
     
        var isPreview: Bool = false
        
        var body: some View {
            Text("Long press for menu")
                .padding()
                .foregroundStyle(Color(isPreview ? .white : .label))
                .background(Color(isPreview ? .black : .systemBackground))
        }
    }
    

    Here is the result (I just added .padding modifier to make this view more appeal):

    final result

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search