20

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

self.moreNavigationController.navigationBar.barStyle

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

self.moreNavigationController.topViewController.view.backgroundColor

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

self.moreNavigationController.topViewController.view.visibleCells 

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

有任何想法吗?

4

6 回答 6

26

继 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;
}
于 2009-01-13T17:01:21.100 回答
21

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

并且单元格是在运行时创建的,因此即使您更改了单元格的内容,它们也会在显示时被替换。

要尝试的一件事是替换 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];
  }
}
于 2009-01-13T10:13:09.847 回答
4

感谢未知。按照他的解决方案,我会将他的代码放在 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)
}

 }
于 2016-04-11T10:49:55.597 回答
2

我按照 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 之前将其设置为这种方式。

于 2011-01-26T23:26:44.820 回答
1
@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
于 2016-03-01T10:12:50.170 回答
1

这适用于我在 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")
            }
        }
    }
}
于 2020-02-12T09:29:51.700 回答