swift 除了为ButtonStyle扩展Button之外,还有其他选择吗?

j0pj023g  于 2023-08-02  发布在  Swift
关注(0)|答案(1)|浏览(122)

我的目标是有条件的按钮样式。但是,.buttonStyle(selected : .bordered : .borderedProminent)不能使用。

struct DepartureArrivalView: View {
    @Binding var value: String
    @Binding var selected: Bool
    
    var body: some View {
        VStack(spacing: 0) {
            Button {
                
            } label: {
                Text(value)
                    .frame(maxWidth: .infinity, alignment: .leading)
                    .font(.title)
            }
            .customButtonStyle(selected)
            .padding(16)
        }
    }
}
extension Button {
    @ViewBuilder
    func customButtonStyle(_ selected: Bool) -> some View {
        switch selected {
        case true:
            self.buttonStyle(.bordered)
        case false:
            self.buttonStyle(.borderedProminent)
        }
    }
}

#if DEBUG
struct DepartureArrivalView_Previews: PreviewProvider {
    static var previews: some View {
        DepartureArrivalView(value: .constant("A"), selected: .constant(true))
    }
}
#endif

字符串

ego6inou

ego6inou1#

注意.bordered.borderedProminent不符合ButtonStyle。符合PrimitiveButtonStyle
因此,解决这个问题的一种方法是引入一个PrimitiveButtonStyle,它 Package 了你想要选择的两种样式。要以一种通用的、可重用的方式来实现,请使其通用于两种样式:

enum Either<Left, Right> {
    case left(Left)
    case right(Right)
}

extension Either: PrimitiveButtonStyle where Left: PrimitiveButtonStyle, Right: PrimitiveButtonStyle {
    func makeBody(configuration: Configuration) -> some View {
        switch self {
        case .left(let left):
            left.makeBody(configuration: configuration)
        case .right(let right):
            right.makeBody(configuration: configuration)
        }
    }
}

字符串
然后像这样使用它:

struct DepartureArrivalView: View {
    @Binding var value: String
    @Binding var selected: Bool

    private var style: some PrimitiveButtonStyle {
        return selected ? Either.left(.bordered) : .right(.borderedProminent)
    }

    var body: some View {
        VStack(spacing: 0) {
            Button {
                
            } label: {
                Text(value)
                    .frame(maxWidth: .infinity, alignment: .leading)
                    .font(.title)
            }
            .buttonStyle(style)
            .padding(16)
        }
    }
}

相关问题