Как скрыть мягкую клавиатуру на андроиде после нажатия вне EditText? - PullRequest
317 голосов
/ 12 ноября 2010

Хорошо, все знают, что для того, чтобы спрятать клавиатуру, вам нужно реализовать:

InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);

Но здесь важно то, как спрятать клавиатуру, когда пользователь касается или выбирает любое другое место, которое не EditText или softKeyboard?

Я пытался использовать onTouchEvent() на моем родителе Activity, но это работает только в том случае, если пользователь касается внешнего вида и нет прокрутки.

IПопытка реализовать прослушивание касанием, щелчком, фокусировкой безуспешно.

Я даже пытался реализовать свое собственное представление прокрутки для перехвата событий касания, но я могу получить только координаты события, а не представление, по которому щелкнули.

Есть ли стандартный способ сделать это ??в iPhone это было действительно легко.

Ответы [ 40 ]

2 голосов
/ 12 ноября 2010

Попробуйте включить stateHidden в качестве вашей активности windowSoftInputMode значение

http://developer.android.com/reference/android/R.attr.html#windowSoftInputMode

Например, для вашей активности:

this.getWindow().setSoftInputMode(
    WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
1 голос
/ 01 марта 2016

Я сделал так:

@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())
                hideKeyboard(this);
        }
    return super.dispatchTouchEvent(ev);
}

Скрыть код клавиатуры :

public static void hideKeyboard(Activity act) {
    if(act!=null)
      ((InputMethodManager)act.getSystemService(Context.INPUT_METHOD_SERVICE)).hideSoftInputFromWindow((act.getWindow().getDecorView().getApplicationWindowToken()), 0);
  }

Готово

1 голос
/ 04 апреля 2016

Чтобы решить эту проблему, вам сначала нужно использовать setOnFocusChangeListener этого Edittext

edittext.setOnFocusChangeListener(new View.OnFocusChangeListener() {
            @Override
            public void onFocusChange(View v, boolean hasFocus) {
                if (!hasFocus) {
                    Log.d("focus", "focus loosed");
                    // Do whatever you want here
                } else {
                    Log.d("focus", "focused");
                }
            }
        });

, а затем вам нужно переопределить dispatchTouchEvent в действии, которое содержит этот Edittext, см. Код ниже

@Override
public boolean dispatchTouchEvent(MotionEvent event) {
    if (event.getAction() == MotionEvent.ACTION_DOWN) {
        View v = getCurrentFocus();
        if ( v instanceof EditText) {
            Rect outRect = new Rect();
            v.getGlobalVisibleRect(outRect);
            if (!outRect.contains((int)event.getRawX(), (int)event.getRawY())) {
                Log.d("focus", "touchevent");
                v.clearFocus();
                InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
                imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
            }
        }
    }
    return super.dispatchTouchEvent(event);
}

Теперь, что произойдет, когда пользователь щелкнет снаружи, то сначала будет вызван этот dispatchTouchEvent, который затем очистит фокус от editext, теперь ваш OnFocusChangeListener будет вызван, так как фокус был изменен теперь, здесь вы можете делать всеВы хотели надеяться, что это сработает

1 голос
/ 17 октября 2014

Это может быть старым, но я получил эту работу, реализовав пользовательский класс

public class DismissKeyboardListener implements OnClickListener {

    Activity mAct;

    public DismissKeyboardListener(Activity act) {
        this.mAct = act;
    }

    @Override
    public void onClick(View v) {
        if ( v instanceof ViewGroup ) {
            hideSoftKeyboard( this.mAct );
        }
    }       
}

public void hideSoftKeyboard(Activity activity) {
        InputMethodManager imm = (InputMethodManager)
        getSystemService(Activity.INPUT_METHOD_SERVICE);
        imm.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY, 0);
}

. Лучшей практикой здесь является создание класса Helper, и каждый контейнер Relative / Linear Layouts должен реализовывать это.

**** Обратите внимание, что только основной Контейнер должен реализовывать этот класс (для оптимизации) ****

и реализовать его следующим образом:

Parent.setOnClickListener( new DismissKeyboardListener(this) ); 

theКлючевое слово это для деятельности.поэтому, если вы находитесь на фрагменте, вы используете, как getActivity ();

--- большие пальцы, если это поможет вам ... --- ура Ральф ---

1 голос
/ 02 июля 2019

В kotlin мы можем сделать следующее.Не нужно повторять все представления.Это будет работать и для фрагментов.

override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
    currentFocus?.let {
        val imm: InputMethodManager = getSystemService(
            Context.INPUT_METHOD_SERVICE
        ) as (InputMethodManager)
        imm.hideSoftInputFromWindow(it.windowToken, 0)
    }
    return super.dispatchTouchEvent(ev)
}
1 голос
/ 05 декабря 2017

Просто добавьте этот код в класс @ Overide

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);
}
1 голос
/ 15 мая 2015

Это слегка измененная версия ответа fje, которая в основном работала идеально.

Эта версия использует ACTION_DOWN, поэтому выполнение действия прокрутки также закрывает клавиатуру. Это также не распространяет событие, если вы не нажмете другой EditText. Это означает, что нажатие в любом месте за пределами вашего EditText, даже на другое нажатие, просто закрывает клавиатуру.

@Override
public boolean dispatchTouchEvent(MotionEvent ev)
{
    if(ev.getAction() == MotionEvent.ACTION_DOWN)
    {
        final View view = getCurrentFocus();

        if(view != null)
        {
            final View viewTmp = getCurrentFocus();
            final View viewNew = viewTmp != null ? viewTmp : view;

            if(viewNew.equals(view))
            {
                final Rect rect = new Rect();
                final int[] coordinates = new int[2];

                view.getLocationOnScreen(coordinates);

                rect.set(coordinates[0], coordinates[1], coordinates[0] + view.getWidth(), coordinates[1] + view.getHeight());

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

                if(rect.contains(x, y))
                {
                    super.dispatchTouchEvent(ev);
                    return true;
                }
            }
            else if(viewNew instanceof EditText || viewNew instanceof CustomEditText)
            {
                super.dispatchTouchEvent(ev);
                return true;
            }

            final InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);

            inputMethodManager.hideSoftInputFromWindow(viewNew.getWindowToken(), 0);

            viewNew.clearFocus();

            return true;
        }
    }
    return super.dispatchTouchEvent(ev);
}
1 голос
/ 16 июля 2017

Ну, вы можете использовать этот код, использовать идентификатор основного макета вместо "mainRelativeLayout"

//hide Soft keyboard on click outside  the input text
    findViewById(R.id.mainRelativeLayout).setOnClickListener(new 
View.OnClickListener() {
        @Override
        public void onClick(View v) {
            InputMethodManager im = (InputMethodManager) 
getSystemService(INPUT_METHOD_SERVICE);
            im.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 
0);
        }

    });
1 голос
/ 01 ноября 2017

Активность

 @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);
 }
1 голос
/ 03 ноября 2016
@Override
    public boolean onTouchEvent(MotionEvent event) {
        InputMethodManager imm = (InputMethodManager)getSystemService(Context.
                INPUT_METHOD_SERVICE);
        imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
        return true;
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...