SwiftUI 按钮选择

问题描述 投票:0回答:4

我正在尝试掌握 SwiftUI 概念(完成了 Apple 的 SwiftUI 教程),但在 UIKit 十年后这对我来说似乎很难。

我需要通过单击 HStack 中的多个按钮(UIKit 的

isSelected
)来切换它们的状态,并更改它们的字体和文本(在 UIKit 世界中,我将在检查
attributedText
属性的
if
语句中使用
isSelected
属性,全部在
@IBAction
TouchUpInside
)。

我的第一个想法是在其操作块中获取 Button 的“引用”,但感觉这不是 SwiftUI 方式(甚至不可能)。我找到了使用配置器及其 isPressed 属性的解决方案(这不是我搜索的),但我需要按钮实际上表现得像切换。 SwiftUI 中是否有任何内置的 isSelected 替换,或者我必须使用 @State 或 @BindableObject 制作自己的 View 实现,以封装一些手势识别器(看起来相当难看)。预先感谢!

swift button uibutton swiftui selected
4个回答
6
投票

我想出了自定义View,它封装了Button,如下所示:

    import SwiftUI

struct SelectableButtonStyle: ButtonStyle {

    var isSelected = false

    func makeBody(configuration: Self.Configuration) -> some View {
        configuration.label
            .frame(width: 60.0, height: 60.0, alignment: .center)
            .padding()
            .background(Color(#colorLiteral(red: 1, green: 0.8980392157, blue: 0.7058823529, alpha: 1)))
            .clipShape(RoundedRectangle(cornerRadius: isSelected ? 16.0 : 0.0))
            .overlay(RoundedRectangle(cornerRadius: isSelected ? 16.0 : 0.0).stroke(lineWidth: isSelected ? 2.0 : 0.0).foregroundColor(Color.pink))
            .animation(.linear)
    }
}


struct StatedButton<Label>: View where Label: View {


    private let action: (() -> ())?

    private let label: (() -> Label)?

    @State var buttonStyle = SelectableButtonStyle()

    init(action: (() -> ())? = nil, label: (() -> Label)? = nil) {
        self.action = action
        self.label = label
    }

    var body: some View {
        Button(action: {
            self.buttonStyle.isSelected = !self.buttonStyle.isSelected
            self.action?()
            print("isSelected now is \(self.buttonStyle.isSelected ? "true" : "false")")
        }) {
            label?()
        }
        .buttonStyle(buttonStyle)
    }    
}

如果这个解决方案不好,请告诉我为什么,我真的很感激。而且我还在努力解决一个相当微不足道的问题:如何将模型的数组元素映射到按钮(即如何检测到底点击了哪个按钮),但我认为我必须为此创建另一个问题。


2
投票

我有一个简单的方法可以做到这一点。

    @State var selected = false

    func createButton() -> some View {
        Button(action: {
            self.selected.toggle()
        }, label: {
            Text("Hello World")
                .padding(.all, 5)
                .background(selected ? Color.blue : Color.white)
                .foregroundColor(selected ? Color.white : Color.blue)
        })
            .overlay(
                RoundedRectangle(cornerRadius: 4)
                    .stroke(Color.blue, lineWidth: 1)
        )
    }


2
投票

您可以创建自定义ButtonStyle并根据

isPressed

修改配置的标签
struct CustomButton: View {
    var body: some View {
        Button {
            // action
        } label: {
            Text("Button")
        }
        .buttonStyle(CustomStyle())
    }
}

struct CustomStyle: ButtonStyle {
    func makeBody(configuration: Self.Configuration) -> some View {
        configuration.label
            .foregroundColor(.white)
            .background(configuration.isPressed ? .green : .black)
    }
}

0
投票

我更喜欢通过

ButtonStyle
和自定义
Environment
“isSelected”实现。以下代码有一些颜色的自定义值,但我希望您能明白这个想法;-)

extension ButtonStyle where Self == ButtonStyleGrey {
    internal static var grey: ButtonStyleGrey {
        ButtonStyleGrey(maxWidth: true)
    }
}

struct ButtonStyleGrey: ButtonStyle {
    let maxWidth: Bool
    @Environment(\.isEnabled) private var isEnabled: Bool
    @Environment(\.isSelected) private var isSelected: Bool

    func makeBody(configuration: ButtonStyle.Configuration) -> some View {
        let font = Font.system(size: UIScreen.titleFontSize, weight: .semibold)
        let text: UIColor = isEnabled ? .titleColor : .systemGray2
        let back: UIColor = isEnabled ? (configuration.isPressed || isSelected ? .graySelected : .grayNormal) : .disabledColor
        
        return configuration
            .label
            .textCase(.uppercase)
            .font(font)
            .foregroundColor(Color(text))
            .padding(.horizontal, .regular)
            .padding(.vertical, .regular)
            .frame(maxWidth: maxWidth ? .infinity : nil)
            .background(Color(back))
    }
}

// MARK: -

private struct isSelectedKey: EnvironmentKey {
    static let defaultValue: Bool = false
}

extension EnvironmentValues {
    var isSelected: Bool {
        get { self[isSelectedKey.self] }
        set { self[isSelectedKey.self] = newValue }
    }
}

extension View {
    func isSelected(_ selected: Bool) -> some View {
        environment(\.isSelected, selected)
    }
}

用法就是这样:

   Button("Some action") {
       // run something
   }
   .buttonStyle(.grey)
   .isSelected(viewModel.someActionSelected)
© www.soinside.com 2019 - 2024. All rights reserved.