Demo 展示效果
从iOS7.0后苹果自带了侧滑返回手势功能
interactivePopGestureRecognizer
,但是有时我们自定义返回按钮或者隐藏了导航栏,侧滑返回就会失效,而它又是我们的应用使用起来更加人性化必不可少的一部分,如何重现它呢?请往下看~
先看官方介绍
//The gesture recognizer responsible for popping the
top view controller off the navigation stack. (read-only)
The navigation controller installs this gesture
recognizer on its view and uses it to pop the topmost
view controller off the navigation stack. You can use
this property to retrieve the gesture recognizer and tie
it to the behavior of other gesture recognizers in your
user interface. When tying your gesture recognizers
together, make sure they recognize their gestures
simultaneously to ensure that your gesture recognizers
are given a chance to handle the event.
@property(nullable, nonatomic, readonly) UIGestureRecognizer *interactivePopGestureRecognizer NS_AVAILABLE_IOS(7_0) __TVOS_PROHIBITED;
介绍和属性中我们可以知道interactivePopGestureRecognizer
是负责把Navigation 栈中最上面的View Controller推出去。而且它只能在iOS7.0及以上可以使用,并且禁止在TVOS中使用!
How to use
- 由于
interactivePopGestureRecognizer
是一种手势,因此我们在使用它时需遵循UIGestureRecognizerDelegate
Protocol.
例如:
#import <UIKit/UIKit.h>
@interface ZHRootViewController : UIViewController<UIGestureRecognizerDelegate>
@end
- 我们需要把
interactivePopGestureRecognizer
使能打开,并设置委托对象,当然在这之前别忘了对系统版本进行判断,因为它只能在iOS7.0及以上使用。
For example:
- (void)viewDidLoad
{
[super viewDidLoad];
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0)
{
self.navigationController.interactivePopGestureRecognizer.enabled = YES; // 手势有效设置为YES 无效为NO
self.navigationController.interactivePopGestureRecognizer.delegate = self; // 手势的代理设置为self
}
// Do any additional setup after loading the view.
}
- 显示或者隐藏NavigationBar 注意这里需要在函数
-(void)viewWillAppear:(BOOL)animated
中调用
Like this:
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self.navigationController setNavigationBarHidden:NO animated:animated];//No 为显示Navigationbar Yes 为隐藏
}
做完这些运行后动画效果有了,是不是就完事了呢?No No
- 你想一想如果已经到Navigation 栈中最底一个Controller时我们还允许侧滑么,显然这时我们应该使侧滑手势失效!
像这样:
-(void)viewDidAppear:(BOOL)animated
{
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0)
{
if (self.navigationController.viewControllers.count==1) {
self.navigationController.interactivePopGestureRecognizer.enabled = NO;
}
}
}
或者:
-(BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
if (self.navigationController.viewControllers.count == 1) {
return NO;
}else{
return YES;
}
}
到现在我们应该做完了吧? No No
- 假如我们的View是一个可滑动的View呢?例如ScrollView,TableView,CollectionView。由于它们自带了
panGestureRecognizer
所以它们一起使用时可能会产生冲突,如何避免呢?我们可以设置一个手势依赖关系!
Like this:
NSArray *gestureArray = self.navigationController.view.gestureRecognizers;//获取所有的手势
//当是侧滑手势的时候设置panGestureRecognizer需要UIScreenEdgePanGestureRecognizer失效才生效即可
for (UIGestureRecognizer *gesture in gestureArray) {
if ([gesture isKindOfClass:[UIScreenEdgePanGestureRecognizer class]]) {
[self.tableView.panGestureRecognizer requireGestureRecognizerToFail:gesture];
}
}
这里你也许会疑惑为什么我们上面用的是UIScreenEdgePanGestureRecognizer
而不是interactivePopGestureRecognizer
?
我们先打印self.navigationController.interactivePopGestureRecognizer
结果为:
<UIScreenEdgePanGestureRecognizer: 0x7f8283d31c90; state = Possible;
delaysTouchesBegan = YES;
view = <UILayoutContainerView 0x7f8283d2fae0>;
target= <(action=handleNavigationTransition:,
target=<_UINavigationInteractiveTransition 0x7f8283d31600>)>>
打印结果中我们看到了UIScreenEdgePanGestureRecognizer
:说明interactivePopGestureRecognizer
其实由UIScreenEdgePanGestureRecognizer
控制并执行handleNavigationTransition:
其代理对象为_UINavigationInteractiveTransition
,所以判断中我们使用了UIScreenEdgePanGestureRecognizer
.
扩展
我们可以根据UIScreenEdgePanGestureRecognizer
,handleNavigationTransition:
来自定义我们自己的侧滑返回,这章先讲诉到这里!
Demo
今天教师节,祝天下所有教师:节日快乐!