老实人先放链接GithubDemo
关键词
- 解决自定义导航栏按钮后侧滑失效的问题
- 解决UIScrollView及其子类与侧滑返回冲突的问题
FDFullscreenPopGesture/UIPageViewController/UIScrollViewPop Gesture/Pan Gesture
使用
- 下载
FDFullscreenPopGesture,无论是源码还是pod管理 - 添加
UIScroll+TGPopGesture,可以再FDFullscreenPopGesture添加,也可单独文件 - 在包含嵌套的页面内,根据设置
scrollView的pageControllerCurrentIndex来判定是否支持侧滑返回
基本内容和FDFullscreenPopGesture一样
隐藏导航栏
// viewController -> viewDidLoad
self.fd_prefersNavigationBarHidden = YES;
禁止拖拽手势
// ViewController -> viewDidLoad
self.fd_interactivePopDisabled = YES;
设置可拖拽边界
self.fd_interactivePopMaxAllowedInitialDistanceToLeftEdge = 50;
追加UIScroll + PageScrollIndex类别
为什么追加类别?
我们知道UIScrollView是通过Pan手势进行的拖拽处理,而我们的Navigation的返回手势也同样是Pan。所以在导航栏栈内的Controller如果包含横向可拖拽的UIScrollView及其子类或扩展类那么基本上都会造成手势的冲突,从而导致拖拽手势只会被滚动视图相应,而导航栏的返回拖拽手势无效的问题。那么我们如何处理这个问题呢?
FDFullScreenPopGesture提供的方案
如果要在ViewController中将全屏弹出手势与scrollView或scrollView的子类一起使用,则应自定义scrollView或scrollView的子类并重载gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:这个类。
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
if (self.contentOffset.x <= 0) {
if ([otherGestureRecognizer.delegate isKindOfClass:NSClassFromString(@"_FDFullscreenPopGestureRecognizerDelegate")]) {
return YES;
}
}
return NO;
}
博主提供的方案
绑定属性,根据属性判断位置;根据位置判断是否响应手势
为什么使用自己绑定的属性?
如框架内的方案可以支持绝大多数情况。但是像一些复用的情况。如UIPageViewController内,无论拖拽到哪里,它的内部的scrollView的contentOfset都会重置到width, 0,导致无法根据offset.x来判断手势的响应。
所以楼主觉得,如果使用页面page进行标识,是不是就可以处理这种了。当页面是第一个页面的时候,左滑相应Pop的手势,当页面不在0 - width 内,则由scrollView的拖拽手势响应拖拽操作;
具体操作如下:
@interface UIScrollView (TGPopGesture)
/// 在滚动结束后或滚动时计算当前是否停留在最左侧界面,即0的时候。支持全屏侧滑返回
@property(nonatomic, assign) NSUInteger pageControllerCurrentIndex;
@end
@implementation UIScrollView (TGPopGesture)
- (NSUInteger)pageControllerCurrentIndex {
return [objc_getAssociatedObject(self, _cmd) integerValue];
}
- (void)setPageControllerCurrentIndex:(NSUInteger)pageControllerCurrentIndex {
objc_setAssociatedObject(self, @selector(pageControllerCurrentIndex), @(pageControllerCurrentIndex), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
if (self.pageControllerCurrentIndex == 0) {
if ([otherGestureRecognizer.delegate isKindOfClass:NSClassFromString(@"_FDFullscreenPopGestureRecognizerDelegate")]) {
return YES;
}
}
return NO;
}
@end
如何支持UIPageViewController
如何支持UIPageViewController
- 获取UIPageViewControlelr的scrollView
for (UIScrollView *scrollView in self.pageVC.view.subviews) {
if ([scrollView isKindOfClass:[UIScrollView class]]) {
self.scrollView = scrollView;
self.scrollView.delegate = self;
break;
}
}
- 在适当的时候设置扩展属性,如pageController的切换代理,设置scroll的属性,当
pageControllerCurrentIndex为0的时候支持拖拽返回
//滚动切换时调用
- (void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray<UIViewController *> *)previousViewControllers transitionCompleted:(BOOL)completed {
if (self.scrollView) {
self.scrollView.pageControllerCurrentIndex = _currentIndex;
}
}
- 在其它适当的时候更新
pageControllerCurrentIndex