阅读 10266

Android Webview和ScrollView冲突和WebView使用总结

更新:

前言:

今天review项目中的代码想起来之前修改一个有关Webview和ScrollView冲突的bug:

  • 1.因为Webview和ScrollView都用滑动事件,导致webview很难被滑动,即使被滑动了一点也非常不顺畅
  • 2.解决滑动冲突问题后发现,如果webview嵌套的html中含有轮播图等还是有问题。

解决方案:

其实这两个问题属于同一类的问题,都是Webview和ScrollView滑动时产生的冲突 解决方法很简单:

public class ScrollWebView extends WebView{
    private float startx;
    private float starty;
    private float offsetx;
    private float offsety;

    public ScrollWebView(Context context) {
        super(context);
    }

    public ScrollWebView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public ScrollWebView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                getParent().requestDisallowInterceptTouchEvent(true);
                startx = event.getX();
                starty = event.getY();
                Log.e("MotionEvent", "webview按下");
                break;
            case MotionEvent.ACTION_MOVE:
                Log.e("MotionEvent", "webview滑动");
                offsetx = Math.abs(event.getX() - startx);
                offsety = Math.abs(event.getY() - starty);
                if (offsetx > offsety) {
                    getParent().requestDisallowInterceptTouchEvent(true);
                    Log.e("MotionEvent", "屏蔽了父控件");
                } else {
                    getParent().requestDisallowInterceptTouchEvent(false);
                    Log.e("MotionEvent", "事件传递给父控件");
                }
                break;
            default:
                break;
        }
        return super.onTouchEvent(event);
    }
}
复制代码

自定义一个WebView,重写onTouchEvent方法。判断当手指横向滑动的偏移量(offsetx)大于纵向滑动的偏移量(offsety)时屏蔽父控件的滑动。 解决方法很简单,只要我们在遇到问题的时候多多思考,弄清楚错误的原因,有针对性的研究,绝大数的问题都是可以解决的。

webview使用总结

本来写到这里就想结束了,但是发现写的东西太少了,估计会被骂,既然写的是webview,索性就把我对webview的使用总结整理一下。

数据加载

  • 加载本地资源 webView.loadUrl("file:///android_asset/text.html");
  • 加载网络资源 webView.loadUrl("www.xxx.com/text.html");
  • 添加请求头信息 Map<String,String> map=new HashMap<String,String>(); map.put("User-Agent","Android"); webView.loadUrl("www.xxx.com/text.html",map);
  • 直接加载html代码片段 String html = "数据"; webView.loadDataWithBaseURL(null,html, "text/html", "utf-8",null);

支持JavaScript

  • 设置支持JavaScript WebSettings webSettings = webView.getSettings(); webSettings.setJavaScriptEnabled(true);//设置支持javascript webView.addJavascriptInterface(new JavaScriptInterface(), "tyk");//添加一个对象, 让JS可以访问该对象的方法, 该对象中可以调用JS中的方法

  • JavaScriptInterface 接口定义 private final class JavaScriptInterface {
    //JavaScript调用此方法拨打电话
    public void call(String phone) {
    //startActivity(new Intent(Intent.ACTION_CALL, Uri.parse("tel:" + phone)));
    Toast.makeText(MainActivity.this, phone, Toast.LENGTH_LONG).show();
    }

          //Html调用此方法传递数据  
          public void showcontacts() {  
              String json = "[{\"name\":\"tyk\", \"amount\":\"9999999\", \"phone\":\"1831041486.\"}]";   
              // 调用JS中的方法  
              webView.loadUrl("javascript:show('" + json + "')");  
          }  
      }  
    复制代码

WebViewClient

  • 主要辅助WebView处理各种通知、请求事件 onLoadResource//加载资源时响应 onPageStart//在加载页面时响应 onPageFinish//在加载页面结束时响应 onReceiveError//在加载出错时响应 onReceivedHttpAuthRequest//获取返回信息授权请求

  • 要实现WebView中链接在WebView内部跳转

      webView.setWebViewClient(new WebViewClient() {
          public boolean shouldOverrideUrlLoading(WebView view, String url) {
              view.loadUrl(url);
              return true;
          }
      });
    复制代码

WebChromeClient

  • 主要辅助WebView处理Javascript的对话框,网站图标,网站title,加载进度等   onCloseWindow//关闭WebView   onCreateWindow() //触发创建一个新的窗口   onJsAlert //触发弹出一个对话框   onJsPrompt //触发弹出一个提示   onJsConfirm//触发弹出确认提示   onProgressChanged //加载进度   onReceivedIcon //获取网页icon   onReceivedTitle//获取网页title

  • 加载进度获取title

      webView.setWebChromeClient(new WebChromeClient() {
          @Override
          public void onProgressChanged(WebView view, int newProgress) {
              if (newProgress == 100) {
                  //网页加载完成
              } else {
                  //网页加载中
              }
          }
      });
    复制代码

WebView 缓存控制

    LOAD_CACHE_ONLY//不使用网络,只读取本地缓存数据
    LOAD_DEFAULT//根据cache-control决定是否从网络上取数据。
    LOAD_CACHE_NORMAL//API level 17中已经废弃, 从API level 11开始作用同LOAD_DEFAULT模式
    LOAD_NO_CACHE//不使用缓存,只从网络获取数据.
    LOAD_CACHE_ELSE_NETWORK//只要本地有,无论是否过期,或者no-cache,都使用缓存中的数据。
复制代码

一般都是根据网络来判断缓存使用情况

     //加载缓存形式
        if (CommonUtils.getNetWorkStatus(context)){//判断网络是否可用
            // 根据cache-control决定是否从网络上取数据。
            websettings.setCacheMode(WebSettings.LOAD_NO_CACHE);
        }else{
            // 只要本地有,无论是否过期,或者no-cache,都使用缓存中的数据。
            websettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
        }
复制代码

页面返回

  • 我们有时需要实现回退到上一目录

      @Override
      public boolean onKeyDown(int keyCode, KeyEvent event) {
          if (keyCode == KeyEvent.KEYCODE_BACK) {
              if (webView.canGoBack()) {
                  webView.goBack();//返回上一浏览页面
                  return true;
              } else {
                  finish();//关闭Activity
              }
          }
          return super.onKeyDown(keyCode, event);
      }
    复制代码

其他设置

    WebSettings webSettings = webView.getSettings();
    //支持缩放
    webSettings.setSupportZoom(true);  
    //支持内容重新布局
    webSettings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN); 
     //多窗口
    webSettings.supportMultipleWindows(); 
    //当webview调用requestFocus时为webview设置节点
    webSettings.setNeedInitialFocus(true); 
    //设置支持缩放
    webSettings.setBuiltInZoomControls(true); 
    //支持通过JS打开新窗口
    webSettings.setJavaScriptCanOpenWindowsAutomatically(true); 
    //支持自动加载图片
    webSettings.setLoadsImagesAutomatically(true);  
    //提高渲染的优先级
     websettings.setRenderPriority(WebSettings.RenderPriority.HIGH);
     // 开启H5(APPCache)缓存功能
     websettings.setAppCacheEnabled(true);
    // 开启 DOM storage 功能
     websettings.setDomStorageEnabled(true);
    // 应用可以有数据库
    websettings.setDatabaseEnabled(true);
    // 可以读取文件缓存(manifest生效)
    websettings.setAllowFileAccess(true);
复制代码