WebView在loadUrl()期间隐藏了软键盘,这意味着键盘在调用javascript时无法保持打开状态

cot*_*aws 15 javascript keyboard android webview android-softkeyboard

因为你在WebView上调用javascript的方式是通过loadUrl("javascript:..."); 键盘不能保持打开状态.

使用loadURL()方法调用loadUrlImpl() ,它调用一个方法叫做clearHelpers() ,然后调用clearTextEntry() ,然后调用hideSoftKeyboard(),然后我们哦变得如此寂寞键盘消失.

据我所知,所有这些都是私人的,不能被覆盖.

有人找到了解决方法吗?有没有办法强制键盘保持打开或直接调用javascript而不通过loadUrl()?

反正是否以某种方式覆盖WebView以防止(私有方法)clearTextEntry()被调用?

cot*_*aws 12

更新

KitKat添加了一个直接调用javascript的公共方法:evaluateJavascript()

对于较旧的api,您可以尝试类似下面的解决方案,但如果我不得不再次这样做,我会看看只是构建一个兼容性方法,在KitKat上使用上述方法,在旧设备上,使用反射钻取到内部私有方法:BrowserFrame.stringByEvaluatingJavaScriptFromString()

然后你可以直接调用javascript而无需处理loadUrl并添加"javascript: "到脚本中.

老答案

根据Alok Kulkarni的要求,我将粗略概述一下我想到的可行解决方法.我实际上没有尝试过,但从理论上说它应该可行.这段代码很粗糙,只是作为一个例子.

不是通过loadUrl()向下发送调用,而是对javascript调用进行排队,然后让javascript将它们拉下来.就像是:

private final Object LOCK = new Object();
private StringBuilder mPendingJS;

public void execJS(String js) {
    synchronized(LOCK) {
        if (mPendingJS == null) {
            mPendingJS = new StringBuilder();
            mPendingJS.append("javascript: ");
        }
        mPendingJS
            .append(js)
            .append("; ");
    }
}
Run Code Online (Sandbox Code Playgroud)

而不是调用loadUrl()调用该方法.(为了简单起见,我使用了一个synchronized块,但这可能更适合于不同的路由.由于javascript在自己的线程上运行,因此需要以某种方式保证线程安全).

然后你的WebView将有这样的界面:

public class JSInterface {

    public String getPendingJS() {
        synchronized(LOCK) {
            String pendingCommands = mPendingJS.toString();
            mPendingJS.setLength(0);
            mPendingJS.append("javascript: ");
            return pendingCommands;
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

返回带有挂起命令的String并清除它们,以便它们不会再次返回.

您可以将它添加到WebView,如下所示:

mWebView.addJavascriptInterface(new JSInterface(), "JSInterface");

然后在您的javascript中,您将设置一些时间间隔来刷新挂起的命令.在每个时间间隔,它将调用JSInterface.getPendingJS()哪个将返回所有待处理命令的字符串,然后您可以执行它们.

您可以通过在execJS方法中添加一个检查来进一步改进这一点,以查看WebView中是否存在EditText字段并且是焦点.如果有一个,那么你将使用这个排队方法,但如果没有一个焦点,那么你可以像正常一样调用loadUrl().这样它只在实际需要时使用此解决方法.