普段何気なく使っていたYouTubeアプリですが、そのミニプレイヤーは結構面白い動作をしています。
画像はYouTube Musicのものですが、ミニプレイヤーは具体的には以下のようなものです。
YouTubeアプリもほぼ同じような動作です。
ハーフモーダルではなく、下部のタブバーと連動し、同一ビューでサイズを変えて、その内部でパーツのサイズを変えてシームレスにUIを変更しています。
サイズの変更は縦スワイプで行えます。
このViewの実装はどうやるんだろうと思い、いろいろ調べてみたのですが、実装方法やライブラリーをうまく見つけることができませんでした。
でもまあ、見つけられないならしょうがないので、とりあえずガワの部分だけでも実装してみることにしました。
その結果のソースはこちらで、Playgroundにコピペで動作します。
基本的にはジェスチャーの移動量に応じて、オートレイアウトでビューの高さと下マージンを変更する、というものになります。
当初はframe
でやろうとしていたのですが、下マージンの兼ね合いでY座標の計算が非常に面倒でしたのでオートレイアウトに切り替えたところ、非常にシンプルになりました。
また当初はスワイプを検出するUISwipeGestureRecognizerで良いのかと思っていたのですが、こちらはiOSで既定されているスワイプ動作を行った際に発火するもので、移動量の取得はできないようです。
移動量を取得する際にはUIPanGestureRecognizerを利用する必要があるようです。
L68-
/// ジェスチャーの設定
private func setGestureRecognizer() {
let recognizer = UIPanGestureRecognizer(target: self, action: #selector(onPanGesture(_:)))
addGestureRecognizer(recognizer)
}
今後いろいろ使いまわせるように、極力MiniPlayerView
内に処理を収めたいという方針でやってみたのですが、結果的に大部分を収めることができました。
こちらはいろいろ調べている最中に見つけたものですが、View内部よりsuperviewでオートレイアウトを設定する、というテクニックは今後いろいろ使えそうです。
L84-
// 制約の設定
translatesAutoresizingMaskIntoConstraints = false
heightConstraint = heightAnchor.constraint(equalToConstant: minHeight)
bottomConstraint = bottomAnchor.constraint(equalTo: superview.bottomAnchor, constant: maxMargin)
NSLayoutConstraint.activate([heightConstraint, bottomConstraint,
leftAnchor.constraint(equalTo: superview.leftAnchor),
rightAnchor.constraint(equalTo: superview.rightAnchor)])
とりあえずView自体の動きだけ試しに実装してみましたが、View内部のUIの動きはオートレイアウトでやっていくことになるでしょう。
タブバーなど外部のUIとの連携はデリゲートなりCombineなどを実装する必要はあり、Viewの継承元クラスとして使えるようにはなっておらず、使い回しは現状できませんが、実際に使う段階で考えたいと思います。