简体   繁体   中英

Exclude UIView from animating on autorotation

TL;DR

Need to keep autorotation, but exclude one UIView from autorotating on orientation change, how?

Back story

I need to keep a UIView stationary during the animation accompanied by autorotation (which happens on orientation change). Similar to how the iOS camera app handles the rotation (ie controls rotate in their place).

Things I've tried

  • Returning false from shouldAutorotate() , subscribing to UIDeviceOrientationDidChangeNotification , and trying to manually handle the rotation event for each view separately.

    Works well if you don't need to change any of your UIViews' places, otherwise it's a pain figuring out where it should end up and how to get it there

  • Placing a non rotating UIWindow under the main UIWindow, and setting the main UIWindow background colour to clear.

    This works well if it's only one item, but I don't want to manage a bunch of UIWindows

  • Inverse rotation Ie rotating the UIView in the opposite direction to the rotation. Not reliable, and looks weird, it's also vertigo inducing

  • Overriding the animation in the viewWillTransitionToSize method. Failed

  • And a bunch of other things that would be difficult to list here, but they all failed .

Question

Can this be done? if so, how?

I'm supporting iOS8+


Update This is how the views should layout/orient given @Casey's example :

在此输入图像描述

I have faced with same problem and found example from Apple, which helps to prevent UIView from rotation: https://developer.apple.com/library/ios/qa/qa1890/_index.html

However, if UIView is not placed in the center of the screen, you should handle new position manually.

i think part of the reason this is so hard to answer is because in practice it doesn't really make sense.

say i make a view that uses autolayout to look like this in portrait and landscape:

标准布局

if you wanted to prevent c from rotating like you are asking, what would you expect the final view to look like? would it be one of these 3 options?

不稳定的布局

without graphics of the portrait/landscape view you are trying to achieve and a description of the animation you are hoping for it'll be very hard to answer your question.

are you using NSLayoutConstraint , storyboard or frame based math to layout your views? any code you can provide would be great too

If you're wanting to have the same effect as the camera app, use size classes (see here and here ).

If not, what is wrong with creating a UIWindow containing a view controller that doesn't rotate? The following code seems to work for me (where the UILabel represents the view you don't want to rotate).

class ViewController: UIViewController {
    var staticWindow: UIWindow!

    override func viewDidLoad() {
        super.viewDidLoad()
        showWindow()
    }

    func showWindow() {
        let frame = CGRect(x: 10, y: 10, width: 100, height: 100)
        let vc = MyViewController()
        let label = UILabel(frame: frame)
        label.text = "Hi there"
        vc.view.addSubview(label)
        staticWindow = UIWindow(frame: frame)
        staticWindow.rootViewController = MyViewController()
        staticWindow.windowLevel = UIWindowLevelAlert + 1;
        staticWindow.makeKeyAndVisible()
        staticWindow.rootViewController?.presentViewController(vc, animated: false, completion: nil)
    }
}

class MyViewController: UIViewController {
    override func shouldAutorotate() -> Bool {
        return false
    }

    override func shouldAutomaticallyForwardRotationMethods() -> Bool {
        return false
    }

    override func shouldAutomaticallyForwardAppearanceMethods() -> Bool {
        return false
    }

    override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
        return UIInterfaceOrientationMask.Portrait
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM