一、UIWebview的发现

问题发现:当UIWebview王深层次点击的时候,返回时需要webView执行goBack方法一级一级返回,这样看到的webView只是在该界面执行刷新,并看不到类似iOS系统那样的侧滑返回上一级。

实现思想:我们可以从第一级开始对每一级webView加载的内容,截取屏幕的图片并保存到数组中,然后给webView添加pan手势,判断手势侧滑的时候,添加UIImageView显示视频里面截图的内容,同时调整webView的x值和imageView的x值,当侧滑完全返回时,移除imageView,webView并重新加载新的链接,即可实现侧滑返回效果。

二、实现代码如下

1、DLPanableWebView.h代码实现

#import <UIKit/UIKit.h>

@class DLPanableWebView;

@protocol DLPanableWebViewDelegate <NSObject>

// 0 成功  1 完成   2 失败

- (void)webViewLoadState:(NSInteger)state;

@optional

- (void)panableWebView:(DLPanableWebView *)webView panPopGesture:(UIPanGestureRecognizer *)pan;

@end

@interface DLPanableWebView : UIWebView

@property(nonatomic, weak) id <DLPanableWebViewDelegate> panDelegate;

@property(nonatomic, assign) BOOL enablePanGesture;

- (void)goBack;

@end

2、DLPanableWebView.m代码实现

#import "DLPanableWebView.h"

@interface DLPanableWebView()<UIWebViewDelegate>

@property (nonatomic, strong) UIGestureRecognizer* popGesture;

@property (nonatomic, weak) id <UIWebViewDelegate> originDelegate;

@property (nonatomic, strong)UIImageView *historyView;

@property (nonatomic, strong) NSMutableArray *historyStack;

@property (nonatomic, assign) CGFloat panStartX;

@end

@implementation DLPanableWebView

+ (UIImage *)screenshotOfView:(UIView *)view {

UIGraphicsBeginImageContextWithOptions(view.frame.size, YES, 0.0);

if ([view respondsToSelector:@selector(drawViewHierarchyInRect:afterScreenUpdates:)]) {

[view drawViewHierarchyInRect:view.bounds afterScreenUpdates:YES];

}

else{

[view.layer renderInContext:UIGraphicsGetCurrentContext()];

}

UIImage *image = UIGraphicsGetImageFromCurrentImageContext();

UIGraphicsEndImageContext();

return image;

}

+ (void)addShadowToView:(UIView *)view{

CALayer *layer = view.layer;

UIBezierPath *path = [UIBezierPath bezierPathWithRect:layer.bounds];

layer.shadowPath = path.CGPath;

layer.shadowColor = [UIColor blackColor].CGColor;

layer.shadowOffset = CGSizeZero;

layer.shadowOpacity = 0.4f;

layer.shadowRadius = 8.0f;

}

- (void)setDelegate:(id<UIWebViewDelegate>)delegate{

self.originDelegate = delegate;

}

- (id<UIWebViewDelegate>)delegate{

return self.originDelegate;

}

- (void)goBack{

[super goBack];

[self.historyStack removeLastObject];

}

- (void)setEnablePanGesture:(BOOL)enablePanGesture{

self.popGesture.enabled = enablePanGesture;

}

- (BOOL)enablePanGesture{

return self.popGesture.enabled;

}

- (NSMutableArray *)historyStack {

if (!_historyStack) {

_historyStack = [NSMutableArray array];

}

return _historyStack;

}

- (UIImageView *)historyView{

if (!_historyView) {

if (self.superview) {

_historyView = [[UIImageView alloc] initWithFrame:self.bounds];

[self.superview insertSubview:_historyView belowSubview:self];

}

}

return _historyView;

}

- (id)init{

if (self = [super init]) {

[self commonInit];

}

return self;

}

- (id)initWithCoder:(NSCoder *)aDecoder{

if (self = [super initWithCoder:aDecoder]) {

[self commonInit];

}

return self;

}

- (id)initWithFrame:(CGRect)frame{

if (self = [super initWithFrame:frame]) {

[self commonInit];

}

return self;

}

- (void)commonInit{

self.popGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panGesture:)];

[self addGestureRecognizer:self.popGesture];

[super setDelegate:self];

[DLPanableWebView addShadowToView:self];

}

- (void)dealloc {

if (self.historyView) {

[self.historyView removeFromSuperview];

self.historyView = nil;

}

}

- (void)layoutSubviews {

[super layoutSubviews];

self.historyView.frame = self.bounds;

}

#pragma mark === gesture===

- (void)panGesture:(UIPanGestureRecognizer *)sender{

if (![self canGoBack] || self.historyStack.count == 0) {

if (self.panDelegate && [self.panDelegate respondsToSelector:@selector(panableWebView:panPopGesture:)]) {

[self.panDelegate panableWebView:self panPopGesture:sender];

}

return;

}

CGPoint point = [sender translationInView:self];

if (sender.state == UIGestureRecognizerStateBegan) {

_panStartX = point.x;

}

else if (sender.state == UIGestureRecognizerStateChanged){

CGFloat deltaX = point.x - _panStartX;

if (deltaX > 0) {

if ([self canGoBack]) {

assert(self.historyStack.count > 0);

self.historyView.image = [self.historyStack.lastObject objectForKey:@"preview"];

self.x = deltaX;

self.historyView.x = -self.width / 2.0f + deltaX / 2.0f;

}

}

}

else if (sender.state == UIGestureRecognizerStateEnded){

CGFloat deltaX = point.x - _panStartX;

CGFloat duration = .5f;

if ([self canGoBack]) {

if (deltaX > self.width / 4.0f) {

[UIView animateWithDuration:(1.0f - deltaX / self.width) * duration animations:^{

self.x = self.width;

self.historyView.x = 0;

[self goBack];

} completion:^(BOOL finished) {

self.x = 0;

[self.historyView removeFromSuperview];

self.historyView = nil;

}];

}

else{

[UIView animateWithDuration:(deltaX/self.bounds.size.width)*duration animations:^{

CGRect rc = self.frame;

rc.origin.x = 0;

self.frame = rc;

rc.origin.x = -self.bounds.size.width/2.0f;

self.historyView.frame = rc;

} completion:^(BOOL finished) {

}];

}

}

}

}

#pragma mark ===uiwebview===

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{

BOOL ret = YES;

if (self.originDelegate && [self.originDelegate respondsToSelector:@selector(webView:shouldStartLoadWithRequest:navigationType:)]) {

ret = [self.originDelegate webView:webView shouldStartLoadWithRequest:request navigationType:navigationType];

}

BOOL isFragmentJump = NO;

if (request.URL.fragment) {

NSString *nonFragmentURL = [request.URL.absoluteString stringByReplacingOccurrencesOfString:[@"#" stringByAppendingString:request.URL.fragment] withString:@""];

if (webView.request.URL.absoluteString) {

NSString *preNonFragmentURL;

if (webView.request.URL.fragment) {

preNonFragmentURL = [webView.request.URL.absoluteString stringByReplacingOccurrencesOfString:[@"#" stringByAppendingString:webView.request.URL.fragment] withString:@""];

}

else{

preNonFragmentURL = webView.request.URL.absoluteString;

}

isFragmentJump = [nonFragmentURL isEqualToString:preNonFragmentURL];

}

}

BOOL isTopLevelNavigation = [request.mainDocumentURL isEqual:request.URL];

BOOL isHTTPOrFile = [request.URL.scheme isEqualToString:@"http"] || [request.URL.scheme isEqualToString:@"https"] || [request.URL.scheme isEqualToString:@"file"];

if (ret && !isFragmentJump && isHTTPOrFile && isTopLevelNavigation) {

if ((navigationType == UIWebViewNavigationTypeLinkClicked || navigationType == UIWebViewNavigationTypeOther) && [[webView.request.URL description] length]) {

if (![[self.historyStack.lastObject objectForKey:@"url"] isEqualToString:[self.request.URL description]]) {

UIImage *curPreview = [DLPanableWebView screenshotOfView:self];

[self.historyStack addObject:@{@"preview":curPreview, @"url":[self.request.URL description]}];

}

}

}

// 点击自带返回,移除一个

if (navigationType == UIWebViewNavigationTypeBackForward) {

[self.historyStack removeLastObject];

}

NSLog(@"数组个数 ===> %zd",self.historyStack.count);

return ret;

}

- (void)webViewDidStartLoad:(UIWebView *)webView {

[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;

if (self.originDelegate && [self.originDelegate respondsToSelector:@selector(webViewDidStartLoad:)]) {

[self.originDelegate webViewDidStartLoad:webView];

}

if ([self.panDelegate respondsToSelector:@selector(webViewLoadState:)]) {

[self.panDelegate webViewLoadState:0];

}

}

- (void)webViewDidFinishLoad:(UIWebView *)webView {

[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;

if (self.originDelegate && [self.originDelegate respondsToSelector:@selector(webViewDidFinishLoad:)]) {

[self.originDelegate webViewDidFinishLoad:webView];

}

if ([self.panDelegate respondsToSelector:@selector(webViewLoadState:)]) {

[self.panDelegate webViewLoadState:1];

}

}

- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error {

[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;

if (self.originDelegate && [self.originDelegate respondsToSelector:@selector(webView:didFailLoadWithError:)]) {

[self.originDelegate webView:webView didFailLoadWithError:error];

}

if ([self.panDelegate respondsToSelector:@selector(webViewLoadState:)]) {

[self.panDelegate webViewLoadState:2];

}

}

@end

UIWebview加载H5界面侧滑返回上一级的更多相关文章

  1. 移动web、webApp、混合APP、原生APP、androd H5混合开发 当无网络下,android怎么加载H5界面

    PhoneGap是一个采用HTML,CSS和JavaScript的技术,创建移动跨平台移动应用程序的快速开发平台.它使开发者能够在网页中调用IOS,Android,Palm,Symbian,WP7,W ...

  2. iOS “请在微信客户端打开链接” UIWebview加载H5页面携带session、cookie、User-Agent信息 设置cookie、清除cookie、设置User-Agent

    公司新开的一个项目..内容基本上是加载H5页面显示..当时觉得挺简单的..后来发现自己掉坑里了..一些心理历程就不说了..说这个项目主要用到的知识点吧..也是自己踩得坑. 首先说说..这个项目上的内容 ...

  3. 新浪微博客户端(13)-使用UIWebView加载OAuth授权界面

    使用UIWebView加载OAuth授权界面 DJOAuthViewController.m #import "DJOAuthViewController.h" @interfac ...

  4. 浅试 Webview 一app 加载 H5小游戏

    整体架构: InventionActivity:实现UI的实例化,基本的按钮Activity之间跳转 GameActivity:实现UI的实例化,Webview的基本使用 MyProgressDial ...

  5. 【iOS进阶】UIWebview加载搜狐视频,自动跳回客户端 问题解决

    UIWebview加载搜狐视频,自动跳回搜狐客户端 问题解决 当我们用UIWebview(iOS端)加载网页视频的时候,会发现,当真机上有搜狐客户端的时候,会自动跳转到搜狐客户端进行播放,这样的体验对 ...

  6. Android使用WebView加载H5页面播放视频音频,退出后还在播放问题解决

    Android中经常会使用到WebView来加载H5的页面,如果H5页面中有音频或者视频的播放时,还没播放完就退出界面,这个时候会发现音频或者视频还在后台播放,这就有点一脸懵逼了,下面是解决方案: 方 ...

  7. iOS Cordova 加载远程界面

    老大说,我们的项目要hybrid,要实现1.html能调用native:2.本地html调用本地html界面:3.能加载远程界面..... 因为我的项目是已有的(以下简称 项目),所以是要在已有的项目 ...

  8. 【Android】首次进入应用时加载引导界面

    参考文章: [1]http://blog.csdn.net/wsscy2004/article/details/7611529 [2]http://www.androidlearner.net/and ...

  9. 【iOS系列】-UIWebView加载网页禁止左右滑动

    [iOS系列]-UIWebView加载网页禁止左右滑动 问题: 做项目时候,用UIWebView加载网页的时候,要求是和微信网页中打开的网页的效果一样,也即是只能上下滑动,不能左右滑动,也不能缩放. ...

随机推荐

  1. Windows Server 2008 IE 无法调整安全级别

    开始”/“程序”/“管理工具”/“服务器管理器”命令,在弹出的服务器管理器窗口中,找到“安全信息”设置项,单击其中的“配置IE ESC”选项,打开如下图所示的IE增强安全配置窗口.

  2. 聊聊、Zookeeper Linux 启动

    Zookeeper 在 windows 下安装比较简单,属于无脑式安装,下载下来双击脚本就可以了.前面的文章中也有介绍,今天我来写写 Linux 下的安装,以及所碰到的坑. 首先,登陆 Linux 系 ...

  3. 如何在window上把你的项目提交到github

    1.首先你需要在https://github.com/ 上注册一个账户 2.注册成功以后,你需要新建一个repository(储藏室),这个用来存放你要上传的项目 点击中间的带加号的图标就可以新建re ...

  4. PROFILE - 库存:物料状态支持 控制【物料状态定义】禁止的事务处理

    PROFILE 库存:物料状态支持

  5. angular使用canvas操作时报错

    最近,用 angular 前端框架为应用登录新增图形验证码认证,由于没有现成的插件,于是便使用canvas+js操作,也是可以正常使用,但是在编译阶段却有个报错: ERROR in src/app/l ...

  6. 每天学一点Python

    9月11日 1.用List实现Python里的?:条件表达式 ["false","true"][判断条件] 其实就是一个List[0]还是List[1]的问题. ...

  7. 安装 Groovy

    brew install groovy http://wiki.jikexueyuan.com/project/groovy-introduction/install-groovy.html

  8. 版本控制工具:SVN和Maven的区别

    一.只有svn的情况 首先考虑没有maven的情况.这样的话,项目组每个开发人员,都需要在本地check out所有的源码. 每次提交之前,需要先更新周边工程的代码.由于工程之间是依赖的,所以很可能需 ...

  9. 关于阿里 weex 的使用与案例

    1. 阿里宣布开源Weex http://mp.weixin.qq.com/s?__biz=MzA4MjA0MTc4NQ==&mid=504089541&idx=1&sn=3a ...

  10. Android开发系列(二十三):实现带图片提示的Toast提示信息框

    Android中的Toast是非经常见的一个消息提示框.可是默认的消息提示框就是一行纯文本.所以我们能够为它设置一些其它的诸如是带上图片的消息提示. 实现这个非常easy: 就是定义一个Layout视 ...