[OSS] FacebookやYouTubeのようなローディング表示ができるライブラリ「SkeletonView」を試してみた

FacebookやYouTubeアプリのローディング表示

FacebookやYouTubeアプリではコンテンツのローティング表示をUIActivityIndicatorViewを使わずに実装しています。

こちらはFacebookアプリ。

facebook

こちらはYouTubeアプリ。

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で接続しておきましょう。

layout

UIImageViewのAutoLayout制約はこんな感じ。

uiimageview_constraints

UILabelの制約はこんな感じ。

uilabel_constraints

スケルトン表示の実装

レイアウトができたらスケルトン表示を実装していきます。 以下が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()
        }
    }
}

ポイントは以下です。

  • スケルトン表示したいビューのisSkeletonabletrueに設定する。逆にスケルトン表示したくない場合はfalseに設定する。
  • ビューのshow〜メソッドを呼びスケルトン表示を実行する
    • スケルトン表示したいビューが複数ある場合は親のビューでメソッドを呼べばOK
    • スケルトン表示したいビューが1つのみの場合は該当のビューでメソッド呼べばOK
  • スケルトン表示をやめてコンテンツを表示したい場合はhideSkeleton()メソッドを呼ぶ

実行結果

いい感じですね!( ´◡` )

skelton_view_sample

おわりに

FacebookやYouTubeのようなローディング表示ができるライブラリ「SkeletonView」を試してみました。 今回ご紹介した以外にもこのライブラリはUITableViewのライフサイクルに対応しています。UITableViewでスケルトン表示したい場合はCollectionsをチェックしてみてください。
なお、UICollectionViewのサポートも実装中とのこと。楽しみですね( ´◡` )