【问题标题】:Customizing the More menu on a Tab bar自定义标签栏上的更多菜单
【发布时间】:2010-10-01 02:29:11
【问题描述】:

我在我的应用程序上使用标签栏 (UITabBarController),我希望自定义单击更多按钮时出现的表格的外观。 我已经研究出如何通过设置来更改更多屏幕上导航栏的外观

self.moreNavigationController.navigationBar.barStyle

在 UITabBarController 的子类中,我设法通过修改来更改表格的背景颜色

self.moreNavigationController.topViewController.view.backgroundColor

,但我不知道如何更改表格上出现的单元格中的字体颜色。 我希望我可以使用

self.moreNavigationController.topViewController.view.visibleCells 

但这似乎总是空的。我试过在 viewDidLoad、viewWillAppear 和 viewDidAppear 中这样做,但没有成功。对象 self.moreNavigationController.topViewController 的类型是 UIMoreListController,它似乎没有记录,我在界面中看不到任何明显的帮助我的东西。

有什么想法吗?

【问题讨论】:

    标签: ios iphone uitabbarcontroller


    【解决方案1】:

    visibleCells 仅在显示 moreNavigationController 后才会填充。

    并且单元格是在运行时创建的,所以即使你改变了单元格的内容,它们在显示时也会被替换。

    可以尝试替换moreNavigationController tableView的数据源,调用原始数据源的cellForRowAtIndexPath,并在返回之前更改其内容。

    使用下面的代码,在显示一次moreNavigationController初始化它后,你会看到当你返回moreNavigationController时,单元格是红色的,但立即返回白色背景。

    UITableView *view = (UITableView *)self.tabBarController.moreNavigationController.topViewController.view;
    if ([[view subviews] count]) {
      for (UITableViewCell *cell in [view visibleCells]) {
        cell.backgroundColor = [UIColor redColor];
      }
    }
    

    【讨论】:

    • 好建议。我要试试
    • 它有效。我是这个网站的新手,我应该将我对您的想法的实现作为单独的答案发布吗?什么是正确的协议?
    • 我建议编辑您自己的问题并在下面添加答案。不过我也是新手!
    • 如何在c#中实现这一点?我正在使用 xamarin 表单。
    【解决方案2】:

    根据 Stephan 的建议,替换 moreNavigationController 的 dataSource,这里是我实现的代码的快速概览。

    我创建了一个名为 MoreTableViewDataSource 的新类,它实现了 UITableViewDataSource 协议。更多页面实际用于构建表的控制器称为 UIMoreListControllerModern,它只实现了 UITableViewDataSource 协议的必需部分。我的实现如下所示。

    -(MoreTableViewDataSource *) initWithDataSource:(id<UITableViewDataSource>) dataSource
    {
        self = [super init];
        if (self)
        {
                self.originalDataSource = dataSource;
        }
    
        return self;
    }
    
    - (void)dealloc
    {
        self.originalDataSource = nil;
        [super dealloc];
    }
    
    - (NSInteger)tableView:(UITableView *)table numberOfRowsInSection:(NSInteger)section
    {
        return [originalDataSource tableView:table numberOfRowsInSection:section];
    }
    
    
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        UITableViewCell *cell = [originalDataSource tableView:tableView cellForRowAtIndexPath:indexPath];
        cell.textColor = [UIColor whiteColor];
        return cell;
    }
    

    然后在我的 CustomTabBarController 类中我重写 viewDidLoad 如下:

    - (void)viewDidLoad {
    
        [super viewDidLoad];
    
        UINavigationController *moreController = self.moreNavigationController;
        moreController.navigationBar.barStyle = UIBarStyleBlackOpaque;
    
        if ([moreController.topViewController.view isKindOfClass:[UITableView class]])
        {
    
            UITableView *view = (UITableView *)moreController.topViewController.view;
            view.backgroundColor = [UIColor blackColor];
            moreTableViewDataSource = [[MoreTableViewDataSource alloc] initWithDataSource:view.dataSource];
            view.dataSource = moreTableViewDataSource;
    
        }
    }
    

    这里要求的是头文件

    @interface MoreTableViewDataSource : NSObject <UITableViewDataSource>
    {
        id<UITableViewDataSource> originalDataSource;
    }
    
    @property (retain) id<UITableViewDataSource> originalDataSource;
    
    -(MoreTableViewDataSource *) initWithDataSource:(id<UITableViewDataSource>) dataSource;
    
    @end
    

    #import "MoreTableViewDataSource.h"
    
    @interface CustomTabBarController : UITabBarController 
    {
        MoreTableViewDataSource *moreTableViewDataSource;
    }
    

    【讨论】:

    • 只是在这里加入对话......如果我理解正确的话,你正在链接 moreTableViewDataSource。好的!不过问题是:在 view.dataSource 分配之后是否应该有一个 [moreTableViewDataSource release] 来平衡分配?
    • 啊,等一下。 moreTableViewDataSource 不是通过属性访问的,所以没有额外的保留,对吧?但我想知道这是否应该是一个属性......嗯......
    • 我自己实现了类似的东西,在 iOS3.x 上我注意到设置 textLabel 的背景颜色不起作用。它始终与 tableView 的背景颜色相同。
    • 这看起来是一个不错的解决方案,但似乎滚动您自己的“更多”选项卡也可以让您更直接地控制。创建一个 MoreViewController,使其成为您的最后一个选项卡(最多 5 个),将 TableView 放入 nib,创建一个映射到您的 ViewControllers 的数组并处理 didSelectRowAtIndexPath。这为您提供了您自己的 MoreViewController,您可以像任何其他 ViewController 一样对其进行自定义。
    • 非常聪明的解决方案..我为 UITableViewDelegate 调整了它,因为我需要使用 willDisplayCell 更改更多表格单元格的背景颜色
    【解决方案3】:

    我按照 Ian 的实现来自定义“更多”菜单,但在出现内存警告后保留自定义设置时遇到了问题。 didReceiveMemoryWarning 似乎破坏了 UITableView,当它重新生成时,它会恢复它的旧数据源。这是我的解决方案:

    我将 CustomTabBarController 上的 viewDidLoad 替换为:

    - (void)viewDidLoad {
        [super viewDidLoad];
        UINavigationController* moreController = self.moreNavigationController;
        if ([moreController.topViewController.view isKindOfClass:[UITableView class]]) {
            moreController.delegate = self;
            self.moreControllerClass = [moreController.topViewController class];
            UITableView* view = (UITableView*) moreController.topViewController.view;
            self.newDataSource = [[[MoreDataSource alloc] initWithDataSource:view.dataSource] autorelease];
        }
    }
    

    如您所见,我添加了一些属性来存储我需要的东西。这些必须添加到标题中并合成。我还在标题中将 CustomTabBarController 设为 UINavigationControllerDelegate。这是我添加的委托函数:

    - (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
        if ([viewController isKindOfClass:self.moreControllerClass]) {
            UIView* view = self.moreNavigationController.topViewController.view;
            if ([view isKindOfClass:[UITableView class]]) {
                UITableView* tview = (UITableView*) view;
                tview.dataSource = self.newDataSource;
                tview.rowHeight = 81.0;
            }
        }
    }
    

    这样我可以确保始终使用我的自定义数据源,因为我在每次显示 UIMoreListController 之前都设置了它。

    【讨论】:

      【解决方案4】:
      @interface TabBarViewController () <UITableViewDelegate,UITableViewDataSource>
      
      @property (nonatomic,strong) UITableView* tabBarTableView;
      @property (nonatomic,weak) id <UITableViewDelegate> currentTableViewDelegate;
      
      @end
      
      @implementation TabBarViewController
      
      - (void)viewDidLoad {
          [super viewDidLoad];
          [self costumizeMoreTableView];
      
      }
      
      -(void)costumizeMoreTableView{
          _tabBarTableView = (UITableView *)self.moreNavigationController.topViewController.view;
          _currentTableViewDelegate = _tabBarTableView.delegate;
          _tabBarTableView.delegate = self;
          _tabBarTableView.dataSource = self;
          [_tabBarTableView registerNib:[UINib nibWithNibName:@"MoreTabBarTableViewCell" bundle:nil] forCellReuseIdentifier:@"MoreTabBarTableViewCell"];
      
      }
      
      -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
          return 120;
      }
      
      -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
          return 2;
      }
      
      - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
          MoreTabBarTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MoreTabBarTableViewCell" forIndexPath:indexPath];
          [cell setMoreTableValues];
          return cell;
      }
      
      -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath: (NSIndexPath *)indexPath{
            [_currentTableViewDelegate tableView:tableView didSelectRowAtIndexPath:indexPath];
       }
      
       @end
      

      【讨论】:

        【解决方案5】:

        感谢未知。 按照他的解决方案,我将把他的代码放在 Swift 中。 只有你应该做的更多是创建 MoreTableViewCell 类和它。您不必使用情节提要。如果要修改 tableView,可以在 customizeMoreTableView 方法中进行。

        class TabBarMenuController: UITabBarController, UITableViewDelegate, UITableViewDataSource{
        
        var tabBarItems: [UIViewController] = []
        var areMessagesVisible: Bool = false
        
        var titleForTabBars: [String] = ["resources", "events", "training", "my profile", "news", "contacts"]
        var iconNames: [String] = ["film", "calendar", "classroom", "profile", "news", "Phone"]
        var controllersStoryboardId: [String] = ["resourcesNavController", "eventsNavController", "enablementNavController", "profileNavController", "newsNavController", "contactsNavController"]
        
        // to manage moreTableView
        var moreTableView: UITableView = UITableView()
        var currentTableViewDelegate: UITableViewDelegate?
        
        override func viewDidLoad() {
            super.viewDidLoad()
        
            self.customizeMoreTableView()
            //to REMOVE
            areMessagesVisible = true
        
            if !areMessagesVisible{
                self.titleForTabBars.removeAtIndex(4)
                self.controllersStoryboardId.removeAtIndex(4)
                self.iconNames.removeAtIndex(4)
            }
        
            for i in 0 ..< controllersStoryboardId.count{
                tabBarItems.append(UIStoryboard(name: "Main", bundle: NSBundle.mainBundle()).instantiateViewControllerWithIdentifier(controllersStoryboardId[i]) as? UINavigationController ?? UINavigationController())
            }
            self.moreNavigationController.navigationBar.tintColor = UIColor.blackColor()
        }
        
        override func viewWillAppear(animated: Bool) {
        
            for i in 0 ..< tabBarItems.count{
                tabBarItems[i].tabBarItem = UITabBarItem(title: titleForTabBars[i], image: UIImage(named: iconNames[i]), selectedImage: UIImage(named: iconNames[i]))
            }
            self.viewControllers = tabBarItems
        }
        
        func customizeMoreTableView(){
            moreTableView = self.moreNavigationController.topViewController!.view as? UITableView ?? UITableView()
            currentTableViewDelegate = moreTableView.delegate;
            moreTableView.delegate = self
            moreTableView.dataSource = self;
            moreTableView.registerClass(MoreTableViewCell.self, forCellReuseIdentifier: "MoreTableViewCell")
        
        }
        
        func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        
            let moreCell  = tableView.dequeueReusableCellWithIdentifier("MoreTableViewCell", forIndexPath: indexPath) as? MoreTableViewCell ?? MoreTableViewCell()
        
            moreCell.textLabel?.text = titleForTabBars[indexPath.row + 4]
            moreCell.imageView?.image = UIImage(named: iconNames[indexPath.row + 4])
        
            /*let testLabel: UILabel = UILabel(frame: CGRect(x: 0, y: 0, width: 100, height: 40))
            testLabel.backgroundColor = UIColor.yellowColor()
            moreCell.addSubview(testLabel)
            */
            return moreCell
        }
        func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            return titleForTabBars.count - 4
        }
        
        func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
            currentTableViewDelegate?.tableView!(tableView, didSelectRowAtIndexPath: indexPath)
        }
        
         }
        

        【讨论】:

        • 那么,我在哪里以及如何初始化这个?
        【解决方案6】:

        这适用于 iOS 13、Swift 5.1:

        extension MyTabBarController: UITabBarControllerDelegate {
            // handle a select of the More tab
            func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
                // style all the tab bar windows and the More tab bar tableview
                if viewController == moreNavigationController,
                    let moreTableView = moreNavigationController.topViewController?.view as? UITableView {
                    view.tintColor = .systemOrange
                    moreNavigationController.navigationBar.tintColor = .systemOrange
                    moreTableView.tintColor = .systemOrange
                    moreTableView.backgroundColor = UIColor(named: "Your Color")
                    moreTableView.visibleCells.forEach {
                        $0.backgroundColor = UIColor(named: "Your Color")
                    }
                }
            }
        }
        

        【讨论】:

          猜你喜欢
          • 2012-01-23
          • 1970-01-01
          • 2022-11-28
          • 2019-05-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多