私のiOSアプリでは、私のウィンドウのrootViewControllerは、次のような階層を持つTab Bar Controllerです。
ユーザーがFirstContentController
の特定の行をタップすると、SecondController
のインスタンスがNavigation Controllerにプッシュされます。 SecondContentController
は、hidesBottomBarWhenPushed
メソッドでYES
をinit
に設定し、self.navigationController.toolbarHidden
からNO
へviewWillAppear:
。
IOS 6では、ユーザーはFirstController
の行をタップし、SecondController
はnavコントローラーにプッシュされます。 hidesBottomBarWhenPushed
が設定されているため、タブバーが非表示になり、遷移アニメーションが完了するまでに、SecondController
がツールバーに表示された状態で画面に表示されます。
ただし、iOS 7でこれをテストすると、hidesBottomBarWhenPushed
の動作が変更されたようです。私が今見ているのは:
ギャップは完全に使用できません-タッチに応答せず、メインビューでclipsToBounds
をYESに設定しても、何も描画されません。多くのデバッグとサブビュー階層の調査の後、iOSの自動サイズ調整メカニズムにより、View Controllerのビューのサイズが411(iPhone 5上)に変更されたように見えます。ツールバーに至るまで460に達するはずですが、レイアウトシステムには「ゴースト」の49ピクセルの高さのタブバーが含まれているようです。
この問題は、View ControllerのTab Bar Controllerが親コンテナである場合にのみ発生します。
IOS 7では、新しいコントローラーが押されたときにタブバーが消え、ツールバーがシームレスに所定の位置にスライドし、ビューがナビゲーション項目とツールバーの間のスペース全体を占めるようにする方法はありますか?
[〜#〜] update [〜#〜]
さらに調査した結果、SecondControllerのedgesForExtendedLayout
がUIRectEdgeNone
に設定されている場合にのみ発生します。ただし、そのプロパティをUIRectEdgeNone
に設定しない限り、ビューのフレームは長すぎてツールバーの下に表示されるため、表示したり操作したりすることはできません。
[プッシュ時にボトムバーを非表示にする]のチェックを外し、タブバーがあるかのように自動制約を設定します。次に、システムタブバーを非表示にするコントローラーの「ViewDidLoad」に、次のコードを配置します。
[self.tabBarController.tabBar setFrame:CGRectZero];
これにより、タブバーはユーザーの操作を受け入れますが、ユーザーには表示されません。 (アルファ値を0に設定したり、非表示にしたりすると、タブバーは役に立たなくなります)autoconstaraintsは、タブバーの高さをゼロとしてビューが正しく表示されるようにします。
SecondViewControllerのviewDidLoad
(TabBarを非表示にし、ツールバーを表示する)に次の2行のコードを追加すると、問題が解決することがわかりました。
self.extendedLayoutIncludesOpaqueBars = YES;
self.edgesForExtendedLayout = UIRectEdgeBottom;
SecondViewControllerの私のviewDidLoadは次のとおりです。
- (void)viewDidLoad {
[super viewDidLoad];
// These 2 lines made the difference
self.extendedLayoutIncludesOpaqueBars = YES;
self.edgesForExtendedLayout = UIRectEdgeBottom;
// The usual configuration
self.navigationController.navigationBar.barStyle = UIBarStyleBlack;
self.navigationController.navigationBar.translucent = NO;
self.navigationController.toolbarHidden = NO;
self.navigationController.toolbar.barStyle = UIBarStyleBlack;
self.navigationController.toolbar.translucent = NO;
.
.
}
ただし、サイズが(320x504)になるため、ビューのフレームを手動で修正する必要があります。これは、ツールバーの背後にも拡張されることを意味します。これが問題にならない場合は、このソリューションが機能するはずです。
この答えは気に入らないでしょう これはあなたが望む答えではありませんが、iOS7でタブバーを隠すことに関するいくつかの調査の後、私の結論は次のとおりです:do n't!
タブバーを非表示にするつもりはありませんでした-結局、タブバーを非表示にしたいのであれば、なぜUITabBarController
があります。 View ControllerのhidesBottomBarWhenPushed
は、TabバーではなくNavigation Controllerの下部バーを非表示にするためのものです。ドキュメントから:
a navigation controllerの子として追加されたView Controllerは、画面の下部にオプションのツールバーを表示できます。一番上のView Controllerのこのプロパティの値は、ツールバーが表示されるかどうかを決定します。このプロパティの値がYESの場合、toolbarは非表示です。このプロパティの値がNOの場合、バーは表示されます。
さらに、タブバーオブジェクトを直接変更しないように警告されます。繰り返しますが、ドキュメントから:
このプロパティに保存されているUITabBarオブジェクト自体を操作しようとしないでください。
これは、非表示に設定するときに実行していることとまったく同じです。
IOS6ではこれは機能していましたが、現在iOS7では機能していません。そして、それを隠すのは非常に間違いやすいようです。最終的に非表示にしたときに、アプリがバックグラウンドに戻って戻ると、Appleのレイアウトロジックが変更をオーバーライドします。
私の提案は、データをモーダルに表示することです。 iOS7では、カスタムトランジションを作成できます。そのため、プッシュトランジションを持つことが重要な場合は、自分でそれを再作成できますが、これは少し上です。通常のモーダルトランジションはユーザーがよく知っているものであり、実際にはタブバーを非表示にするプッシュよりもこのケースに適しています。
別の解決策は、タブバーの代わりにツールバーを使用することです。タブにNavigation Controllerのツールバーを使用する場合、必要に応じてhidesBottomBarWhenPushed
を使用すると、期待どおりの動作が得られます。
これは、次の特定の組み合わせによるiOS 7 UIKitのバグです。
Appleでバグを報告し、サンプルコードを含める必要があります。
バグを回避するには、これら4つの条件のいずれかを削除する必要があります。考えられる2つのオプション:
「2番目の」View Controllerのレイアウトを修正して、edgesForExtendedLayout
がUIRectEdgeAll
に設定されている場合に正しく機能するようにします。これは、スクロールビューでcontentInset
を設定するのと同じくらい簡単です。
UINavigationControllerの組み込みツールバーを使用しないでください。代わりに、別のUIToolBarインスタンスを作成し、2つ目のView Controllerのビューに手動で追加します。
tabBar
のTabBarController
をhidden
に設定する必要があり、ビューにはautosizing
を柔軟な高さに設定する必要があります。
このコードで動作します:
@implementation SecondController
-(id)init
{
if( (self = [super init]) )
{
}
return self;
}
- (void)viewDidLoad;
{
[super viewDidLoad];
self.view.backgroundColor = [UIColor redColor];
self.view.autoresizingMask = UIViewAutoresizingFlexibleHeight;
self.tabBarController.tabBar.hidden = YES;
}
-(void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
// will log a height of 411, instead of the desired 460
NSLog(@"frame: %@", NSStringFromCGRect(self.view.frame));
}
@end
または、hidesBottomBarWhenPushed
メソッドを使用する場合は、これを行う必要がありますbefore you Pushビューコントローラーは明らかに:
-(void)tableView:(UITableView*)tableView didSelectRowAtIndexPath:(NSIndexPath*)indexPath
{
SecondController* controller = [[SecondController alloc] init];
controller.hidesBottomBarWhenPushed = YES;
[self.navigationController pushViewController:controller animated:YES];
}
2番目のメソッドを使用する場合、viewDidLoadメソッドは、柔軟なheightメソッドとtabBarHiddenを取り除くことができます。
- (void)viewDidLoad;
{
[super viewDidLoad];
self.view.backgroundColor = [UIColor redColor];
self.edgesForExtendedLayout = UIRectEdgeNone;
}
結果を見る:
この難問の鍵は、navigationcontroller.view.frameサイズが変わらないことです。バトキンの要点はここにある 自分の要点 です。
FirstViewController.m
#import "FirstController.h"
#import "SecondController.h"
@implementation FirstController
-(id)init
{
if( (self = [super init]) )
{
self.tabBarItem.title = @"Foo";
self.tabBarItem.image = [UIImage imageNamed:@"Tab Icon.png"];
}
return self;
}
-(NSInteger)tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)section
{
return 1;
}
-(UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath
{
UITableViewCell* cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil];
cell.textLabel.text = @"Click";
return cell;
}
-(void)tableView:(UITableView*)tableView didSelectRowAtIndexPath:(NSIndexPath*)indexPath
{
SecondController* controller = [[SecondController alloc] init];
self.tabBarController.tabBar.hidden = YES;
[self.navigationController pushViewController:controller animated:YES];
}
@end
SecondViewController.m
#import "SecondController.h"
@implementation SecondController
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.view.backgroundColor = [UIColor redColor];
self.view.clipsToBounds = YES;
/* ENTER VORTEX OF DESPAIR */
// without this, there's no gap, but the view continues under the tool
// bar; with it, I get the 49-pixel gap thats making my life miserable
self.edgesForExtendedLayout = UIRectEdgeNone;
//this resizes the navigation controller to fill the void left by the tab bar.
CGRect newFrame = self.navigationController.view.frame;
newFrame.size.height = newFrame.size.height + 49;
self.navigationController.view.frame = newFrame;
/* EXIT VORTEX OF DESPAIR */
self.navigationController.toolbarItems = @[
[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemSave target:nil action:nil]
];
}
-(void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
self.navigationController.toolbarHidden = NO;
// will log a height of 411, instead of the desired 460
NSLog(@"frame: %@", NSStringFromCGRect(self.view.frame));
NSLog(@"frame: %@", NSStringFromCGRect(self.navigationController.view.frame));
}
-(void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
self.tabBarController.tabBar.hidden = NO;
self.navigationController.toolbarHidden = YES;
//this resizes the navigation controller back to normal.
CGRect newFrame = self.navigationController.view.frame;
newFrame.size.height = newFrame.size.height - 49;
self.navigationController.view.frame = newFrame;
//this is optional and resizes the view to fill the void left by the missing toolbar.
CGRect newViewFrame = self.view.frame;
newViewFrame.size.height = newViewFrame.size.height + 49;
self.view.frame = newViewFrame;
}
@end
自動レイアウトを使用している場合は、トップレイアウトガイドまたはボトムレイアウトガイドではなく、必ずスーパービューにビューを固定してください。
edgesForExtendedLayout
に触れないことでこれを修正できると言います。 View Controllerのコンテンツ/コントロールが、プッシュされたView Controllerのルートビューに含まれている必要な理由はありますか?メインビューの最初で唯一の子であるビューですべてをラップすることを検討できます。次に、プッシュされたView ControllerのviewDidLayoutSubviews
でそのビューのフレームを調整し、View Controllerのtop/bottomLayoutGuideを使用してツールバーの下に永続的にコンテンツが表示されるのを防ぎます。
私は手動でボトムタブバーの非表示/非表示をフェードアニメーションとともに管理します
...
[self.tabBarController.tabBar setHidden:NO];
[self.tabBarController.tabBar setAlpha:0.1];
[UIView animateWithDuration:0.2 animations:^{
[self.tabBarController.tabBar setAlpha:1.0];
}];
...
SecondVCの下部ツールバーがIBに追加されました。今のところ問題ありません。ストーリーボードを使用します。
これは私を助けます:ストーリーボードでコントローラーの表示を選択します->プロパティに移動->「スクロールインセットの調整」のチェックを外します
Gistを使用して新しいプロジェクトを作成し、UITabBarControllerをUINavigationControllerに入れました。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
UITabBarController* tabController = [[UITabBarController alloc] init];
tabController.viewControllers = @[
[[UINavigationController alloc] initWithRootViewController:[[FirstViewController alloc] init]],
[[UINavigationController alloc] initWithRootViewController:[[FirstViewController alloc] init]]
];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:tabController];
[navController setNavigationBarHidden:YES];
self.window.rootViewController = navController;
return YES;
}
そして、SecondViewControllerを表示するために、私がやったことは次のとおりです。
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
SecondViewController* controller = [[SecondViewController alloc] init];
// Reaching the UITabBarViewController's parent navigationController
[self.parentViewController.navigationController pushViewController:controller animated:YES];
}
最後に、secondViewControllerで:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.view.backgroundColor = [UIColor redColor];
self.view.clipsToBounds = YES;
// The following line only works in iOS7
if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1) {
self.edgesForExtendedLayout = UIRectEdgeNone;
}
[self.navigationItem setRightBarButtonItem:[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemSave target:nil action:nil]];
UIBarButtonItem * logoutButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemReply target:nil action:nil];
NSMutableArray * arr = [NSMutableArray arrayWithObjects:logoutButton, nil];
[self setToolbarItems:arr animated:YES];
[self.navigationController setNavigationBarHidden:NO animated:YES];
[self.navigationController setToolbarHidden:NO animated:YES];
}
- (void)viewWillDisappear:(BOOL)animated
{
[self.navigationController setNavigationBarHidden:YES animated:YES];
[self.navigationController setToolbarHidden:YES animated:YES];
}
表示されるのは次のとおりです。
編集:サンプルを変更し、スクリーンショットを変更しました。 iOS6の例を互換性のあるものにしました。
ViewDidLoadで、またはsecondViewControllerがプッシュされる前に、呼び出しhidesBottomBarWhenPushedを移動しようとしましたか?
Ios7では、適切なタイミングで呼び出しを行わないと、多くのタイミングの問題が発生します。
SecondControllerのedgesForExtendedLayoutをUIRectEdgeBottomに設定できると思います。