[iOS]iOS中UITabbarController左右滑动切换

iOS中UITabbarController左右滑动切换;UIViewController左右滑动;滑动切换;UITabbarController左右切换


转载请注明出处:http://blog.csdn.net/infant09/article/details/48773281


在经典的带有tabbar的app中,一般是引入一个UITabbarController,再添加多个UIViewController实现的。一般通过点击不同的UITabbarItem,实现不同的UIViewController切换。目前许多经典的app都是这样切换的,比如微信、微博以及iPhone自带的一些应用等等。

有时候也会有特殊的需求,比如要求左右滑动实现UIViewController的切换(例如android版的微信、QQ就可以这样,当然iOS版不这样,个人觉得可能和左右滑动会误操作有关?)。这时候如何实现呢?


思路1:在每个UIViewController中添加Pan手势,实现切换。

原理很简单,即为每个View添加Pan手势,能够左右滑动。当滑动过半的时候,tabbar切换页面。并且当每个ViewController DidAppear后,将左右两边的Controller渲染出来,添加到当前的View中(成为subView)。


下面给出一个例程。

0x00.新建一个project

选择新建一个“Tabbed Application”


0x01.补全storyboard和4个ViewController,并连接

新建出来的project包含一个TabBarController和2和ViewController,再补全两个ViewController即可。修改各个ViewController上的文字和颜色。最后按control键连接TabBarController和ViewController,选择“Relationship Segue”。

0x02.对每个ViewController增加手势

做到左右滑动的关键点,即为每个ViewController的self.view增加一个Pan手势。以SecondViewController为例,在viewDidLoad中添加:

    //添加左右滑动手势pan
    UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)];
    [self.view addGestureRecognizer:pan];

并添加handlePan:方法:

- (void) handlePan:(UIPanGestureRecognizer*)recongizer{
    NSLog(@"UIPanGestureRecognizer");
    
    NSUInteger index = [self.tabBarController selectedIndex];
    
    CGPoint point = [recongizer translationInView:self.view];
    NSLog(@"%f,%f",point.x,point.y);
    
    recongizer.view.center = CGPointMake(recongizer.view.center.x + point.x, recongizer.view.center.y);
    [recongizer setTranslation:CGPointMake(0, 0) inView:self.view];
    
    if (recongizer.state == UIGestureRecognizerStateEnded) {
        if (recongizer.view.center.x < [UIScreen mainScreen].bounds.size.width && recongizer.view.center.x > 0 ) {
            [UIView animateWithDuration:time delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
                recongizer.view.center = CGPointMake([UIScreen mainScreen].bounds.size.width/2 ,[UIScreen mainScreen].bounds.size.height/2);
            }completion:^(BOOL finished) {
                
            }];
        } else if (recongizer.view.center.x <= 0 ){
            [UIView animateWithDuration:time delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
                recongizer.view.center = CGPointMake(-[UIScreen mainScreen].bounds.size.width/2 ,[UIScreen mainScreen].bounds.size.height/2);
            }completion:^(BOOL finished) {
                [self.tabBarController setSelectedIndex:index+1];
                recongizer.view.center = CGPointMake([UIScreen mainScreen].bounds.size.width/2 ,[UIScreen mainScreen].bounds.size.height/2);
            }];
        } else {
            [UIView animateWithDuration:time delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
                recongizer.view.center = CGPointMake([UIScreen mainScreen].bounds.size.width*1.5 ,[UIScreen mainScreen].bounds.size.height/2);
            }completion:^(BOOL finished) {
                [self.tabBarController setSelectedIndex:index-1];
                recongizer.view.center = CGPointMake([UIScreen mainScreen].bounds.size.width/2 ,[UIScreen mainScreen].bounds.size.height/2);
            }];
        }
    }
}

0x03.渲染左右两边的ViewController,添加到当前View中

viewDidAppear中渲染左右两边的ViewController,将其view分别保存为_imageviewLeft和_imageviewRight中。(注意,此处以SecondViewController为例,如果是第一个和最后一个ViewController,要考虑没有更左边和更右边的ViewController了)

 NSUInteger selectedIndex = [self.tabBarController selectedIndex];
    UIViewController* v1 = [self.tabBarController.viewControllers objectAtIndex:selectedIndex-1];
    UIImage* image1 = [self imageByCropping:v1.view toRect:v1.view.bounds];
    _imageviewLeft = [[UIImageView alloc] initWithImage:image1];
    _imageviewLeft.frame = CGRectMake(_imageviewLeft.frame.origin.x - [UIScreen mainScreen].bounds.size.width, _imageviewLeft.frame.origin.y , _imageviewLeft.frame.size.width, _imageviewLeft.frame.size.height);
    [self.view addSubview:_imageviewLeft];
    
    UIViewController* v2 = [self.tabBarController.viewControllers objectAtIndex:selectedIndex+1];
    UIImage* image2 = [self imageByCropping:v2.view toRect:v2.view.bounds];
    _imageviewRight = [[UIImageView alloc] initWithImage:image2];
    _imageviewRight.frame = CGRectMake(_imageviewRight.frame.origin.x + [UIScreen mainScreen].bounds.size.width, 0, _imageviewRight.frame.size.width, _imageviewRight.frame.size.height);
    [self.view addSubview:_imageviewRight];
注意这里面的关键方法imageByCropping
//与pan结合使用 截图方法,图片用来做动画
-(UIImage*)imageByCropping:(UIView*)imageToCrop toRect:(CGRect)rect
{
    CGFloat scale = [[UIScreen mainScreen] scale];
    CGSize pageSize = CGSizeMake(scale*rect.size.width, scale*rect.size.height) ;
    UIGraphicsBeginImageContext(pageSize);
    CGContextScaleCTM(UIGraphicsGetCurrentContext(), scale, scale);
    
    CGContextRef resizedContext =UIGraphicsGetCurrentContext();
    CGContextTranslateCTM(resizedContext,-1*rect.origin.x,-1*rect.origin.y);
    [imageToCrop.layer renderInContext:resizedContext];
    UIImage*imageOriginBackground =UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    imageOriginBackground = [UIImage imageWithCGImage:imageOriginBackground.CGImage scale:scale orientation:UIImageOrientationUp];
    
    return imageOriginBackground;
}

0x04.切换页面后移除subView

在左右移动或者点击tab按钮切换页面后,在当前页面didDisappear里面要清除self.view的左右两个subView。
- (void)viewDidDisappear:(BOOL)animated{
    /********用于移除pan时的左右两边的view********/
    [_imageviewLeft removeFromSuperview];
    [_imageviewRight removeFromSuperview];
    /********用于移除pan时的左右两边的view********/
}


0x05.结束

放一张图和github链接: https://github.com/Caeson/TabbedApplicationWithPan

[iOS]iOS中UITabbarController左右滑动切换_第1张图片




思路2:在UITabbarController中添加pan手势,实现切换。(经测试,不可行)


思路3:使用UIPageViewController,取代UITabbarController。



参考文献:
UITabbarController左右滑动切换标签页 - 自助者天助之的日志 - 网易博客
iphone - iOS: Swipe left/right between tabs possible? - Stack Overflow
UITabBarController 多个页面如何通过滑动来切换?
iOS 手势操作:拖动、捏合、旋转、点按、长按、轻扫、自定义 - KenmuHuang - 博客园
扩展UITabBarController实现循环滑动效果_洪水猛兽_新浪博客

你可能感兴趣的:(iOS)