UITabBarController管理着几个UINavigationController时怎么android 横屏时宽高

总结iOS App开发中控制屏幕旋转的几种方式
作者:汪鸿俊
字体:[ ] 类型:转载 时间:
这篇文章主要介绍了iOS app开发中控制屏幕旋转的方法总结,分为自动旋转和手动旋转以及强制旋转三种情况,代码为Objective-C语言,需要的朋友可以参考下
在iOS6之前的版本中,通常使用 shouldAutorotateToInterfaceOrientation 来单独控制某个UIViewController的方向,需要哪个viewController支持旋转,只需要重写shouldAutorotateToInterfaceOrientation方法。
但是iOS 6里屏幕旋转改变了很多,之前的 shouldAutorotateToInterfaceOrientation 被列为 DEPRECATED 方法,查看UIViewController.h文件也可以看到:
// Applications should use supportedInterfaceOrientations and/or shouldAutorotate..&
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation NS_DEPRECATED_IOS(2_0, 6_0);&
程序将使用如下2个方法来代替:
- (BOOL)shouldA&
- (NSUInteger)supportedInterfaceO&
除了重写这个2个方法,IOS6之后要旋转还有一些需要注意的地方,下面会细述。另外还有一个硬性条件,需要在Info.plist文件里面添加程序支持的所有方向,可以通过以下2种方式添加
另外要兼容IOS6之前的系统,要保留原来的 shouldAutorotateToInterfaceOrientation 方法,还有那些 willRotateToInterfaceOrientation 等方法。
自动旋转设置:
控制某个viewController旋转并不是像IOS5或者IOS4一样在这个viewController里面重写上面那2个方法,而是需要在这个viewController的rootViewController(根视图控制器)里面重写,怎么解释呢?就是最前面的那个viewController,直接跟self.window接触的那个controller,比如以下代码:
UIViewController *viewCtrl = [[UIViewController alloc] init];&
UINavigationController *navCtrl = [[UINavigationController alloc] initWithRootViewController:viewCtrl];&
if ([window respondsToSelector:@selector(setRootViewController:)]) {&
&&& self.window.rootViewController = navC&
&&& [self.window addSubview:navCtrl.view];&
如果需要设置viewCtrl的旋转,那么不能在UIViewController里面重写shouldAutorotate和supportedInterfaceOrientations方法,而是需要在navCtrl里面设置,又因为UINavigationController是系统控件,所以这里需要新建一个UINavigationController的子navigationController的子类,然后在里面实现shouldAutorotate和supportedInterfaceOrientations方法,比如:
-(NSUInteger)supportedInterfaceOrientations{&
&&& return UIInterfaceOrientationMaskAllButUpsideD&
- (BOOL)shouldAutorotate{&
&&& return YES;&
eg1:如果上面的例子是self.window.rootViewController = viewCtrl,而不是navCtrl,那么上面的那2个控制旋转的方法就应该写在UIViewController里面!
eg2:如果viewCtrl又pushViewController到viewCtrl2,需要设置viewCtrl2的旋转,怎么办呢? 还是在navCtrl里面控制,因为viewCtrl和viewCtrl2的rootViewController都是navCtrl,一般的写法都是
UIViewController *viewCtrl2 = [[UIVewController alloc] init];&
[self.navigationController.navigationController pushViewController:viewCtrl2 animated:YES];
所以要控制一个UINavigationController push到的所有viewController的旋转,那么就得在navCtrl里面区分是哪个viewController,以便对他们一一控制!同样如果rootViewController是UITabbarController,那么需要在子类化的UITabbarController里面重写那2个方法,然后分别控制!
但是有时候我初始化UINavigationController的时候,并不知道所有我所有需要push到的viewController,那么这里有一个通用的方法,就是让viewController自己来控制自己,首先在navCtrl里面的实现方法改为以下方式:
- (BOOL)shouldAutorotate&&&
&&& return self.topViewController.shouldA&&&
- (NSUInteger)supportedInterfaceOrientations&&&
&&& return self.topViewController.supportedInterfaceO&&&
全部调用self.topViewController,就是返回当前呈现出来的viewController里面的设置,然后在viewCtrl、viewCtrl2等等这些viewController里面重写shouldAutorotate和supportedInterfaceOrientations,以方便设置每个viewController的旋转
eg3:如果viewCtrl 是 presentModalViewController 到 viewCtrl3,那么viewCtrl3的旋转设置就不在navCtrl里面了!如果presentModalViewController的viewController是navController、tabbarController包装过的viewCtrl3,那么就应在新包装的navController、tabbarController里面设置,如果是直接presentModalViewController到viewCtrl3,那么就在viewCtrl3里面设置
手动旋转也有2种方式,一种是直接设置 UIDevice 的 orientation,但是这种方式不推荐,上传appStore有被拒的风险:
if ([[UIDevice currentDevice] respondsToSelector:@selector(setOrientation:)]) {&
&&& [[UIDevice currentDevice] performSelector:@selector(setOrientation:) withObject:(id)UIInterfaceOrientationPortrait];&
第二种是假旋转,并没有改变 UIDevice 的 orientation,而是改变某个view的 transform,利用 CGAffineTransformMakeRotation 来达到目的,比如:
self.view.transform = CGAffineTransformMakeRotation(M_PI/2)&
下面讲解采用第二种方式的各版本手动旋转:
思想是首先设置 statusBarOrientation,然后再改变某个view的方向跟 statusBarOrientation 一致!
那既然是旋转,最少也得有2个方向,那么还是少不了上面说的那个硬性条件,先在plist里面设置好所有可能需要旋转的方向。既然是手动旋转,那么就要关闭自动旋转:
- (BOOL)shouldAutorotate{&
&&&&&&& return NO;&
手动触发某个按钮,调用方法,这个方法的实现如下:
[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight];&
self.view.transform = CGAffineTransformMakeRotation(M_PI/2);&
self.view.bounds = CGRectMake(0, 0, kScreenHeight, 320);
1. 只需要改变self.view.transform,那么self.view的所有subview都会跟着自动变;其次因为方向变了,所以self.view的大小需要重新设置,不要使用self.view.frame,而是用bounds。
2. 如果shouldAutorotate 返回YES的话,下面设置setStatusBarOrientation 是不管用的!setStatusBarOrientation只有在shouldAutorotate 返回NO的情况下才管用!
强制旋转屏幕
最近接手了一个项目,正常情况下使用查看图片是没问题的。
用到了 MWPhotoBrowser 这个第三方图片浏览库。
不过发现了一个问题,就是设备横屏modal这MWPhotoBrowser的时候,发生了图片位置错乱。
实在没办法,所以想到了一个馊主意。
就是modal的时候使用代码把设备强制旋转回去。
//UIDevice+WJ.h
@interface UIDevice (WJ)
&*& 强制旋转设备
&*& @param& 旋转方向
+ (void)setOrientation:(UIInterfaceOrientation)
//UIDevice+WJ.m
#import "UIDevice+WJ.h"
@implementation UIDevice (WJ)
//调用私有方法实现
+ (void)setOrientation:(UIInterfaceOrientation)orientation {
&&& SEL selector = NSSelectorFromString(@"setOrientation:");
&&& NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[self instanceMethodSignatureForSelector:selector]];
&&& [invocation setSelector:selector];
&&& [invocation setTarget:[self currentDevice]];
&&& int val =
&&& [invocation setArgument:&val atIndex:2];
&&& [invocation invoke];
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具在 SegmentFault,解决技术问题
每个月,我们帮助 1000 万的开发者解决各种各样的技术问题。并助力他们在技术能力、职业生涯、影响力上获得提升。
一线的工程师、著名开源项目的作者们,都在这里:
获取验证码
已有账号?
问题对人有帮助,内容完整,我也想知道答案
问题没有实际价值,缺少关键内容,没有改进余地
在push出的viewcontroller里面 下面方法不会被执行
- (BOOL)shouldAutorotate
return YES;
- (NSUInteger)supportedInterfaceOrientations
return UIInterfaceOrientationMaskLandscapeL
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
return UIInterfaceOrientationLandscapeL
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
我之前是这么做的:
添加UITabBarController、UINavigationController的分类
UITabBarController (xxx)
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
return [self.selectedViewController preferredInterfaceOrientationForPresentation];
- (BOOL)shouldAutorotate
return [self.selectedViewController shouldAutorotate];
- (NSUInteger)supportedInterfaceOrientations
return [self.selectedViewController supportedInterfaceOrientations];
UINavigationController (xxx)
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
return [self.topViewController preferredInterfaceOrientationForPresentation];
- (BOOL)shouldAutorotate
return [self.topViewController shouldAutorotate];
- (NSUInteger)supportedInterfaceOrientations
return [self.topViewController supportedInterfaceOrientations];
分享到微博?
关闭理由:
删除理由:
忽略理由:
推广(招聘、广告、SEO 等)方面的内容
与已有问题重复(请编辑该提问指向已有相同问题)
答非所问,不符合答题要求
宜作评论而非答案
带有人身攻击、辱骂、仇恨等违反条款的内容
无法获得确切结果的问题
非开发直接相关的问题
非技术提问的讨论型问题
其他原因(请补充说明)
我要该,理由是:好多项目都同时用到了UITabBarController和UINavigationController,XCode可以直接创建这两个控制器中的其中一个,但是要一起用的话就得稍微麻烦点。
首先得搞清这两个控制器之间的层级关系,我们直接看官网给的图,如下所示:
从这张图可以看到:最右边的Assembled views是呈现给用户的界面,它左边的Window是最底层的窗口,重点来了,再往左,是Tab bar view,Tab bar view的上方是Navigation view,最后是用户定制的视图。
看完这个,代码就应该很好写了,我们需要把Navigation view加到 Tab bar view的内容上去,Tab bar view再加到Window上去。就是Window套UITabBarController,UITabBarController套UINavigationController, UINavigationController套UIViewController。
好了,接下来,我们开始实战。
1、新建Single View Application项目
为了更好的理解,我们直接新建Single View Application
2、删除ViewController.h等3个文件
删除如下图所示的3个文件:
ViewController.h、ViewController.m和Main.storyboard。
3、新建MainViewController
根据上面的层级关系图,我们需要把UITabBarController加到Window上去,所以在这里,我们直接新建MainViewController,让它继承UITabBarController,如下图所示:
点击Next,继承于UITabBarController,不用勾选Also Create XIB file,如下图:
4、修改AppDelegate.m文件
我们为了让MainViewController加到Window上去,修改AppDelegate.m文件,直接上代码,如下所示:
#import "AppDelegate.h"
#import "MainViewController.h"
@interface AppDelegate ()
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
MainViewController *mainVC = [[MainViewController alloc] init];
self.window.rootViewController = mainVC;
return YES;
5、新建两个标签页
新建FirstViewController和SecondViewController,继承于UIViewController,勾选Also create XIB file
FirstViewController:
SecondViewController:
创建好后,现在的文件目录结构是这样的
6、修改MainViewController.m
现在,我们需要把刚才创建的页面(First/Second ViewController)加入到导航控制器,再把导航控制器加到标签控制器上去。
直接上代码:
#import "MainViewController.h"
#import "FirstViewController.h"
#import "SecondViewController.h"
@interface MainViewController ()
@implementation MainViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self loadViewControllers];
- (void)loadViewControllers {
FirstViewController *firstVC = [[FirstViewController alloc] init];
UINavigationController *firstNC = [[UINavigationController alloc] initWithRootViewController:firstVC];
UITabBarItem *firstTabBarItem =[[UITabBarItem alloc] initWithTabBarSystemItem:UITabBarSystemItemBookmarks tag:0];
firstNC.tabBarItem = firstTabBarI
SecondViewController *secondVC = [[SecondViewController alloc] init];
UINavigationController *secondNC = [[UINavigationController alloc] initWithRootViewController:secondVC];
UITabBarItem *secondTabBarItem = [[UITabBarItem alloc] initWithTabBarSystemItem:UITabBarSystemItemContacts tag:1];
secondNC.tabBarItem = secondTabBarI
NSArray *controllersArray = @[firstNC, secondNC];
[self setViewControllers:controllersArray animated:YES];
直接看代码注释就可以大致了解流程:UIViewController加到UINavigationController上,UINavigationController加入UITabBarController,跟上面的层级关系图相符。
我们现在可以运行一下,会提示如下错误:
‘NSInvalidArgumentException’, reason: ‘Could not find a storyboard named ‘Main’ in bundle NSBundle
看这个提示,原来是我们步骤2中删除了Main.storyboard,但是程序设置的Main Interface默认是Main,这肯定会报错了。我们需要修改一下项目的配置,就暂且改成LaunchScreen吧,如下图:
我们再次运行一下,应该是没问题的,效果已经出来了,如下图:
我们把每页的title加一下,方便看效果:
FirstViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
self.title = @"main";
SecondViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
self.title = @"second";
再次运行,点击相应的标签图片,就可以看到效果了:
7、新建DetailsViewController
为了体现UINavigaitonController,我们需要再新建一个页面,然后在FirstViewController里增加一个按钮,点击按钮跳转到此页面,如下图:
文件新建好之后,我们给这个页面加上标题:
DetailsViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
self.title = @"details";
我们接下来在FirstViewController.xib里加一个按钮,然后连线到FirstViewController.m文件里实现点击事件,如下图:
FirstViewController.m里的点击事件代码:
- (IBAction)btnGoOnClick:(id)sender {
DetailsViewController *detailsVC = [[DetailsViewController alloc] init];
detailsVC.hidesBottomBarWhenPushed = YES;
[self.navigationController pushViewController:detailsVC animated:YES];
通过上面的代码,点击Go就可以跳转到DetailsViewController页面。
注意第四行,如果我们需要在进入Details页面之后隐藏底部的标签栏,可以在这里设置hidesBottomBarWhenPushed为YES。注意,在DetailsViewController.m文件中的viewDidLoad方法中调用是没效果的,在viewWillAppear里也不行,只有在init方法中调用才可以,如以下代码:
- (instancetype)init {
self.hidesBottomBarWhenPushed = YES;
return [super init];
再次运行,点击Go按钮,顺利跳转到了Details页面:
到此,就已经算是实现了TabBar和Navigation的整合使用。
顶部导航栏
我们可以美化一下顶部导航栏,比如更改背景、文字颜色,还有状态栏文字颜色等。
MainViewController.m文件中的loadViewControllers方法,在新建firstNC实例之后,加入:
[firstNC.navigationBar setBackgroundImage:[UIImage imageNamed:@"bg"] forBarMetrics:UIBarMetricsDefault];
[firstNC.navigationBar setBarStyle:UIBarStyleBlackTranslucent];
[firstNC.navigationBar setTintColor:[UIColor whiteColor]];
加入上述代码之后,再次运行,可以看到导航栏和状态栏的文字颜色已经更改
进入details页面
底部标签栏
当然,底部的标签栏也可以更改背景,在MainViewController.m的viewDidLoad方法中:
- (void)viewDidLoad {
[super viewDidLoad];
[self loadViewControllers];
[self.tabBar setBackgroundImage:[UIImage imageNamed:@"bg"]];
还可以自定义每个标签默认和选中的图片,拷入素材图片之后,
在MainViewControllers中,重新定义第一个标签栏Item:
UIImage *homeNormal = [UIImage imageNamed:@"home_normal"];
UITabBarItem *firstTabBarItem = [[UITabBarItem alloc] initWithTitle:@"Main" image:homeNormal tag:0];
最终效果,如下图:
最后,附上代码下载地址:
本文已收录于以下专栏:
相关文章推荐
简单介绍ios开发中常用的选项卡控制器UITabBarController以及其代理UITabBarControllerDelegate
文章目的如何用纯代码的方式创建UITabBarController方法1. 首先开启XCode并建立一个Empty Application2. 加入一个Objective-C Class并继承自UIV...
两种常见的UITabBarController+UINavigationController模式
一. UITabBarController简介
(一). 继承关系
UITabBarController和UINavigationController类似,也继承于UIViewContr...
首先开始项目之前我们需要搭建框架,首选UITabBarController +UINavigationController,下面的代码是整理好的,包括我们会遇到的问题解决方法都在里面
自定义UINav...
来源:http://hecc-/blog/984235
在广大的Java界,关于WeakHashMap一直都存在这么个传说:
在WeakHa...
导航控制器nav,nav的根控制器vc1; 下一个控制器leftVC;按钮在vc1 的导航上(场景:在vc1中点击按钮,push 到leftVC)
    设置下一个控制器的tabBar隐藏,要在p...
在Xcode5上做以上的操作没有问题,这次是要在Xcode6上实现之,特记录以备用.
首先新建一个storyboard文件.取名Custom.storyboard.拖动菜单添加一个TabBarCom...
UINavigationController是IOS编程中比较常用的一种容器view controller,很多系统的控件以及很多有名的APP中(如qq,系统相册等)都有用到。
        nav...
1、UINavigationController导航控制器如何使用UINavigationController可以翻译为导航控制器,在iOS里经常用到。我们看看它的如何使用:下面的图显示了导航控制器的...
他的最新文章
讲师:姜飞俊
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)UITabBarController、UINavigationController使用
一、UITabBarController
例如:手机内闹钟底部的tabbarController的实现。
1、在AppDelegate中 实例一个:
@property(nonatomic, strong)UITabBarController
*tabBarViewC
(BOOL)application:(UIApplication
*)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
& // Override point for
customization after application launch.
&&_tabBarViewController =
[[UITabBarController alloc]init];
&&UINavigationController *nav =
[[UINavigationController
alloc]initWithRootViewController:_tabBarViewController];
& self.window.rootViewController
&&FirstViewController *first =
[[FirstViewController alloc]init];
& SecondViewController *second =
[[SecondViewController alloc]init];
& ThirdViewController *third =
[[ThirdViewController alloc]init];
& _tabBarViewController.viewControllers = [NSArray arrayWithObjects:first,second,third, nil];
& UITabBar
*tabBar = _tabBarViewController.tabBar;
& UITabBarItem
*firstItem = [tabBar.items objectAtIndex:0];
& UITabBarItem
*secondItem = [tabBar.items objectAtIndex:1];
& UITabBarItem
*thirdItem = [tabBar.items objectAtIndex:2];
& firstItem.title
= @"first";
& secondItem.title
= @"second";
& thirdItem.title
= @"third";
3、理清关系:
UITabBar、UITabBarButton、UITabBarItem
&UITabBar&是一个控件,代表的是UITabBarController的底部的选项卡条。
&UITabBarButton是UITabBar底部的每一个标签,每一个UITabBarButton里面显示什么内容,取决于UITabBarItem,UITabBarButton本身是私有的,无法获取到。底部选项卡为什么能够显示图片和文字,完全就是因为它。它的数据来自于UITabBarItem。
&&UITabBarItem&是一个
获得方式:&
&self.tabBarItem // self是指控制器
作用:可以用来设置当前控制器对应的选项卡标签的内容;
标签的标题
self.tabBarItem.title
标签的图标
self.tabBarItem.image
标签的选中图标
self.tabBarItem.selectdImage
&总结一句话:
&UITabBarButton你获取不到,暂且可以不理它。为底部每个选项卡设置内容的时候,
self.tabBarItem.title/image/selecImage =
二、UINavigationController
1、首先理清关系:
UINavigationBar、UINavigationItem、UIBarButtoItem
UINavigationBar是一个控件,
表示UINavigationController(导航控制器)顶部那个玩意儿,UINavigationBar上面显示什么内容,完全由UINavigationItem属性决定。
&UINavigationItem是一个模型(不是控件),它可以设置UINavigationBar中间那部分的内容;
获得方式:
self.navigationItem // self是指控制器
为UINavigationBar设置导航栏内容的方式:
设置导航栏中间的内容
self.navigationItem.title
self.navigationItem.titleView
UINavigationBar是view,UINavitgationItem是由self.navigationItem(UINavigationItem)给UINavigationBar提供内容数据。
UIBarButtonItem
是一个数据类型,我们在设置导航控制器内容的时候,左右两边同样需要设置,他们分别是:
设置导航栏左上角的内容
self.navigationItem.leftBarButtonItem
设置导航栏右上角的内容
self.navigationItem.rightBarButtonItem
总结一点:
设置导航控制器中间内容的就用:
&self.navigationItem.title/tileView =
&左右两边内容就用:&
self.navigation.leftBarButtonItem/rightBarButtonItem =
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。UITabBarController 与 UINavigationController - 简书
UITabBarController 与 UINavigationController
关于 UITabBarController 和 UINavigationController 怎么用,我在这里并不探讨这个,今天在这里说的是,当这两个东西碰到一起时,有时会有一些令人无法捉摸的细节上的问题,下面进入正题:1.以 UINavigationController 为整个应用的根控制器,UITabBarController 又为 navigationController 的 rootViewController 时,以往设置 navigationController 的 navigationItem.title 属性的方式就不适用了,比如 self.title = @"",又或者self.navigationItem.title = @"323423";都无法成功的设置导航栏的标题.这是因为你当前所处的控制器并不是 navigationController (而是 UITabBarController)的子控制器,所以 self.navigationItem 并不能获取到 navigationController 的 navigationItem 属性,既然当前控制器处于 UITabBarController 下面,设置头部导航栏标题就应该是self.tabBarController.navigationItem.title = @"你的标题".同理,设置其他的导航栏的属性也应该在前面加上 self.tabBarController.
不想成为架构师的程序员不是好程序员

我要回帖

更多关于 android 横屏时崩溃 的文章

 

随机推荐