SwiftUI 3.0 で追加されたButtonの引数やプロパティを色々試してみた

SwiftUI 3.0 で Button 表示に関するプロパティに色々と改修が入り、削除やキャンセル、角丸ボタンといったよくあるスタイルのボタンが作りやすくなりました。

一通りの形状のボタンを試してみましたのでご参考下さい。

動作確認済環境

MacOSX 11.6 Big Sur

Xcode 13.0

iOS 15.0

iPhone 13 Pro Max シミュレータ

SwiftUI 3.0 で追加されたButtonの引数やプロパティを色々試してみた

追加された引数とプロパティの確認

引数、またはプロパティをさまざまに組み合わせることで一般的なアプリで見られるような形状・色合いのボタンを作ることができます。

role: ButtonRole(引数)

Role を直訳すると「役割」という意味で、3つのタイプが用意されています。

  • none:特に意味はない汎用的な肯定的な役割のボタンに用います(デフォルト)
  • cancel:キャンセルする意味合いのボタンに用います。
  • destructive:削除などの注意を促す役割のボタンに用います。

buttonStyle(プロパティ)

枠や色の反転などのボタンスタイルの指定で、4種類用意されています。

  • plain:枠も色も無いシンプルなスタイルです。Textだけだと一見ボタンに見えないので注意です。
  • bordered:薄いグレーの背景で枠がわかるようになります。
  • borderless:枠は無いですが、OSのアクセントカラーが付くのでボタンと認識できます。
  • borderedProminent:背景側がOSのアクセントカラーに、文字色が白字になります。

controlSize(プロパティ)

ボタンの Padding と、角の丸みが自動調整されます。4種類用意されています。

  • mini:極小ボタン
  • small:小さめのボタンです。しかし、試した限りminiとの違いがよくわかりませんでした。
  • regular:デフォルトサイズのボタンです。
  • large:余白が広いボタンです。

buttonBorderShape(プロパティ)

ボタンの枠の形状を指定します。3タイプの指定ができます。

  • capsule:左右が半円のカプセル型の形状になります。
  • roundedRectangle:角がやや丸みを帯びた形状になります(デフォルト)。
  • roundedRectangle(radius: CGFloat):角の丸みを自由に数値で指定できます。

tint(プロパティ)

ボタンの色合い指定です。

buttonStyle が bordered の場合は文字色が指定の色になり、背景は薄い指定色で塗られますborderedProminent の場合は指定した色で背景が塗られ、文字色は白になります

冒頭スクリーンショットのサンプルコード

記事冒頭に貼ったスクリーンショットのコードは以下の通りです。

struct ContentView: View {
    var body: some View {
        VStack {
            VStack {
                Button("Plain", role: .none, action: {})
                    .buttonStyle(.plain)
                Button("Bordered", role: .none, action: {})
                    .buttonStyle(.bordered)
                Button("Borderless", role: .none, action: {})
                    .buttonStyle(.borderless)
                Button("Bordered Cancel", role: .cancel, action: {})
                    .buttonStyle(.bordered)
                Button("Bordered Prominent Cancel", role: .cancel, action: {})
                    .buttonStyle(.borderedProminent)
                Button("Bordered Destructive", role: .destructive, action: {})
                    .buttonStyle(.bordered)
                Button("Bordered Prominent Destructive", role: .destructive, action: {})
                    .buttonStyle(.borderedProminent)
            }
            HStack {
                Button("Mini", role: .none, action: {})
                    .buttonStyle(.bordered)
                    .controlSize(.mini)
                Button("Small", role: .none, action: {})
                    .buttonStyle(.bordered)
                    .controlSize(.small)
                Button("Regular", role: .none, action: {})
                    .buttonStyle(.bordered)
                    .controlSize(.regular)
                Button("Large", role: .none, action: {})
                    .buttonStyle(.bordered)
                    .controlSize(.large)
            }
            VStack {
                Button("Capsule", role: .none, action: {})
                    .buttonStyle(.bordered)
                    .buttonBorderShape(.capsule)
            }
            VStack {
                Button("Yellow", role: .none, action: {})
                    .buttonStyle(.bordered)
                    .tint(.yellow)
                Button("Purple", role: .none, action: {})
                    .buttonStyle(.borderedProminent)
                    .tint(.purple)
                Button("Pink", role: .none, action: {})
                    .buttonStyle(.borderedProminent)
                    .tint(.pink)
            }
            VStack {
                Button(role: .none, action: {}, label: {
                    Text("Wide").frame(maxWidth: .infinity)
                })
                .buttonStyle(.borderedProminent)
                .frame(maxWidth: .infinity)
                Button(role: .none, action: {}, label: {
                    Text("FixedSize").frame(maxWidth: .infinity)
                })
                .buttonStyle(.borderedProminent)
                .fixedSize(horizontal: false, vertical: true)
                .frame(width: 200)
            }
            VStack {
                Button("Bordered", role: .none, action: {})
                    .buttonStyle(.bordered)
                    .border(.blue, width: 2)
                    .buttonBorderShape(.roundedRectangle(radius: 0))
                Button("Rounded Bordered", role: .none, action: {})
                    .buttonStyle(.bordered)
                    .buttonBorderShape(.capsule)
                    .overlay(
                        RoundedRectangle(cornerRadius: 16)
                            .stroke(.blue, lineWidth: 2)
                    )
            }
        }
    }
}

ちなみに、下4つの形状は今回紹介したプロパティだけでは作れないので、frameoverlay などを駆使して実現しています。縁のあるボタンなどは需要があるのでは無いでしょうか。

以上、参考になれば幸いです。