iOS开发——实用技术OC篇&简单抽屉效果的实现

简单抽屉效果的实现

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

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

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

1 @property (nonatomic, weak, readonly) UIView *mainV;
2
3 @property (nonatomic, weak, readonly) UIView *leftV;
4
5 @property (nonatomic, weak, readonly) UIView *rightV;

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

 1 // @"frame"
 2
 3 #define XMGkeyPath(objc, keyPath) @(((void)objc.keyPath, #keyPath))
 4
 5 // 在宏里面如果在参数前添加了#,就会把参数变成C语言字符串
 6
 7 // 获取屏幕的宽度
 8 #define screenW [UIScreen mainScreen].bounds.size.width
 9
10 // 获取屏幕的高度
11 #define screenH [UIScreen mainScreen].bounds.size.height

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

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

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

 1 // 添加所有的子控件
 2 - (void)setUpAllChildView
 3 {
 4     // left
 5     UIView *leftV = [[UIView alloc] initWithFrame:self.view.bounds];
 6     leftV.backgroundColor = [UIColor greenColor];
 7     [self.view addSubview:leftV];
 8     _leftV = leftV;
 9
10     // right
11     UIView *rightV = [[UIView alloc] initWithFrame:self.view.bounds];
12     rightV.backgroundColor = [UIColor blueColor];
13     [self.view addSubview:rightV];
14     _rightV = rightV;
15
16     // main
17     UIView *mainV = [[UIView alloc] initWithFrame:self.view.bounds];
18     mainV.backgroundColor = [UIColor redColor];
19     [self.view addSubview:mainV];
20     _mainV = mainV;
21 }

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

 1     // 添加拖拽手势
 2     UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(pan:)];
 3
 4     [_mainV addGestureRecognizer:pan];
 5 

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

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

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

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

 1 #define targetR 300
 2
 3 #define targetL -200
 4
 5 - (void)pan:(UIPanGestureRecognizer *)pan
 6 {
 7     // 获取手势的偏移量
 8     CGPoint transP = [pan translationInView:_mainV];
 9     // 获取x轴的偏移量,相对于上一次
10     CGFloat offsetX = transP.x;
11     // 修改最新的main.frame,
12     _mainV.frame = [self frameWithOffsetX:offsetX];
13     // 复位
14     [pan setTranslation:CGPointZero inView:_mainV];
15     // 判断下当前手指有没有抬起,表示手势结束
16     if (pan.state == UIGestureRecognizerStateEnded) { // 手指抬起,定位
17         // x>屏幕的一半,定位到右边某个位置
18         CGFloat target = 0;
19         if (_mainV.frame.origin.x > screenW * 0.5) {
20             target = targetR;
21         }else if (CGRectGetMaxX(_mainV.frame) < screenW * 0.5){
22             // 最大的x < 屏幕一半的时候,定义到左边某个位置
23             target = targetL;
24         }
25         // 获取x轴的偏移量
26         CGFloat offsetX = target - _mainV.frame.origin.x;
27         [UIView animateWithDuration:0.25 animations:^{
28             _mainV.frame = [self frameWithOffsetX:offsetX];
29         }];
30     }
31 }
32
33 #define XMGMaxY 100
34
35 // 给定一个x轴的偏移量计算下最新main的frame
36 - (CGRect)frameWithOffsetX:(CGFloat)offsetX
37 {
38
39
40
41
42     // 获取当前main的frame
43     CGRect frame = _mainV.frame;
44
45     // 计算当前的x,y,w,h
46     // 获取最新的x
47     CGFloat x = frame.origin.x + offsetX;
48
49     // 获取最新的y
50     CGFloat y = x / screenW * XMGMaxY;
51
52     // 当用户往左边移动的时候,_main.x < 0,y需要增加,为正
53     if (frame.origin.x < 0) {
54         y = -y;
55     }
56     // 获取最新的h
57     CGFloat h = screenH - 2 * y;
58     // 获取缩放比例
59     CGFloat scale = h / screenH;
60     // 获取最新的w
61     CGFloat w = screenW * scale;
62     return CGRectMake(x, y, w, h);
63 }

属性监听方法:

1 // 只要监听的属性一改变,就会调用
2 - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
3 {
4     if (_mainV.frame.origin.x > 0) { // 往右滑动,显示左边控件,隐藏右边控件
5         _rightV.hidden = YES;
6     }else if (_mainV.frame.origin.x < 0){ // 往左滑动,显示右边控件
7         _rightV.hidden = NO;
8     }
9 }

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

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

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

1      // 给控制器的view添加一个点按
2
3      UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tap)];
4
5      [self.view addGestureRecognizer:tap];

还原方法的实现:

 1 - (void)tap
 2 {
 3     if (_mainV.frame.origin.x != 0) {
 4         // 把_mainV还原最开始的位置
 5
 6         [UIView animateWithDuration:0.25 animations:^{
 7             _mainV.frame = self.view.bounds;
 8
 9         }];
10
11     }
12 }

下面就是最重的效果:

     

时间: 2024-10-10 05:43:31

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

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

单例模式的实实现(ACR&MRC) 在iOS开发中单例模式是一种非常常见的模式,虽然我们自己实现的比较少,但是,系统却提供了不少的到来模式给我们用,比如最常见的UIApplication,Notification等, 那么这篇文章就简单介绍一下,我们开发中如果想要实现单例模式要怎么去实现! 单例模式顾名思义就是只有一个实例,它确保一个类只有一个实例,并且自行实例化并向整个系统提供这个实例.它经常用来做应用程序级别的共享资源控制.这个模式使用频率非常高,通过一个单例类,可以实现在不同窗口之间传递数

iOS开发——实用技术OC篇&amp;多线程整合

多线程整合 本文知识对iOS开发中多线程的一些知识整合,关于一些概念和技术问题并没有过多的介绍,如果你想了解更多请查看笔者之前写的iOS开发之多线程详解(比较完整):但是有部分涉及到之前文章中没有的技术点和常识,比如加锁的方式,面试相关的,还有一些关于GCD的高级用法,希望你能认真看完,或许可以收获到很多! http://www.cnblogs.com/iCocos/p/4553103.html http://www.cnblogs.com/iCocos/p/4553262.html ??先来看

iOS开发——实用技术OC篇&amp;?Invocation简单介绍

Invocation简单介绍 方法一:运行时方法:(这里在之前的文章定时器的几种方法中说过:www.cnblogs.com/iCocos/p/4694581.html) 1:创建一个签名: NSMethodSignature *singature = [NSMethodSignature signatureWithObjCTypes:"[email protected]:"]; 这里我想如果你仔细的话肯定注意到了:后面的“[email protected]:”,这里是运行时的语法在这里

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

8行代码教你搞定导航控制器全屏滑动返回效果 前言 此次文章,讲述的是导航控制器全屏滑动返回效果,而且代码量非常少,10行内搞定. 效果如图: 如果喜欢我的文章,可以关注我,也可以来小码哥,了解下我们的iOS培训课程.陆续还会有更新ing.... 一.自定义导航控制器 目的:以后需要使用全屏滑动返回功能,就使用自己定义的导航控制器. 二.分析导航控制器侧滑功能 效果:导航控制器默认自带了侧滑功能,当用户在界面的左边滑动的时候,就会有侧滑功能. 系统自带的侧滑效果: 分析: 1.导航控制器的view

iOS开发——实用技术OC篇&amp;CocoaPods简单粗暴

CocoaPods简单粗暴 直接上代码,不要问为什么,照着做就可以,我也是这么做的,具体的细节,请查看相关文档,网上太多! 1:移除ruby镜像 1 $ gem sources --remove https://rubygems.org/ 2:新增淘宝镜像 1 $ gem sources -a http://ruby.taobao.org/ 3:查看列表 1 $ gem sources -l 4:正式安装 1 sudo gem install cocoapods 接下来就是开始使用了. 查看对应

iOS开发——实用技术OC篇&amp;UIWebView与JS的交互

UIWebView与JS的交互 事情的起因还是因为项目需求驱动.折腾了两天,由于之前没有UIWebView与JS交互的经历,并且觉得这次在功能上有一定的创造性,特此留下一点文字,方便日后回顾. 我要实现这样一个需求:按照本地的CSS文件展示一串网络获取的带HTML格式的只有body部分的文本,需要自己拼写完整的HTML.除此之外,还需要禁用获取的HTML文本中自带的 < img > 标签自动加载,并把下载图片的操作放在native端来处理,并通过JS将图片在Cache中的地址返回给UIWebv

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

事件处理详解 一:事件处理 事件处理常见属性: 事件类型 @property(nonatomic,readonly) UIEventType     type; @property(nonatomic,readonly) UIEventSubtype  subtype; 事件产生的时间 @property(nonatomic,readonly) NSTimeInterval  timestamp; 事件传递 - hitTest:withEvent: SWIFT func hitTest(_ po

iOS开发——实用技术OC篇&amp;关于自定义相册删除复活的实现

关于自定义相册删除复活的实现 在这里(http://www.cnblogs.com/iCocos/p/4705585.html)我们提到了. 1:简单的实现了获取系统相册图片并且保存图片到系统相册 2:定义自定义的相册,并且保存到自定义相册 这里久以一个简单的例子实现一个上面的所有功能,并且添加一个很有用的功能实现 App中自定义的相册呗删除之后再次保存相片无法成功 这里使用的是一个系统的库:ALAssetsLibrary 先来看看咱们取得相册中的相片 1 - (void)getAllPhoto

iOS开发——实用技术OC篇&amp;给分类增加属性

给分类增加属性 关于分类的创建这里就不扯了,咱们直接开干 这里以文本看占位文字颜色为例一:简单方式(关键技术:KVC)1.在头文件定义一个属性 1 @property (nonatomic, strong) UIColor *placeholderColor; 2 /** 3 * 分类中只会产生属性对应Setter和Getter方法的声明,不会有实现,需要我们自己实现 4 */ 5 //-(void)setPlaceholderColor:(UIColor *)placeholderColor;