LoginSignup
33
25

More than 3 years have passed since last update.

iOS 13 の Large Title 表示を iOS 12 までと同じデザインにする

Last updated at Posted at 2019-10-07

はじめに

皆さんは Large Title 使っていますか?
iOS 11 から 全体的に太字のデザインに変わって少し残念に
思っていたのですが,Large Title だけは好きでよく使っています。

iOS 13 から表示が変わって対応に少し困ったので調べてみました。
UINavigationBarAppearance1 というのが追加されています。

iOS 13 の NavigationBar の見た目が変わった

多くのアプリではテーマカラーを持っており,NavigationBar
色設定にテーマカラーやそれ相当の色を充てていたりします。
私のアプリもテーマカラーを充てています。

iOS 13 対応を行う際に Xcode 11 でビルドしたアプリを見ていて
Large Title を使っている部分の表示に違和感を感じました。
NavigationBarbarTintColor を設定していないと
あまり気にならないですが,
Large Title 表示時の NavigationBar の色がなくなり背景と同化しています。
通常時は,問題なく想定通りです。

下記が実際のアプリでの表示です。

Large Title 表示時(背景に溶け込んでいる)

iOS 11, 12 iOS 13 ⁉️
IMG_1834.PNG iOS13_large.png

通常時(問題ない)

iOS 11, 12 🆗 iOS 13 🆗
IMG_1835.PNG iOS13_normal.png

iOS 13 から NavigationBar をデフォルトで透過させるようにしたようです。
そのため,self.viewBackground Color と同化して見えるということです。
(上の例は UITableViewController のため,UITableView の色 Grouped Table View Color になっている)

モーダルのデフォルト表示スタイルの変更(Sheet)もそうだけど
デフォルトを変更する(変更を強いる)のやめて欲しい・・・

UINavigationBarAppearance とは

iOS 13 からは UINavigationBarAppearance を用いて,
NavigationBar 周りのデザインをカスタマイズするようです。

UINavigationBarAppearanceUIBarAppearance2 のサブクラスで,
親戚に UIToolBarAppearanceUITabBarAppearance などもあります。

設定できる外観(Appearance)は3種類です。

.standardAppearance 
.compactAppearance 
.scrollEdgeAppearance 

.standardAppearance はいわゆる通常の 44pt のもの。
standard.png

.compactAppearance は Landscape の低い高さのもの。

compact.png

.scrollEdgeAppearance はラージタイトル用のもの。
スクロールビューがトップに来たときの表示。

largeTitle.png

NavigationBar のタイトルやフォント Large Title のカスタマイズは
iOS 12 までと同様に設定できるようです。

titleTextAttributes
largeTitleTextAttributes

iOS 12 までは下記のように書いていました。

self.navigationController?.navigationBar.largeTitleTextAttributes =
[NSAttributedString.Key.foregroundColor: UIColor.white,
 NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 30.0)]

iOS 13 からは書き方が変わります。

// インスタンス生成
let appearance = UINavigationBarAppearance()
// 設定をリセット
appearance.configureWithDefaultBackground() 

// ここに適用させたい設定を書く

// Large Title 表示用設定
self.navigationController?.navigationBar.scrollEdgeAppearance = appearance
// 通常表示時の設定
self.navigationController?.navigationBar.standardAppearance = appearance

設定のリセットは3種類あります。
使い分けはいまいちわからないです・・・

@available(iOS 13.0, *)
open class UIBarAppearance : NSObject, NSCopying, NSSecureCoding {
    /// Reset background and shadow properties to their defaults.
    open func configureWithDefaultBackground()

    /// Reset background and shadow properties to display theme-appropriate opaque colors.
    open func configureWithOpaqueBackground()

    /// Reset background and shadow properties to be transparent.
    open func configureWithTransparentBackground()

iOS 13 でも iOS 11 や 12 でも同じ Large Title の表示にしたい

サンプルプロジェクトを用意しました。
適宜参考にしてください。
GitHub: https://github.com/MilanistaDev/NewLargeTitleSample

環境

  • Xcode 11
  • サポート:iOS 11以上(場合分けが増えるため)
  • iOS 12 端末
  • iOS 13 端末

要件

  • TableView をスクロールすると Large Title が隠れて NavigationBar のタイトルとなる
  • NavigationBar の色は赤で,タイトル色は黒
  • iOS 13 ではライトモードでタイトルの色は黒,ダークモードでは白とする

(指定は赤だけどライトモードとダークモードとで色味が変わる .systemRed の方が良い)

以下,現行コードから移行する感じで書いていきます。

まず,iOS 11, 12 で想定している表示となるコードは下記です。
(長くなるので TableView 周りの実装は省きます。)

ViewController.swift
class ViewController: UIViewController {

    @IBOutlet weak var tableView: UITableView!

    override func viewDidLoad() {
        super.viewDidLoad()
        self.setUpNavigationBar()
    }

    private func setUpNavigationBar() {
        // Large Title Basic Settings
        self.navigationItem.title = "Large Title"
        self.navigationController?.navigationBar.prefersLargeTitles = true
        self.navigationItem.largeTitleDisplayMode = .always
        self.navigationController?.navigationBar.barTintColor = .red
    }
}

これで iOS 12 端末で実行すると問題なく表示されます。
iOS 13 では,通常表示の場合は正しく赤色が設定されていますが,
Large Title 表示時は透過しており,赤色が出ていません。

iOS 12 🆗 iOS 13 🤔
RPReplay_Final1570184333.gif RPReplay_Final1570184462.gif

UINavigationBarAppearance を用いて iOS 13 の NavigationBar 設定を行います。
iOS 11, 12 の場合と場合分けする必要があります。

ViewController.swift
private func setUpNavigationBar() {
    // Large Title Basic Settings

    // abbreviation 略

    if #available(iOS 13.0, *) {
        let appearance = UINavigationBarAppearance()
        appearance.configureWithDefaultBackground()
        appearance.backgroundColor = .red // .systemRed の方が望ましい
        appearance.largeTitleTextAttributes = [.foregroundColor: UIColor.label]
        appearance.titleTextAttributes = [.foregroundColor: UIColor.label]
        // Large Title 用 NavigationBar の色設定
        self.navigationController?.navigationBar.scrollEdgeAppearance = appearance
        // 通常の NavigationBar の色設定
        self.navigationController?.navigationBar.standardAppearance = appearance
    } else {
        // iOS 13 未満はこれまで通り
        self.navigationController?.navigationBar.barTintColor = .red
    }
}

これでちゃんと表示されるようになりました!

RPReplay_Final1570188881.gif

largeTitleTextAttributestitleTextAttributes もあるので
テキストカラーとサイズを変更する場合も容易ですね。

Large Title のポジションもある程度カスタマイズできるようです。
titlePositionAdjustment を下記のように調整します。

appearance.titlePositionAdjustment = UIOffset(horizontal: CGFloat , vertical: CGFloat)

こんなふうに左側に寄せることもできますね。
vertical の方は使い勝手難しそう。

RPReplay_Final1570436073.gif

おわりに

今回は,iOS 13 の Large Title 表示を iOS 12 までと同じデザインにする実装に関して書きました。UINavigationBarAppearance ってどこで説明されてたの?って思いましたが,ちょうど見忘れていたセッションで説明が軽くありました。
リリースしたアプリはこの対応していないので早速実装しようと思います。

ご覧いただきありがとうございました!!

参考

今回参考にしたセッションは細かいけど大事なことが詰め込まれているセッションです。

Modernizing Your UI for iOS 13
https://developer.apple.com/videos/play/wwdc2019/224/

【iOS11】NavigationBarのlargeTitlesの文字をカスタマイズする
https://qiita.com/MilanistaDev/items/4ff029c2e93bd5357fbd

33
25
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
33
25