本文是我的处女篇啦,全文参考官方文档,基于自己公司项目所写。在这里实现侧拉功能,使用的是MMDrawerController第三方库如,有不正确的地方,还请留下一笔,以做参考
Mutual Mobile Drawer Controller
https://github.com/mutualmobile/MMDrawerController
MMDrawerControlleris侧抽屉导航容器视图控制器设计用于支持应用程序利用侧抽屉方式越来越多。这个库的目的是完全支持侧抽屉式导航在一个轻量级的、集中的方法,在呈现和解聘抽屉提供自定义动画的能力。
Documentation
Official appledoc documentation can be found atCocoaDocs.
安装 MMDrawerController
在项目中安装 MMDrawerController通过CocoaPods:
pod'MMDrawerController','~> 0.5.7'
创建a drawer controller
AppDelegate.m ->- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(nullable NSDictionary *)launchOptions
self.sideViewController = [[SideViewController alloc] init];
self.homeViewController = [[HomeViewController alloc] init];
UINavigationController *navigationControllerHome = [[UINavigationController alloc] initWithRootViewController:self.homeViewController];
UINavigationController *navigationControllerLeft = [[UINavigationController alloc]initWithRootViewController:self.sideViewController];
self.drawerController = [[MMDrawerController alloc]
initWithCenterViewController:navigationControllerHome
leftDrawerViewController:navigationControllerLeft
rightDrawerViewController:nil];
[self.drawerController setRestorationIdentifier:@"MMDrawer"];
[navigationController setRestorationIdentifier:@"MMExampleCenterNavigationControllerRestorationKey"];
[self.sideViewController setRestorationIdentifier:@"MMExampleLeftSideDrawerController"];
[self.drawerController setMaximumLeftDrawerWidth:SIDE_OFFSET];
self.drawerController.showsShadow = NO;
self.drawerController.shouldStretchDrawer = NO;
[self.drawerController setOpenDrawerGestureModeMask:MMOpenDrawerGestureModeAll];
[self.drawerController setCloseDrawerGestureModeMask:MMCloseDrawerGestureModeAll];
[self.drawerController
setDrawerVisualStateBlock:^(MMDrawerController *drawerController, MMDrawerSide drawerSide, CGFloat percentVisible) {
MMDrawerControllerDrawerVisualStateBlock block;
block = [MMDrawerVisualState parallaxVisualStateBlockWithParallaxFactor:2.0f];
if(block){
block(drawerController, drawerSide, percentVisible);
}
}];
实现侧拉效果
UIGestureRecognizer Support
MMOpenDrawerGestureMode
MMOpenDrawerGestureModePanningNavigationBar: 用户清扫导航栏打开侧边栏;
MMOpenDrawerGestureModePanningCenterView: 用户清扫中间的屏幕打开侧边栏;
MMOpenDrawerGestureModeBezelPanningCenterView: 用户清扫底部20个地方打开侧边栏;
MMOpenDrawerGestureModeCustom:开发者可以提供一个回调块来确定该手势是否应该被识别。
MMCloseDrawerGestureMode
MMCloseDrawerGestureModePanningNavigationBar:用户清扫顶部导航栏关闭侧边栏;
MMCloseDrawerGestureModePanningCenterView: 用户清扫中间的视图关闭侧边栏;
MMCloseDrawerGestureModeBezelPanningCenterView:用户清扫底部中间视图关闭侧边栏;
MMCloseDrawerGestureModeTapNavigationBar:用户点击顶部导航栏关闭侧边栏;
MMCloseDrawerGestureModeTapCenterView: 用户点击中间的视图关闭侧边栏;
MMCloseDrawerGestureModePanningDrawerView:用户清扫侧边栏关闭侧边栏;
MMCloseDrawerGestureModeCustom: 开发者可以提供一个回调块来确定该手势是否应该被识别。
Custom Gesture Recognizer Support
从版本0.3.0┊,你现在可以自定义一个手势使用setGestureShouldRecognizeTouchBlock提供一个回调方法。该方法提供了三个参数-抽屉控制器,手势和触摸。作为开发人员,您负责检查这些元素,并确定该手势是否应该被确认。注块仅供参考如果你设置了openDrawerGestureModeMask 包含了 MMOpenDrawerGestureModeCustom,你可以设置代码块如下。
[myDrawerController
setGestureShouldRecognizeTouchBlock:^BOOL(MMDrawerController *drawerController, UIGestureRecognizer *gesture, UITouch *touch) {
BOOL shouldRecognizeTouch = NO;
if(drawerController.openSide == MMDrawerSideNone &&
[gesture isKindOfClass:[UIPanGestureRecognizer class]]){
UIView * customView = [drawerController.centerViewController myCustomSubview];
CGPoint location = [touch locationInView:customView];
shouldRecognizeTouch = (CGRectContainsPoint(customView.bounds, location));
}
return shouldRecognizeTouch;
}];
方法drawerVisualStateBlock的含义
当一个抽屉状态更新时,设置一个回调函数。
这一块是负责更新抽屉状态,和抽屉控制器动画处理状态转变。回调函数将被调用当抽屉被打开或关闭,以及当用户打开抽屉。这一块是不负责直接做动画,而只是更新的视图属性(alpha, anchor point, transform,等)。注意,如果`shouldStretchDrawer`是yes,`percentVisible`要大于1。如果` shouldStretchDrawer`设置为no,` percentVisible `不大于1
`shouldStretchDrawer` is set to YES, it is possible for `percentVisible` to be greater than 1.0. If `shouldStretchDrawer` is set to NO, `percentVisible` will never be greater than 1.0.
注意,当抽屉完成开启或关闭,侧抽屉控制器视图将具有以下性能复位:
- alpha: 1.0
- transform: CATransform3DIdentity
- anchorPoint: (0.5,0.5)
@param drawerVisualStateBlock block块被调用执行更新抽屉的视觉特性。` percentVisible`表示当前可见的抽屉与抽屉空间的大小,空间被定义为屏幕上的maxmimum抽屉宽度的边缘。注意,你已经进入drawercontroller,这将允许您更新像侧抽屉层定位点。
视图恢复的实现
- (UIViewController *)application:(UIApplication *)application viewControllerWithRestorationIdentifierPath:(NSArray *)identifierComponents coder:(NSCoder *)coder
{
NSString * key = [identifierComponents lastObject];
if([key isEqualToString:@"MMDrawer"]){
return self.window.rootViewController;
}
else if ([key isEqualToString:@"MMExampleCenterNavigationControllerRestorationKey"]) {
return ((MMDrawerController *)self.window.rootViewController).centerViewController;
}
else if ([key isEqualToString:@"MMExampleLeftNavigationControllerRestorationKey"]) {
return ((MMDrawerController *)self.window.rootViewController).leftDrawerViewController;
}
else if ([key isEqualToString:@"MMExampleLeftSideDrawerController"]){
UIViewController * leftVC = ((MMDrawerController *)self.window.rootViewController).leftDrawerViewController;
if([leftVC isKindOfClass:[UINavigationController class]]){
return [(UINavigationController*)leftVC topViewController];
}
else {
return leftVC;
}
}
return nil;
}
二级页面滑动返回到一级界面
SideViewController.h
实现主界面向左滑动时进入侧边栏,二级页面返回进入主页面,在
- (void)pushViewController:(UIViewController *)viewController
{
if ([viewController isKindOfClass:[HomeViewController class]]) {
[User currentUser].isHome = YES;
[self.mm_drawerController closeDrawerAnimated:YES completion:nil];
return;
}
[User currentUser].isHome = NO;
AppDelegate *delegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
[self.mm_drawerController toggleDrawerSide:MMDrawerSideLeft animated:YES completion:nil];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:delegate.homeViewController];
[self.mm_drawerController setCenterViewController:nav withCloseAnimation:NO completion:^(BOOL finished) {
AppDelegate *delegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
[delegate.homeViewController.navigationController pushViewController:viewController animated:YES];
}];
self.seletedIndex = 0;
}
方法toggleDrawerSide的含义
调用这个方法基于进入`drawer`。
请注意,如果您试图切换抽屉关闭,而另一个是开放的,没有什么会发生。例如,如果你进入MMDrawerSideLeft页面,但正确的抽屉是开着的,什么都不会发生。此外,完成块将被称为完成标志设置为不。
@param 切换drawerSide The `MMDrawerSide` . 它的值不能是 `MMDrawerSideNone`.
@param 动画决定`drawer`是否应该切换动画。
@param 当切换完成的时候调用这个block块,或者如果没有切换发生。
demo:在首页点击导航栏最左侧的按钮,进入左侧边栏,实现如下:
[self.mm_drawerController toggleDrawerSide:MMDrawerSideLeft animated:YES completion:nil];