拨开荷叶行,寻梦已然成。仙女莲花里,翩翩白鹭情。
IMG-LOGO
主页 文章列表 SwiftUI:初始值设定项中没有标签/字符串但带有ButtonStyle的按钮

SwiftUI:初始值设定项中没有标签/字符串但带有ButtonStyle的按钮

白鹭 - 2022-01-23 2052 0 0

SwiftUI 有一些Button初始值设定项,但所有这些初始值设定项都需要 aStringsome View作为自变量与action.

但是,按钮的外观也可以在ButtonStyles的帮助下进行自定义,s 可以为其添加自定义视图。

让我们考虑一个带有以下图示的复制按钮:

SwiftUI:初始值设定项中没有标签/字符串但带有 ButtonStyle 的按钮

我为按钮制作的样式如下所示:

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

这也带来了一些好处:

  1. 默认情况下,按钮是蓝色的,表示它可以被点击
  2. 您当前拥有的影像没有奇怪的拉伸
  3. 无需实作按下时不透明度的变化方式

您也可以将其重构为自己的视图:

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 评论

发表评论

您的电子邮件地址不会被公开。 必填的字段已做标记 *