katzenhut katzenhut - 1 month ago 13
Objective-C Question

UIButtons titleLabel clips Text after being rotated by CGAffineTransformMakeRotate()

I am developing a iOS-6 app. I have a UIViewController with a view that needs fixed orientation (portrait mode). But when the phone is rotated, one control on that view needs to be moved and rotated (so that it will always be in the upper left corner, and its text will be readable). I am achieving this by shifting the control(a UIView) using the frame-property of my control (it is a custom view, more on that later), and then using CGAffineTRansformMakeRotate() afterwards, since i know that its not advisable to use the frame after rotating a view. everything is fine so far, but here's the thing: That custom view has three UIButtons of type UIButtonTypeCustom as its subviews. Because i rotated the View, but cannot rotate the buttons inside the view (they are not squares), i need to rotate the titleLabels of the Buttons for the text to be readable in the new deviceOrientation. But it wont work very well. The text will be rotated, as i intended, but it will be clipped by the titleLabel, because the titleLabel has the wrong frame. i checked this by applying borders to the label. So i need to change the titleLabels frame, right? But how can i do that? I tried setting it using

[titleLabel setFrame: frameThatFits];
, but to no avail. (frameThatFits is a CGRect i created). also,, calling
[button.titleLabel sizeToFit];
has no effect that i could see.
I am using
[button setTitle:title forControlState: UIControlStateNormal];
to set the title.

TL;DR: Im trying to change the frame/bounds of a UIButtons titleLabel after rotating it using an affine transformation. Any help?
Thanks.

PS: I can supply code when needed, but i wouldnt know what to show you. Tell me what you need, ill post it.

Answer

OK, first of all, thanks to everyone who tried to help. Im posting an alternative solution for my problem, and although it doesnt really address the problem of changing the titleLabels dimensions, it will result in the proper display of my ViewController. It turns out using the frame is a bad idea. I initially used the frame to reposition the view and i figured that this couldnt be a problem because i only ever applied transformations afterwards, but i was wrong. Because OBVIOUSLY i tried to change the titleLabels frame. AFTER the rotation. And that didnt work. So the way to go here is using the center-property and the bouds of the view consistently throughout the code. It will result in properly rotated Buttons, that do not need any fidgeting afterwards. My takeaway here is that i will never ever again use the frame-property outside of a NSLog-statement. But why [button sizeToFit];wouldnt yield any results is still beyond me. If i ever figure it out, i might post it if i remember.

EDIT: @ZevEisenberg nailed it with this comment: “Warning: If the transform property is not the identity transform, the value of this property is undefined and therefore should be ignored.” So you are right to use the center and bounds here, but if you do not have a transform, the frame is perfectly safe to use.

NEXT EDIT: Heres how i ended up repositioning the Buttons:

-(CGPoint)centerForView:(UIView *)view{
    //calculate a suitableposition for the view
    //depending on the current orientation and the device type (iphone 4S/5, etc)
    return point;
}

Then, as a reaction to the deviceOrientation change notification, i apply CGAffineTransformIdentity to all the views, reposition them using my centerForView shown above, and apply the correct rotation transformation to the View. I do this for all the subviews every time the divice rotates, like so:

-(void)setRightRotationTransformations{
[self resetAllTransformations];
self.someSubview.transform = CGAffineTransformRotate(self.someSubview.transform, -M_PI_2);
}