在UITabBar顶部查看

时间:2017-02-22 06:46:03

标签: ios swift uitabbar

类似于Spotify或Apple Music应用程序在播放歌曲时所执行的操作,它会在UITabBar顶部放置一个自定义视图: enter image description here

我尝试过的解决方案:

  1. ViewController中的UITabBarController,具有最大尺寸的容器视图,以及底部布局指南上方Container View49pt顶部的自定义视图: enter image description here 问题: UITabBarController中嵌入的ViewControllers中的任何内容都限制在底部,因为它们隐藏在自定义布局后面。我尝试在UITabBarController中覆盖size forChildContentContainer,尝试更新底部布局指南,Nothing。 我需要调整UITabBarController的容器视图框架。

  2. 再次尝试#1,但尝试通过increasing the size of UITabBar解决隐藏在其后面的内容问题,然后使用ImageInset on every TabBarItem将其关闭,并在我的基础上添加自定义视图UITabBar。哈斯工作得很好。有时候我想隐藏自定义视图。

  3. UITabBarController作为root用户,每个子节点都是一个ViewController,带有一个Container View +我的自定义视图: enter image description here 但现在我有多个自定义视图实例浮动。如果我想更改其上的标签,则必须将其更改为所有视图。或者隐藏等等。

  4. 覆盖UITabBarController的UITabBar属性,并返回具有UITabBar +我的自定义视图的自定义UITabBar(用xib充气)。 问题:可能是所有人最令人沮丧的尝试。如果您使用class MyCustomTabBar : UITabBar {}实例覆盖该属性,则不会显示任何标签!是的,我将myCustomTabBar的代表设置为self

  5. 倾向于#3,但寻找更好的解决方案。

7 个答案:

答案 0 :(得分:6)

我明白了!

enter image description here

本质上,我增加了原始UITabBar的大小以容纳自定义视图(并缩小上面的viewcontrollers的框架),然后在其上添加一个重复的UITabBar +自定义视图。

这是我必须要做的事情。我上传了一个功能正常的例子,可以是found in this repo

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
    }
}

答案 1 :(得分:6)

如果您继承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
  }
}

答案 2 :(得分:4)

自iOS 11起,这变得更加容易。添加视图时,可以执行以下操作:

viewControllers?.forEach {
   $0.additionalSafeAreaInsets = UIEdgeInsets(
      top: 0, 
      left: 0,
      bottom: yourView.height,
      right: 0
   )
}

答案 3 :(得分:2)

您将它放在包装器viewcontroller中的想法很好,但它只会导致开销(更多的viewcontrollers加载到内存中),以及以后想要更改代码时出现的问题。如果您希望该栏始终显示在final ObjectMapper mapper = new ObjectMapper(); WatcherTO[] dimensionList = mapper.readValue(passYourJson, WatcherTO[].class); 上,那么您应该将其添加到那里。

您应该继承override func touchesBegan(_ touches: Set<AnyHashable>, withEvent event: UIEvent) { var touch: UITouch? = touches.first //location is relative to the current view // do something with the touched point if touch?.view != yourView { yourView.isHidden = true } } 并从笔尖加载自定义栏。在那里你可以访问标签栏(这样你就可以正确地将它放在它上面),你只需加载一次(这就解决了你在每个标签上都有不同栏的问题)。

至于您的观点没有对自定义栏的大小做出反应,我不知道如何做到这一点,但我最好的建议是使用您在各个标签中收听的公共变量和通知。
然后,您可以使用它来更改底部约束。

答案 4 :(得分:1)

除了使用UITabBar或容器vc之外,您还可以考虑将App Delegate中的视图添加到主窗口,如下面的帖子所示:

View floating above all ViewControllers

由于您的视图与标签栏一起出现,因此可以在App Delegate中进行查看。

您始终可以通过将App Delegate Singleton的属性作为App Delegate的属性来访问浮动视图。然后,可以轻松地在代码的任何位置控制其可见性。

在浮动视图和超级视图窗口之间更改约束常量可以调整视图的位置,从而对方向变化做出很好的响应。

另一种(类似的)方法是使浮动视图成为另一个窗口,如uid按钮。

答案 5 :(得分:1)

除非我有误解,否则您可以从UITabBarController类创建自定义视图。然后,您可以上方插入它,并将其约束到tabBar对象,该对象是与控制器的tabBar关联。

因此,从您的UITabBarController类中,创建您的自定义视图

class CustomTabBarController: UITabBarController {
    var customView: UIView = {
            let bar = UIView()
            bar.backgroundColor = .white
            bar.translatesAutoresizingMaskIntoConstraints = false
            return bar
        }()

在viewDidLoad()中,将自定义视图添加到UITabBarController的视图对象并将其放置在上方 tabBar对象

override func viewDidLoad() {
        super.viewDidLoad()

        ...

        self.view.insertSubview(customView, aboveSubview: tabBar)

然后在将自定义视图添加为子视图之后,添加约束以使其正确定位。这也应该在viewDidLoad()中完成,但只能在插入视图之后进行。

self.view.addConstraints([
            NSLayoutConstraint(item: customView, attribute: .leading, relatedBy: .equal, toItem: tabBar, attribute: .leading, multiplier: 1, constant: 0),
            NSLayoutConstraint(item: customView, attribute: .trailing, relatedBy: .equal, toItem: tabBar, attribute: .trailing, multiplier: 1, constant: 0),
            NSLayoutConstraint(item: customView, attribute: .top, relatedBy: .equal, toItem: tabBar, attribute: .top, multiplier: 1, constant: -50),
            NSLayoutConstraint(item: customView, attribute: .bottom, relatedBy: .equal, toItem: tabBar, attribute: .top, multiplier: 1, constant: 0)
            ])

您可以通过很多创造性的方法来设置约束以执行所需的操作,但是上面的约束应在tabBar上方附加一个高度为50的视图。

答案 6 :(得分:0)

  1. 使视图的框架具有选项卡栏的高度并将其移到顶部,2.将tabBar隐藏设置为true。