今天给大家详细介绍一下IOS手势的用法,最后给大家分享一点干货,《基于手势识别的侧滑展开菜单栏》,这个功能在开发中会经常用到,是非常重要的。

一、UIGestureRecognizer介绍




手势在ios经常用到,可以说是非常重要的存在,在之前,大部分都是通过touch方法来进行手势的判定,但是在ios系统3.2之后,添加了UIGestureRecongnizer抽象类,抽象出了几个子类




UITapGestureRecognizer  (点)

UIPinchGestureRecognizer (缩放)

UIRotationGestureRecognizer (旋转)

UISwipeGestureRecognizer (轻扫)

UIPanGestureRecognizer (拖动)

UILongPressGestureRecognizer (长按)




这些手势都很简单,基本上明白一个的用法,其他的也就都明白了,所以我们今天就以 拖动为例,给大家做一个侧滑展开菜单栏



我们先来了解一下这些手势的基本用法



1、缩放手势


UIPinchGestureRecognizer *pinchGestureRecognizer = [[UIPinchGestureRecognizer alloc]
                                                        initWithTarget:self
                                                        action:@selector(handlePinch:)];
[imageView addGestureRecognizer:pinchGestureRecognizer];



回调方法



- (void) handlePinch:(UIPinchGestureRecognizer*) recognizer
{
    recognizer.view.transform = CGAffineTransformScale(recognizer.view.transform, recognizer.scale, recognizer.scale);
    recognizer.scale = 1;
}



2.拖动手势


UIPanGestureRecognizer * panRecognizer = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(handlePan:)];
    //添加手势到 tabBarController.view
    [tabBarController.view addGestureRecognizer:panRecognizer];



回调方法


- (void) 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:CGPointZero inView:self.view];
    
}





3.旋转手势



/**
 *  处理旋转手势
 *
 *  @param recognizer 旋转手势识别器对象实例
 */
- (void)handleRotation:(UIRotationGestureRecognizer *)recognizer {
    recognizer.view.transform = CGAffineTransformRotate(recognizer.view.transform, recognizer.rotation);
    recognizer.rotation = 0.0;
}






大家需要注意的是,一个手势只能对应一个View, 但是一个View可以有多个手势


二、拖动手势实现侧滑菜单栏





1.新建工程





文件结构如图所示:




iOS 上拉边界下拉出现空白怎么解决_iOS手势





2.创建MenuView



在ViewController里面创建一个menuView,作为最底层



- (void)viewDidLoad {
    [super viewDidLoad];
    
    //新建一个菜单栏放在最底部,设置大小,这样就可以在拖动上层界面的时候,将底下的菜单栏漏出来
    UIView * menuView = [[UIView alloc] init];
    [self.view addSubview:menuView];
    menuView.frame = CGRectMake(0, 0, self.view.frame.size.width * 0.8, self.view.frame.size.height);
    //设置菜单栏的颜色为红色
    menuView.backgroundColor = [UIColor redColor];
    
    
    CXRSplitController * splitViewController = [[CXRSplitController alloc] init];
    //将splitViewController的控制器和根视图都交由跟控制器进行管理
    [self addChildViewController:splitViewController];
    [self.view addSubview:splitViewController.view];
    
    
}


3.创建CXRSplitController


CXRSplitController 作为 tabBarController 的存在,拖动手势在响应的时候,其实拖动的是CXRSplitController ,所以我们需要在上面添加一个UITabBarController,并且添加三个页面


//新建一个tabBarController
    UITabBarController * tabBarController = [[UITabBarController alloc] init];
    //将tabBarController交给 CXRSplitController 进行管理
    [self addChildViewController:tabBarController];
    [self.view addSubview:tabBarController.view];
    
    self.tabBarController = tabBarController;
    
    [tabBarController.tabBar setBackgroundImage:[UIImage imageNamed:@"tabbar_bg"]];
    //给tabBarController 添加三个viewController
    UIViewController * mainController = [[UIViewController alloc] init];
    [self setItemImageWithController:mainController image:@"tab_me_nor" selectImage:@"tab_me_press" title:@"主页"];
    mainController.view.backgroundColor = [UIColor colorWithRed:0.980 green:0.765 blue:0.620 alpha:1.000];
    UIViewController * messageController = [[UIViewController alloc] init];
    [self setItemImageWithController:messageController image:@"tab_recent_nor" selectImage:@"tab_recent_press" title:@"消息"];
    messageController.view.backgroundColor = [UIColor colorWithRed:0.949 green:0.525 blue:0.537 alpha:1.000];
    UIViewController *dynamicController = [[UIViewController alloc] init];
    [self setItemImageWithController:dynamicController image:@"tab_qworld_nor" selectImage:@"tab_qworld_press" title:@"动态"];
    dynamicController.view.backgroundColor = [UIColor colorWithRed:0.847 green:0.522 blue:0.702 alpha:1.000];


设置图片标题的方法,同时把每一个页面作为导航栏的根视图


- (void)setItemImageWithController:(UIViewController *)viewCotroller image:(NSString *)image selectImage:(NSString *)selectImage title:(NSString *)title {
    
    viewCotroller.title = title;
    
    
    
    viewCotroller.tabBarItem.image = [[UIImage imageNamed:image] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
    
    viewCotroller.tabBarItem.selectedImage = [[UIImage imageNamed:selectImage] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
    
#pragma mark - 把 UINavigationController 添加到TabBarController 进行管理
    
    UINavigationController * navController = [[UINavigationController alloc]initWithRootViewController:viewCotroller];
    
    
    [self.tabBarController addChildViewController:navController];
}


到这里,我们的基本框架也就搭建起来了,这也是国内主流APP的结构(可以参照qq)



4.添加手势到tabBarController


UIPanGestureRecognizer * panRecognizer = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(handlePan:)];
    //添加手势到 tabBarController.view
    [tabBarController.view addGestureRecognizer:panRecognizer];


5.实现收拾的回调方法



- (void)handlePan:(UIPanGestureRecognizer *)recognizer {
    
    CGPoint point = [recognizer translationInView:self.tabBarController.view];
    recognizer.view.center = CGPointMake(recognizer.view.center.x + point.x, recognizer.view.center.y);
    CGFloat viewX = recognizer.view.frame.origin.x;
    CGFloat viewY = recognizer.view.frame.origin.y;
    
    recognizer.view.frame = CGRectMake(viewX + point.x, viewY, recognizer.view.frame.size.width, 
                            recognizer.view.frame.size.height);
    
    [recognizer setTranslation:CGPointZero inView:self.tabBarController.view];
}




运行一下,是不是可以拖动了,大家就会发现问题了,我可以任意拖动界面,都超出边界了还能够继续拖动,我们只需要他拖动部分,所以我们需要给他加一个界限



- (void)handlePan:(UIPanGestureRecognizer *)recognizer {
    
    CGPoint point = [recognizer translationInView:self.tabBarController.view];
    recognizer.view.center = CGPointMake(recognizer.view.center.x + point.x, recognizer.view.center.y);
    CGFloat viewX = recognizer.view.frame.origin.x;
    CGFloat viewY = recognizer.view.frame.origin.y;
    
   
    if (viewX <= 0) {
        
        recognizer.view.frame = CGRectMake(0, viewY, recognizer.view.frame.size.width, recognizer.view.frame.size.height);
    }else if (viewX >= self.view.frame.size.width * 0.8) {
        
        recognizer.view.frame = CGRectMake(self.view.frame.size.width * 0.8, viewY, recognizer.view.frame.size.width, recognizer.view.frame.size.height);
    }else {
        recognizer.view.frame = CGRectMake(viewX + point.x, viewY, recognizer.view.frame.size.width, recognizer.view.frame.size.height);
        
    }

    
    if (recognizer.state == UIGestureRecognizerStateEnded) {
        
   
        if (viewX < 120) {
            [UIView animateWithDuration:0.5 animations:^{
                recognizer.view.frame = CGRectMake(0, viewY, recognizer.view.frame.size.width, recognizer.view.frame.size.height);
            }];
            
        }
        if (viewX > 120) {
            [UIView animateWithDuration:0.5 animations:^{
                recognizer.view.frame = CGRectMake(self.view.frame.size.width * 0.8, viewY, recognizer.view.frame.size.width, recognizer.view.frame.size.height);
            }];
        }
    }
    
    [recognizer setTranslation:CGPointZero inView:self.tabBarController.view];
}


这样,就可以了,完美运行,下面我把代码给大家,大家可以尝试一下用轻扫手势侧滑出菜单栏,看看两者直接有什么区别



代码示例