animate pan gesture - cocoa-touch

i have wrote a subclass of UIView, which in drawRect: draws itself. it is actually something like day-long timeline for movie - it draws time axis with ticks and time text labels. it can be zoomed in up to seconds and zoomed out up to all 24 hours. when its zoomed in, it could be scrolled with pan gesture. so here is the question: how can i implement simple animation, when the finger is lifted, timeline continues to scroll for a while and then stops (with negative acceleration)?
two ideas comes to my mind:
implement animation by myself using another thread
make new class - a subclass of CALayer and then use CABasicAnimation. add this class to the layers of my view. but here i should totally move all my code written for view to new subclass of CALayer, what i dont want to do. would it be ok?
any other ideas?

Wouldn't it be easier to integrate the view in a UIScrollView, let that handle the scrolling and zooming and let your class just do the drawing?

Related

Objective C draw in view dynamically

I have seen many examples of views being subclassed to override drawRect, but that approach is pretty static (at least as far as I understand).
What I'd like to do is set up a very simple drawing canvas. In that, I've got a view with a UIPanGestureRecognizer attached to it. Whenever the gesture fires a new position, I'd like to draw a circle of a fixed size and color in that position of the view. The gesture recognizer is attached to the view, but it fires a selector in the view controller. I already have a subclass of a UIView. So, what would be the best approach?
Thanks.
What you need to do in this case is still to override drawRect!
The difference is that you, when recognising gestures, need to keep track of the location(s) in which this circle should be drawn, and access that information the next time you are redrawing the view, essentially building up an image in memory that you draw into the view.

Too many UIViews causes lag

I am creating an app for practice that is a simple drawing app. The user drags his/her finger along the screen and it colors in a 100px x 100px square.
I currently achieve this by creating a new colored UIView where the user taps, and that is working. But, after a little time coloring in, there is substantial lag, which I believe is down to there being too many UIViews as a subview of the main view.
How can I, and others who similarly create UIViews on dragging a finger reduce the lag to none at all, no matter how many UIViews there are. I also think that perhaps this is an impossible task, so how else can someone like me color a cube of the size stated above in the main view on a finger dragged along the screen?
I know that this may seem like a specific question, but I believe that it could help others understand how to reduce lag if there are a very large amount of UIViews where a less performance reducing option is available.
One approach is to draw each square into an image and display that image, rather than keeping around an UIView for each square.
If your drawing is simple enough, though, you can use OpenGL to do this, which is much faster. You should look at Apple's GL Paint Sample Code which shows how to do this in OpenGL.
If your drawing is too complex for OpenGL, you could create, for example, a CGBitmapContext, and draw each square into that context when the user drags their finger. Whenever you draw a new square into that bitmap, you can turn the bitmap into an image (via CGBitmapConxtextCreateImage) and display that image an a UIImageView.
There are two things that come to my mind:
1- Use Instruments tool to check if you are leaking any memory
2- If you are just coloring the views than instead of creating images for each of them, either set the background color property of UIView or override the drawRect method to do custom drawing
I think what you are looking for is the drawRect: method of UIView. You could create your custom UIView (you propably have that already) and override the drawRect method and do your drawing there! You will have to save your drawings in an array or another container and call the setNeedsDisplay method whenever the array content is changed.

Manually scrolling a UIView contentOffset

I'm trying to scroll the contents of a UIView using the contentOffset which so far I achieve handling touchesBegan: and touchesMoves: methods of the view, however I get a jumpy effect as I'm changing the bounds of the UIView manually (for example: current position +/- the change of the last position of the finger and the new position)
Is there any easy way to achieve this without manually changing the bounds of the UIView?
IMPORTANT NOTES: I'm not using a UIScrollView because the mentioned UIView has plenty of draggable subviews so if I use a UIScrollView I can't drag because the UIViewScroll scrolling event executes over the subviews events.
Animating the layer of the mentioned UIView causes the contents to move out of control, like if the point of reference had changed somehow.
However I'm always open to suggestions.
I would rather make a UIView container clipping subviews, add the content view which we will drag as a subview and change it's frame. I think it shouldn't have jumpy effect as it must be the same as animating the view frame change.

How to keep an object in view of a scrollview while animation moves the object offscreen

Good day all;
I have an UIImageView that I animate around a large UIView. The UIView is contained within a UIScrollView.
Now, with small movement animations of the UIImageView within the UIView, if it passes a certain thresh hold (gets close to the edge of the screen), I will manually scroll the UIScrollView to re-center the UIImageView. The code is synchronous in that I animate the UIImageView and then scroll to point in the UIScrollView.
Where I am having an issue is when there is a really long movement animation, the entire scrolling process struggles and I get a lot of skipped frames. I am not certain bit I think it is due to my synchronous code and I believe I need a way to execute the scrolling and the animation at the same time but I have no idea how to do it.
Is there a way to make the scrollview listen to where the UIImageView is at all times and center it when it passes a thresh hold even when in the middle of executing an animation?
By the way, I have disabled the user from scrolling the UIScrollView.
Thanks in advance.
Sorry I have left this for so long, I actually solved this a long time ago but forgot to post my solution.
Basically, pass the UIScrollview to the animated object (a layer or view). The animated object will have itself as a delegate for the animation and implement the methond "animationDidStart:(CAAnimation *)theAnimation".
If you persist the destination location in the animated object and the UIScrollView, then you can compute where to move the scrollview in the "animationDidStart" method.
Beware that the content offset and you destination location in the scrollview must be scaled if your scollview has been scaled. (Trap for young players)

How can I render a custom view in a UIScrollView at varying zoom levels without distorting the view?

The scenario:
I have a custom view (a subclass of UIView) that draws a game board. To enable the ability to zoom into, and pan around, the board I added my view as a subview of UIScrollView. This kind of works, but the game board is being rendered incorrectly. Everything is kind of fuzzy, and nothing looks right.
The question:
How can I force my view to be redrawn correctly ay varying scales? I'm providing my view with the current scale and sending it a setNeedsDisplay message after the scroll view is done zooming in/out, but the game board is still being rendered incorrectly. My view should be redrawing the game board depending on the zoom level, but this isn't happening. Does the scroll view perform a generic transformation on subviews? Is there a way to disable this behavior?
The easiest way to do this is to render your game board at a really high resolution, then let the ScrollView handle scaling it down to your display size automatically.
Basically, set the contentSize of your ScrollView to something big (say 1024x1024), and make your game board one giant view inside it, of the same size (say 1024x1024). Then simply let the ScrollView handle all the scaling questions. You don't even need to intercept setNeedsDisplay or anything; as far as your game is concerned, it's just always rendering at the highest resolution.