【发布时间】:2011-10-10 13:59:45
【问题描述】:
我正在构建某种滚动标签,它基本上是一个 UIView,其中包含我动画的标签,如果文本大于 UIView,则会导致子标签来回移动;
@implementation ScrollLabel
static float DEFAULT_SPEED_IN_PIXELS_PER_SECOND = 30.0;
static float DEFAULT_ANIMATION_DELAY = 2.0;
#pragma mark - Properties
#pragma mark - Initialization and Memory Management
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
label1 = [[UILabel label] retain];
[label1 setAutoresizingMask:UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight];
[label1 setBackgroundColor:[UIColor clearColor]];
[label1 setNumberOfLines:1];
[self addSubview:label1];
speedInPixelsPerSecond = DEFAULT_SPEED_IN_PIXELS_PER_SECOND;
scrollAnimationDelay = DEFAULT_ANIMATION_DELAY;
scrollType = theScrollType;
//[self setBackgroundColor:[UIColor greenColor]];
[self setClipsToBounds:YES];
return self;
}
- (void)dealloc
{
[label1 release];
[super dealloc];
}
#pragma mark - Public Static Methods
#pragma mark - Public Instance Methods
// Implement this method if you need more precise control over the layout of your subviews than the autoresizing behaviors provide.
- (void)layoutSubviews
{
[super layoutSubviews];
[self setLabelSize];
[self checkToStartOrStopAnimating];
}
- (void)setText:(NSString *)text
{
if( text == [label1 text] ) return;
[self stopAnimating];
[label1 setText:text];
[self setNeedsLayout];
scrollAnimationDelay = DEFAULT_ANIMATION_DELAY;
}
- (void)checkToStartOrStopAnimating
{
if ([self shouldAnimate])
{
[self startAnimating];
}
else
{
[self stopAnimating];
}
}
- (void)setLabelSize
{
[label1 sizeToFit];
[label1 setFrame:CGRectMake(0, 0, [label1 frame].size.width, [label1 frame].size.height)];
}
- (void)startAnimating
{
if (!animating)
{
animating = YES;
[self animateForwards];
}
}
- (void)stopAnimating
{
if(animating)
{
animating = NO;
[[label1 layer] removeAllAnimations];
}
}
- (BOOL)isAnimating
{
return animating;
}
#pragma mark - Private Methods
- (void)animateForwards
{
float distanceToTravel = [label1 frame].size.width - [self frame].size.width;
if(distanceToTravel > 0 && animating )
{
CGRect rect = [label1 frame];
[UIView animateWithDuration:distanceToTravel / speedInPixelsPerSecond
delay:scrollAnimationDelay
options:UIViewAnimationOptionAllowUserInteraction | UIViewAnimationOptionCurveLinear
animations:^(void)
{
[label1 setFrame:CGRectMake(rect.size.width - self.size.width, 0, rect.size.width, rect.size.height)];
}
completion:^(BOOL finished)
{
scrollAnimationDelay = DEFAULT_ANIMATION_DELAY;
if(finished)
{
[self animateBackwards];
}
else
{
[self stopAnimating];
[self setNeedsLayout];
}
}];
}
else
{
[self stopAnimating];
[self setNeedsLayout];
}
}
- (void)animateBackwards
{
float distanceToTravel = [label1 frame].size.width - [self frame].size.width;
if (distanceToTravel > 0 && animating)
{
CGRect rect = [label1 frame];
[UIView animateWithDuration:distanceToTravel / speedInPixelsPerSecond
delay:scrollAnimationDelay
options:UIViewAnimationOptionAllowUserInteraction | UIViewAnimationOptionCurveLinear
animations:^(void)
{
[label1 setFrame:CGRectMake(0, 0, rect.size.width, rect.size.height)];
}
completion:^(BOOL finished)
{
if (finished)
{
[self animateForwards];
}
else
{
[self stopAnimating];
[self setNeedsLayout];
}
}];
}
else
{
[self stopAnimating];
[self setNeedsLayout];
}
}
- (BOOL) shouldAnimate
{
return [label1 frame].size.width > [self frame].size.width && [self frame] > 0.0;
}
@end
除了在动画运行时(即文本占用的空间大于容器视图的宽度),如果您将文本更改为占用空间大于容器视图宽度的其他内容,不知何故事情正在回归到某种流动状态,其中所有动画都以finish = NO结束(即使标签和父视图具有正确的大小),这当然会导致layoutSubviews被调用,这反过来又会导致动画重新开始并以finish = NO再次结束。 请注意,当文本实际适合父框架时,不会发生这种情况。
我几乎不知道为什么会这样;我显然可以猜测设置文本后某些内容设置不正确,但我无法弄清楚那是什么。 Asked in a more general form,但当然没有确凿的答案。
【问题讨论】:
标签: iphone ios animation uilabel