Search code examples
iosios5uigesturerecognizeruipangesturerecognizeruiswipegesturerecognizer

How to realize the same combination of pan/swipe effect as in navigating between homescreens on the iPhone?


On the iPhone you can switch between different home screens in three different ways.

  1. You can swipe to the left or to the right and the next respectively next screen will be animated in.

  2. You touch the screen and without lifting the finger you drag the screen to the right or to the left. After passing critical point (which is a distance more then halve the screen) the next homescreen is animated in when you lift your finger.

  3. You touch the screen and without lifting the finger you drag the screen a little, if you want you can stop dragging but still don't left the finger. And you can accelerate to the left or right on a relatively short distance and it will animate to the respective screen to the left or right.

If we mutual exclusively look at the points 1 and 2, we find them trivial to implement. It's just a UISwipeGuestureRecognizer for point 1. and a UIPanGuestureRecognizerfor 2.

Combining 1 and 2 them seems somehow not so trivial, since the swiping seems to dominate (I tried to combine them with - (void)requireGestureRecognizerToFail:(UIGestureRecognizer *)otherGestureRecognizer). To trigger the pan I had to lay my finger on the screen and drag very very soft to not trigger the swipe.

Not to speak of point three as an addition. This seems totally out of order for my state of knowledge.

Any advice around here? Thank you very much in advance. If more information is needed to solve this question I will gladly deliver it.


Solution

  • The home screen is just an UIScrollView with UIPageControl It's that easy :)

    Example :

    // MyViewController.h
    @interface MyViewController : UIViewController <UIScrollViewDelegate> {
        UIScrollView *_scrollView;
        UIPageControl *_pageControl;
    }
    
    // MyViewController.m
    // in your viewDidLoad method
    int numberOfPages = 3;
    _scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width,
                                                                     self.view.frame.size.height)];
     [_scrollView setContentSize:CGSizeMake(numberOfPages*_scrollView.frame.size.width, _scrollView.frame.size.height)];
     [_scrollView setPagingEnabled:YES];
     [_scrollView setShowsHorizontalScrollIndicator:NO];
     [_scrollView setDelegate:self];
     [self.view addSubview:_scrollView];
    
     _pageControl = [[UIPageControl alloc] initWithFrame:CGRectMake(0, _scrollView.frame.size.height-30, _scrollView.frame.size.width, 20)];
     [_pageControl setNumberOfPages:numberOfPages];
     [_pageControl setCurrentPage:0];
     [self.view addSubview:_pageControl];
    
    for (int i=0; i<numberOfPages; i++) {
       CGRect frame = _scrollView.frame;
       frame.origin.x = frame.size.width * i;
       frame.origin.y = 0;
       UIView *view = [UIView alloc] initWithFrame:frame];
       //Setup your view     
       [_scrollView addSubview:view];
    }
    

    If you want to execute specific method regarding current view displayed, use the scrollViewDidScroll: method (for example to load content from database)

    - (void)scrollViewDidScroll:(UIScrollView *)sender {
        CGFloat pageWidth = _scrollView.frame.size.width;
        int page = floor((_scrollView.contentOffset.x - pageWidth / 2) / pageWidth) + 1;
        _pageControl.currentPage = page;
    
        //do whatever you want..
    }
    

    It's just an example to show you how you could do. If you're using database or if each view is different you should proceed differently to setup your views or retrieve data but the logic would be the same...