更新:

  • 时间:2017年4月20日10:32:32
    关于302重定向的问题大家可以去看看

前言:

今天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);复制代码