【问题标题】:Scrolling UILabel Animation not starting after specific content change特定内容更改后滚动UILabel动画未启动
【发布时间】: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


    【解决方案1】:

    我解决了问题;显然,当设置文本时,动画停止并正确调用layoutSubViews,而停止动画将转到finished = NO,因此再次调用layoutSubViews 重新启动动画。解决方案是检查动画是否正在运行,仅在当前没有动画运行时调用layoutSubviews,否则依赖动画取消并调用layoutSubviews

    @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;
    
        [label1 setText:text];
    
        if(animating) 
    {
        [self stopAnimating];
    } 
    else 
    {
        [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];
        }
    }
    
    - (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];
        }
    }
    
    - (BOOL) shouldAnimate
    { 
        return [label1 frame].size.width > [self frame].size.width && [self frame] > 0.0;
    }
    
    @end
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多