简单抽屉效果的实现

就目前大部分App来说基本上都有关于抽屉效果的实现,比如QQ/微信等。所以,今天我们就来简单的实现一下。当然如果你想你的效果更好或者是封装成一个到哪里都能用的工具类,那就还需要下一些功夫了,我们这里知识简单的介绍怎么去实现,不过一般我们开发都是找别人做好的,也没必要烂肺时间,除非你真的是大牛或者闲的蛋疼。

其实关于抽屉效果就是界面有三个View,其实一个主View其他两个分别是左边和右边的View,我们分别为他们添加手势,实现左右滑动显示对应的View。

一:所以,首先我们需要在头文件中定义三个View的属性,来给外界调用,实现设置对应的属性和效果:

 @property (nonatomic, weak, readonly) UIView *mainV;

 @property (nonatomic, weak, readonly) UIView *leftV;

 @property (nonatomic, weak, readonly) UIView *rightV;

二:然后在实现文件中定义对应的宏,后面要用到:

 // @"frame"

 #define XMGkeyPath(objc, keyPath) @(((void)objc.keyPath, #keyPath))

 // 在宏里面如果在参数前添加了#,就会把参数变成C语言字符串

 // 获取屏幕的宽度
 #define screenW [UIScreen mainScreen].bounds.size.width

 // 获取屏幕的高度
 #define screenH [UIScreen mainScreen].bounds.size.height

相信这里有一个宏你们一定很陌生,由于本章主要介绍抽屉效果,宏不是本章的内容,如果你真的想了解或者不能看懂上面的含义清看大神王魏分享的:

宏定义的黑魔法 - 宏菜鸟起飞手册

三:在ViewDidLoad中调用下面这个方法实现三个View的创建:

 // 添加所有的子控件
 - (void)setUpAllChildView
 {
     // left
     UIView *leftV = [[UIView alloc] initWithFrame:self.view.bounds];
     leftV.backgroundColor = [UIColor greenColor];
     [self.view addSubview:leftV];
     _leftV = leftV;

     // right
     UIView *rightV = [[UIView alloc] initWithFrame:self.view.bounds];
     rightV.backgroundColor = [UIColor blueColor];
     [self.view addSubview:rightV];
     _rightV = rightV;

     // main
     UIView *mainV = [[UIView alloc] initWithFrame:self.view.bounds];
     mainV.backgroundColor = [UIColor redColor];
     [self.view addSubview:mainV];
     _mainV = mainV;
 }

四:在ViewDidLoad中为界面添加滑动手势:

     // 添加拖拽手势
     UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(pan:)];

     [_mainV addGestureRecognizer:pan];
 

并且使用KVO监听frame的变化:

注意:这里是整篇文章中最重的地方,也是相对最难的地方,主要设置到的一些计算

     // KVO作用:时刻监听某个对象的某个属性的改变
     // _main frame属性的改变
     // Observer:观察者
     // KeyPath:监听的属性
     // NSKeyValueObservingOptionNew:表示监听新值的改变
     [_mainV addObserver:self forKeyPath:XMGkeyPath(_mainV, frame) options:NSKeyValueObservingOptionNew context:nil];
     

五:实现滑动手势的方法,和监听属性变化的方法:

 #define targetR 300

 #define targetL -200

 - (void)pan:(UIPanGestureRecognizer *)pan
 {
     // 获取手势的偏移量
     CGPoint transP = [pan translationInView:_mainV];
     // 获取x轴的偏移量,相对于上一次
     CGFloat offsetX = transP.x;
     // 修改最新的main.frame,
     _mainV.frame = [self frameWithOffsetX:offsetX];
     // 复位
     [pan setTranslation:CGPointZero inView:_mainV];
     // 判断下当前手指有没有抬起,表示手势结束
     if (pan.state == UIGestureRecognizerStateEnded) { // 手指抬起,定位
         // x>屏幕的一半,定位到右边某个位置
         CGFloat target = ;
         if (_mainV.frame.origin.x > screenW * 0.5) {
             target = targetR;
         }else if (CGRectGetMaxX(_mainV.frame) < screenW * 0.5){
             // 最大的x < 屏幕一半的时候,定义到左边某个位置
             target = targetL;
         }
         // 获取x轴的偏移量
         CGFloat offsetX = target - _mainV.frame.origin.x;
         [UIView animateWithDuration:0.25 animations:^{
             _mainV.frame = [self frameWithOffsetX:offsetX];
         }];
     }
 }

 #define XMGMaxY 100

 // 给定一个x轴的偏移量计算下最新main的frame
 - (CGRect)frameWithOffsetX:(CGFloat)offsetX
 {

     // 获取当前main的frame
     CGRect frame = _mainV.frame;

     // 计算当前的x,y,w,h
     // 获取最新的x
     CGFloat x = frame.origin.x + offsetX;

     // 获取最新的y
     CGFloat y = x / screenW * XMGMaxY;

     // 当用户往左边移动的时候,_main.x < 0,y需要增加,为正
     ) {
         y = -y;
     }
     // 获取最新的h
     CGFloat h = screenH -  * y;
     // 获取缩放比例
     CGFloat scale = h / screenH;
     // 获取最新的w
     CGFloat w = screenW * scale;
     return CGRectMake(x, y, w, h);
 }

属性监听方法:

 // 只要监听的属性一改变,就会调用
 - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
 {
     ) { // 往右滑动,显示左边控件,隐藏右边控件
         _rightV.hidden = YES;
     }){ // 往左滑动,显示右边控件
         _rightV.hidden = NO;
     }
 }

注意:还记得我们前面学通知的时候一般用完都会讲通知移除,这里的KVO也是同样,所以我就提前做了,方便后面忘了(实际开发中也是一样的)

 // 注意:当对象被销毁的时候,一定要注意移除观察者
 - (void)dealloc
 {
     // 移除观察者
     [_mainV removeObserver:self forKeyPath:XMGkeyPath(_mainV, frame)];
 }

六:为界面添加一个Tap手势,为了实现点一下屏幕还原

      // 给控制器的view添加一个点按

      UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tap)];

      [self.view addGestureRecognizer:tap];

还原方法的实现:

 - (void)tap
 {
     ) {
         // 把_mainV还原最开始的位置

         [UIView animateWithDuration:0.25 animations:^{
             _mainV.frame = self.view.bounds;

         }];

     }
 }

下面就是最重的效果:

     

iOS开发——实用技术OC篇&简单抽屉效果的实现的更多相关文章

  1. iOS开发——实用技术OC篇&单例模式的实实现(ACR&MRC)

    单例模式的实实现(ACR&MRC) 在iOS开发中单例模式是一种非常常见的模式,虽然我们自己实现的比较少,但是,系统却提供了不少的到来模式给我们用,比如最常见的UIApplication,No ...

  2. iOS开发——实用技术OC篇&8行代码教你搞定导航控制器全屏滑动返回效果

    8行代码教你搞定导航控制器全屏滑动返回效果 前言 如果自定了导航控制器的自控制器的leftBarButtonItem,可能会引发边缘滑动pop效果的失灵,是由于 self.interactivePop ...

  3. ios开发——实用技术OC篇&地图与定位

    地图与定位 11.1 iOS定位服务 11.2 iOS地图 11.3 Web地图 1 iOS定位服务 iOS中有三个定位服务组件: Wifi定位,通过查询一个Wifi路由器的地理位置的信息.比较省电, ...

  4. iOS开发——实用技术OC篇&事件处理详解

    事件处理详解 一:事件处理 事件处理常见属性: 事件类型 @property(nonatomic,readonly) UIEventType     type; @property(nonatomic ...

  5. ios开发——实用技术OC篇》倒计时实现的两种方法

    倒计时实现的两种方法 timeFireMethod函数,timeFireMethod进行倒计时的一些操作,完成时把timer给invalidate掉就ok了,代码如下: secondsCountDow ...

  6. iOS开发——实战OC篇&环境搭建之Xib(玩转UINavigationController与UITabBarController)

    iOS开发——实战OC篇&环境搭建之Xib(玩转UINavigationController与UITabBarController)   前面我们介绍了StoryBoard这个新技术,和纯技术 ...

  7. iOS开发——实战OC篇&环境搭建之纯代码(玩转UINavigationController与UITabBarController)

    iOS开发——实战OC篇&环境搭建之纯代码(玩转UINavigationController与UITabBarController)   这里我们就直接上实例: 一:新建一个项目singleV ...

  8. ios开发——实用技术OC-Swift篇&触摸与手势识别

    iOS开发学习之触摸事件和手势识别   iOS的输入事件 触摸事件 手势识别 手机摇晃 一.iOS的输入事件   触摸事件(滑动.点击) 运动事件(摇一摇.手机倾斜.行走),不需要人为参与的 远程控制 ...

  9. iOS开发——实战OC篇&环境搭建之StoryBoard(玩转UINavigationController与UITabBarController)

      环境搭建之StoryBoard(玩转UINavigationController与UITabBarController)   研究了这么就IOS开发,都没有所处一个像样或者自己忙一点的项目.最近自 ...

随机推荐

  1. stringstream实例

    stringstream的具体作用稍后来总结,这里分享一个实例,从txt文档中读取数据,并对进行处理. #include <iostream> #include <sstream&g ...

  2. mybatis系列-16-spring和mybatis整合

    16.1     整合思路 需要spring通过单例方式管理SqlSessionFactory. spring和mybatis整合生成代理对象,使用SqlSessionFactory创建SqlSess ...

  3. 牛课--C/C++

    引用是除指针外另一个可以产生多态效果的手段. //引用是除指针外另一个可以产生多态效果的手段. #include<iostream> using namespace std; class ...

  4. 从四大音乐APP首页设计对比分析产品方向

    原帖:http://www.ui.cn/detail/63201.html 本文章中作者例举四个音乐APP应用:虾米.网易.百度.QQ首页 1. 推荐内容:作者将四个首页界面划分出官方推荐与个性化推荐 ...

  5. Python:类属性,实例属性,私有属性与静态方法,类方法,实例方法

    From: http://www.cnblogs.com/pengsixiong/p/4823473.html 属性分为实例属性与类属性 方法分为普通方法,类方法,静态方法 一:属性: 尽量把需要用户 ...

  6. VBA

    1.ActiveWorkbook是Application对象的一个属性,表示的是一个active Workbook. 2.Application对象可以获得一些顶级的对象,比如ActiveCell,A ...

  7. HDU1227:Fast Food

    题目链接:Fast Food 题意:一条直线上有n个饭店,问建造k个原料厂(仍旧在商店位置)得到的最小距离 分析:见代码 //一条直线上有n个饭店,问建造k个原料厂(仍旧在商店位置)得到的最小距离 / ...

  8. iconfont阿里妈妈前端小图标使用方法详解

    图标选购网址:http://www.iconfont.cn/ 1.从阿里妈妈网站选购好小图标,加入购物车,下载好文件: 2.把字体文件放入字体(font)文件夹(tff)(woff),(eot) 3. ...

  9. windows平台下安装python的setuptools工具

    到下面的网址下载setuptools-0.6c11.win32-py2.7.exe http://pypi.python.org/pypi/setuptools#files 然后安装setuptool ...

  10. 关于文章“cocos2dx移植android平台-我的血泪史”需要注意事项

    关于文章"cocos2dx移植android平台-我的血泪史"需要注意事项 在上次转载的这篇文章中,按照配置一步一步的下去.发现工程中在Android.mk中有一处错误.直接bui ...