2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ContentUnavailableView使ってみる

Posted at

ContentUnavailableViewとは

データがない状態を表す UI を提供してくれる APIです。
iOS17から使用できます。

公式のドキュメントでは以下の用意説明されています。

An interface, consisting of a label and additional content, that you display when the content of your app is unavailable to users.

日本語訳

アプリのコンテンツがユーザーに提供できない場合に表示される、ラベルと追加コンテンツで構成されるインターフェース。

例えば、何かしらのデータをリスト形式で表示する UI を想定したときに、データが何もない場合、「データを追加してください」や「データがありません」といったメッセージを表示するケースがあると思います。

例として、Xではポストした動画がない場合は、「ぜひ動画をポストしてみましょう。」といるテキストを表示しています。

Apple の Human Interface Guidline でもデータがない場合には、次に何をすべきかを表示しましょうと言及されています。

Provide clear next steps on any blank screens. An empty state, like a completed to-do list or bookmarks folder with nothing in it, can provide a good opportunity to make people feel welcome and educate them about your app. Empty states can also showcase your app’s voice, but make sure that the content is useful and fits the context. An empty screen can be daunting if it isn’t obvious what to do next, so guide people on actions they can take, and give them a button or link to do so if possible. Remember that empty states are usually temporary, so don’t show crucial information that could then disappear.

https://developer.apple.com/design/human-interface-guidelines/writing

ContentUnavailableViewを使ってみる

ContentUnavailableViewを使う方法は超単純で、ViewとしてContentUnavailableViewをインスタンス化するだけです。
普段使う、TextButtonと同じような感覚で使えます。

例として Preview で使ってみると以下のような感じです。

#Preview {
    ContentUnavailableView(
        "データがありません",
         systemImage: "plus"
    )
}

上記の他にもイニシャライザは用意されており、どのイニシャライザで呼び出すかによって表示できる内容もやや変わるので紹介していきます。

ContentUnavailableViewのイニシャライザ紹介

タイトルの表示

#Preview {
    ContentUnavailableView("データがありません", image: "")
}

image.png

imageを空文字で設定すれば画像が表示されないので、結果的にタイトルのみ表示する UI になります。
このイニシャライザでは、fontmodifier でフォントサイズのカスタマイズは行えませんでした。

上記イニシャライザに限らず、画像指定部分のから文字にしてしまえば同じことができます。

Labelを指定するイニシャライザでは、フォントのサイズをカスタマイズすることも可能でした。

画像とタイトルの表示

#Preview {
    ContentUnavailableView("データがありません", image: "sample")
}

タイトル部分は先ほどと同じだが、image部分に Asset に入っている画像の名前を指定すると、画像付きの UI を表示できます。

制限として、試した限りだと、画像とタイトルの位置関係はいじれず、画像の下にタイトルが表示されるレイアウトしか表示できなさそうです。

大きな画像をimageに指定すると、なぜか画像が表示されなかったです。
どれぐらい大きければ表示されなくなるかはわからないが、表示されない場合は画像のサイズを小さくすると表示されるかも。

SF Symbols の画像を表示したい場合は、以下イニシャライザを使うこともできます。

#Preview {
    ContentUnavailableView("データがありません", systemImage: "plus")
}

画像とタイトルと Description の表示

#Preview {
    ContentUnavailableView(
        "データがありません",
        systemImage: "plus",
        description: Text("データを追加しましょう")
    )
}

これまで紹介してきたイニシャライザには、descriptionの引数があり、これにTextで文言を指定することで、Description の表示も行えます。

もし、Description のサイズを変更したい場合は、以下イニシャライザを使用するとできます。

ボタン付き

#Preview {
    ContentUnavailableView {
        Label("データがありません", systemImage: "plus")
    } description: {
        Text("データを追加しましょう")
    } actions: {
        Button {
            print("tapped button")
        } label: {
            HStack(spacing: 4) {
                Image(systemName: "plus")
                Text("action")
                    .font(.title3)
            }
            .padding(8)
            .background(.cyan)
            .foregroundStyle(.white)
            .clipShape(RoundedRectangle(cornerRadius: 8))
        }
    }
}

actionの引数にButtonを指定することができます。
ここに指定するButtonは普段通りいろんな modifier を使えるので好きなボタンを実装できました。

このイニシャライザではactionだけでなく、labeldescriptionでもButtonを使えるので、やろうと思えば、labelをボタンにして他はデフォルトにしてしまえば、以下のような UI も実装できます。

#Preview {
    ContentUnavailableView {
        Button {
            print("tapped title")
        } label: {
            Label("データがありません", systemImage: "plus")
        }
    }
}

検索結果が見つからなかったケース専用のUI

#Preview {
    ContentUnavailableView.search
}

検索結果が見つからなかった場合専用のUIは、静的に定義されていました。

一応、多言語対応もしていそうで、以下のようにlocaleをenvironmenntで注入すると日本語にも変更できました。

#Preview {
    ContentUnavailableView.search
        .environment(\.locale, .init(identifier: "ja_JP"))
}

また、検索した文言を付与することも可能でした。

#Preview {
    ContentUnavailableView.search(text: "sample")
}

ContentUnavailableViewのアクセシビリティ

Apple提供のUIコンポーネントなので、おそらくアクセシビリティ機能は標準で大体実装されているだろう思ったので、VoiceOverとDynamicTypeに対応しているかみてみました。

VoiceOverの対応状況

想定通り、VoiceOverで読み上げられました。
ただこれは自分の知識不足で、日本語の文言が読み上げられなくて少しハマりました。

以下記事にある通り、String Catalogsで日本語として文言を管理することで、正しく読み上げられるようになりました。

DynamicType

こちらも想定通り、DynamicFontに対応していました。
image.png

ただ、以下イニシャライザだと、FontをsystemFontで設定できるので、systemFontで固定のフォントによる設定を行うと、DynaimcTypeには対応できませんでした。

おわり

ContentUnavailableViewを使うことで、統一感のあるEmpty StateのUIを素早く実装できそうです。
また、Appleに提供されているUIコンポーネントを使うことのメリットとして、アクセシビリティの対応を開発者が意識せずとも実装されていたりするので、
業務でもデザイナーさんと相談しつつ積極的に取り入れるのはアリかなと思いました。

2
1
0

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
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?