Pregunta

Estoy usando una barra de pestañas (UITabBarController) en mi aplicación y deseo personalizar la apariencia de la tabla que aparece cuando hace clic en el botón más. He calculado cómo cambiar la apariencia de la barra de navegación que se encuentra en la pantalla más configurando

self.moreNavigationController.navigationBar.barStyle

en una subclase de UITabBarController y he logrado cambiar el color de fondo de la tabla modificando

self.moreNavigationController.topViewController.view.backgroundColor

, pero no puedo resolver cómo cambiar el color de fuente en las celdas que aparecen en la tabla. Esperaba poder usar

self.moreNavigationController.topViewController.view.visibleCells 

pero esto siempre parece estar vacío. He intentado hacer esto en viewDidLoad, viewWillAppear y viewDidAppear sin éxito. El objeto self.moreNavigationController.topViewController es del tipo UIMoreListController, que parece no estar documentado y no puedo ver nada obvio en la interfaz que me ayude.

¿Alguna idea?

¿Fue útil?

Solución

visibleCells se completa solo después de que se muestra moreNavigationController.

Y las celdas se crean en tiempo de ejecución, por lo que incluso si cambia el contenido de las celdas, se reemplazan cuando se muestran.

Una cosa para intentar sería reemplazar el origen de datos de moreNavigationController tableView, llamar a cellForRowAtIndexPath del origen de datos original y cambiar su contenido antes de devolverlo.

Usando el siguiente código, después de haber mostrado una vez más moreNavigationController para inicializarlo, verá que cuando regrese a moreNavigationController, las celdas son rojas, pero vuelven inmediatamente al fondo blanco.

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

Otros consejos

Siguiendo la sugerencia de Stephan de reemplazar la fuente de datos de moreNavigationController, aquí hay una vista rápida del código que implementé.

Creé una nueva clase llamada MoreTableViewDataSource que implementa el protocolo UITableViewDataSource. El controlador que más páginas usa realmente para construir la tabla se llama UIMoreListControllerModern, y esto implementa solo las partes requeridas del protocolo UITableViewDataSource. Mi implementación se ve así.

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

y luego en mi clase CustomTabBarController anulo viewDidLoad de la siguiente manera:

- (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;

    }
}

Como se solicita aquí están los archivos de encabezado

@interface MoreTableViewDataSource : NSObject <UITableViewDataSource>
{
    id<UITableViewDataSource> originalDataSource;
}

@property (retain) id<UITableViewDataSource> originalDataSource;

-(MoreTableViewDataSource *) initWithDataSource:(id<UITableViewDataSource>) dataSource;

@end

y

#import "MoreTableViewDataSource.h"

@interface CustomTabBarController : UITabBarController 
{
    MoreTableViewDataSource *moreTableViewDataSource;
}

Gracias a Desconocido . Después de su solución, pondré su código en Swift. Lo único que debe hacer más es crear la clase MoreTableViewCell y solo eso. No tienes que usar Storyboard. Si desea modificar tableView, puede hacerlo en el método personalizarMoreTableView.

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

 }

Seguí la implementación de Ian para personalizar el menú Más, pero tenía problemas para retener las personalizaciones después de una advertencia de memoria. didReceiveMemoryWarning parece destruir el UITableView, y cuando se regenera, recupera su antigua fuente de datos. Aquí está mi solución:

Reemplazo viewDidLoad en CustomTabBarController con esto:

- (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];
    }
}

Como puede ver, agregué algunas propiedades para almacenar cosas que necesitaba. Esos deben agregarse al encabezado y sintetizarse. También hice CustomTabBarController un UINavigationControllerDelegate en el encabezado. Aquí está la función de delegado que agregué:

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

De esta manera me aseguro de que mi fuente de datos personalizada siempre se use, porque la configuré de esa manera justo antes de mostrar el UIMoreListController, cada vez que se muestra.

@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
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top