I have been trying for quite some time to add a custom button style/behavior to the label of a SwiftUI Menu() but haven't had any success so far. Here is an example of what I want to achieve:
Custom Button Style
Let's assume I have a custom Button Style that lets a button's text become red when pressed.
struct RedButtonStyle: ButtonStyle {
func makeBody(configuration: Configuration) -> some View {
configuration.label
.foregroundColor(configuration.isPressed ? .red : .primary)
}
Menu
Also, I have a standard SwiftUI menu.
Menu("Menu button", content: {
// Some menu content goes here
})
In this configuration the SwiftUI menu displays a standard button in the accent color (system blue) that behaves like a standard button (getting greyed out when pressed). When pressed, the menu is shown as expected.
Custom menu button
Now I want to somehow apply the custom button style to the button the menu is using. What I tried was the following:
Menu(content: {
// Some menu content goes here
}, label: {
Button("Menu button", action: { })
.buttonStyle(RedButtonStyle())
})
However, the behavior of the menu's button is not changing at all - it's still just getting greyed out when being pressed, not getting colored red.
I also experimented a bit with creating a custom MenuStyle but haven't had any success so far.
Any suggestions on this? Thanks!
SwiftUI's button is similar to UIButton , except it's more flexible in terms of what content it shows and it uses a closure for its action rather than the old target/action system. To create a button with a string title you would start with code like this: Button("Button title") { print("Button tapped!") }
Use SwiftUI Views From Other Frameworks To get started, you'll create a new custom view to manage your map. Choose File > New > File, select iOS as the platform, select the “SwiftUI View” template, and click Next. Name the new file MapView. swift and click Create.
SwiftUI lets us disable any part of its forms or even the whole form, all by using the disabled() modifier. This takes a single Boolean that defines whether the element should be disabled or not. The form element's style automatically gets updated to reflect its status – buttons and toggles get grayed out, for example.
In iOS 15.0+, there's the init(_:role:action:)
initializer that allows you create a red label color using .destructive
role. If you're not intending to delete user data, use this role for your button. Here's how the code may look like:
import SwiftUI
struct ContentView: View {
var body: some View {
ZStack {
Color.black.ignoresSafeArea()
Menu("Actions") {
Button(role: .destructive, action: { }) {
Label("Apple Swift 6.0", systemImage: "swift")
.font(.largeTitle)
}
}
.font(.largeTitle)
.foregroundColor(.yellow)
}
}
}
Here's my workaround for changing Menu's button text color.
import SwiftUI
struct ContentView: View {
@State private var color: Color = .red
var body: some View {
let press = LongPressGesture(minimumDuration: 0.0001)
.onChanged { _ in color = .yellow }
.onEnded { _ in color = .red }
ZStack {
Color.black.ignoresSafeArea()
Menu("Choose") {
Button(role: .none, action: { }) {
Label("Apple Swift 6.0", systemImage: "swift")
}
}
.font(.largeTitle)
.foregroundColor(color)
.gesture(press)
}
}
}
P.S.
Tested on iOS 15.5 and macOS 12.4.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With