この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
FacebookやYouTubeアプリのローディング表示
FacebookやYouTubeアプリではコンテンツのローティング表示をUIActivityIndicatorViewを使わずに実装しています。
こちらはFacebookアプリ。
こちらはYouTubeアプリ。
UIActivityIndicatorViewと使った方法と比べ以下の利点があると思います。
- ユーザーがあらかじめどこにどのくらいの量の情報が表示されるかわかる
- ユーザーがアプリが現在何を読み込んでいるのかがわかる
個人的には見せ方によりますが、UIActivityIndicatorViewはちょっと 操作をブロックされている感が強いと思うことがあるのでFacebookやYouTubeアプリのような表示は良いなぁと思っていたところ、SkeletonViewというライブラリを見つけたのでご紹介したいと思います。
SkeletonViewとは
リポジトリはこちらです。
リポジトリからライブラリの説明を引用します。
An elegant way to show users that something is happening and also prepare them to which contents he is waiting
サポートしているOS、言語バージョンは以下です。MITライセンスで公開されています。
- iOS 9.0+
- Swift 4 (Swift 3 compatible)
検証環境
本エントリは以下の環境で検証を行っています。
- macOS Sierra バージョン 10.12.6
- Xcode Version 9.1 (9B55)
- Swift 4
- CocoaPods バージョン 1.3.1
- iPhone X シミュレーター iOS 11.1
セットアップ
CocoaPodsでサクッとインストールできます。
podfileにpod "SkeletonView"
と記載し、pod install
するだけです。
記事執筆時点の最新であるバージョン1.0.2
がインストールされました。
※ CocoaPods以外の方法でのインストール方法についてはInstallationをご覧ください。
試してみた
ビューのレイアウト
SkeletonViewを使ったローディング表示を以降「スケルトン表示」と表現させていただきます。 スケルトン表示は任意のUIViewで使用可能です。 今回は以下のように画面にUIImageViewとUILabelを配置してみました。 レイアウトを行ったらViewControllerとIBOutletで接続しておきましょう。
UIImageViewのAutoLayout制約はこんな感じ。
UILabelの制約はこんな感じ。
スケルトン表示の実装
レイアウトができたらスケルトン表示を実装していきます。
以下がViewControllerのソースコードです。
showAnimatedGradientSkeleton(usingGradient:)
を使ってグラデーションをかけたアニメーションを実行しています。
class ViewController: UIViewController {
@IBOutlet weak var myImageView: UIImageView!
@IBOutlet weak var myLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// スケルトン表示したいサブビューのisSkeletonableはtrueに設定する必要がある
myImageView.isSkeletonable = true
myLabel.isSkeletonable = true
// UILabelのnumberOfLinesを0に設定することでラベルの高さを埋めるような行数でスケルトン表示される。
// スケルトン表示の行数を明示的に指定したい場合は1以上を指定する。マイナスの値を設定するとクラッシュしてしまうので注意!
myLabel.numberOfLines = 0
// コンテナビュー
let containerView = view!
containerView.isSkeletonable = false
let gradient = SkeletonGradient(baseColor: .clouds)
containerView.showAnimatedGradientSkeleton(usingGradient: gradient)
// 擬似的なAPIコール
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + .seconds(5)) {
// 例えば非同期で取得した画像を表示する
self.myImageView.image = UIImage(named: "classmethod")
self.myLabel.text = "例えばここにAPIで取得した文字列を表示する"
// スケルトン表示をやめることで上で設定した内容が表示される
containerView.hideSkeleton()
}
}
}
ポイントは以下です。
- スケルトン表示したいビューの
isSkeletonable
をtrue
に設定する。逆にスケルトン表示したくない場合はfalse
に設定する。 - ビューのshow〜メソッドを呼びスケルトン表示を実行する
- スケルトン表示したいビューが複数ある場合は親のビューでメソッドを呼べばOK
- スケルトン表示したいビューが1つのみの場合は該当のビューでメソッド呼べばOK
- スケルトン表示をやめてコンテンツを表示したい場合は
hideSkeleton()
メソッドを呼ぶ
実行結果
いい感じですね!( ´◡` )
おわりに
FacebookやYouTubeのようなローディング表示ができるライブラリ「SkeletonView」を試してみました。
今回ご紹介した以外にもこのライブラリはUITableViewのライフサイクルに対応しています。UITableViewでスケルトン表示したい場合はCollectionsをチェックしてみてください。
なお、UICollectionViewのサポートも実装中とのこと。楽しみですね( ´◡` )