自定义选项卡栏上的更多菜单

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

self.moreNavigationController.navigationBar.barStyle 

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

 self.moreNavigationController.topViewController.view.backgroundColor 

,但我不能解决如何更改表格中出现的单元格的字体颜色。 我希望能用

 self.moreNavigationController.topViewController.view.visibleCells 

但是这似乎总是空的。 我已经尝试在viewDidLoad中执行此操作,viewWillAppear和viewDidAppear没有成功。 对象self.moreNavigationController.topViewController的types是UIMoreListController,这似乎是无证的,我不能看到任何明显的界面,将帮助我。

有任何想法吗?

只有显示moreNavigationController后,才会填充visibleCells。

单元格是在运行时创build的,所以即使您更改了单元格的内容,它们在显示时也会被replace。

有一件事是尝试replacemoreNavigationController 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]; } } 

继斯蒂芬的build议,以取代moreNavigationController的dataSource,以下是我实现的代码的快速查看。

我创build了一个名为MoreTableViewDataSource的新类,它实现了UITableViewDataSource协议。 更多页面实际用来构build表的控制器被称为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; } 

感谢未知 。 按照他的解决scheme,我将把他的代码放在Swift中。 只有你应该做更多的是创buildMoreTableViewCell类,只是它。 您不必使用Storyboard。 如果你想修改tableView,你可以在customMoreTableView方法中完成。

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

我遵循Ian的实现来自定义更多菜单,但是在内存警告之后,我遇到了保留自定义的问题。 didReceiveMemoryWarning似乎破坏了UITableView,并且当它被重新生成时,它将得到它的旧数据源。 这是我的解决scheme:

我用下面的代码replaceCustomTabBarController上的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的头。 这是我添加的委托function:

 - (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之前就设置了它。

 @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