iOS, Swift, SwiftUI

iOS 13でのNavigationBarのカスタマイズ方法

NavigationBarをカスタマイズする方法がiOS13から変わったそうです。
ご丁寧にAppleからサンプルアプリが提供されているのでそれを確認していけばカスタマイズできそうです。
今回の記事ではAppleのサンプルアプリをみつつ、NavigationBarのカスタマイズ方法を解説します。

実行環境

  • Xcode 11.4.1

Customizing Your App’s Navigation Bar

AppleはCustomizing Your App’s Navigation Barという記事を公開し、NavigationBarのカスタマイズの実装方法を解説しています。

具体的にはNavigationBarの外見を変える方法や独自Viewを配置する方法、NavigationItemを画像に変更する方法、戻るボタンをカスタマイズする方法などです。

NavigationBarのカスタマイズ方法はほぼ網羅されているのでこれを確認すれば自分のやりたいことが実現できそうですね。

NavigationBarの外見を変える方法

NavigationBarの外見を変えるコードを見ていきましょう。

iOS 13からUINavigationBarAppearanceというNavigationBarの外見をカスタマイズする設定クラスが追加されました。これのインスタンスを作って外見の設定をしていきます。

ViewControllerのviewDidLoadの中で次のコードを書きます。

let appearance = UINavigationBarAppearance()
appearance.configureWithOpaqueBackground()
appearance.backgroundColor = UIColor.systemRed
appearance.titleTextAttributes = [.foregroundColor: UIColor.lightText]

configureWithOpaqueBackgroundメソッドを呼び出すと以前の設定をリセットして、不透明の色としてNavigationBarの外見をセットできるようになります。
appearance.backgroundColorで色を赤色のUIColor.systemRedに設定します。
appearance.titleTextAttributesでタイトル文字の装飾をしています。背景が赤色なので文字色を白色にして読みやすくしています。

そしてこのappearancenavigationItemに反映します。

navigationItem.standardAppearance = appearance
navigationItem.scrollEdgeAppearance = appearance
navigationItem.compactAppearance = appearance

反映するプロパティはstandardAppearancescrollEdgeAppearancecompactAppearanceです。
これらのプロパティはNavigatinBarの種類にそれぞれ対応しています。

standardAppearanceを更新すると通常のNavigaitonBarの外見が変更されます。

standardAppearance

scrollEdgeAppearanceはiOS 11から導入されたラージタイトルの場合の外見設定です。
ラージタイトルを表示するには次のコードを実装します。

navigationController?.navigationBar.prefersLargeTitles = true

するとこのような外見になります。

scrollEdgeAppearance

最後にcompactAppearanceはiPhoneを横向きにした場合の小さいNavigationBarの外見設定を意味します。

compactAppearance

コードの全体はこちらです。

override func viewDidLoad() {
    super.viewDidLoad()

    self.title = "Appearance"
    // Make the navigation bar's title with red text.
    let appearance = UINavigationBarAppearance()
    appearance.configureWithOpaqueBackground()
    appearance.backgroundColor = UIColor.systemRed
    appearance.titleTextAttributes = [.foregroundColor: UIColor.lightText] // With a red background, make the title more readable.
    navigationItem.standardAppearance = appearance
    navigationItem.scrollEdgeAppearance = appearance
    navigationItem.compactAppearance = appearance // For iPhone small navigation bar in landscape.
    // navigationController?.navigationBar.prefersLargeTitles = true // ラージタイトルを表示する
}

SwiftUIでNavigationBarをカスタマイズ

SwiftUIでNavigaitonBarをカスタマイズしたい場合もあるでしょう。
しかし前述の方法ではUIViewControllernavigationItemプロパティを更新するので、SwiftUIでは使えません。

SwiftUIのNavigationBarをカスタマイズしたい場合はUINavigationBar.appearance()を更新します。UINavigationBar.appearance()を更新するとアプリ全体のNavigationBarを更新できるので結果SwiftUIのNavigationBarも更新されます。

AppDelegatefunc application(_, didFinishLaunchingWithOptions)メソッドでUINavigationBar.appearance()を更新するコードを実装します。

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    // Override point for customization after application launch.

    let appearance = UINavigationBarAppearance()
    appearance.configureWithOpaqueBackground()
    appearance.backgroundColor = .red

    let attrs: [NSAttributedString.Key: Any] = [
        .foregroundColor: UIColor.white,
        .font: UIFont.monospacedSystemFont(ofSize: 36, weight: .black)
    ]

    appearance.largeTitleTextAttributes = attrs

    UINavigationBar.appearance().scrollEdgeAppearance = appearance // ラージタイトルの場合の外見
    UINavigationBar.appearance().standardAppearance = appearance // 通常の外見
    UINavigationBar.appearance().compactAppearance = appearance //横向きの場合
    return true
}

そしてNavigationViewでビューを作ります。

struct ContentView: View {
    var body: some View {
        NavigationView {
            NavigationLink(destination: Text("Detail")) {
                Text("Master")
            }
            .navigationBarTitle("Nav", displayMode: .large) // ラージタイトルで表示する
        }
    }
}

すると赤色のNavigationBarが表示されます。

SwiftUIでもNavigationBarをカスタマイズ

SwiftUIのNavigationは内部でUINavigationViewを使っているのでこのような指定ができます。
次回バージョンであるiOS 14でSwiftUIのNavigationUIKitを利用しない方式に変更されたらこのコードは使えなくなるので注意が必要です。

まとめ

  • AppleがCustomizing Your App’s Navigation Barという記事でNavigationBarのカスタマイズ方法を公開している。
  • UINavigationBarAppearanceはNavigationBarの外見設定クラス。インスタンスをつくって外見設定を作成する
  • navigationItem.standardAppearanceを更新すると通常のNavigationBarの外見を変更できる
  • navigationItem.scrollEdgeAppearanceを更新するとラージタイトルの外見を変更できる
  • navigationItem.compactAppearanceを更新するとiPhoneの横向きのNavigationBarの外見を変更できる
  • SwiftUIはUINavigationBar.appearance()を更新する。

宣伝

SwiftUIでアプリを作り方を解説した「1人でアプリを作る人を支えるSwiftUI開発レシピ」がBOOTHで発売中です。
SwiftUIでアプリを作りたい方、ぜひチェックしてください!

https://personal-factory.booth.pm/items/1920812



参考

Author image

About Sato Takeshi

  • Tokyo, Japan