【SwiftUI】CheckBoxボタンを作ってみる

Webページや Windows でよくあるチェックボックスを SwiftUI で作成してみましたので紹介します。

SwiftUI にはデフォルトで CheckBox という View は存在しません(2020/8/12現在)ので、カスタムビューを作成する必要があります。

作り方は様々あるかと思いますので、参考程度と考えておいて下さい。

【SwiftUI】CheckBoxボタンを作ってみる

CheckBox サンプルプログラム

早速ですが、CheckBox の全体コードです(CheckBox のチェック画像は任意の画像を用意して下さい)。

struct CheckBox: View {
    
    @Binding var checked: Bool
    private var onTapped: () -> Void
    
    init(checked: Binding<Bool>, onTapped: @escaping () -> Void) {
        self._checked = checked
        self.onTapped = onTapped
    }
    
    var body: some View {
        Button(action: {
            self.$checked.wrappedValue.toggle()
            self.onTapped()
        }) {
            RoundedRectangle(cornerRadius: 8)
                .stroke(Color(.gray), lineWidth: 1)
                .frame(width: 20, height: 20)
                .overlay(showCheckImage())
        }
        .buttonStyle(PlainButtonStyle())
    }
    
    private func showCheckImage() -> AnyView {
        if self.$checked.wrappedValue {
            return AnyView(
                Image("icon_checkbox")
                    .resizable()
                    .renderingMode(.original)
            )
        } else {
            return AnyView(EmptyView())
        }
    }
}

引数は2つです。

checked: Binding<Bool> CheckBox が保持する Bool 値とバインディングさせる Bool 変数を受け取ります。

onTapped: @escaping () -> Void タップ時に行いたい処理のクロージャを受け取ります。

View の構造は、RoundedRectangle で角丸の矩形を配置し、その View の上に .overlay でチェックボックスの画像をおいています。ちなみに ZStack を用いても同様のことができます。

そして、Bool値によって、チェックボックスの ImageEmptyView(空の View)を表示するようにしてチェックボックス を表現しています。

また、Button のスタイルを .buttonStyle(PlainButtonStyle()) とすることで押下時のハイライトを無効化しています。

画像ボタンの記事でも触れていますが、Button に画像(Image)を要素として適用する場合は、Image の描画モードを .renderingMode(.original) としておかないとアクセントカラーの表示になってしまいます。

使用例

最後に、冒頭の動画サンプルの使用例のコードです。

struct ContentView: View {
    
    @State private var checked = false
    
    var body: some View {
        VStack {
            CheckBox(checked: $checked, onTapped: {
                if self.checked {
                    print("Check!")
                } else {
                    print("Uncheck!")
                }
            })
            if checked {
                Text("チェックされています。")
            } else {
                Text("チェックされていません。")
            }
        }
    }
}

同様の要領で、「いいね」ボタンや「お気に入り」ボタンなども作れそうですね。

以上

【今回の関連記事】