美文网首页
屏幕旋转及ipad分屏情形下的适配

屏幕旋转及ipad分屏情形下的适配

作者: 啧啧同学 | 来源:发表于2018-12-29 19:28 被阅读0次

屏幕旋转及ipad的分屏操作均会引起页面size的变化,此时会自动触发一些系统的方法:

  • viewWillLayoutSubviews()
  • viewDidLayoutSubviews()
  • viewWillTransitionToSize()
  • viewWillTransition(to:with:)

这里主要用到的是viewWillTransition(to:with:)
苹果官文https://developer.apple.com/documentation/uikit/uicontentcontainer/1621466-viewwilltransitiontosize?language=occ对该函数的解释很清楚:

UIKit calls this method before changing the size of a presented view controller’s view. You can override this method in your own objects and use it to perform additional tasks related to the size change. For example, a container view controller might use this method to override the traits of its embedded child view controllers. Use the provided coordinator object to animate any changes you make.
If you override this method in your custom view controllers, always call super at some point in your implementation so that UIKit can forward the size change message appropriately. View controllers forward the size change message to their views and child view controllers. Presentation controllers forward the size change to their presented view controller.

Parameters

size:
The new size for the container’s view.
coordinator:
The transition coordinator object managing the size change. You can use this object to animate your changes or get information about the transition that is in progress.


开始动手

首先为基类设置个约束条件(Protocol)

protocol ZWScreenTransitionProtocol: class {
    
    /*
     旋转或分屏情形下导致页面的Size变化后通过此代理方法来更新Controller subViews的布局
     由于ipad不同方向且多任务分屏的存在,控件大小的布局尽量不要通过设置高度和宽度,尽量以左右、上下的相对位置来确定
     size : CGSize 屏幕变化后的size
     xScale : CGFloat 水平方向上的等比变化
     xScale : CGFloat 数值方向上的等比变化
     */
    func screenFrameTransitionTo(_ size: CGSize, xScale: CGFloat, yScale: CGFloat)
}

基类Controller中默认实现改协议,由子类来实现具体的适配

class ZWBaseViewController: UIViewController, ZWScreenTransitionProtocol {

    func screenFrameTransitionTo(_ size: CGSize, xScale: CGFloat, yScale: CGFloat) {
        //override by sub Class
    }
}

基类Controller的extension中实现viewWillTransition(to:with:)方法(这里用extension主要是为了代码结构美观,没别的)

extension ZWBaseViewController {


    override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {

        //查看旋转的方向,刘海屏会用到(safeArea布局)
        let orient = UIDevice.current.orientation
        
        //屏幕改变后的Size
        let newWidth: CGFloat = size.width
        let newHeight: CGFloat = size.height

        //屏幕改变前的Size
        let oldWidth: CGFloat = self.view.frame.size.width
        let oldHeight: CGFloat = self.view.frame.size.height

        let xScale: CGFloat = newWidth / oldWidth
        let yScale: CGFloat = newHeight / oldHeight
        
        switch orient {
        case .unknown:
            
            currentOrient = .portrait
        case .portrait:
            
            currentOrient = .portrait
            
        case .portraitUpsideDown:

            currentOrient = .portraitUpsideDown
            RLog.info("portraitUpsideDown")
        case .landscapeLeft:

            currentOrient = .landscapeLeft
            RLog.info("landscapeLeft")
        case .landscapeRight:
 
            currentOrient = .landscapeRight
            RLog.info("landscapeRight")
        case .faceUp:
            
            RLog.info("faceUp")
        case .faceDown:
            
            RLog.info("faceDown")
        }
        //触发protocol方法
        screenFrameTransitionTo(size, xScale: xScale, yScale: yScale)
    }    
}

//Demo

class DemoController: ZWBaseViewController {
      
    override func viewDidLoad() {
        super.viewDidLoad()
        title = "Main"
        
        setupSubViews()
    }
    
    func setupSubViews() {
        
        view.addSubview(tipLabel)
        view.addSubview(printLabel)
        view.addSubview(pushBtn)
        view.addSubview(textField0)
        view.addSubview(textField1)
        
        layoutSubViews()
    }

    func layoutSubViews() {
    
        screenFrameTransitionTo(self.view.frame.size, xScale: 1.0, yScale: 1.0)
    }

    //MARK: Property
    lazy var tipLabel: UILabel = {
        let label = UILabel()
        label.textColor = .blue
        label.textAlignment = .center
        label.font = .systemFont(ofSize: 20.0)
        label.text = "测试基类backHandler"
        
        return label
    }()
    
    lazy var printLabel: UILabel = {
        let label = UILabel()
        label.textColor = .blue
        label.textAlignment = .center
        label.font = .systemFont(ofSize: 14.0)
        
        return label
    }()
    
    lazy var pushBtn: UIButton = {
     
        let btn = UIButton()
        btn.setTitle("push", for: .normal)
        btn.setTitle("push", for: .highlighted)
        btn.setTitleColor(.white, for: .normal)
        btn.setTitleColor(.white, for: .highlighted)
        btn.backgroundColor = .red
        btn.addTarget(self, action: #selector(pushToMainPage), for: .touchUpInside)
        return btn
    }()
    
    lazy var textField0: UITextField = {
        //没有左右布局,但是有宽度
        let tf = UITextField()
        tf.placeholder = "i am place holder"
        tf.textColor = .black
        tf.textAlignment = .left
        tf.font = .systemFont(ofSize: 30.0)
        tf.layer.borderColor = UIColor.blue.cgColor
        tf.layer.borderWidth = 1.0
        
        return tf
    }()
    
    lazy var textField1: UITextField = {
        
        //有左右布局
        let tf = UITextField()
        tf.placeholder = "i am place holder"
        tf.textColor = .black
        tf.textAlignment = .left
        tf.font = .systemFont(ofSize: 30.0)
        tf.layer.borderColor = UIColor.blue.cgColor
        tf.layer.borderWidth = 1.0
        
        return tf
    }()
}

//MARK: YFLayoutOrientProtocol
extension DemoController {

    override func screenFrameTransitionTo(_ size: CGSize, xScale: CGFloat, yScale: CGFloat) {

        tipLabel.snp.remakeConstraints { (make) in

            //multipliedBy 不生效  -_-!!!??
            // make.left.equalToSuperview().offset(20.0).multipliedBy(xScale)
            make.left.equalToSuperview().offset(20.0 * xScale)
            make.top.equalToSuperview().offset(120.0 * yScale)
        }
        
        printLabel.snp.remakeConstraints { (make) in
            make.left.equalToSuperview().offset(20.0 * xScale)
            make.top.equalTo(tipLabel.snp.bottom).offset(20.0 * yScale)
        }
        
        pushBtn.snp.remakeConstraints { (make) in
            make.top.equalTo(printLabel.snp.bottom).offset(80 * yScale)
            make.left.equalToSuperview().offset(20.0 * xScale)
            make.size.equalTo(CGSize(width: 160.0, height: 24.0))
        }
        
        textField0.snp.remakeConstraints { (make) in
            make.left.equalToSuperview().offset(20.0 * xScale)
            make.top.equalTo(tipLabel.snp.bottom).offset(180.0 * yScale)
            make.size.equalTo(CGSize(width: 300.0 * xScale, height: 100.0 * yScale))
        }
        
        
        textField1.snp.remakeConstraints { (make) in
            make.left.equalToSuperview().offset(20.0 * xScale)
            make.top.equalTo(tipLabel.snp.bottom).offset(340.0 * yScale)
            make.right.equalToSuperview().offset(-30.0 * xScale)
            make.height.equalTo(200.0 * yScale)
        }
    }
}

rotation.gif

垂直

相关文章

网友评论

      本文标题:屏幕旋转及ipad分屏情形下的适配

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