有条件地使用颜色和渐变作为填充?

问题描述 投票:0回答:2

我有以下代码:

struct TestContainer: View {
    @State var useGradient = false
    
    var body: some View {
        ZStack {
            Color.black
            
            Button {
                
                
            } label: {
                RoundedRectangle(cornerRadius: .infinity)
                    .fill(useGradient ? buttonGradient() as! Color : Color.green)
                    .overlay {
                        Text("Done")
                            .font(.system(size: 17, weight: .semibold))
                            .foregroundStyle(.white)
                        
                    }
                    .cornerRadius(.infinity)
                
            }
            .frame(height: 44)
            .padding(.horizontal, 40)
            
        }
    }
    
    private func buttonGradient() -> some View {
        
        return LinearGradient(
            stops: [
                Gradient.Stop(color: Color(red: 0.1, green: 0.2, blue: 0.2), location: 0.00),
                Gradient.Stop(color: Color(red: 0.1, green: 0.3, blue: 0), location: 1.00),
            ],
            startPoint: UnitPoint(x: 0, y: 1),
            endPoint: UnitPoint(x: 1, y: 0)
            )
    }
}

有时我会得到:

无法将“SwiftUI.LinearGradient”类型的值(0x1f2bf7980)转换为“SwiftUI.Color”(0x1f2c1b688)。

我怎样才能根据填充变化的

useGradient
状态来完成这项工作?

swiftui
2个回答
0
投票

A

LinearGradient
无法转换为
Color
。它们的共同祖先是
ShapeStyle
协议

由于您需要在

.fill()
方法中返回单一类型,因此您必须将擦除
Color
LinearGradient
键入为单一样式,您可以使用
AnyShapeStyle
:

来完成此操作
.fill(useGradient ? AnyShapeStyle(buttonGradient()) : AnyShapeStyle(Color.green))

但是您应该从

some ShapeStyle
返回
some View
而不是
buttonGradient()


0
投票

评论中的建议提供了几种执行此操作的方法。

另一种方法是使用接收

ShapeStyle
作为参数的通用函数。这要求梯度以
some ShapeStyle
的形式传递,而不是
some View
:

struct TestContainer: View {
    @State var useGradient = false

    private func buttonLabel<F: ShapeStyle>(fillStyle: F) -> some View {
        RoundedRectangle(cornerRadius: .infinity)
            .fill(fillStyle)
            .overlay {
                Text("Done")
                    .font(.system(size: 17, weight: .semibold))
                    .foregroundStyle(.white)
            }
            .cornerRadius(.infinity)
    }

    private var buttonGradient: some ShapeStyle {
        LinearGradient(
            stops: [
                Gradient.Stop(color: Color(red: 0.1, green: 0.2, blue: 0.2), location: 0.00),
                Gradient.Stop(color: Color(red: 0.1, green: 0.3, blue: 0), location: 1.00),
            ],
            startPoint: UnitPoint(x: 0, y: 1),
            endPoint: UnitPoint(x: 1, y: 0)
        )
    }

    var body: some View {
        ZStack {
            Color.black

            Button {
                useGradient.toggle()
            } label: {
                if useGradient {
                    buttonLabel(fillStyle: buttonGradient)
                } else {
                    buttonLabel(fillStyle: .green)
                }
            }
            .frame(height: 44)
            .padding(.horizontal, 40)
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.