在iOS 8中处理方向更改的"正确"方法是什么?

 KLD受害者 发布于 2022-12-19 14:49

有人可以告诉我在iOS 8中使用纵向和横向界面方向的"正确"或"最佳"方法吗?似乎我想要用于此目的的所有功能都在iOS 8中被弃用,而我的研究似乎没有明确,优雅的替代方案.我真的应该看看宽度和高度,以确定我们是在纵向还是横向模式?

例如,在我的视图控制器中,我应该如何实现以下伪代码?

if we are rotating from portrait to landscape then
  do portrait things
else if we are rotating from landscape to portrait then
  do landscape things

smileyborg.. 254

Apple建议使用大小类作为可用屏幕空间大小的粗略度量,以便UI可以显着改变其布局和外观.考虑到纵向的iPad具有与横向相同的尺寸等级(常规宽度,常规高度).这意味着您的UI在两个方向之间应该或多或少相似.

但是,iPad中从纵向到横向的变化非常重要,即使尺寸类没有改变,您也可能需要对UI进行一些较小的调整.由于UIViewController不推荐使用与接口方向相关的方法,Apple现在建议在UIViewController替换时实现以下新方法:

- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id )coordinator
{
    [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];

    // Code here will execute before the rotation begins.
    // Equivalent to placing it in the deprecated method -[willRotateToInterfaceOrientation:duration:]

    [coordinator animateAlongsideTransition:^(id context) {

        // Place code here to perform animations during the rotation.
        // You can pass nil or leave this block empty if not necessary.

    } completion:^(id context) {

        // Code here will execute after the rotation has finished.
        // Equivalent to placing it in the deprecated method -[didRotateFromInterfaceOrientation:]

    }];
}

大!现在你在旋转开始之前以及完成之后得到回调.但实际上知道旋转是纵向还是横向呢?

Apple建议将旋转视为父视图大小的变化.换句话说,在iPad从纵向旋转到横向旋转期间,您可以将其视为根级视图,只需将其bounds.size从更改{768, 1024}{1024, 768}.知道了这一点,你应该使用size传递给viewWillTransitionToSize:withTransitionCoordinator:上面的方法来确定你是否正在旋转到纵向或横向.

如果您想要一种更加无缝的方式将遗留代码迁移到新的iOS 8工作方式,请考虑在UIView上使用这个简单类别,它可用于确定视图是基于其的"纵向"还是"横向"尺寸.

回顾一下:

    您应该使用大小类来确定何时显示根本不同的UI(例如"类似iPhone的"UI与"类似iPad"的UI)

    如果在大小类更改但容器(父视图)大小发生变化时(例如iPad旋转时)需要对UI进行较小的调整,请使用viewWillTransitionToSize:withTransitionCoordinator:UIViewController中的回调.

    应用程序中的每个视图都应该仅根据布局给出的空间做出布局决策.让视图的自然层次结构将此信息向下级联.

    同样,不要使用statusBarOrientation- 这基本上是设备级属性 - 来确定是否为"肖像"与"横向"布局视图.状态栏方向只应由处理UIWindow实际位于应用程序根本级别的事务的代码使用.

很好的答案!顺便说一句,你在AL上的YouTube视频非常有用.Thanx分享.看看这个!https://www.youtube.com/watch?v=taWaW2GzfCI (5认同)


CMont.. 16

基于smileyborg非常详细(和接受)的答案,这是使用swift 3的改编:

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
    super.viewWillTransition(to: size, with: coordinator)
    coordinator.animate(alongsideTransition: nil, completion: {
        _ in
        self.collectionView.collectionViewLayout.invalidateLayout()
    })        
}

并在UICollectionViewDelegateFlowLayout实施中,

public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    // retrieve the updated bounds
    let itemWidth = collectionView.bounds.width
    let itemHeight = collectionView.bounds.height
    // do whatever you need to do to adapt to the new size
}


inVINCEable.. 11

我只是使用通知中心:

添加一个方向变量(将在最后解释)

//Above viewdidload
var orientations:UIInterfaceOrientation = UIApplication.sharedApplication().statusBarOrientation

视图出现时添加通知

override func viewDidAppear(animated: Bool) {
    NSNotificationCenter.defaultCenter().addObserver(self, selector: "orientationChanged:", name: UIDeviceOrientationDidChangeNotification, object: nil)
}

视图消失后删除通知

override func viewWillDisappear(animated: Bool) {
        NSNotificationCenter.defaultCenter().removeObserver(self, name: UIDeviceOrientationDidChangeNotification, object: nil) 
}

触发通知时获取当前方向

func orientationChanged (notification: NSNotification) {
    adjustViewsForOrientation(UIApplication.sharedApplication().statusBarOrientation)
}

检查方向(纵向/横向)并处理事件

func adjustViewsForOrientation(orientation: UIInterfaceOrientation) {
    if (orientation == UIInterfaceOrientation.Portrait || orientation == UIInterfaceOrientation.PortraitUpsideDown)
    {
        if(orientation != orientations) {
            println("Portrait")
            //Do Rotation stuff here
            orientations = orientation
        }
    }
    else if (orientation == UIInterfaceOrientation.LandscapeLeft || orientation == UIInterfaceOrientation.LandscapeRight)
    {
       if(orientation != orientations) {
            println("Landscape")
            //Do Rotation stuff here
            orientations = orientation
        }
    }
}

我添加方向变量的原因是因为在物理设备上进行测试时,方向通知会在设备中的每次轻微移动时调用,而不是在旋转时调用.添加var和if语句只会在切换到相反方向时调用代码.

3 个回答
  • Apple建议使用大小类作为可用屏幕空间大小的粗略度量,以便UI可以显着改变其布局和外观.考虑到纵向的iPad具有与横向相同的尺寸等级(常规宽度,常规高度).这意味着您的UI在两个方向之间应该或多或少相似.

    但是,iPad中从纵向到横向的变化非常重要,即使尺寸类没有改变,您也可能需要对UI进行一些较小的调整.由于UIViewController不推荐使用与接口方向相关的方法,Apple现在建议在UIViewController替换时实现以下新方法:

    - (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id <UIViewControllerTransitionCoordinator>)coordinator
    {
        [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
    
        // Code here will execute before the rotation begins.
        // Equivalent to placing it in the deprecated method -[willRotateToInterfaceOrientation:duration:]
    
        [coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context) {
    
            // Place code here to perform animations during the rotation.
            // You can pass nil or leave this block empty if not necessary.
    
        } completion:^(id<UIViewControllerTransitionCoordinatorContext> context) {
    
            // Code here will execute after the rotation has finished.
            // Equivalent to placing it in the deprecated method -[didRotateFromInterfaceOrientation:]
    
        }];
    }
    

    大!现在你在旋转开始之前以及完成之后得到回调.但实际上知道旋转是纵向还是横向呢?

    Apple建议将旋转视为父视图大小的变化.换句话说,在iPad从纵向旋转到横向旋转期间,您可以将其视为根级视图,只需将其bounds.size从更改{768, 1024}{1024, 768}.知道了这一点,你应该使用size传递给viewWillTransitionToSize:withTransitionCoordinator:上面的方法来确定你是否正在旋转到纵向或横向.

    如果您想要一种更加无缝的方式将遗留代码迁移到新的iOS 8工作方式,请考虑在UIView上使用这个简单类别,它可用于确定视图是基于其的"纵向"还是"横向"尺寸.

    回顾一下:

      您应该使用大小类来确定何时显示根本不同的UI(例如"类似iPhone的"UI与"类似iPad"的UI)

      如果在大小类更改但容器(父视图)大小发生变化时(例如iPad旋转时)需要对UI进行较小的调整,请使用viewWillTransitionToSize:withTransitionCoordinator:UIViewController中的回调.

      应用程序中的每个视图都应该仅根据布局给出的空间做出布局决策.让视图的自然层次结构将此信息向下级联.

      同样,不要使用statusBarOrientation- 这基本上是设备级属性 - 来确定是否为"肖像"与"横向"布局视图.状态栏方向只应由处理UIWindow实际位于应用程序根本级别的事务的代码使用.

    2022-12-19 14:51 回答
  • 我只是使用通知中心:

    添加一个方向变量(将在最后解释)

    //Above viewdidload
    var orientations:UIInterfaceOrientation = UIApplication.sharedApplication().statusBarOrientation
    

    视图出现时添加通知

    override func viewDidAppear(animated: Bool) {
        NSNotificationCenter.defaultCenter().addObserver(self, selector: "orientationChanged:", name: UIDeviceOrientationDidChangeNotification, object: nil)
    }
    

    视图消失后删除通知

    override func viewWillDisappear(animated: Bool) {
            NSNotificationCenter.defaultCenter().removeObserver(self, name: UIDeviceOrientationDidChangeNotification, object: nil) 
    }
    

    触发通知时获取当前方向

    func orientationChanged (notification: NSNotification) {
        adjustViewsForOrientation(UIApplication.sharedApplication().statusBarOrientation)
    }
    

    检查方向(纵向/横向)并处理事件

    func adjustViewsForOrientation(orientation: UIInterfaceOrientation) {
        if (orientation == UIInterfaceOrientation.Portrait || orientation == UIInterfaceOrientation.PortraitUpsideDown)
        {
            if(orientation != orientations) {
                println("Portrait")
                //Do Rotation stuff here
                orientations = orientation
            }
        }
        else if (orientation == UIInterfaceOrientation.LandscapeLeft || orientation == UIInterfaceOrientation.LandscapeRight)
        {
           if(orientation != orientations) {
                println("Landscape")
                //Do Rotation stuff here
                orientations = orientation
            }
        }
    }
    

    我添加方向变量的原因是因为在物理设备上进行测试时,方向通知会在设备中的每次轻微移动时调用,而不是在旋转时调用.添加var和if语句只会在切换到相反方向时调用代码.

    2022-12-19 14:52 回答
  • 基于smileyborg非常详细(和接受)的答案,这是使用swift 3的改编:

    override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
        super.viewWillTransition(to: size, with: coordinator)
        coordinator.animate(alongsideTransition: nil, completion: {
            _ in
            self.collectionView.collectionViewLayout.invalidateLayout()
        })        
    }
    

    并在UICollectionViewDelegateFlowLayout实施中,

    public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        // retrieve the updated bounds
        let itemWidth = collectionView.bounds.width
        let itemHeight = collectionView.bounds.height
        // do whatever you need to do to adapt to the new size
    }
    

    2022-12-19 14:52 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有