Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are rotated Views compatible with Auto Layout?

I have learned how to rotate a view with Affine Transforms (see here). I have also learned about Auto Layout (see here and here), and even programmatic Auto Layout (see here and here). However, I don't know how to get Auto Layout to work with a rotated view.

This image shows what I would like to do:

enter image description here

I think the trouble comes from the width and the height changing because of the rotation. Is there any way to make a rotated view fill it's superview? Is there some trick to get Auto Layout to work or is it just incompatible after a rotation?

(I've only learned Swift, but I'd be glad to wade through Objective-C answers if that is what you are more familiar with.)

Update

Following @VinayJain's suggestion I did the following:

  • pinned the subview edges to the superview in the storyboard.
  • created IBOutlets for the spacing constraints on all sides of the subview.

    @IBOutlet weak var rightSpace: NSLayoutConstraint!
    @IBOutlet weak var leftSpace: NSLayoutConstraint!
    @IBOutlet weak var topSpace: NSLayoutConstraint!
    @IBOutlet weak var bottomSpace: NSLayoutConstraint!
    
  • rotated the subview

    subview.transform = CGAffineTransformMakeRotation(CGFloat(M_PI_2))
    
  • changed the constraints from the outlets

    self.rightSpace.constant = CGFloat(0)
    self.leftSpace.constant = CGFloat(0)
    self.topSpace.constant = CGFloat(0)
    self.bottomSpace.constant = CGFloat(0)
    

But it was at this point that I realized that I don't really need to change the spacing value. I want the spacing to remain 0. I just need it to adjust itself. However, the rotation messes that up. The effect is shown in the following image:

enter image description here

like image 950
Suragch Avatar asked Jun 15 '15 08:06

Suragch


2 Answers

After setting up my UI with auto layout, I created a label, rotated it then set the bounds to a view that was already laid out.

let lbl = UILabel()
    lbl.text = Constants.UI.FlightRequest.flightRequest
    lbl.textColor = .white
    lbl.font = UIFont.systemFont(ofSize: 12)
    lbl.rotation = -90
    lbl.textAlignment = .center
    lbl.frame = blueSideBar.bounds //<--- here is where I set the frame
    blueSideBar.addSubview(lbl)

var rotation: Int {
    get {
        return 0
    } set {
        let radians = ((CGFloat.pi) * CGFloat(newValue) / CGFloat(180.0))
        self.transform = CGAffineTransform(rotationAngle: radians)
    }
}
like image 129
devjme Avatar answered Oct 13 '22 10:10

devjme


I came across this problem when trying to run external video over HDMI / AirPlay from iOS to a rotated TV screen.

Sometimes, the TV will have a setting to "rotate" the signal 90-degrees or 180-degrees, etc. but often times it will not have that option.

With a "wrapper" view like this, I am able to force the view controller on the external screen to rotate its contents without the contents actually being aware that anything is different.

let contentsView = SomeWildCustomViewUsingAutoLayoutEtc()
let wrapper = RotatingWrapperView(contentsView)
wrapper.translatesAutoresizingMaskIntoConstraints = false
parentView.addSubview(wrapper)
// ...
wrapper.rotation = .upsideDown

Source for RotatingWrapperView: https://github.com/quantcon/UIKit/blob/master/AutoLayoutRotationDemo/Views/RotatingWrapperView.swift

like image 33
snakeoil Avatar answered Oct 13 '22 09:10

snakeoil