検証環境:
Xcode 12.3
Swift 5.3.2
※追記
この記事の実装方法では問題があることが発覚したので新しい記事で修正版を書いた。
多くのアプリでよく見かける、タブバーの中央に大きな画像ボタンを配置する方法について。
やり方はいろいろあるが、今回は中央のタブの上に別の UIView を貼り付ける方法で実現する。
実装例
まずは5つのタブがあるタブバーを用意する。
今回は StoryBoard 上で UITabBarController を配置、そこに5つの ViewController を接続する。
次に UITabBarController を継承したサブクラスを作成し、StoryBoard の UITabBarController のクラスとして設定する。
このクラス内で画像ボタンのビュー(今回は UIButton)を生成して貼り付け、 tabBar の中央に位置するように制約を付ける。
import UIKit class MyTabBarController: UITabBarController { override func viewDidLoad() { super.viewDidLoad() delegate = self setupMiddleButton() } private func setupMiddleButton() { let middleButtonHeight: CGFloat = 100 let middleButton = UIButton(type: .custom) middleButton.addTarget(self, action: #selector(handleMiddleButton), for: .touchUpInside) middleButton.setImage(UIImage.init(named: "play"), for: .normal) middleButton.translatesAutoresizingMaskIntoConstraints = false view.insertSubview(middleButton, aboveSubview: tabBar) middleButton.widthAnchor.constraint(equalToConstant: middleButtonHeight).isActive = true middleButton.heightAnchor.constraint(equalToConstant: middleButtonHeight).isActive = true middleButton.centerXAnchor.constraint(equalTo: tabBar.centerXAnchor).isActive = true let heightDifference = (tabBar.frame.height / 2) - (middleButtonHeight / 2) middleButton.topAnchor.constraint(equalTo: tabBar.topAnchor, constant: heightDifference).isActive = true } @objc func handleMiddleButton(_ sender: UIButton) { print("handleMiddleButton") } } extension MyTabBarController: UITabBarControllerDelegate { func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool { // 選択されたタブが中央の場合は画面遷移が発生しないように false を返す。 // ここでは中央のタブの viewController に ViewController2 を設定していたとする。 // ちなみに tabBarController.selectedIndex はまだ遷移前の index が入っているので判定には使えない。 if viewController is ViewController2 { return false } return true } func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) { print("didSelect: \(tabBarController.selectedIndex)") } }
UIButton の貼り付け先は UITabBarController.tabBar ではなく、UITabBarController.view にしている。
理由は tabBar に貼り付けると親ビューである tabBar の矩形からはみ出したビューに対してのタッチイベントが反応しなくなるため。