Android開發 在用EditText對話框Dialog退出后實現輸入盤的退出


前言

  在使用繼承的Dialog的方式實現自定義Dialog,如果這個Dialog我們還添加了EditText就會發現一個問題。在輸入盤顯示后,Dialog退出輸入盤不會退出。網上有一些奇怪的解決辦法,最奇怪的是去根據Touch事件判斷Touch坐標來確定是否點擊了空白在隱藏輸入盤,繞了一個大圈來實現,根本就沒仔細閱讀過Dialog的代碼。其實實現退出Dialog的時候隱藏輸入法很簡單,只要重寫Dialog的dismiss()方法即可,為什么寫這篇博客是因為不想大家被錯誤的實現方式而誤導。所以,這里會啰嗦下問題根結。

了解Dialog的退出方式

  在了解隱藏輸入盤之前,需要排列一下Dialog的退出的3種方式:

  1.自定義退出按鍵,點擊后實現dialog.dismiss(); 退出對話框

  2.按back鍵,退出對話框

  3.點擊Dialog外面的空白背景,退出對話框

錯誤的隱藏輸入盤的方式

            @Override
            public void onClickLeft(EditDialog dialog) {
                dialog.dismiss();
                InputMethodManager imm = (InputMethodManager) dialog.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
                imm.hideSoftInputFromWindow(dialog.getEditContent().getWindowToken(), InputMethodManager.RESULT_UNCHANGED_SHOWN);
            }

說說為什么這種方式有問題,其實是因為你調用了dialog.dismiss(); 后在獲取dialog.getEditContent().getWindowToken() 這個token的時候,必定會返回為null。 因為你的Dialog已經退出了。這個EditText已經被Window解除關系。所以我們需要在dimiss方法之前隱藏輸入盤。

容易被誤導難點在哪里?

 看了上面的錯誤例子,我們肯定會在隱藏輸入法后在調用dismiss(); 好像問題已經解決了? 並沒有,因為你只解決了第一種情況 ”自定義退出按鍵,點擊后實現dialog.dismiss(); 退出對話框“ ,還有

按back鍵,退出對話框“ 

點擊Dialog外面的空白背景,退出對話框

這2個情況的調用是Dialog直接在內部封裝調用了dismiss(); 你無法在獲取在dismiss之前操作隱藏輸入盤。 setOnDismissListener();方法 與 setOnCancelListener();方法 都是執行完dismiss();方法后調用的。這里下面的源碼中看到

按外部空白退出的方式

    /**
     * Called when a touch screen event was not handled by any of the views
     * under it. This is most useful to process touch events that happen outside
     * of your window bounds, where there is no view to receive it.
     * 
     * @param event The touch screen event being processed.
     * @return Return true if you have consumed the event, false if you haven't.
     *         The default implementation will cancel the dialog when a touch
     *         happens outside of the window bounds.
     */
    public boolean onTouchEvent(@NonNull MotionEvent event) {
        if (mCancelable && mShowing && mWindow.shouldCloseOnTouch(mContext, event)) {
            cancel();
            return true;
        }
        
        return false;
    }

按返回鍵退出的方式

    /**
     * Called when the dialog has detected the user's press of the back
     * key.  The default implementation simply cancels the dialog (only if
     * it is cancelable), but you can override this to do whatever you want.
     */
    public void onBackPressed() {
        if (mCancelable) {
            cancel();
        }
    }

最后都調用了cancel()方法,而cancel方法最后都調用了dismiss方法,但是這些回調都是用Handler發出去的,所以Dialog都已經關閉(並沒有被銷毀)與window解除了綁定關系了,才會接收到 setOnDismissListener();方法 與 setOnCancelListener(); 這2個回調。所以在這2個回調里寫隱藏輸入盤也是錯誤的。

正確的方式

重寫dismiss方法

    @Override
    public void dismiss() {
        InputMethodManager imm = (InputMethodManager) mEditContent.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.hideSoftInputFromWindow(mEditContent.getWindowToken(), InputMethodManager.RESULT_UNCHANGED_SHOWN);
        super.dismiss();
    }

 

End


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM