如何使用故事板将两个不同的Tab栏图标连接到同一个视图控制器?

问题描述 投票:3回答:7

我在iPad应用程序中有一个带有6个项目的标签栏控制器。当您点击它们时,其中两个图标将指向相同的视图控制器。此视图控制器具有将显示的项目列表,它将根据您点击的哪个标签栏图标稍微改变。

我如何用故事板设置它?可以将关系拖动两次到同一个视图控制器,但它只是在标签栏上显示两个相同的图标。我希望这两个选择有不同的图标和名称。

ios ipad uitabbarcontroller storyboard uistoryboard
7个回答
1
投票

我遇到了类似的问题并且很容易解决。

在Storyboard中创建一个TabBarController。

在每个选项卡中分配导航控制器。

将所有导航控制器设置为Root View Controller,即要在它们之间共享的一个视图控制器。

在View Controller中,在ViewDidLoad中,根据tabBarController.selectedIndex创建条件,以根据所选选项卡自定义视图控制器。像这样的东西:

override func viewDidLoad() {
    super.viewDidLoad()
    if let selectedTabIndex = tabBarController?.selectedIndex {
           switch selectedTabIndex:
           case 0: // Customize ViewController for tab 1
           case 1: // Customize ViewController for tab 2
           case 2: // Customize ViewController for tab 3
           default: break

}

0
投票

我不认为你可以做你正在尝试用UITabBarController做的事情。如果需要,可以添加同一视图控制器类的两个不同实例。否则,您必须向常规UIViewController添加标签栏,并编写自己的逻辑以在控制器之间切换。


0
投票

我能够通过在viewDidLoad中设置标签标题来实现这一目标。我为同一个View Controller创建了2个关系。然后我将条形项标题设置为“未设置”。最后,我将viewDidLoad方法设置如下:

  UITabBarController *tc = (UITabBarController *)self.parentViewController;
  NSArray *vcs = tc.viewControllers;
  BOOL tabsInitialized=YES;
  for (UIViewController *vc in vcs)
  {
    if ([vc.tabBarItem.title isEqualToString:@"Not Set"])
    {
      tabsInitialized = NO;
      break;
    }
  }
  if (!tabsInitialized)
  {
    int I=1;
    for (UIViewController *vc in vcs)
    {
      vc.tabBarItem.title = [NSString stringWithFormat:@"Tab %i", i++];
    }
  }
}

0
投票

我意识到这个问题已经回答了一段时间,但没有一个解决方案提到直接使用UITabBar并覆盖其UITabBarDelegate tabBar(:,didSelect item:)方法,而不是让UITabBarController间接处理选择。

extension MyListViewController: UITabBarDelegate {

    func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) {

        // Set some filter based on the selected item or its tag (tag values can be assigned in IB)
        switch item.tag {
            // Apply filter to your datasource based on the item.tag
        }

        // Or if you are using a CoreData NSFetchedResultsController, set its predicate:
        // resultsController.predicate = makePredicate(item.tag)
        // resultsController.performFetch()

        tableView.reloadData()
    }
}

通过直接覆盖UITabBarDelegate方法,您可以直接控制选项卡的选择行为。所以你可以重复使用你的UIViewController的相同实例,而不是UITabBarController为每个标签创建一个新的UIViewController实例。例如,在didSelect方法中,您可以将过滤器应用于UITableView中的现有项目列表,而不是像其他解决方案那样在新的UITableView中创建列表的新实例。

注意:如果你在代码或IB中的视图控制器中使用UITabBar,UIKit似乎不会识别它的存在,并且“underlapping”滚动视图(例如UITableViewUICollectionView)将不会自动调整它们的contentInset。如果你将它固定在安全区域的底部(它将看起来“浮动”,它自身和屏幕之间有一个间隙,它也不会固定在UITabBar的底部正确地放置在具有非零安全区域边距的设备上-边缘)。

解决方案(第1部分):特别在UITabBar实例上设置顶部约束:首先将标签栏的下边缘锚定到Superview并将顶边固定到安全区域的底边并将常数设置为49(在撰写本文时,UITabBar的标准高度)。然后在具有和没有安全区域边距的设备上看起来是正确的。

解决方案(第2部分):您需要手动调整tableView.contentInset / collectionView.contentInset以确保内容可以在标签栏下滚动。您需要确保最底部的项目仍然可以向上滚动到底部标签栏上方:

  1. 禁用viewDidLoad()中的自动内容插入调整: tableView.contentInsetAdjustmentBehavior = .never
  2. 在适当的位置调整UIScrollView.contentInset,添加以下方法并在viewDidLoad()中调用它,或者每当视图在viewDidLayoutSubviews()中放置时调用它。 (如果viewDidLoad()对你来说太早了,viewWillAppear()也可能太早了。) private func adjustScrollViewInsets() { // This snippet only insets the bottom of the table view, but you may need to adjust both top and bottom edges if you also need to accommodate a top navigation bar. var contentInset = tableView.contentInset if let windowInsets = view.window ?? UIApplication.shared.keyWindow?.safeAreaInsets { contentInset.bottom = windowInsets.bottom } else { contentInset.bottom = 0 } tableView.contentInset = contentInset }
© www.soinside.com 2019 - 2024. All rights reserved.