UIScreenEdgePanGestureRecognizer : UIPanGestureRecognizer : UIPanGestureRecognizer
专门处理在屏幕边缘触发的手势类型
edges属性叫,来设置它的触发边缘(上、下、左、右、全部)
私有类,看来是专门用来做导航控制器交互动画的
delegate == _UINavigationInteractiveTransition
taget == _UINavigationInteractiveTransition
私有类,专门来做导航控制器交互动画
acrtion == handleNavigationTransition
- UIGestureRecognizer有个叫_targets的属性,数组
_targets[0] == (action=handleNavigationTransition:, target=<_UINavigationInteractiveTransition 0x7faae8508ea0>)
是UIGestureRecognizerTarget 私有类
image
最简单版,全屏返回手势
/**
全屏滑动返回
利用系统 pop返回功能
*/
- (void)viewDidLoad {
[super viewDidLoad];
// 获取系统自带滑动手势的target对象
id target = self.interactivePopGestureRecognizer.delegate;
// 创建全屏滑动手势,调用系统自带滑动手势的target的action方法
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:target action:@selector(handleNavigationTransition:)];
// NSSelectorFromString(@"
// 设置手势代理,拦截手势触发
pan.delegate = self;
// 给导航控制器的view添加全屏滑动手势
[self.view addGestureRecognizer:pan];
// 禁止使用系统自带的滑动手势
self.interactivePopGestureRecognizer.enabled = NO;
}
// 是否开始触发。
// 作用:拦截手势触发
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
// 注意:只有非根控制器才有滑动返回功能,根控制器没有。
// 判断导航控制器是否只有一个子控制器,如果只有一个子控制器,肯定是根控制器
if (self.childViewControllers.count == 1) {
// 表示用户在根控制器界面,就不需要触发滑动手势,
return NO;
}
return YES;
}
- 优点:简单易于理解
- 缺点:每个控制器不能控制自己的导航栏状态,显示也有问题
- (void)fd_viewWillAppear:(BOOL)animated
{
// 执行原始方法
[self fd_viewWillAppear:animated];
// 即将要显示时,调用block, 完成每个控制器 导航栏你的显示
if (self.fd_willAppearInjectBlock) {
self.fd_willAppearInjectBlock(self, animated);
}
}
---------------------------------------------------------
- (void)fd_pushViewController:(UIViewController *)viewController animated:(BOOL)animated
{
if (![self.interactivePopGestureRecognizer.view.gestureRecognizers containsObject:self.fd_fullscreenPopGestureRecognizer]) {
// 添加自定义全屏手势
[self.interactivePopGestureRecognizer.view addGestureRecognizer:self.fd_fullscreenPopGestureRecognizer];
// 使用系统侧滑返回手势 target 和 处理方法
NSArray *internalTargets = [self.interactivePopGestureRecognizer valueForKey:@"targets"];
id internalTarget = [internalTargets.firstObject valueForKey:@"target"];
// 私有处理方法不能用kvc 获取??
SEL internalAction = NSSelectorFromString(@"handleNavigationTransition:");
// 为手势设置代理
self.fd_fullscreenPopGestureRecognizer.delegate = self.fd_popGestureRecognizerDelegate;
// 为手势设置target-action
[self.fd_fullscreenPopGestureRecognizer addTarget:internalTarget action:internalAction];
// 禁用系统的手势事件
self.interactivePopGestureRecognizer.enabled = NO;
}
// 处理所有 push方法 之前都进行操作
[self fd_setupViewControllerBasedNavigationBarAppearanceIfNeeded:viewController];
// 调用原始方法 进行push, 判断已经有这个子控制器,就不会push
if (![self.viewControllers containsObject:viewController]) {
[self fd_pushViewController:viewController animated:animated];
}
}
/**
所有push操作,都会来到这个方法
对导航栏外观 进行预处理
*/
- (void)fd_setupViewControllerBasedNavigationBarAppearanceIfNeeded:(UIViewController *)appearingViewController
{
// 导航控制器 是否允许 所有导航栏的操作
// 为NO 各个子控制器不能单独操作
if (!self.fd_viewControllerBasedNavigationBarAppearanceEnabled) {
return;
}
// 创建实现一个block 包含2个参数
// 进行处理操作
__weak typeof(self) weakSelf = self;
_FDViewControllerWillAppearInjectBlock block = ^(UIViewController *viewController, BOOL animated) {
__strong typeof(weakSelf) strongSelf = weakSelf;
if (strongSelf) {
[strongSelf setNavigationBarHidden:viewController.fd_prefersNavigationBarHidden animated:animated];
}
};
// 给即将push进来的控制器 赋值blcok
// 以后传什么参数, 由它自己决定!
appearingViewController.fd_willAppearInjectBlock = block;
// 给即将消失是的控制器 赋值block, 就是当前控制器
// 有的子控制器不是 push进来的, 本身就是导航控制器的 根控制器
UIViewController *disappearingViewController = self.viewControllers.lastObject;
if (disappearingViewController && !disappearingViewController.fd_willAppearInjectBlock) {
disappearingViewController.fd_willAppearInjectBlock = block;
}
}
- (_FDFullscreenPopGestureRecognizerDelegate *)fd_popGestureRecognizerDelegate
{
_FDFullscreenPopGestureRecognizerDelegate *delegate = objc_getAssociatedObject(self, _cmd);
if (!delegate) {
delegate = [[_FDFullscreenPopGestureRecognizerDelegate alloc] init];
delegate.navigationController = self;
objc_setAssociatedObject(self, _cmd, delegate, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
return delegate;
}
/**
懒加载创建 自定义全屏手势
*/
- (UIPanGestureRecognizer *)fd_fullscreenPopGestureRecognizer
{
UIPanGestureRecognizer *panGestureRecognizer = objc_getAssociatedObject(self, _cmd);
if (!panGestureRecognizer) {
panGestureRecognizer = [[UIPanGestureRecognizer alloc] init];
panGestureRecognizer.maximumNumberOfTouches = 1;
objc_setAssociatedObject(self, _cmd, panGestureRecognizer, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
return panGestureRecognizer;
}
image
全屏滑动返回手势
网友评论