正在将SwiftUI视图提取到新视图中



是否有方法将配置的视图提取到其自己的视图结构中,以便应用某些自定义?例如,我在UI中的几个位置配置了Button

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,它将StringColor作为参数/属性,并像这样使用它:

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

但这与SwiftUI的一致性不如:

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

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

有时我可能也想改变其他方面。但我不知道如何制作这样一个真正的自定义视图。

就将修饰符组合成自定义修饰符而言,

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)))
}
}

请注意,因为我们将字体应用于Button,而不是直接应用于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时,我认为后者给了你一点额外的语义优势:你只想将这种风格应用于按钮,而不想应用于其他任何东西,但视图修饰符有点过于笼统,无法传达这一点。

自定义视图修改器可以做到这一点,但您必须记住SwiftUI是如何创建视图的。视图由视图修饰符修改,每个修饰符返回一个新的视图。因此,在中应用修改器的顺序很重要。

在应用了其他视图修改器后,不可能覆盖视图修改器(如其背景色((如果您希望获得与更改原始背景完全相同的结果,则不可能(。

你可以创建一个新的视图修改器,如下所示:

struct ButtonModifier: ViewModifier {
var color:Color

func body(content: Content) -> some View {
content
.frame(maxWidth: .infinity)
.frame(height: 50.0)
.foregroundColor(.black)
.background(color)
.clipShape(RoundedRectangle(cornerSize: CGSize(width: 10.0, height: 10.0)))
.padding([.leading, .trailing], 20.0)
.padding(.top, 33.0)
}
}
extension Button {
func roundedWithBackground(_ color:Color) -> some View {
self.modifier(ButtonModifier(color: color))
}
}

这将允许你在代码中的其他地方使用你的按钮;更像SwiftUI的";语法:

Button(action: {}) {
Text(title)
.font(.custom("SomeFont", size: 17.0))
.fontWeight(.bold)
}.roundedWithBackground(.red)

很明显,你可以根据自己的意愿向这个视图修改器添加更多的参数,或者如果你将一些按钮参数包装到它们自己的视图中,它可以这样调用:

MyButton(title: "Some Button Text")
.roundedWithBackground(.red)

最新更新