SpotifyまたはAppleミュージックアプリが曲の再生中に行うことと同様に、カスタムビューをUITabBarの上に配置します:
最大サイズのコンテナービューを備えたViewControllerのUITabBarController、およびコンテナービューの上にあるカスタムビュー49pt下のレイアウトガイドの上: 問題:下部に制約されたUITabBarControllerに埋め込まれたViewControllersのコンテンツは、カスタムレイアウトの背後に隠れているため表示されません。私はUITabBarControllerでsize forChildContentContainer
をオーバーライドしてみました。下部のレイアウトガイドNothingを更新してみました。 UITabBarControllerのコンテナビューのフレームのサイズを変更する必要があります。
もう一度#1を試しましたが、コンテンツの背後に隠れている問題を ITabBarのサイズを増やす で解決し、次に すべてのTabBarItemのImageInset を使用してそれを停止し、追加しましたUITabBarの上にあるカスタムビュー。本当にうまくいきませんでした。カスタムビューを非表示にしたい場合があります。
ルートとしてのUITabBarController、各子はコンテナビュー+私のカスタムビューを持つViewController: しかし、今では、カスタムビューの複数のインスタンスが浮かんでいます。ラベルを変更したい場合は、すべてのビューに変更する必要があります。または非表示など.
UITabBarControllerのUITabBarプロパティをオーバーライドし、UITabBar +カスタムビューを持つカスタムUITabBar(xibでインフレートされた)を返します。 問題:おそらくすべての中で最もイライラする試み。そのプロパティをclass MyCustomTabBar : UITabBar {}
のインスタンスでオーバーライドすると、タブは表示されません!そして、はい、myCustomTabBar
のデリゲートをself
に設定しました。
#3に傾いているが、より良いソリューションを探している。
わかった!
基本的に、元のUITabBarのサイズを大きくしてカスタムビューに対応し(そして上記のビューコントローラーのフレームを縮小し)、その上に複製のUITabBar +カスタムビューを追加しました。
これが私がしなければならないことの要点です。私はそれの機能的な例をアップロードしました このリポジトリにあります :
class TabBarViewController: UITabBarController {
var currentlyPlaying: CurrentlyPlayingView!
static let maxHeight = 100
static let minHeight = 49
static var tabbarHeight = maxHeight
override func viewDidLoad() {
super.viewDidLoad()
currentlyPlaying = CurrentlyPlayingView(copyFrom: tabBar)
currentlyPlaying.tabBar.delegate = self
view.addSubview(currentlyPlaying)
tabBar.isHidden = true
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
currentlyPlaying.tabBar.items = tabBar.items
currentlyPlaying.tabBar.selectedItem = tabBar.selectedItem
}
func hideCurrentlyPlaying() {
TabBarViewController.tabbarHeight = TabBarViewController.minHeight
UIView.animate(withDuration: 0.5, animations: {
self.currentlyPlaying.hideCustomView()
self.updateSelectedViewControllerLayout()
})
}
func updateSelectedViewControllerLayout() {
tabBar.sizeToFit()
tabBar.sizeToFit()
currentlyPlaying.sizeToFit()
view.setNeedsLayout()
view.layoutIfNeeded()
viewControllers?[self.selectedIndex].view.setNeedsLayout()
viewControllers?[self.selectedIndex].view.layoutIfNeeded()
}
}
extension UITabBar {
open override func sizeThatFits(_ size: CGSize) -> CGSize {
var sizeThatFits = super.sizeThatFits(size)
sizeThatFits.height = CGFloat(TabBarViewController.tabbarHeight)
return sizeThatFits
}
}
UITabBarControllerをサブクラス化し、ビューをプログラムで追加すると、これは実際には非常に簡単です。この方法を使用すると、使用しているバージョンに関係なく、タブバーの回転とサイズの変更が自動的にサポートされます。
class CustomTabBarController: UITabBarController {
override func viewDidLoad() {
super.viewDidLoad()
//...do some of your custom setup work
// add a container view above the tabBar
let containerView = UIView()
containerView.backgroundColor = .red
view.addSubview(containerView)
containerView.translatesAutoresizingMaskIntoConstraints = false
containerView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
containerView.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
// anchor your view right above the tabBar
containerView.bottomAnchor.constraint(equalTo: tabBar.topAnchor).isActive = true
containerView.heightAnchor.constraint(equalToConstant: 50).isActive = true
}
}
ラッパービューコントローラーに配置するという考えは良いですが、オーバーヘッド(ビューコントローラーがメモリに読み込まれる)が増えるだけで、後でコードを変更するときに問題が発生します。バーを常にUITabBarController
に表示したい場合は、そこに追加する必要があります。
UITabBarController
をサブクラス化し、nibからカスタムバーをロードする必要があります。そこでタブバーにアクセスでき(その上にバーを正しく配置できます)、一度にロードするだけです(これにより、各タブに別のバーがあることに直面するという問題が解決されます)。
カスタムバーのサイズに反応しないビューについては、どうすればよいかわかりませんが、個々のタブでリッスンするパブリック変数と通知を使用することをお勧めします。
それを使用して、下部拘束を変更できます。
UITabBarまたはコンテナーvcで遊ぶ以外に、次の投稿のように、アプリデリゲートのビューをメインウィンドウに追加することも検討できます。
すべてのViewControllerの上にフローティングビュー
あなたのビューはタブバーと一緒に四方八方にあるので、アプリデリゲートでそれを作ることは全く問題ありません。
アプリデリゲートのプロパティにすると、アプリデリゲートシングルトンからフローティングビューにいつでもアクセスできます。コードの任意の場所で可視性を制御するのは簡単です。
フローティングビューとスーパービューウィンドウ間の制約の定数を変更すると、ビューの位置を調整できるため、向きの変化にスムーズに対応できます。
別の(類似した)アプローチは、フローティングビューをuidボタンのような別のウィンドウにすることです。