WebView 在 loadUrl() 期间隐藏了软键盘,这意味着在调用 javascript 时键盘无法保持打开状态 [英] WebView hides soft keyboard during loadUrl(), which means a keyboard cannot stay open while calling javascript

查看:13
本文介绍了WebView 在 loadUrl() 期间隐藏了软键盘,这意味着在调用 javascript 时键盘无法保持打开状态的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Since the way you call javascript on a WebView is through loadUrl("javascript: ... "); The keyboard cannot stay open.

loadUrl() 方法调用 loadUrlImpl() ,它调用了一个名为 clearHelpers() 然后调用 clearTextEntry(),然后调用 嗨deSoftKeyboard() 然后随着键盘的消失,我们变得非常孤独.

The loadUrl() method calls loadUrlImpl() , which calls a method called clearHelpers() which then calls clearTextEntry(), which then calls hideSoftKeyboard() and then we become oh so lonely as the keyboard goes away.

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

As far as I can see all of those are private and cannot be overridden.

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

Has anyone found a workaround for this? Is there a way to force the keyboard to stay open or to call the javascript directly without going through loadUrl()?

无论如何,是否可以通过某种方式覆盖 WebView 以防止(私有方法)clearTextEntry() 被调用?

Is there anyway to override the WebView in a way to prevent (the private method) clearTextEntry() from being called?

推荐答案

更新

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

KitKat added a public method for invoking javascript directly: evaluateJavascript()

对于较旧的 api,您可以尝试如下解决方案,但如果我必须再次这样做,我会考虑构建一种兼容性方法,该方法在 KitKat 上使用上述方法,而在旧设备上使用反射来深入研究到内部私有方法:BrowserFrame.stringByEvaluatingJavaScriptFromString()

For older apis, you could try a solution like below, but if I had to do this again I'd look at just building an compatibility method that on KitKat uses the above method and on older devices, uses reflection to drill down to a inner private method: BrowserFrame.stringByEvaluatingJavaScriptFromString()

那么你就可以直接调用javascript了,而不必处理loadUrl并在脚本中添加"javascript:".

Then you could call javascript directly without having to deal with loadUrl and adding "javascript: " to the script.

旧答案

根据 Alok Kulkarni 的要求,我将粗略概述我为此想到的可能解决方法.我还没有真正尝试过,但理论上它应该可以工作.这段代码会比较粗糙,仅作为示例.

As requested by Alok Kulkarni, I'll give a rough overview of a possible workaround I thought of for this. I haven't actually tried it but in theory it should work. This code is going to be rough and is just to serve as an example.

不是通过 loadUrl() 发送调用,而是将 javascript 调用排入队列,然后让 javascript 将它们拉下来.比如:

Instead of sending the calls down through loadUrl(), you queue your javascript calls and then have javascript pull them down. Some thing like:

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("; ");
    }
}

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

Instead of calling loadUrl() call that method. (For making this simple I used a synchronized block, but this might be better suited to a different route. Since javascript runs on its own thread, this will need to be thread safe in some way or another).

那么你的 WebView 就会有一个这样的界面:

Then your WebView would have an interface like this:

public class JSInterface {

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

}

这会返回一个带有待处理命令的字符串并清除它们,这样它们就不会再次返回.

That returns a String with the pending commands and clears them so they don't get returned again.

您可以像这样将其添加到 WebView:

You would add it to the WebView like this:

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

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

Then in your javascript you would set some interval in which to flush the pending commands. On each interval it would call JSInterface.getPendingJS() which would return a String of all of the pending commands and then you could execute them.

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

You could further improve this by adding a check in the execJS method to see if a EditText field exists in the WebView and is in focus. If there is one, then you would use this queueing method, but if there wasn't one in focus then you could just call loadUrl() like normal. That way it only uses this workaround when it actually needs to.

这篇关于WebView 在 loadUrl() 期间隐藏了软键盘,这意味着在调用 javascript 时键盘无法保持打开状态的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆