简单抽屉效果的实现

就目前大部分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. 黑马程序员——Foundation中的OC结构体

    <span style="font-size:14px">------<a target="_blank" href="http:/ ...

  2. 剑指offer

    今天完成了剑指offer上的66道编程题,感觉自己还是很多代码实现能力和算法积累都还不够!还需要继续联系,坚持自己独立写代码实现. 最后将今天的两道题目奉上,都有异曲同工之妙: 矩阵中的路径: #in ...

  3. 回调函数与DOM事件

    原文:http://dean.edwards.name/weblog/2009/03/callbacks-vs-events/ 先看如下代码: document.addEventListener(&q ...

  4. 上传控件swfupload的使用笔记

    1.下载下来的官方domo里不同的例子里会引入各自的JS,注意区分.可以直接拿官方例子来改成自己想要的例子. 2.注意PHP配置文件里也有最大上传文件限制,如果文件太大会上传不成功. 3.如果有问题可 ...

  5. Java基础 —— Java常用类

    Java常用类: java.lang包: java.lang.Object类: hashcode()方法:返回一段整型的哈希码,代表地址. toString()方法:返回父类名+"@&quo ...

  6. freetds相关

    什么是FreeTDS  简单的说FreeTDS是一个程序库,可以实现在Linux系统下访问微软的SQL数据库! FreeTDS 是一个开源(如果你喜欢可以称为自由)的程序库,是TDS(表列数据流 )协 ...

  7. 【转】Hive学习路线图

    原文博客出自于:http://blog.fens.me/hadoop-hive-roadmap/ 感谢! Hive学习路线图 Hadoop家族系列文章,主要介绍Hadoop家族产品,常用的项目包括Ha ...

  8. [原创]Devexpress XtraReports 系列 4 创建多栏报表

    昨天我们完成了 [原创]Devexpress XtraReports 系列 3 创建主从报表 今天我们继续学习新的一种报表模式:多栏报表.(Demo源码,数据库最后附上) 或许很多人会问什么是多栏报表 ...

  9. V7承保 bug代码

    v7 bug1

  10. ubuntu 64位系统下加速Android模拟器

    安装KVM: sudo apt-get install qemu-kvm libvirt-bin ubuntu-vm-builder bridge-utils 在Postfix Configurati ...