16

i want to hide the soft keyboard when i click out side of editbox in a screen. how can i do this?

Noah Witherspoon
  • 57,021
  • 16
  • 130
  • 131
Sujit
  • 10,512
  • 9
  • 40
  • 45
  • It should do that automatically. As long as you click somewhere that doesn't bring up the keyboard itself – Falmarri Oct 24 '10 at 03:35
  • @Falmarri Initially I thought you were right but I am unable to make this happen on my test app. Tested scenario: 1) click on an EditText-view which brings up the keyboard, 2) click on a SeekBar in the same Fragment 3) click on a RadioButton with focusable=true. Neither 2 nor 3 closed the keyboard. Is this suggested behaviour documented anywhere? – Nilzor Mar 16 '13 at 10:48

10 Answers10

58

Had to edit this one to get it to work. Added a check to see if the focused view is a EditText.

@Override
public boolean dispatchTouchEvent(MotionEvent event) {

    View v = getCurrentFocus();
    boolean ret = super.dispatchTouchEvent(event);

    if (v instanceof EditText) {
        View w = getCurrentFocus();
        int scrcoords[] = new int[2];
        w.getLocationOnScreen(scrcoords);
        float x = event.getRawX() + w.getLeft() - scrcoords[0];
        float y = event.getRawY() + w.getTop() - scrcoords[1];

        Log.d("Activity", "Touch event "+event.getRawX()+","+event.getRawY()+" "+x+","+y+" rect "+w.getLeft()+","+w.getTop()+","+w.getRight()+","+w.getBottom()+" coords "+scrcoords[0]+","+scrcoords[1]);
        if (event.getAction() == MotionEvent.ACTION_UP && (x < w.getLeft() || x >= w.getRight() || y < w.getTop() || y > w.getBottom()) ) { 

            InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
            imm.hideSoftInputFromWindow(getWindow().getCurrentFocus().getWindowToken(), 0);
        }
    }
return ret;
}

Could probably be done in a smoother way but it works really well.

Daniel
  • 613
  • 1
  • 5
  • 7
  • 2
    To add a bit of clarification - if you're looking to close the keyboard when the user clicks ANYWHERE OUTSIDE OF AN EDITTEXT, and not just in another button's onClick(), then Daniel's code works perfectly. Just add/override the method to your Activity and the user will be able to close the keyboard by clicking anywhere outside of an EditText (works for multiple EditTexts on a single screen too). Thanks Daniel! – Kyle Clegg Nov 16 '11 at 19:18
  • 2
    This is not a perfect answer since it will hide the keyboard on touch, not tap. If you e.g. scroll a bit, the keyboard will be hidden. This is frequently not wanted. – User Aug 13 '14 at 20:39
  • @Daniel,@kyle Clegg,@lxx,@bibangamba, i am using his code and it works perfectly but it causes flickering of screen , if there a about 15-20 editext and you scroll to bottom from a focused editext(while typing), u came to same positiong u are typing with flickering of screen, so please help me in solving the issue. – Reprator Feb 12 '16 at 12:28
32

To forcibly hide the keyboard you would use the following code... I put it in a method called 'hideSoftKeyboard()'. As mentioned by Falmarri, the softkeyboard should hide itself when you click out of it. However, if you call this method in an 'onClick()' of another item, it will forcibly close the keyboard.

private void hideSoftKeyboard(){
    if(getCurrentFocus()!=null && getCurrentFocus() instanceof EditText){
        InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.hideSoftInputFromWindow(yourEditTextHere.getWindowToken(), 0);
    }
}
Community
  • 1
  • 1
Nick Vallely
  • 1,396
  • 1
  • 13
  • 18
7

This can be done using following code :

1) Take a reference of your parent layout into java code by using findViewById().

2) then apply setOnTouchListener() to it.

3) Add following code in onTouchMethod().

 lin = (LinearLayout) findViewById(R.id.lin);
    lin.setOnTouchListener(new OnTouchListener() 
    {
        @Override
        public boolean onTouch(View v, MotionEvent event) 
        {
               InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
                               imm.hideSoftInputFromWindow(getWindow().getCurrentFocus().getWindowToken(), 0);
                       return false;
        }
    });
Virag Brahme
  • 2,062
  • 1
  • 20
  • 32
6

I added the following to my activity. It works because touching outside a Focusable View doesn't change the focus (so w == v) but the touch will be outside the View's rectangle.

public boolean dispatchTouchEvent(MotionEvent event) {
    View v = getCurrentFocus();
    boolean ret = super.dispatchTouchEvent(event);
    View w = getCurrentFocus();
    int scrcoords[] = new int[2];
    w.getLocationOnScreen(scrcoords);
    float x = event.getRawX() + w.getLeft() - scrcoords[0];
    float y = event.getRawY() + w.getTop() - scrcoords[1];

    Log.d("Activity", "Touch event "+event.getRawX()+","+event.getRawY()+" "+x+","+y+" rect "+w.getLeft()+","+w.getTop()+","+w.getRight()+","+w.getBottom()+" coords "+scrcoords[0]+","+scrcoords[1]);
    if (event.getAction() == MotionEvent.ACTION_UP && (x < w.getLeft() || x >= w.getRight() || y < w.getTop() || y > w.getBottom()) ) { 
        inputManager.hideSoftInputFromWindow(getWindow().getCurrentFocus().getWindowToken(), 0);
    }
    return ret;

}

[edit: fix minor bug]

Kirk
  • 16,182
  • 20
  • 80
  • 112
Robert Diamond
  • 1,155
  • 1
  • 14
  • 12
1

As an supplementary to the accepted answer.

If the accepted answer is not working for you, you can add the hideSoftKeyboard() method to the onClick() method of the onClickListener of your EditText. For example:

editText.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        hideSoftKeyboard();
    }
});

(place the above code in onResume() or somewhere else)

ps. the definition of hideSoftKeyboard()

private void hideSoftKeyboard(){
    if(getCurrentFocus()!=null && getCurrentFocus() instanceof EditText){
        InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.hideSoftInputFromWindow(editText.getWindowToken(), 0);
    }
}
kexanie
  • 211
  • 3
  • 9
0
public boolean OutsideTouchEvent(MotionEvent m_event) {
    View v = getCurrentFocus();
    boolean value = super.dispatchTouchEvent(m_event);
    View w = getCurrentFocus();
    int scrcoords[] = new int[2];
    w.getLocationOnScreen(scrcoords);
    float x = m_event.getRawX() + w.getLeft() - scrcoords[0];
    float y = m_event.getRawY() + w.getTop() - scrcoords[1];

    if (m_event.getAction() == MotionEvent.ACTION_UP && (x < w.getLeft() || x >= w.getRight() || y < w.getTop() || y > w.getBottom()) ) { 
        InputMethodManager inputMethodManager = (InputMethodManager)  YourActivity.this.getSystemService(Activity.INPUT_METHOD_SERVICE);
        inputMethodManager.hideSoftInputFromWindow(YourActivity.this.getCurrentFocus().getWindowToken(), 0);
    }
    return value;

}
Ebin Sebastian
  • 1,291
  • 1
  • 13
  • 15
0

set inputType to zero for edit text
editText.setInputType(0);

it's work for me

Saeed-rz
  • 1,435
  • 1
  • 20
  • 38
0

First of all thank you to Daniel, his code is really nice and I was using it for a while.

Recently I realized that I have to improve it. The problem was scrolling page. I had many EditTexts in my project and it was hiding the keyboard when you scroll the page.

I came up with a solution using onGestureListener instead of overriding dispatchTouchEvent.

public class TabActivity extends ActionBarActivity implements GestureDetector.OnGestureListener {

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ...
        ...
        gestureScanner = new GestureDetector(TabActivity.this,this);
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        gestureScanner.onTouchEvent(ev);
        return super.dispatchTouchEvent(ev);
    }

    @Override
    public boolean onSingleTapUp(MotionEvent event) {
        View v = getCurrentFocus();

        if (v instanceof EditText) {
            View w = getCurrentFocus();
            int scrcoords[] = new int[2];
            w.getLocationOnScreen(scrcoords);
            boolean hide = true;

            View view = ((ViewGroup)findViewById(android.R.id.content)).getChildAt(0);
            ArrayList<View> editTexts = view.getFocusables(0);     // Get All EditTexts in view

            for(int i=0; i< editTexts.size(); i++){
                View editText = editTexts.get(i);
                editText.getLocationOnScreen(scrcoords);
                float x = event.getRawX();
                float y = event.getRawY();
                int viewX = scrcoords[0];
                int viewY = scrcoords[1];

                // If touch is in any of EditText, keep keyboard active, otherwise hide it.
                if (event.getAction() == MotionEvent.ACTION_UP  && ( x > viewX && x < (viewX + editText.getWidth())) && ( y > viewY && y < (viewY + editText.getHeight())) ) {
                    hide = false;
                }
            }

            if (hide) {
                InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
                imm.hideSoftInputFromWindow(getWindow().getCurrentFocus().getWindowToken(), 0);
            }
        }
        return true;
    }

    @Override
    public boolean onScroll(MotionEvent event, MotionEvent e2, float distanceX, float distanceY) {
        return true;
    }     
}

So, if user scrolls the page it goes to onScroll method and it does nothing. If users just touches to screen it triggers onSingleTapUp method.

I also had to change if statement of Daniel's code. Daniel was checking if the touch event is outside the EditText. Since I have many EditViews I changed the code to find if touch event is inside any of EditTexts.

It works fine with me, let me know for any kind of improvements or mistakes.

Gokhan Arik
  • 2,626
  • 2
  • 24
  • 50
  • View view = ((ViewGroup)findViewById(android.R.id.content)).getChildAt(0); i did not get this . Will you plz explain? – Tara May 19 '16 at 12:06
  • That was an old project I worked on, I don't remember the details. Basically, what I do there is to retrieve parent view. `android.R.id.content` will give you the root view. `getChildAt(0)` is probably used to retrieve parent of my EditTexts. – Gokhan Arik May 19 '16 at 15:55
  • so you mean to say add all edit text in view group or inside view? – Tara May 20 '16 at 05:39
  • Your case might be different. In my case, all of my `EditText`s were in a `LinearLayout`. So `view` is my `LinearLayout`, so I retrieve all `EditText`s in that LinearLayout. What are you trying to achieve? – Gokhan Arik May 20 '16 at 06:31
  • In my case also all Edit Texts are in Linear Layout. When i Click on submit button , should hide virtual keyboard.! – Tara May 20 '16 at 06:43
  • Do you want to hide keyboard on submit only, or do you want to hide it when user touches on screen outside EditText? – Gokhan Arik May 20 '16 at 06:51
  • You shouldn't worry about my code then. My code is to hide keyboard when you tap on screen outside EditText. There are other ways to hide keyboard – Gokhan Arik May 20 '16 at 18:11
0

Just set the input type to null like that

editText.setInputType(InputType.TYPE_NULL);

Simona Stoyanova
  • 322
  • 2
  • 11
0

I got a good solution.I know its too late but when searching most of times getting this link as first link. so it may be helpful for others. If you click on any text/button it will hide the softkeyboard which is already visible.

date.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // Hide soft keyboard
       InputMethodManager imm = (InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE);
            imm.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY, 0);

      // here i am showing the Date Dialog. one can proceed with their functionality

            //show date picker dialog
            showDialog(Date_DIALOG_ID);
        }
    });
Tara
  • 2,598
  • 1
  • 21
  • 30