Rotating a view in layoutSubviews
The problem with the code in the question seems to be that the transformations keep getting added to each other. In order to fix this, the solution is to reset the transformations every time, that is, set it to the identity transform.
rotationView.transform = CGAffineTransformIdentity
Here is a partial implementation that shows the key parts.
import UIKit
@IBDesignable class UIVerticalTextView: UIView {
var textView = UITextView()
let rotationView = UIView()
var underlyingTextView: UITextView {
get {
return textView
}
set {
textView = newValue
}
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override init(frame: CGRect){
super.init(frame: frame)
self.setup()
}
override func awakeFromNib() {
super.awakeFromNib()
self.setup()
}
func setup() {
rotationView.backgroundColor = UIColor.redColor()
textView.backgroundColor = UIColor.yellowColor()
self.addSubview(rotationView)
rotationView.addSubview(textView)
// could also do this with auto layout constraints
textView.frame = rotationView.bounds
}
override func layoutSubviews() {
super.layoutSubviews()
rotationView.transform = CGAffineTransformIdentity // *** key line ***
rotationView.frame = CGRect(origin: CGPointZero, size: CGSize(width: self.bounds.height, height: self.bounds.width))
rotationView.transform = translateRotateFlip()
}
func translateRotateFlip() -> CGAffineTransform {
var transform = CGAffineTransformIdentity
// translate to new center
transform = CGAffineTransformTranslate(transform, (self.bounds.width / 2)-(self.bounds.height / 2), (self.bounds.height / 2)-(self.bounds.width / 2))
// rotate counterclockwise around center
transform = CGAffineTransformRotate(transform, CGFloat(-M_PI_2))
// flip vertically
transform = CGAffineTransformScale(transform, -1, 1)
return transform
}
}
My most recent implementation is most likely to be found in this github link.
How to layout subviews on device rotation in iOS 10
Add and use didRotateFromInterfaceOrientation
orientation delegate method.
To layout subviews use autoresizingMask
property of UIView
,
Like,
YourView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
From the UIView documentation:
When a view’s bounds change, that view automatically resizes its
subviews according to each subview’s autoresizing mask.
Changing autoresizingMask
to other than None
will trigger layoutSubviews
.
So, you can use below code to layout subviews using didRotateFromInterfaceOrientation
delegate method.
-(void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
[self.view layoutIfNeeded];
[self.view setNeedsLayout];
self.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
//....Other code
}
-(void)layoutSubviews{
//write your code to draw here
}
layoutSubviews called twice when rotating
I had the same question. I found this page to be helpful for me. Is this useful for you?
EDIT:
Here is the summary of the page (copied):
- init does not cause layoutSubviews to be called (duh)
- addSubview causes layoutSubviews to be called on the view being added, the view it’s being added to (target view), and all the subviews of the target view
- setFrame intelligently calls layoutSubviews on the view having it’s frame set only if the size parameter of the frame is different
- scrolling a UIScrollView causes layoutSubviews to be called on the scrollView, and it’s superview
- rotating a device only calls layoutSubview on the parent view (the responding viewControllers primary view)
- removeFromSuperview – layoutSubviews is called on superview only (not show in table)
viewDidLayoutSubviews in Autolayout with rotation on UIPageViewController
From two of the answers, it looks like viewDidLayoutSubviews maybe the
wrong place to layout the views. I'm trying to find where this should
be done and have the view's know their bounds and orientation but
before they are visible on the screen.
I would subclass UIScrollView
and override there layoutSubviews
, which will be called for you by the system only when needed and when all the variables (orientation, size, etc.) have the proper values.
Custom UIView layoutSubviews with orientation and animations?
I have recently started overriding viewDidLayoutSubviews
(many times instead of viewWillAppear
) in my UIViewControllers
.
Yes viewDidLayoutSubviews
is called on rotations. (from comment)
The method fires after all the internal layouts have already been completed so all finalized frames should be setup, but still give you the time you need to make adjustments before the the view is visible and shouldn't have any issues with animations because you are not already inside an animation block.
viewcontroller.m
- (void)viewDidLayoutSubViews {
// At this point I know if an animation is appropriate or not.
if (self.shouldRunAnimation)
[self.fuView runPrettyAnimations];
}
fuView.m
- (void)runPrettyAnimations {
// My animation blocks for whatever layout I'd like.
}
- (void)layoutSubviews {
// My animations are not here, but non animated layout changes are.
// - Here we have no idea if our view is visible to the user or may appear/disappear
// partway through an animation.
// - This also might get called far more than we intend since it gets called on
// any frame updates.
}
Related Topics
How to Prevent iOS 13 Dark Mode from Breaking Emails
Uitableviewcells with Uibutton Overlaps While Scrolling
Didreceiveremotenotification: Fetchcompletionhandler: Open from Icon VS Push Notification
Swift: How to Get Substring from Start to Last Index of Character
Missing Push Notification Entitlement Warning
Modal Segue, Navigation Bar Disappears
How to Add Uipickerview into Uialertcontroller (Alert or Actionsheet) in Swift
Ios5 Images Disappear When Scrolling with Webkit-Overflow-Scrolling: Touch
iOS Wifi Scan, Signal Strength
Input Field iOS Safari Bug - Can't Type in Any Text
Coca Pod Chart Not Appearing (Swift4)
Is There a Public Way to Force Mpnowplayinginfocenter to Show Podcast Controls
Xcode 6 with Swift Super Slow Typing and Autocompletion
How to Set Imageview in Circle Like Imagecontacts in Swift Correctly
How to Use Autolayout to Provide Different Constraints for Landscape and Portrait Orientations
Showing the File Download Progress with Nsurlsessiondatatask