[TOC]
iOS 的导航支持左滑手势返回上一个界面,这是果粉普遍喜欢的一个特性,iOS7 之后的 APP 适配大多会保留这一特性,慢慢的大多用户已经有了这种操作习惯,对于 iPhone 的无虚拟键,这种操作也能增加比较友好的用户体验。
在公司新项目之前,没有考虑过多语言 RTL 的适配方案,开始做的时候 UI 方面基本实现用一套布局代码支持 RTL 的两种布局方向。但是真正拿在手里把玩体验时才真切的感受到没有侧滑返回的 RTL 有多么的不爽。几经查找并没有找到可参考的合适方案,可能国内做多语言适配的技术圈本身就小,适配 RTL 的就显得更加的稀有了。
希望能帮助到有需要的人,或者有更好的思路可以联系共同探讨。
查不到可参考的资料,只能自己想一想比较合适的方式,恰好在实现一个首页列表跳转详情页时候,解决特殊的转场动画,突然就有了灵感。可能应该有更好的实现方式,现将我的方式展现给大家。
- UIPercentDrivenInteractiveTransition
- finishInteractiveTransition
- cancelInteractiveTransition
- updateInteractiveTransition:
使用 runtime 方式或者基类方式,viewdidappea 每次设置 nav 的代理为自己,viewdiddisappear 清空代理 (Yoins 新版中使用 RTL 框架中的分类)
- - (void)RTL_viewWillAppear:(BOOL)animated
- {
- [self RTL_viewWillAppear:animated];
- self.navigationController.delegate = self;
- }
- - (void)RTL_viewWillDisappear:(BOOL)animated
- {
- [self RTL_viewWillDisappear:animated];
- if (self.navigationController.delegate == self) {
- self.navigationController.delegate = nil;
- }
- }
基类初始化时,RTL 环境下添加右滑手势,关闭左滑手势,实现最基本的右滑返回。
- Navigation中实现
- - (void) RTL_ViewWillAppear: (BOOL) animate {
- // self.view.backgroundColor = [UIColor whiteColor];
- // // Do any additional setup after loading the view.
- if (! [[RTLManager appearance] RTL]) {
- self.interactivePopGestureRecognizer.delegate = self;
- }
- self.interactivePopGestureRecognizer.enabled = ![[RTLManager appearance] RTL];
- [self RTL_ViewWillAppear: animate];
- }
基类 VC 中 增加一个基础属性,保存临时转场上下文
- @property(strong, nonatomic) UIPercentDrivenInteractiveTransition * transitonContext;
在 VC 右滑动作触发事件中,处理转场动画进度
- - (void)handlePanGesture:(UIScreenEdgePanGestureRecognizer *)pan
- {
- // NSLog(@"_____%zd-----%zd",self.navigationController.childViewControllers.count,self.navigationController.viewControllers.count);
- // NSLog(@"----%@",NSStringFromCGPoint([pan translationInView:self.view]));
- CGFloat progress = ABS([pan translationInView:self.view].x) / (self.view.bounds.size.width * 1.0);
- progress = MIN(1.0, MAX(0.0, progress));
- if (pan.state == UIGestureRecognizerStateBegan) {
- // 创建过渡对象,弹出viewController
- self.transitonContext = [[UIPercentDrivenInteractiveTransition alloc] init];
- [self.navigationController popViewControllerAnimated:YES];
- }else if (pan.state == UIGestureRecognizerStateChanged) {
- // 更新 interactive transition 的进度
- [self.transitonContext updateInteractiveTransition:progress];
- }else if (pan.state == UIGestureRecognizerStateEnded || pan.state == UIGestureRecognizerStateCancelled) {
- // 完成或者取消过渡
- if (progress > 0.5) {
- [self.transitonContext finishInteractiveTransition];
- }
- else {
- [self.transitonContext cancelInteractiveTransition];
- }
- self.transitonContext = nil;
- }
- }
- - (id<UIViewControllerInteractiveTransitioning>)navigationController:(UINavigationController *)navigationController interactionControllerForAnimationController:(id<UIViewControllerAnimatedTransitioning>)animationController{
- if (self.transitonContext) {
- return self.transitonContext;
- }
- else {
- return nil;
- }
- }
最后就是实现自定的各种转场动画了,可以简单模仿系统的滑动切换转场, 具体处理在下面 VC 实现的方法中,返回一个处理转场的实例即可
- - (id < UIViewControllerAnimatedTransitioning > ) navigationController: (UINavigationController * ) navigationController animationControllerForOperation: (UINavigationControllerOperation) operation fromViewController: (UIViewController * ) fromVC toViewController: (UIViewController * ) toVC
- @implementation RTLPushAnimation
- - (NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext
- {
- return 0.5;
- }
- - (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
- {
- UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
- UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
- UIView *container = transitionContext.containerView;
- UIView *tmpV = [fromVC.view snapshotViewAfterScreenUpdates:YES];
- [container addSubview:toVC.view];
- toVC.view.transform = CGAffineTransformMakeTranslation(-toVC.view.bounds.size.width, 0);
- [container addSubview:tmpV];
- [UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{
- tmpV.transform = CGAffineTransformMakeTranslation(toVC.view.bounds.size.width, 0);
- toVC.view.transform = CGAffineTransformIdentity;
- } completion:^(BOOL finished) {
- [tmpV removeFromSuperview];
- [transitionContext completeTransition:YES];
- }];
- }
- @end
- @implementation RTLPopAnimation
- - (NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext
- {
- return 0.5;
- }
- - (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
- {
- UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
- UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
- UIView *container = transitionContext.containerView;
- UIView *tmpV = [fromVC.view snapshotViewAfterScreenUpdates:YES];
- [container addSubview:toVC.view];
- toVC.view.transform = CGAffineTransformMakeTranslation(toVC.view.bounds.size.width, 0);
- [container addSubview:tmpV];
- [UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{
- tmpV.transform = CGAffineTransformMakeTranslation(-toVC.view.bounds.size.width, 0);
- toVC.view.transform = CGAffineTransformIdentity;
- } completion:^(BOOL finished) {
- [tmpV removeFromSuperview];
- toVC.view.transform = CGAffineTransformIdentity;
- [transitionContext completeTransition:!transitionContext.transitionWasCancelled];
- }];
- }
- @end
大家或许有更好的处理方案,可以一切探讨下。
新版项目中使用的 RTL 还在不断地完善中,在公司的公开项目里,有需要可以公开出来。
来源: http://www.jianshu.com/p/6a8a0a54ada9