iOS 中的抽屉菜单

前言

在移动应用的软件设计当中,由于扣扣的侧滑抽屉,通过右划展示大半屏的个人UI,在用户交互上,新颖方便,因此在大部分应用也借鉴了扣扣的效果,我们项目中便在此基础上,修改了一下,实际上,扣扣的抽屉效果,在Android和iOS两个不同的平台,还有些稍微不一样:

  • iOS 抽屉,二级页面会直接返回到中间的页面;
  • Android 抽屉,二级页面会返回到左边页面;

而我们需求是跟Android的抽屉效果接近;

先看一下最终效果

初期探索

一开始接到这个需求,表示懵了,因为项目已经上线一段时间,不是一开始从头开始,项目的页面结构在一开始就确定好了,要更改项目的结构,容易产生一些意料之外的坑,而且让人摸不着头脑;

下图是app更改前后的结构对比图:

  • 开始尝试一:(不更改原来项目的结构)

    实现思路:

    • 用一个父控制器同时管理两个子控制器,也即就是在父控制器的scrollView上添加两个子控制器的view

    缺点:

    • 一开始就会加载左边的页面,性能不好
    • 由于tabbar优先级比较高,往右边滑动拉出左边的时候,或者往左滑动显示中间页面时候,底部的tabbar会突然显示或者消失,体验不好

    优化:

    • 朋友提示可以截图优化底部tabbar的突然显示或者隐藏,具体就是:用户刚拉出左边的页面,就截取当前显示的页面,然后当左边页面完全消失后,移除中间页面显示最上层的截图,但是这样做,有一个bug,就是用户快速点击左上角两次,会截取正在滑动的页面的图,然后在回到中间页面的时候,会出现视觉上界面元素混乱
  • 开始尝试二:(不更改项目结构)

    实现思路:
    app一启动,直接在当前window添加左边的控制器,通过添加手势,改变左边VC-View的frame;
    缺点:

    • 左边页面push时,需要切换app的根控制器,然后再切换中间页面时,又需要改变当前窗口的根控制器,来回频繁切换并且都是一开始加载不显示的页面,性能体验不好;

最终做法

最后,通过查找摸索,采用第三方MMDrawerController,通过在基类VC中增加一个开关,来控制哪些页面,可以打开抽屉,哪些不能打开;

  • 传送门:MMDrawerController
  • star✨:7000+经得起考验;
  • 效果图:

MMDrawerController使用简介

优点:

  • 左边VC和右边VC,显示时加载,消失时,销毁,性能较好;
  • 左边VC出现的菜单边距可控,还有各种效果,如3D旋转,平移,位移差平移;

使用方法

导入头文件

#import "MMDrawerController.h"#import "MMDrawerVisualState.h"#import "UIViewController+MMDrawerController.h"
  • 设置根控制器
- (MMDrawerController *)drawerController{    if (!_drawerController) {        leftViewController *leftVc = [[leftViewController alloc] init];        LX_NavgationViewController *leftNavVc = [[LX_NavgationViewController alloc] initWithRootViewController:leftVc];                LX_NavgationViewController *centerNavVc = [[LX_NavgationViewController alloc] initWithRootViewController:self.mainTabBarController];        centerNavVc.navigationBar.hidden = YES;        _drawerController = [[MMDrawerController alloc] initWithCenterViewController:centerNavVc leftDrawerViewController:leftNavVc rightDrawerViewController:nil];        _drawerController.openDrawerGestureModeMask = MMOpenDrawerGestureModeAll;                //初始化手势控制        _drawerController.closeDrawerGestureModeMask =MMCloseDrawerGestureModeAll;        _drawerController.maximumLeftDrawerWidth = leftSideBarWidth;                //阴影效果        _drawerController.showsShadow = NO;                //菜单效果        [_drawerController         setDrawerVisualStateBlock:^(MMDrawerController *drawerController, MMDrawerSide drawerSide, CGFloat percentVisible) {             MMDrawerControllerDrawerVisualStateBlock block;             block = [[MMExampleDrawerVisualStateManager sharedManager]                      drawerVisualStateBlockForDrawerSide:drawerSide];             if(block){                 block(drawerController, drawerSide, percentVisible);             }         }];    }    return _drawerController;}
  • 设置抽屉菜单的效果;
typedef NS_ENUM(NSInteger, MMDrawerAnimationType){    MMDrawerAnimationTypeNone,  //无效果    MMDrawerAnimationTypeSlide, //滑动    MMDrawerAnimationTypeSlideAndScale, //井深效果    MMDrawerAnimationTypeSwingingDoor, //开门效果    MMDrawerAnimationTypeParallax,//位移差,视觉差效果};       [[MMExampleDrawerVisualStateManager sharedManager] setLeftDrawerAnimationType:MMDrawerAnimationTypeParallax];
  • 基类设置开关
- (void)enableOpenCenterDrawer:(BOOL)enable{    if (enable == YES) {        // 能够打开        [AppDelegate appDelegate].drawerController.closeDrawerGestureModeMask =MMCloseDrawerGestureModeAll;    } else {        // 不能打开抽屉        [AppDelegate appDelegate].drawerController.closeDrawerGestureModeMask = MMCloseDrawerGestureModeNone;    }    }- (void)enableOpenLeftDrawer:(BOOL)enable{    if (enable == YES) {        // 能够打开        LX_NavigationController *leftNav = [[LX_NavigationController alloc] initWithRootViewController:[LX_MeViewController meViewController]];        [[AppDelegate appDelegate].drawerController setLeftDrawerViewController:leftNav];        [AppDelegate appDelegate].drawerController.closeDrawerGestureModeMask =MMCloseDrawerGestureModeAll;    } else {        // 不能打开抽屉        [AppDelegate appDelegate].drawerController.closeDrawerGestureModeMask = MMCloseDrawerGestureModeNone;        [[AppDelegate appDelegate].drawerController closeDrawerAnimated:YES completion:^(BOOL finished) {            [[AppDelegate appDelegate].drawerController setLeftDrawerViewController:nil];        }];    }}- (void)enableOpenRightDrawer:(BOOL)enable{    if (enable == YES) {        // 能够打开        //                UINavigationController *RightNav = [[UINavigationController alloc] initWithRootViewController:[[RightViewController alloc] init]];        //        RightViewController *rightVC = [[RightViewController alloc] init];        //        [ShareApp.drawerController setRightDrawerViewController:rightVC];    } else {        // 不能打开抽屉        [[AppDelegate appDelegate].drawerController closeDrawerAnimated:YES completion:^(BOOL finished) {            [[AppDelegate appDelegate].drawerController setRightDrawerViewController:nil];        }];    }}

末尾

demo地址:LXMMDrawerController

关于控制显示隐藏抽屉的开关参考:

抽屉效果的一个第三方库的使用MMDrawerController

如果在使用中,有任何问题,欢迎留言,谢谢

更多相关文章

  1. 【Android】Webview使用自定义的javascript进行回调
  2. Android属性动画(下),InterPolator、ViewPropertyAnimator和布局动
  3. 听说谷歌Baba更新了 Material UI ...
  4. 如何优雅的实现Android(安卓)屏幕适配方案
  5. Android如何实现毛玻璃效果之Android高级模糊技术
  6. 我的安卓应用——SchoolSystem的代码展示
  7. android仿腾讯安全管家首页抽屉效果
  8. Android开发之adb && 破解开屏图案 && 代码判断当前是否处于锁屏
  9. 【Android的从零单排开发日记】之入门篇(十六)——Android的动画效

随机推荐

  1. 直接用 Chrome 扩展来回复 Android(安卓)
  2. 写给有 Android(安卓)开发经验的你们
  3. Android和iOS如何连接指定的蓝牙设备
  4. Android卡顿相关原理和排查工具
  5. 通过AspectJX拦截Android重复点击事件
  6. Android官方MVP架构项目解析
  7. Android布局(一)之基本视图View
  8. Android(安卓)getIdentifier()使用
  9. android 项目实战——打造超级课程表一键
  10. Android(安卓)自定义自由选择时间区间的