【问题标题】:How to restore animation when UIView reappears?UIView重新出现时如何恢复动画?
【发布时间】:2014-02-01 01:46:56
【问题描述】:

我有一个自定义的 UIView 子类 (ValveStatusView)。它是一个放置在自定义'UITableViewCellsubclass (ValveCell) . Upon receivingawakeFromNibinValveStatusView`中的子视图,我设置了许多子层,其中一个是动画的。动画设置代码如下所示:

CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position"];
animation.toValue = [NSValue valueWithCGPoint:CGPointMake(32, 64 + 6)];
    animation.duration = 0.75;
    animation.repeatCount = HUGE_VALF;
    animation.timingFunction = [CAMediaTimingFunction functionWithName: kCAMediaTimingFunctionEaseIn];
[drop addAnimation:animation forKey:@"position"];

它使“水滴”图像不断地从水龙头上掉下来,永远。这些单元格嵌入在UITableView 中,然后在选项卡式视图中。当我导航到另一个选项卡然后返回时,我的动画不再运行。我假设当包含我的视图的视图堆栈不再映射到窗口时,它会关闭动画。这是一个正确的假设吗?假设是,当视图再次映射时,让它再次运行的惯用方法是什么?

我查看了UIView 方法,但没有任何东西作为明显的“钩子”跳出来让它再次运行。我承认只是略读,而不是全部阅读。

【问题讨论】:

    标签: ios uiview ios7 core-animation


    【解决方案1】:

    您应该在问题中提到包含动画层的视图是 UITableViewCell 的子类。 :) 因为,这实际上是你的动画被停止的原因。 UITableViewCell 从其子图层中删除动画以避免在从 tableview 中删除单元格以供以后重用时进行不必要的计算。要解决您的问题,您可以覆盖单元格的 prepareForReuse 方法并在那里重新启动动画。所以你应该这样做:

    - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
    {
        self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
        if (self) {
            // Initialization code
    
            // some initial setup here...
    
            [self addAnimation];
        }
        return self;
    }
    
    - (void)prepareForReuse {
    
        [super prepareForReuse];
    
        [self addAnimation];
    }
    
    - (void)addAnimation {
    
        // remove previous animations
        [drop removeAllAnimations];
    
        CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position"];
        animation.toValue = [NSValue valueWithCGPoint:CGPointMake(32, 64 + 6)];
        animation.duration = 0.75;
        animation.repeatCount = HUGE_VALF;
        animation.timingFunction = [CAMediaTimingFunction functionWithName: kCAMediaTimingFunctionEaseIn];
        [drop addAnimation:animation forKey:@"position"];
    }
    

    希望这会有所帮助。

    【讨论】:

    • 不错的收获 +1。但是,就单元重用管理而言,这会增加内存开销吗?如果是这样,您是否可以分享另一种选择?谢谢。
    • 我不太明白您关心的内存开销。但是正如您在addAnimation 中看到的那样,每次添加新动画之前,我们都会从drop 层中删除所有以前的动画。因此,我们没有在整个重用周期中收集任何垃圾。
    • 那么有没有办法在视图级别封装这个呢?我不希望我的自定义视图必须与它所嵌入的环境如此绑定。我只是希望它知道它何时重新曝光,以便它可以重新打开。
    • 澄清一下,做动画的子类不是 UITableViewCell 的子类。它是 UIView 的子类。作为我自己的 UITableView 子类的控件(子视图)嵌入。
    【解决方案2】:

    尝试将您的代码放在- (void) viewWillAppear: 方法而不是awakeFromNib 中,这样只要显示视图就会触发它。

    编辑:

    好的,我知道了,你可以使用NSNotificationCenter:

    在你的 customCell 的 awakeFromNib 中添加一个观察者:

    - (void) awakeFromNib
        {
            [[NSNotificationCenter defaultCenter] addObserver:self
                                                     selector:@selector(startAnimation:)
                                                         name:@"addAnimation"
                                                       object:nil];
        }
    
    • 在startAnimation: 方法中,您当然会放入您的动画代码。
    • 然后在 UITableViewController 的 viewWillAppear 中发布通知以重新启动动画。

      [[NSNotificationCenter 默认中心] postNotificationName:@"addAnimation" 对象:自我];

    • 您必须在 CustomCell 中的某个位置移除观察者,否则该单元格将永远不会被卸载。

    【讨论】:

    • 我的解释可能太模糊了。我的自定义视图是自定义UITableViewCell(也是子类)的子视图,由UITableViewController 以重用样式创建。所以UITableViewController 子类的@viewWillAppear: 和这些之间有一点距离。也许我需要遍历视图树(呃)?有没有办法封装到UIView子类中?
    • 我编辑了我的帖子,希望这次我确实理解了问题。
    【解决方案3】:

    显然,我最初的问题措辞很糟糕。我已尝试进行编辑以澄清情况。不管UITableViewCell 是否被收容,我的愿望是找到一个对此无动于衷的解决方案。封装等等。

    以下代码,添加到ValveStatusView(我的UIView 的子类)。

    - (void) didMoveToWindow {
        if (self.window != nil) {
            [self startDropAnimation];
        }
    }
    

    成功了。 startDropAnimation 受到上述@Davlat 建议的重构的启发:

    - (void)startDropAnimation {
        CALayer* drop = self.activeFaucet.sublayers.firstObject;
        [drop removeAllAnimations];
        CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position"];
        animation.toValue = [NSValue valueWithCGPoint:CGPointMake(32, 64 + 6)];
        animation.duration = 0.75;
        animation.repeatCount = HUGE_VALF;
        animation.timingFunction = [CAMediaTimingFunction functionWithName: kCAMediaTimingFunctionEaseIn];
        [drop addAnimation:animation forKey:@"position"];
    }
    

    didMoveToWindow 是我一直在寻找的钩子(我认为)。

    【讨论】:

    • 当滚动非常快时它不起作用(在这种情况下,UITableView / UICollectionView 在重用之前不会从superveiw中删除单元格)。只有 prepareForReuse 在这种情况下有效,但它破坏了封装,因为我在单元格的子视图中使用动画......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多