Zamknij / ukryj miękką klawiaturę Androida


3818

Mam A EditTexti A Buttonw moim układzie.

Po wpisaniu w polu edycji i kliknięciu przycisku Buttonchcę ukryć wirtualną klawiaturę. Zakładam, że jest to prosty fragment kodu, ale gdzie mogę znaleźć przykład?

Podczas dotykania poza klawiaturą.


13
Co jeśli masz tylko jeden EditText i kilka przycisków, takich jak pola wyboru i radia? Jedyne miejsce, w którym potrzebujesz klawiatury, to pojedynczy EditText. Jak się zarejestrować, aby wiedzieć, że wybrano / kliknięto coś innego, aby ukryć klawiaturę?
AlikElzin-kilaka

14
czuję się głupio. Nie mogę ukryć klawiatury w ICS. Wypróbowałem tutaj wszystkie metody i ich kombinacje. Nie ma mowy. Metoda pokazania, że ​​działa, ale nie mogę tego ukryć bez względu na żeton wiatru, ukryć flagi, zamanifestować ustawienia lub świece świętym. Na klawiaturze zawsze to widzę: I / LatinIME (396): Podano InputType.TYPE_NULL W / LatinIME (396): Nieoczekiwana klasa wejściowa: inputType = 0x00000000 imeOptions = 0x00000000
rupps

4
/ ** * Ta metoda służy do ukrywania miękkiej klawiatury. * @param activity * / public void hideSoftKeyboard (Activity activity) {InputMethodManager inputMethodManager = (InputMethodManager) activity.getSystemService (Activity.INPUT_METHOD_SERVICE); inputMethodManager.hideSoftInputFromWindow (activity.getCurrentFocus (). getWindowToken (), 0); }
Harshal Benake

to zadziałało dla mnie
nmxprime

Ponieważ urządzenia zwiększają rozmiar i rozdzielczość ekranu, ukrywanie wirtualnej klawiatury staje się coraz mniej ważne.
Al-Kathiri Khalid

Odpowiedzi:


2033

Aby pomóc wyjaśnić to szaleństwo, chciałbym zacząć od przeprosin w imieniu wszystkich użytkowników Androida za wręcz absurdalne traktowanie przez Google miękkiej klawiatury. Powodem jest tak wiele odpowiedzi, z których każda jest inna, na to samo proste pytanie, ponieważ ten interfejs API, podobnie jak wiele innych w Androidzie, jest strasznie zaprojektowany. Nie potrafię wymyślić żadnego grzecznego sposobu na wyrażenie tego.

Chcę ukryć klawiaturę. Spodziewam się, aby zapewnić Android z następującym stwierdzeniem: Keyboard.hide(). Koniec. Dziękuję Ci bardzo. Ale Android ma problem. Musisz użyć, InputMethodManageraby ukryć klawiaturę. OK, w porządku, to jest interfejs API Androida do klawiatury. ALE! Musisz mieć Context, aby uzyskać dostęp do IMM. Teraz mamy problem. Mogę chcieć ukryć klawiaturę przed klasą statyczną lub użytkową, która nie jest potrzebna ani potrzebna Context. lub I DALEKO gorzej, IMM wymaga określenia, coView (lub jeszcze gorzej, co Window) chcesz ukryć przed klawiaturą.

Właśnie dlatego ukrywanie klawiatury jest tak trudne. Drogi Google: Kiedy szukam przepisu na ciasto, nie maRecipeProvider na Ziemi która nie odmówiłaby podania mi przepisu, chyba że najpierw odpowiem KTO, przez co ciasto zostanie zjedzone ORAZ gdzie zostanie zjedzone !!

Ta smutna historia kończy się brzydką prawdą: aby ukryć klawiaturę Androida, musisz podać 2 formy identyfikacji: a Contexti a Viewlub aWindow .

Stworzyłem statyczną metodę narzędzia, która może wykonać zadanie BARDZO solidnie, pod warunkiem, że wywołasz go z Activity.

public static void hideKeyboard(Activity activity) {
    InputMethodManager imm = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
    //Find the currently focused view, so we can grab the correct window token from it.
    View view = activity.getCurrentFocus();
    //If no view currently has focus, create a new one, just so we can grab a window token from it
    if (view == null) {
        view = new View(activity);
    }
    imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}

Należy pamiętać, że ta metoda narzędzia działa TYLKO po wywołaniu z Activity! Powyższe wywołania metody getCurrentFocuscelu w Activitycelu pobrania odpowiedniego tokena okna.

Ale załóżmy, że chcesz ukryć klawiaturę przed EditTexthostowanym w DialogFragment? Nie możesz użyć powyższej metody do tego:

hideKeyboard(getActivity()); //won't work

To nie zadziała, ponieważ przekażesz referencję do Fragmenthosta Activity, który nie będzie miał żadnej skoncentrowanej kontroli, gdy Fragmentzostanie wyświetlony! Łał! Aby ukryć klawiaturę przed fragmentami, uciekam się do niższego poziomu, bardziej powszechnego i brzydszego:

public static void hideKeyboardFrom(Context context, View view) {
    InputMethodManager imm = (InputMethodManager) context.getSystemService(Activity.INPUT_METHOD_SERVICE);
    imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}

Poniżej znajduje się kilka dodatkowych informacji zebranych po dłuższym marnowaniu czasu na pogoń za tym rozwiązaniem:

Informacje o windowSoftInputMode

Jest jeszcze jeden punkt sporny, o którym należy pamiętać. Domyślnie Android automatycznie przypisze początkowy fokus do pierwszej EditTextlub sterowalnej fokusu w twoim Activity. Wynika z tego naturalnie, że InputMethod (zazwyczaj miękka klawiatura) zareaguje na zdarzenie skupienia, pokazując się. windowSoftInputModeAtrybut AndroidManifest.xml, gdy ustawiony stateAlwaysHidden, instruuje klawiaturę do ignorowania tego automatycznie przypisany początkowej ostrości.

<activity
    android:name=".MyActivity"
    android:windowSoftInputMode="stateAlwaysHidden"/>

Niemal niewiarygodne wydaje się, że nie robi nic, aby uniemożliwić otwarcie klawiatury po dotknięciu kontrolki (chyba że focusable="false"i / lub focusableInTouchMode="false"są przypisane do kontrolki). Najwyraźniej ustawienie windowSoftInputMode dotyczy tylko zdarzeń automatycznego fokusa, a nie zdarzeń fokusa wyzwalanych przez zdarzenia dotykowe.

Dlatego stateAlwaysHiddenjest BARDZO źle nazwany. Być może należy to nazwać ignoreInitialFocuszamiast tego.

Mam nadzieję że to pomoże.


AKTUALIZACJA: Więcej sposobów na uzyskanie tokena okna

Jeśli nie ma skupionego widoku (np. Może się zdarzyć, jeśli właśnie zmieniłeś fragmenty), istnieją inne widoki, które dostarczą przydatnego tokena okna.

Są to alternatywy dla powyższego kodu. if (view == null) view = new View(activity); Nie odnoszą się one wprost do Twojej aktywności.

Wewnątrz klasy fragmentu:

view = getView().getRootView().getWindowToken();

Biorąc pod uwagę fragment fragmentjako parametr:

view = fragment.getView().getRootView().getWindowToken();

Począwszy od treści treści:

view = findViewById(android.R.id.content).getRootView().getWindowToken();

AKTUALIZACJA 2: Wyczyść fokus, aby uniknąć ponownego wyświetlania klawiatury, jeśli otworzysz aplikację z tła

Dodaj ten wiersz na końcu metody:

view.clearFocus();


2
Bardzo fajny opis. Jedną rzeczą jest to, że jeśli rozpoczniesz na nim inną czynność, która uruchamia klawiaturę, klawiatura będzie nadal dostępna po powrocie. Naprawiono to, usuwając klawiaturę przy użyciu metody podczas wychodzenia z największej aktywności.
Oyvind

3
@rmirabelle FragmentWydaje się, że możesz użyćgetActivity().getWindow().getDecorView()
McX

1
Ten post jest świetny, ale brakuje ci dwóch bardzo ważnych części. Subtelne zmiany dokonane dla poszczególnych wersji i dla poszczególnych produkcji. Na przykład na Samsung Galaxy S6 musimy użyć .clearFocus () przed ukryciem klawiatury ... jeśli nie, klawiatura nadal będzie się wyświetlać po drugim kliknięciu edittext: S
Warpzit

17
Google powinien po prostu naprawdę udostępnić to Keyboard.hide();narzędzie
HendraWD,

1
[someView] .getContext () << Może być przypadek działania. To zawsze ten sam obiekt. (Z wyjątkiem usług wewnętrznych ...)
Oliver Dixon

4417

Możesz zmusić Androida do ukrycia wirtualnej klawiatury za pomocą InputMethodManager , wywołując hideSoftInputFromWindow, przekazując token okna zawierającego skupiony widok.

// Check if no view has focus:
View view = this.getCurrentFocus();
if (view != null) {  
    InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
    imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}

Wymusi to ukrycie klawiatury we wszystkich sytuacjach. W niektórych przypadkach będziesz chciał przekazać InputMethodManager.HIDE_IMPLICIT_ONLYjako drugi parametr, aby mieć pewność, że ukryjesz klawiaturę tylko wtedy, gdy użytkownik nie wymusił jej jawnego wyświetlenia (przytrzymując menu).

Uwaga: Jeśli chcesz to zrobić w Kotlin, użyj: context?.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager

Składnia Kotlina

// Check if no view has focus:
 val view = this.currentFocus
 view?.let { v ->
  val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as? InputMethodManager 
  imm?.hideSoftInputFromWindow(v.windowToken, 0)
 }

14
Dzięki temu wydaje się, że działa świetnie, jeśli używasz 0 jako drugiego parametru. Ale jeśli użyję InputMethodManager.HIDE_IMPLICIT_ONLY, klawiatura nigdy nie jest ukryta (chociaż nie przytrzymuję menu). Jakieś wskazówki?
RoflcoptrException

27
Fajne. Żeby to wyjaśnić, to tylko odrzuca je, jeśli jest obecne, ale nie zapobiega wyskakiwaniu, prawda?
Cheezmeister

15
Pomocne może być wywołanie editText.clearFocus () przed ukryciem softInput
user2224350

111
Wywołanie editText.clearFocus()wtedy InputMethodManager.HIDE_IMPLICIT_ONLYdziała nawet dalej4.1
sprocket12

11
To, co działało dla mnie w wersji 4.4 / htc, polegało View focused = getCurrentFocus()na uzyskaniu tego, co zdecydowanie jest aktualnie skupionym widokiem, wywoływaniem focused.clearFocus(), a następnie inputMethodManager.hideSoftInputFromWindow(focused.getWindowToken(), 0)(z wyraźnymi flagami).
Ionoclast Brigham

805

Przydatne również do ukrywania klawiatury programowej jest:

getWindow().setSoftInputMode(
    WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN
);

Można tego użyć, aby wyłączyć klawiaturę ekranową, dopóki użytkownik nie dotknie widoku edycji tekstu.


116
Możesz także osiągnąć ten sam efekt, dodając Androida: windowSoftInputMode = "stateHidden" do twojej aktywności w manifeście.
BoD

7
Próbowałem tego we fragmencie (odwołującym się do aktywności właściciela) na poziomie API 9 i niestety nie zadziałało. Próbowałem wywołać go w onResume i onActivityCreated - bez efektu.
AgentKnopf,

2
Pracuję w oknie dialogowym i to zadziałało. Używam Androida 3.2. Umieściłem go w metodzie onCreateDialog (pakiet). Nie działało w metodzie onCreate. Okno dialogowe = super.onCreateDialog (saveInstanceState); dialog.getWindow (). setSoftInputMode (WindowManager.LayoutParams. SOFT_INPUT_STATE_ALWAYS_HIDDEN); Rezultat jest taki, że mój widok z EditTexts pokazuje się bez klawiatury. Gdy użytkownik dotknie edytowanego tekstu, pojawi się klawiatura.
flobacca

4
To nie działa, gdy fokus znajduje się nadal w EditText (np. Po dotknięciu przycisku). Użyj do tego rozwiązania Reto.
Noumenon

4
Dlaczego zastępowanie ustawień manifestu jest złym pomysłem? Nazywam to z fragmentu. Nie ma żadnego oczywistego ustawienia, które dotyczyłoby fragmentu ...
Greg Ennis

348

Mam jeszcze jedno rozwiązanie, aby ukryć klawiaturę:

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

Tutaj przechodzą HIDE_IMPLICIT_ONLYw pozycji showFlagi 0w pozycji hiddenFlag. Mocno zamknie miękką klawiaturę.


4
Używasz flagi ukrywania w parametrze showflags. Działa to tylko dlatego, że stałe używają tych samych liczb całkowitych. Przykład użycia poprawnych flag
Alex

testowany na Androidzie 4.0, podoba mi się to rozwiązanie, ponieważ mam wiele tekstów do edycji, przycisków na tej aktywności, które mogą się skupić

32
@Mark: Ponieważ metoda nazywa się „toggleSoftInput”, a nie „hideSoftInput” :)
Sver

19
To rozwiązanie pokazuje klawiaturę, jeśli jest ukryta. To nie jest poprawne
Michael Katkov

1
@AkashAggarwal - „Działa”, jeśli zignorujesz fakt, że działał tylko dla Ciebie, ponieważ klawiatura była wyświetlana. (TO WŁĄCZA widoczność klawiatury: ukrywa się, gdy jest wyświetlana, ALE pokazuje ją, gdy jest ukryta !!) Czy możesz GWARANTOWAĆ, że w każdych okolicznościach, na wszystkich urządzeniach, dla wszystkich przyszłych wersji Androida, że ​​klawiatura NIE będzie wyświetlana w momencie, gdy dzwonisz? Jeśli tak, to skorzystaj z niego!
ToolmakerSteve,

148

Rozwiązanie Meiera również działa dla mnie. W moim przypadku najwyższym poziomem mojej aplikacji jest tabHost i chcę ukryć słowo kluczowe podczas przełączania kart - otrzymuję token okna z widoku tabHost.

tabHost.setOnTabChangedListener(new OnTabChangeListener() {
    public void onTabChanged(String tabId) {
        InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.hideSoftInputFromWindow(tabHost.getApplicationWindowToken(), 0);
    }
}

Mam to również do pracy z SearchView. Zobacz poniżej moją odpowiedź. Dzięki mckoss!
Azurespot

138

Spróbuj tego poniżej kodu w onCreate()

EditText edtView=(EditText)findViewById(R.id.editTextConvertValue);
edtView.setInputType(0);

2
Ta metoda działa w celu obejścia błędu „nie można ukryć miękkiej klawiatury” w wersjach 2.0 i 2.1, jak opisano w code.google.com/p/android/issues/detail?id=7115 ... metoda hideSoftInputFromWindow wymienione powyżej nie działało, kiedy próbowałem, ale editView.setInputType (0) działało.
Spike Williams

18
Jest to zgodne z Javadoc (nie hack), ale przepisałbym tę metodę jakoeditView.setInputType(InputType.TYPE_NULL);
Bostone,

3
działa to jednak ukrywa Androida: wskazówka. używam Androida 1.5
Tirtha

jest to świetne, gdy trzeba zamknąć klawiaturę z okna dialogowego, nie trzeba uzyskiwać instancji ani niczego, i można to przypisać do wszystkich tekstów edycji, gdy użytkownik naciśnie przycisk zamykający okno dialogowe
I'm_With_Stupid

Działa, ale ukrywa również kursor. Potrzebuję kursora, ale nie ma klawiatury systemowej.
Stefan Brendle,

128

Aktualizacja: Nie wiem, dlaczego to rozwiązanie już nie działa (właśnie testowałem na Androidzie 23). Zamiast tego skorzystaj z rozwiązania Saurabh Pareek . Oto on:

InputMethodManager imm = (InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE);
//Hide:
imm.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY, 0);
//Show
imm.toggleSoftInput(InputMethodManager.SHOW_IMPLICIT, 0);

Stara odpowiedź:

//Show soft-keyboard:
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
//hide keyboard :
 getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);

8
Gdzie powinienem umieścić ten kod? Próbowałem wkleić getWindow (). SetSoftInputMode (WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN); w onCreate (), ale klawiatura nigdy nie jest ukryta
user2236096

nie działa, testowany w radioGroup.setOnCheckedChangeListener, API 23
Christian Schäfer

Jeśli przyjrzysz się bliżej, InputMethodManager.HIDE_IMPLICIT_ONLY i InputMethodManager.SHOW_IMPLICIT mają tę samą wartość, czyli „1”, więc nie ma różnicy między tymi wywołaniami. => nie działa
Palejandro

jeśli wywołuje imm.toggleSoftInput (InputMethodManager.HIDE_IMPLICIT_ONLY, 0); wtedy klawiatura pokaże się na ekranie :) Najlepsza implementacja to: github.com/ravindu1024/android-keyboardlistener Wstyd w zestawie Android SDK
Duna

I don't know why this solution is not work any more- ponieważ jest to Android , wszystko będzie w stanie się zmienić, być może częściowo złego projektu ... Piszemy niedbale, a następnie przekreślamy wszystko i przepisujemy wszystko.
King King

88
protected void hideSoftKeyboard(EditText input) {
    InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
    imm.hideSoftInputFromWindow(input.getWindowToken(), 0);    
}

5
To zadziałało dla mnie! Ale dlaczego umieściłeś input.setInputType (0) ? Nie mogłem wchodzić w interakcje z EditTextView, gdy miałem ten wiersz kodu (działało, gdy go usunąłem).
ymerdrengene

Prawdopodobnie input.getContext().getSystemService(Context.INPUT_METHOD_SERVICE).
CoolMind,

Usunąłem input.setInputType(0);z tego kodu. Zmieniło zachowanie klawiatury i inputTypedla EditText.
CoolMind,

73

Jeśli wszystkie inne odpowiedzi tutaj nie działają tak, jak chcesz, istnieje inny sposób ręcznego sterowania klawiaturą.

Utwórz funkcję, która będzie zarządzać niektórymi EditTextwłaściwościami:

public void setEditTextFocus(boolean isFocused) {
    searchEditText.setCursorVisible(isFocused);
    searchEditText.setFocusable(isFocused);
    searchEditText.setFocusableInTouchMode(isFocused);

    if (isFocused) {
        searchEditText.requestFocus();
    }
}

Następnie upewnij się, że onFocus EditTextciebie otwiera / zamyka klawiaturę:

searchEditText.setOnFocusChangeListener(new OnFocusChangeListener() {
    @Override
    public void onFocusChange(View v, boolean hasFocus) {
        if (v == searchEditText) {
            if (hasFocus) {
                // Open keyboard
                ((InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE)).showSoftInput(searchEditText, InputMethodManager.SHOW_FORCED);
            } else {
                // Close keyboard
                ((InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE)).hideSoftInputFromWindow(searchEditText.getWindowToken(), 0);
            }
        }
    }
});

Teraz, gdy chcesz ręcznie otworzyć klawiaturę, zadzwoń:

setEditTextFocus(true);

I do zakończenia połączenia:

setEditTextFocus(false);

+1 - Jeśli chcesz rozpocząć działanie z zamkniętą klawiaturą, skorzystaj z tego rozwiązania i dodaj onclicklistener, który ustawia setEditTextFocus (true). Działa jak urok!
schlingel

Dostaję komunikat „Nie można rozwiązać kontekstu symboli” w 7. i 10. linii drugiego bloku kodu.
gimmegimme

Zamiast tego użyj getContext ()
Rotemmiz

61

Saurabh Pareek ma najlepszą jak dotąd odpowiedź.

Może jednak również użyć poprawnych flag.

/* hide keyboard */
((InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE))
    .toggleSoftInput(InputMethodManager.SHOW_IMPLICIT, 0);

/* show keyboard */
((InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE))
    .toggleSoftInput(0, InputMethodManager.HIDE_IMPLICIT_ONLY);

Przykład rzeczywistego użycia

/* click button */
public void onClick(View view) {      
  /* hide keyboard */
  ((InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE))
      .toggleSoftInput(InputMethodManager.SHOW_IMPLICIT, 0);

  /* start loader to check parameters ... */
}

/* loader finished */
public void onLoadFinished(Loader<Object> loader, Object data) {
    /* parameters not valid ... */

    /* show keyboard */
    ((InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE))
        .toggleSoftInput(0, InputMethodManager.HIDE_IMPLICIT_ONLY);

    /* parameters valid ... */
}

1
Jest to najbardziej wydajny w najnowszej wersji. Zawsze trzeba będzie go dostosować do starszych wersji. Zwłaszcza przed wersją 3.
Alex

2
@Mazen: usefragment.getActivity().getSystemService();
Johan S

To najbardziej wyczerpująca odpowiedź, obejmująca zarówno show, jak i hide.
André Staltz

4
Nie. Na mojej karcie Samsung, Android 5.0, tak zwany powyższy kod „ukryj klawiaturę” PRZEŁĄCZY miękką klawiaturę - jeśli jest już ukryta, pokaże ją. Istnieje powód, dla którego ta funkcja ma w nazwie TOGGLE.
ToolmakerSteve,

57

po tak poszukiwaniach znalazłem odpowiedź, która działa dla mnie

// Show soft-keyboard:
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);

// Hide soft-keyboard:
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);

Jedyny, który pracował dla mnie dla Motorola z Androidem 5.1
GMX

55

Krótka odpowiedź

W swoim OnClicksłuchaczu zadzwoń onEditorActionza EditTextpomocąIME_ACTION_DONE

button.setOnClickListener(new OnClickListener() {

    @Override
    public void onClick(View v) {
        someEditText.onEditorAction(EditorInfo.IME_ACTION_DONE)
    }
});

Drążenie w dół

Wydaje mi się, że ta metoda jest lepsza, prostsza i bardziej zgodna ze wzorcem projektowym Androida. W powyższym prostym przykładzie (i zwykle w większości typowych przypadków) będziesz mieć, EditTextktóry był / miał fokus, a także zwykle to on w pierwszej kolejności wywoływał klawiaturę (zdecydowanie jest w stanie wywołać ją w wielu przypadkach typowe scenariusze). W tej samej drodze, to powinno być jedno, aby zwolnić klawiaturę, zazwyczaj, które mogą być wykonywane przez ImeAction. Zobacz, jak to EditTextdziałaandroid:imeOptions="actionDone" zachowuje się „ , i chcesz osiągnąć to samo zachowanie w ten sam sposób.


Sprawdź tę powiązaną odpowiedź


To jest odpowiedź. Tylko metoda działająca w różnych wersjach. Wróciłem do tego pytania, aby opublikować tę odpowiedź, ponieważ nie sądziłem, że ktokolwiek wiedział
Noah Passalacqua

To powinna być poprawna odpowiedź. Zamiast oszukiwać Androida, aby ukrył klawiaturę, kiedy naprawdę powinna tam być, mówimy, że użytkownik jest skończony, co z kolei uruchamia tę samą ImeAction [głupia nazwa, przyznaję], jakby użytkownik kliknął „GOTOWE” na klawiaturze . W ten sposób nie ma znaczenia, czy użytkownik potwierdzi wprowadzenie na klawiaturze, czy stuknie przycisk interfejsu użytkownika.
Oliver Hausler

46

To powinno działać:

public class KeyBoard {

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

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

    public static void toggle(Activity activity){
        InputMethodManager imm = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
        if (imm.isActive()){
            hide(activity); 
        } else {
            show(activity); 
        }
    }
}

KeyBoard.toggle(activity);

Działa częściowo, nawet jeśli klawiatura była ukryta „isActive ()” zwraca false!
xpto

Oczywiście, że tak, powinno. A może cię nie rozumiem. W każdym razie możesz uzupełnić klasę metodami hide()i show()metodami, aby mieć większą kontrolę nad tym, kiedy powinna się ona pokazywać, a kiedy nie. Działa dla mnie, ja też to zrobiłem :)
Zmienię

@YoushaAleayoub tak to zrobi. KeyBoard.toggle(fragment.getActivity())
slinden77

@ slinden77, lol, mówię o twojej odpowiedzi ... nie tej, którą skomentowałeś. Więc ta odpowiedź wciąż NIE DZIAŁA.
Yousha Aleayoub

@YoushaAleayoub uhm tak to zrobi. Oryginalne pytanie nie wspomina o fragmentach, to ty wspomniałeś o fragmentach. Więc moja odpowiedź jest całkowicie poprawna. Aby użyć go z fragmentami, wywołaj metodę inaczej niż a Fragment, jak w komentarzu. Dowiedz się, jak korzystać z metod, a następnie wróć.
Mylicie

43

Używam niestandardowej klawiatury do wprowadzenia numeru szesnastkowego, więc nie mogę wyświetlić klawiatury IMM ...

W wersji 3.2.4_r1 setSoftInputShownOnFocus(boolean show)dodano, aby kontrolować pogodę lub nie wyświetlać klawiatury, gdy obiekt TextView zostanie ustawiony, ale nadal jest ukryty, więc należy użyć odbicia:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
    try {
        Method method = TextView.class.getMethod("setSoftInputShownOnFocus", boolean.class);
        method.invoke(mEditText, false);
    } catch (Exception e) {
        // Fallback to the second method
    }
}

W przypadku starszych wersji uzyskałem bardzo dobre wyniki (ale dalekie od ideału) za pomocą a OnGlobalLayoutListener, dodanego za pomocą a ViewTreeObserverz mojego widoku głównego, a następnie sprawdzenia, czy klawiatura jest wyświetlana w następujący sposób:

@Override
public void onGlobalLayout() {
    Configuration config = getResources().getConfiguration();

    // Dont allow the default keyboard to show up
    if (config.keyboardHidden != Configuration.KEYBOARDHIDDEN_YES) {
        InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.hideSoftInputFromWindow(mRootView.getWindowToken(), 0);
    }
}

To ostatnie rozwiązanie może pokazywać klawiaturę na ułamek sekundy i zadziera z uchwytami wyboru.

Kiedy na klawiaturze pojawia się pełny ekran, onGlobalLayout nie jest wywoływany. Aby tego uniknąć, użyj TextView # setImeOptions (int) lub w deklaracji XML TextView :

android:imeOptions="actionNone|actionUnspecified|flagNoFullscreen|flagNoExtractUi"

Aktualizacja: Właśnie znalazłem okna dialogowe, które nigdy nie pokazują klawiatury i działają we wszystkich wersjach:

getWindow().setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
        WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);

Dziękuję Ci. Dwie flagi FLAG_ALT_FOCUSABLE_IM i FLAG_ALT_FOCUSABLE_IM są w rzeczywistości jedyną rzeczą, która pomogła w moim przypadku. Nie chciałem, aby klawiatura była pokazywana w mojej aktywności - nawet gdy użytkownik kliknął edycję tekstu. (Zrobiłem własną „klawiaturę”).
Daniel Novak,

Fajne rozwiązanie, jednak jeśli przednia aktywność nie jest pełnoekranowa, za nią widoczna jest klawiatura. Również pomoc ruchu kursora na klawiaturze jest nadal widoczna. I to nie jest możliwe do skórowania.
halaksynat

Popieram to. Ze wszystkich możliwych sposobów działa tylko metoda getWindow (). SetFlags (), przynajmniej na standardowym Androidzie 5.1. Zauważ, że setSoftInputShownOnFocus () jest teraz setShowSoftInputOnFocus () i nie jest już ukryty, ale nie działa, przynajmniej nie, gdy użytkownik dotknie pola.
olefevre

Twoja „aktualizacja” była dla mnie jedynym działającym rozwiązaniem. Szukam rozwiązania przez co najmniej dwie godziny :)
Stefan Brendle,

33
public void setKeyboardVisibility(boolean show) {
    InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
    if(show){
        imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
    }else{
        imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(),0);
    }
}

30

Spędziłem ponad dwa dni pracując nad wszystkimi rozwiązaniami opublikowanymi w wątku i stwierdziłem, że brakuje im w ten czy inny sposób. Moim dokładnym wymaganiem jest mieć przycisk, który ze 100% niezawodnością pokaże lub ukryje klawiaturę ekranową. Gdy klawiatura jest w stanie ukrytym, nie powinna się ponownie pojawiać, bez względu na pola wejściowe, które kliknie użytkownik. Gdy jest w stanie widocznym, klawiatura nie powinna zniknąć bez względu na to, jakie przyciski użytkownik kliknie. To musi działać na Androidzie 2.2+ aż do najnowszych urządzeń.

Możesz zobaczyć działającą implementację tego w mojej aplikacji czystym RPN .

Po przetestowaniu wielu sugerowanych odpowiedzi na wielu różnych telefonach (w tym na urządzeniach froyo i piernikowych) stało się jasne, że aplikacje na Androida mogą niezawodnie:

  1. Tymczasowo ukryj klawiaturę. Pojawi się ponownie, gdy użytkownik ustawi nowe pole tekstowe.
  2. Pokaż klawiaturę po rozpoczęciu działania i ustaw flagę działania wskazującą, że klawiatura powinna być zawsze widoczna. Tę flagę można ustawić tylko podczas inicjowania działania.
  3. Oznacz aktywność, aby nigdy nie pokazywać ani nie zezwalać na korzystanie z klawiatury. Tę flagę można ustawić tylko podczas inicjowania działania.

Dla mnie chwilowe ukrywanie klawiatury nie wystarczy. Na niektórych urządzeniach pojawi się ponownie, gdy tylko nowe pole tekstowe zostanie zogniskowane. Ponieważ moja aplikacja korzysta z wielu pól tekstowych na jednej stronie, skupienie nowego pola tekstowego spowoduje ponowne pojawienie się ukrytej klawiatury.

Niestety pozycje 2 i 3 na liście działają tylko wtedy, gdy działanie jest rozpoczęte. Gdy aktywność stanie się widoczna, nie można trwale ukryć ani pokazać klawiatury. Sztuką jest zrestartowanie aktywności, gdy użytkownik naciśnie przycisk przełączania klawiatury. W mojej aplikacji, gdy użytkownik naciśnie przycisk przełączania klawiatury, uruchamia się następujący kod:

private void toggleKeyboard(){

    if(keypadPager.getVisibility() == View.VISIBLE){
        Intent i = new Intent(this, MainActivity.class);
        i.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
        Bundle state = new Bundle();
        onSaveInstanceState(state);
        state.putBoolean(SHOW_KEYBOARD, true);
        i.putExtras(state);

        startActivity(i);
    }
    else{
        Intent i = new Intent(this, MainActivity.class);
        i.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
        Bundle state = new Bundle();
        onSaveInstanceState(state);
        state.putBoolean(SHOW_KEYBOARD, false);
        i.putExtras(state);

        startActivity(i);
    }
}

Powoduje to, że bieżąca aktywność zostaje zapisana w pakiecie, a następnie aktywność jest uruchamiana, przechodząc przez wartość logiczną, która wskazuje, czy klawiatura powinna być pokazana, czy ukryta.

Wewnątrz metody onCreate uruchamiany jest następujący kod:

if(bundle.getBoolean(SHOW_KEYBOARD)){
    ((InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE)).showSoftInput(newEquationText,0);
    getWindow().setSoftInputMode(LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
}
else{
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
            WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
}

Jeśli powinna zostać wyświetlona klawiatura programowa, wówczas InputMethodManager ma wyświetlać klawiaturę, a okno jest instruowane, aby program był zawsze widoczny. Jeśli miękka klawiatura powinna być ukryta, wówczas ustawiany jest WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM.

To podejście działa niezawodnie na wszystkich urządzeniach, na których testowałem - od 4-letniego telefonu HTC z Androidem 2.2 do Nexusa 7 z 4.2.2. Jedyną wadą tego podejścia jest ostrożność przy posługiwaniu się przyciskiem Wstecz. Ponieważ moja aplikacja zasadniczo ma tylko jeden ekran (jest to kalkulator), mogę zastąpić onBackPressed () i wrócić do ekranu głównego urządzeń.


1
skomplikowane obejście, ale myślę, że to zbyt wiele, aby odtworzyć tysiące obiektów tylko po to, aby ukryć klawiaturę. Nie wiem, kto zaprojektował IMM dla Androida, ale pachnie jak Windows APi. Moim zdaniem dobry edytor IME powinien mieć dwie metody: ukryj i pokaż :-)
rupps

To wszystko prawda, ale moje obejście ma jedną zaletę - zawsze działa! Nie ma innego rozwiązania, które mógłbym znaleźć, które zawsze przełączałoby klawiaturę, niezależnie od tego, jakie pola w interfejsie użytkownika mają fokus, co użytkownik zrobił, aby włączyć klawiaturę i klawiaturę oraz jaką wersję Androida oni uruchamiają: - \
Luke Sleeman

Człowieku, jestem całkowicie zdesperowany, aby ukryć klawiaturę. Próbowałem tysięcy rzeczy i nikt nie działa. Ale twoje obejście to dla mnie za dużo, musiałbym odtworzyć jak 10 fragmentów, zainicjować usługi, usunąć wiele słabych odniesień ... wiesz? GC po prostu wyrzuci jak 25mb: S ... Nadal szukam niezawodnego sposobu na zrobienie tego :(
rupps

@Dmitry dobrze, to nie jest cześć świat ... to złożona aplikacja na tablety. Odmawiam całkowitego rozładowania go z pamięci tylko po to, aby ukryć głupią klawiaturę ... W każdym razie znalazłem coś, co działa, łącząc tysiące zaproponowanych tutaj rozwiązań :)
rupps

27

Alternatywnie do tego wszechstronnego rozwiązania , jeśli chcesz zamknąć klawiaturę programową z dowolnego miejsca bez odniesienia do pola (EditText), które było użyte do otwarcia klawiatury, ale nadal chciałbyś to zrobić, jeśli pole było skupione, możesz użyć to (z działania):

if (getCurrentFocus() != null) {
    InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
    imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
}

25

Dzięki tej odpowiedzi SO wyprowadziłem następujące, które w moim przypadku działa ładnie podczas przewijania fragmentów ViewPager ...

private void hideKeyboard() {   
    // Check if no view has focus:
    View view = this.getCurrentFocus();
    if (view != null) {
        InputMethodManager inputManager = (InputMethodManager) this.getSystemService(Context.INPUT_METHOD_SERVICE);
        inputManager.hideSoftInputFromWindow(view.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
    }
}

private void showKeyboard() {   
    // Check if no view has focus:
    View view = this.getCurrentFocus();
    if (view != null) {
        InputMethodManager inputManager = (InputMethodManager) this.getSystemService(Context.INPUT_METHOD_SERVICE);
        inputManager.showSoftInput(view, InputMethodManager.SHOW_IMPLICIT);
    }
}

21

Powyższe odpowiedzi działają w różnych scenariuszach, ale jeśli chcesz ukryć klawiaturę w widoku i próbujesz uzyskać właściwy kontekst, spróbuj tego:

setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View v) {
        hideSoftKeyBoardOnTabClicked(v);
    }
}

private void hideSoftKeyBoardOnTabClicked(View v) {
    if (v != null && context != null) {
        InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.hideSoftInputFromWindow(v.getApplicationWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
    }
}

i pobierz kontekst, pobierz go z konstruktora :)

public View/RelativeLayout/so and so (Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    this.context = context;
    init();
}

18

Jeśli chcesz zamknąć klawiaturę programową podczas testu jednostkowego lub funkcjonalnego, możesz to zrobić, klikając przycisk „Wstecz” w teście:

// Close the soft keyboard from a Test
getInstrumentation().sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);

W cudzysłowie wstawiam „przycisk Wstecz”, ponieważ powyższe nie uruchamia onBackPressed() danego działania. Po prostu zamyka klawiaturę.

Pamiętaj, aby zatrzymać się na chwilę przed przejściem dalej, ponieważ zamknięcie przycisku wstecz zajmuje trochę czasu, więc kolejne kliknięcia w Widoki itp. Nie zostaną zarejestrowane, dopóki nie nastąpi krótka pauza (1 sekunda jest wystarczająco długa ).


16

Oto jak to robisz w Mono na Androida (AKA MonoDroid)

InputMethodManager imm = GetSystemService (Context.InputMethodService) as InputMethodManager;
if (imm != null)
    imm.HideSoftInputFromWindow (searchbox.WindowToken , 0);

1
Co jest searchboxwe fragmencie?
PCoder,

16

To zadziałało w przypadku wszystkich dziwnych zachowań klawiatury

private boolean isKeyboardVisible() {
    Rect r = new Rect();
    //r will be populated with the coordinates of your view that area still visible.
    mRootView.getWindowVisibleDisplayFrame(r);

    int heightDiff = mRootView.getRootView().getHeight() - (r.bottom - r.top);
    return heightDiff > 100; // if more than 100 pixels, its probably a keyboard...
}

protected void showKeyboard() {
    if (isKeyboardVisible())
        return;
    InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
    if (getCurrentFocus() == null) {
        inputMethodManager.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
    } else {
        View view = getCurrentFocus();
        inputMethodManager.showSoftInput(view, InputMethodManager.SHOW_FORCED);
    }
}

protected void hideKeyboard() {
    if (!isKeyboardVisible())
        return;
    InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
    View view = getCurrentFocus();
    if (view == null) {
        if (inputMethodManager.isAcceptingText())
            inputMethodManager.toggleSoftInput(InputMethodManager.HIDE_NOT_ALWAYS, 0);
    } else {
        if (view instanceof EditText)
            ((EditText) view).setText(((EditText) view).getText().toString()); // reset edit text bug on some keyboards bug
        inputMethodManager.hideSoftInputFromInputMethod(view.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
    }
}

1
Myślę, że wypróbowałem 10 odpowiedzi przed tym. Porzuciłem nadzieję. Dzięki stary.
Bolling

Co to jest mRootView?
justdan0227

14

Dodaj do swojej aktywności android:windowSoftInputMode="stateHidden"w pliku manifestu. Przykład:

<activity
            android:name=".ui.activity.MainActivity"
            android:label="@string/mainactivity"
            android:windowSoftInputMode="stateHidden"/>

14

Prosta i łatwa w użyciu metoda, wystarczy wywołać hideKeyboardFrom (YourActivity.this); ukryć klawiaturę

/**
 * This method is used to hide keyboard
 * @param activity
 */
public static void hideKeyboardFrom(Activity activity) {
    InputMethodManager imm = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
    imm.hideSoftInputFromWindow(activity.getCurrentFocus().getWindowToken(), 0);
}

13

Po prostu użyj tego zoptymalizowanego kodu w swojej działalności:

if (this.getCurrentFocus() != null) {
    InputMethodManager inputManager = (InputMethodManager) this.getSystemService(Context.INPUT_METHOD_SERVICE);
    inputManager.hideSoftInputFromWindow(this.getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
}

Działa w porządku. Dzięki
Alif

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

po tym wywołaniu onTouchListener:

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

Spróbuj również tego - to zadziałało dla mnie: InputMethodManager imm = ((InputMethodManager) getSystemService (Activity.INPUT_METHOD_SERVICE)); imm.hideSoftInputFromWindow (getWindow (). getCurrentFocus (). getWindowToken (), 0);
zmicer

12

Użyj tego

this.getWindow().setSoftInputMode(
            WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);

12

W moim przypadku korzystałem z SearchView na pasku akcji. Po przeprowadzeniu wyszukiwania przez użytkownika klawiatura ponownie się otworzy.

Użycie InputMethodManager nie zamknęło klawiatury. Musiałem wyczyścić Focus i ustawić fokus widoku wyszukiwania na false:

mSearchView.clearFocus();
mSearchView.setFocusable(false);

1
Bardzo mądry. Jeśli użytkownik chce innego wyszukiwania, po prostu kliknij ponownie szukaj.
Alex

SearchView nie ma clearFocus()na stronach interfejsu API Androida, więc nie działało to dla mnie, ale zadziałało inne rozwiązanie (patrz moja odpowiedź poniżej).
Azurespot


12

Mam skrzynkę, w której mój EditTextmoże być umieszczony również w AlertDialog, więc klawiatura powinna być zamknięta po zwolnieniu. Następujący kod wydaje się działać wszędzie:

public static void hideKeyboard( Activity activity ) {
    InputMethodManager imm = (InputMethodManager)activity.getSystemService( Context.INPUT_METHOD_SERVICE );
    View f = activity.getCurrentFocus();
    if( null != f && null != f.getWindowToken() && EditText.class.isAssignableFrom( f.getClass() ) )
        imm.hideSoftInputFromWindow( f.getWindowToken(), 0 );
    else 
        activity.getWindow().setSoftInputMode( WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN );
}

1
To rozwiązanie jest lepsze, ponieważ nie musisz kontrolować, który parametr EditText przekazuje jako parametr do metody hideSoftInputFromWindow (). Działa świetnie !!
Billyjoker,

12

Prawie wypróbowałem wszystkie te odpowiedzi, miałem kilka przypadkowych problemów, szczególnie z Samsung Galaxy S5.

Skończyło się na wymuszeniu pokazu i ukrycia, i działa idealnie:

/**
 * Force show softKeyboard.
 */
public static void forceShow(@NonNull Context context) {
    InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
    imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
}

/**
 * Force hide softKeyboard.
 */
public static void forceHide(@NonNull Activity activity, @NonNull EditText editText) {
    if (activity.getCurrentFocus() == null || !(activity.getCurrentFocus() instanceof EditText)) {
        editText.requestFocus();
    }
    InputMethodManager imm = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE);
    imm.hideSoftInputFromWindow(editText.getWindowToken(), 0);
    activity.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.