0

I want to resize my label from center and animate that process. However, the only option I can use there is CGAffineTransformMakeScale with default anchor point of corresponding CALayer.

[UIView animateWithDuration:0.5 animations:^{
    self.title.transform = CGAffineTransformMakeScale(2.0,1.0);
}];

But it squished the text inside. I considered this answer and it looks like the problem is solved in Swift.

However, I can't modify only size part of the frame. How to approach this in Obj C?

Community
  • 1
  • 1
efimovdk
  • 368
  • 4
  • 16

4 Answers4

1

This will work for you. You just need to give scale for width and height (default 1, which will have no effect). And this will animate your view's frame and set it back to the original.

[UIView animateWithDuration:0.5
                  delay:0
                options:UIViewAnimationOptionBeginFromCurrentState
             animations:(void (^)(void)) ^{
                 self.textLabel.transform=CGAffineTransformMakeScale(3, 1);
             }
             completion:^(BOOL finished){
                 self.textLabel.transform=CGAffineTransformIdentity;
             }];

If you dont want revert effect than you can do like this

[UIView animateWithDuration:0.5
                  delay:0
                options:UIViewAnimationOptionBeginFromCurrentState
             animations:(void (^)(void)) ^{
                 self.textLabel.transform=CGAffineTransformMakeScale(3, 1);
             }
             completion:nil];
Milan Manwar
  • 374
  • 3
  • 10
  • How is that different from the code in the question? – efimovdk Mar 29 '16 at 14:05
  • @efimovD you didn't provide option for UIViewAnimationOptionBeginFromCurrentState, and the answer provides that option. This is the difference. If you want to try it then you can, because when i wrote answer for swift question, i originally wrote it in obj-c, and then i converted it to swift. – Milan Manwar Mar 30 '16 at 07:56
  • That didn't work for me. Can you attach some gif to show me what you get? – efimovdk Mar 30 '16 at 08:24
0

From what I understood you want to change the size of UILabel not the text via animation. This can be achieved by grabbing a copy of the current label's frame and then modify it and set it back.

i.e

var frame = self.myLabel.frame
// frame modification ...
self.myLabel.frame = frame

Solution

Code

For the sizeTranformAction: you can a simple button and connect it to test the behavior.

class SizeTransformViewController: UIViewController {
    var myLabel: UILabel! = nil

    // MARK: - View lifecycle

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
        self.setupLabel()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    // MARK: - Setups

    func setupLabel() {
        self.myLabel = UILabel()
        self.myLabel.center = self.view.center
        self.myLabel.text = "Text"
        self.myLabel.sizeToFit()

        self.myLabel.textAlignment = NSTextAlignment.Center
        self.myLabel.backgroundColor = UIColor.redColor()

        self.view.addSubview(self.myLabel)
    }

    // MARK: - Actions

    @IBAction func sizeTranformAction(sender: AnyObject) {
        var frame = self.myLabel.frame
        let size = frame.size
        frame.size = CGSize(width: 2*size.width, height: size.height)
        frame.origin.x = self.view.center.x - size.width

        UIView.animateWithDuration(0.5, delay: 0, options: UIViewAnimationOptions.CurveLinear, animations: { 
            self.myLabel.frame = frame
        }, completion: nil)
    }
}

Output

enter image description here

E-Riddie
  • 14,660
  • 7
  • 52
  • 74
  • Well, the reason I want to stretch it from center is that I want to avoid the twitching you get. Text must be aligned to the center during all animation. Otherwise it looks ugly – efimovdk Mar 29 '16 at 14:04
  • You can make a custom view for that, as the label waits for the frame to be set, and then it sets the `textAligment`, which causes this behavior – E-Riddie Mar 29 '16 at 14:14
  • @efimovD Or another approach should be by hiding the text during the transition and then show it when the animation is finished. – E-Riddie Mar 29 '16 at 14:20
  • Thanks for your help, @EridB. No, actually this will create a blinking which is undesired. Thank you anyway! – efimovdk Mar 29 '16 at 14:26
0

I actually ended up with 2 labels. Animation sequence is following:

  • Create a temporary label with no text in it, attributes like bg color, font, font size, etc should be the same as of your main label.

  • Place the temporary label above your main label. Set main label's text property to nil

  • Animate the frame of main label to a desired value
  • When animation finishes, set back main label's text property to original value (presumably, in completion handler of animateWithDuration:)
  • Hide temporary label / remove it at all
efimovdk
  • 368
  • 4
  • 16
0

You can change your constant to compensate the new width after scaling. Would this help?

layoutIfNeeded()

let scale: CGFloat = 0.72

let consLeft = NSLayoutConstraint(
    item: titleLabel,
    attribute: .left,
    relatedBy: .equal,
    toItem: self,
    attribute: .left,
    multiplier: 1,
    constant: titleLabel.frameWidth * -(1-scale)/2
  )

consLeft.isActive = true

let animations = {
  self.titleLabel.transform = CGAffineTransform(scaleX: scale, y: scale)
  self.layoutIfNeeded()
}
UIView.animate(withDuration: 0.25, delay: 0, options: [.curveEaseOut],
                     animations: animations,
                     completion: nil)
Everton Cunha
  • 1,017
  • 8
  • 10