java 如何在 WebView 中禁用软键盘

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17672116/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-01 14:37:39  来源:igfitidea点击:

How disable softkeyboard in WebView

javaandroidwebviewandroid-softkeyboard

提问by Tapa Save

I need disable open softkeyboard in my WebView and in all edittexts in WebView (I do not access to thay because its is in WebView).

我需要在我的 WebView 和 WebView 中的所有编辑文本中禁用打开软键盘(我无法访问 thay,因为它在 WebView 中)。

I try use 'android:windowSoftInputMode="stateAlwaysHidden"' in my Manifest file, but keyboard popup on when I click in editable field.

我尝试在我的 Manifest 文件中使用 'android:windowSoftInputMode="stateAlwaysHidden"',但是当我在可编辑字段中单击时会弹出键盘。

What is right solution for disable softkeyboard in WebView?

在 WebView 中禁用软键盘的正确解决方案是什么?

EDIT:

编辑:

I find solution (thanks @g00dy in this post and @Kachi in post https://stackoverflow.com/a/9108219/1665964) for close keyboard after it open:

我找到解决方案(感谢这篇文章中的@g00dy 和帖子https://stackoverflow.com/a/9108219/1665964 中的@Kachi )在打开后关闭键盘:

public class ActivityBrowser extends Activity 
 {
   private static WebView        webviewHTML;
   private static View           viewRootHTML;
   private static int            iViewRootHTMLHeightDifferent; 
   public  static Context        contextBrowser;

    {
      contextBrowser = this;
    }


   public class webViewClient extends WebViewClient
    {
      @Override
      public void onPageStarted( WebView view, String url, Bitmap favicon)
       {
         if( view == webviewHTML)  super.onPageStarted( view, url, favicon);
       }

      @Override
      public void onPageFinished( WebView view, String url)
       {
         if( view == webviewHTML)  super.onPageFinished( view, url);
       }

      @Override
      public boolean shouldOverrideUrlLoading( WebView view, String url)
       {
         if( view == webviewHTML)  view.loadUrl( url);
         return false;
         // return super.shouldOverrideUrlLoading( view, url);
       }

      @Override
      public void onReceivedError( WebView view, int errorCode, String description, String failingUrl)
       {
         if( view == webviewHTML)  ApplicationLeta.fPopup( getString( R.string.sPopupErrorSiteOpen) + " : " + description);
         // ActivityBrowser.this.finish();
       }

      public void onReceivedSslError( WebView view, SslErrorHandler handler, SslError error)
       {
         if( view == webviewHTML)  handler.proceed();
       }
    }


   @Override
   public boolean dispatchTouchEvent( MotionEvent motionEvent)
    {
      super.dispatchTouchEvent( motionEvent);

      if( motionEvent.getAction() == MotionEvent.ACTION_MOVE)  return true;

      if( motionEvent.getAction() == MotionEvent.ACTION_UP)
        {
          // do something
        }

      if( motionEvent.getAction() == MotionEvent.ACTION_UP)
        {
          // do something
        }
      return false;
    }


   @Override
   public void onBackPressed()
    {
    }


   @Override
   public void onWindowFocusChanged( boolean eFocus)
    {
      super.onWindowFocusChanged( eFocus);
      if( eFocus == false)
        {
          fKeyboardClose();

          new Thread( new Runnable()
           {
             @Override
             public void run()
              {
                try
                  {
                    Instrumentation inst = new Instrumentation();
                    inst.sendKeyDownUpSync( KeyEvent.KEYCODE_BACK);
                  }
                 catch( Exception e) {}
              }
           } ).start();
        }
    }


   private void fKeyboardClose()
    {
      InputMethodManager inputMethodManager = (InputMethodManager)getSystemService( Activity.INPUT_METHOD_SERVICE);
      inputMethodManager.hideSoftInputFromWindow( getCurrentFocus().getWindowToken(), 0);
    }


   public OnGlobalLayoutListener onGlobalLayoutListener = new OnGlobalLayoutListener()
    {
      @Override
      public void onGlobalLayout()
       {
         Rect rect = new Rect();
         viewRootHTML.getWindowVisibleDisplayFrame( rect);
         iViewRootHTMLHeightDifferent = viewRootHTML.getRootView().getHeight() - (rect.bottom - rect.top);
         if( iViewRootHTMLHeightDifferent > 50)  fKeyboardClose();
       }
    };

   @SuppressWarnings( "deprecation")
   @SuppressLint( "SetJavaScriptEnabled")
   public void onCreate( Bundle savedInstanceState)
    {
      super.onCreate( savedInstanceState);
      setContentView( R.layout.browser);

      if( savedInstanceState == null)
        {
          viewRootHTML = findViewById( R.id.linearLayoutHTML);
          viewRootHTML.getViewTreeObserver().addOnGlobalLayoutListener( onGlobalLayoutListener);

          webviewHTML = (WebView) findViewById( R.id.webviewHTML);
          WebSettings webSettings = webviewHTML.getSettings();
          webSettings.setJavaScriptEnabled( true);
          webSettings.setJavaScriptCanOpenWindowsAutomatically( true);
          webviewHTML.setWebViewClient( new wiewClient());
          webviewHTML.loadUrl( ApplicationLeta.sAppInterviewURL);
        }
    }
 }

This code also close system message "Edit text / Input method" when user longpress on input field.

当用户长按输入字段时,此代码还会关闭系统消息“编辑文本/输入法”。

But! This code close keyboard only after it open. Keyboard stay visible a few miliseconds and user (fast user) can press any key on keyboard. This is not best situation.

但!此代码仅在打开后关闭键盘。键盘保持可见几毫秒,用户(快速用户)可以按键盘上的任意键。这不是最好的情况。

Maybe exist best way to 100% disable keyboard without open it?

也许存在在不打开键盘的情况下 100% 禁用键盘的最佳方法?

回答by Sunil

This answer worked for me (provided by Android Weblineindia): https://stackoverflow.com/a/29409478/4813198

这个答案对我有用(由 Android Weblineindia 提供):https://stackoverflow.com/a/29409478/4813198

Add following code in main (parent) layout in your layout.xml:

在 layout.xml 的主(父)布局中添加以下代码:

>
>    android:descendantFocusability="blocksDescendants"
>

and set following properties in your webview:

并在您的 webview 中设置以下属性:

>    android:focusable="false"
>    android:focusableInTouchMode="true"

回答by vir us

A kind of hack solution which came to my mind but still does what is required - hides the keyboard so user will not see it:

我想到了一种 hack 解决方案,但仍然可以满足要求 - 隐藏键盘,因此用户不会看到它:

public class WebViewEx extends WebView {

    private Handler mHandler;

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        ensureKeyboard();
        return super.onTouchEvent(event);
    }

    private void ensureKeyboard() {
        if(mHandler == null){
            mHandler = new Handler() {
                @Override
                public void handleMessage(Message msg) {
                    super.handleMessage(msg);
                    closeKeyboard();
                    sendEmptyMessageDelayed(0, 10);
                }
            };
        }
        mHandler.removeCallbacksAndMessages(null);
        mHandler.sendEmptyMessage(0);
        mHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                mHandler.removeCallbacksAndMessages(null);
            }
        }, 300);
    }

    private void closeKeyboard() {
        InputMethodManager inputMethodManager = (InputMethodManager) getContext().getSystemService(Activity.INPUT_METHOD_SERVICE);
        inputMethodManager.hideSoftInputFromWindow(getWindowToken(), 0);
    }

}

Feel free to play with the delays to minimize overhead because of rapid call of a function during the predefined period. I believe optimal values may vary depending on device.

由于在预定义期间快速调用函数,因此可以随意使用延迟以最小化开销。我相信最佳值可能因设备而异。

回答by g00dy

For the keyboard hidden state:

对于键盘隐藏状态:

public void hideSoftKeyboard(View v) {
            Activity activity = (Activity) v.getContext();
            InputMethodManager inputMethodManager = (InputMethodManager)  activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
            inputMethodManager.hideSoftInputFromWindow(activity.getCurrentFocus().getWindowToken(), 0);
        }

To disable the EditTexts:

要禁用EditTexts

Set android:editable="false"in the layout of them EditText.setFocusable(false)in the activity.

android:editable="false"EditText.setFocusable(false)活动中设置它们的布局。

EDIT:

编辑:

To detect the click event in the WebViewuse this:

要检测单击事件,请WebView使用以下命令:

 mWebView.setOnTouchListener(new View.OnTouchListener() {
        public boolean onTouch(View v, MotionEvent event) {
            // The code of the hiding goest here, just call hideSoftKeyboard(View v);
            return false;  
            }     
        }); 

回答by Ashtar

None of this seemed to work Sunil's answer didn't work when i put it in the layout. It led me to look at all the webview settings so i did this in the webview settings and it worked. No keyboard poping up.

当我把它放在布局中时,这些似乎都不起作用 Sunil 的答案不起作用。它让我查看了所有的 webview 设置,所以我在 webview 设置中执行了此操作并且它起作用了。没有弹出键盘。

webview = (WebView) findViewById(R.id.webview);
webview.setFocusableInTouchMode(false);
webview.setFocusable(false);
webview.loadUrl("file:///android_asset/index.html");

回答by Haomin

This answer is for those who do not want the keyboard to pop up, but still want to let the user interact with the input box. Either by hardware keyboards or touch cursor

这个答案是给那些不想弹出键盘,但又想让用户和输入框交互的人的。通过硬件键盘或触摸光标

You could take into consideration of an approach from both Javascript and Android combined.

您可以考虑结合 Javascript 和 Android 的方法。

Case - we have a WebView (In MainActivity) that has input boxes and we don't want Android to pop the soft keyboard after the user click the textbox

案例 - 我们有一个带有输入框的 WebView(在 MainActivity 中),我们不希望 Android 在用户单击文本框后弹出软键盘

Below is how to achieve hiding: We need to use both Javascript and Java to achieve this on Android:

下面是如何实现隐藏: 我们需要同时使用 Javascript 和 Java 在 Android 上实现这一点:



First on Javascript side

首先在 Javascript 方面

We can create a JS file to handle the webpage displayed in the WebView, and apply it to the webview by calling this in the onCreate of the MainActivity i.e:

我们可以创建一个 JS 文件来处理 WebView 中显示的网页,并通过在 MainActivity 的 onCreate 中调用它来将其应用到 webview,即:

ExtendedWebView webView = findViewById(R.id.webview_id);
WebSettings settings = webView.getSettings();
settings.setJavaScriptEnabled(true);
webView.addJavascriptInterface(new MyJavascript(), "_my_javascript");

We can then have the JS checking each of the input boxes on the webpage displayed. And if the input box is the type we are interested in we can then apply this function to the input_box we are interested in:

然后我们可以让 JS 检查显示的网页上的每个输入框。如果输入框是我们感兴趣的类型,我们可以将这个函数应用到我们感兴趣的 input_box 上:

function hide_soft_keyboard(input_box) {
      input_box.addEventListener("click", function() {
              input_box.blur(); // very important call
              input_box.focus();// very important call x2
      });
}

The above code, force OnClick event of the input box to be out of focus first and then focus. And this is the key to hide the keyboard.

上面的代码,强制输入框的OnClick事件先脱焦,再聚焦。这是隐藏键盘的关键。

Second on Java side

Java方面的第二个

Now that we have the JS part taken care of, we need to extend the WebView we are using to override a specific method provided by the WebView class from the framework:

现在我们已经处理了 JS 部分,我们需要扩展我们使用的 WebView 来覆盖框架中 WebView 类提供的特定方法:

@Override 
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
        hideKeyboard();
        return super.onCreateInputConnection(outAttrs);
}

What this method does is to create an input connected to the input_box in the HTML webpage displayed in webview, and this method is called the first time you click an input box on the webview. However, this method will only be called once before the input connection is established, which means if you call hideKeyboard() in this method, it will only work the first time user clicks it, but not the second time.

该方法的作用是在webview中显示的HTML网页中创建一个与input_box相连的input,在webview上第一次点击输入框时调用该方法。但是,这个方法只会在输入连接建立之前被调用一次,这意味着如果你在这个方法中调用 hideKeyboard() ,它只会在用户第一次点击它时起作用,而不是第二次。

BUT, together with the JS change we have earlier, hideKeyboard() will work... How?

但是,连同我们之前的 JS 更改, hideKeyboard() 将起作用......如何?

Since in the JS file we created earlier we forced the onClick of the input box to trigger a blur() call, which closes the current input connection, and followed by a focus() call to let android focus on to the same input_box again, this will force the onCreateInputConnection() method to be called again, which triggers the hideKeyboard() method, allowing user to interact with the input box without the soft keyboard popping out, which successfully answered this question: Disable SoftKeyboard inside a WebView

因为在我们之前创建的 JS 文件中,我们强制输入框的 onClick 触发了一个 blur() 调用,它关闭了当前的输入连接,然后是一个 focus() 调用,让 android 再次聚焦到同一个 input_box,这将强制再次调用 onCreateInputConnection() 方法,从而触发 hideKeyboard() 方法,允许用户在不弹出软键盘的情况下与输入框交互,成功回答了这个问题:Disable SoftKeyboard inside a WebView

private void hideKeyboard() {
        post(new Runnable() {
            @Override
            public void run() {
                InputMethodManager imm = (InputMethodManager) getContext()
                    .getSystemService(Context.INPUT_METHOD_SERVICE);
                if (imm != null) imm.hideSoftInputFromWindow(getRootView().getWindowToken(), 0);
            }
        });
}

Source: I worked on a device with hardware num keys, but has no physical qwerty keyboard, and found out this solution when trying to disable soft keyboard popping out only when input box type is limited to numbers.

来源:我在一个带有硬件数字键的设备上工作,但没有物理 qwerty 键盘,并且在尝试禁用软键盘弹出时发现了这个解决方案,当输入框类型仅限于数字时。

回答by yital9

Try such a solution, it's pretty simple:

试试这样的解决方案,很简单:

final WebView webView = (WebView) findViewById(R.id.webView);
webView.getSettings().setJavaScriptEnabled(true);  

final String js = "javascript: var allInputs = document.getElementsByTagName('input'); for (var i = 0, len = allInputs.length; i < len; ++i) { allInputs[i].readOnly = true;}";
webView.setWebViewClient(new WebViewClient(){
    @Override
    public void onPageFinished(WebView view, String url) {
        if (Build.VERSION.SDK_INT >= 19) {
            view.evaluateJavascript(js, new ValueCallback<String>() {
            @Override
            public void onReceiveValue(String s) { }
        });
        } else {
            view.loadUrl(js);
        }
    }
});
webView.loadUrl("https://www.google.de/");