gpt4 book ai didi

ios - UIViewControllerAnimatedTransitioning : Black screen fragments after rotation change

转载 作者:搜寻专家 更新时间:2023-11-01 07:27:31 25 4
gpt4 key购买 nike

我已经创建了一个 Viewcontrollertransition,只要我不改变设备方向,一切都正常。

图 1 显示了应有的屏幕。然后我切换到下一个更改方向的 View Controller 。现在我回到第一个 viewcontroller 并再次切换方向。然后我得到了图像 2 中可见的结果。出现黑色边框。请不要介意屏幕中央的白框。

下面是我的动画代码。你能看出哪里出了问题吗?

import Foundation

import UIKit

class ZoomOutCircleViewTransition: NSObject, UIViewControllerAnimatedTransitioning, UIViewControllerTransitioningDelegate {

var hideDelayed = false
var transitionContext: UIViewControllerContextTransitioning?

init(hideDelayed : Bool = true) {
self.hideDelayed = hideDelayed
super.init()
}


func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval {
return 0.6
}

func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
self.transitionContext = transitionContext

guard let toViewController: UIViewController = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey) else {
return
}

guard let fromViewController = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey) else {
return
}

guard let toViewTransitionFromView = toViewController as? TransitionFromViewProtocol else {
return
}

let containerView = transitionContext.containerView()

let imageViewSnapshot = toViewTransitionFromView.getViewForTransition()
imageViewSnapshot.alpha = 0.0
let imageViewSnapshotOriginalFrame = imageViewSnapshot.frame

let startFrame = CGRectMake(-CGRectGetWidth(toViewController.view.frame)/2, -CGRectGetHeight(toViewController.view.frame)/2, CGRectGetWidth(toViewController.view.frame)*2, CGRectGetHeight(toViewController.view.frame)*2)

let quadraticStartFrame = CGRect(x: startFrame.origin.x - (startFrame.height - startFrame.width)/2, y: startFrame.origin.y, width: startFrame.height, height: startFrame.height)

containerView!.insertSubview(toViewController.view, atIndex: 0)
containerView!.addSubview(imageViewSnapshot)


// UIViewController circle shrink animation
let bigCirclePath = UIBezierPath(ovalInRect: quadraticStartFrame)

let smallCirclePath = UIBezierPath(ovalInRect: imageViewSnapshot.frame)
let maskLayer = CAShapeLayer()
maskLayer.frame = toViewController.view.frame
maskLayer.path = bigCirclePath.CGPath//maskPath.CGPath
fromViewController.view.layer.mask = maskLayer

let pathAnimation = CABasicAnimation(keyPath: "path")
pathAnimation.delegate = self
pathAnimation.fromValue = bigCirclePath.CGPath
pathAnimation.toValue = smallCirclePath.CGPath
pathAnimation.duration = transitionDuration(transitionContext)
maskLayer.path = smallCirclePath.CGPath
maskLayer.addAnimation(pathAnimation, forKey: "pathAnimation")

// pathAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)

imageViewSnapshot.frame = quadraticStartFrame

// Make imageView visible with animation
let showImageViewAnimation = {
imageViewSnapshot.alpha = 1.0
}
let showImageViewDelay = 0.3
UIView.animateWithDuration(transitionDuration(transitionContext) - showImageViewDelay , delay: showImageViewDelay, options: UIViewAnimationOptions.CurveLinear, animations: showImageViewAnimation) { (completed) -> Void in
}

// Shrink the imageView to the original size
let scaleImageViewAnimation = {
imageViewSnapshot.frame = imageViewSnapshotOriginalFrame
}
UIView.animateWithDuration(transitionDuration(transitionContext), delay: 0.0, options: UIViewAnimationOptions.CurveLinear, animations: scaleImageViewAnimation) { (completed) -> Void in
// After the complete animations have endet

// Hide ImageView after it is completely resized. Added some animation delay to not abruptly change the contactImage
if self.hideDelayed {
let hideImageViewAnimation = {
imageViewSnapshot.alpha = 0.0
}
UIView.animateWithDuration(0.2 , delay: 0.2, options: UIViewAnimationOptions.CurveLinear, animations: hideImageViewAnimation) { (completed) -> Void in
imageViewSnapshot.removeFromSuperview()
}
}
else {
imageViewSnapshot.removeFromSuperview()
}
}
}

override func animationDidStop(anim: CAAnimation, finished flag: Bool) {
if let transitionContext = self.transitionContext {
transitionContext.completeTransition(!transitionContext.transitionWasCancelled())
}
}

// MARK: UIViewControllerTransitioningDelegate protocol methods

// return the animataor when presenting a viewcontroller
func animationControllerForPresentedController(presented: UIViewController, presentingController presenting: UIViewController, sourceController source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return self
}

// return the animator used when dismissing from a viewcontroller
func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return self
}

}

最佳答案

您需要将新框架设置为 toViewController.view。这会将 View 更新为当前方向。

toViewController.view.frame = fromViewController.view.frame

使用我更新的代码:

class ZoomOutCircleViewTransition: NSObject, UIViewControllerAnimatedTransitioning, UIViewControllerTransitioningDelegate {

var hideDelayed = false
var transitionContext: UIViewControllerContextTransitioning?

init(hideDelayed : Bool = true) {
self.hideDelayed = hideDelayed
super.init()
}


func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval {
return 0.6
}

func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
self.transitionContext = transitionContext

guard let toViewController: UIViewController = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey) else {
return
}

guard let fromViewController = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey) else {
return
}

guard let toViewTransitionFromView = toViewController as? TransitionFromViewProtocol else {
return
}

toViewController.view.frame = fromViewController.view.frame

let containerView = transitionContext.containerView()

let imageViewSnapshot = toViewTransitionFromView.getViewForTransition()
imageViewSnapshot.alpha = 0.0
let imageViewSnapshotOriginalFrame = imageViewSnapshot.frame

let startFrame = CGRectMake(-CGRectGetWidth(fromViewController.view.frame)/2, -CGRectGetHeight(fromViewController.view.frame)/2, CGRectGetWidth(toViewController.view.frame)*2, CGRectGetHeight(toViewController.view.frame)*2)

let quadraticStartFrame = CGRect(x: startFrame.origin.x - (startFrame.height - startFrame.width)/2, y: startFrame.origin.y, width: startFrame.height, height: startFrame.height)

containerView!.insertSubview(toViewController.view, atIndex: 0)
containerView!.addSubview(imageViewSnapshot)


// UIViewController circle shrink animation
let bigCirclePath = UIBezierPath(ovalInRect: quadraticStartFrame)

let smallCirclePath = UIBezierPath(ovalInRect: imageViewSnapshot.frame)
let maskLayer = CAShapeLayer()
maskLayer.frame = toViewController.view.frame
maskLayer.path = bigCirclePath.CGPath//maskPath.CGPath
fromViewController.view.layer.mask = maskLayer

let pathAnimation = CABasicAnimation(keyPath: "path")
pathAnimation.delegate = self
pathAnimation.fromValue = bigCirclePath.CGPath
pathAnimation.toValue = smallCirclePath.CGPath
pathAnimation.duration = transitionDuration(transitionContext)
maskLayer.path = smallCirclePath.CGPath
maskLayer.addAnimation(pathAnimation, forKey: "pathAnimation")

// pathAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)

imageViewSnapshot.frame = quadraticStartFrame

// Make imageView visible with animation
let showImageViewAnimation = {
imageViewSnapshot.alpha = 1.0
}
let showImageViewDelay = 0.3
UIView.animateWithDuration(transitionDuration(transitionContext) - showImageViewDelay , delay: showImageViewDelay, options: UIViewAnimationOptions.CurveLinear, animations: showImageViewAnimation) { (completed) -> Void in
}

// Shrink the imageView to the original size
let scaleImageViewAnimation = {
imageViewSnapshot.frame = imageViewSnapshotOriginalFrame
}
UIView.animateWithDuration(transitionDuration(transitionContext), delay: 0.0, options: UIViewAnimationOptions.CurveLinear, animations: scaleImageViewAnimation) { (completed) -> Void in
// After the complete animations have endet

// Hide ImageView after it is completely resized. Added some animation delay to not abruptly change the contactImage
if self.hideDelayed {
let hideImageViewAnimation = {
imageViewSnapshot.alpha = 0.0
}
UIView.animateWithDuration(0.2 , delay: 0.2, options: UIViewAnimationOptions.CurveLinear, animations: hideImageViewAnimation) { (completed) -> Void in
imageViewSnapshot.removeFromSuperview()
}
}
else {
imageViewSnapshot.removeFromSuperview()
}
toViewController.view.layer.mask = nil
}
}

override func animationDidStop(anim: CAAnimation, finished flag: Bool) {
if let transitionContext = self.transitionContext {
transitionContext.completeTransition(!transitionContext.transitionWasCancelled())
}
}

// MARK: UIViewControllerTransitioningDelegate protocol methods

// return the animataor when presenting a viewcontroller
func animationControllerForPresentedController(presented: UIViewController, presentingController presenting: UIViewController, sourceController source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return self
}

// return the animator used when dismissing from a viewcontroller
func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return self
}

}

class ZoomOutCircleViewTransition: NSObject, UIViewControllerAnimatedTransitioning, UIViewControllerTransitioningDelegate {

var hideDelayed = false
var transitionContext: UIViewControllerContextTransitioning?

init(hideDelayed : Bool = true) {
self.hideDelayed = hideDelayed
super.init()
}


func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval {
return 0.6
}

func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
self.transitionContext = transitionContext

guard let toViewController: UIViewController = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey) else {
return
}

guard let fromViewController = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey) else {
return
}

guard let toViewTransitionFromView = toViewController as? TransitionFromViewProtocol else {
return
}

toViewController.view.frame = fromViewController.view.frame

let containerView = transitionContext.containerView()

let imageViewSnapshot = toViewTransitionFromView.getViewForTransition()
imageViewSnapshot.alpha = 0.0
let imageViewSnapshotOriginalFrame = imageViewSnapshot.frame

let startFrame = CGRectMake(-CGRectGetWidth(fromViewController.view.frame)/2, -CGRectGetHeight(fromViewController.view.frame)/2, CGRectGetWidth(toViewController.view.frame)*2, CGRectGetHeight(toViewController.view.frame)*2)

let quadraticStartFrame = CGRect(x: startFrame.origin.x - (startFrame.height - startFrame.width)/2, y: startFrame.origin.y, width: startFrame.height, height: startFrame.height)

containerView!.insertSubview(toViewController.view, atIndex: 0)
containerView!.addSubview(imageViewSnapshot)


// UIViewController circle shrink animation
let bigCirclePath = UIBezierPath(ovalInRect: quadraticStartFrame)

let smallCirclePath = UIBezierPath(ovalInRect: imageViewSnapshot.frame)
let maskLayer = CAShapeLayer()
maskLayer.frame = toViewController.view.frame
maskLayer.path = bigCirclePath.CGPath//maskPath.CGPath
fromViewController.view.layer.mask = maskLayer

let pathAnimation = CABasicAnimation(keyPath: "path")
pathAnimation.delegate = self
pathAnimation.fromValue = bigCirclePath.CGPath
pathAnimation.toValue = smallCirclePath.CGPath
pathAnimation.duration = transitionDuration(transitionContext)
maskLayer.path = smallCirclePath.CGPath
maskLayer.addAnimation(pathAnimation, forKey: "pathAnimation")

// pathAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)

imageViewSnapshot.frame = quadraticStartFrame

// Make imageView visible with animation
let showImageViewAnimation = {
imageViewSnapshot.alpha = 1.0
}
let showImageViewDelay = 0.3
UIView.animateWithDuration(transitionDuration(transitionContext) - showImageViewDelay , delay: showImageViewDelay, options: UIViewAnimationOptions.CurveLinear, animations: showImageViewAnimation) { (completed) -> Void in
}

// Shrink the imageView to the original size
let scaleImageViewAnimation = {
imageViewSnapshot.frame = imageViewSnapshotOriginalFrame
}
UIView.animateWithDuration(transitionDuration(transitionContext), delay: 0.0, options: UIViewAnimationOptions.CurveLinear, animations: scaleImageViewAnimation) { (completed) -> Void in
// After the complete animations have endet

// Hide ImageView after it is completely resized. Added some animation delay to not abruptly change the contactImage
if self.hideDelayed {
let hideImageViewAnimation = {
imageViewSnapshot.alpha = 0.0
}
UIView.animateWithDuration(0.2 , delay: 0.2, options: UIViewAnimationOptions.CurveLinear, animations: hideImageViewAnimation) { (completed) -> Void in
imageViewSnapshot.removeFromSuperview()
}
}
else {
imageViewSnapshot.removeFromSuperview()
}
toViewController.view.layer.mask = nil
}
}

override func animationDidStop(anim: CAAnimation, finished flag: Bool) {
if let transitionContext = self.transitionContext {
transitionContext.completeTransition(!transitionContext.transitionWasCancelled())
}
}

// MARK: UIViewControllerTransitioningDelegate protocol methods

// return the animataor when presenting a viewcontroller
func animationControllerForPresentedController(presented: UIViewController, presentingController presenting: UIViewController, sourceController source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return self
}

// return the animator used when dismissing from a viewcontroller
func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return self
}
}

关于ios - UIViewControllerAnimatedTransitioning : Black screen fragments after rotation change,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34993774/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com