SwiftUI 自定义RadioButton

2023-03-06  本文已影响0人  O2Space_Xiu

系统CheckBox(Toggle组件)开关无法改造,系统提供的Picker组件可以采用RadioGroupPickerStyle()来实现单选,但UI过于单一。需要单选按钮可以分组且选中和非选中icon可自定义方便扩展,直接上代码

RadioButton.swift
import Foundation
import SwiftUI

public struct RadioButton<Image, Label> : View where Image : View, Label : View {
    
    let id: String
    @Binding var selectedId: String
    
    @ViewBuilder var image: (Bool) -> Image
    @ViewBuilder var label: () -> Label
    
    public init(id: String, selectedId: Binding<String>, @ViewBuilder image: @escaping (Bool) -> Image, @ViewBuilder label: @escaping () -> Label) {
        self.id = id;
        self._selectedId = selectedId
        self.image = image
        self.label = label
    }
    
    public var body: some View {
        Button {
            self.selectedId = id
        } label: {
            HStack {
                image(id == self.selectedId)
                label()
            }
            .contentShape(Rectangle())
        }
        .buttonStyle(.plain)
    }
}
调用举例
@State private var radioSelected: String = "0" //获取选中值且起到分组作用
@State private var radioSelected2: String = "0"

var body: some View {
  VStack(spacing: 10) {

  //===================组一

    RadioButton(id: "0", selectedId: $radioSelected) { check in
      Image(systemName: check ? "record.circle.fill" : "circle")
        .resizable()
        .aspectRatio(contentMode: .fit)
        .frame(width: 14, height: 14, alignment: .center)
        .foregroundColor(check ? Color.accentColor : Color.gray)
    } label: {
      Text("选项A")
        .font(.system(size: 14))
    }
    
    RadioButton(id: "1", selectedId: $radioSelected) { check in
      Image(systemName: check ? "record.circle.fill" : "circle")
        .resizable()
        .aspectRatio(contentMode: .fit)
        .frame(width: 14, height: 14, alignment: .center)
        .foregroundColor(check ? Color.accentColor : Color.gray)
    } label: {
      Text("选项B")
        .font(.system(size: 14))
    }

  //===================组二

    RadioButton(id: "0", selectedId: $radioSelected2) { check in
      Image(systemName: check ? "checkmark.circle.fill" : "circle")
        .resizable()
        .aspectRatio(contentMode: .fit)
        .frame(width: 14, height: 14, alignment: .center)
        .foregroundColor(check ? Color.accentColor : Color.gray)
    } label: {
      Text("选项A")
        .font(.system(size: 14))
    }

   RadioButton(id: "1", selectedId: $radioSelected2) { check in
      Image(systemName: check ? "checkmark.circle.fill" : "circle")
        .resizable()
        .aspectRatio(contentMode: .fit)
        .frame(width: 14, height: 14, alignment: .center)
        .foregroundColor(check ? Color.accentColor : Color.gray)
    } label: {
      Text("选项B")
        .font(.system(size: 14))
    }
  
  }
}
上一篇下一篇

猜你喜欢

热点阅读