Is content drawn by drawRect able to animate using UIView animation? - ios

On iOS, if there are two circles, both of which are UIView objects, then their center or frame can animate using UIView animation.
But the difficulty is, the container UITreeView containing these two circles, draw a line connecting the centers of the circles, using drawRect. In drawRect, I could use CG or UIKit to draw the line, and I chose to use UIBezierPath's moveToPoint and addLineToPoint to draw the line, which should actually just be CG calls underneath, but easier to use.
But when one circle animates to the other position, the line won't animate with it, so the animation can look kind of weird. Is there a way to make it animate?
I tried animating in the TreeView class instead of inside the UINodeView class (the circle), but that won't help. In fact, if I draw the circle using a random color in its drawRect method, when the circle moves slowly in the animation, the color won't change rapidly, suggesting that its drawRect isn't called. It probably is just CALayer that hold a cached image being animated.
So is there a way to make the line animate as well?
The other methods I can think of is:
1) Use a hack to use a UIView to hold the line also, so its frame can animate, but what if the circle moves so that the line needs to be drawn inside the UIView from (0, 0) to (200, 200), but now the line needs to slant the other way, drawing from (200, 0) to (0, 200), so in this case, it probably won't work. (But if I use some kind of transform to flip the image at the same time, it probably will work, but it seems complicated to consider when the transform should be used)
2) use CADisplayLink to do the animation, and just let it call [treeView setNeedsDisplay]; and in this case, the drawRect will be called for sure. (it can be an overkill, and since the whole background of the TreeView will be first erased, there might be a little flashing on the screen going on)
Or is there a simpler or better way?

You could assign your path to a CAShapeLayer (such as wrapping it in a UIView subclass that returns CAShapeLayer as its +layerClass). The path is assigned to the CGPath -path property (and note that UIBezierPath provides a CGPath property).
Then you have a line in a view that you can animate (such as a group animation using UIView +beginAnimations
.

Related

How can I animate a tile in a UIView

I need to create an animated chevron effect using the bitmap tile below. I am hoping that a UIView with a pattern fill will be sufficient, but I need to be able to animate the origin of the pattern over time, and I can't see that this is possible.
I think this is possible with Quartz, or CoreGraphics at the low level. What would be the best way to do this, and can you provide some example code in Swift that demonstrates the solution?
I would add the image as contents of multiple sublayers (CALayer instances) aligned one below the other and animate those sublayers y position.
The main layer would clip its sublayers on the border and sublayers that go offscreen would move to the bottom to be reused, similarly to how UITableView reuses its cells.
You might also want to look at CADisplayLink to have better control of the rendering.

Resizing a rectangle drawn in drawRect

I have two UIViews. My aim is to draw the smallest rectangle which contains both these UIViews. I thought to draw a rectangle using the frame which I'll get out of
CGRectUnion(view1.frame, view2.frame);
But when I move any of the two UIViews, I need to update the frame of the outlining rectangle.
I thought I could do this by :
1) Resizing the previously drawn rectangle.
(or)
2) Deleting the previously drawn rectangle and drawing a new one.
The problem is that, I don't know how to get the instance of the previously drawn rectangle. So, I don't know how to update or delete it..
Can any of you guys help?
Is there any other solution to this problem?
Perhaps you can declare the following in your .h file:
CGRect *transformingRect;
Doing so should retain the rectangle and its properties so long as whatever view controller this is in is visible and loaded. This way you can have a method that resizes the same drawn rect. You would simply call this whenever you need to resize it.
-(void)resizeRect {
transformingRect = CGRectUnion(view1.frame, view2.frame);
}

Resize UIView so that whatever I draw is visible - ObjectiveC

I have a UIView. I am drawing a line inside the UIView programmativally. But when the line goes outside the UIView, the part of the line which goes out, is invisible. How can I resize the UIView so that whatever I draw inside the drawRect method is visible?
you can change the frame of view. If your line is horizontal then give width to view else increase height of view.
view.frame = CGRectMake(view.frame.origine.x, view.frame.origine.y,view.frame.size.width,lengthOfLine );
If the curve you are drawing is a subview, then you can make use of sizeToFit method. This will make the view's frame enclose the curve(and all subviews, for that matter). Then you can reposition and scale the view's frame to make it fit in the window.
You have mentioned in a comment that you are actually drawing a curve. From what I can tell, you will need to calculate the curve's bounding box yourself.
Based on the bounding box, update the UIView's bounds property (as Durgaprasad suggested). This also resizes the underlying CALayer, which also gives its underlying Core Graphics rendering context a larger bitmap.
Without knowing more about your curve, it's hard to help, apart from linking to some very generic discussion on quadratic Beziers.
You may want to update your question with a minimal implementation of -drawRect: that will allow someone to reproduce your issue.

Using panning gesture to animate GCRect resize

I'm drawing a few circles, each filled with an image. When the user pans I'd like to scale/resize the circles. So I called drawRect again and again, redrawing every GCRect until the gesture was completed - of course the animation was very choppy. In my case a UIScrollView doesn't fit the needs, because I don't want to scroll, but to scale the circles while the user is panning.
Is there any way except using OpenGL ES to implement this functionality?
Do you really need custom drawing for this? You can easily clip an image to a circle without drawRect.
Without -drawRect:
Using Core Animation you can set the corner radius of a layer. If all you want is to show an image inside a circle then you can put the image in an image view with a square frame and set the corner radius of the image views layer to half the width of the frame.
Now each time the user drags you can change the bounds and the corner radius of the image views layer. This will make it look like the circle becomes bigger/smaller.
If you require custom drawing
Maybe you are doing some custom shadows or blending that can only be done with Core Graphics. If so, you could apply a scale transform and stretch the image while the user is dragging their finger and only redraw once the finger lifts from the screen. That will be much, much cheaper and is also very easy to implement. Just create a scale transform (CGAffineTransformMakeScale(xScale, yScale);) and set it as the transform on the view with the circle (this will only work if each circle is its own view).
Note: You can still use the same trick (scaling while dragging and then redrawing) if you use the corner radius approach if you require the extra performance.

Shape animation in iOS

I have an UIView in which I draw many shapes. I just want to keep redrawing this view in order to make kind of an animation. I searched for animation options, but all animations looks like they only work with properties, like transform, alpha... I just want a timed animation option, and that do not block the screen, I mean, that allows the application to realize the screen was tapped. Is it possible?
It is totally possible and you have a few different ways that you can go about doing it. If you want a simple png sequence style animation you can just fill a UIImageView like this:
imageView.animationImages = myImages;
imageView.animationDuration = 3;
[imageView startAnimating];
or you can override the drawrect function in a custom UIView, set up an NSTimer to tick however frequently you want to change the animation and call setNeedsDisplay on the view to draw the next frame.
Assuming you have a bezier path that represents each shape, try looking at CAShapeLayer - this can be used to draw a path on the screen, and you can animate the position, fill colour and many other properties of it.
Have one CAShapeLayer per shape, and add them as sub layers to your main view's layer.
You need to add the QuartzCore framework to use it, but it is very straightforward and there are plenty of tutorials out there.

Resources