首页 > 解决方案 > 将 SwiftUI 视图提取到新视图中

问题描述

有没有办法将配置的视图提取到它自己的视图结构中,以便可以应用某些自定义?例如,我Button在 UI 的几个地方进行了配置:

    Button(action: {}) {
        Text("Some Button Text")
            .font(.custom("SomeFont", size: 17.0))
            .fontWeight(.bold)
    }
    .frame(maxWidth: .infinity)
    .frame(height: 50.0)
    .foregroundColor(.black)
    .background(Color("user-profile-action-call1"))
    .clipShape(RoundedRectangle(cornerSize: CGSize(width: 10.0, height: 10.0)))
    .padding([.leading, .trailing], 20.0)
    .padding(.top, 33.0)

我希望能够重新使用它,指定不同的按钮文本和不同的背景颜色。显然,一种方法是创建一个新View的,将 aStringColor作为参数/属性,并像这样使用它:

    MyButton(title: "Some Button Text", color: Color("user-profile-action-call1"))

但这与 SwiftUI 不一致:

    MyButton(title: "Some Button Text")
        .background(Color("user-profile-action-call1"))

不幸的是,将背景放在填充区域之后.clipShape()会导致填充区域,而不是剪切区域。

有时我也想改变其他方面。但我不确定如何制作像这样的真正自定义视图。

标签: swiftswiftui

解决方案


Grey 的答案是将修饰符组合成自定义修饰符的一个很好的答案,但我认为更惯用的 SwiftUI 方式是创建按钮样式

自定义按钮样式是符合ButtonStyle协议的结构;为了满足协议要求,您需要提供一个makeBody将您的样式应用于按钮并返回新视图的函数。像任何其他视图或修饰符一样,您可以声明变量来初始化您的结构,以使样式可自定义。

在您的情况下,我将提取除填充值之外的所有内容:

struct FullWidthButtonStyle: ButtonStyle {
    var backgroundColor: Color
    
    func makeBody(configuration: Configuration) -> some View {
        configuration.label
            .font(.custom("SomeFont", size: 17.0).bold())
            .frame(maxWidth: .infinity)
            .frame(height: 50.0)
            .foregroundColor(.black)
            .background(backgroundColor)
            .clipShape(RoundedRectangle(cornerSize: CGSize(width: 10.0, height: 10.0)))
    }
}

请注意,因为我们将字体应用于 aButton而不是直接应用于Text,所以.fontWeight修饰符将不起作用 - 但我们应该能够应用于.bold()字体声明本身(这需要 Xcode 12.5 - 在早期版本中,您需要切换能够Font.custom...以这种方式链接字体修饰符)。

然后,您可以将样式应用于任何按钮,指定您喜欢的任何背景颜色:

Button(action: {}) { Text("Some Button Text") }
  .buttonStyle(FullWidthButtonStyle(backgroundColor: Color("user-profile-action-call1"))

Button(action: {}) { Text("Some other button text") }
  .buttonStyle(FullWidthButtonStyle(backgroundColor: .orange))

当谈到 ViewModifier 与 ButtonStyle 时,我认为后者给了您一点额外的语义优势:您只想将此样式应用于按钮而不是其他任何东西,但是视图修饰符有点过于笼统,无法传达这一点。


推荐阅读