Jak wykryć, czy klawiatura oprogramowania jest widoczna na urządzeniu z Androidem, czy nie?


249

Czy w Androidzie jest sposób na wykrycie, czy klawiatura programowa (inaczej „miękka”) jest widoczna na ekranie?



1
w niektórych przypadkach (jeśli zainstalowano klawiaturę innej firmy) rozwiązaniem może być sprawdzenie powiadomień globalnych, ponieważ gdy klawiatura jest otwarta, pojawia się powiadomienie systemowe z napisem „zmień klawiaturę” - można to zrobić za pomocą NotificationListenerService
Prof

2
prawie 8 lat i wciąż nie ma solidnego rozwiązania, och, jeśli je wprowadzą, to i tak będzie dla API> 30, więc nieważne ...
M.kazem Akhgary

Odpowiedzi:



276

To działa dla mnie. Może to zawsze najlepszy sposób dla wszystkich wersji .

Skuteczne byłoby uczynienie właściwości widoczności klawiatury i obserwowanie tych zmian z opóźnieniem, ponieważ metoda onGlobalLayout wywołuje wiele razy. Dobrze jest również sprawdzić obrót urządzenia i windowSoftInputModetak nie jest adjustNothing.

boolean isKeyboardShowing = false;
void onKeyboardVisibilityChanged(boolean opened) {
    print("keyboard " + opened);
}

// ContentView is the root view of the layout of this activity/fragment    
contentView.getViewTreeObserver().addOnGlobalLayoutListener(
    new ViewTreeObserver.OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {

        Rect r = new Rect();
        contentView.getWindowVisibleDisplayFrame(r);
        int screenHeight = contentView.getRootView().getHeight();

        // r.bottom is the position above soft keypad or device button.
        // if keypad is shown, the r.bottom is smaller than that before.
        int keypadHeight = screenHeight - r.bottom;

        Log.d(TAG, "keypadHeight = " + keypadHeight);

        if (keypadHeight > screenHeight * 0.15) { // 0.15 ratio is perhaps enough to determine keypad height.
            // keyboard is opened
            if (!isKeyboardShowing) {
                isKeyboardShowing = true
                onKeyboardVisibilityChanged(true)
            }
        }
        else {
            // keyboard is closed
            if (isKeyboardShowing) {
                isKeyboardShowing = false
                onKeyboardVisibilityChanged(false)
            }
        }
    }
});


1
Umieść to w klasie utils i przekaż aktywność - teraz przydatna w całej aplikacji.
Justin

2
A gdzie jest contentViewzadeklarowane?
Code-Apprentice

1
@ Code-Apprentice W ćwiczeniu / fragmencie chcesz zareagować na zmiany miękkiej klawiatury. ContentView to widok główny układu tego działania / fragmentu.
airowe

1
Pracował dla mnie na Androidzie 6 i 7.
V.Marzec

71

Spróbuj tego:

InputMethodManager imm = (InputMethodManager) getActivity()
            .getSystemService(Context.INPUT_METHOD_SERVICE);

    if (imm.isAcceptingText()) {
        writeToLog("Software Keyboard was shown");
    } else {
        writeToLog("Software Keyboard was not shown");
    }

9
To mi nie działa. Gałąź pokazana na klawiaturze uruchamia się nawet wtedy, gdy klawiatura nigdy nie była pokazywana lub była pokazywana, a następnie zamykana.
Peter Ajtai

30
zawsze zwraca prawdę.
shivang Trivedi

1
Tak, zawsze zwraca prawdę.
Léon Pelletier

Źle. To zawsze zwraca prawdę
Gaurav Arora

178
Żałosne jest to, że w systemie Android brakuje, a co gorsza, niespójne pod tym względem. To powinno być bardzo proste.
Vicky Chijwani,

57

Stworzyłem prostą klasę, której można użyć do tego: https://github.com/ravindu1024/android-keyboardlistener . Po prostu skopiuj go do swojego projektu i użyj:

KeyboardUtils.addKeyboardToggleListener(this, new KeyboardUtils.SoftKeyboardToggleListener()
{
    @Override
    public void onToggleSoftKeyboard(boolean isVisible)
    {
        Log.d("keyboard", "keyboard visible: "+isVisible);
    }
});

Gdzie w kodzie kodowym muszę to umieścić? Umieszczam to w działaniu, jednak nie wykrywa żadnego wyglądu ani zniknięcia klawiatury.
toom

Możesz umieścić go w dowolnym miejscu swojej aktywności. Wystarczy umieścić go w metodzie onCreate () po wywołaniu setContentView (), a powinieneś otrzymywać wywołania zwrotne. Przy okazji, na jakim urządzeniu próbujesz?
ravindu1024

@MaulikDodia Sprawdziłem i działa dobrze we fragmentach. Skonfiguruj to w następujący sposób: KeyboardUtils.addKeyboardToggleListener (getActivity (), this); i powinno działać. Na jakim urządzeniu próbujesz?
ravindu1024

Próbuję na urządzeniu Moto-G3. @ Ravindu1024
Maulik Dodia

Dzięki za ten fragment, mam jedno pytanie, czy ten kod jest wymagany do usunięcia nasłuchiwania?
Pratik Butani,

28

Bardzo łatwe

1. Umieść identyfikator w widoku głównym

rootViewjest tylko widokiem wskazującym mój widok główny w tym przypadku relative layout:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:id="@+id/addresses_confirm_root_view"
                android:background="@color/WHITE_CLR">

2. Zainicjuj widok główny w swojej działalności:

RelativeLayout rootView = (RelativeLayout) findViewById(R.id.addresses_confirm_root_view);

3. Sprawdź, czy klawiatura jest otwarta czy zamknięta za pomocą getViewTreeObserver()

    rootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                int heightDiff = rootView.getRootView().getHeight() - rootView.getHeight();

                if (heightDiff > 100) { 
                    Log.e("MyActivity", "keyboard opened");
                } else { 
                    Log.e("MyActivity", "keyboard closed");
                }
            }
        });

15
hej kolego, czy możesz mi powiedzieć, skąd pochodzi ta magia 100? Dlaczego nie 101 lub 99? Dzięki
Karoly,

@Karoly Myślę, że to może być i 1. Bez znaczenia. Tylko to musi być mniejsza niż rzeczywista długość klawiatury
Vlad

@Karoly w zasadzie porównuje rozmiar okna z rozmiarem widoku głównego twojej aktywności. wygląd miękkiej klawiatury nie wpływa na wielkość głównego okna. więc nadal możesz obniżyć wartość 100.
mr5

Magiczna liczba zależy między innymi od układu paska górnego. Jest to więc względne w stosunku do Twojej aplikacji. Użyłem 400 w jednym z moich.
Morten Holmgaard,

pamiętaj, że onGlobalLayout jest nazywany każdą ramką, więc upewnij się, że nie robisz tam ciężkich rzeczy.
Akshay Gaonkar,

8

Użyłem tego jako podstawy: http://www.ninthavenue.com.au/how-to-check-if-the-software-keyboard-is-shown-in-android

/**
* To capture the result of IMM hide/show soft keyboard
*/
public class IMMResult extends ResultReceiver {
     public int result = -1;
     public IMMResult() {
         super(null);
}

@Override 
public void onReceiveResult(int r, Bundle data) {
    result = r;
}

// poll result value for up to 500 milliseconds
public int getResult() {
    try {
        int sleep = 0;
        while (result == -1 && sleep < 500) {
            Thread.sleep(100);
            sleep += 100;
        }
    } catch (InterruptedException e) {
        Log.e("IMMResult", e.getMessage());
    }
    return result;
}
}

Następnie napisał tę metodę:

public boolean isSoftKeyboardShown(InputMethodManager imm, View v) {

    IMMResult result = new IMMResult();
    int res;

    imm.showSoftInput(v, 0, result);

    // if keyboard doesn't change, handle the keypress
    res = result.getResult();
    if (res == InputMethodManager.RESULT_UNCHANGED_SHOWN ||
            res == InputMethodManager.RESULT_UNCHANGED_HIDDEN) {

        return true;
    }
    else
        return false;

}

Następnie możesz użyć tego do przetestowania wszystkich pól (EditText, AutoCompleteTextView itp.), Które mogły otworzyć klawiaturę programową:

    InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
    if(isSoftKeyboardShown(imm, editText1) | isSoftKeyboardShown(imm, autocompletetextview1))
        //close the softkeyboard
        imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);

Wprawdzie nie jest to idealne rozwiązanie, ale wykonuje zadanie.


2
To działa. Jeśli zaimplementujesz jako singelton, możesz zastosować wszystkie edycje tekstu o zmianie fokusa i mieć jednego globalnego detektora klawiatury
Rarw

@depperm getActivity () jest specyficzny dla Fragmentów, spróbuj YourActivityName.this zamiast tego. Zobacz także: stackoverflow.com/questions/14480129/...
Christopher Hackl


6

Możesz odnieść się do tej odpowiedzi - https://stackoverflow.com/a/24105062/3629912

To działało dla mnie za każdym razem.

adb shell dumpsys window InputMethod | grep "mHasSurface"

Zwróci wartość true, jeśli klawiatura oprogramowania jest widoczna.


10
Jest to przydatne tylko podczas programowania - nie jest rozwiązaniem do użycia w aplikacji. (Użytkownicy nie będą mieli uruchomionego adb.)
ToolmakerSteve

5

Więc po długim czasie zabawy z usługami AccessibilityServices, wstawkami okien, wykrywaniem wysokości ekranu itp., Myślę, że znalazłem sposób, aby to zrobić.

Oświadczenie: używa ukrytej metody w Androidzie, co oznacza, że ​​może nie być spójna. Jednak w moich testach wydaje się, że działa.

Metodą jest InputMethodManager # getInputMethodWindowVisibleHeight () i istnieje od wersji Lollipop (5.0).

Wywołanie, które zwraca wysokość bieżącej klawiatury (w pikselach). Teoretycznie klawiatura nie powinna mieć 0 pikseli wysokości, więc wykonałem prostą kontrolę wysokości (w Kotlinie):

val imm by lazy { context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager }
if (imm.inputMethodWindowVisibleHeight > 0) {
    //keyboard is shown
else {
    //keyboard is hidden
}

Używam Android Hidden API, aby uniknąć odbicia, gdy wywołuję metody ukryte (robię to dużo dla aplikacji, które opracowuję, które są w większości aplikacjami typu hacky / tuner), ale powinno to być możliwe również z odbiciem:

val imm by lazy { context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager }
val windowHeightMethod = InputMethodManager::class.java.getMethod("getInputMethodWindowVisibleHeight")
val height = windowHeightMethod.invoke(imm) as Int
//use the height val in your logic

Niesamowite użycie odbić
kaustubhpatange

4

Było to o wiele mniej skomplikowane dla potrzeb, których potrzebowałem. Mam nadzieję, że to może pomóc:

Na MainActivity:

public void dismissKeyboard(){
    InputMethodManager imm =(InputMethodManager)this.getSystemService(Context.INPUT_METHOD_SERVICE);
    imm.hideSoftInputFromWindow(mSearchBox.getWindowToken(), 0);
    mKeyboardStatus = false;
}

public void showKeyboard(){
    InputMethodManager imm =(InputMethodManager)this.getSystemService(Context.INPUT_METHOD_SERVICE);
    imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, InputMethodManager.HIDE_IMPLICIT_ONLY);
    mKeyboardStatus = true;
}

private boolean isKeyboardActive(){
    return mKeyboardStatus;
}

Domyślna pierwotna wartość logiczna dla mKeyboardStatus zostanie zainicjowana na false .

Następnie sprawdź wartość w następujący sposób i w razie potrzeby wykonaj akcję:

 mSearchBox.requestFocus();
    if(!isKeyboardActive()){
        showKeyboard();
    }else{
        dismissKeyboard();
    }

4

Powinno to działać, jeśli chcesz sprawdzić stan klawiatury:

fun Activity.isKeyboardOpened(): Boolean {
    val r = Rect()

    val activityRoot = getActivityRoot()
    val visibleThreshold = dip(UiUtils.KEYBOARD_VISIBLE_THRESHOLD_DP)

    activityRoot.getWindowVisibleDisplayFrame(r)

    val heightDiff = activityRoot.rootView.height - r.height()

    return heightDiff > visibleThreshold;
}

fun Activity.getActivityRoot(): View {
    return (findViewById<ViewGroup>(android.R.id.content)).getChildAt(0);
}

Gdzie UiUtils.KEYBOARD_VISIBLE_THRESHOLD_DP= 100, a dip () to funkcja anko, która konwertuje dpToPx:

fun dip(value: Int): Int {
    return (value * Resources.getSystem().displayMetrics.density).toInt()
}

3

Zrobiłem to, ustawiając GlobalLayoutListener w następujący sposób:

final View activityRootView = findViewById(R.id.activityRoot);
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(
        new OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                int heightView = activityRootView.getHeight();
                int widthView = activityRootView.getWidth();
                if (1.0 * widthView / heightView > 3) {
                    //Make changes for Keyboard not visible
                } else {
                    //Make changes for keyboard visible
                }
            }
        });

Będzie to nazywać BARDZO często
Denis Kniazhev

W jakich przypadkach będzie to różnić się od odpowiedzi @BrownsooHan? Szukam sposobu, w jaki pokazuje aplikacja, która przesuwa się nad innymi aplikacjami, aby usunąć się z klawiatury.
Evan Langlois,

Jego odpowiedź jest zasadniczo taka sama jak moja, tyle że ja wydobywałem ją wiele miesięcy wcześniej, a on ma więcej pozytywnych opinii.
PearsonArtPhoto

3

Wypróbuj ten kod, który naprawdę działa, jeśli wyświetlona zostanie opcja KeyboardShown, a następnie ta funkcja zwróci prawdziwą wartość ....

private final String TAG = "TextEditor";
private TextView mTextEditor;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_editor);
    mTextEditor = (TextView) findViewById(R.id.text_editor);
    mTextEditor.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            isKeyboardShown(mTextEditor.getRootView());
        }
    });
}

private boolean isKeyboardShown(View rootView) {
    /* 128dp = 32dp * 4, minimum button height 32dp and generic 4 rows soft keyboard */
    final int SOFT_KEYBOARD_HEIGHT_DP_THRESHOLD = 128;

    Rect r = new Rect();
    rootView.getWindowVisibleDisplayFrame(r);
    DisplayMetrics dm = rootView.getResources().getDisplayMetrics();
    /* heightDiff = rootView height - status bar height (r.top) - visible frame height (r.bottom - r.top) */
    int heightDiff = rootView.getBottom() - r.bottom;
    /* Threshold size: dp to pixels, multiply with display density */
    boolean isKeyboardShown = heightDiff > SOFT_KEYBOARD_HEIGHT_DP_THRESHOLD * dm.density;

    Log.d(TAG, "isKeyboardShown ? " + isKeyboardShown + ", heightDiff:" + heightDiff + ", density:" + dm.density
            + "root view height:" + rootView.getHeight() + ", rect:" + r);

    return isKeyboardShown;
}

IsKeyboardShown nadal wywołuje się, gdy nie jest pokazywany.
Mandeep Singh,

2

W moim przypadku miałem tylko jeden EditTextukład do zarządzania, więc wymyśliłem to rozwiązanie. Działa dobrze, w zasadzie jest to zwyczaj, EditTextktóry nasłuchuje fokusu i wysyła transmisję lokalną, jeśli fokus zmieni się lub jeśli zostanie naciśnięty przycisk Wstecz / Gotowe. Aby pracować, musisz umieścić manekina Vieww swoim układzie za pomocą android:focusable="true"i android:focusableInTouchMode="true"ponieważ podczas rozmowyclearFocus() fokus zostanie ponownie przypisany do pierwszego widoku, który można ustawić. Przykładowy widok manekina:

<View
android:layout_width="1dp"
android:layout_height="1dp"
android:focusable="true"
android:focusableInTouchMode="true"/>

Dodatkowe informacje

Rozwiązanie, które wykrywa różnicę w zmianach układu, nie działa zbyt dobrze, ponieważ silnie zależy od gęstości ekranu, ponieważ 100 pikseli może być dużo w określonym urządzeniu, a w innych nie można uzyskać fałszywych wyników dodatnich. Również różni dostawcy mają różne klawiatury.


1

W Androidzie możesz wykryć za pomocą powłoki ADB. Napisałem i używam tej metody:

{
        JSch jsch = new JSch();
        try {
            Session session = jsch.getSession("<userName>", "<IP>", 22);
            session.setPassword("<Password>");
            Properties config = new Properties();
            config.put("StrictHostKeyChecking", "no");
            session.setConfig(config);
            session.connect();

            ChannelExec channel = (ChannelExec)session.openChannel("exec");
            BufferedReader in = new BufferedReader(new    
            InputStreamReader(channel.getInputStream()));
            channel.setCommand("C:/Android/android-sdk/platform-tools/adb shell dumpsys window 
            InputMethod | findstr \"mHasSurface\"");
            channel.connect();

            String msg = null;
            String msg2 = " mHasSurface=true";

            while ((msg = in.readLine()) != null) {
                Boolean isContain = msg.contains(msg2);
                log.info(isContain);
                if (isContain){
                    log.info("Hiding keyboard...");
                    driver.hideKeyboard();
                }
                else {
                    log.info("No need to hide keyboard.");
                }
            }

            channel.disconnect();
            session.disconnect();

        } catch (JSchException | IOException | InterruptedException e) {
            e.printStackTrace();
        }
    }
}

1
Czy możesz poprawić tę odpowiedź za pomocą bardziej konkretnego przykładu, z całym importem i działającym przykładem?
Użytkownik3

1
final View activityRootView = findViewById(R.id.rootlayout);
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {

            Rect r = new Rect();
            activityRootView.getWindowVisibleDisplayFrame(r);

            int screenHeight = activityRootView.getRootView().getHeight();
            Log.e("screenHeight", String.valueOf(screenHeight));
            int heightDiff = screenHeight - (r.bottom - r.top);
            Log.e("heightDiff", String.valueOf(heightDiff));
            boolean visible = heightDiff > screenHeight / 3;
            Log.e("visible", String.valueOf(visible));
            if (visible) {
                Toast.makeText(LabRegister.this, "I am here 1", Toast.LENGTH_SHORT).show();
            } else {
                Toast.makeText(LabRegister.this, "I am here 2", Toast.LENGTH_SHORT).show();
            }
        }
});

1

Odpowiedź @iWantScala jest świetna, ale nie działa dla mnie
rootView.getRootView().getHeight()zawsze ma tę samą wartość

Jednym ze sposobów jest zdefiniowanie dwóch zmiennych

private int maxRootViewHeight = 0;
private int currentRootViewHeight = 0;

dodaj globalny odbiornik

rootView.getViewTreeObserver()
    .addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            currentRootViewHeight = rootView.getHeight();
            if (currentRootViewHeight > maxRootViewHeight) {
                maxRootViewHeight = currentRootViewHeight;
            }
        }
    });

następnie sprawdź

if (currentRootViewHeight >= maxRootViewHeight) {
    // Keyboard is hidden
} else {
    // Keyboard is shown
}

działa w porządku


1

Wreszcie jest teraz bezpośredni sposób, zaczynając od Androida R opartego na Kotlinie.

 val imeInsets = view.rootWindowInsets.getInsets(Type.ime()) 
    if (imeInsets.isVisible) { 
     //Ime is visible
     //Lets move our view by the height of the IME
     view.translationX = imeInsets.bottom }

0

Miałem podobny problem. Musiałem zareagować na przycisk Enter na ekranie (który ukrywał klawiaturę). W takim przypadku możesz zasubskrybować opcję OnEditorAction widoku tekstowego, z którym korzystała klawiatura - jeśli masz wiele edytowalnych pól, zasubskrybuj je wszystkie.

W swojej działalności masz pełną kontrolę nad klawiaturą, więc w żadnym momencie nie staniesz przed problemem, czy klawiatura jest otwarta, czy nie, jeśli słuchasz wszystkich zdarzeń otwierania i zamykania.


Nie działa dla mnie. Otrzymuję tylko klawisz Enter w OnEditorAction.
3c71,

0

Istnieje bezpośredni sposób, aby się tego dowiedzieć. I nie wymaga zmian układu.
Działa więc również w trybie pełnego ekranu.
Ale niestety nie działa na wszystkich urządzeniach. Musisz to przetestować na swoich urządzeniach.

Sztuka polega na tym, że próbujesz ukryć lub pokazać miękką klawiaturę i uchwycić wynik tej próby.
Jeśli działa poprawnie, klawiatura nie jest tak naprawdę pokazywana ani ukryta. Po prostu pytamy o państwo.

Aby być na bieżąco, wystarczy powtórzyć tę operację, np. Co 200 milisekund, używając programu obsługi.

Poniższa implementacja wykonuje tylko jedną kontrolę.
Jeśli wykonujesz wiele kontroli, powinieneś włączyć wszystkie testy (_keyboardVisible).

public interface OnKeyboardShowHide
{
    void    onShowKeyboard( Object param );
    void    onHideKeyboard( Object param );
}

private static Handler      _keyboardHandler    = new Handler();
private boolean             _keyboardVisible    = false;
private OnKeyboardShowHide  _keyboardCallback;
private Object              _keyboardCallbackParam;

public void start( OnKeyboardShowHide callback, Object callbackParam )
{
    _keyboardCallback      = callback;
    _keyboardCallbackParam = callbackParam;
    //
    View view = getCurrentFocus();
    if (view != null)
    {
        InputMethodManager imm = (InputMethodManager) getSystemService( Activity.INPUT_METHOD_SERVICE );
        imm.hideSoftInputFromWindow( view.getWindowToken(), InputMethodManager.HIDE_IMPLICIT_ONLY, _keyboardResultReceiver );
        imm.showSoftInput( view, InputMethodManager.SHOW_IMPLICIT, _keyboardResultReceiver );
    }
    else // if (_keyboardVisible)
    {
        _keyboardVisible = false;
        _keyboardCallback.onHideKeyboard( _keyboardCallbackParam );
    }
}

private ResultReceiver      _keyboardResultReceiver = new ResultReceiver( _keyboardHandler )
{
    @Override
    protected void onReceiveResult( int resultCode, Bundle resultData )
    {
        switch (resultCode)
        {
            case InputMethodManager.RESULT_SHOWN :
            case InputMethodManager.RESULT_UNCHANGED_SHOWN :
                // if (!_keyboardVisible)
                {
                    _keyboardVisible = true;
                    _keyboardCallback.onShowKeyboard( _keyboardCallbackParam );
                }
                break;
            case InputMethodManager.RESULT_HIDDEN :
            case InputMethodManager.RESULT_UNCHANGED_HIDDEN :
                // if (_keyboardVisible)
                {
                    _keyboardVisible = false;
                    _keyboardCallback.onHideKeyboard( _keyboardCallbackParam );
                }
                break;
        }
    }
};

jak to nazwać i gdzie?
Mahdi Astanei,

0

Oto obejście, aby wiedzieć, czy klawiatura programowa jest widoczna.

  1. Sprawdź, czy usługi są uruchomione w systemie za pomocą ActivityManager.getRunningServices (max_count_of_services);
  2. W zwróconych instancjach ActivityManager.RunningServiceInfo sprawdź wartość clientCount dla obsługi klawiatury programowej .
  3. Wyżej wymienione clientCount będzie zwiększane za każdym razem, gdy wyświetlana jest klawiatura programowa. Na przykład, jeśli clientCount był początkowo 1, to będzie 2, gdy klawiatura jest wyświetlana.
  4. Po zwolnieniu klawiatury wartość clientCount jest zmniejszana. W takim przypadku resetuje się do 1.

Niektóre popularne klawiatury mają określone słowa kluczowe w swojej klasieNazwy:

  1. Google AOSP = edytor IME
  2. Swype = IME
  3. Swiftkey = KeyboardService
  4. Fleksy = klawiatura
  5. Adaptxt = IME (KPTAdaptxtIME)
  6. Smart = klawiatura (SmartKeyboard)

W ActivityManager.RunningServiceInfo sprawdź powyższe wzorce w ClassNames. Ponadto, clientPackage = android , ActivityManager.RunningServiceInfo's = android, wskazując, że klawiatura jest powiązana z systemem.

Powyższe informacje można połączyć w celu dokładnego sprawdzenia, czy widoczna jest miękka klawiatura.


0

Jak zapewne wiesz, klawiatura oprogramowania Android będzie widoczna tylko wtedy, gdy możliwe jest pisanie na klawiaturze. Innymi słowy Klawiatura staje się widoczna tylko wtedy, gdy jest skoncentrowany EditText. oznacza to, że możesz uzyskać pogodę, że klawiatura jest widoczna lub nie, używając OnFocusChangeListener .

//Declare this Globally

public boolean isKeyBoardVisible = false;

//In OnCreate *[For Activity]*, OnCreateView *[For Fragment]*

text_send.setOnFocusChangeListener(new View.OnFocusChangeListener() {

    @Override
    public void onFocusChange(View v, boolean hasFocus) {
        if(hasFocus)
            isKeyBoardVisible = true;
        else
            isKeyBoardVisible = false;
    }
});

Teraz możesz użyć zmiennej isKeyBoardVisible w dowolnym miejscu w klasie, aby uzyskać pogodę, że klawiatura jest otwarta lub nie. To działało dla mnie dobrze.

Uwaga: Ten proces nie działa, gdy klawiatura jest otwierana programowo za pomocą InputMethodManager, ponieważ nie wywołuje OnFocusChangeListener.


tak naprawdę nie hack, nie działał w przypadku zagnieżdżonego fragmentu fragmentu. Nie mogę powiedzieć o działaniach, ponieważ jeszcze tego nie próbowałem.
antroid

0

Przekształciłem odpowiedź na kotlin, mam nadzieję, że pomoże to użytkownikom kotlin.

private fun checkKeyboardVisibility() {
    var isKeyboardShowing = false

    binding.coordinator.viewTreeObserver.addOnGlobalLayoutListener {
        val r = Rect()
        binding.coordinator.getWindowVisibleDisplayFrame(r)
        val screenHeight = binding.coordinator.rootView.height

        // r.bottom is the position above soft keypad or device button.
        // if keypad is shown, the r.bottom is smaller than that before.
        val keypadHeight = screenHeight - r.bottom


        if (keypadHeight > screenHeight * 0.15) { // 0.15 ratio is perhaps enough to determine keypad height.
            // keyboard is opened
            if (!isKeyboardShowing) {
                isKeyboardShowing = true

            }
        } else {
            // keyboard is closed
            if (isKeyboardShowing) {
                isKeyboardShowing = false

            }
        }
    }
}

0

Działa z funkcją dostosowaniaNie są używane flagi aktywności i zdarzeń cyklu życia. Również z Kotlinem:

/**
 * This class uses a PopupWindow to calculate the window height when the floating keyboard is opened and closed
 *
 * @param activity The parent activity
 *  The root activity that uses this KeyboardManager
 */
class KeyboardManager(private val activity: AppCompatActivity) : PopupWindow(activity), LifecycleObserver {

    private var observerList = mutableListOf<((keyboardTop: Int) -> Unit)>()

    /** The last value of keyboardTop */
    private var keyboardTop: Int = 0

    /** The view that is used to calculate the keyboard top  */
    private val popupView: View?

    /** The parent view  */
    private var parentView: View

    var isKeyboardShown = false
        private set

    /**
     * Create transparent view which will be stretched over to the full screen
     */
    private fun createFullScreenView(): View {
        val view = LinearLayout(activity)
        view.layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.MATCH_PARENT)
        view.background = ColorDrawable(Color.TRANSPARENT)
        return view
    }

    init {
        this.popupView = createFullScreenView()
        contentView = popupView

        softInputMode = LayoutParams.SOFT_INPUT_ADJUST_RESIZE or LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE
        inputMethodMode = INPUT_METHOD_NEEDED

        parentView = activity.findViewById(android.R.id.content)

        width = 0
        height = LayoutParams.MATCH_PARENT

        popupView.viewTreeObserver.addOnGlobalLayoutListener {
            val rect = Rect()
            popupView.getWindowVisibleDisplayFrame(rect)

            val keyboardTop = rect.bottom
            if (this.keyboardTop != keyboardTop) {
                isKeyboardShown = keyboardTop < this.keyboardTop
                this.keyboardTop = keyboardTop
                observerList.forEach { it(keyboardTop) }
            }
        }
        activity.lifecycle.addObserver(this)
    }

    /**
     * This must be called after the onResume of the Activity or inside view.post { } .
     * PopupWindows are not allowed to be registered before the onResume has finished
     * of the Activity
     */
    @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
    fun start() {
        parentView.post {
            if (!isShowing && parentView.windowToken != null) {
                setBackgroundDrawable(ColorDrawable(0))
                showAtLocation(parentView, Gravity.NO_GRAVITY, 0, 0)
            }
        }
    }

    /**
     * This manager will not be used anymore
     */
    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
    fun close() {
        activity.lifecycle.removeObserver(this)
        observerList.clear()
        dismiss()
    }

    /**
     * Set the keyboard top observer. The observer will be notified when the keyboard top has changed.
     * For example when the keyboard is opened or closed
     *
     * @param observer The observer to be added to this provider
     */
    fun registerKeyboardTopObserver(observer: (keyboardTop: Int) -> Unit) {
        observerList.add(observer)
    }
}

Przydatna metoda utrzymywania widoku zawsze nad klawiaturą

fun KeyboardManager.updateBottomMarginIfKeyboardShown(
        view: View,
        activity: AppCompatActivity,
        // marginBottom of view when keyboard is hide
        marginBottomHideKeyboard: Int,
        // marginBottom of view when keybouard is shown
        marginBottomShowKeyboard: Int
) {
    registerKeyboardTopObserver { bottomKeyboard ->
        val bottomView = ViewUtils.getFullViewBounds(view).bottom
        val maxHeight = ScreenUtils.getFullScreenSize(activity.windowManager).y
        // Check that view is within the window size
        if (bottomView < maxHeight) {
            if (bottomKeyboard < bottomView) {
                ViewUtils.updateMargin(view, bottomMargin = bottomView - bottomKeyboard +
                        view.marginBottom + marginBottomShowKeyboard)
            } else ViewUtils.updateMargin(view, bottomMargin = marginBottomHideKeyboard)
        }
    }
}

Gdzie getFullViewBounds

fun getLocationOnScreen(view: View): Point {
    val location = IntArray(2)
    view.getLocationOnScreen(location)
    return Point(location[0], location[1])
}

fun getFullViewBounds(view: View): Rect {
     val location = getLocationOnScreen(view)
     return Rect(location.x, location.y, location.x + view.width,
            location.y + view.height)
 }

Gdzie getFullScreenSize

fun getFullScreenSize(wm: WindowManager? = null) =
            getScreenSize(wm) { getRealSize(it) }

private fun getScreenSize(wm: WindowManager? = null, block: Display.(Point) -> Unit): Point {
    val windowManager = wm ?: App.INSTANCE.getSystemService(Context.WINDOW_SERVICE)
            as WindowManager
    val point = Point()
    windowManager.defaultDisplay.block(point)
    return point
}

Gdzie updateMargin

fun updateMargin(
        view: View,
        leftMargin: Int? = null,
        topMargin: Int? = null,
        rightMargin: Int? = null,
        bottomMargin: Int? = null
) {
    val layoutParams = view.layoutParams as ViewGroup.MarginLayoutParams
    if (leftMargin != null) layoutParams.leftMargin = leftMargin
    if (topMargin != null) layoutParams.topMargin = topMargin
    if (rightMargin != null) layoutParams.rightMargin = rightMargin
    if (bottomMargin != null) layoutParams.bottomMargin = bottomMargin
    view.layoutParams = layoutParams
}

-1

Zrobiłem to w następujący sposób, ale ma to znaczenie tylko wtedy, gdy Twoim celem jest zamknięcie / otwarcie klucza.

zamknij przykład: (sprawdzenie, czy klawiatura jest już zamknięta, jeśli nie - zamknięcie)

imm.showSoftInput(etSearch, InputMethodManager.HIDE_IMPLICIT_ONLY, new ResultReceiver(null) {
                    @Override
                    protected void onReceiveResult(int resultCode, Bundle resultData) {
                        super.onReceiveResult(resultCode, resultData);
                        if (resultCode != InputMethodManager.RESULT_UNCHANGED_HIDDEN)
                            imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
                    }
                });

Pytanie dotyczyło tego, czy klawiatura jest wyświetlana, czy nie
Gopal Singh Sirvi

-1

a może używać:

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);

    Log.d(
    getClass().getSimpleName(), 
    String.format("conf: %s", newConfig));

    if (newConfig.hardKeyboardHidden != hardKeyboardHidden) {
        onHardwareKeyboardChange(newConfig.hardKeyboardHidden);

        hardKeyboardHidden = newConfig.hardKeyboardHidden;
    }

    if (newConfig.keyboardHidden != keyboardHidden) {
        onKeyboardChange(newConfig.keyboardHidden);

        keyboardHidden = newConfig.hardKeyboardHidden;
    }

}

public static final int KEYBOARDHIDDEN_UNDEFINED = 0;
public static final int KEYBOARDHIDDEN_NO = 1;
public static final int KEYBOARDHIDDEN_YES = 2;
public static final int KEYBOARDHIDDEN_SOFT = 3;

//todo
private void onKeyboardChange(int keyboardHidden) {

}

//todo
private void onHardwareKeyboardChange(int hardKeyboardHidden) {

}



-1

Jeśli w swojej aplikacji obsługujesz api dla AndroidR, możesz użyć poniższej metody.

In kotlin :
    var imeInsets = view.rootWindowInsets.getInsets(Type.ime()) 
    if (imeInsets.isVisible) { 
        view.translationX = imeInsets.bottom 
    }

Uwaga: ta opcja jest dostępna tylko dla systemu AndroidR, a poniżej wersja Androida musi podążać za inną odpowiedzią lub zaktualizuję ją w tym celu.

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.