I am using the locationInView to set the position of my bouton when the user release it. After release, I give the location stored before but in fact, my button is not going back to the correct position.
This my code:
- (IBAction)handlePan:(UIPanGestureRecognizer *)recognizer{
CGPoint translation = [recognizer translationInView:self.view];
recognizer.view.center = CGPointMake(recognizer.view.center.x + translation.x,
recognizer.view.center.y + translation.y);
[recognizer setTranslation:CGPointMake(0, 0) inView:self.view];
static CGPoint startLocation;
if (recognizer.state == UIGestureRecognizerStateBegan) {
startLocation = [recognizer locationInView:self.view];
NSLog(#"Began: %d" #"-" #"%d", (int)startLocation.x , (int)startLocation.y);
}
if (recognizer.state == UIGestureRecognizerStateEnded)
{
NSLog(#"Ended Bef: %d" #"-" #"%d", (int)startLocation.x, (int)startLocation.y);
recognizer.view.center = CGPointMake(startLocation.x, startLocation.y);
startLocation = [recognizer locationInView:self.view];
NSLog(#"Ended Aft: %d" #"-" #"%d", (int)startLocation.x, (int)startLocation.y);
}
}
In fact, the instruction:
recognizer.view.center = CGPointMake(startLocation.x, startLocation.y);
give a wrong effect. Someone know why?
A couple of thoughts:
I'd suggest making sure you capture startLocation before you do any changing of the center.
You're using the location of the user's touch for startLocation. You really should initialize this with the center of the recognizer.view. It's exceedingly unlikely that the user started their gesture precisely in the center of the button. And as a result, you're unlikely to return back at the original location.
Somewhat unrelated, but:
You don't need to use CGMakePoint when resetting the center of recognizer.view in the UIGestureRecognizerStateEnded clause. You can use CGPointMake if you really want, but it's unnecessary. You can just use startLocation, if you want.
You might want to animate the returning of the view back to that startLocation. It's jarring to have it immediately go there.
As an aside, if you've saved startLocation, you don't need to continually reset the translation. Just use startLocation plus translation. Seems more clear to me, but clearly that's subjective.
I personally think NSStringFromCGPoint is very useful when logging CGPoint structures.
So, I'd suggest:
- (IBAction)handlePan:(UIPanGestureRecognizer *)recognizer
{
static CGPoint startLocation;
if (recognizer.state == UIGestureRecognizerStateBegan)
{
startLocation = recognizer.view.center;
NSLog(#"Began: %#", NSStringFromCGPoint(startLocation));
}
CGPoint translation = [recognizer translationInView:self.view];
recognizer.view.center = CGPointMake(startLocation.x + translation.x,
startLocation.y + translation.y);
if (recognizer.state == UIGestureRecognizerStateEnded)
{
NSLog(#"Ended Bef: %#", NSStringFromCGPoint(startLocation));
[UIView animateWithDuration:0.25
animations:^{
recognizer.view.center = startLocation;
}];
CGPoint finalLocation = [recognizer locationInView:self.view];
NSLog(#"Ended Aft: %#", NSStringFromCGPoint(finalLocation));
}
}
Related
So I have a view with an UITableView on which I am able to add some objects (they come from my nib: SelectPostIt.xib).
These objects are draggable and what I want to do later is, when I'll drag then drop the object on a row of the TableView , it will add the object into the good row etc.
So I thought about many solutions and the one who seems to me the best is to catch the last coordinates of where I dropped my finger (the rest of the problem is another story :') ).
Here's my question, do I need to add something in my method who handle the dragNdrop of my object to know where I dropped it?
Here's my method:
-(IBAction)handlePan:(UIPanGestureRecognizer *)recognizer{
CGPoint translation = [recognizer translationInView:self];
recognizer.view.center = CGPointMake(recognizer.view.center.x + translation.x, recognizer.view.center.y + translation.y);
[recognizer setTranslation:CGPointMake(0, 0) inView:self]; }
Every help will be welcome, thanks in advance!
Check for the state property of UIGestureRecognizer, if its UIGestureRecognizerStateEnded that means your panning has been ended, so you can choose that point of location as drop point.
-(IBAction)handlePan:(UIPanGestureRecognizer *)recognizer{
CGPoint translation = [recognizer translationInView:self];
recognizer.view.center = CGPointMake(recognizer.view.center.x + translation.x, recognizer.view.center.y + translation.y);
if(recognizer.state == UIGestureRecognizerStateEnded){
// Just take the Coordintate
CGPoint centerPointOfView = [recognizer locationInView:self.view];
NSLog(#"X - %f, Y - %f",centerPointOfView.x,centerPointOfView.y);
}
[recognizer setTranslation:CGPointMake(0, 0) inView:self];
}
I would like to know if there isn't any method which will allow me to simulate a touch/click/pressure (call it as you want) on iOS.
I don't know if I have something to add about this... Except that I'm coding with Objective-c.
Every help will be appreciated, thanks in advance!
EDIT:
Here is the method that allow me to have the coordinates of the case that I've selected (it show me in the log) :
- (void)collectionViewTableLayoutManager:(DRCollectionViewTableLayoutManager *)manager collectionView:(UICollectionView *)collectionView didSelectCellAtRow:(NSUInteger)row column:(NSUInteger)column indexPath:(NSIndexPath *)indexPath
{
NSLog(#"SELECTED: %ld.%ld / %ld.%ld", (long)indexPath.section, (long)indexPath.row, (long)row, (long)column);
}
Here is my method who handle the dragNdrop of my PostIt (see in the comments for more info):
-(IBAction)handlePan:(UIPanGestureRecognizer *)recognizer{
CGPoint translation = [recognizer translationInView:self];
recognizer.view.center = CGPointMake(recognizer.view.center.x + translation.x, recognizer.view.center.y + translation.y);
//Here to know the coordinates of the drop
if(recognizer.state == UIGestureRecognizerStateEnded){
CGPoint centerPointOfView = [recognizer locationInView:self.superview];
NSLog(#"X - %f, Y - %f",centerPointOfView.x,centerPointOfView.y);
}
[recognizer setTranslation:CGPointMake(0, 0) inView:self];
}
So here is how I solved my problem. Initially, the method who handle the postIt's dragNdrop was in the postIt.m . So I moved it into my viewController.m . Now, from this method, I'm able to pick up the CollectionView of my viewController and "simulate" a click.
Here is how my new method looks like:
-(IBAction)handlePan:(UIPanGestureRecognizer *)recognizer{
CGPoint translation = [recognizer translationInView:self.view];
recognizer.view.center = CGPointMake(recognizer.view.center.x + translation.x, recognizer.view.center.y + translation.y);
//the coordinates of the drop
if(recognizer.state == UIGestureRecognizerStateEnded){
CGPoint centerPointOfView = [recognizer locationInView:self.view];
NSLog(#"X - %f, Y - %f",centerPointOfView.x,centerPointOfView.y);
//Here is how I pick up the cell where the post it has been dropped
[_collectionView cellForItemAtIndexPath:[_collectionView indexPathForItemAtPoint:centerPointOfView]];
NSIndexPath *indexPath =[_collectionView indexPathForItemAtPoint:centerPointOfView];
//some log tests
NSLog(#"SELECTED: %ld.%ld ", (long)indexPath.section, (long)indexPath.row);
}
[recognizer setTranslation:CGPointMake(0, 0) inView:self.view];
}
I'm trying to track the horizontal distance that a user has swiped using a UIPanGestureRecognizer, but I'm having difficulty interpreting the results. Here is the code that I am using:
- (IBAction)handlePan:(UIPanGestureRecognizer *)recognizer {
CGPoint startLocation;
if (recognizer.state == UIGestureRecognizerStateBegan) {
startLocation = [recognizer locationInView:self.view];
}
if (recognizer.state == UIGestureRecognizerStateEnded) {
CGPoint stopLocation = [recognizer locationInView:self.view];
CGFloat dx = stopLocation.x - startLocation.x;
NSLog(#"dx: %f", dx);
}
}
If I swipe left-to-right, I get output something like this:
dx: 50328911327402404790403072.000000
My screen is only 320 pixels wide, so my end result cannot be greater than 320. Is there a problem with my code or am I just interpreting this number incorrectly? How can I get this value stated in pixels? Thanks!
startLocation doesn't persist after handlePan: returns, so you're getting garbage.
Either declare startLocation as static or save it in an instance variable / property.
You can use UIPanGestureRecognizer as below:-
CGPoint translatedPoint = [(UIPanGestureRecognizer*)sender translationInView:self.view];
if ([(UIPanGestureRecognizer*)sender state] == UIGestureRecognizerStateBegan) {
firstX = [[sender view] center].x;
firstY = [[sender view] center].y;
}
translatedPoint = CGPointMake(firstX+translatedPoint.x, firstY);
[[sender view] setCenter:translatedPoint];
if ([(UIPanGestureRecognizer*)sender state] == UIGestureRecognizerStateEnded) {
CGFloat velocityX = (0.2*[(UIPanGestureRecognizer*)sender velocityInView:self.view].x);
CGFloat finalX = translatedPoint.x + velocityX;
CGFloat finalY = firstY;
I have a scrollView with some UIViews as subviews that I drag around. The problem is that the subviews is rather small, and when dragging them, you can't see them because the finger is in the way.
How do I offset the view a little bit upwards while dragging?
Thanks
if (recognizer.state == UIGestureRecognizerStateChanged)
{
CGPoint translation = [recognizer translationInView:self];
draggingView.center = CGPointMake(draggingView.center.x + translation.x,
draggingView.center.y + translation.y);
[recognizer setTranslation:CGPointZero inView:self];
}
Try following code
CGPoint touchPoint = [recognizer locationInView:self];
try changing touchPoint
I have a UIView object that can be dragged around using UIPanGestureRecognizer, but I only want it to be able to move up 3/4 of the screen. I don't want to it be clipped, but to get to a certain point and not be able to be dragged any further. What I have so far allows it to only move on the Y axis (which is desired).
- (IBAction)panGesture:(UIPanGestureRecognizer *)recognizer
{
CGPoint translation = [recognizer translationInView:self.view];
recognizer.view.center = CGPointMake(recognizer.view.center.x,
recognizer.view.center.y + translation.y);
[recognizer setTranslation:CGPointMake(0, 0) inView:self.view];
}
Thanks for any help.
So just check whether the new Y coordinate would be too small. Don't change the view if it would be too small:
- (IBAction)panGesture:(UIPanGestureRecognizer *)recognizer
{
CGPoint translation = [recognizer translationInView:self.view];
[recognizer setTranslation:CGPointMake(0, 0) inView:self.view];
CGPoint center = recognizer.view.center;
center.y += translation.y;
if (center.y < self.yMin)
return;
recognizer.view.center = center;
}
Its work fine for me.
CGPoint currentTouchPoint = [gesture translationInView:self.bottomView];
if (fabsf(currentTouchPoint.x) > fabsf(currentTouchPoint.y)) {
// avoid horizontal movement of pan geuture.
return;
}
thanks,
Naveen Shan
Implement the following gesture delegate and check your condition inside it. Returning YES or NO from this delegate will make the gesture active and inactive.
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch;