CABasicAnimation in uitableviewcell doesn't seem to work

青春壹個敷衍的年華 提交于 2020-01-05 06:59:27

问题


I'm trying to make a label within a tableview cell change background color with a CABasicAnimation and it doesn't seem to be working - the cell background color remains solid with no animation. This code is in the cellForRowAtIndexPath method

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
MainCellTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
NSString *name = @"Hello";
UIColor *color = [UIColor colorWithRed:0.0f/255.0f green:100.0f/255.0f blue:200.0f/255.0f alpha:1.0f];

// I'm setting the label as a strong property of the cell 
cell.label = [[UILabel alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 100.0f, cell.contentView.frame.size.height)]; 

cell.label.text = name;

cell.label.textColor = [UIColor whiteColor];
cell.label.backgroundColor = color;
[cell.contentView addSubview:cell.label];


UIColor *endColor = [UIColor redColor];
CABasicAnimation *animation;
animation=[CABasicAnimation animationWithKeyPath:@"backgroundColor"];
animation.duration=0.7;
animation.repeatCount=HUGE_VALF;
animation.autoreverses=YES;
animation.fromValue=(id)color.CGColor;
animation.toValue=(id)endColor.CGColor;
[cell.label.layer addAnimation:animation forKey:@"pulses"];

return cell;
}

回答1:


I figured out the problem, though I'm not sure why it is the case. If somebody else can add to this answer, please feel free.

It looks as though setting the background color of the cell label was hiding the animation of the layer. If I comment out the backgroundColor setting for the label OR use cell.label.layer.backgroundColor, it works.

What confuses me is that outside of the context of the cell, for instance if you just set a label within a regular view, you can set the backgroundColor and still see the animation.




回答2:


The problem seems to be with UILabel.

It seems that, annoyingly,

you have to set the bg color of UILabel to clear, before you can fool with the color or animate it.

The following works great:

Small text badge, where the background color throbs, throbs, throbs:

In storyboard, simply set the bg color to say black just so you can see what you're doing. (The IBDesignable system is not good enough, as of writing, to render the bounce animation in storyboard.)

Naturally, you can add an @IBInspectable just to set the color bounce - but why when red/orange is so good!? :)

@IBDesignable class ColorTextBadge: UILabel {

    override var text: String? {
        didSet {
            print("Text changed from \(oldValue) to \(text)")
            // very often, you'll want to change the color or whatever
            // when this happens
        }
    }

    override init(frame: CGRect) {
        super.init(frame: frame)
        initialSetup()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        initialSetup()
    }

    func initialSetup() {
        // this will only happen ONCE

        // annoyingly, you have to, in a word, do this to make color bg animations work, on a UILabel:
        backgroundColor = UIColor.clear

        // also, shape the corners...easy
        let r = self.bounds.size.height / 2
        let path = UIBezierPath(roundedRect: self.bounds, cornerRadius:r)
        let mask = CAShapeLayer()
        mask.path = path.cgPath
        self.layer.mask = mask
    }

    override func layoutSubviews() {
        super.layoutSubviews()

        doAnimation()
        // you will have to restart the animation EACH TIME
        // the label is shaped by layout.
    }

    func doAnimation() {

        layer.removeAnimation(forKey: "bounce")

        let bounce = CABasicAnimation(keyPath: "backgroundColor")
        bounce.fromValue = sfRed.cgColor
        bounce.toValue = UIColor.orange.cgColor

        // core magic:
        let ct = CACurrentMediaTime().truncatingRemainder(dividingBy: 1)
        bounce.timeOffset = ct

        bounce.duration = 0.5
        bounce.autoreverses = true
        bounce.repeatCount = Float.greatestFiniteMagnitude

        bounce.isRemovedOnCompletion = false

        layer.add(bounce, forKey: "bounce")
    }
}

There's more!

When table view cells disappear in iOS, any layer animations are killed - boo!

Unfortunately there is only one way to deal with this. Honest, it's the only way. (.isRemovedOnCompletion does not help here.)

In your table view, add

override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    if let c = cell as? ActivityCell {
        c.cellWillDisplaySignalling()
    }
}

Then in your cell class,

class YourCell: UITableViewCell { @IBOutlet var blah: UILabel! @IBOutlet var blah: UILabel! @IBOutlet var aBadge: ColorTextBadge! @IBOutlet var anotherBadge: ColorTextBadge!

...

override func cellWillDisplaySignalling() {
    aBadge.doAnimation()
    anotherBadge.doAnimation()
}

}

That is, unfortunately, the only way for now for a cell to know it is appearing.

Simply call the "doAnimation"s in that function.

Finally, syncing the pulses!

Look in doAnimation at the two lines core magic. I can't be bothered explaining, but try it with and without that; it looks shoddy unless it is synced!



来源:https://stackoverflow.com/questions/26941027/cabasicanimation-in-uitableviewcell-doesnt-seem-to-work

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!