问题
I am getting issues in autorotation of a UIView which is nothing but a red line of width 4 and height half of superview's height in landscape mode, and in portrait mode the height is 4 points and width is half of superview width. You can see the issue in the gif. As I rotate from landscape to portrait, the effect of autorotation is not smooth and with distortions.
Here is the code. What am I doing wrong?
private var myView:UIView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
myView = UIView(frame: CGRect(x: 0, y: 0, width: self.view.bounds.width/2, height: 4))
myView.backgroundColor = UIColor.red
view.addSubview(myView)
myView.center = CGPoint(x: view.bounds.width/2, y: view.bounds.height/2)
}
private func layoutMyView() {
let orientation = UIApplication.shared.statusBarOrientation
if orientation == .landscapeLeft || orientation == .landscapeRight {
myView.frame = CGRect(x: 0, y: 0, width: view.bounds.width/2, height: 4)
} else {
myView.frame = CGRect(x: 0, y: 0, width: 4, height: view.bounds.height/2)
}
myView.center = CGPoint(x: view.bounds.width/2, y: view.bounds.height/2)
}
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
let orientation = UIApplication.shared.statusBarOrientation
NSLog("View will transition to \(size), \(orientation.rawValue)")
if size.width < size.height {
NSLog("Portrait mode")
} else {
NSLog("Landscape mode")
}
super.viewWillTransition(to: size, with: coordinator)
coordinator.animate(alongsideTransition: { [unowned self] (_) in
let orient = UIApplication.shared.statusBarOrientation
self.layoutMyView()
}, completion: { [unowned self] (UIViewControllerTransitionCoordinatorContext) -> Void in
let orient = UIApplication.shared.statusBarOrientation
self.layoutMyView()
NSLog("rotation completed to \(orient.rawValue), \(self.myView.frame)")
})
}
回答1:
There are a few potential options:
In
animate(alongsideTransition:completion:), do a keyframe animation to set mid animation point so you don’t end up with that curious boxy feel mid animation. E.g. this shrink it down to a 4x4 boxoverride func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { super.viewWillTransition(to: size, with: coordinator) let origin = CGPoint(x: (view.bounds.midX + view.bounds.midY) / 2 - 2, y: (view.bounds.midX + view.bounds.midY) / 2 - 2) coordinator.animate(alongsideTransition: { _ in UIView.animateKeyframes(withDuration: coordinator.transitionDuration, delay: 0, animations: { UIView.addKeyframe(withRelativeStartTime: 0, relativeDuration: 0.5) { self.myView.frame = CGRect(origin: origin, size: CGSize(width: 4, height: 4)) } UIView.addKeyframe(withRelativeStartTime: 0.5, relativeDuration: 0.5) { self.layoutMyView() } }) }) }There are many possible variations on this theme. This still animates the view, but gives it a more “deliberate” sort of vibe and doesn’t lose the “line” feel of it.
Rather than rendering a “line” with
UIView, use CAShapeLayer and update its path.You could run a CADisplayLink while transition is in progress, and then update the frame to whatever you want as the animation progresses.
Instead of animating the
frame, you could animate thetransformof this view, possibly rotating it in the opposite direction that the view is rotating.
来源:https://stackoverflow.com/questions/54389933/uiview-autorotation-issue