👂
animated-tab-barを使ってタブバーアイコンのアニメーションを実装する
概要
UITabBarController
の下に表示されるアイコンを選択したときにアニメーションをつけたいと思い少し調べた所、Viewを再帰的に見ないといけない等で大変そうな印象でした。
そこで今回はお手軽にanimated-tab-barを使って下記のような動きをする実装を試してみました。
参考
- Ramotion/animated-tab-bar
- [iOS][Swift3.0] タブにちょっとしたアニメーションを入れるanimated-tab-bar
- ライブラリを使わない実装はViewを再帰的に見たりしないといけないとかで大変そう…
実装
Ramotion/animated-tab-barのREADME通りCocoapodsで導入します
pod 'RAMAnimatedTabBarController'
初めにUITabBarController
の代わりにRAMAnimatedTabBarController
のカスタムクラスを作成します。
import RAMAnimatedTabBarController
class MainTabController: RAMAnimatedTabBarController {
// ~
}
- 今回は
self.viewControllers
にUINavigationController
を入れ込みます。 - このとき
UINavigationController
のUITabBarItem
にRAMAnimatedTabBarItem
を指定し、アニメーションを設定します。- アニメーションは後で作成する
RAMMyBounceAnimation
を指定しておきます。
- アニメーションは後で作成する
func templateNavigationController(image: UIImage?, selectedImage: UIImage? = nil, rootViewController: UIViewController) -> UINavigationController {
let nav = UINavigationController(rootViewController: rootViewController)
let animatedTabBarItem = RAMAnimatedTabBarItem(title: nil, image: image, selectedImage: selectedImage)
animatedTabBarItem.animation = RAMMyBounceAnimation() // オーバライドしたアニメーションクラスを適用させる
nav.tabBarItem = animatedTabBarItem
nav.navigationBar.barTintColor = .white
return nav
}
- 参考までに、上記は下記の通り使用しています。
func configureViewControllers() {
let feed = FeedController(collectionViewLayout: UICollectionViewFlowLayout())
let nav1 = templateNavigationController(image: UIImage(systemName: "house"),
selectedImage: UIImage(systemName: "house.fill"),
rootViewController: feed)
let list = ListController(collectionViewLayout: UICollectionViewFlowLayout())
let nav2 = templateNavigationController(image: UIImage(systemName: "doc.plaintext"),
rootViewController: list)
let search = SearchController(style: .plain)
let nav3 = templateNavigationController(image: UIImage(systemName: "magnifyingglass"),
rootViewController: search)
viewControllers = [nav1, nav2, nav3]
self.setSelectIndex(from: 0, to: 1)
}
- 続いてカスタムのアニメーションクラス
RAMMyBounceAnimation
を作成します。- デフォルトの
RAMBounceAnimation
がちょっと気にいらなかったので…
- デフォルトの
- 基本的に
RAMBounceAnimation
のコードをコピペしているだけで、アニメーションの時間と拡大縮小のコマ割りの設定だけ変更しています。
import RAMAnimatedTabBarController
class RAMMyBounceAnimation: RAMItemAnimation {
// MARK: - Properties
+ private let costomDuration: CGFloat = 0.2
// ...
func playBounceAnimation(_ icon: UIImageView) {
+ let bounceAnimation = CAKeyframeAnimation(keyPath: "transform.scale")
+ bounceAnimation.values = [0.9, 0.8, 0.9, 1.0]
+ bounceAnimation.duration = TimeInterval(costomDuration)
// ...
}
}
- また今のままでは、選択されているタブバーアイコンを再度選択した場合はアニメーションがつきません。
- そのため
UITabBarControllerDelegate
を利用して、同じアイコン選択時もアニメーションが表示されるようにします。- ただ
RAMAnimatedTabBarController
のprivate func handleSelection(index: Int)
をOverrideするのが本筋かもしれません。
- ただ
class MainTabController: RAMAnimatedTabBarController {
// MARK: - Properties
private var previousTabBarItemIndex = 0
private var nextTabBarItemIndex = 0
// ...
}
// MARK: - UITabBarControllerDelegate
extension MainTabController: UITabBarControllerDelegate {
func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool {
previousTabBarItemIndex = tabBarController.selectedIndex
return true
}
func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
nextTabBarItemIndex = tabBarController.selectedIndex
guard previousTabBarItemIndex == nextTabBarItemIndex,
let tabBarItem = viewController.tabBarItem as? RAMAnimatedTabBarItem else {
return
}
tabBarItem.playAnimation()
}
}
課題
SelectedImageが機能しない
- 今回参考にした
RAMBounceAnimation
はSelectedImage
を使用していないようです。 - Possible to work with different images of selected and unselected state? #75
- 実装する場合はデフォルトのアニメーション、例えば
RAMFrameItemAnimation
あたりを参考にしたらいいかもしれません。
Discussion