Choppy全屏退出过渡

时间:2017-09-07 01:49:29

标签: ios swift animation viewcontroller

我有一个自定义视图控制器,可以通过按钮全屏显示。它通常是视图的子视图(嵌入式)。我从嵌入中输入全屏是:

private func enterFullScreenFromEmbed() {

    self.proxyView = UIView(frame: self.view.frame)
    self.proxyView?.isHidden = true
    self.proxyView?.autoresizingMask = self.view.autoresizingMask
    self.view.superview?.addSubview(self.proxyView!)

    // Now set the frame to the screen frame
    let frame = self.view.window?.convert(self.view.frame, from: self.proxyView?.superview)
    self.view.window?.addSubview(self.view)
    self.view.frame = frame!

    self.isFullscreen = true

    UIView.animate(withDuration: 0.25) { 
        self.view.frame = self.view.window!.bounds
        self.view.layoutIfNeeded()
        self.setNeedsStatusBarAppearanceUpdate()
    }
}

退出全屏:

private func exitFullScreenToEmbed() {

    let frame = self.view.window?.convert(self.view.frame, to: self.proxyView?.superview)
    self.proxyView?.superview?.addSubview(self.view)
    self.view.frame = frame!

    self.isFullscreen = false

    UIView.animate(withDuration: 0.25, animations: {

        self.view.frame = self.proxyView!.frame

        self.view.layoutIfNeeded()
        self.setNeedsStatusBarAppearanceUpdate()
    }) { (_) in
        self.proxyView?.removeFromSuperview()
        self.proxyView = nil
    }
}

这很好,除了我在输入全屏动画中隐藏状态栏,并在退出全屏动画中显示它。这会导致我的顶视图跳回原位,无需动画。

注意,isFullscreen变量隐藏了状态栏。

override var prefersStatusBarHidden: Bool {
    return isFullscreen
}

override var preferredStatusBarUpdateAnimation: UIStatusBarAnimation {
    return .slide
}

以下是动画的GIF动词:

Horizonal

Vertical

注意景观的顶部和景观的底部(在景观中更容易看到)。在顶部,玩家框架立即设置为旧位置,并将所有内容向下移动20px(或状态栏的高度)

它与隐藏状态栏有关。有没有人有解决方案?

1 个答案:

答案 0 :(得分:0)

我明白了。它是一种hacky并没有经过全面测试,但这是我提出的解决方案。

首先,获取一个变量来保存状态栏高度(不是0)。

var statusBarHeight: CGFloat = UIApplication.shared.statusBarFrame.height != 0 ? UIApplication.shared.statusBarFrame.height : 20.0

然后,设置状态栏框架更改的通知。

NotificationCenter.default.addObserver(self, selector: #selector(SKPlayerViewController.updateLocalStatusBarFrameHeight), name: .UIApplicationDidChangeStatusBarFrame, object: nil)

现在,在方法中,仅在高度不为0时才更新变量。我们保存高度,因为状态栏可能不是20(如果在通话中等)。

@objc private func updateLocalStatusBarFrameHeight() {
        let height = UIApplication.shared.statusBarFrame.height
        if height > 0 {
            self.statusBarHeight = height
        }
    }

现在,我更新了我的exitFullScreenToEmbed(),只有在没有横向的情况下(因为状态栏隐藏在横向中),才会减去statusBarHeight的计算帧原点。

private func exitFullScreenToEmbed() {

    var frame = self.view.window?.convert(self.view.frame, to: self.proxyView?.superview)
    self.proxyView?.superview?.addSubview(self.view)

    if !(UIApplication.shared.statusBarOrientation == .landscapeRight || UIApplication.shared.statusBarOrientation == .landscapeLeft) {
        frame?.origin.y -= self.statusBarHeight
    }

    self.view.frame = frame!

    self.isFullscreen = false

    UIView.animate(withDuration: 0.25, animations: {

        self.view.frame = self.proxyView!.frame

        self.view.layoutIfNeeded()
        self.setNeedsStatusBarAppearanceUpdate()
    }) { (_) in
        self.proxyView?.removeFromSuperview()
        self.proxyView = nil
    }
}

如果这对任何人都有帮助,那么欢迎你。我只是在这里分享一些知识:)