Skip to content

Latest commit

 

History

History
477 lines (381 loc) · 20 KB

README.md

File metadata and controls

477 lines (381 loc) · 20 KB
private ViewPager vpArticle;
private MyPagerAdapter myAdapter;
private List<View> mListViews;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);


    myAdapter = new MyPagerAdapter();
    vpArticle = (ViewPager) findViewById(R.id.viewpager);

    mListViews = new ArrayList<View>();
    addView(mListViews, "https://www.baidu.com");
    addView(mListViews, "https://123.sogou.com/");
    addView(mListViews, "http://lcoc.top/2.2/");

    vpArticle.setAdapter(myAdapter);
}

private void addView(List<View> viewList,String url) {
    WebView webView=new WebView(this);
    WebSettings webSettings=webView.getSettings();

///JS处理
    webSettings.setJavaScriptEnabled(true);   //支持JS插件
    // 若加载的 html 里有JS 在执行动画等操作,会造成资源浪费(CPU、电量)
    // 在 onStop 和 onResume 里分别把 setJavaScriptEnabled() 给设置成 false 和 true 即可

    webSettings.setPluginState(WebSettings.PluginState.ON);  //设置是否支持flash插件
    webSettings.setJavaScriptCanOpenWindowsAutomatically(true);   //支持通过JS打开窗口



///缩放处理
    //设置自适应屏幕,两者合用
    webSettings.setUseWideViewPort(true);  //将图片调整到合适webview的大小
    webSettings.setLoadWithOverviewMode(true);  //缩放至屏幕的大小


    webSettings.setSupportZoom(true);      //支持缩放,默认为true,与BuiltInZoomControls一起用
    webSettings.setBuiltInZoomControls(true);   //设置内置的缩放控件,这个取决于setSupportZoom(),
    // 若setSupportZoom(false),则该WebView不可缩放,这个不管设置什么都不能缩放。
    webSettings.setDisplayZoomControls(false);  //隐藏原生的缩放控件

///内容布局
    webSettings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN); //支持内容重新布局
    webSettings.setSupportMultipleWindows(true);  //多窗口

//文件缓存
    webSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);  //关闭webview中缓存
    webSettings.setAllowFileAccess(true);   //设置可以访问文件
    webSettings.setDomStorageEnabled(true); //开启DOM storage API功能

    //离线加载
    webSettings.setDatabaseEnabled(true);   //开启 database storage API 功能
    webSettings.setAppCacheEnabled(true);   //开启 Application Caches 功能
    webSettings.setAppCachePath("path"); //设置  Application Caches 缓存目录
    /**
     * 每个 Application 只调用一次 WebSettings.setAppCachePath(),WebSettings.setAppCacheMaxSize()
     */


    ///其他设置
    webSettings.setNeedInitialFocus(true);  //当webview调用requestFocus时为webview设置节点
    webSettings.setLoadsImagesAutomatically(true);  //支持自动加载图片
    webSettings.setDefaultTextEncodingName("utf-8");  //设置编码格式
    webSettings.setDefaultFontSize(20); // 设置默认字体的大小

    webView.loadUrl(url);

    viewList.add(webView);




}

private class MyPagerAdapter extends PagerAdapter{
    @Override
    public int getCount() { return mListViews.size(); }

    @Override
    public boolean isViewFromObject(View view, Object object) {  return view==object;  }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        ((ViewPager)container).removeView(mListViews.get(position));
    }

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        ((ViewPager)container).addView(mListViews.get(position),0);
        return mListViews.get(position);
    }
}


/**
 * 方式1. 加载一个网页:  webView.loadUrl("http://www.google.com/");
 * 方式2:加载apk包中的html页面:  webView.loadUrl("file:///android_asset/test.html");
 * 方式3:加载手机本地的html页面:  webView.loadUrl("content://com.android.htmlfileprovider/sdcard/test.html");
 * 方式4:加载 HTML 页面的一小段内容
 *  WebView.loadData(String data, String mimeType, String encoding)
 *    参数1:需要截取展示的内容,内容里不能出现 ’#’, ‘%’, ‘\’ , ‘?’ 这四个字符,若出现了需用 %23, %25, %27, %3f 对应来替代,否则会出现异常
 *    参数2:展示内容的类型
 *    参数3:字节码
 */



/**
 WebView的状态
    激活WebView为活跃状态,能正常执行网页的响应
    webView.onResume();
     当页面被失去焦点被切换到后台不可见状态,需要执行onPause
     通过onPause动作通知内核暂停所有的动作,比如DOM的解析、plugin的执行、JavaScript执行。
     webView.onPause();
     当应用程序(存在webview)被切换到后台时,这个方法不仅仅针对当前的webview而是全局的全应用程序的webview
     它会暂停所有webview的layout,parsing,javascripttimer。降低CPU功耗。
     webView.pauseTimers()
     恢复pauseTimers状态
     webView.resumeTimers();
     销毁Webview
     在关闭了Activity时,如果Webview的音乐或视频,还在播放。就必须销毁Webview
     但是注意:webview调用destory时,webview仍绑定在Activity上
     这是由于自定义webview构建时传入了该Activity的context对象
     因此需要先从父容器中移除webview,然后再销毁webview:
     rootLayout.removeView(webView);
     webView.destroy();
 */



/**
    WebView LifeCycle
    onResume():WebView为活跃状态时回调,可以正常执行网页的响应。
    onPause(): WebView被切换到后台时回调, 页面被失去焦点, 变成不可见状态,
                    onPause动作通知内核暂停所有的动作,比如DOM的解析、plugin的执行、JavaScript执行。
    pauseTimers():  当应用程序被切换到后台时回调,该方法针对全应用程序的WebView,
                    它会暂停所有webview的layout,parsing,javascripttimer。降低CPU功耗。
    resumeTimers(): 恢复pauseTimers时的动作。
    destroy():关闭了Activity时回调, WebView调用destory时, WebView仍绑定在Activity上.
            这是由于自定义WebView构建时传入了该Activity的context对象, 因此需要先从父容器中移除WebView, 然后再销毁webview。
    mRootLayout.removeView(webView);
    mWebView.destroy()
 */



/**
     WebView: 主要负责解析和渲染网页
     WebViewClient: 辅助WebView处理各种通知和请求事件
     WebChromeClient: 辅助WebView处理JavaScript中的对话框, 网址图标和标题等
 */



/**
Android的返回键,
 是否可以后退
 Webview.canGoBack()
 后退网页
 Webview.goBack()
 是否可以前进
 Webview.canGoForward()
 前进网页
 Webview.goForward()
 以当前的index为起始点前进或者后退到历史记录中指定的steps
 如果steps为负数则为后退,正数则为前进
 Webview.goBackOrForward(intsteps)
 如果想要实现WebView内网页的回退, 可以重写onKeyEvent()方法。
     if ((keyCode == KeyEvent.KEYCODE_BACK) && myWebView.canGoBack()) {
        myWebView.goBack();
        return true;
     }
 */



/**
 * 做下拉刷新等功能时, 经常会去判断WebView是否滚动到顶部或者滚动到底部
 *
 * getScrollY();  返回的是当前可见区域的顶端距整个页面顶端的距离,也就是当前内容滚动的距离.
 *
 * getHeight(); getBottom();  返回当前WebView这个容器的高度
 *
 * getContentHeight();  返回的是整个html的高度, 但并不等同于当前整个页面的高度,
 * 因为WebView有缩放功能, 所以当前整个页面的高度实际上应该是原始html的高度再乘上缩放比例
 * if (webView.getContentHeight() * webView.getScale() == (webView.getHeight() + webView.getScrollY())) {
 *    //已经处于底端
 *  }
 *
 * if(webView.getScrollY() == 0){  //处于顶端  }
 *
 * 以上这个方法常用,从API 17开始, mWebView.getScale()被标记为deprecated
 *
 */

/** * 重新加载网页和停止加载 reload(); //刷新页面(当前页面的所有资源都会重新加载) stopLoading(); //停止加载 */

/**
 WebView缓存实现
    在项目中如果使用到WebView控件, 当加载html页面时, 会在/data/data/包名目录下生成database与cache两个文件夹。
    请求的url记录是保存在WebViewCache.db, 而url的内容是保存在WebViewCache文件夹下。
     控制缓存行为
        //优先使用缓存
        webSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);  只要本地有,无论是否过期,或者no-cache,都使用缓存中的数据。
        webSettings.setCacheMode(LOAD_DEFAULT) (默认)根据cache-control决定是否从网络上取数据。
        webSettings.setCacheMode(WebSettings.LOAD_CACHE_ONLY);  不使用网络,只读取本地缓存数据
        WwebSettings.setCacheMode(WebSettings.LOAD_NO_CACHE);   不使用缓存,只从网络获取数据.
     清除缓存
         clearCache(true); //清除网页访问留下的缓存,由于内核缓存是全局的因此这个方法不仅仅针对webview而是针对整个应用程序.
         clearHistory (); //清除当前webview访问的历史记录,只会webview访问历史记录里的所有记录除了当前访问记录.
         clearFormData () //这个api仅仅清除自动完成填充的表单数据,并不会清除WebView存储到本地的数据。
 */



/**
 WebView Cookies
 添加Cookies
     public void synCookies() {
         if (!CacheUtils.isLogin(this)) return;
         CookieSyncManager.createInstance(this);
         CookieManager cookieManager = CookieManager.getInstance();
         cookieManager.setAcceptCookie(true);
         cookieManager.removeSessionCookie();//移除
         String cookies = PreferenceHelper.readString(this, AppConfig.COOKIE_KEY, AppConfig.COOKIE_KEY);
         KJLoger.debug(cookies);
         cookieManager.setCookie(url, cookies);
         CookieSyncManager.getInstance().sync();
     }
 清除Cookies
    CookieManager.getInstance().removeSessionCookie();
 */



/**
 WebView本地资源访问
     当我们在WebView中加载出从web服务器上拿取的内容时,是无法访问本地资源的,
     如assets目录下的图片资源,因为这样的行为属于跨域行为(Cross-Domain),
     而WebView是禁止的。解决这个问题的方案是把html内容先下载到本地,
     然后使用loadDataWithBaseURL加载html。这样就可以在html中使用 file:///android_asset/xxx.png
     的链接来引用包里面assets下的资源了。
    private void loadWithAccessLocal(final String htmlUrl) {
        new Thread(new Runnable() {
            public void run() {
                try {
                    final String htmlStr = NetService.fetchHtml(htmlUrl);
                    if (htmlStr != null) {
                        TaskExecutor.runTaskOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                loadDataWithBaseURL(htmlUrl, htmlStr, "text/html", "UTF-8", "");
                            }
                        });
                        return;
                    }
                } catch (Exception e) {
                    Log.e("Exception:" + e.getMessage());
                }
                TaskExecutor.runTaskOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        onPageLoadedError(-1, "fetch html failed");
                    }
                });
            }
        }).start();
    }
 */


/**
 如何避免WebView内存泄露?
     从网络上下载html的过程应放在工作线程中
     html下载成功后渲染出html的步骤应放在UI主线程,不然WebView会报错
     html下载失败则可以使用我们前面讲述的方法来显示自定义错误界面
 1 不在xml中定义 Webview ,而是在需要的时候在Activity中创建,并且Context使用 getApplicationgContext()
    new WebView(getApplicationContext());
 2 在 Activity 销毁( WebView )的时候,先让 WebView 加载null内容,然后移除 WebView,再销毁 WebView,最后置空。
     @Override
     protected void onDestroy() {
         if (mWebView != null) {
             mWebView.loadDataWithBaseURL(null, "", "text/html", "utf-8", null);
             mWebView.clearHistory();
             ((ViewGroup) mWebView.getParent()).removeView(mWebView);
             mWebView.destroy();
             mWebView = null;
         }
         super.onDestroy();
     }
 */



private class MyWebChromeClient extends WebChromeClient {
    @Override
    public void onProgressChanged(WebView view, int newProgress) {
        super.onProgressChanged(view, newProgress);
        //获得网页的加载进度,显示在右上角的TextView控件中
    }

    @Override
    public void onReceivedTitle(WebView view, String title) {
        super.onReceivedTitle(view, title);
        //获取Web页中的title用来设置自己界面中的title, 当加载出错的时候,
        //比如无网络,这时onReceiveTitle中获取的标题为”找不到该网页”,
    }

    @Override
    public void onReceivedIcon(WebView view, Bitmap icon) {
        super.onReceivedIcon(view, icon);
        //获取Web页中的icon

    }

    @Override
    public boolean onCreateWindow(WebView view, boolean isDialog, boolean isUserGesture, Message resultMsg) {


        return super.onCreateWindow(view, isDialog, isUserGesture, resultMsg);
    }

    @Override
    public void onCloseWindow(WebView window) {
        super.onCloseWindow(window);
    }

    @Override
    public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
        //处理alert弹出框,html 弹框的一种方式

        return super.onJsAlert(view, url, message, result);
    }

    @Override
    public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
        //处理confirm弹出框

        return super.onJsPrompt(view, url, message, defaultValue, result);
    }

    @Override
    public boolean onJsConfirm(WebView view, String url, String message, JsResult result) {
        //处理prompt弹出框

        return super.onJsConfirm(view, url, message, result);
    }
}

private class MyWebViewClient extends WebViewClient{

// shouldOverrideUrlLoading()方法在API >= 24时被标记deprecated, 它的替代方法是 @Override public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) { //复写shouldOverrideUrlLoading()方法,使得打开网页时不调用系统浏览器, 而是在本WebView中显示 // if (Uri.parse(url).getHost().equals("github.com/guoxiaoxing")) { // //如果是自己站点的链接, 则用本地WebView跳转 // view.loadUrl(request.toString()); // return false; // } // //如果不是自己的站点则launch别的Activity来处理 // Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); // mContext.startActivity(intent);

        //返回true: Android 系统会处理URL, 一般是唤起系统浏览器。
        //返回false: 当前 WebView 处理URL。  由于默认放回false,
        // 如果我们只想在WebView内处理链接跳转只需要设置mWebView.setWebViewClient(new WebViewClient())即可
        return true;
    }


    @Override
    public void onPageStarted(WebView view, String url, Bitmap favicon) {
        super.onPageStarted(view, url, favicon);
        //开始载入页面调用的,我们可以设定一个loading的页面,告诉用户程序在等待网络响应
    }

    @Override
    public void onPageFinished(WebView view, String url) {
        super.onPageFinished(view, url);
        //在页面加载结束时调用。我们可以关闭loading 条,切换程序动作
    }

    @Override
    public void onLoadResource(WebView view, String url) {
        super.onLoadResource(view, url);
        //在加载页面资源时会调用,每一个资源(比如图片)的加载都会调用一次。
    }

    @Override
    public void onPageCommitVisible(WebView view, String url) {
        super.onPageCommitVisible(view, url);
    }

    @Override
    public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
        return super.shouldInterceptRequest(view, request);
    }

    @Override
    public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
        super.onReceivedError(view, request, error);
        //加载页面的服务器出现错误时(如404)调用。
    }

    @Override
    public void onReceivedHttpError(WebView view, WebResourceRequest request, WebResourceResponse errorResponse) {
        super.onReceivedHttpError(view, request, errorResponse);
    }

    @Override
    public void onFormResubmission(WebView view, Message dontResend, Message resend) {
        super.onFormResubmission(view, dontResend, resend);
    }

    @Override
    public void doUpdateVisitedHistory(WebView view, String url, boolean isReload) {
        super.doUpdateVisitedHistory(view, url, isReload);
    }

    @Override
    public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
        super.onReceivedSslError(view, handler, error);
        //处理https请求   webView默认是不处理https请求的,页面显示空白
        //handler.proceed();    //表示等待证书响应
        // handler.cancel();      //表示挂起连接,为默认方式
        // handler.handleMessage(null);    //可做其他处理
    }

    @Override
    public void onReceivedClientCertRequest(WebView view, ClientCertRequest request) {
        super.onReceivedClientCertRequest(view, request);
    }

    @Override
    public void onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler, String host, String realm) {
        super.onReceivedHttpAuthRequest(view, handler, host, realm);
    }

    @Override
    public boolean shouldOverrideKeyEvent(WebView view, KeyEvent event) {
        return super.shouldOverrideKeyEvent(view, event);
    }

    @Override
    public void onUnhandledKeyEvent(WebView view, KeyEvent event) {
        super.onUnhandledKeyEvent(view, event);
    }

    @Override
    public void onScaleChanged(WebView view, float oldScale, float newScale) {
        super.onScaleChanged(view, oldScale, newScale);
    }

    @Override
    public void onReceivedLoginRequest(WebView view, String realm, String account, String args) {
        super.onReceivedLoginRequest(view, realm, account, args);
    }

    @Override
    public boolean onRenderProcessGone(WebView view, RenderProcessGoneDetail detail) {
        return super.onRenderProcessGone(view, detail);
    }
}