Animation with control re-use - iphone

I need to animate controls by moving them along the x axis from x to x-1000.
My container view is 200 pixels across and each control is 100 pixels wide.
There is a maximum of 4 controls (the controls are heavy and I need to re-use them)
So therefore, as I animate the controls from x to x-1000, I need to re-use them.
So as control 1 goes off to the left, it becomes invisible and needs to be re-positioned to the right hand side of the container view.
As I will be using an ease in function, the control needs to inherit the same speed and deceleration is it had before; so it literally just animates from right to left, once off screen, instantly re-positioned to the right of the container view, and carries on animating from right to left at the same deceleration rate.
Is there anyway to invoke a function for each frame of a CAPropertyAnimation? or something along those lines?

As far as I know, you can't get velocity information from core animation.
You will have to roll your own animation for this. Setup a timer, and give each view an xVelocity. Every time the timer fires, have it adjust the xVelocity of all objects (you could apply a sine curve to it to give it an ease/out effect). Then change the center point of all the objects.

Related

[unity 2d]zoom in and out on the camera when …Can we set a different zoom level for each of the backgrounds?

I am making a side scrolling game.
What I want is that the layers distant view, middle distance view, near distance view zoom in and out at different ratios.
How do you do that?
You have to understand that if you're using an orthographic camera, the depth (i.e. transform.position.z) is used to decide which objects are rendered on top of others.
Any effect associated with perspective (i.e.: scaling) is lost.
So, in order to do what you want to do, a quick way is to group your objects based on distance (far, middle, near) and scale them accordingly via code (changing their transform.localScale X and Y values). Of course the objects on the far distance will change their localScale less than the middle, and the middle will change less than the near.

How to create infinite motion effect?

I have some square UIView, inside I have an image that looks like a sin signal.
I would like to move that image inside this view from left to right but create infinite effect - so it seems that the sin signal is always going from left to right.
The only way I see is to animate it to move right and when its there simply add it again on left, then remove the previous, etc.
I suspect this would cause memory issues if done on multiple views inside a cell.
Is that the right way to go ?

rotary dial - rotation limitation

I am making a vintage phone and got a working starting code where user moves his fingers over a UIImageView numbers and it rotates dial. It then moves it back to original position. See screenshot.
The three problems that I can't seem to figure out are;
How can I restrict user to rotate only in clockwise direction? Currently user can move it in any direction (clockwise and counter clockwise)
How can I detect which number that user selected? Meaning user touched 1 or 3 or 5? I need this info so that I can stop the rotation when that number reaches the bar on the right.
In my current code when I stop the rotation and let go of the circle, it moves back to it's place by moving back counter clockwise. It works well if I select 1,2,3,4 but for any number 5 and up the dial moves clockwise back to its original position. How can I force counter clockwise motion on touchesEnded?
Let’s assume that you’re talking about this gesture:
Source.
Build a single-touch rotation gesture recognizer. After building the gesture recognizer correctly, you can just look at the rotation and see what to do with the rotary pad.
There are several things you’ll consider when building a single-touch rotation gesture recognizer. If you look at UIRotationGestureRecognizer, it uses connection between two touches, backed by two fingers, to derive the current angle, then compares the angle to the previous angle, derived from an earlier touch change event, to see the delta.
Measuring the current angle
It takes two points to form a line and you need a line to know the angle. If you’re working with only one touch, you need an anchor point. There are many ways to send an anchor point to your gesture recognizer, and since you’re likely going to build a custom class, use delegation.
Accumulating rotation counts
If you simply note the angle and send off messages during touch changes, it’ll sometimes work. However, if you’d like to implement hysteresis (e.g. this rotary dial will only rotate once clockwise, then it tightens up), you’ll need to accumulate rotation counts for both clockwise and counter-clockwise directions.
Fortunately, you can assume that a) the touch events will not get dropped too often, and b) simply comparing the current angle against the past angle, seeing if they cross quadrant boundaries, will suffice.
For example:
If the touch moved from the top-left quadrant into the top-right quadrant, add one to the rotation count.
If the touch moved from the top-right quadrant into the top-left quadrant, subtract one from the rotation count.
(Yup, this actually works.)
Emitting the correct, accumulated rotation
If you want to emit rotation information exactly like how UIRotationGestureRecognizer did, there will be four things you’re tracking.
Starting Angle: The angle between a connection from the anchor point to the starting touch, and a connection from the anchor point to a fixed reference point.
Current Angle: The angle between a connection from the anchor point to the current touch, and a connection from the anchor point to a fixed reference point.
Rotation Count: The number of clockwise revolutions derived from continuously comparing the current value of Current Angle against its last value (as talked about in the last section). If the touch is moving counter-clockwise, then this count will go into negative.
You’ll provide Rotation Count * 2_PI + (Current Angle - Starting Angle) as the rotation.
OK, I would take a different approach. First, you want to create a RotaryDial class to encapsulate all of the behavior. Then you can just plug it into any view as you see fit.
To keep things simple I would consider making each number button a movable UIImageView, call it RotaryDialDigit or something like that. You would instantiate and place ten of those.
The dial "frame" would just tag along for the ride as the user moves one of the RotaryDialDigit buttons. It's just an image (unless you want the user to be able to touch it and do something with it.
From there, knowing which button is being held down and limiting its rotation to a given direction as well as stopping at at the bar is fairly easy stuff.
By using a protocol you can then have the RotaryDial instance tell the container when a number has been dialed. To the container RotaryDial would feel like a keypad sending a message every time a button is pressed. You really don't want the container bothering with anything other than completed number selections.
To detect which number is touched, when you create each number you should set the tag value of its UIView. Then when the user touches the number you can detect which UIView object it was by checking that tag value.
For the rotation problem, I'd suggest looking at how you are calculating the angle. At a guess I'd say for numbers greater than 4 (which you discern from the tag) you need to do something like subtract the angle you are currently calculating from 360 degrees (well 2Pi). (But I have a head cold right now so the actual math is escaping me :-) )
Without seeing your code, I assume the numbers are a static image and you are animating the finger holes as they rotate past each number. If so:
Detecting which number: defina a CGRect around each button. When the user taps the screen, check which rectangle contains the tap location.
Controlling rotation direction: as the user drags their finger, comtinuously calculate the angle from the dial stop to the current tap location. If the angle moves in the wrong direction, dont update the position of the finger hole. Note that trig functions return vales from +Pi to -Pi radians. For the digits greater than 5, rather than handle negative angles you will probably want to add 2Pi radians ( or 360 degrees) to the angle.
Rotating wrong way: the digits below 5 are generatting angles in the range of 0 to -Pi. Without seeing code, I suspect adding 2Pi to the angle will correct your rotation direction.
Here is a better dial:
Have fun!

How can I move a UIView, but leave its content positions unchanged relative to the superview?

A UIView has 2 images as sub-views, and clip to bounds set to yes.
I want to move the UIView in an animation block, but have the sub-views not move with the parent. If the view was to move 50 points to the right, more of the second image would be seen, and less of the first.
I can move the view manually, and update the subview positions opposite the new view position, but I can't figure out how to achieve the same thing in a block.
I think the limitation you're running into has to do with the fact that UIView Animation blocks use Core Animation under the hood, and Core Animation animates a 'presentation' layer which is a copy of the original view/layer that the animation was scheduled on. So during your block's animation, the presentation layer's position is changing, but the position of the model view remains unchanged.
Since you mentioned that you can update the view position manually (and subview positions in the opposite direction) to achieve the desired effect, consider creating an NSTimer at animation schedule time that runs 60 times per second (to try and catch every animation frame) that simply queries the presentation layer for its current position (as set by the animation itself + any special timing functions specified as argument to the animation), and perform your work to update the underlying model to match that.
You should be able to query the animated layer's position with:
yourUIView.layer.presentationLayer.frame.origin
Then add a completion block to your animation that invalidates the timer.
Before you can access the view's layer property, you must add to your project the
QuartzCore.framework
Cheers,

iphone cocoa : how to drag an image along a path

I am trying to figure out how can you drag an image while constraining its movement along a certain path.
I tried several tricks including animation along a path, but couldn't get the animation to play and pause and play backwards - so that seems out of the question.
Any ideas ? anyone ?
What you're basically trying to do is match finger movement to a 'translation' transition.
As the user touches down and starts to move their finger you want to use the current touch point value to create a translation transform which you apply to your UIImageView. Here's how you would do it:
On touch down, save the imageview's starting x,y position.
On move, calculate the delta from old point to new one. This is where you can clamp the values. So you can ignore, say, the y change and only use the x deltas. This means that the image will only move left to right. If you ignore the x and use y, then it only moves up and down.
Once you have the 'new' calculated/clamped x,y values, use it to create a new transform using CGAffineTransformMakeTranslation(x, y). Assign this transform to the UIImageView. The image moves to that place.
Once the finger lifts, figure out the delta from the original starting x,y, point and the lift-off point, then adjust the ImageView's bounds and reset the transform to CGAffineTransformIdentity. This doesn't move the object, but it sets it so subsequent accesses to the ImageView use the actual position and don't have to keep adjusting for transforms.
Moving along on a grid is easy too. Just round out the x,y values in step 2 so they're a multiple of the grid size (i.e. round out to every 10 pixel) before you pass it on to make the translation transform.
If you want to make it extra smooth, surround the code where you assign the transition with UIView animation blocks. Mess around with the easing and timing settings. The image should drag behind a bit but smoothly 'rubber-band' from one touch point to the next.
See this Sample Code : Move Me