Animate the `backgroundColor`` UIView` which implements the` drawRect`

I have a custom UIView and would like to animate its backgroundColor property. This is an animated property of UIView .

This is the code:

 class ETTimerUIView: UIView { required init(coder aDecoder: NSCoder) { super.init(coder: aDecoder) } // other methods func flashBg() { UIView.animateWithDuration( 1.0, animations: { self.backgroundColor = UIColor.colorYellow() }) } override func drawRect() { // Something related to a timer I'm rendering } 

This code causes the animation to skip and the color changes immediately:

 self.backgroundColor = UIColor.colorYellow() // Changes immediately to yellow 

If I animate alpha, it animates from 1 to 0 in one second, as expected:

 self.alpha = 0 // animates 

How can I change the background color in this situation?

I think I need to do a separate viewing - should this go in the storyboard in the same controller? programmatically created?

Sorry, I'm really new to iOS and Swift.

+6
source share
2 answers

The answer is that you cannot animate the backgroundColor view that implements drawRect . I do not see the documents for this anywhere (comment if you know about it).

You cannot animate it with animateWithDuration , or with Core Animation.

This thread has the best explanation I have found yet:

When you implement -drawRect :, the background color of your view is then pulled into the associated CALayer, and not just set to CALayer as a style property ... thus preventing the crossfade content from getting

The solution, as @Paul points out, is to add another view above, behind, or anywhere and animate it. It comes to life just fine.

I would like to understand well why this is, and why he silently swallows the animation, rather than screaming.

+2
source

This really does not work when I try to do this, I had a related question in which the layoutIfNeeded () method was placed inside the animation and did a smooth viewing of the animation (the button for moving to the target using the restrictions, no reaction? ). But in this case, it does not work with backgroundColor. If someone knows the answer, I will be interested to know.

But if you need a solution right now, you can create a UIView (programmatically or through a storyboard) that is used only as a container. Then you add 2 views inside: one on top and one below, with the same frame as the container. And you only change the top view alpha, which allows the user to see the view behind:

 class MyView : UIView { var top : UIView! override init(frame: CGRect) { super.init(frame: frame) self.backgroundColor = UIColor.blueColor() top = UIView(frame: CGRectMake(0,0, self.frame.width, self.frame.height)) top.backgroundColor = UIColor.yellowColor() self.addSubview(top) } override func touchesBegan(touches: NSSet, withEvent event: UIEvent) { let sub = UIView(frame: CGRectMake(0,0, self.frame.width, self.frame.height)) sub.backgroundColor = UIColor.purpleColor() self.sendSubviewToBack(sub) UIView.animateWithDuration(1, animations: { () -> Void in self.top.alpha = 0 }) { (success) -> Void in println("anim finished") } } } 
+4
source

Source: https://habr.com/ru/post/983368/


All Articles