iPhone - Move object along touch and drag path - ios

I am developing a simple animation where an UIImageView moves along a UIBezierPath, now I want to provide user interation to the moving UIImageView so that user can guide the UIImageView by touching the UIImageView and drag the UIImageview around the screen.

Change the frame of the position of the image view in touchesMoved:withEvent:.
Edit: Some code
- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event {
UITouch *touch = [[event allTouches] anyObject];
if ([touch.view isEqual: self.view] || touch.view == nil) {
return;
}
lastLocation = [touch locationInView: self.view];
}
- (void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event {
UITouch *touch = [[event allTouches] anyObject];
if ([touch.view isEqual: self.view]) {
return;
}
CGPoint location = [touch locationInView: self.view];
CGFloat xDisplacement = location.x - lastLocation.x;
CGFloat yDisplacement = location.y - lastLocation.y;
CGRect frame = touch.view.frame;
frame.origin.x += xDisplacement;
frame.origin.y += yDisplacement;
touch.view.frame = frame;
lastLocation=location;
}
You should also implement touchesEnded:withEvent: and touchesCanceled:withEvent:.

So you want the user to be able to touch an image in the middle of a keyframe animation along a curved path, and drag it to a different location? What do you want to happen to the animation at that point?
You have multiple challenges.
First is detecting the touch on the object while a keyframe animation is "in flight".
To do that, you want to use the parent view's layer's presentation layer's hitTest method.
A layer's presentation layer represents the state of the layer at any given instant, including animations.
Once you detect touches on your view, you will need to get the image's current location from the presentation layer, stop the animation, and take over with a touchesMoved/touchesDragged based animation.
I wrote a demo application that shows how to detect touches on an object that's being animated along a path. That would be a good starting point.
Take a look here:
Core Animation demo including detecting touches on a view while an animation is "in flight".

Easiest way would be subclassing UIImageView.
For simple dragging take a look at the code here (code borrowed from user MHC):
UIView drag (image and text)
Since you want to drag along Bezier path you'll have to modify touchesMoved:
-(void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *aTouch = [touches anyObject];
//here you have location of user's finger
CGPoint location = [aTouch locationInView:self.superview];
[UIView beginAnimations:#"Dragging A DraggableView" context:nil];
//commented code would simply move the view to that point
//self.frame = CGRectMake(location.x-offset.x,location.y-offset.y,self.frame.size.width, self.frame.size.height);
//you need some kind of a function
CGPoint calculatedPosition = [self calculatePositonForPoint: location];
self.frame = CGRectMake(calculatedPosition.x,calculatedPosition.y,self.frame.size.width, self.frame.size.height);
[UIView commitAnimations];
}
What exactly you would like to do in -(CGPoint) calculatePositionForPoint:(CGPoint)location
is up to you. You could for example calculate point in Bezier path that is the closest to location. For simple test you can do:
-(CGPoint) calculatePositionForPoint:(CGPoint)location {
return location;
}
Along the way you're gonna have to decide what happens if user wonders off to far from your
precalculated Bezier path.

Related

Issue regarding TouchesMoved using the method CGRectContainsPoint

My issue occurs when I drag the uiimageview accross the screen on, which is set to only be dragable in the x axis direction.
The code sort of works. The uiimageview is moving alright and it's limited to the x axis only, which is exactly what it should.
BUT when you start dragging outside the frame of the uiimageview, it stops moving along side my finger.
This obliviously has something to do with this method: CGRectContainsPoint.
Bare in mind it's very necessary in my code as I only want the uiimageview to move, when a user has set it's finger on it.
If I didn't use this method CGRectContainsPoint, the image would still move even when a users finger wouldn't touch the image. Any work around this is much appreciated.
here's my code:
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
NSLog(#"Touches Moved is running");
UITouch *touch = [[event allTouches] anyObject];
CGPoint location = [touch locationInView:self.view];
if (CGRectContainsPoint(UIImageView, location) && UIImageView >= 40)
{
NSLog(#"Contains Point UIImageView Center!");
CGPoint xLocation = CGPointMake(location.x,UIImageView);
UIImageView = xLocation;
//here it comes.. big block of code//
if (location.x <= 40) {
NSLog(#"Start Dragging Point");
CGPoint newLocation = CGPointMake(40
, 402);
UIImageView = newLocation;
}
else if(location.x >= 273) {
NSLog(#"End Dragging Point");
CGPoint newLocation = CGPointMake(273
, 402);
UIImageView = newLocation;
}
}
Move CGRectContainsPoint(UIImageView, location) from -(void)touchesMoved:... to -(void)touchesBegan:....
Set an ivar there that points to the view only when you began the touch inside the view. Use this ivar from -(void)touchesMoved:... to boundlessly move the view. You can then unset this variable both in -(void)touchesEnded:... and -(void)touchesCancelled:....

Can glow on the touch point when touch the view in IOS?

Just like the title ,when I touch the UIView I want the touch point to be glow, I came up with a idea that to show a glow image on the touch point ,but if by code?any example or idea?thanks for sharing!!
You can try touchesBegan event below Code:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
if([touch view] ==self.my_view)//Check click your uiview or not
{
CGRect frame = [your_image_view frame];
CGPoint touchLocation = [touch locationInView:touch.view];
frame.origin.x=touchLocation.x;
frame.origin.y=touchLocation.y;
[your_image_view setFrame:frame];
[self.my_view addSubview:your_image_view];
}
}
Thanks..!
Well the first step would be to detect the touch on your UIView for that I would recommend using the high level API UIGestureRecognizer andd add to your view. Then you can use the call back to do whatever you want, perhaps some sort of animation?. If so you can use an animation block to animate your changes.

How to use drag items in iOS

I'm not quite sure how to start explaining this, but I'll try.
I started reading iOS books awhile ago, and I'm trying to get a handle on Objective-C. I think I have an ok understanding of it.
What I'm doing in iOS is making a simple game that involves dragging numbers into a box, which the app then grabs the number that was dragged into the box. However, I have no idea how I do this.
I was wondering if you guys have any links/articles on something like this, if I should use a certain framework for this, or maybe even some example code.
Thanks for any answers.
do a search on 'cocos2d drag' ... also, here is an article that might help you get started.
This is a pretty general question with huge scope, but a simple approach could be to create a custom UIView subclass for each draggable number that handles the drawing. In a view controller you can create all of these custom UIViews and create a UILongPressGestureRecognizer for each one, with the allowableMovement property set to CGFLOAT_MAX, or some large number. Attach the recognizer to each draggable view with the action method some callback in the view controller.
Then, in the view controller gesture recognizer action method, you can just update the views center property to the gesture recognizers location in the view controllers view. Something like:
- (void)handleLongPressGesture:(UIGestureRecognizer *)recognizer
{
if ([recognizer state] == UIGestureRecognizerStateChanged)
{
[[recognizer view] setCenter:[recognizer locationInView:self.view]];
}
}
Cocos2D is fine, and I like it, but you don't really need to go to that level just to do some basic UITouch handling. If all you want to do is handle some touches, here is an example:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [[event allTouches] anyObject];
// Only move the placard view if the touch was in the placard view
if ([touch view] != placardView) {
// On double tap outside placard view, update placard's display string
if ([touch tapCount] == 2) {
[placardView setupNextDisplayString];
}
return;
}
// "Pulse" the placard view by scaling up then down
// Use UIView's built-in animation
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
CGAffineTransform transform = CGAffineTransformMakeScale(1.2, 1.2);
placardView.transform = transform;
[UIView commitAnimations];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
transform = CGAffineTransformMakeScale(1.1, 1.1);
placardView.transform = transform;
[UIView commitAnimations];
// Move the placardView to under the touch
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.25];
placardView.center = [self convertPoint:[touch locationInView:self] fromView:placardView];
[UIView commitAnimations];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [[event allTouches] anyObject];
// If the touch was in the placardView, move the placardView to its location
if ([touch view] == placardView) {
CGPoint location = [touch locationInView:self];
location = [self convertPoint:location fromView:placardView];
placardView.center = location;
return;
}
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [[event allTouches] anyObject];
// If the touch was in the placardView, bounce it back to the center
if ([touch view] == placardView) {
CGPoint location = [touch locationInView:self];
location = [self convertPoint:location fromView:placardView];
UIView* dropZone; // assume this exists
CGRect dz = [dropZone frame];
if (CGRectContainsPoint(dz,location)) {
[self doDropMagic];
}
}
}
For more, check out the event handling guide which is where I got this hacked up code from.
I actually would point you to using Cocos2d. It's a nice framework on top of opengl and is pretty fast. It's so easy to create objects(in terms of Cocos2d it's a CCSprite) and put them on your view(CCLayer) and interact with them.
A drag and drop would actually consists of three phase (pseudo-code) using the touch handler methods (similar to UIKit's touch methods):
Pick up a number in ccTouchesBegan
move the number in ccTouchesMoves: update the numbers position with the touch position
Drop the number with ccTouchesEnded
The TouchesTest target in the repository shows a decent example on drag and drop. It implements a simple Pong like game:
Touch handling basics of cocos2d
There are tons of examples in the repository of cocos2d to understand the different parts better.
A decent book on cocos2d is the Learning Cocos2D.

If I use ccDrawLine as part of a custom class, can it detect touches?

Basically, I've got a custom class that has a draw method that draws a line from point a to point b.
I'm subclassing CCSprite, so does the line then have a bounding box I can use to detect when someone touches the line?
As an example of what I'm trying to accomplish, I've cobbled together this code:
- (void)ccTouchesBegan:(NSSet*)touches withEvent:(UIEvent*)event
{
UITouch* touch = [touches anyObject];
CGPoint location = [touch locationInView: [touch view]];
location = [[CCDirector sharedDirector] convertToGL: [touch locationInView:touch.view ]];
for (Path *path in paths) {
CGRect pathRect = CGRectMake(path.position.x, path.position.y, path.contentSize.width, path.contentSize.height);
if(CGRectContainsPoint(pathRect, location)) {
CCLOG(#"Line Touched");
}
}
}
paths is a mutable array of Path objects. I've put logs after each statement in the method, and it gets through everything but the for loop. For some reason, it seems like it never gets into the loop.
The answer is yes, you can. You just have to make sure you set the rectangle the the right size, and place it at the correct origin point, which was where I was breaking it.

rotate an image with touch

I making an app which sets the sleep timer with a clock .Basically it is clock which has a single hand which user can move to set his sleep time .I tried to rotate the image with uitouch but it rotates from middle but i want it to rotate from the tip.Secondly i want that the image only rotates when user is touching the tip of the image but in my project the image is also rotating when use touches any part of the screen.Also i want to rotate the image in both directions but in my project it moves only clockwise due to this method
image.transform = CGAffineTransformRotate(image.transform, degreesToRadians(1));
Can anybody give me hints or solutions about how can it be done?
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
//
touch = [[event allTouches] anyObject];
touchLocation = [touch locationInView:touch.view];
NSLog(#"began");
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
// get touch event
[image.layer setAnchorPoint:CGPointMake(0.0,0.0)];
if ([touch view] == image) {
image.transform = CGAffineTransformRotate(image.transform, degreesToRadians(1));
//image.center = touchLocation;
}
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
NSLog(#"end");
}
In detail, you can custom a rotateView,then:
1: In the delegate method of "touchesBegan", get initialPoint of finger and initialAngle.
2: During "touchesMoved",get the newPoint of finger:
CGPoint newPoint = [[touches anyObject] locationInView:self];
[self pushTouchPoint:thePoint date:[NSDate date]];
double angleDif = [self angleForPoint:newPoint] - [self angleForPoint:initialPoint];
self.angle = initialAngle + angleDif;
[[imageView layer] setTransform:CATransform3DMakeRotation(angle, 0, 0, 1)];
3: At last, in "touchesEnded" you can calculate final AngularVelocity.
If anything being confused, for more detail, you can write back.
To rotate it the other way you just use:
image.transform = CGAffineTransformRotate(image.transform, degreesToRadians(1));
And to rotate form the tip you should use setAnchorPoint (like you used in your code, but i think you should do: [image setAnchorPoint]).
more on the subject: setAnchorPoint for UIImage?
I tried to rotate the image with uitouch but it rotates from middle but i want it to rotate from the tip
I dont know any way in SDK to rotate an element on its extreme end. If you want to have that effect take the clock handle image you have twice in length with half portion transparent. It is not a direct solution, but a workaround.
Also i want to rotate the image in both directions but in my project it moves only clockwise due to this method
As per iOS developer documentation, a positive angle value specifies counterclockwise rotation and a negative value specifies clockwise rotation.

Resources