見出し画像

SwiftUI にボタンを追加する【個人開発日記#1】

XCode を開いて新規プロジェクトの構築を始めると、最初はサンプルの "Hello World" が表示される。
問題は現時点での Swift や SwiftUI に関する知識がゼロだということ。

まあ、そのうち分かるでしょう、という気楽な感じでコーディングを進めましょう。

画像のようにボタンを配置したい

今回作るサンプル

上の画像は Figma で作成した UI のサンプル。
・ペインにボタンを3つ表示
・ボタンには文字を書く
・ボタンをマウスオーバーすると色が変わる。
今回は、この3つを実装する。

SwiftUIにボタンを追加

import SwiftUI

struct ContentView: View {
    var body: some View {
        VStack {
            RoundedRectangle(cornerRadius: 10)
                .frame(minWidth:400, minHeight:400)
                .padding(.vertical, 30)
                .overlay(
                    VStack(spacing: 20){
                        Button(action: {}) {
                            Text("ボタン")
                                .font(.custom("HiraginoSans-W6", size: 36))
                        }
                        .buttonStyle(RoundedButtonStyle())
                        Button(action: {}) {
                            Text("グラフ")
                                .font(.custom("HiraginoSans-W6", size: 36))
                        }
                        .buttonStyle(RoundedButtonStyle())
                        Button(action: {}) {
                            Text("カレンダー")
                                .font(.custom("HiraginoSans-W6", size: 36))
                        }
                        .buttonStyle(RoundedButtonStyle())
                    }
                )
        }
        .padding(100)
    }
}

#Preview {
    ContentView()
        .frame(minWidth: 600, minHeight: 600)
}

struct RoundedButtonStyle: ButtonStyle {
    func makeBody(configuration: Configuration) -> some View {
        configuration.label
            .frame(minWidth: 300, minHeight: 100)
            .foregroundColor(.white)
            .background(.green)
            .cornerRadius(10)
    }
}

下記の記事を参考にレイアウトを作成した。

VStack と HStack という箱を組み合わせてレイアウトを作成し、内側に Button などの要素を追加するという流れ。

親要素と小要素の間(例えば VStack と RoundedRectangle )は padding、小要素間(例えば Button 同士の間)は spacing で調整する、となんとなく理解が進んだ。

苦労した点

  1. 要素を重ねる場合は overlay を使用
    RoundedRectangle の上にボタン要素を乗せたい時は .overlay() を追加して要素を追加してゆく。VStack などと同じく箱を追加するイメージかな?

  2. フォントの指定方法
    最初、Text("カレンダー").font(.custom("Hiragino-Kaku-Gothic-ProN", size: 36))と書いていました。
    反映されない……
    Mac の FontBook から、使いたいフォントを選択し、識別子のところにある PostScript名を custom の部分に入力して無事解決。

UI関連の開発経験は、Python の GUI フレームワークである Kivy や Java と html を使った開発の経験しかなかったので、コードを変えるとすぐに見た目に反映されるのは新鮮。

SwiftUI 完全に理解した

マウスホバーで色を変える処理を追加


「ボタン」の上にマウスオーバーすると色が変わる

ボタン・背景用の色を追加

左ペインの Asset を開いて、New Color Set で色を追加。
Input Method を 8-bit Hexadecimal にすると Hex 表記で色をセットできるのでとても便利。
項目に Device があり iPhone や Mac などデバイスごとに色を変えられるのが面白い。どのデバイスで使われるアプリかハッキリしているので、それに最適化できるという Apple の強みがよくわかる。

色を view に適応できるようにコードを編集

import SwiftUI

struct ContentView: View {
    var body: some View {
        VStack {
            RoundedRectangle(cornerRadius: 10)
                .fill(Color.cellColor) // .fill で色を塗る。.background だとコーナー部分が反映されない。
                .frame(minWidth:400, minHeight:400)
                .padding(.vertical, 30)
                .overlay(
// 中略

#Preview {
    ContentView()
        .frame(minWidth: 600, minHeight: 600)
        .background(Color.windowColor) // .background で色を塗る
}
// Asset で追加した色を定数にしている。
// "WindowColor" "AreaColor" などは Asset で色を追加した時の名前
extension Color {
    static let windowColor = Color("WindowColor")
    static let cellColor = Color("AreaColor")
    static let selectedButtonColor = Color("SelectedButtonColor")
}
struct RoundedButtonStyle: ButtonStyle {
    @State var isHover = false
    func makeBody(configuration: Configuration) -> some View {
        configuration.label
            .frame(minWidth: 300, minHeight: 100)
            .foregroundColor(.white)
            .background(Group{
                if isHover{
                    Color.selectedButtonColor
                }
            })
            .cornerRadius(10)
            .onHover { hovering in
                withAnimation {
                    self.isHover = hovering
                }
            }
    }
}

.fill や .background で色を追加。

苦労した点

  1. @State をつけないといけない
    これを忘れると view が更新されないらしい

  2. var body のなかで if 文を使えない
    以下の記事を参考に Group を使って解決した。マウスホバーぐらいならとにかく、複雑なことはしないほうが良さそうだ。

今回のまとめ

SwiftUI 1mm も分からない状態から view や button についてなんとなく理解できた。実は一番苦労したのはここではないという…





この記事が気に入ったらサポートをしてみませんか?