仿新浪微博 UINavigationController 向左滑动时显示上一个控制器的View.

实现原理,UINavigationController 的 self.view显示时把当前显示的view截图下来,保存到一个数组中。当push一个view时把上一个view的截图放到self.view后面,当self.view向右拖动时显示上一个view。

NavigationController.m

#import "NavigationController.h"

@interface NavigationController ()
/** 存放每个控制器的全屏截图 */
@property (nonatomic, strong) NSMutableArray *images;
@property (nonatomic, strong) UIImageView *lastVcView;
@property (nonatomic, strong) UIView *cover;
@end @implementation NavigationController - (UIImageView *)lastVcView
{
if (!_lastVcView) {
UIWindow *window = [UIApplication sharedApplication].keyWindow;
UIImageView *lastVcView = [[UIImageView alloc] init];
lastVcView.frame = window.bounds;
self.lastVcView = lastVcView;
}
return _lastVcView;
} - (UIView *)cover
{
if (!_cover) {
UIWindow *window = [UIApplication sharedApplication].keyWindow;
UIView *cover = [[UIView alloc] init];
cover.backgroundColor = [UIColor blackColor];
cover.frame = window.bounds;
cover.alpha = 0.5;
self.cover = cover;
}
return _cover;
} - (NSMutableArray *)images
{
if (!_images) {
self.images = [[NSMutableArray alloc] init];
}
return _images;
} - (void)viewDidLoad {
[super viewDidLoad]; // 拖拽手势
UIPanGestureRecognizer *recognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(dragging:)];
[self.view addGestureRecognizer:recognizer];
} - (void)dragging:(UIPanGestureRecognizer *)recognizer
{
// 假设仅仅有1个子控制器,停止拖拽
if (self.viewControllers.count <= 1) return; // 在x方向上移动的距离
CGFloat tx = [recognizer translationInView:self.view].x;
if (tx < 0) return; if (recognizer.state == UIGestureRecognizerStateEnded || recognizer.state == UIGestureRecognizerStateCancelled) {
// 决定pop还是还原
CGFloat x = self.view.frame.origin.x;
if (x >= self.view.frame.size.width * 0.5) {
[UIView animateWithDuration:0.25 animations:^{
self.view.transform = CGAffineTransformMakeTranslation(self.view.frame.size.width, 0);
} completion:^(BOOL finished) {
[self popViewControllerAnimated:NO];
[self.lastVcView removeFromSuperview];
[self.cover removeFromSuperview];
self.view.transform = CGAffineTransformIdentity;
[self.images removeLastObject];
}];
} else {
[UIView animateWithDuration:0.25 animations:^{
self.view.transform = CGAffineTransformIdentity;
}];
}
} else {
// 移动view
self.view.transform = CGAffineTransformMakeTranslation(tx, 0); UIWindow *window = [UIApplication sharedApplication].keyWindow;
// 加入截图到最后面
self.lastVcView.image = self.images[self.images.count - 2];
[window insertSubview:self.lastVcView atIndex:0];
[window insertSubview:self.cover aboveSubview:self.lastVcView];
}
} /**
* 产生截图
*/
- (void)createScreenShot
{
UIGraphicsBeginImageContextWithOptions(self.view.frame.size, YES, 0.0);
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
[self.images addObject:image];
} - (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated]; if (self.images.count > 0) return; [self createScreenShot];
} - (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
{
[super pushViewController:viewController animated:animated]; [self createScreenShot];
} @end

ios 仿新浪微博 UINavigationController 向左滑动时显示上一个控制器的View.的更多相关文章

  1. Flutter - 添加从左向右滑动,返回上一个页面

    很多App比如微信.IT之家等都支持从屏幕左侧向右滑动,来返回上一个页面. 很多iOS上的App也都支持. 那么这个神奇的手势滑动是怎么实现的呢? 其实非常简单,只需要添加一句话即可. platfor ...

  2. appium 中swipe()方法向左滑动时

    应该在UI Automator Viewer中读取到的例如ImageView [180,600][900,1320],如果要左滑,代码中应该是写为driver.swipe(900,1320,180,6 ...

  3. decltype的参数是左值时,得到一个引用类型

    int* a = new int(10); decltype(*a) 得到的是引用类型:int&

  4. vue 组件来回切换时 记住上一个组件滚动位置(keep-alive)

    记住组件滚动状态: 使用场景:从某列表组件进入详情页,在返回的时候需要保留列表组件状态,包括滚动的高度.这个时候需要keep-alive配合. 方法一:如下情况导航在做普遍用法.前提是使用keep-a ...

  5. VS调试时监视上一个错误代码和错误的文本描述

    以前我都是用GetLastError()然后在MSDN里面查错误原因的.现在才知道有很简便的方法: 在Watch窗口选择一行,然后输入$err,hr

  6. jquery怎么在点击li标签之后添加一个在class,点击下一个li时删除上一个class?

    思路:点击当前li元素后是用removeClass()删除所有兄弟元素(使用siblings()获取)的class样式,然后使用addClass()为当前li添加class. 具体演示如下: 1.HT ...

  7. jquery点击li标签之后在该li标签上添加一个class,点击下一个li时删除上一个li的class

    思路:点击当前li元素后是用removeClass()删除所有兄弟元素(使用siblings()获取)的class样式,然后使用addClass()为当前li添加class 具体演示如下: 1.HTM ...

  8. iOS学习之UINavigationController

    一.UINavigationController      1.UINavigationController:导航控制器,是iOS中最常用的多视图控制器之一,用它来管理多个视图控制器.可以称为是管理控 ...

  9. Android Animation动画实战(一): 从布局动画引入ListView滑动时,每一Item项的显示动画

    前言: 之前,我已经写了两篇博文,给大家介绍了Android的基础动画是如何实现的,如果还不清楚的,可以点击查看:Android Animation动画详解(一): 补间动画 及 Android An ...

随机推荐

  1. Python天天美味(25) - 深入理解yield

    Python天天美味(25) - 深入理解yield - CoderZh - 博客园 Python天天美味(25) - 深入理解yield   yield的英文单词意思是生产,刚接触Python的时候 ...

  2. ZOJ3805:Machine

    In a typical assembly line, machines are connected one by one. The first machine's output product wi ...

  3. [Cocos2d-x]CCSpriteFrameCache的使用

    文档: http://cocos2d.cocoachina.com/document/index/class?url=dc/dda/classcocos2d_1_1_c_c_sprite_frame_ ...

  4. OCaml Language Sucks

    OCaml Language Sucks OCaml Language Sucks

  5. poj 1991 Turning in Homework dp

    这个可以证明必须从两边的任务开始交起,因为中间交的任务可以后面经过的时候再交,所以就变成了一个n*n的dp. #include <iostream> #include <cstdio ...

  6. hello MemSQL 入门安装演示样例

    一,介绍 MemSQL号称世界上最快的分布式关系型数据库,兼容mysql但快30倍,能实现每秒150万次事务.原理是仅用内存并将SQL预编译为C++. 二,部署 官网下载地址:http://www.m ...

  7. 使用POI生成Excel报表

    先把报表模板截图贴上来 下面是POI编写的报表生成类ExcelReport.java package com.jadyer.report; import java.io.FileNotFoundExc ...

  8. Phalcon之 表单(Forms)

    Phalcon中提供了 Phalcon\Forms组件以方便开发人员创建和维护应用中的表单. 以下的样例中展示了主要的用法: <?php use Phalcon\Forms\Form, Phal ...

  9. 【译】ASP.NET MVC 5 教程 - 5:使用 SQL 服务器 LocalDB 创建连接字符串

    原文:[译]ASP.NET MVC 5 教程 - 5:使用 SQL 服务器 LocalDB 创建连接字符串 在上一节中,我们创建了MovieDBContext 类来连接数据库.处理Movie 对象和数 ...

  10. LVS+Keepalived实现高可用负载均衡(转)

    LVS+Keepalived实现高可用负载均衡   一.原理         1.概要介绍         如果将TCP/IP划分为5层,则Keepalived就是一个类似于3~5层交换机制的软件,具 ...