美文网首页
横竖屏问题

横竖屏问题

作者: 守护地中海的花 | 来源:发表于2019-11-13 13:44 被阅读0次

这是一个老生常谈的问题啦。开始吧。

Controller里面控制横竖屏切换

在定义控制器种可以自行控制

UITabBarController.m
#pragma mark - 状态栏style
- (UIStatusBarStyle)preferredStatusBarStyle
{
    return self.selectedViewController.preferredStatusBarStyle;
}
#pragma mark - 屏幕旋转
- (BOOL)shouldAutorotate
{
    return [self.selectedViewController shouldAutorotate];
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientations
{
    return [self.selectedViewController supportedInterfaceOrientations];
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
    return [self.selectedViewController preferredInterfaceOrientationForPresentation];
}

UINavigationController.m
#pragma mark - 状态栏style
- (UIStatusBarStyle)preferredStatusBarStyle
{
    return self.topViewController.preferredStatusBarStyle;
}
#pragma mark - 屏幕旋转
- (BOOL)shouldAutorotate
{
    //return [self.viewControllers.lastObject shouldAutorotate];
    return [self.topViewController shouldAutorotate];
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientations
{
    return [self.topViewController supportedInterfaceOrientations];
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
    return [self.topViewController preferredInterfaceOrientationForPresentation];
}
UIViewController.m
#pragma mark - 状态栏style
- (UIStatusBarStyle)preferredStatusBarStyle
{
    /**
     UIStatusBarStyleDefault                                  = 0, // Automatically chooses light or dark content based on the user interface style
     UIStatusBarStyleLightContent     API_AVAILABLE(ios(7.0)) = 1, // Light content, for use on dark backgrounds
     UIStatusBarStyleDarkContent     API_AVAILABLE(ios(13.0)) = 3, // Dark content, for use on light backgrounds
     
     UIStatusBarStyleBlackTranslucent NS_ENUM_DEPRECATED_IOS(2_0, 7_0, "Use UIStatusBarStyleLightContent") = 1,
     UIStatusBarStyleBlackOpaque
     */
    //UIStatusBarStyleDefault、UIStatusBarStyleLightContent UIStatusBarStyleBlackTranslucent UIStatusBarStyleBlackOpaque 白色
    //UIStatusBarStyleDarkContent
    //12.100000 13.000000
    if (@available(iOS 13.0, *)) {
        return 3;
    } else {
        return UIStatusBarStyleDefault;
    }
//    if (iOS13) {
//        return UIStatusBarStyleDarkContent;
//    } else {
//        return UIStatusBarStyleDefault;
//    }
}
#pragma mark - 屏幕旋转
- (BOOL)shouldAutorotate
{
    return NO;
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskPortrait;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
    return UIInterfaceOrientationPortrait;
}

判断控制器种横竖屏的通知

备注:

  • 有iOS8之前 和之后的 如果新的方法实现了, 旧的方法会被覆盖(不会执行)
  • 不能以[UIScreen mainScreen].bounds.size.width判断 因为切换有延迟等会讲
- (void)viewDidLoad {
    [super viewDidLoad];
    //iOS8之后的方法 保证首次加载屏幕正确
    [self viewWillTransitionToSize:[UIScreen mainScreen].bounds.size withTransitionCoordinator:self.transitionCoordinator];
}

- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
{
    //有延迟
    if (size.width > size.height) {
        NSLog(@"横屏");
        //切换viewframe
    } else {
        NSLog(@"竖屏");
        //切换viewframe
    }
}


iOS之前的方法
[self willRotateToInterfaceOrientation:self.interfaceOrientation duration:0];

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
    //Landscape: 横屏
    if (UIInterfaceOrientationIsLandscape(toInterfaceOrientation)) {
        // 更改dockView的宽度和高度
        self.dockView.width = 200;
        self.dockView.height = 768;
        
    } else if (UIInterfaceOrientationIsPortrait(toInterfaceOrientation)) {
        //Portrait: 竖屏
        
        // 更改dockView的宽度和高度
        self.dockView.width = 50;
        self.dockView.height = 1024;

    }
}

子视图的切换问题

  • 自定义BView 创建在控制器中
1.自定义BView
- (void)setFrame:(CGRect)frame
{
    [super setFrame:frame];
    NSLog(@"子视图:frame:%f,%f",WIDTH,HEIGHT);
}
- (void)layoutSubviews
{
    [super layoutSubviews];
    NSLog(@"子视图:layoutSubviews:%f,%f",WIDTH,HEIGHT);
}


BView *view = [[BView alloc]init];
view.frame = CGRectMake(0, 0, WIDTH - 20, 20);
view.backgroundColor = [UIColor purpleColor];
[self.view addSubview:view];
self.bView = view;

  • 首先对viewWillTransitionToSize方法进行分析看看
- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
{
    //有延迟
    if (size.width > size.height) {
        
        NSLog(@"横屏:bounds.size.width:%f,HEIGHT:%f,size.width:%f,size.height:%f",[UIScreen mainScreen].bounds.size.width,HEIGHT,size.width,size.height);
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.01 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            NSLog(@"0.01s后横屏:WIDTH:%f,HEIGHT:%f,size.width:%f,size.height:%f",WIDTH,HEIGHT,size.width,size.height);
        });
        self.bView.frame = CGRectMake(0, 0, 20, HEIGHT - 20);
        dispatch_async(dispatch_get_global_queue(0, 0), ^{
            //必须放到并行队列里面 不然串行队列执行f完 才切换横屏
            //执行到 26 差不多横竖屏就切换了
            for (NSInteger index = 0; index < 100; index ++) {
                //NSLog(@"%ld:%f",index,WIDTH);
            }
        });
    } else {
        NSLog(@"竖屏:WIDTH:%f,HEIGHT:%f,size.width:%f,size.height:%f",WIDTH,HEIGHT,size.width,size.height);
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.01 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            NSLog(@"0.01s后竖屏:WIDTH:%f,HEIGHT:%f,size.width:%f,size.height:%f",WIDTH,HEIGHT,size.width,size.height);
        });
        self.bView.frame = CGRectMake(0, 0, WIDTH - 20, 20);
    }
}

切换横屏后打印

LoginPageVC.m--44--->:横屏:bounds.size.width:375.000000,HEIGHT:667.000000,size.width:667.000000,size.height:375.000000
BView.m--15--->:子视图:frame:375.000000,667.000000
BView.m--20--->:子视图:layoutSubviews:667.000000,375.000000
BView.m--20--->:子视图:layoutSubviews:667.000000,375.000000
LoginPageVC.m--46--->:0.01s后横屏:WIDTH:667.000000,HEIGHT:375.000000,size.width:667.000000,size.height:375.000000

切换竖屏

LoginPageVC.m--57--->:竖屏:WIDTH:667.000000,HEIGHT:375.000000,size.width:375.000000,size.height:667.000000
BView.m--15--->:子视图:frame:667.000000,375.000000
BView.m--20--->:子视图:layoutSubviews:375.000000,667.000000
BView.m--20--->:子视图:layoutSubviews:375.000000,667.000000
LoginPageVC.m--59--->:0.01s后竖屏:WIDTH:375.000000,HEIGHT:667.000000,size.width:375.000000,size.height:667.000000

总结(如从竖到横屏 ipad同样问题):

  • 瞬间切换也不能利用bounds.size.widthWIDTH正常思维来布局 因为这个时候WIDTH还是375(短)并不是667
  • 在通知里面 只有改变自定义viewframe 然后触发自定义viewlayoutSubviews方法 这个时候 在layoutSubviews方法里面横竖屏已经切换了
  • 所以对通知里面的自定义view 用代理方法里面的size
    改进如下
- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
{
    //有延迟
    if (size.width > size.height) {
        self.bView.frame = CGRectMake(0, 0, 20, size.height - 20);
    } else {
        self.bView.frame = CGRectMake(0, 0, size.width - 20, 20);
    }
}

通知UIDeviceOrientationDidChangeNotification

可以用于控制器和自定义View里面参考之前一些视频播放器旋转demo

  • 注册通知来接受屏幕旋转的通知
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(statusBarOrientationChange:) name:UIDeviceOrientationDidChangeNotification object:[UIDevice currentDevice]];
  • 通知
#pragma mark - 屏幕旋转通知
- (void)statusBarOrientationChange:(NSNotification *)notification
{
    UIDeviceOrientation orientation = [UIDevice currentDevice].orientation;
    if (orientation == UIDeviceOrientationLandscapeLeft) {
        NSLog(@"左");
        [[UIDevice currentDevice]setValue:[NSNumber numberWithInteger:UIDeviceOrientationLandscapeLeft] forKey:@"orientation"];
        //自定义view里面所需???不知道为什么要写
        //[self updateConstraintsIfNeeded];
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.01 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            NSLog(@"0.01s后:%f,%f",WIDTH,HEIGHT);
        });
    } else if (orientation == UIDeviceOrientationLandscapeRight) {
        NSLog(@"右");
    } else if (orientation == UIDeviceOrientationPortrait) {
        NSLog(@"竖屏");
    }
}
  • kvc方法直接改变屏幕旋转用于按钮点击选择
    点击完成后 屏幕直接旋转
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    [[UIDevice currentDevice]setValue:[NSNumber numberWithInteger:UIDeviceOrientationLandscapeLeft] forKey:@"orientation"];
}

相关文章

网友评论

      本文标题:横竖屏问题

      本文链接:https://www.haomeiwen.com/subject/rwuhictx.html