内容字号:默认大号超大号

段落设置:段首缩进取消段首缩进

字体设置:切换到微软雅黑切换到宋体

iOS右滑返回UINavigationBar跟随滑动实现

2018-04-16 12:17 出处:清屏网 人气: 评论(0

项目中要实现像今日头条一样的返回效果,当用户手指右滑时,当前屏幕显示的东西都向右移动,也就是UINavigationBar也要跟随当前的ViewController移动。移动后的位置露出要返回的界面,当移动到一定位置后,实现pop效果。

原生UINavigationController pop效果为什么不行

如图效果,原生的操作是把ViewController的view压入到当前的导航界面,其动画只是view的位置变化动画,NavigationBar不会跟随,只是会根据当前的view信息来跟新自己的显示信息。

如何解决

一 . 实现View和NavigationBar的整体移动

如果能找到一个上级视图包含NavigationBar 和 controller的view ,那么用手指滑动这个视图,NavigationBar 和 UIView就会同时移动,当滑动到一定位置时再调用原生的pop方法。

在xcode中截取一个UINavigationController的UI结构如图

根据上图我们发现,红色的视图同时包含了NavigationBar和UIViewController的View,那么我们现在只需要拿到这个属性就可以了,很幸运,NavigationController的view属性就是这个值.

那我们就先来定义一个继承于UINavigationController的YMNavigationController

#import <UIKit/UIKit.h>
 YMNavigationController : UINavigationController
YMNavigationController ()
- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor greenColor];
}

定义两个UIViewController 加入到 YMNavigationController运行代码。视图结构如下:

选中UILayoutContainerView,其颜色确实变成了绿色.

那接下来我们就为其加一个手势来实现移动。

为了不跟系统的返回手势冲突,我们首先关闭系统的返回手势, 然后再添加自己的手势。

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor greenColor];
    self.interactivePopGestureRecognizer.enabled = NO;
    [self addPanGestureRecognizer];
}
- (void)popViewController:(UIPanGestureRecognizer *)recognizer {

    CGPoint transition = [recognizer translationInView:self.view]; //总共移动了多少位置
    if (transition.x > 0) {
        self.view.transform = CGAffineTransformMakeTranslation(transition.x, 0);
    }

运行,并尝试右滑,效果如下

像上图一样,整体滑动的效果已经实现了。

二. 显示上一级界面

如上图展现的那样,滑动的时候整个Navigation的界面都移动到了新位置,漏出了后面的UIWindow。

我们想要在漏出的window上展示上一级界面,只要把要展示的界面放到window上就可以了,现在我们的任务就变成了如何获取上一级界面。

上级界面其实就是上一次UILayoutContainerView的展示内容,我们只要把这个view保存下来加到window就可以了。想到了两种方法来保存上一级的view。

  1. 复制view保存到数组中
  2. 获取view的截图保存到数组中

第一种方法使用了下面的函数去复制数组

- (UIView *)copyView:(UIView *)view{
    NSData * tempArchive = [NSKeyedArchiver archivedDataWithRootObject:view];
    return [NSKeyedUnarchiver unarchiveObjectWithData:tempArchive];
}

复制后的view在无法正常显示statusBar,没有想到办法去解决,所以就暂时放弃了。

第二个方法使用OC截取屏幕并且保存在数组中,方法如下

- (NSMutableArray *)lastVCScreenShootArray {

    if (!_lastVCScreenShootArray) {
        _lastVCScreenShootArray = [[NSMutableArray alloc] initWithCapacity:0];
    }

    return _lastVCScreenShootArray;
}

- (void)takeScreenShoot{

    UIGraphicsBeginImageContextWithOptions(self.view.bounds.size,NO,0);
    [self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage * newScreenSnapImg = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    [self.lastVCScreenShootArray addObject:newScreenSnapImg];
}

那我们什么时候去截取屏幕呢,当然是在push的时候了。在代码中重载一下push方法,在其加入截屏的方法就ok了。

//重载系统方法
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated {

    [self takeScreenShoot];
    [super pushViewController:viewController animated:animated];
}

现在我们就把这个截图添加到window上,这时候我们需要一个UIImageView来显示这个截图。

//通过懒加载的方法,创建一个UIImageView,并且加到Window的最底层

- (UIImageView *)lastVCScreenShootImageView {

    if (!_lastVCScreenShootImageView) {

        UIImageView *shootImageView = [[UIImageView alloc] init];
        shootImageView.frame = self.view.bounds;
        [self.view.superview addSubview:shootImageView];     //self.view.super = [UIApplication window] keyWIndow]
        [self.view.superview insertSubview:shootImageView atIndex:0];
        _lastVCScreenShootImageView = shootImageView;
    }

    return _lastVCScreenShootImageView;
}

滑动时我们调用方法把上面的UIImageView加上去

- (void)popViewController:(UIPanGestureRecognizer *)recognizer {

    CGPoint transition = [recognizer translationInView:self.view];
    if (transition.x > 0) {
        self.view.transform = CGAffineTransformMakeTranslation(transition.x, 0);
        self.lastVCScreenShootImageView.image = [self.lastVCScreenShootArray lastObject];
    }

运行效果

效果已经出现了,但是看上去特别奇怪,因为两个NavigationBar重合在了一起,我们给它加一个过度层效果,一个透明图变化的图层就好了,window上的布局顺序

[截图, 过渡层, UIVigationController 界面 ]

剩下的事情就是当用户停止滑动时,根据滑动的位置来决定是否调用原生的pop以及后续UINavigationController的view还原到原始位置。

最终代码下载


分享给小伙伴们:
本文标签: UINavigationiOS

相关文章

发表评论愿您的每句评论,都能给大家的生活添色彩,带来共鸣,带来思索,带来快乐。

CopyRight © 2015-2016 QingPingShan.com , All Rights Reserved.

清屏网 版权所有 豫ICP备15026204号