weex封装两端webView组件(可加载本地HTML文件)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_33718648/article/details/80274163

       因为项目需求需要显示较为复杂的UI,类似echart的各种统计图。如果封装Android和iOS两端的组件费时费力,因此就想到通过加载本地HTML的方式来实现,但是发现weex的webView组件是没有加载本地html的功能,因此就要自己扩展一下。

        这次封装的webView组件具有较强的通用性,可以在HTML界面的事件传递到weex端,也可以在weex端调用HTML端的js方法,这篇先主要说一下Android端的封装。

       首先按照weex官网提供的组件封装方式新建HtmlComponent类继承WXComponet<WebView>。 

public class Html5Component extends WXComponent<WebView>{
    //我们操作的webView
    private WebView webView;
    //持有组建的当前weex实例
    private WXSDKInstance instance;
    //要加载的HTML文件,此文件放在assets下的html文件夹下
    private String url="file:///android_asset/html/index.html";
    //浏览器加载界面是否完成
    private boolean  mLoadFinish=false;
    //构造方法,获得当前weex实例instance
    public Html5Component(WXSDKInstance instance, WXDomObject dom, WXVContainer parent) {
        super(instance, dom, parent);
        this.instance = instance;
    }
    public Html5Component(WXSDKInstance instance, WXDomObject dom, WXVContainer parent, int type) {
        super(instance, dom, parent, type);
        this.instance = instance;
    }
     //初始化webView设置一些参数
    @SuppressLint("SetJavaScriptEnabled")
    private void init(){
        webView.setInitialScale(100);
        webView.addJavascriptInterface(this,"native");
        WebSettings webSettings=webView.getSettings();
        webSettings.setJavaScriptEnabled(true);
        webSettings.setUseWideViewPort(true); //将图片调整到适合webview的大小
        webSettings.setLoadWithOverviewMode(true); // 缩放至屏幕的大小
        webSettings.setSupportZoom(false); //支持缩放,默认为true。是下面那个的前提。
//        webSettings.setBuiltInZoomControls(false); //设置内置的缩放控件。若为false,则该WebView不可缩放
//        webSettings.setDisplayZoomControls(false); //隐藏原生的缩放控件
        //其他细节操作
        webSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK); //关闭webview中缓存
        webSettings.setSavePassword(false);
        webSettings.setSaveFormData(false);
        webSettings.setAllowFileAccess(false); //设置可以访问文件
        webSettings.setJavaScriptCanOpenWindowsAutomatically(true); //支持通过JS打开新窗口
        webSettings.setLoadsImagesAutomatically(true); //支持自动加载图片

        webSettings.setDefaultTextEncodingName("utf-8");//设置编码格式
        webView.loadUrl(url);
        //复写shouldOverrideUrlLoading()方法,使得打开网页时不调用系统浏览器, 而是在本WebView中显示
        webView.setWebViewClient(new WebViewClient(){
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                view.loadUrl(url);
                return true;
            }
            @RequiresApi(api = Build.VERSION_CODES.KITKAT)
            @Override
            public void onPageFinished(WebView view, String url) {
                    mLoadFinish=true;
                    //这里出发webView组件的finish事件,表示网页已经加载完成 
                    fireEvent("finish");
            }
        });
    }
    //父类的方法,重写这个方法获取path属性的值,这个是我们要加载的html界面
    @Override
    protected WebView initComponentHostView(@NonNull Context context) {
        if(getDomObject().getAttrs().get("path")!=null){
            this.url="file:///android_asset/html/"+getDomObject().getAttrs().get("path").toString();
        }
        //新建webView   
        this.webView = new WebView(context);
        init();
        return this.webView;
    }

    @Override
    protected void onCreate() {
        super.onCreate();
    }
    @Override
    public void onActivityDestroy() {
        super.onActivityDestroy();
    }
    /*要加载的html的文件路径*/
    @WXComponentProp(name = "path")
    public void setPath(String path) {
        this.url="file:///android_asset/html/"+path;
    }
    @RequiresApi(api = Build.VERSION_CODES.KITKAT)
    @Override
    protected void onFinishLayout() {
        super.onFinishLayout();
    }
    //为html提供的通用的触发webView在weex中的对应方法名的事件
    @JavascriptInterface
    public void fireWeexEvent(final String weexMethod, String param){
        String data="";
        if(param!=null){
            data=param;
        }
        final HashMap map=new HashMap();
        map.put("data",data);
        this.webView.post(new Runnable() {
            @Override
            public void run() {
                fireEvent(weexMethod,map);
            }
        });
    }
    /*为weex界面提供的调用h5中js方法的接口*/
    @RequiresApi(api = Build.VERSION_CODES.KITKAT)
    @JSMethod
    public void executeJsFunction(String functionName, String param, final JSCallback callback){
        if (!mLoadFinish){
            return;
        }
        if (!TextUtils.isEmpty(functionName)) {
            webView.evaluateJavascript("javascript:"+functionName+"("+param+")", new ValueCallback<String>() {
                @Override
                public void onReceiveValue(String value) {
                    //此处为 js 返回的结果
                    if(callback!=null){
                        HashMap map=new HashMap();
                        map.put("res",value);
                        callback.invoke(map);
                    }
                }
            });
        }
    }
}

       这里着重说明fireWeexEvent和executeJSFunction这两个方法的用法。

     1、 fireWeexEvent(String weexMethod,String param)

      在HTML中可以调用这个方法出发webView组件上对应weexMethod参数的事件,并可以传递param作为参数到weex端,

      具体写法如下:

      在HTML中在合适的时机通过js执行

native.fireWeexEvent('newEvent','yololiu');

      在weex端接受事件和参数

<webView ref="myWeb" @newEvent="newEvent" path="index.html" @finish="htmlFinish" style="width: 720px; height:600px;">
</webView>
<script>
     var modal=weex.requireModule('modal');
    export default {
        methods: {
            htmlFinish(){
                modal.alert({message:'界面加载完成'});
            },
            newEvent(e){
                 //e.data即为HTML传来的值
                 modal.alert({message:e.data});
            } 
      }
</script>

    2、 executeJSFunction(String functionName,String param,JSCallBack callback)

      使用方法如下:

      在HTML中声明方法doSomeThing

function doSomeThing(param){
      console.log(param);
}

      在weex端调用此方法

<webView ref="myWeb"  path="index.html" @finish="htmlFinish" style="width: 720px; height:600px;">
</webView>
<script>
     var modal=weex.requireModule('modal');
    export default {
        methods: {
            htmlFinish(){
                modal.alert({message:'界面加载完成'});
            },
            excuJS(e){
                this.$refs.myWeb.executeJSFunction('doSomeThing','传到HTML的数据', 
              function(){
                    //执行完成的回调
                   })
            } 
      }
</script>

   封装完成不要忘记在Application中注册组件

WXSDKEngine.registerComponent("webView", Html5Component.class);

  至此Android的webView组件就封装完成了,下一篇简单说一下iOS端的封装 ,原理和Android端基本一致,有iOS开发基础的话可以自己试一下。

猜你喜欢

转载自blog.csdn.net/qq_33718648/article/details/80274163