如何在WebView中禁用软键盘

11

我需要禁用我的WebView中的软键盘以及所有编辑框中的软键盘(因为它们在WebView中,我无法访问它们)。

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

如何在WebView中禁用软键盘?

编辑:

我找到了解决方案(感谢@g00dy在这个帖子和@Kachi在https://dev59.com/WHI95IYBdhLWcg3wyRM0#9108219中的帖子),可以在键盘打开后关闭它:

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

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

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

也许存在一种更好的方式可以在不打开键盘的情况下完全禁用键盘吗?

6个回答

9
这个回答对我有帮助(由Android Weblineindia提供):https://dev59.com/sonca4cB1Zd3GeqP9FDp#29409478 在您的layout.xml中的主(父)布局中添加以下代码:
>
>    android:descendantFocusability="blocksDescendants"
>

请在您的Webview中设置以下属性:
>    android:focusable="false"
>    android:focusableInTouchMode="true"

2
如果我想通过编程重新激活软键盘呢? - Sergiob
我需要手动从应用程序的内部选项进行更改。 - K K Muhammed Fazil

2

似乎这些都没有起作用,当我将Sunil的答案放入布局中时,它并没有起作用。这让我查看了所有的webview设置,所以我在webview设置中进行了操作,然后它就起作用了。没有键盘弹出。

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

1
我想到了一种折中的解决方案,可以隐藏键盘,让用户看不到它,但仍能完成所需操作。
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);
    }

}

随意调整延迟以最小化预定义时间段内函数的快速调用所带来的开销。我相信最优值可能因设备而异。


这有点太hacky了。 - Alberto M

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

1
我无法更改EditText的属性,因为我只有我的WebView。 - Tapa Save
你没有权限更改WebView中的EditText属性,为什么?WebView的内容是什么?你是在可控制的网页下还是其他随机网页下进行可视化呈现? - g00dy
你应该尝试检测点击,我会编辑我的帖子。 - g00dy
我已经有了onTouch代码。我在onTouch中添加了您的隐藏键盘代码(在事件.getAction()== MotionEvent.ACTION_UP的情况下),但是键盘总是弹出 :( - Tapa Save
为什么不尝试使用通用的 onTouch(),而不指定事件。这将让您看到是否基本上可以工作。然后,如果您愿意,可以尝试过滤不同的事件,但是首先请检查此事件。 - g00dy
显示剩余6条评论

1
本答案适用于不想让键盘弹出,但仍希望用户与输入框进行交互的人。无论是硬件键盘还是触摸光标

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

情况 - 我们有一个WebView(在MainActivity中),其中包含输入框,我们不希望Android在用户单击文本框后弹出软键盘

以下是如何实现隐藏:我们需要在Android上使用Javascript和Java两者来实现:

首先是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检查网页上显示的每个输入框。如果输入框是我们感兴趣的类型,我们就可以将此功能应用于我们感兴趣的输入框:
function hide_soft_keyboard(input_box) {
      input_box.addEventListener("click", function() {
              input_box.blur(); // very important call
              input_box.focus();// very important call x2
      });
}

上述代码将强制点击事件先失去焦点,然后再重新聚焦。这是隐藏键盘的关键。
Java端第二步:
既然我们已经处理了JS部分,我们需要扩展正在使用的WebView以覆盖框架提供的特定方法:
@Override 
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
        hideKeyboard();
        return super.onCreateInputConnection(outAttrs);
}

这个方法的作用是创建一个与 webview 中 input_box 相连接的输入框,这个方法会在第一次点击 webview 中的输入框时被调用。但是,在建立输入连接之前,该方法只会被调用一次,这意味着如果你在此方法中调用 hideKeyboard(),它只会在用户第一次点击时生效,而不是第二次。 但是,结合我们之前的 JS 更改,hideKeyboard() 将会如何工作呢? 由于在之前创建的 JS 文件中,我们强制 onClick 事件触发 blur() 调用,这将关闭当前的输入连接,并跟随 focus() 调用,让 Android 再次关注到同一个 input_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键盘,当我试图在输入框类型限制为数字时禁用软键盘弹出时,发现了这个解决方案。


-2

试试这个解决方案,它非常简单:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接