如何在WebView中禁用软键盘

时间:2013-07-16 08:54:28

标签: java android webview android-softkeyboard

我需要在我的WebView和WebView的所有edittexts中禁用打开的软键盘(我不能访问它,因为它在WebView中)。

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

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

修改

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

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

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

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

也许存在最好的方法来100%禁用键盘而不打开它?

6 个答案:

答案 0 :(得分:6)

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

  

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

>
>    android:descendantFocusability="blocksDescendants"
>
  

并在网页视图中设置以下属性:

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

答案 1 :(得分:1)

对于键盘隐藏状态:

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

禁用EditTexts

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

修改

要检测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;  
            }     
        }); 

答案 2 :(得分:0)

我想到了一种黑客攻击解决方案但仍然可以执行所需操作 - 隐藏键盘以便用户不会看到它:

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

}

由于在预定义时间段内快速调用某个功能,因此请尽量使用延迟来最小化开销。我认为最佳值可能因设备而异。

答案 3 :(得分:0)

当我把它放在布局中时,Sunil的答案并没有起作用。它让我看看所有的webview设置,所以我在webview设置中这样做,并且它工作。没有键盘弹出。

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

答案 4 :(得分:0)

此答案适用于那些不想弹出键盘,但仍然希望用户与输入框进行交互的用户。通过硬件键盘或触摸光标

您可以考虑同时使用Javascript和Android的方法。

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

以下是实现隐藏的方法:我们需要同时使用Javascript和Java在Android上实现此目标:


首先在JavaScript方面

我们可以创建一个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");

然后,我们可以让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
      });
}

上面的代码强制输入框的OnClick事件首先失去焦点,然后再聚焦。这是隐藏键盘的键。

Java方面的第二个

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

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

此方法的作用是在webview中显示的HTML网页中创建连接到input_box的输入,并且第一次单击Webview上的输入框时将调用此方法。但是,此方法只会在建立输入连接之前被调用一次,这意味着,如果您在此方法中调用hideKeyboard(),它将仅在用户第一次单击时起作用,而第二次则不起作用。

但是,再加上我们之前进行的JS更改,hideKeyboard()可以正常工作。

由于我们在之前创建的JS文件中,我们强制输入框的onClick触发blur()调用,该调用会关闭当前输入连接,然后再调用focus()来让android专注于同一调用再次输入_box,这将强制再次调用onCreateInputConnection()方法,这将触发hideKeyboard()方法,从而允许用户与输入框进行交互而不会弹出软键盘,从而成功回答了以下问题:禁用软键盘在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);
            }
        });
}

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

答案 5 :(得分:-1)

尝试这样的解决方案,非常简单:

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/");