问题
I am using iOS 7 and I am trying to move a label that is centered off to the left of my view. Currently I am trying to do this by changing how my UILabel is aligned, and I am trying to animate it in the process. I am currently calling the following:
[UIView animateWithDuration:0.5
animations:^{
self.monthLabel.textAlignment = NSTextAlignmentLeft;
} completion:nil];
But this just jumps the label to the new alignment. Is there a way to animate this, or a better way to adjust the label to make this happen?
回答1:
Set the UILabel frame size to exactly contain the text and center the UILabel in your view.
self.monthLabel.text = @"February";
[self.monthLabel sizeToFit];
self.monthLabel.center = parentView.center; // You may need to adjust the y position
Then set the alignment which should not affect the layout since there will be no extra space.
self.monthLabel.textAlignment = NSTextAlignmentLeft;
Next, animate the UILabel frame size so it slides over where you want it.
[UIView animateWithDuration:0.5
animations:^{
CGRect frame = self.monthLabel.frame;
frame.origin.x = 10;
self.monthLabel.frame = frame;
} completion:nil];
回答2:
Is your label multiline? An animation like this: http://img62.imageshack.us/img62/9693/t7hx.png?
If so, then there's a couple of alternatives.
Multiline label
Option 1:
Instead of a traditional UIView animation, try a UIView transition. The text wont slide to the left, but instead it will fade nicely to the new position.
[UIView transitionWithView:self.monthLabel
duration:0.5
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^{
self.monthLabel.textAlignment = NSTextAlignmentLeft;
} completion:NO];
Option 2:
You can manually work out where the new lines will appear, then create a separate UILabel for each line of text then animate the frames. This is obviously more work, but will give that desired slide animation.
Single line label
Instead of animating the textAlignment, make the label the same size of the string it contains with [self.monthLabel sizeToFit], then manually work out the framing and the centering. Then just animate the frame, the same as option 2 on a multiline label.
回答3:
you can animate the FRAME, not the textAlignment.
Do a [UILabel sizeToFit] on your label if you want to get rid of any "padding" on the frame, then you can animate the frame in your animation block to move it around as you desire
CGRect frameLabel = self.monthLabel.frame;
[UIView animateWithDuration:0.5
animations:^{
frameLabel.origin.x -= 100; // e.g. move it left by 100
self.monthLabel.frame = frameLabel;
} completion:nil];
回答4:
you just need to animate your label frame. As here completion block is there in it you should change the frame again. and make the loop going.
[UIView animateWithDuration:0.5
animations:^{
// Change the frame
} completion:^{[UIView animateWithDuration:0.5
animations:^{
// Change the frame
} completion:^{
// repeat the proccess
}]
}];
回答5:
This has served me well
import Foundation
import UIKit
class AnimatableMultilineLabel: UIView {
enum Alignment {
case left
case right
}
public var textAlignment: Alignment = .left {
didSet {
layout()
}
}
public var font: UIFont? = nil {
didSet {
setNeedsLayout()
}
}
public var textColor: UIColor? = nil {
didSet {
setNeedsLayout()
}
}
public var lines: [String] = [] {
didSet {
for label in labels {
label.removeFromSuperview()
}
labels = []
setNeedsLayout()
}
}
private var labels: [UILabel] = []
override init(frame: CGRect) {
super.init(frame: frame)
setup()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setup()
}
private func setup() {
isUserInteractionEnabled = false
}
override func layoutSubviews() {
super.layoutSubviews()
layout()
}
private func layout() {
autocreateLabels()
var yPosition: CGFloat = 0.0
for label in labels {
let size = label.sizeThatFits(bounds.size)
let minX = textAlignment == .left ? 0.0 : bounds.width - size.width
let frame = CGRect(x: minX, y: yPosition, width: size.width, height: size.height)
label.frame = frame
yPosition = frame.maxY
}
}
private func autocreateLabels() {
if labels.count != lines.count {
for text in lines {
let label = UILabel()
label.font = font
label.textColor = textColor
label.text = text
addSubview(label)
labels.append(label)
}
}
}
override func sizeThatFits(_ size: CGSize) -> CGSize {
autocreateLabels()
var height: CGFloat = 0.0
for label in labels {
height = label.sizeThatFits(size).height
}
return CGSize(width: size.width, height: height)
}
}
Then you should be able to
UIView.animate(withDuration: 0.5, animations: {
multilineLabel.textAlignment = .right
})
来源:https://stackoverflow.com/questions/19251506/is-there-a-way-to-animate-changing-a-uilabels-textalignment