1

A UIViewController is called when a user touches an image on a UITableViewCell. It is called using modalViewController. On this modalViewController is a UIScrollView, with another UIImageView in the middle, that fetches an image using NSDictionary (passed from the UITableViewCell).

Now, what I wanted to achieve was the ability for the user to drag the image vertically only, such that dragging and releasing a little would cause the image to return to the center with animation. If the user drags it to the extremes, the entire UIScrollView is dismissed and the user returns to the UITableView. I used the following code. The issue here is, and as my name suggests, this code is crude. Is there an elegant way of doing this, without the need of so much calculation?

BOOL imageMoved=NO;

- (void) touchesMoved:(NSSet *)touches
        withEvent:(UIEvent *)event {
UITouch * touch = [touches anyObject];
CGPoint pos = [touch locationInView: [UIApplication sharedApplication].keyWindow];

CGRect imageRect = _photoImageView.frame;//_photoImageView object of UIImageView
CGFloat imageHeight = imageRect.size.height;//getting height of the image
CGFloat imageTop=240-imageHeight/2;
CGFloat imageBottom=imageTop+imageHeight;//setting boundaries for getting coordinates of touch.
// Touches that originate above imageTop and below imageBottom are ignored(until touch reaches UIImageView)

if (pos.y>50&&pos.y<430&&pos.y>=imageTop&&pos.y<=imageBottom){//extremes are defined as top and bottom 50 pixels.
    imagedMoved=YES;//BOOL variable to hold if the image was dragged or not
    NSLog(@"%f", pos.y);
    [UIView setAnimationDelay:0];

    [UIView animateWithDuration:0.4

                     animations:^{_photoImageView.frame=CGRectMake(0,pos.y-imageHeight/2,320,200);}

                     completion:^(BOOL finished){ }];
}
}

- (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {

UITouch * touch = [touches anyObject];
CGPoint pos = [touch locationInView: [UIApplication sharedApplication].keyWindow];

if (pos.y>50&&pos.y<430){//if touch has NOT ended in the extreme 50 pixels vertically
    [UIView setAnimationDelay:0];//restoring UIImageView to original center with animation

    [UIView animateWithDuration:0.4

                     animations:^{_photoImageView.frame=CGRectMake(0,140,320,200);}

                     completion:^(BOOL finished){ }];
imagedMoved=NO;//prepare BOOL value for next touch event
}

else if(pos.y<50||pos.y>430)
    if(imagedMoved)
    [self.photoBrowser exit] ;//exit function(imported from UIScrollViewController) dismisses
                  //modalView using [self dismissViewControllerAnimated:YES completion:nil];
}

All code here is a modification onto a customized copy of UITapView in MWPhotoBrowser.

jszumski
  • 7,430
  • 11
  • 40
  • 53
n00bProgrammer
  • 4,261
  • 3
  • 32
  • 60
  • Why are you using an imageMoved BOOL value? If the image is centered on the screen and you don't move it, its pos.y will always be >50 && <430, so the if(imageMoved) check is useless. Have you thought about using UIPanGestureRecognizer instead of raw touch events? – Alessandro Orrù May 01 '13 at 19:34
  • Unless i use this BOOL variable, the modal dismisses even if the user does not drag the image, and clicks in the extremes(top and bottom 50 pixels). Hence it is necessary. – n00bProgrammer May 04 '13 at 05:50
  • I'm sorry. I haven't had time to integrate this module. Will let you know as soon as i get to this one. :) – n00bProgrammer May 11 '13 at 05:57

1 Answers1

1

Yo, here is a much easier way to do this, more or less an example of what Alessandro stated. I'm not finding the top of the screen but I'm giving the illusion of it.

BCViewController.h

#import <UIKit/UIKit.h>

@interface BCViewController : UIViewController <UIScrollViewDelegate>
@property (weak, nonatomic) IBOutlet UIScrollView *svScroller;
@property (weak, nonatomic) IBOutlet UIImageView *ivFish;

@end




#import "BCViewController.h"

@interface BCViewController (){
   UIPanGestureRecognizer *_panGestureRecognizer;
   CGPoint                 _fishOrigin;
}

@end

@implementation BCViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
   self.svScroller.delegate = self;
   [self.svScroller setContentSize:self.view.frame.size];
   self.svScroller.translatesAutoresizingMaskIntoConstraints = NO;
   self.ivFish.userInteractionEnabled = YES;

   _panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePanFrom:)];
   [self.ivFish addGestureRecognizer:_panGestureRecognizer];

   _fishOrigin = self.ivFish.center;

   NSLog(@"center %f", self.ivFish.center.x);
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

-(void)handlePanFrom:(UIPanGestureRecognizer *)recognizer{
   // if you want it but not used
   CGPoint translation = [recognizer translationInView:recognizer.view];
   // if you want it but not used
   CGPoint velocity    = [recognizer velocityInView:recognizer.view];
   CGPoint tempPoint;


if (recognizer.state == UIGestureRecognizerStateBegan) {

} else if (recognizer.state == UIGestureRecognizerStateChanged) {
    tempPoint = [recognizer locationInView:self.view];

    self.ivFish.center = CGPointMake(175.5, tempPoint.y);

} else if (recognizer.state == UIGestureRecognizerStateEnded) {
    CGPoint tempPoint;
    tempPoint = [recognizer locationInView:self.view];

    if (tempPoint.y < 132) {
        [UIView animateWithDuration:.3 delay:0
                            options:UIViewAnimationOptionCurveEaseOut
                         animations:^ {
                             [self.navigationController popViewControllerAnimated:TRUE];
                         }
                         completion:NULL];
    } else {
        [UIView animateWithDuration:.3 delay:0
                            options:UIViewAnimationOptionCurveEaseOut
                         animations:^ {
                             self.ivFish.center = _fishOrigin;
                         }
                         completion:NULL];
    }
}
}
Ben Coffman
  • 1,750
  • 1
  • 18
  • 26