Search code examples
iosuiviewtransformationobjective-c-category

Most elegant way to rotate a UILabel; maintain bottom left corner


Say you want text standing upwards. Of course, it's easy to rotate it 90degrees:

someUIView.transform = CGAffineTransformMakeRotation(- 90.0f * M_PI / 180.0f);

But typically, you want it to MAINTAIN THE BOTTOM LEFT CORNER

So, in storyboard IB you position the (horizontal) text where you want the bottom left corner to be, and you expect that when the app is running, and the text is vertical, that is where the "new" bottom left corner of the vertical text will be.

enter image description here

Here's a category on UIView...

-(void)standOnBottomLeftCorner
    {
    CGPoint org = self.frame.origin;
    org.y += self.frame.size.height;
    self.transform = CGAffineTransformMakeRotation(- 90.0f * M_PI / 180.0f);
    CGRect nu = self.frame;
    nu.origin = org;
    nu.origin.y -= nu.size.height; 
    self.frame = nu;
    }

However, note:

JRT explains: "You shouldn't set the frame on a transformed view, it's undefined behaviour."

Unless I'm drunk, that works ......... but what's the best way?


This illustrations show's Matic's very clever idea:

enter image description here


Solution

  • Changing the layer's anchor point will alter the point that transforms work around.

    In your case, you'd want to set the anchor point to halfway down the label and half of the height in from the left hand side, as pointed out by Matic:

    CGRect frame = self.frame;
    self.layer.anchorPoint = CGPointMake((frame.size.height / frame.size.width * 0.5),0.5); // Anchor points are in unit space
    self.frame = frame; // Moving the anchor point moves the layer's position, this is a simple way to re-set
    CGAffineTransform rotate = CGAffineTransformMakeRotation(- 90.0f * M_PI / 180.0f); // Performs the rotation
    self.transform = rotate;
    

    Done. You shouldn't set the frame on a transformed view, it's undefined behaviour.