Two views with multitouch - ios

I should manage two different views inside my main view; I want detect the exact number of finger inside my views, that is if I have four fingers inside "first view" I want a var that say me a value = 4, and if I have 3 fingers in "second view" I want another var that say me a value = 3. I show you my code that don't work fine.
- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
UITouch *touch = [[event allTouches] anyObject];
CGPoint touchLocation = [touch locationInView:self.view];
NSLog(#"cgpoint:%f,%f", touchLocation.x, touchLocation.y);
if (CGRectContainsPoint(view1.frame, touchLocation)){
NSLog(#"TOUCH VIEW 1");
totalTouch1 = [[event allTouches]count];
NSLog(#"TOTAL TOUCH 1:%d", totalTouch1);
}
else if (CGRectContainsPoint(view2.frame, touchLocation)){
NSLog(#"TOUCH VIEW 2");
totalTouch2 = [[event allTouches]count];
NSLog(#"TOTAL TOUCH 2:%d", totalTouch2);
}
}
With my code if I begin to lay my finger in "first view", it's all ok, but for example if I lay my fourth finger inside second view my code enter in first "if" and say that my finger is yet in first view. I don't understand the problem.

[[event allTouches] anyObject]; is fetching you only one of the touches.
you need to iterate over all the touches like so:
- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
int touch1 = 0;
int touch2 = 0;
NSArray *touches = [[event allTouches] allObjects];
for( UITouch *touch in touches ) {
CGPoint touchLocation = [touch locationInView:self.view];
NSLog(#"cgpoint:%f,%f", touchLocation.x, touchLocation.y);
if (CGRectContainsPoint(view1.frame, touchLocation)){
NSLog(#"TOUCH VIEW 1");
touch1 += 1;
NSLog(#"TOTAL TOUCH 1:%d", totalTouch1);
}
else if (CGRectContainsPoint(view2.frame, touchLocation)){
NSLog(#"TOUCH VIEW 2");
touch2 += 1;
NSLog(#"TOTAL TOUCH 2:%d", totalTouch2);
}
}
NSLog(#"Total touches on view 1: %d", touch1);
NSLog(#"Total touches on view 2: %d", touch2);
}

Related

moving 2 objects at same time

In my current ios project, I have dedicated one side of the screen to one object and the other side of the screen to the other object and i have made it so that if you swipe your finger across one side of the screen on the designated object would move. However, I want to make it so that you can move both objects at the same time in different movement but i cannot figure out how to do so. Below is my current code.
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [[event allTouches] anyObject];
CGPoint location = [touch locationInView:touch.view];
if (location.x <= 270 ) {
[Person setCenter:CGPointMake(location.x, Person.center.y)];
}
else {
[Person1 setCenter:CGPointMake(location.x, Person1.center.y)];
}
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [[event allTouches] anyObject];
CGPoint location = [touch locationInView:touch.view];
if (location.x <= 270 ) {
[Person setCenter:CGPointMake(location.x, Person.center.y)];
}
else {
[Person1 setCenter:CGPointMake(location.x, Person1.center.y)];
}
}
you should start handling multiple touches that are delivered in the touches set - loop through all the UITouch objects and do your handling.
Edit:
here's your code:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
for(UITouch *touch in [event allTouches]) {
CGPoint location = [touch locationInView:touch.view];
if (location.x <= 270 ) {
[Person setCenter:CGPointMake(location.x, Person.center.y)];
}
else {
[Person1 setCenter:CGPointMake(location.x, Person1.center.y)];
}
}
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
for(UITouch *touch in [event allTouches]) {
CGPoint location = [touch locationInView:touch.view];
if (location.x <= 270 ) {
[Person setCenter:CGPointMake(location.x, Person.center.y)];
}
else {
[Person1 setCenter:CGPointMake(location.x, Person1.center.y)];
}
}
}
If you move the -touchesBegan & touchesMoved code into the Person view class rather than the view/or viewController class it is in currently then those views can handle touches independent of each other and simultaneously.
*Edit: More info:
Currently you are handling touches events (in I'm guessing a UIViewController) using the code you pasted above, if you moved that code into your Person class you have created you could make the code simpler and achieve the result you desire.
This will have the effect that the Person will decide if it is being touched and where and will move itself accordingly.
In your Person.m file add this code,
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
UITouch *touch = [[event allTouches] anyObject];
CGPoint location = [touch locationInView:self.superview];
[self moveToLocation:location];
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
UITouch *touch = [[event allTouches] anyObject];
CGPoint location = [touch locationInView:self.superview];
[self moveToLocation:location];
}
-(void)moveToLocation:(CGPoint)location{
CGFloat halfOfPersonWidth = self.bounds.size.width /2.0f;
CGFloat halfOfSuperviewWidth = self.superview.bounds.size.width/2.0f;
// Stop Person from going off left screen edge
if ((location.x - halfOfPersonWidth) <= 0.0f){
return;
} // Stop Person from going off right screen edge
else if ((location.x + halfOfPersonWidth) >= self.superview.bounds.size.width){
return;
}
if (self.center.x < halfOfSuperviewWidth) {
// Person is on the left of the screen and should not move to right side
if ((location.x + halfOfPersonWidth) > halfOfSuperviewWidth) {
return;
}
} else{
// Person is on the right of the screen and should not move to left side
if ((location.x - halfOfPersonWidth) < halfOfSuperviewWidth) {
return;
}
}
// If we have made it this far then we can move the Person
// move to touch location on x axis only
[self setCenter:CGPointMake(location.x, self.center.y)];
}
Now in your View Controller class you can delete the original -touchesBegan & -touchesMoved code that you pasted here, Or just comment it out if you want to be cautious
/* put slash asterisks above the code and asterisks slash below the code to comment out */
If you build and run you should be able to move each Person view around as before but if you put a finger on each Person view at the same time you should be able to move them simultaneously.

TouchesMoved with UITouch

I'm trying to create a simple application where you can move your UIImageView by touching him and dragging him around.
my UIImageView is called imv
-(void ) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
UITouch * touch = [touches anyObject];
if([touch view] == self.imv){
CGPoint location = [touch locationInView:self.view];
self.imv.center = location;
}
}
-(void ) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
UITouch * touch = [touches anyObject];
if([touch view] == self.imv){
CGPoint location = [touch locationInView:self.view];
self.imv.center = location;
}
}
i'am trying to solve this like whole day and i don't know what is wrong. If i disable if statement it's working else not. What can i do?
Thanks for the answers
Unless you've subclassed UIImageView (unlikely), your view is receiving the touch events.
These days it's simpler & more usual to use a UIGestureRecognizer for this kind of thing, in this case a UIPanGestureRecognizer.
e.g.
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(dragImageView:)];
[self.imv addGestureRecognizer:pan];
- (void)dragImageView:(UIPanGestureRecognizer *)dragImageView {
if(UIGestureRecognizerStateBegan == state) {
originalCenter = self.imv.center; // add CGPoint originalCenter; member
} else if(UIGestureRecognizerStateChanged == state) {
CGPoint translate = [pan translationInView:self.imv.superview];
self.imv.center = CGPointMake(originalCenter.x + translate.x, originalCenter.y + translate.y);
}
}
From a bit of experimenting, it seems that the [touch view] is returning the main UIView and not your subview, hence the problem with the if statement not working (I added the UIImageView in a storyboard xib). EDIT- it's because UIImageViews don't handle touch events by default - see here . When adding a regular UIView in the viewDidLoad seems to work as you would expect.
Anyway, this adapted version of your code works for me
-(void)moveImageForTouches:(NSSet*)touches
{
UITouch * touch = [touches anyObject];
CGPoint location = [touch locationInView:self.view];
if(CGRectContainsPoint(self.imv.frame, location))
{
self.imv.center = location;
}
}
-(void ) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
[self moveImageForTouches:touches];
}
-(void ) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[self moveImageForTouches:touches];
}

UIImageView Jumps when Touch Event Occurs

Okay basically what this code currently does is drag an image up and down along the Y axis depending on where the user drags it, and it returns to its original position. My problem is that if someone were to not touch directly on the center of the UIImageView and start dragging it would jolt (very not smooth). Wherever someone is touching the UIImageView and starts dragging the UIImageView jolts a little to go directly on the center of the touch event.
I was thinking about using animation just to move it where the image needs to go, or is there another way?
I apologize if this is an inefficient way to do this. I'm fairly new to the IOS world.
Here's what I have:
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
//Gets location of UIImageView.
self.originalFrame = self.foregroundImage.frame;
}
//This method is used for moving the UIImageView along the y axis depending on touch events.
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [[event allTouches] anyObject];
if([touch view]==self.foregroundImage) {
CGPoint location = [touch locationInView:self.view];
location.x=self.foregroundImage.center.x;
self.foregroundImage.center=location;
}
}
//This method sets the UIImageView back to its original position.
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
CGRect newFrame = self.foregroundImage.frame;
newFrame.origin.y = self.originalFrame.origin.y;
[UIView animateWithDuration:1.1 animations:^{
self.foregroundImage.frame = newFrame;
}];
}
You also need to save the first location in touchesBegan, relative to the parent view. Then, you can use that to change the frame by the difference between the previous location and the new location. Please see the following code.
- (void) touchesBegan: (NSSet*) touches
withEvent: (UIEvent*) event
{
if (touches.count == 1)
{
UITouch* touch = [touches anyObject];
self.touchLocation = [touch locationInView: self.view];
}
}
- (void) touchesMoved: (NSSet*) touches
withEvent: (UIEvent*) event
{
if (touches.count == 1)
{
UITouch* touch = [touches anyObject];
CGPoint newTouchLocation = [touch locationInView: self.view];
if (touch.view == self.foregroundImage)
{
/* Determine the difference between the last touch locations */
CGFloat deltaX = newTouchLocation.x - self.touchLocation.x;
CGFloat deltaY = newTouchLocation.y - self.touchLocation.y;
/* Offset the foreground image */
self.foregroundImage.center
= CGPointMake(self.foregroundImage.center.x + deltaX,
self.foregroundImage.center.y + deltaY);
}
/* Keep track of the new touch location */
self.touchLocation = newTouchLocation;
}
}

Have an image follow your finger along the x axis, but have a fixed y-coordinate

I'm using the touchesMoved method to have an image "follow" someone's finger along the bottom of the screen. So the image will follow the x position of the finger, but it ignores the y position and stays vertically-fixed at the bottom (but not horizontally-fixed). Is there some way I can implement this?
This is my code:
- (void)viewDidLoad
{
[super viewDidLoad];
// create basket image that will be shown on the screen
basketView = [[UIImageView alloc]
initWithImage:[UIImage imageNamed:#"bucket.png"]];
basketView.frame = CGRectMake(130.0, 412.0, 50.0, 50.0);
[self.view addSubview:basketView];
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
// get current touch location
UITouch *touch = [[event touchesForView:self.view] anyObject];
CGPoint point = [touch locationInView:self.view];
// update location of the image
basketView.center = point;
}
Maintain the y position, change the x
basketView.center = CGPointMake(point.x, basketView.center.y);
In touchesMoved Do this
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
// get current touch location
UITouch *touch = [[event touchesForView:self.view] anyObject];
CGPoint point = [touch locationInView:self.view];
// update location of the image
basketView.center = CGPointMake(point.x,basketView.center.y);
}
Do as follows...
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
// get current touch location
UITouch *touch = [[event touchesForView:self.view] anyObject];
CGPoint point = [touch locationInView:self.view];
point.y=basketView.center.y; //Fix 'y' of basket
// update location of the image
basketView.center = point;
}

Drag UIVIew relative to finger

I have a little problem.
I have some UIView and I'm able to drag them with methods touchesBegan and touchesMoved.
My problem is my UIView's coordinates (0,0) is coming under my finger. I would like to avoid that.
Do you know how to do that. I try some things but with no success :(
Thanks a lot !
It will depend on the size of the view but you can probably set the center property to your touch's location.
Animating the center to your tap location
[UIView animateWithDuration:0.25f
delay:0.0f
options:(UIViewAnimationOptionBeginFromCurrentState|UIViewAnimationOptionCurveEaseInOut)
animations:^{
theView.center = tapLocation;
}
completion:NULL]
Instead of just moving the location or translating it, you can animate the view to your current touch in all touches* methods.
when you press down your finger save the point
then measure the speed of the drag, and apply the speed to the position of your view (I translate my view with origin in my exemple)
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
NSUInteger touchCount = [touches count];
NSUInteger tapCount = [[touches anyObject] tapCount];
NSLog(#"touchesBegan");
NSLog(#"%d touches", touchCount);
NSLog(#"%d taps", tapCount);
UITouch *touch = [touches anyObject];
pNow = [touch locationInView:self];
pLast = [touch locationInView:self];
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
NSUInteger touchCount = [touches count];
NSUInteger tapCount = [[touches anyObject] tapCount];
NSLog(#"touchesMoved");
NSLog(#"%d touches", touchCount);
NSLog(#"%d taps", tapCount);
UITouch *touch = [touches anyObject];
pNow = [touch locationInView:self];
mouseSpeed.x = pNow.x - pLast.x;
mouseSpeed.y = pNow.y - pLast.y;
NSLog(#"mouseSpeed : %f, %f", mouseSpeed.x, mouseSpeed.y);
origin.x += mouseSpeed.x;
origin.y += mouseSpeed.y;
NSLog(#"origin : %f, %f", origin.x, origin.y);
//copy point for the next update
pLast = pNow;
}

Resources