How to hide soft keyboard on android after clicking outside EditText?

前端 未结 30 1761
醉话见心
醉话见心 2020-11-22 11:46

Ok everyone knows that to hide a keyboard you need to implement:

InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
imm.hi         


        
相关标签:
30条回答
  • 2020-11-22 12:11

    I got this working with a slight variant on Fernando Camarago's solution. In my onCreate method I attach a single onTouchListener to the root view but send the view rather than activity as an argument.

            findViewById(android.R.id.content).setOnTouchListener(new OnTouchListener() {           
            public boolean onTouch(View v, MotionEvent event) {
                Utils.hideSoftKeyboard(v);
                return false;
            }
        });
    

    In a separate Utils class is...

        public static void hideSoftKeyboard(View v) {
        InputMethodManager imm = (InputMethodManager) v.getContext().getSystemService(Context.INPUT_METHOD_SERVICE); 
        imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
    }
    
    0 讨论(0)
  • 2020-11-22 12:12

    Well I manage to somewhat solve the problem, I overrode the dispatchTouchEvent on my activity, there I am using the following to hide the keyboard.

     /**
     * Called to process touch screen events. 
     */
    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
    
        switch (ev.getAction()){
            case MotionEvent.ACTION_DOWN:
                touchDownTime = SystemClock.elapsedRealtime();
                break;
    
            case MotionEvent.ACTION_UP:
                //to avoid drag events
                if (SystemClock.elapsedRealtime() - touchDownTime <= 150){  
    
                    EditText[] textFields = this.getFields();
                    if(textFields != null && textFields.length > 0){
    
                        boolean clickIsOutsideEditTexts = true;
    
                        for(EditText field : textFields){
                            if(isPointInsideView(ev.getRawX(), ev.getRawY(), field)){
                                clickIsOutsideEditTexts = false;
                                break;
                            }
                        }
    
                        if(clickIsOutsideEditTexts){
                            this.hideSoftKeyboard();
                        }               
                    } else {
                        this.hideSoftKeyboard();
                    }
                }
                break;
        }
    
        return super.dispatchTouchEvent(ev);
    }
    

    EDIT: The getFields() method is just a method that returns an array with the textfields in the view. To avoid creating this array on every touch, I created an static array called sFields, which is returned at the getFields() method. This array is initialized on the onStart() methods such as:

    sFields = new EditText[] {mUserField, mPasswordField};


    It is not perfect, The drag event time is only based on heuristics so sometimes it doesnt hide when performing long clics, and I also finished by creating a method to get all the editTexts per view; else the keyboard would hide and show when clicking other EditText.

    Still, cleaner and shorter solutions are welcome

    0 讨论(0)
  • 2020-11-22 12:12

    Activity

     @Override
     public boolean dispatchTouchEvent(MotionEvent ev) {
         ScreenUtils.hideKeyboard(this, findViewById(android.R.id.content).getWindowToken());
         return super.dispatchTouchEvent(ev);
     }
    

    ScreenUtils

     public static void hideKeyboard(Context context, IBinder windowToken) {
         InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
         imm.hideSoftInputFromWindow(windowToken, InputMethodManager.HIDE_NOT_ALWAYS);
     }
    
    0 讨论(0)
  • 2020-11-22 12:13

    Use OnFocusChangeListener.

    For example:

    editText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
        @Override
        public void onFocusChange(View v, boolean hasFocus) {
            if (!hasFocus) {
                hideKeyboard();
            }
        }
    });
    

    Update: you also may override onTouchEvent() in your activity and check coordinates of the touch. If coordinates are outside of EditText, then hide the keyboard.

    0 讨论(0)
  • 2020-11-22 12:14

    A more Kotlin & Material Design way using TextInputEditText (this approach is also compatible with EditTextView)...

    1.Make the parent view(content view of your activity/fragment) clickable and focusable by adding the following attributes

    android:focusable="true"
    android:focusableInTouchMode="true"
    android:clickable="true"
    

    2.Create an extension for all View (inside a ViewExtension.kt file for example) :

    fun View.hideKeyboard(){
        val inputMethodManager = context.getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager
        inputMethodManager.hideSoftInputFromWindow(this.windowToken, 0)
    }
    

    3.Create a BaseTextInputEditText that inherit of TextInputEditText. Implement the method onFocusChanged to hide keyboard when the view is not focused :

    class BaseTextInputEditText(context: Context?, attrs: AttributeSet?) : TextInputEditText(context, attrs){
        override fun onFocusChanged(focused: Boolean, direction: Int, previouslyFocusedRect: Rect?) {
            super.onFocusChanged(focused, direction, previouslyFocusedRect)
            if (!focused) this.hideKeyboard()
        }
    }
    

    4.Just call your brand new custom view in your XML :

    <android.support.design.widget.TextInputLayout
            android:id="@+id/textInputLayout"
            ...>
    
            <com.your_package.BaseTextInputEditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                ... />
    
        </android.support.design.widget.TextInputLayout> 
    

    That's all. No need to modify your controllers (fragment or activity) to handle this repetitive case.

    0 讨论(0)
  • 2020-11-22 12:17

    Instead of iterating through all the views or overriding dispatchTouchEvent.

    Why Not just override the onUserInteraction() of the Activity this will make sure keyboard dismisses whenever the user taps outside of EditText.

    Will work even when EditText is inside the scrollView.

    @Override
    public void onUserInteraction() {
        if (getCurrentFocus() != null) {
            InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
            imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
        }
    }
    
    0 讨论(0)
提交回复
热议问题