🦋

SwiftUI: macOSの信号機ボタンを再現チャレンジ

2022/11/29に公開1

  1. カーソルを乗せると×-のアイコンが表示される
  2. ボタンを押すと背景色が薄くなる
struct WindowButton: View {
    @State private var hovering: Bool = false

    var body: some View {
        HStack {
            colorButton("multiply", Color.red)
            colorButton("minus", Color.yellow)
            colorButton("arrow.up.left.and.arrow.down.right", Color.green)
        }
        .onHover { hovering = $0 }
    }

    func colorButton(_ iconName: String, _ baseColor: Color) -> some View {
        ZStack(alignment: .center) {
            Image(systemName: "circle.fill")
                .font(.system(size: 12, weight: .bold))
                .foregroundColor(baseColor)
            Button {

            } label: {
                Image(systemName: "circle.fill")
                    .font(.system(size: 12, weight: .bold))
                    .colorMultiply(Color.white.opacity(0.5))
            }
            .buttonStyle(.borderless)
            if hovering {
                Image(systemName: iconName)
                    .font(.system(size: 8, weight: .bold))
                    .foregroundColor(Color.black.opacity(0.8))
                    .allowsHitTesting(false)
            }
        }
        .frame(width: 12, height: 12)
    }
}


うーんお粗末

Discussion

KyomeKyome

ずむさんのアドバイスを受けてさらにチャレンジ。
ButtonStyleを使ってかなりいい線まできました。

struct DeleteButtonStyle: ButtonStyle {
    @State var hovering: Bool = false

    func makeBody(configuration: Configuration) -> some View {
        configuration.label
            .foregroundColor(hovering ? .black.opacity(0.6) : .clear)
            .frame(width: 12, height: 12)
            .background(
                Ellipse()
                    .fill(Color.primary.opacity(configuration.isPressed ? 0.4 : 0.0))
                    .aspectRatio(1, contentMode: .fill)
            )
            .background(
                Ellipse()
                    .fill(Color(red: 0.999, green: 0.373, blue: 0.334))
                    .aspectRatio(1, contentMode: .fill)
            )
            .onHover { hovering = $0 }
    }
}
Button {
    deleteHandler?()
} label: {
    Image(systemName: "xmark")
        .font(.system(size: 8, weight: .bold))
}
.buttonStyle(DeleteButtonStyle())