×
广告

Hybrid小技巧:通过js调用原生对话框(Android)

96
YuTao_
2018.05.08 10:36 字数 272

在web开发中,我们会经常使用到Alert、Confirm、Prompt等对话框,但是web自带的对话框又很丑,很多时候我们不得不自己写一些弹窗或者用一些第三方库来实现,但是在Hybrid开发中,我们可以通过一些简单操作,在web页面用js调用原生的对话框,让web页面更接近原生体验。

先看看效果吧

效果图.gif

下面看看具体是怎么实现的

assets文件夹下面新建一个index.html

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
</head>

<body>
<p>通过JS调用三种不同的原生对话框</p>

<p>Alert对话框</p>
<p>
    <input type="submit" name="Submit1" value="展示Alert对话框" onclick="alertFun()" />
</p>
<p>Confirm对话框</p>
<p>
    <input type="submit" name="Submit2" value="展示Confirm对话框" onclick="confirmFun()" />
</p>
<p>Prompt对话框</p>
<p>
    <input type="submit" name="Submit3" value="展示Prompt对话框" onclick="promptFun()" />
</p>
<script language="JavaScript">
        function alertFun() {
            alert("这是js的alert,但是弹出的是原生的Alert警告对话框哦!")
        };

        function confirmFun() {
            if (confirm("访问百度?")) {
                location.href = "http://www.baidu.com";
            } else alert("取消访问!");
        };

        function promptFun() {
            var word = prompt("对YuTao说的话写在下面吧", "对YuTao说的话写在这里吧");
            if (word) {
                alert("你输入了:" + word)
            } else {
                alert("呵呵,你什么都没写!");
            }
        }
    </script>
</body>

</html>

WebView布局

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <WebView
        android:id="@+id/wView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:padding="5dp" />

</LinearLayout>

新建一个prompt_view布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <TextView
        android:id="@+id/text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <EditText
        android:id="@+id/edit"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:scrollHorizontally="true"
        android:selectAllOnFocus="true" />

</LinearLayout>  

加载web页面到webview

wView = (WebView) findViewById(R.id.wView);
//获得WebSetting对象,支持js脚本,可访问文件,支持缩放,以及编码方式
WebSettings webSettings = wView.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setAllowFileAccess(true);
webSettings.setBuiltInZoomControls(true);
webSettings.setDefaultTextEncodingName("UTF-8");
//设置WebChromeClient,处理网页中的各种js事件
wView.setWebChromeClient(new MyWebChromeClient());
wView.loadUrl("file:///android_asset/index.html");

自定义一个类实现WebChromeClient类,并重写三种不同对话框

 //分别重写onJsAlert,onJsConfirm,onJsPrompt方法
    class MyWebChromeClient extends WebChromeClient {
        @Override
        public boolean onJsAlert(WebView view, String url, String message,
                                 final JsResult result) {
            //创建一个Builder来显示网页中的对话框
            new Builder(MainActivity.this).setTitle("Alert对话框").setMessage(message)
                    .setPositiveButton("确定", new OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            result.confirm();
                        }
                    }).setCancelable(false).show();
            return true;
        }

        @Override
        public boolean onJsConfirm(WebView view, String url, String message,
                                   final JsResult result) {
            new Builder(MainActivity.this).setTitle("Confirm对话框").setMessage(message)
                    .setPositiveButton("确定", new OnClickListener() {

                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            result.confirm();
                        }
                    })
                    .setNegativeButton("取消", new DialogInterface.OnClickListener() {

                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            result.cancel();
                        }
                    }).setCancelable(false).show();
            return true;
        }

        @Override
        public boolean onJsPrompt(WebView view, String url, String message,
                                  String defaultValue, final JsPromptResult result) {
            //①获得一个LayoutInflater对象factory,加载指定布局成相应对象
            final LayoutInflater inflater = LayoutInflater.from(MainActivity.this);
            final View myview = inflater.inflate(R.layout.prompt_view, null);
            //设置TextView对应网页中的提示信息,edit设置来自于网页的默认文字
            ((TextView) myview.findViewById(R.id.text)).setText(message);
            ((EditText) myview.findViewById(R.id.edit)).setText(defaultValue);
            //定义对话框上的确定按钮
            new Builder(MainActivity.this).setTitle("Prompt对话框").setView(myview)
                    .setPositiveButton("确定", new OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            //取得输入的值,传给网页处理
                            String value = ((EditText) myview.findViewById(R.id.edit)).getText().toString();
                            result.confirm(value);
                        }
                    })
                    .setNegativeButton("取消", new OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            result.cancel();
                        }
                    }).show();
            return true;
        }

    }

其实原理很简单,就是自定义一个类实现WebChromeClient类,并重写三种不同对话框的处理方法

从html的js代码可以看,我们在web中只写了最简单的js语法,没有其他任何处理,所以这种实现还得Android配合。

最后送上源码:源码

HybridTry
Web note ad 1