タブバーの[その他]メニューのカスタマイズ
-
22-07-2019 - |
質問
アプリでタブバー(UITabBarController)を使用しています。[詳細]ボタンをクリックしたときに表示されるテーブルの外観をカスタマイズしたいです。
を設定して、より多くの画面にあるナビゲーションバーの外観を変更する方法を考えましたself.moreNavigationController.navigationBar.barStyle
UITabBarControllerのサブクラスで、変更することでテーブルの背景色を変更できました
self.moreNavigationController.topViewController.view.backgroundColor
、ただし、テーブルに表示されるセルのフォントの色を変更する方法はわかりません。 使用できることを望んでいました
self.moreNavigationController.topViewController.view.visibleCells
しかし、これは常に空のようです。 viewDidLoad、viewWillAppear、viewDidAppearでこれを試しましたが、成功しませんでした。オブジェクトself.moreNavigationController.topViewControllerは、UIMoreListController型であり、文書化されていないようであり、インターフェイスでわかりやすいものは表示されません。
アイデアはありますか
解決
visibleCellsは、moreNavigationControllerが表示された後にのみ入力されます。
また、セルは実行時に作成されるため、セルのコンテンツを変更しても、セルは表示されるときに置き換えられます。
試してみることの1つは、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];
}
}
他のヒント
moreNavigationControllerのdataSourceを置き換えるというStephanの提案に続いて、実装したコードの概要を簡単に説明します。
UITableViewDataSourceプロトコルを実装するMoreTableViewDataSourceという新しいクラスを作成しました。より多くのページが実際にテーブルを構築するために使用するコントローラーは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
and
#import "MoreTableViewDataSource.h"
@interface CustomTabBarController : UITabBarController
{
MoreTableViewDataSource *moreTableViewDataSource;
}
不明に感謝します。 彼の解決策に従って、彼のコードをSwiftに配置します。 さらにすべきことは、MoreTableViewCellクラスを作成することだけです。 Storyboardを使用する必要はありません。 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)
}
}
Ianの実装に従ってMoreメニューをカスタマイズしましたが、メモリの警告後にカスタマイズを保持するのに問題がありました。 didReceiveMemoryWarningはUITableViewを破壊しているようで、再生成されると古いdataSourceを取り戻します。私の解決策は次のとおりです。
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を表示する直前に、表示されるたびにカスタムデータソースを常に設定するため、常にカスタムデータソースが使用されるようにします。
@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