How to drag an image view after applying CGAffineTransformMakeRotation - ios

I am developing an app, Which has feature that dragging and rotating the image view.
I have implemented to drag and rotate successfully by using below code
In touchesBegan Method
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
UITouch *touch = [[event allTouches] anyObject];
touchStart = [[touches anyObject] locationInView:imageView];
isResizingLR = (containerVw.bounds.size.width - touchStart.x < kResizeThumbSize && containerVw.bounds.size.height - touchStart.y < kResizeThumbSize);
}
In touchesMoved Method
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
CGPoint touchPoint = [[touches anyObject] locationInView:containerVw];
CGPoint previous=[[touches anyObject]previousLocationInView:containerVw];
UITouch *touch = [[event allTouches] anyObject];
if (isResizingLR) {
CGFloat currA = [self pointToAngleFromCenter:[touch locationInView:containerVw.superview]] ;
CGFloat prevA = [self pointToAngleFromCenter:[touch previousLocationInView:containerVw.superview]] ;
// the current value of the rotation angle
CGFloat tranA = atan2(containerVw.transform.b, containerVw.transform.a) ;
// the angle difference between last touch and the current touch
CGFloat diffA = currA - prevA ;
// the new angle resulting from applying the difference
CGFloat angle1 = tranA - diffA ;
CGAffineTransform t = CGAffineTransformMakeRotation(angle1) ;
containerVw.transform =t;
}
if (!isResizingLR) {
containerVw.center = CGPointMake(containerVw.center.x + touchPoint.x - touchStart.x, containerVw.center.y + touchPoint.y - touchStart.y);
}
}
My Problem
Above code is working fine until rotating the image view after dragging. In case if i drag the image view after rotating it. image view has gone away from screen.
In touchesEnd method i tried to print the image view frame. for example my image view frame at the beginning is (100,100,150,149) after rotating it the image view 160ยบ frame has changed to (103,31,182,183) up to now its working fine.
After rotating it if try to move an image view, the image view has gone away from screen now the frame has changed to (615,-212,182,183)
Please guide me how do i resolve it.

Have a look at this project. This may help you. But here, the movement is handled by gestures and not by touch. It may solve your problem.

Related

Scaling custom UIView by CGAffineTransformMakeScale breaks dragging with touchesMoved

I have prepared and checked into GitHub a simple test case for dragging custom UIView:
It works well and dragging is implemented in the Tile.m as:
- (void) touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event
{
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInView:self];
CGPoint previous = [touch previousLocationInView:self];
self.frame = CGRectOffset(self.frame,
(location.x - previous.x),
(location.y - previous.y));
}
However the tiles are too large for my actual game (and I will have to adjust their scaling once the game board in UIScrollView is zoomed anyway):
So I scale my custom UIViews down by calling
tile.transform = CGAffineTransformMakeScale(.5, .5);
The size changes, but the tiles are suddenly dragged "twice as quickly" as needed:
Probably the touchesMoved code (s. above) should be adjusted, but I'm not sure what has been broken there by the transform manipulation?
Nevermind, I have found the solution:
- (void) touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event
{
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInView:self];
CGPoint previous = [touch previousLocationInView:self];
if (!CGAffineTransformIsIdentity(self.transform)) {
location = CGPointApplyAffineTransform(location, self.transform);
previous = CGPointApplyAffineTransform(previous, self.transform);
}
self.frame = CGRectOffset(self.frame,
(location.x - previous.x),
(location.y - previous.y));
}

touchesMoved, how do I make my view catch up - and stay under the finger?

I have written some code that restricts the movement of a box (UIView) to a grid.
When moving the box, the movement is locked to the grid and the box starts getting behind your finger if you drag diagonally or really fast.
So what is the best way to write a method that makes the box catch up and get back under the finger - it must move on the same path as your finger - and it must also not move through other boxes, so it needs collision detection - so I just can't do an Animate to new center point.
Any suggestions?
This is current code in use:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInView:self.superview];
lastLocation = location;
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInView:self.superview];
CGPoint offset = CGPointMake(self.center.x + location.x - lastLocation.x, self.center.y + location.y - lastLocation.y);
CGPoint closestCenter = [self closestCenter:offset];
CGRect rect = CGRectMake(offset.x - (self.size.width / 2), offset.y - (self.size.height / 2), self.size.width, self.size.height);
if (fabsf(closestCenter.x - offset.x) < fabsf(closestCenter.y - offset.y)) {
offset.x = closestCenter.x;
}
else {
offset.y = closestCenter.y;
}
// Do collision detection - removed for clarity
lastLocation = location;
self.center = offset;
}
Don't use a relative offset movement. Instead, use the actual touch location as the desired position and then bound (modify) it based on the grid restrictions. In this way you won't get any lag behind the touch.
From your collision detection I guess there is a path that must be followed and a naive implementation will 'jump' the view to the touch across boundaries. A simple solution to this is to limit jumping to a maximum of half a grid square (so the user must bring the touch back to the view if they drop it).

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;
}
}

iOS route-me draggable marker looses track (even in samples)

In my iOS app I'm using the route me lib to display a map in offline mode.
I have some markers on the map, and now I would like to make them draggable. I used this code :
- (void) mapView:(RMMapView *)map didDragMarker:(HotspotMarker*)marker withEvent:(UIEvent *)event
{
UITouch* touch = [[event allTouches] anyObject];
if([[event allTouches] count] == 1 && touch.phase == UITouchPhaseMoved)
{
CGPoint position = [touch locationInView:[touch.view superview]];
CGSize delta = CGSizeMake((position.x-(marker.position.x)),
(position.y-(marker.position.y)));
[marker moveBy: delta];
[marker setProjectedLocation:[[_mapView.contents projection]
latLongToPoint:[_mapView pixelToLatLong:marker.position]]];
}
}
The markers drag well when I move the mouse slowly, but when I move the mouse a little quickly, I loose the track.
So I looked the sample "MapTestbedFlipMaps" project and run it... And encountered the same problem.
Then I tried to do it by myself with a gesture recognizer... but I still have the issue.
Any idea ?
EDIT : the problem doesn't come from the marker's image's size, I tried with a 100x100 image and got the same result.
Try This:
- (void) mapView:(RMMapView *)map didDragMarker:(RMMarker *)marker withEvent:(UIEvent *)event
{
CGPoint position = [[[event allTouches] anyObject] locationInView:mapView];
CGRect rect = [marker bounds];
[self.mapView.markerManager moveMarker:marker AtXY:CGPointMake(position.x,position.y +rect.size.height/3)];
}

uiview touch move get the anchorpoint on uiview

I have a view which, when I click on it, will move left and right. I only get the point center of the view. How can I get the uiview on the anchorpoint because where ever i click on the view it will move.
Here is my code:
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
NSLog(#"touchesMoved called");
UITouch *touch = [[event allTouches] anyObject];
CGPoint touchpoint=[touch locationInView:self.view];
if ([touch view]==secondView)
{
secondView.center=touchpoint;
[self animateFirstPoint:[touch view]];
}
}
If I get you right you're searching for the anchorpoint of the UIView.
First import QuartzCore:
#import <QuartzCore/QuartzCore.h>
Now you can use the anchorpoint of your view:
secondView.layer.anchorPoint = touchpoint;
Remember you have to specify anchor point like CGPointMake(x,y), where x and y are more or equal to 0 or less or equal to 1;
For example:
CGPoint selectionAnchorPoint = CGPointMake(0.15, 0.2);

Resources