Jak ukryć miękką klawiaturę na Androidzie po kliknięciu poza EditText?

Ok wszyscy wiedzą, że aby ukryć klawiaturę trzeba zaimplementować:

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

Ale najważniejsze jest to, jak ukryć klawiaturę, gdy użytkownik dotknie lub wybierze inne miejsce, które nie jest EditText lub softKeyboard?

Próbowałem użyć onTouchEvent() na moim rodzicu Activity, ale działa to tylko wtedy, gdy użytkownik dotknie poza innym widokiem i nie ma widoku przewijania.

Próbowałem zaimplementować dotyk, kliknięcie, skupienie słuchacza bez powodzenia.

Próbowałem nawet wdrożyć mój własny scrollview do przechwytywania zdarzeń dotykowych, ale mogę uzyskać tylko współrzędne zdarzenia, a nie Widok kliknięty.

Czy jest na to standardowy sposób?? w iPhone to było naprawdę proste.
Author: Gowtham Subramaniam, 2010-11-12

30 answers

Poniższy fragment po prostu ukrywa klawiaturę:

public static void hideSoftKeyboard(Activity activity) {
    InputMethodManager inputMethodManager = 
        (InputMethodManager) activity.getSystemService(
            Activity.INPUT_METHOD_SERVICE);
    inputMethodManager.hideSoftInputFromWindow(
        activity.getCurrentFocus().getWindowToken(), 0);
}

Możesz umieścić to w klasie użytkowej, lub jeśli definiujesz to w aktywności, unikaj parametru activity lub wywołaj hideSoftKeyboard(this).

Najtrudniejsze jest to, kiedy to nazwać. Możesz napisać metodę, która jest powtarzana przez każdą View w Twojej aktywności i sprawdzić, czy jest to instanceof EditText, Jeśli nie jest to Zarejestruj {[5] } do tego komponentu, a wszystko spadnie na swoje miejsce. Jeśli zastanawiasz się, jak to zrobić, jest to w fakt dość prosty. Oto co robisz, piszesz rekurencyjną metodę jak poniżej, w rzeczywistości możesz użyć tego do zrobienia wszystkiego, jak ustawienie niestandardowych krojów pisma itp... Oto metoda
public void setupUI(View view) {

    // Set up touch listener for non-text box views to hide keyboard.
    if (!(view instanceof EditText)) {
        view.setOnTouchListener(new OnTouchListener() {
            public boolean onTouch(View v, MotionEvent event) {
                hideSoftKeyboard(MyActivity.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);
        }
    }
}

To wszystko, po prostu wywołaj tę metodę po sobie setContentView w swojej aktywności. Jeśli zastanawiasz się, jaki parametr chcesz przekazać, jest to id kontenera nadrzędnego. Przypisanie id do kontenera nadrzędnego, np.

<RelativeLayoutPanel android:id="@+id/parent"> ... </RelativeLayout>

I zadzwonić setupUI(findViewById(R.id.parent)), to wszystko.

Jeśli jeśli chcesz efektywnie korzystać z tej metody, możesz utworzyć rozszerzoną Activity i wprowadzić tę metodę, a wszystkie inne działania w Twojej aplikacji rozszerzyć tę aktywność i wywołać jej setupUI() w metodzie onCreate().

Mam nadzieję, że to pomoże.

Jeśli użyjesz więcej niż 1 aktywności zdefiniuj wspólny identyfikator układu nadrzędnego, jak <RelativeLayout android:id="@+id/main_parent"> ... </RelativeLayout>

Następnie rozszerz klasę z Activity i zdefiniuj setupUI(findViewById(R.id.main_parent)) w jej OnResume() i rozszerz tę klasę zamiast " Activity in your program

 516
Author: Navneeth G,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-29 14:57:54

Możesz to osiągnąć wykonując następujące kroki:

  1. Aby widok nadrzędny (Widok zawartości Twojej aktywności) był klikalny i ustawialny, dodając następujące atrybuty

        android:clickable="true" 
        android:focusableInTouchMode="true" 
    
  2. Zaimplementuj metodę hideKeyboard ()

        public void hideKeyboard(View view) {
            InputMethodManager inputMethodManager =(InputMethodManager)getSystemService(Activity.INPUT_METHOD_SERVICE);
            inputMethodManager.hideSoftInputFromWindow(view.getWindowToken(), 0);
        }
    
  3. Na koniec ustaw onFocusChangeListener twojego edittext.

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

Jak wspomniano w jednym z poniższych komentarzy, może to nie działać, jeśli nadrzędnym widokiem Jest widok przewijania. W takim przypadku klikalne i focusableInTouchMode można dodać w widoku bezpośrednio pod przewijaniem.

 216
Author: vida,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-11 16:20:04

Akceptowana odpowiedź jest dla mnie trochę skomplikowana.

Oto moje rozwiązanie. Dodaj OnTouchListener do głównego układu, tj.:
findViewById(R.id.mainLayout).setOnTouchListener(this)

I umieść następujący kod w metodzie onTouch.

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

W ten sposób nie musisz iterować wszystkich widoków.

 47
Author: roepit,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-02 14:25:04

Mam jeszcze jedno rozwiązanie do ukrycia klawiatury przez:

InputMethodManager imm = (InputMethodManager) getSystemService(
    Activity.INPUT_METHOD_SERVICE);
imm.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY, 0);

Tutaj mijamy HIDE_IMPLICIT_ONLY na pozycji showFlag i 0 na pozycji hiddenFlag. Spowoduje to silne zamknięcie miękkiej klawiatury.

 35
Author: Saurabh Pareek,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-20 07:38:11

Cóż udaje mi się nieco rozwiązać problem, i overrode dispatchTouchEvent na mojej działalności, nie używam następujących, aby ukryć klawiaturę.

 /**
 * 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: metoda getFields() jest tylko metodą, która zwraca tablicę z polami tekstowymi w widoku. Aby uniknąć tworzenia tej tablicy przy każdym dotknięciu, utworzyłem statyczną tablicę o nazwie sFields, która jest zwracana przy metodzie getFields (). Tablica ta jest inicjalizowana metodami onStart () takimi as:

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


To nie jest idealny, przeciągnij czas zdarzenia jest oparty tylko na heurystyce, Więc czasami nie ukrywa się podczas wykonywania długich kliknięć, a ja również skończyłem tworząc metodę, aby uzyskać wszystkie edittext na widok; w przeciwnym razie klawiatura będzie ukrywać i pokazywać po kliknięciu innego EditText.

Mimo to, czystsze i krótsze rozwiązania są mile widziane]}
 16
Author: htafoya,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-01 14:26:57

Użyj OnFocusChangeListener .

Na przykład:

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

Update : możesz również nadpisać onTouchEvent() w swojej aktywności i sprawdzić współrzędne dotyku. Jeśli współrzędne znajdują się poza EditText, ukryj klawiaturę.

 12
Author: Sergey Glotov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-11-12 14:48:00

Zaimplementowałem dispatchTouchEvent w Activity, aby to zrobić:

private EditText mEditText;
private Rect mRect = new Rect();
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
    final int action = MotionEventCompat.getActionMasked(ev);

    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();

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

    if (action == MotionEvent.ACTION_DOWN && !mRect.contains(x, y)) {
        InputMethodManager input = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
        input.hideSoftInputFromWindow(mEditText.getWindowToken(), 0);
    }
    return super.dispatchTouchEvent(ev);
}

I Przetestowałem go, działa idealnie!

 11
Author: Jishi Chen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-24 11:25:42

Override public Boolean dispatchTouchEvent (Zdarzenie MotionEvent) w dowolnej aktywności (lub rozszerz klasę aktywności)

@Override
public boolean dispatchTouchEvent(MotionEvent event) {
    View view = getCurrentFocus();
    boolean ret = super.dispatchTouchEvent(event);

    if (view 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];

        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;
}

And that ' s all you need to do

 10
Author: Hoang Trinh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-27 13:21:23

Zdaję sobie sprawę, że ten wątek jest dość stary, poprawna odpowiedź wydaje się ważna i istnieje wiele działających rozwiązań, ale myślę, że podejście opisane poniżej może mieć dodatkową korzyść w zakresie wydajności i elegancji.

Potrzebuję tego zachowania dla wszystkich moich działań, więc stworzyłem klasę CustomActivity dziedzicząc po klasie Activity i "podłączyłem" funkcję dispatchTouchEvent . Istnieją głównie dwa warunki, aby zadbać of:

  1. Jeśli fokus jest niezmieniony i ktoś naciska poza bieżącym polem wejściowym, Odrzuć IME
  2. jeśli focus się zmienił, a następny element Focus nie jest instancją żadnego rodzaju pola wejściowego, Odrzuć IME

Oto mój wynik:

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

        if(view != null) {
            final boolean consumed = super.dispatchTouchEvent(ev);

            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)) {
                    return consumed;
                }
            }
            else if(viewNew instanceof EditText || viewNew instanceof CustomEditText) {
                return consumed;
            }

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

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

            viewNew.clearFocus();

            return consumed;
        }
    }       

    return super.dispatchTouchEvent(ev);
}

Uwaga na marginesie: dodatkowo przypisuję te atrybuty do widoku głównego, dzięki czemu możliwe jest wyczyszczenie ostrości na każdym polu wejściowym i uniemożliwienie Polom wejściowym skupienia się na uruchomieniu aktywności (sprawianie, że zawartość będzie wyświetlana jako "focus catcher"):

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    final View view = findViewById(R.id.content);

    view.setFocusable(true);
    view.setFocusableInTouchMode(true);
}
 9
Author: fje,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-23 18:11:43

Zmodyfikowałem rozwiązanie Andre Luis IM osiągnąłem to:

Stworzyłem narzędzie do ukrycia miękkiej klawiatury tak samo jak Andre Luiz IM:

public static void hideSoftKeyboard(Activity activity) {
    InputMethodManager inputMethodManager = (InputMethodManager)  activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
    inputMethodManager.hideSoftInputFromWindow(activity.getCurrentFocus().getWindowToken(), 0);
}

Ale zamiast zarejestrować OnTouchListener dla każdego widoku, który daje słabą wydajność, zarejestrowałem OnTouchListener dla tylko widoku głównego. Ponieważ zdarzenie bąbelki dopóki nie zostanie zużyte (EditText jest jednym z widoków, który domyślnie zużywa go), jeśli dojdzie do widoku głównego, to dlatego, że nie zostało zużyte, więc zamykam miękką klawiaturę.

findViewById(android.R.id.content).setOnTouchListener(new OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        Utils.hideSoftKeyboard(activity);
        return false;
    }
});
 7
Author: Fernando Camargo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-12 20:01:35

Podoba mi się podejście wywołania dispatchTouchEvent wykonane przez htafoya, ale:

  • nie rozumiałem części czasomierza (Nie wiem dlaczego mierzenie przestojów powinno być konieczne?)
  • Nie lubię rejestrować / wyrejestrowywać wszystkich Edittextów przy każdej zmianie widoku (może być sporo viewchanges i edittextów w złożonych hierarchiach)

Więc zrobiłem to nieco łatwiejsze rozwiązanie:

@Override
public boolean dispatchTouchEvent(final MotionEvent ev) {
    // all touch events close the keyboard before they are processed except EditText instances.
    // if focus is an EditText we need to check, if the touchevent was inside the focus editTexts
    final View currentFocus = getCurrentFocus();
    if (!(currentFocus instanceof EditText) || !isTouchInsideView(ev, currentFocus)) {
        ((InputMethodManager) getApplicationContext().getSystemService(Context.INPUT_METHOD_SERVICE))
            .hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
    }
    return super.dispatchTouchEvent(ev);
}

/**
 * determine if the given motionevent is inside the given view.
 * 
 * @param ev
 *            the given view
 * @param currentFocus
 *            the motion event.
 * @return if the given motionevent is inside the given view
 */
private boolean isTouchInsideView(final MotionEvent ev, final View currentFocus) {
    final int[] loc = new int[2];
    currentFocus.getLocationOnScreen(loc);
    return ev.getRawX() > loc[0] && ev.getRawY() > loc[1] && ev.getRawX() < (loc[0] + currentFocus.getWidth())
        && ev.getRawY() < (loc[1] + currentFocus.getHeight());
}

Jest jedna wada:

Przejście z jednego EditText do drugiego EditText sprawia, że klawiatura hide i reshow - w moim przypadku jest to pożądane w ten sposób, ponieważ pokazuje, że przełączane między dwoma komponentami wejściowymi.

 5
Author: Christian R.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-20 00:00:27

Apel: uznaję, że nie mam wpływu, ale proszę potraktuj moją odpowiedź poważnie.

Problem: Odrzuć miękką klawiaturę, gdy klikniesz z dala od klawiatury lub edytuj tekst przy minimalnym kodzie.

Rozwiązanie: zewnętrzna biblioteka znana jako Butterknife.

Rozwiązanie Jednej Linii:

@OnClick(R.id.activity_signup_layout) public void closeKeyboard() { ((InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE)).hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0); }

Bardziej Czytelne Rozwiązanie:

@OnClick(R.id.activity_signup_layout) 
public void closeKeyboard() {
        InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
}

Explanation: Bind onclick Listener do identyfikatora nadrzędnego układu XML, tak aby każde kliknięcie na układ (nie na edytowanym tekście lub klawiaturze) spowoduje uruchomienie tego fragmentu kodu, który ukryje klawiaturę.

Przykład: jeśli twoim plikiem układu jest R. layout. my_layout, a twoim identyfikatorem układu jest R. id. my_layout_id, to twoje wywołanie butterknife powinno wyglądać następująco:

(@OnClick(R.id.my_layout_id) 
public void yourMethod {
    InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
    imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
}

Link do dokumentacji Butterknife: http://jakewharton.github.io/butterknife/

Wtyczka: Butterknife zrewolucjonizuje rozwój Androida. Rozważ to.

Uwaga: ten sam wynik można osiągnąć bez użycia zewnętrznej biblioteki Butterknife. Wystarczy ustawić OnClickListener do układu nadrzędnego, jak opisano powyżej.

 4
Author: Charles Woodson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-30 15:09:05

Metoda pokazywania / ukrywania miękkiej klawiatury

InputMethodManager inputMethodManager = (InputMethodManager) currentActivity.getSystemService(Context.INPUT_METHOD_SERVICE);
    if (isShow) {
        if (currentActivity.getCurrentFocus() == null) {
            inputMethodManager.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
        } else {
            inputMethodManager.showSoftInput(currentActivity.getCurrentFocus(), InputMethodManager.SHOW_FORCED);    
        }

    } else {
        if (currentActivity.getCurrentFocus() == null) {
            inputMethodManager.toggleSoftInput(InputMethodManager.HIDE_NOT_ALWAYS, 0);
        } else {
            inputMethodManager.hideSoftInputFromInputMethod(currentActivity.getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);    
        }

    }

Mam nadzieję, że były użyteczne

 3
Author: lalosoft,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-08-10 18:43:37

Oto kolejna wariacja na temat odpowiedzi fje, która odnosi się do problemów podniesionych przez sosite.

Chodzi o to, aby obsługiwać zarówno działania w dół, jak i w górę w metodzie dispatchTouchEvent działania. Podczas operacji down notujemy aktualnie skupiony Widok (jeśli taki istnieje) i czy dotyk był w środku, zapisując oba te bity informacji na później.

Na akcji up, najpierw wysyłamy, aby umożliwić inny widok, aby potencjalnie skupić się. Jeśli po tym, aktualnie skupiony widok jest pierwotnie widok zogniskowany, a dotyk w dół był wewnątrz tego widoku, a następnie pozostawiamy klawiaturę otwartą.

Jeśli aktualnie ustawiony widok jest inny niż pierwotnie ustawiony widok i {[21] }jest to EditText, to pozostawiamy klawiaturę otwartą.

Inaczej go zamkniemy.

Podsumowując, działa to następująco:

    Po dotknięciu wewnątrz aktualnie skupionej klawiatury Klawiatura pozostaje otwarta]}
  • podczas przechodzenia z skupionego EditText na inny EditText, klawiatura pozostaje otwarta (nie zamyka się/nie otwiera)
  • Po dotknięciu dowolnego miejsca poza aktualnie skupionym EditText, które nie jest innym EditText, klawiatura zamyka się
  • po długim naciśnięciu w EditText, aby wywołać pasek akcji kontekstowej (z przyciskami wytnij/kopiuj/wklej), klawiatura pozostaje otwarta, nawet jeśli akcja w górę miała miejsce poza skupionym EditText (który przesunął się w dół, aby zrobić miejsce dla kabiny). Należy jednak pamiętać, że po dotknięciu przycisku w kabinie klawiatura zostanie zamknięta. To może, ale nie musi być pożądane; jeśli chcesz wyciąć/skopiować z jednego pola i wkleić do drugiego, byłoby. Jeśli chcesz wkleić z powrotem do tego samego EditText, nie będzie.
  • Gdy focused EditText znajduje się na dole ekranu i długo klikasz na jakiś tekst, aby go zaznaczyć, EditText zachowuje ostrość i dlatego klawiatura otwiera się tak, jak chcesz, ponieważ robimy "touch is within view bounds" sprawdzić na akcji w dół, a nie w górę akcji.

    private View focusedViewOnActionDown;
    private boolean touchWasInsideFocusedView;
    
    
    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                focusedViewOnActionDown = getCurrentFocus();
                if (focusedViewOnActionDown != null) {
                    final Rect rect = new Rect();
                    final int[] coordinates = new int[2];
    
                    focusedViewOnActionDown.getLocationOnScreen(coordinates);
    
                    rect.set(coordinates[0], coordinates[1],
                            coordinates[0] + focusedViewOnActionDown.getWidth(),
                            coordinates[1] + focusedViewOnActionDown.getHeight());
    
                    final int x = (int) ev.getX();
                    final int y = (int) ev.getY();
    
                    touchWasInsideFocusedView = rect.contains(x, y);
                }
                break;
    
            case MotionEvent.ACTION_UP:
    
                if (focusedViewOnActionDown != null) {
                    // dispatch to allow new view to (potentially) take focus
                    final boolean consumed = super.dispatchTouchEvent(ev);
    
                    final View currentFocus = getCurrentFocus();
    
                    // if the focus is still on the original view and the touch was inside that view,
                    // leave the keyboard open.  Otherwise, if the focus is now on another view and that view
                    // is an EditText, also leave the keyboard open.
                    if (currentFocus.equals(focusedViewOnActionDown)) {
                        if (touchWasInsideFocusedView) {
                            return consumed;
                        }
                    } else if (currentFocus instanceof EditText) {
                        return consumed;
                    }
    
                    // the touch was outside the originally focused view and not inside another EditText,
                    // so close the keyboard
                    InputMethodManager inputMethodManager =
                            (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
                    inputMethodManager.hideSoftInputFromWindow(
                        focusedViewOnActionDown.getWindowToken(), 0);
                    focusedViewOnActionDown.clearFocus();
    
                    return consumed;
                }
                break;
        }
    
        return super.dispatchTouchEvent(ev);
    }
    
 3
Author: Andy Dennie,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-24 20:27:25

Its too simple, just make your recent layout clickable an focusable by this code:

android:id="@+id/loginParentLayout"
android:clickable="true"
android:focusableInTouchMode="true"

A następnie napisz metodę i OnClickListner dla tego układu, tak aby po dotknięciu najwyższego układu wywołał metodę, w której napiszesz kod na klawiaturze. poniżej znajduje się kod dla obu; // musisz to napisać w OnCreate ()

 yourLayout.setOnClickListener(new View.OnClickListener(){
                @Override
                public void onClick(View view) {
                    hideKeyboard(view);
                }
            });

Metoda wywołana z listnera:-

 public void hideKeyboard(View view) {
     InputMethodManager imm =(InputMethodManager)getSystemService(Activity.INPUT_METHOD_SERVICE);
        imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
    }
 3
Author: swarnim dixit,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-20 10:52:43

Istnieje prostsze podejście, oparte na iPhone sam problem. Po prostu nadpisuj układ tła podczas zdarzenia dotykowego, w którym zawarty jest tekst edycji. Po prostu użyj tego kodu w aktywności OnCreate (login_fondo to układ główny):

    final LinearLayout llLogin = (LinearLayout)findViewById(R.id.login_fondo);
    llLogin.setOnTouchListener(
            new OnTouchListener()
            {
                @Override
                public boolean onTouch(View view, MotionEvent ev) {
                    InputMethodManager imm = (InputMethodManager) mActivity.getSystemService(
                            android.content.Context.INPUT_METHOD_SERVICE);
                    imm.hideSoftInputFromWindow(mActivity.getCurrentFocus().getWindowToken(), 0);
                    return false;
                }
            });
 2
Author: Alex R. R.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-07-12 08:53:32

Udoskonaliłem metodę, umieściłem poniższy kod w jakiejś klasie użytkowej UI (najlepiej, niekoniecznie), aby mógł być dostępny ze wszystkich klas aktywności lub fragmentów, aby służył jej celowi.

public static void serachAndHideSoftKeybordFromView(View view, final Activity act) {
    if(!(view instanceof EditText)) {
        view.setOnTouchListener(new View.OnTouchListener() {
            public boolean onTouch(View v, MotionEvent event) {
                hideSoftKeyboard(act);
                return false;
            }
        });
    }
    if (view instanceof ViewGroup) {
        for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
            View nextViewInHierarchy = ((ViewGroup) view).getChildAt(i);
            serachAndHideSoftKeybordFromView(nextViewInHierarchy, act);
        }
    }
}
public static void hideSoftKeyboard (Activity activity) {
    InputMethodManager inputMethodManager = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
    inputMethodManager.hideSoftInputFromWindow(activity.getCurrentFocus().getWindowToken(), 0);
}

Następnie powiedz na przykład, że musisz wywołać go z aktywności, nazwij to w następujący sposób;

UIutils.serachAndHideSoftKeybordFromView(findViewById(android.R.id.content), YourActivityName.this);

Zawiadomienie

FindViewById (android.r.id.content)

To daje nam Widok root bieżącej grupy(nie musisz ustawiać id na root widok).

Pozdrawiam :) [3]}
 2
Author: Uzair,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-22 06:46:19

Spróbuj umieścić stateHidden jako swoją aktywność windowSoftInputMode wartość

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

Na przykład dla Twojej aktywności:

this.getWindow().setSoftInputMode(
    WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
 2
Author: Alex Volovoy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-20 07:33:31

Aktywność

 @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);
 }
 2
Author: icebail,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-01 13:39:32

A more Kotlin & Material Design Sposób użycia TextInputEditText (to podejście jest również zgodne z EditTextView )...

1.Aby Widok nadrzędny (Widok zawartości aktywności/fragmentu) był klikalny i ustawiany na ostrość, dodaj następujące atrybuty

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

2.Utwórz rozszerzenie dla wszystkich widoków (wewnątrz ViewExtension.plik kt na przykład):

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

3.Utwórz BaseTextInputEditText, który odziedziczy TextInputEditText. Wdrożenie metoda onFocusChanged do ukrycia klawiatury, gdy widok nie jest skupiony :

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.Wystarczy wywołać nowy widok niestandardowy w 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> 
To wszystko. nie trzeba modyfikować kontrolerów (fragment lub aktywność), aby obsłużyć ten powtarzający się przypadek.
 2
Author: Phil,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-01 08:37:38

Uznaję akceptowaną odpowiedź za skomplikowaną dla tego prostego wymogu. Oto, co zadziałało dla mnie bez żadnych usterek.

findViewById(R.id.mainLayout).setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View view, MotionEvent motionEvent) {
            InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
            imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
            return false;
        }
    });
 2
Author: Joohay,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-20 13:59:22

To może być stare, ale mam to działanie poprzez zaimplementowanie niestandardowej klasy

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);
}

Najlepszą praktyką jest stworzenie klasy pomocniczej i każdy relatywny / Liniowy układ kontenera powinien to zaimplementować.

* * * * zwróć uwagę, że tylko główny kontener powinien zaimplementować tę klasę (dla optymalizacji) * * * *

I zaimplementuj to tak:

Parent.setOnClickListener( new DismissKeyboardListener(this) ); 

To słowo kluczowe dla aktywności. więc jeśli jesteś na fragmencie używasz getactivity ();

---kciuki w górę, jeśli to pomoże ty... --- pozdrawiam Ralph - - -

 1
Author: ralphgabb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-17 03:16:25

Jest to nieco zmodyfikowana wersja odpowiedzi fje, która w większości działała idealnie.

Ta wersja używa ACTION_DOWN, więc wykonanie akcji przewijania również zamyka klawiaturę. Nie propaguje również zdarzenia, chyba że klikniesz na inny EditText. Oznacza to, że kliknięcie w dowolnym miejscu poza edytowanym tekstem, nawet na innym klikalnym, po prostu zamyka klawiaturę.

@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
Author: Cadmonkey33,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-14 23:39:49

Zrobiłem tak:

@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);
}

Ukryj kod klawiatury :

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

Done

 1
Author: Hiren Patel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-01 13:49:07

Aby rozwiązać ten problem, musisz najpierw użyć setOnFocusChangeListener tego 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");
                }
            }
        });

A następnie musisz nadpisać dispatchTouchEvent w aktywności, która zawiera ten Edittext patrz poniższy kod

@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);
}

Teraz, co się stanie, gdy użytkownik kliknie na zewnątrz, to najpierw zostanie wywołany dispatchTouchEvent, który następnie wyczyści fokus z editext teraz twój OnFocusChangeListener zostanie wywołany, że fokus został zmieniony teraz tutaj możesz zrobić wszystko, co chcesz zrobić, mam nadzieję, że to zadziała

 1
Author: Sudhanshu Gaur,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-04 19:41:22
@Override
    public boolean onTouchEvent(MotionEvent event) {
        InputMethodManager imm = (InputMethodManager)getSystemService(Context.
                INPUT_METHOD_SERVICE);
        imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
        return true;
    }
 1
Author: Jeffy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-03 17:56:26

Innym pomysłem jest nadpisanie metody onInterceptTouchEvent w widoku głównym dla Twojej aktywności.

Zdarzenie dotykowe przechodzi od głównego widoku na ekranie (gdzie wystąpiło zdarzenie dotykowe) w dół stosu widoków wywołujących metodę onTouch, aż któryś z widoków zwróci wartość true, wskazując, że zdarzenie dotykowe zostało wykorzystane. Ponieważ wiele z widoków domyślnie zużywa Zdarzenie touch (na przykład EditText lub TextView), zdarzenie nie dociera do głównego widoku aktywności onTouch metoda.

Ale przed wykonaniem tego przejścia, Zdarzenie dotykowe przemieszcza się inną ścieżką, przechodząc od widoku głównego w dół drzewa widoku, aż do widoku głównego. Przejście to odbywa się przez wywołanie onInterceptTouchEvent. Jeśli metoda zwraca true, przechwytuje Zdarzenie... niehhh, ale to jest mała sztuczka, nie sądzę, że chcesz to zrobić ani znać szczegółów. Musisz wiedzieć, że możesz zastąpić tę metodę w widoku głównym dla swojej aktywności i umieścić tam kod, aby ukryć klawiatura w razie potrzeby.

 0
Author: Andre Luis IM,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-11-12 14:59:47

Mam to z lekkim wariantem rozwiązania Fernando Camarago. W mojej metodzie onCreate dołączam pojedynczy onTouchListener do widoku głównego, ale wysyłam widok zamiast aktywności jako argument.

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

W osobnej klasie Utils jest...

    public static void hideSoftKeyboard(View v) {
    InputMethodManager imm = (InputMethodManager) v.getContext().getSystemService(Context.INPUT_METHOD_SERVICE); 
    imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
}
 0
Author: AndyMc,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-04 16:48:53

Możesz łatwo nadpisać Zdarzenie onKey () w aktywności i fragmentach, aby ukryć klawiaturę.

@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {

    if (event.getAction() == MotionEvent.ACTION_DOWN) {
        if (keyCode == event.KEYCODE_ENTER) {

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

            return true;
        }
    }
    return false;
}
 0
Author: Ajith Memana,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-13 08:14:11

Hey guys I have simple solution for this problem and this solution can be used for simple registration or login form. moje rozwiązanie jest takie samo jak zaimplementowane w iOS setontouch listener do widoku głównego

Activity_main.XML dodaj ID do głównego układu względnego android:id="@+id/mainlayout"

I dodaj ten kod do swojej aktywności

  RelativeLayout mainLayout = (RelativeLayout)findViewById(R.id.mainlayout);
  mainLayout.setOnTouchListener(new OnTouchListener() {

            @Override
            public boolean onTouch(View v, MotionEvent event) {
                // TODO Auto-generated method stub
                 Log.d("Json Response", "Touch outside");
                  InputMethodManager inputMethodManager = (InputMethodManager)  MainActivity.this.getSystemService(Activity.INPUT_METHOD_SERVICE);
                    inputMethodManager.hideSoftInputFromWindow(MainActivity.this.getCurrentFocus().getWindowToken(), 0);
                return false;
            }
        });
 0
Author: Swap-IOS-Android,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-28 11:11:29