zoukankan      html  css  js  c++  java
  • UIWebview加载H5界面侧滑返回上一级

    一、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

  • 相关阅读:
    MYSQL 字符串操作
    关于IT企业组织架构的一些思考
    关于《Java封面》一些感想
    浏览器缓存资源文件的问题
    为什么《一个程序员怎么能做出这样的事情》?
    TCP/IP协议中的参数说明
    java编译器对代码的优化
    事务属性小结
    事务的编程模型
    从阿里云os和Google之争看开源协议
  • 原文地址:https://www.cnblogs.com/yang-shuai/p/6529511.html
Copyright © 2011-2022 走看看