15

If I create a Menu in SwiftUI (iOS), I cannot set the color of the Buttons inside, e.g.:

Menu("Actions") {
    Button(action: { }) {
        Label("Whatever", systemImage: "pencil")
             .background(Color.red)  // does not work
    }
    .background(Color.red)           // does not work either
    .buttonStyle(RedButtonStyle())   // does not work either
}

struct RedButtonStyle: ButtonStyle {
    func makeBody(configuration: Configuration) -> some View {
        configuration.label.foregroundColor(Color.red)
    }
}

If instead of Label, I use Text, or Image (I am aware of this), it doesn't work either.

Is there any way to do it?

P.S.: there is another related SO question, but it is very generic and wider in scope.

2
  • 2
    You can't change the default Menu's buttons style, colors etc. in SwiftUI 2.0. You can try to build your own custom Menu. Commented Feb 18, 2021 at 12:00
  • 1
    The link that you posted leads to Apple's sample code on how to create your own it with UIKit. Follow that and then wrap it into a UIViewControllerRepresentable or a UiViewRepresentable to make it work in SwiftUI. Commented Feb 18, 2021 at 13:51

3 Answers 3

29

This is now possible in iOS 15 by setting a Button's role. Documentation

Example:

Menu("Actions") {
    Button(role: .destructive, action: { }) {
        Label("Whatever", systemImage: "pencil")
    }
}

Result:

Result

Sign up to request clarification or add additional context in comments.

5 Comments

I was hoping that there was a workaround for iOS 14 without resorting to UIKit. Thanks anyway. I really hate that to overcome the deficiencies of SwiftUI I have to use a higher version of the OS itself...
@noe Yeah, sometimes you just have to use UIKit for certain parts instead. I have a really recent Q&A here which I made actually to create a custom context menu. I do the Introspect with ScrollView thing, and then add a UIContextMenuInteraction with scrollView.subviews.first!.addInteraction(/* interaction delegate instance */). You may find that useful to implement an iOS 14 version of the context menu.
Thanks for that! I'll check it out.
I can't set the font to a custom font or color other than red
@JAHelia Although more customisation is nice, this would be an unusual UX to use something other than "plain" or red as a destructive action
7

2024

In iOS 17 you can use a .foregroundStyle with multiple arguments, where the first one will be the color for the icon.

Menu {
  HStack { /// This can be a button or whatever you want
    Text("Empty")
    Image(systemName: "circle.fill")
      .foregroundStyle(.red, .primary, .secondary) /// this only works with multiple arguments; a single style would turn into the primary color.
  }
} label: {
  Text("Menu")
}

Comments

0

The color of the icon can be set With .foregroundSytle, but inside Menu{} it won't change according to Color Scheme (.dark or .light), might be a bug, following is a not very nice workaround, the converting Code can be put into Color extension. And still can't find a way to change text's color.

@Environment(\.self) var environment
...
Menu{
    let resolvedColor = Color.primary.resolve(in: environment)
    let uiColor = UIColor(displayP3Red: CGFloat(resolvedColor.red), green: CGFloat(resolvedColor.green), blue: CGFloat(resolvedColor.blue), alpha: resolvedColor.cgColor.alpha)

    Button {
        //...
    } label: {
        Label("Whatever", systemImage: "circle.fill")
           .foregroundStyle(Color.init(uiColor:uiColor),.primary,.secondary)
    }
}label: {
    Text("Menu")
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.