iOS详解MMDrawerController抽屉效果(一)
提前说好,本文绝对不是教你如何使用MMDrawerController这个第三方库,因为那太多人写了 ,也太简单了。这篇文章主要带你分析MMDrawerController是怎么实现抽屉效果,明白第三方库的内部原理。例外,本人也封装了一个FHSegmentControl的第三方库,欢迎大家去看看啊。
1.MMDrawerController的实例化方法
先明确几个变量的意义。
// 中央控制器
@property (nonatomic, strong) UIViewController * centerViewController;
// 左侧控制器、右侧控制器,统称侧边控制器
@property (nonatomic, strong) UIViewController * leftDrawerViewController;
@property (nonatomic, strong) UIViewController * rightDrawerViewController;
我分析第三方库,都是从实例化方法开始的。那么多类,方法更多,必须有一个开始。从实例化方法开始,可以找出作者的思考方式,这里也就是怎么实现抽屉效果的。
// 1.
-(instancetype)initWithCenterViewController:(UIViewController *)centerViewController leftDrawerViewController:(UIViewController *)leftDrawerViewController rightDrawerViewController:(UIViewController *)rightDrawerViewController{
NSParameterAssert(centerViewController);
self = [super init];
if(self){
[self setCenterViewController:centerViewController];
[self setLeftDrawerViewController:leftDrawerViewController];
[self setRightDrawerViewController:rightDrawerViewController];
}
return self;
}
// 2.
-(instancetype)initWithCenterViewController:(UIViewController *)centerViewController leftDrawerViewController:(UIViewController *)leftDrawerViewController{
return [self initWithCenterViewController:centerViewController leftDrawerViewController:leftDrawerViewController rightDrawerViewController:nil];
}
//3.
-(instancetype)initWithCenterViewController:(UIViewController *)centerViewController rightDrawerViewController:(UIViewController *)rightDrawerViewController{
return [self initWithCenterViewController:centerViewController leftDrawerViewController:nil rightDrawerViewController:rightDrawerViewController];
}
一共有3个实例方法,第2.3个实例方法,最后都得调用第1个实例方法,所以我们只要分析第1个实例方法就可以了。第一个实例方法调用了三个方法。
// 4
[self setCenterViewController:centerViewController];
// 5
[self setLeftDrawerViewController:leftDrawerViewController];
// 6
[self setRightDrawerViewController:rightDrawerViewController];
我们先看第5、6个方法。
-(void)setRightDrawerViewController:(UIViewController *)rightDrawerViewController{
[self setDrawerViewController:rightDrawerViewController forSide:MMDrawerSideRight];
}
-(void)setLeftDrawerViewController:(UIViewController *)leftDrawerViewController{
[self setDrawerViewController:leftDrawerViewController forSide:MMDrawerSideLeft];
}
这两个方法其实都是调用了同一个方法:
- (void)setDrawerViewController:(UIViewController *)viewController forSide:(MMDrawerSide)drawerSide;
综上所述,我们要明白MMDrawerController是怎样创建的,只要明白下面的两个方法就可以了,顿时感觉工作量少了很多有没有。
// 1.添加中央控制器
-(void)setCenterViewController:(UIViewController *)centerViewController;
// 2.添加左右两边的控制器
- (void)setDrawerViewController:(UIViewController *)viewController forSide:(MMDrawerSide)drawerSide;
2.添加中央控制器
// 1.
-(void)setCenterViewController:(UIViewController *)centerViewController{
[self setCenterViewController:centerViewController animated:NO];
}
//2.直接看这个方法就好了,因为第一个方法也是调用这个方法
-(void)setCenterViewController:(UIViewController *)centerViewController animated:(BOOL)animated{
// 如果将要添加的中央控制器和原来的一样,就不要再添加了
// self.centerViewController 已经添加的中央内容控制器。第一次实例化,为nil。
if ([self.centerViewController isEqual:centerViewController]) {
return;
}
// 添加中央内容视图,也就是:往self.childControllerContainerView上添加self.centerContainerView
if (_centerContainerView == nil) {
// self.childControllerContainerView 是一个添加在self.view 上面和self.view位置和大小一样的UIView。
CGRect centerFrame = self.childControllerContainerView.bounds;
if(self.centerContainerView == nil){
// MMDrawerCenterContainerView 先当做UIView,后面在慢慢分析
self.centerContainerView = [[MMDrawerCenterContainerView alloc] initWithFrame:centerFrame];
[self.centerContainerView setAutoresizingMask:UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight];
[self.centerContainerView setBackgroundColor:[UIColor clearColor]];
//开始时: self.openSide = MMDrawerSideNone;因为我们实例化的时候,并没有展示左右边两边的抽屉视图
[self.centerContainerView setOpenSide:self.openSide];
//开始时: self.centerHiddenInteractionMode = MMDrawerOpenCenterInteractionModeNavigationBarOnly;设置响应模式
[self.centerContainerView setCenterInteractionMode:MMDrawerOpenCenterInteractionModeNone];
[self.childControllerContainerView addSubview:self.centerContainerView];
}
}
// 因为要添加新的中央控制器,如果旧的存在,就要删除
UIViewController * oldCenterViewController = self.centerViewController;
if(oldCenterViewController){
[oldCenterViewController willMoveToParentViewController:nil];
if(animated == NO){
[oldCenterViewController beginAppearanceTransition:NO animated:NO];
}
[oldCenterViewController.view removeFromSuperview];
if(animated == NO){
[oldCenterViewController endAppearanceTransition];
}
[oldCenterViewController removeFromParentViewController];
}
// 添加新的中央控制器
_centerViewController = centerViewController;
[self addChildViewController:self.centerViewController];
[self.centerViewController.view setFrame:self.childControllerContainerView.bounds];
[self.centerContainerView addSubview:self.centerViewController.view];
// 把中央视图放在子视图容器最前面
[self.childControllerContainerView bringSubviewToFront:self.centerContainerView];
[self.centerViewController.view setAutoresizingMask:UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight];
// 设置阴影,以后讲
[self updateShadowForCenterView];
if(animated == NO){
// 实例化的时候,这个方法不走
// self.view.window 是判断是否添加到了手机屏幕上,也就是keyWindow上。
if(self.view.window) {
[self.centerViewController beginAppearanceTransition:YES animated:NO];
[self.centerViewController endAppearanceTransition];
}
//告诉系统有一个视图控制器从容器中添加或者移除
[self.centerViewController didMoveToParentViewController:self];
}
}
其实这里一共有四个View,这四个View的大小和位置都是一样的。self 是MMDrawerController 的对象。它们的层级结构就是:
self.view -> self.childControllerContainerView ->self.centerContainerView -> self.centerViewController.view。中央控制器的view在最上面,运行APP的时候,最先看到。
3.添加侧边控制器
- (void)setDrawerViewController:(UIViewController *)viewController forSide:(MMDrawerSide)drawerSide{
// 如果你添加的是中央控制器,程序就会崩溃。因为这个方法只能添加左右两边的控制器。
NSParameterAssert(drawerSide != MMDrawerSideNone);
// 这个方法,可以获得当前的左边或右边的控制器
UIViewController *currentSideViewController = [self sideDrawerViewControllerForSide:drawerSide];
// 如果和原来的侧边视图控制器相同,就不必添加了
if (currentSideViewController == viewController) {
return;
}
// 如果原来已经有了侧边视图控制器,移除
if (currentSideViewController != nil) {
[currentSideViewController beginAppearanceTransition:NO animated:NO];
[currentSideViewController.view removeFromSuperview];
[currentSideViewController endAppearanceTransition];
[currentSideViewController willMoveToParentViewController:nil];
[currentSideViewController removeFromParentViewController];
}
// 添加新的侧边视图控制器
// 左边
UIViewAutoresizing autoResizingMask = 0;
if (drawerSide == MMDrawerSideLeft) {
_leftDrawerViewController = viewController;
autoResizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleHeight;
}
// 右边
else if(drawerSide == MMDrawerSideRight){
_rightDrawerViewController = viewController;
autoResizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleHeight;
}
// viewController不为空,代表你想添加侧边控制器
if(viewController){
[self addChildViewController:viewController];
// 实例化的时候不走,直接看else里面的方法
if((self.openSide == drawerSide) &&
[self.childControllerContainerView.subviews containsObject:self.centerContainerView]){
[self.childControllerContainerView insertSubview:viewController.view belowSubview:self.centerContainerView];
[viewController beginAppearanceTransition:YES animated:NO];
[viewController endAppearanceTransition];
}
else{
// 添加新的侧边控制器
[self.childControllerContainerView addSubview:viewController.view];
[self.childControllerContainerView sendSubviewToBack:viewController.view];
[viewController.view setHidden:YES];
}
[viewController didMoveToParentViewController:self];
[viewController.view setAutoresizingMask:autoResizingMask];
//侧边栏的最大宽度默认280.
// H:代表self.view的高,W代表self.view的宽,w代表侧边栏的最大的宽度
// 左侧视图的frame: (0,0,w,H);右侧视图的frame: (W-w,0,w,H);
[viewController.view setFrame:viewController.mm_visibleDrawerFrame];
}
}


这篇文章介绍了MMDrawerController的实例化方法和各个控制器与视图的层级结构,下篇文章主要讲侧边栏的切换动画。如果喜欢就推荐一下吧!
iOS详解MMDrawerController抽屉效果(一)的更多相关文章
- IOS详解TableView——选项抽屉(天猫商品列表)
在之前的有篇文章讲述了利用HeaderView来写类似QQ好友列表的表视图. 这里写的天猫抽屉其实也可以用该方法实现,具体到细节每个人也有所不同.这里采用的是点击cell对cell进行运动处理以展开“ ...
- ios学习--详解IPhone动画效果类型及实现方法
详解IPhone动画效果类型及实现方法是本文要介绍的内容,主要介绍了iphone中动画的实现方法,不多说,我们一起来看内容. 实现iphone漂亮的动画效果主要有两种方法,一种是UIView层面的,一 ...
- .NET DLL 保护措施详解(三)最终效果
针对.NET DLL 保护措施详解所述思路完成最终的实现,以下为程序包下载地址 下载 注意: 运行环境为.net4.0,需要安装VS2015 C++可发行组件包vc_redist.x86.exe.然后 ...
- android shape的使用详解以及常用效果(渐变色、分割线、边框、半透明阴影效果等)
shape使用.渐变色.分割线.边框.半透明.半透明阴影效果. 首先简单了解一下shape中常见的属性.(详细介绍参看 api文档 ) 转载请注明:Rflyee_大飞: http://blog.cs ...
- iOS中 超简单抽屉效果(MMDrawerController)的实现
ios开发中,展示类应用通常要用到抽屉效果,由于项目需要,本人找到一个demo,缩减掉一些不常用的功能,整理出一个较短的实例. 首先需要给工程添加第三方类库 MMDrawerController: 这 ...
- iOS:详解MJRefresh刷新加载更多数据的第三方库
原文链接:http://www.ios122.com/2015/08/mjrefresh/ 简介 MJRefresh这个第三方库是李明杰老师的杰作,这个框架帮助我们程序员减轻了超级多的麻烦,节约了开发 ...
- iOS側拉栏抽屉效果Demo
源代码下载 側拉栏抽屉效果Demo 须要导入第三方的类库例如以下: 抽屉效果所需第三方类库下载 效果:既能够两側都实现抽屉效果也可仅仅实现左側栏或者右側栏的抽屉效果 waterm ...
- css样式之background详解(格子效果)
background用法详解: 1.background-color 属性设置元素的背景颜色 可能的值 color_name 规定颜色值为颜色名称的背景颜色(比如 red) he ...
- IOS详解TableView——内置刷新,EGO,以及搜索显示控制器
内置刷新 内置刷新是苹果IOS6以后才推出的一个API,主要是针对TableViewController增加了一个属性,refreshControl,所以如果想用这个内置下拉刷新的话,最好给你的Tab ...
随机推荐
- 10、手把手教你Extjs5(十)自定义模块的设计
从这一节开始我们来设计并完成一个自定义模块.我们先来确定一个独立的模块的所能定义的一些模块信息.以下信息只是我自己在开发过程中想到或用到的,希望有新的想法的或者有建议的跟贴回复. 一个独立模块包含以下 ...
- 在阿里云ECS(CentOS6.5)上安装tomcat
切换到你要安装的目录下 命令: cd /home/ 下载你要安装的tomcat 命令: wget http://mirror.bit.edu.cn/apache/tomcat/tomcat-7/v7. ...
- mysql 千万量级的表的优化
参考: 一 大的优化方向: 数据结构优化,慢查询优化,索引优化,mysql参数设置优化 数据结构优化:先读写分离.再垂直拆分.再水平拆分! 说3点 1. 设计合适的索引,基于主键的查找,上亿数据也是 ...
- getElementsByTagName("div")和$("div")区别
作者:zccst <body> <div class="selected">1</div> <div class="select ...
- Android自定义控件(状态提示图表) (转)
源:Android自定义控件(状态提示图表) 源:Android应用开发 [工匠若水 http://blog.csdn.net/yanbober 转载烦请注明出处,尊重分享成果] 1 背景 前面分析 ...
- Java程序员常犯的10个错误
本文总结了Java程序员常犯的10个错误. #1. 把Array转化成ArrayList 把Array转化成ArrayList,程序员经常用以下方法: List<String> lis ...
- 分布式存储 CentOS6.5虚拟机环境搭建FastDFS-5.0.5集群(转载)
原文:http://www.open-open.com/lib/view/open1435468300700.html 第一步,确定目标: Tracker 192.168.224.20:22122 ...
- UVa 10814 - Simplifying Fractions
题目大意:给一个分数,对其进行化简.因为分子.分母最大为1030,所以用要用大数. import java.io.*; import java.util.*; import java.math.*; ...
- AutoLayout没有相对比例布局
怎么实现相对比例布局 比如我一个控件相对上边距的位置在整个屏幕的比例 可以用stack view来管理相对布局
- 1.1.2.托管对象模型(Core Data 应用程序实践指南)
托管对象模型即对象图,可以看成实体类的描述,规定了数据字段. 要想创建托管对象模型,需生成NSManagedObjectModel类的实例.