iOS中的抽屉菜单
16lz
2021-01-26
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
如果在使用中,有任何问题,欢迎留言,谢谢
更多相关文章
- 【Android】Webview使用自定义的javascript进行回调
- Android属性动画(下),InterPolator、ViewPropertyAnimator和布局动
- 听说谷歌Baba更新了 Material UI ...
- 如何优雅的实现Android(安卓)屏幕适配方案
- Android如何实现毛玻璃效果之Android高级模糊技术
- 我的安卓应用——SchoolSystem的代码展示
- android仿腾讯安全管家首页抽屉效果
- Android开发之adb && 破解开屏图案 && 代码判断当前是否处于锁屏
- 【Android的从零单排开发日记】之入门篇(十六)——Android的动画效