I got the coordinates of touchesBegan and touchesEnded.
But in touchesMoved can I get all the coordinates of the touch from touchesBegan to touchesEnded.
I mean that when I put finger on screen and dragged to some position and then I lifted it.
So, can I get all the coordinates of the starting position to end position.
If possible, how I can I get them ?
TouchesMoved gets called whenever there is movement on the touch. If you want an array of all points you'll need to add them to a mutable array every time touchesMoved is called.
- (void) touchesMoved: (NSSet *)touches withEvent:(UIEvent *)event {
CGPoint tappedPt = [[touches anyObject] locationInView: self];
int xPos = tappedPt.x;
int yPos = tappedPt.y;
// do something with xPos and yPos like add them to an array
}
Related
I can't work out how to pass the touch location in touch began into my method that is ran when touch began starts.
-(BOOL) ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event
{
[self schedule:#selector(moveSprite:)];
return TRUE;
}
-(void)ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event
{
[self unschedule:#selector(moveSprite:)];
}
-(void)moveSprite:(ccTime) delta
{
CGPoint spriteCenter = CGPointMake(player.contentSize.width /2,player.contentSize.height /2);
CGPoint touchPoint; //how to get this touch began?
float distanceX = touchPoint.x - spriteCenter.x;
float distanceY = touchPoint.y - spriteCenter.y;
float angle = atan2f(distanceY,distanceX); // returns angle in radians
player.rotation = angle;
}
I also have a question about [self schedule:#selector: Will this continuously call my move sprite method? As I'm going to want the sprite to continuously move and change rotation accordingly as the touch is held down and the sprites position changes.
My final question is about moving the sprite to the x coordinate of the touch. If I use ccmoveto I can't use velocity to make the sprite slowly increase its speed can I? How would I move the sprite to the touched point increasing velocity? I'm guessing its something to do with delta.
Actually, I don't see any need in your scheduled method. You just can implement
- (void)ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event
method and place your sprite rotation logic there.
To get changeable move velocity, you can use one of CCActionEase subclasses. Wrap your move action in one of them and you will see velocity changes during movement. Something like
id move_ease_in = [CCEaseIn actionWithAction:yourMoveAction rate:3.0f];
[player runAction: move_ease_in];
you can see few examples here
I have developed a psuedo 3D carousel for the iPhone that looks pretty much like the image below:
I basically create an array of UIViews and then register for the touch events:
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
// if we're not already tracking a touch then...
if(!trackingTouch)
{
// ... track any of the new touches, we don't care which ...
trackingTouch = [touches anyObject];
}
}
While the movement is still being registered I do the following:
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
// if our touch moved then...
if([touches containsObject:trackingTouch])
{
// use the movement of the touch to decide
// how much to rotate the carousel
CGPoint locationNow = [trackingTouch locationInView:self];
CGPoint locationThen = [trackingTouch previousLocationInView:self];
lastAngle = currentAngle;
currentAngle += (locationNow.x - locationThen.x) * 180.0f / self.bounds.size.width;
// and update the view positions
[self setCarouselAngle:currentAngle];
}
}
I then call when the touches end:
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
// if our touch ended then...
if([touches containsObject:trackingTouch])
{
// make sure we're no longer tracking it
trackingTouch = nil;
// and kick off the inertial animation
animationTimer = [NSTimer scheduledTimerWithTimeInterval:0.03 target:self selector:#selector(animateAngle) userInfo:nil repeats:YES];
}
}
The animageAngle method basically then calls another method with effectively divides 360 degrees by the number of views in the array and use the cosine and sine functions to generate the x and y coordinates.
The above all works good however, I am having difficulty comprehending the maths required to complete the following:
Click on a view out of the main focus i.e. not at the front e.g the purple view in the image
Rotate the purple view into focus i.e. to the front
Load a new view controller once the rotation has complete
I understand that I have to calculate the angle between the view in its current position and the planned destination to make the rotation but I can not for the life of me figure it out.
Apologies for the prior confusion - I have been looking at this problem for sooooo long that I am starting to lose the plot.
Thanks
Finally....I managed to crack it.
I was acting incredibly stupid and was not thinking logically. I basically re-ran a NSTimer calling a method that run the following calculation on the currentAngle property (in psuedo code):
CGFloat currentLocation;
CGFloat nextLocation;
CGFloat destinationLocation;
currentLocation = viewImInterestedIn.frame.origin.x;
nextLocation = currentLocation - 1; //or + 1 if the selected view is to the left of centre
destinationLocation = 115.0f //set this to a default value
currentAngle += (currentLocation - nextLocation ) * 180.0f / self.bounds.size.width;
// and update the view positions
[self setCarouselAngle:currentAngle];
Et voila!
Remarkably simple - I have to learn to just take a step back sometimes and come back to a problem with a clear head.
Thanks all
I'm having a problem with a jumping movement with using CGAffineTransformMakeRotation. It seems to work fine until I get to the top of quadrants 1 and 2. Below is the code I am using and youtube link that shows what happens. Any insight would be really appreciated.
My goal is to rotate a UIWebView with an svg inside. Since I can't easily detect touch on the UIWebView alone, I'm putting a blank UIImageView over it. This allows me to detect the touch and prevent the copy dialog from popping up.
http://www.youtube.com/watch?v=x_OmS0MPdEE&feature=youtu.be
- (void)touchesMoved: (NSSet *)touches withEvent:(UIEvent *)event {
[super touchesBegan:touches withEvent:event];
NSArray *allTouches = [touches allObjects];
CGPoint location = [[allTouches objectAtIndex:0] locationInView:self.view];
if(selected == 1) {
CGFloat rads = atan2f(location.y - (grid1.frame.size.height/2),location.x - (grid1.frame.size.width/2));
grid1.transform = grid1Btn.transform = CGAffineTransformMakeRotation(rads);
}
}
- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[super touchesBegan:touches withEvent:event];
NSArray *allTouches = [touches allObjects];
CGPoint location = [[allTouches objectAtIndex:0] locationInView:self.view];
if(CGRectContainsPoint(grid1Btn.frame, location))
{
selected = 1;
}
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
selected = -1;
}
You use some frame.size.* in your computations. Note, that those values (unlike bounds.size.*) are affected by transform. Use grid1.center instead. It is also more logical (you rotate around center).
The next thing you need to fix is that it should not jump to new position when touches start :)
The jerkiness is caused by the inherent inaccuracy of touch event locations.
Touch events that are located sufficiently close to the center of the frame have a high likelihood of straying to the diagonally opposite quadrant of the frame whilst a circle is being traced about the center of the frame.
This will result in a sudden jump of 90 degrees as observed in your video.
One way to avoid the problem is to introduce a dead zone about the center of the frame. Any touch that is located within a given radius of the center of the frame would not trigger the rotation to be recalculated.
Hope this helps.
I have a UIImageView and I am trying to determine when a drag is performed, how far that drag is from the origin. I currently have this:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInView:touch.view];
if(CGRectContainsPoint(myimage.frame, location) == 0){
}
else
{ //user didn't tap inside image}
The image itself does not move, but a person can take their finger, click on the image and then drag their finger. I am just trying to determine that drag distance.
If you want to calculate distance, you need to remember the point (store it somewhere) in touchesBegan if the user tapped on your image.
Then in touchesMoved or touchesEnd you will be able to get current point and calculate distance to your original point.
If you need to get distance from UIImageView origin, you can call [touch locationInView:myImage];
And I suggest you to use UIGestureRecognizer class instead of handling touches by yourself. They are simpler to implement.
I have a grid of images/buttons, and I want the user to be able to drag their finger over the images/buttons such that when their finger touches each image/button an event is called.
How do I do this???
The best example I can think of now is the Contacts app, how you drag your finger down the list of letters (on the right) and as you touch each letter it jumps to that part of the contacts list.
You're going to want to implement -(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event in your UIViewController. This method is called any time a touch moves on the screen. You can then either use the coordinates (use [myUITouch locationInView:self.view]) or [self.view.layer hitTest:[myUITouch locationInView:self.view]] to get the image/button the touch occurred in and work from that.
For example, if I have a row of ten images, each 32 pixels by 32 pixels, and I want to record when each of them is touched, I could do something like the following:
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
CGSize buttonSize = myButton.bounds.size;
CGPoint touchPoint = [[touches anyObject] locationInView:self.view];
if (touchPoint.y < buttonSize.y) {
NSInteger buttonNumber = touchPoint.x/buttonSize.x;
NSLog(#"Button number %d pushed", buttonNumber);
}
}
Note this assumes multitouch is disabled or it will randomly pick one touch to record