탭 표시줄의 자세히 메뉴 사용자 정의
-
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가 표시된 후에만 채워집니다.
그리고 셀은 런타임에 생성되기 때문에 셀의 내용을 변경하더라도 표시될 때 교체됩니다.
시도해 볼 수 있는 한 가지는 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의 데이터 소스를 대체하기위한 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 클래스에서 i 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;
}
감사합니다 알려지지 않은. 그의 해결책에 따라 나는 그의 코드를 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)
}
}
더 많은 메뉴를 사용자 정의하기 위해 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를 헤더에서 UinavationControllerDelegate로 만들었습니다. 내가 추가 한 대의원 기능은 다음과 같습니다.
- (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