2
votes

I created a UIView in storyboard and i linked to a custom UIView class called "XXX". Where in drawRect i have written code to fill color in XXX. From my view controller i'm trying to animate the UIView. Filling color in XXX(UIView) is happening but no animation. here is my code.

class XXX: UIView {

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

override func drawRect(rect: CGRect) {
var context: CGContextRef = UIGraphicsGetCurrentContext()!
CGContextClearRect(context, rect)
let color = UIColor.greenColor().CGColor
CGContextSetFillColorWithColor(context, color)
CGContextAddRect(context, rect)
CGContextFillPath(context)
}


myviewcontroller.swift
@IBOutlet var xxxView: XXX!

 override func viewDidLoad() {
        super.viewDidLoad()

        XXX.animateWithDuration(1.0, delay: 0, options:
            UIViewAnimationOptions.Repeat, animations: { () -> Void in
                XXX.setAnimationDuration(1.0)
                self.xxxView = XXX (frame: CGRectMake(0, 0, 100, 100))

            },completion: nil);
    }

Some where i'm making mistake in my view controller animation. couldn't figure it out. So, How to animate a custom UIView? or How to animate the content of drawrect?

Note: drawRect is been called and rect is filled with color but without animation. My earlier approach was just create a UIView in controller and increase the width with animation. But, it was not accepted by team. some thing like below and works fine.

var xxxView = UIView()
xxxView.frame = CGRectMake(0, 10, startingPoint, 20)
xxxView.backgroundColor = UIColor.greenColor()

UIView.animateWithDuration(1.0, delay: 0, options:
            UIViewAnimationOptions.Repeat, animations: { () -> Void in
            UIView.setAnimationDuration(3.0)

            let totalWidth: CGFloat = 50
            let animationWidth: CGFloat = totalWidth - startingPoint

            var frame : CGRect = xxxView.frame;
            frame.size.width = (startingPoint + animationWidth)
            xxxView.frame = frame;
            },completion: nil);

Thanks!

3

3 Answers

1
votes

UPDATE I see what you are asking now, I misunderstood at first. You are wanting to animate filling of the UIView without actually animating the view (not sure why).

Inside of your drawRect instead of using the supplied rect variable, create your own with a custom "currentHeight" variable with a value of 0, and then increase your "currentHeight" variable until it is full either using an animation block or timer.

You can use a CADisplayLink to call a function to call "setNeedsDisplay" in order to trigger the redrawing as animating a custom variable will not trigger an update to drawing (although maybe you could animate another variable to trigger it, it is sloppy but may work).

Sorry I cannot provide a better explanation or example but I am away from my laptop right now.


The problem is that you are creating a whole new instance of your xxxView inside of your animation block instead of animating the existing one.

If you want your view to animate you need to initialize your existing self.xxxView outside of your animation block (using storyboard or code) to your starting point and inside of your animation block adjust its values that you want to animate. For example:

 override func viewDidLoad() {
    super.viewDidLoad()
    self.xxxView = XXX(frame:CGRectMake(0,0,100,100) //set starting point here or set it in storyboard
    XXX.animateWithDuration(1.0, delay: 0, options:
        UIViewAnimationOptions.Repeat, animations: { () -> Void in
            XXX.setAnimationDuration(1.0)
            self.xxxView.alpha = 1

        },completion: nil);
}

This code will initialize a view with an alpha of 0 and then animate it to an alpha of 1 with a duration of 1 second.

If you want it to appear as if the view is being filled with color you can use the trick of adjusting the views size. It is the same concept of manipulating the attributes of your existing view from within your animation block.

Example:

override func viewDidLoad() {
 super.viewDidLoad()
    self.xxxView = XXX(frame:CGRectMake(0,0,0,0) //set starting point here or set it in storyboard
    self.xxxView.alpha = 0 
    XXX.animateWithDuration(1.0, delay: 0, options:
        UIViewAnimationOptions.Repeat, animations: { () -> Void in
            XXX.setAnimationDuration(1.0)
            self.xxxView.frame = CGRectMake(0,0,100,100)

        },completion: nil);
}
0
votes

I think your problem is that when the view loads, it already loads the animation. When the view appears, you want it animate. Try putting it in override func viewDidAppear().

0
votes

If you just need to animate changing the colour of a UIView then the easiest way would be to use the backgroundColor property and change it in an animation block like so:

UIView.animateWithDuration(duration:1.0, animations:{ () -> Void in
    myView.backgroundColor = UIColor.greenColor();
})

Remember that the animateWithDuration func is a class func so you don't call it on an instance of UIView but the class itself.

In terms of animating the drawRect: method, this is more complex and I cannot give you a definitive answer. One option would be to use a CAAnimation object and add it to the view's layer for the property backgroundColor like so:

var animation : CABasicAnimation = CABasicAnimation(keyPath:"backgroundColor")
animation.fromValue = myView.backgroundColor
animation.toValue = UIColor.greenColor
animation.duration = 1.0

myView.layer.backgroundColor = UIColor.greenColor.CGColor

myView.layer.addAnimation(animation, forKey:"backgroundColor")

NOTE: the above code is untested and is designed to give an idea not be definitive. This also assumes that you want a nice fade animation from one colour to another. For custom animations, like filling from top to bottom you would need to do something else like add a sublayer and animate it's change in size.