ちゃちゃっす!iOS Advent Calendar 2018の15日目担当、株式会社ゆめみ新卒iOSエンジニアの山田です!
入社9ヶ月ほど経って色々経験したので、今まで使ったライブラリや技術を利用して出来るだけエモいTableViewを作ってみようチャレンジでした!
できたもの
ぜひ、実機で動かしてみてください!
何を作ったか
iTunesからトップ映画のxmlを取得してきてリスト表示
作成期間
8時間!
ここがエモい!
スケルトン表示
このライブラリすっごい便利じゃないっすか!!??
入れて見せておくだけでオシャンティになります。
(これが見せたいがためにTableViewのリロード三秒止めました😇)
離した時のアニメーション
dumpingアニメーション使っているので、バネっぽく元に戻ります!
気持ちよくないすか!!??
チームの先輩に教えてもらったのですが、すっかり虜になりました。
haptics
最近ハプティクスの使い所を探っているので、使ってみました。
プレスした状態から指を離した時に**ブルん!**ってなります!
気持ちいい!!!
(こちらは触ってみないと分からないので見せられなかったです...)
利用した技術/ハマりどころ
SkeletonView
Facebookが全く同じようなものを利用していますが、主に非同期通信時の読み込み中に表示しておくViewです。
基本的に簡単なのですが、微妙に使い方にクセがあるので慣れが必要です。
UIView
, UITableView
, UICollectionView
のいずれも対応されています。
dumpingアニメーション
UIViewの標準アニメーションを利用して、以下のように実装しました。
private func shrink() {
let animationScale: CGFloat = 0.90
UIView.animate(withDuration: 0.1) { [unowned self] in
self.transform = .init(scaleX: animationScale,
y: animationScale)
}
}
private func expand() {
let animationScale: CGFloat = 1.10
UIView.animate(withDuration: 0.1) { [unowned self] in
self.transform = .init(scaleX: animationScale,
y: animationScale)
}
}
private func restore() {
UIView.animate(withDuration: 0.1,
delay: 0,
usingSpringWithDamping: 0.7,
initialSpringVelocity: 1,
options: [],
animations: { [unowned self] in
self.transform = CGAffineTransform.identity
})
}
haptics
こちら、実装は極めて簡単で10行程度で実現できてしまいます。
注意点というのが一つだけあって、フィードバックの発生に遅延が出てしまう可能性があるらしく、処理の数秒前に feedbackGenerator.prepare()
を呼ぶのをAppleが推奨しています。
該当部分抜粋してGoogle翻訳先生にお聞きしました。
ジェネレーターを準備することで、フィードバックをトリガーするときの待ち時間を短縮できます。これは、音や映像の合図にフィードバックを一致させるときに特に重要です。
ジェネレータのprepare()メソッドを呼び出すと、Taptic Engineが準備された状態になります。パワーを維持するために、Taptic Engineは短時間(数秒のオーダー)の間、または次回のフィードバックをトリガーするまでこの状態にとどまります。
いつ、どこで発電機を準備するのが最も良いか考えてみましょう。 prepare()を呼び出してすぐにフィードバックをトリガーすると、システムはTaptic Engineを準備状態にするのに十分な時間がなくなり、待ち時間が短縮されることはありません。一方、prepare()をあまりに早く呼び出すと、フィードバックをトリガする前にTaptic Engineが再びアイドル状態になることがあります。
private let feedbackGenerator = UIImpactFeedbackGenerator(style: .light)
...
extension FloatingSkeletonTableViewController: FloatingSkeletonTableViewCellDelegate {
func cellWillStartAnimating() {
feedbackGenerator.prepare()
}
func cellWillEndAnimating() {
feedbackGenerator.impactOccurred()
}
}
UITableViewのセルの間のすきま
こんな感じのハックみたいな解決法をよく見かけたのですが、セクションを使いたくなった瞬間死ぬので使いませんでした。
https://stackoverflow.com/questions/6216839/how-to-add-spacing-between-uitableviewcell
- UITableViewCellのContentViewの上にさらに
floatingView
というのを乗せて上下左右10ptずつ内側に制約を付ける。 -
floatingView
は白背景に、その他背面ViewのbackgroundColorは全て.clear
にする。(青色のViewを除く)という対応にしました。
やりきれなかったところ
前半は勢いで書きましたが、本来hapticsの利用には最新の注意を払う必要があり、なにかユーザーに注意を促したい時や変化がある時以外は原則使わない方が良いです。
アニメーション+haptics feedbackで状態の変化を表現しようと思ったのですが(トップ画像が入れ替わるなど)残念ながらタイムオーバー。
TableViewCellが自分でリサイズとか、細かい詰めるところは全部すっ飛ばしました。
あとがき
ここまで読んでいただきありがとうございました!
レポジトリは公開しているので興味があれば実機で動かしてみてください!
(プルリクもお待ちしております!)