自定义按钮样式内修改形状颜色

huangapple go评论73阅读模式
英文:

Modify shape color inside custom ButtonStyle

问题

在我的项目中,我正在使用自定义形状作为按钮的标签。现在,我试图创建一个自定义的 ButtonStyle,当按钮被按下时,可以改变自定义形状的颜色。

如果我要使用一个“普通”的按钮标签,比如 Text,我可以这样做:

struct LightGrayButtonStyle: ButtonStyle {
    func makeBody(configuration: Self.Configuration) -> some View {
        configuration.label
            .foregroundColor(configuration.isPressed ? .black : .red)
    }
}

然而,configuration.label 并没有任何特定于 Shape 的视图修饰符,因此无法使用 .fill 等来改变颜色。

这是我的其余代码:

Button {
   action()
} label: {
   RingSegment() // 这是我的自定义形状
}
.buttonStyle(LightGrayButtonStyle()) // 我应用了自定义的按钮样式

如何在我的自定义 ButtonStyle 中更改自定义形状的颜色?或者,如何使我的自定义形状遵循我在 LightGrayButtonStyle 中实现的 makeBody 方法中可以设置的 foregroundColor

英文:

In my project, I am using my custom shape as a button's label. Now, I am trying to create a custom ButtonStyle which changes the custom shape's color whenever a button is currently pressed.

If I were to use a "normal" Button label, e.g. a Text, I could do this:

struct LightGrayButtonStyle: ButtonStyle {
    func makeBody(configuration: Self.Configuration) -> some View {
        configuration.label
            .foregroundColor(configuration.isPressed ? .black : .red)
    }
}

However, configuration.label does not have any Shape specific view modifiers, making it impossible to alter the color using .fill for example.

This is the rest of my code:

Button {
   action()
} label: {
   RingSegment() // this is my custom shape
}
.buttonStyle(LightGrayButtonStyle()) // I apply my custom button style

How can I now change the color of my custom shape inside my custom ButtonStyle? Alternatively, how can I make my custom shape respect the provided foregroundColor which I can set inside the makeBody method implemented by my LightGrayButtonStyle?

答案1

得分: 1

你可以将所有的代码放在ButtonStyle内部。

struct MyShapeButtonStyle<S: Shape>: ButtonStyle {
    /// 自定义形状
    let shape: S
    /// 默认颜色
    let color: Color
    /// 使用任何形状
    init(shape: S, color: Color) {
        self.shape = shape
        self.color = color
    }
    /// 默认是一个 `Circle`
    init(color: Color) where S == Circle {
        self.shape = Circle()
        self.color = color
    }
    
    func makeBody(configuration: Self.Configuration) -> some View {
        // 自定义形状
        shape
            // 形状的填充
            .fill(configuration.isPressed ? .black : color) // 保持按钮内部能够放置标签
            .overlay(content: {
                // 保持自定义标签的能力
                configuration.label
                    .foregroundColor(.white)
            })
            .foregroundColor(configuration.isPressed ? .black : color)
    }
}

然后,你可以传入任何 Shape 和任何 Color

struct CustomButtonShapeView: View {
    var body: some View {
        VStack{
            Button("Test") {
                print("test")
            }
            .buttonStyle(MyShapeButtonStyle(color: .red))
            
            Button("Test") {
                print("test")
            }
            .buttonStyle(MyShapeButtonStyle(shape: Rectangle(), color: .blue))
        }
    }
}

这就是你的翻译结果。

英文:

You can move all the code inside the ButtonStyle

struct MyShapeButtonStyle&lt;S: Shape&gt;: ButtonStyle {
    ///Custom Shape
    let shape: S
    ///Default Color
    let color: Color
    ///Uses any Shape
    init(shape: S, color: Color) {
        self.shape = shape
        self.color = color
    }
    ///Default is a `Circle`
    init(color: Color) where S == Circle {
        self.shape = Circle()
        self.color = color
    }
    
    func makeBody(configuration: Self.Configuration) -&gt; some View {
        //Custom shape
        shape
            //Fill for the shape
            .fill(configuration.isPressed ? .black : color)//Keep the ability to put a label in the button
            .overlay(content: {
                //Keep the ability to have a custom label.
                configuration.label
                    .foregroundColor(.white)
            })
            .foregroundColor(configuration.isPressed ? .black : color)
    }
}

Then you can pass in any Shape and any Color.

struct CustomButtonShapeView: View {
    var body: some View {
        VStack{
            Button(&quot;Test&quot;) {
                print(&quot;test&quot;)
            }
            .buttonStyle(MyShapeButtonStyle(color: .red))
            
            Button(&quot;Test&quot;) {
                print(&quot;test&quot;)
            }
            .buttonStyle(MyShapeButtonStyle(shape: Rectangle(), color: .blue))
        }
    }
}

答案2

得分: 0

我选择的解决方案是在makeBody函数内部应用foregroundColor修饰符,并在填充自定义形状时使用该颜色。

这是我的代码:

// 声明按钮样式
struct LightGrayRingSegmentButtonStyle: ButtonStyle {
    func makeBody(configuration: Self.Configuration) -> some View {
        configuration.label
            .foregroundColor(configuration.isPressed ? .red : .blue)
    }
}

Button {
    action()
} label: {
    RingSegment()
        // 使用我们在自定义按钮样式中设置的前景色
        .fill(.foreground)
}
.buttonStyle(LightGrayRingSegmentButtonStyle())
英文:

The solution I went for is to apply the foregroundColor modifier inside the makeBody function and use that color when filling my custom shape.

This is my code:

// Declare Button Style
struct LightGrayRingSegmentButtonStyle: ButtonStyle {
    func makeBody(configuration: Self.Configuration) -&gt; some View {
        configuration.label
            .foregroundColor(configuration.isPressed ? .red : .blue)
    }
}


Button {
    action()
} label: {
    RingSegment()
        // respect foregroundColor which we set inside the custom button style
        .fill(.foreground)
}
.buttonStyle(LightGrayRingSegmentButtonStyle())

</details>



huangapple
  • 本文由 发表于 2023年5月25日 01:04:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/76325896.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定