SwiftUI 有一些Button
初始值设定项,但所有这些初始值设定项都需要 aString
或some View
作为自变量与action
.
但是,按钮的外观也可以在ButtonStyle
s的帮助下进行自定义,s 可以为其添加自定义视图。
让我们考虑一个带有以下图示的复制按钮:
我为按钮制作的样式如下所示:
struct CopyButtonStyle: ButtonStyle {
init() {}
func makeBody(configuration: Configuration) -> some View {
let copyIconSize: CGFloat = 24
return Image(systemName: "doc.on.doc")
.renderingMode(.template)
.resizable()
.frame(width: copyIconSize, height: copyIconSize)
.accessibilityIdentifier("copy_button")
.opacity(configuration.isPressed ? 0.5 : 1)
}
}
它作业得很好,但是,我必须Button
在呼叫站点用空字符串初始化:
Button("") {
print("copy")
}
.buttonStyle(CopyButtonStyle())
那么,问题是如何去掉按钮初始化自变量中的空字符串?
潜在解决方案
我能够创建一个简单的扩展来完成我需要的作业:
import SwiftUI
extension Button where Label == Text {
init(_ action: @escaping () -> Void) {
self.init("", action: action)
}
}
呼叫站点:
Button() { // Note: no initializer parameter
print("copy")
}
.buttonStyle(CopyButtonStyle())
但是很好奇,我是否Button
错误地使用了结构并且已经有一个用例,以便我可以摆脱这个扩展。
uj5u.com热心网友回复:
比进行ButtonStyle
配置更简单的方法是直接传入标签:
Button {
print("copy")
} label: {
Label("Copy", systemImage: "doc.on.doc")
.labelStyle(.iconOnly)
}
这也带来了一些好处:
- 默认情况下,按钮是蓝色的,表示它可以被点击
- 您当前拥有的影像没有奇怪的拉伸
- 无需实作按下时不透明度的变化方式
您也可以将其重构为自己的视图:
struct CopyButton: View {
let action: () -> Void
var body: some View {
Button(action: action) {
Label("Copy", systemImage: "doc.on.doc")
.labelStyle(.iconOnly)
}
}
}
像这样呼叫:
CopyButton {
print("copy")
}
整体看起来干凈多了。
uj5u.com热心网友回复:
这是您尝试执行的操作的正确方法,您不需要为每种 Button 都创建一个新的 ButtonStyle,您可以只创建一个并将其重用于您想要的任何其他 Button。我也解决了你的影像拉伸问题.scaledToFit()
。
struct CustomButtonView: View {
let imageString: String
let size: CGFloat
let identifier: String
let action: (() -> Void)?
init(imageString: String, size: CGFloat = 24.0, identifier: String = String(), action: (() -> Void)? = nil) {
self.imageString = imageString
self.size = size
self.identifier = identifier
self.action = action
}
var body: some View {
return Button(action: { action?() } , label: {
Image(systemName: imageString)
.renderingMode(.template)
.resizable()
.scaledToFit()
.frame(width: size, height: size)
.accessibilityIdentifier(identifier)
})
.buttonStyle(CustomButtonStyle())
}
}
struct CustomButtonStyle: ButtonStyle {
func makeBody(configuration: Configuration) -> some View {
return configuration.label
.opacity(configuration.isPressed ? 0.5 : 1.0)
.scaleEffect(configuration.isPressed ? 0.95 : 1.0)
}
}
用例:
struct ContentView: View {
var body: some View {
CustomButtonView(imageString: "doc.on.doc", identifier: "copy_button", action: { print("copy") })
}
}
uj5u.com热心网友回复:
您可以EmptyView
用于标签,例如
Button(action: { // Note: no initializer parameter
print("copy")
}, label: { EmptyView() })
.buttonStyle(CopyButtonStyle())
但从重用和代码可读性的角度来看,将它包装在自定义按钮型别(如其他答案中所示)更可取。
0 评论