28

I need to hide the softkeypad in android when user click on anywhere other than a Edittext. There are many help for iphone but not for android. I tried this code but its not working :(

final RelativeLayout base = (RelativeLayout) findViewById(R.id.RelativeLayout1);

    findViewById(R.id.base).setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
            imm.hideSoftInputFromWindow(base.getWindowToken(), 0);

        }
    });

Thanks in advance !

Chrishan
  • 4,076
  • 7
  • 48
  • 67

6 Answers6

56

You can use the onTouchEvent() to hide the Softkeyboard.

@Override
    public boolean onTouchEvent(MotionEvent event) {
        InputMethodManager imm = (InputMethodManager)getSystemService(Context.
                                                        INPUT_METHOD_SERVICE);
        imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
        return true;
    }

Though this solution works, but the best I would suggest is to use below answer as it gives best solution of closing the keyboard touching anywhere else then EditText.

Community
  • 1
  • 1
Lalit Poptani
  • 67,150
  • 23
  • 161
  • 242
  • 1
    +1 Yes I think so, Hope it's not considering key press of keyboard as Activity touch event..But yes I think this is the way.!! – MKJParekh Jan 02 '12 at 05:42
  • If you have any other view you can just use its *instance.getWindowToken()* and it would work. – Lalit Poptani Jan 02 '12 at 05:44
  • 1
    this is not worked for me. I found the correct one [here](http://stackoverflow.com/a/7241790/651422) – Chrishan Jan 02 '12 at 06:15
  • If you return true, won't that mean that none of the other views will get the on touch event? – Richard Fung Dec 25 '13 at 00:56
  • Not so good, when you scroll the keyboard is hidden. It would be better if it was possible to detect tap, not only touch. – User Aug 13 '14 at 20:37
  • @Ixx you can modify it as per your requirement, seeking for spoon feeding? heh! – Lalit Poptani Aug 14 '14 at 04:40
  • Spoon feeding? I think in this site the answers have to, well, answer the question. The question is about tap, and touch != tap. – User Aug 14 '14 at 08:36
  • @Ixx but you can clearly see that the user was satisfied with the answer, right? so now whats the problem with you? :) – Lalit Poptani Aug 18 '14 at 05:13
  • @Prabuddha it's surprising that with your rep you don't understand correctly how this community is supposed to work. A user selecting an answer doesn't mean necessarily the answer is correct, and the community can / has the responsibility to fix, or at least bring attention to incorrect / incomplete answers. See e.g. http://stackoverflow.com/help/accepted-answer "Accepting an answer is not meant to be a definitive and final statement indicating that the question has now been answered perfectly. It simply means that the author received an answer that worked for him or her personally..." – User Aug 18 '14 at 09:41
  • @Ixx The problem is that I don't want to understand at all. Also, its surprising that why you are too much bothered about this answer. If you feel that answer is wrong/not good/anything you don't like then go and down-vote it! – Lalit Poptani Aug 18 '14 at 10:11
  • I agree with `Ixx`, touch is different from tap. So, the problem of your answer is: How can we keep the keyboard being shown when scrolling? It's nice if you can solve it too. Thanks :) – Triet Doan Jun 23 '15 at 14:53
  • 2
    @Forte_201092 you can check my another answer posted below, which is a work around for you as you want to scroll too. – Lalit Poptani Jun 24 '15 at 08:12
27

Well I have done this way:

Add code in your Activity.

This would work for Fragment also, no need to add this code in Fragment.

@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
    View view = getCurrentFocus();
    if (view != null && (ev.getAction() == MotionEvent.ACTION_UP || ev.getAction() == MotionEvent.ACTION_MOVE) && view instanceof EditText && !view.getClass().getName().startsWith("android.webkit.")) {
        int scrcoords[] = new int[2];
        view.getLocationOnScreen(scrcoords);
        float x = ev.getRawX() + view.getLeft() - scrcoords[0];
        float y = ev.getRawY() + view.getTop() - scrcoords[1];
        if (x < view.getLeft() || x > view.getRight() || y < view.getTop() || y > view.getBottom())
        ((InputMethodManager)this.getSystemService(Context.INPUT_METHOD_SERVICE)).hideSoftInputFromWindow((this.getWindow().getDecorView().getApplicationWindowToken()), 0);
    }
    return super.dispatchTouchEvent(ev);
}

Hope this will help you.

Hiren Patel
  • 52,124
  • 21
  • 173
  • 151
14

The best work around I found was using as below,

Override dispatchTouchEvent() and try to get the area of EditText using Rect

 @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
         int x = (int) ev.getX();
         int y = (int) ev.getY();

         if (ev.getAction() == MotionEvent.ACTION_DOWN &&
             !getLocationOnScreen(etFeedback).contains(x, y)) {
             InputMethodManager input = (InputMethodManager) 
                                   activity.getSystemService(Context.INPUT_METHOD_SERVICE);
             input.hideSoftInputFromWindow(etFeedback.getWindowToken(), 0);
         }

        return super.dispatchTouchEvent(ev);
    }

Method that caculates 4 corner of View(here its EditText)

protected Rect getLocationOnScreen(EditText mEditText) {
        Rect mRect = new Rect();
        int[] location = new int[2];

        mEditText.getLocationOnScreen(location);

        mRect.left = location[0];
        mRect.top = location[1];
        mRect.right = location[0] + mEditText.getWidth();
        mRect.bottom = location[1] + mEditText.getHeight();

        return mRect;
    }

By using above code we can detect the area of EditText and we can check if the touch on the screen is part of the area of EditText or not. If its part of EditText then don't do anything let the touch do its job, and if the touch doesn't contain area of EditText then just close the softkeyboard.

******EDIT******

I just found another approach if we don't want to give any EditText as input and want to hide keyboard inside whole application when user touches anywhere else other than EditText. Then you have to create an BaseActivity and write global code for hiding keyboard as below,

 @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {

        boolean handleReturn = super.dispatchTouchEvent(ev);

        View view = getCurrentFocus();

         int x = (int) ev.getX();
         int y = (int) ev.getY();

         if(view instanceof EditText){
             View innerView = getCurrentFocus();

             if (ev.getAction() == MotionEvent.ACTION_UP && 
                                    !getLocationOnScreen(innerView).contains(x, y)) {

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

        return handleReturn;
    }
Lalit Poptani
  • 67,150
  • 23
  • 161
  • 242
0

I tried this to hide Keyboard. You need to pass the method in your Layout file.

public void setupUI(View view) {
    // Set up touch listener for non-text box views to hide keyboard.
    if (!(view instanceof EditText)) {
        view.setOnTouchListener(new View.OnTouchListener() {
            public boolean onTouch(View v, MotionEvent event) {
                hideSoftKeyboard(LOGSignUpActivity.this);
                return false;
            }
        });
    }
    //If a layout container, iterate over children and seed recursion.
    if (view instanceof ViewGroup) {
        for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
            View innerView = ((ViewGroup) view).getChildAt(i);
            setupUI(innerView);
        }
    }
}
Gowtham Subramaniam
  • 3,358
  • 2
  • 19
  • 31
0

Call this method in your MainAcitivity.class

  public static void hideKeyboardwithoutPopulate(BaseActivity activity) {
    InputMethodManager inputMethodManager =
            (InputMethodManager) activity.getSystemService(
                    Activity.INPUT_METHOD_SERVICE);
    inputMethodManager.hideSoftInputFromWindow(
            activity.getCurrentFocus().getWindowToken(), 0);
}
Eric Aya
  • 69,473
  • 35
  • 181
  • 253
Vishal Yadav
  • 1,020
  • 4
  • 15
  • 30
0

For those who are looking for a Xamarin code for this, here you go :

  public override bool DispatchTouchEvent(MotionEvent ev)
    {
        try
        {
            View view = CurrentFocus;
            if (view != null && (ev.Action == MotionEventActions.Up || ev.Action == MotionEventActions.Move) && view is EditText && !view.Class.Name.StartsWith("android.webkit."))
            {
                int[] Touch = new int[2];
                view.GetLocationOnScreen(Touch);
                float x = ev.RawX + view.Left - Touch[0];
                float y = ev.RawY + view.Top - Touch[1];
                if (x < view.Left || x > view.Right || y < view.Top || y > view.Bottom)
                    ((InputMethodManager)GetSystemService(InputMethodService)).HideSoftInputFromWindow((Window.DecorView.ApplicationWindowToken), 0);
            }
        }
        catch (System.Exception ex)
        {

        }

        return base.DispatchTouchEvent(ev);
    }
FreakyAli
  • 13,349
  • 3
  • 23
  • 63