Wie erkenne ich, ob auf dem Android-Gerät eine Softwaretastatur sichtbar ist oder nicht?

249

Gibt es in Android eine Möglichkeit zu erkennen, ob die Software-Tastatur (auch "Soft" genannt) auf dem Bildschirm sichtbar ist?

andreea
quelle
1
was kann eine Lösung dieses Problem in bestimmten Fällen (wenn eine 3rd - Party - Tastatur installiert ist) ist es, die globalen Meldungen zu überprüfen , wenn eine Tastatur geöffnet ist eine System - Benachrichtigung ist , die „change - Tastatur“ , sagt - mit einem getan werden NotificationListenerService
Prof
2
Fast 8 Jahre und immer noch keine feste Lösung, oh, wenn sie eine einführen, wird es sowieso für API> 30 sein, also
egal
Mögliches Duplikat von Android: Softkeyboard offen erkennen
AbdelHady

Antworten:

276

Das funktioniert bei mir. Vielleicht ist dies immer der beste Weg für alle Versionen .

Es wäre effektiv, eine Eigenschaft der Tastatursichtbarkeit festzulegen und diese Änderungen verzögert zu beobachten, da die onGlobalLayout-Methode viele Male aufgerufen wird. Es ist auch gut, die Gerätedrehung zu überprüfen und windowSoftInputModenicht 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)
            }
        }
    }
});
Brownsoo Han
quelle
3
Hier ist eine funktionierende Zusammenfassung: gist.github.com/faruktoptas/e9778e1f718214938b00c2dcd2bed109
Faruk Toptas
1
Fügen Sie dies in eine Utils-Klasse ein und übergeben Sie die Aktivität - jetzt nützlich für die gesamte App.
Justin
2
Und wo wird contentViewdeklariert?
Code-Apprentice
1
@ Code-Apprentice In der Aktivität / dem Fragment möchten Sie auf Änderungen an der Softtastatur reagieren. ContentView ist die Stammansicht des Layouts dieser Aktivität / dieses Fragments.
Airowe
1
Arbeitete für mich auf Android 6 und 7.
V.März
71

Versuche dies:

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

    if (imm.isAcceptingText()) {
        writeToLog("Software Keyboard was shown");
    } else {
        writeToLog("Software Keyboard was not shown");
    }
IHeartAndroid
quelle
9
Das funktioniert bei mir nicht. Der angezeigte Zweig der Tastatur wird auch dann ausgelöst, wenn die Tastatur nie angezeigt oder angezeigt und dann geschlossen wurde.
Peter Ajtai
30
es wird immer wahr zurückgegeben.
Shivang Trivedi
1
Ja, es kehrt immer wahr zurück.
Léon Pelletier
Falsch. Dies gibt immer wahr zurück
Gaurav Arora
178
Es ist erbärmlich, dass das Android-Framework in dieser Hinsicht fehlt und schlimmer noch inkonsistent ist . Das sollte super einfach sein.
Vicky Chijwani
57

Ich habe eine einfache Klasse erstellt, die dafür verwendet werden kann: https://github.com/ravindu1024/android-keyboardlistener . Kopieren Sie es einfach in Ihr Projekt und verwenden Sie es wie folgt:

KeyboardUtils.addKeyboardToggleListener(this, new KeyboardUtils.SoftKeyboardToggleListener()
{
    @Override
    public void onToggleSoftKeyboard(boolean isVisible)
    {
        Log.d("keyboard", "keyboard visible: "+isVisible);
    }
});
ravindu1024
quelle
Wo genau muss ich das in den Code einfügen? Ich habe dies in eine Aktivität eingefügt, es erkennt jedoch kein Erscheinungsbild oder Verschwinden der Tastatur.
Toom
Nun, Sie können es überall in Ihrer Aktivität platzieren. Fügen Sie es einfach nach dem Aufruf von setContentView () in die onCreate () -Methode ein, und Sie sollten Rückrufe erhalten. Übrigens, auf welchem ​​Gerät probierst du es an?
Ravindu1024
@ MaulikDodia Ich habe es überprüft und es funktioniert gut in Fragmenten. Richten Sie es folgendermaßen ein: KeyboardUtils.addKeyboardToggleListener (getActivity (), this); und es sollte funktionieren. Auf welchem ​​Gerät probierst du es an?
Ravindu1024
Ich versuche es mit einem Moto-G3-Gerät. @ Ravindu1024
Maulik Dodia
Vielen Dank für diesen Ausschnitt. Ich habe eine Frage: Ist dieser Code erforderlich, um den Listener zu entfernen?
Pratik Butani
28

Sehr leicht

1. Fügen Sie die ID in Ihre Stammansicht ein

rootViewist in diesem Fall nur eine Ansicht, die auf meine Stammansicht verweist relative layout: a :

<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. Initialisieren Sie Ihre Stammansicht in Ihrer Aktivität:

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

3. Ermitteln Sie mithilfe von, ob die Tastatur geöffnet oder geschlossen ist 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");
                }
            }
        });
CommonSenseCode
quelle
15
Hey Kumpel, kannst du mir bitte sagen, woher diese magische 100 kommt? Warum nicht 101 oder 99? Danke
Karoly
@ Karoly ich denke das kann sein und 1. Ganz gleich. Nur dies muss kleiner sein als die tatsächliche Länge der Tastatur
Vlad
@Karoly Im Grunde vergleicht er die Fenstergröße mit der Größe der Stammansicht Ihrer Aktivität. Das Erscheinungsbild der Softtastatur wirkt sich nicht auf die Größe des Hauptfensters aus. so können Sie den Wert von 100 noch senken.
mr5
Die magische Zahl hängt unter anderem von Ihrem Layout der oberen Leiste ab. Es ist also relativ zu Ihrer App. Ich habe 400 in einem von mir verwendet.
Morten Holmgaard
Denken Sie daran, dass onGlobalLayout in jedem Frame aufgerufen wird. Stellen Sie also sicher, dass Sie dort keine schweren Dinge tun.
Akshay Gaonkar
8

Ich habe dies als Grundlage verwendet: 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;
}
}

Dann schrieb diese Methode:

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;

}

Sie können dies dann verwenden, um alle Felder (EditText, AutoCompleteTextView usw.) zu testen, die möglicherweise ein Softkeyboard geöffnet haben:

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

Zwar keine ideale Lösung, aber es erledigt den Job.

Christopher Hackl
quelle
2
Das funktioniert. Wenn Sie als Singelton implementieren, können Sie sich auf alle Edittexte zur Fokusänderung bewerben und haben einen globalen Tastatur-Listener
Rarw
@depperm getActivity () ist spezifisch für Fragmente. Versuchen Sie stattdessen YourActivityName.this. Siehe auch: stackoverflow.com/questions/14480129/…
Christopher Hackl
6

Sie können sich auf diese Antwort beziehen - https://stackoverflow.com/a/24105062/3629912

Es hat jedes Mal bei mir funktioniert.

adb shell dumpsys window InputMethod | grep "mHasSurface"

Es wird true zurückgegeben, wenn die Softwaretastatur sichtbar ist.

l '-' l
quelle
10
Dies ist nur während der Entwicklung nützlich - keine Lösung für die Verwendung in einer App. (Benutzer haben kein AdB ausgeführt.)
ToolmakerSteve
5

Nach einer langen Zeit des Herumspielens mit AccessibilityServices, Fenstereinfügungen, Bildschirmhöhenerkennung usw. habe ich einen Weg gefunden, dies zu tun.

Haftungsausschluss: In Android wird eine versteckte Methode verwendet, was bedeutet, dass sie möglicherweise nicht konsistent ist. Bei meinen Tests scheint es jedoch zu funktionieren.

Die Methode ist InputMethodManager # getInputMethodWindowVisibleHeight () und existiert seit Lollipop (5.0).

Ein Aufruf, der die Höhe der aktuellen Tastatur in Pixel zurückgibt. Theoretisch sollte eine Tastatur nicht 0 Pixel groß sein, daher habe ich eine einfache Höhenprüfung durchgeführt (in Kotlin):

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

Ich verwende die Android Hidden API , um Reflexionen zu vermeiden, wenn ich versteckte Methoden aufrufe (das mache ich häufig für die von mir entwickelten Apps, bei denen es sich hauptsächlich um Hacky / Tuner-Apps handelt), aber dies sollte auch mit Reflexionen möglich sein:

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
Der Wanderer
quelle
Erstaunliche Verwendung von Reflexionen
kaustubhpatange
4

Dies war für die Anforderungen, die ich brauchte, viel weniger kompliziert. Hoffe das könnte helfen:

Auf der Hauptaktivität:

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

Der standardmäßige primitive boolesche Wert für mKeyboardStatus wird auf false initialisiert .

Überprüfen Sie dann den Wert wie folgt und führen Sie gegebenenfalls eine Aktion aus:

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

Dies sollte funktionieren, wenn Sie den Tastaturstatus überprüfen müssen:

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

Wobei UiUtils.KEYBOARD_VISIBLE_THRESHOLD_DP= 100 und dip () eine Anko-Funktion ist, die dpToPx konvertiert:

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

Dazu habe ich einen GlobalLayoutListener wie folgt festgelegt:

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
                }
            }
        });
PearsonArtPhoto
quelle
Dies wird sehr oft genannt
Denis Kniazhev
In welchen Fällen unterscheidet sich dies von der Antwort von @BrownsooHan? Ich suche nach einer Möglichkeit, die eine App zeigt, die andere Apps verwendet, um der Tastatur aus dem Weg zu gehen.
Evan Langlois
Seine Antwort ist im Grunde die gleiche wie meine, nur ich habe meine viele Monate vor seiner gemacht, und er hat mehr positive Stimmen.
PearsonArtPhoto
3

Versuchen Sie diesen Code, es funktioniert wirklich, wenn KeyboardShown angezeigt wird, dann gibt diese Funktion den wahren Wert zurück ....

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;
}
Ravi Makvana
quelle
Das isKeyboardShown ruft sich weiterhin selbst auf, wenn es nicht angezeigt wird.
Mandeep Singh
2

In meinem Fall hatte ich nur eine EditTextin meinem Layout zu verwalten, also kam ich auf diese Lösung. Es funktioniert gut, im Grunde ist es eine benutzerdefinierte Funktion, EditTextdie auf den Fokus wartet und eine lokale Sendung sendet, wenn sich der Fokus ändert oder wenn die Zurück / Fertig-Taste gedrückt wird. Arbeiten Sie einen Dummy platzieren müssen Viewmit in Ihrem Layout android:focusable="true"und android:focusableInTouchMode="true"weil , wenn Sie anrufen wird clearFocus()der Fokus auf die erste fokussierbare Ansicht neu zugewiesen werden. Beispiel für eine Dummy-Ansicht:

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

Zusätzliche Infos

Die Lösung, die den Unterschied bei Layoutänderungen erkennt, funktioniert nicht sehr gut, da sie stark von der Bildschirmdichte abhängt, da 100 Pixel in einem bestimmten Gerät sehr viel sein können und in einigen anderen Geräten nichts Falsches. Auch verschiedene Anbieter haben unterschiedliche Tastaturen.

TheRedFox
quelle
1

In Android können Sie über ADB-Shell erkennen. Ich habe diese Methode geschrieben und angewendet:

{
        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();
        }
    }
}
Eyal Sooliman
quelle
1
Können Sie diese Antwort mit einem konkreteren Beispiel mit allen Importen und einem funktionierenden Beispiel verbessern?
User3
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();
            }
        }
});
user3068659
quelle
1

Die Antwort von @iWantScala ist großartig, aber nicht für mich zu arbeiten hat
rootView.getRootView().getHeight()immer den gleichen Wert

Eine Möglichkeit besteht darin, zwei Vars zu definieren

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

globalen Listener hinzufügen

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

dann überprüfe

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

funktioniert gut

Vlad
quelle
1

Es gibt jetzt endlich einen direkten Weg von Android R basierend auf Kotlin.

 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 }
Bharadwaj Giridhar
quelle
0

Ich hatte ein ähnliches Problem. Ich musste auf die Eingabetaste auf dem Bildschirm reagieren (die die Tastatur verbarg). In diesem Fall können Sie die OnEditorAction der Textansicht abonnieren, mit der die Tastatur geöffnet wurde. Wenn Sie mehrere bearbeitbare Felder haben, abonnieren Sie alle.

In Ihrer Aktivität haben Sie die volle Kontrolle über die Tastatur, sodass Sie zu keinem Zeitpunkt das Problem haben, ob die Tastatur geöffnet ist oder nicht, wenn Sie alle Öffnungs- und Schließereignisse abhören.

Andras Balázs Lajtha
quelle
Funktioniert bei mir nicht Ich erhalte nur die Eingabetaste in OnEditorAction.
3c71
0

Es gibt eine direkte Methode, um dies herauszufinden. Die Layoutänderungen sind nicht erforderlich.
So funktioniert es auch im immersiven Vollbildmodus.
Leider funktioniert es nicht auf allen Geräten. Sie müssen es also mit Ihren Geräten testen.

Der Trick besteht darin, dass Sie versuchen, die Softtastatur auszublenden oder anzuzeigen und das Ergebnis dieses Versuchs zu erfassen.
Wenn es richtig funktioniert, wird die Tastatur nicht wirklich angezeigt oder ausgeblendet. Wir fragen nur nach dem Staat.

Um auf dem neuesten Stand zu bleiben, wiederholen Sie diesen Vorgang einfach, z. B. alle 200 Millisekunden, mit einem Handler.

Die folgende Implementierung führt nur eine einzige Überprüfung durch.
Wenn Sie mehrere Überprüfungen durchführen, sollten Sie alle (_keyboardVisible) -Tests aktivieren.

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;
        }
    }
};
fies
quelle
wie man es nennt und wo?
Mahdi Astanei
0

Hier ist eine Problemumgehung, um festzustellen, ob das Softkeyboard sichtbar ist.

  1. Überprüfen Sie mithilfe von ActivityManager.getRunningServices (max_count_of_services), ob Dienste auf dem System ausgeführt werden.
  2. Überprüfen Sie in den zurückgegebenen ActivityManager.RunningServiceInfo-Instanzen Wert clientCount für den Softtastaturdienst .
  3. Der oben genannte clientCount wird jedes Mal erhöht, wenn die Softtastatur angezeigt wird. Wenn clientCount beispielsweise anfangs 1 war, wäre es 2, wenn die Tastatur angezeigt wird.
  4. Beim Entlassen der Tastatur wird clientCount dekrementiert. In diesem Fall wird es auf 1 zurückgesetzt.

Einige der gängigen Tastaturen haben bestimmte Schlüsselwörter in ihren Klassennamen:

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

Überprüfen Sie in ActivityManager.RunningServiceInfo die oben genannten Muster in ClassNames. Außerdem ist clientPackage = android von ActivityManager.RunningServiceInfo angegeben , dass die Tastatur an das System gebunden ist.

Die oben genannten Informationen können kombiniert werden, um herauszufinden, ob eine Softtastatur sichtbar ist.

Satishkumar
quelle
0

Wie Sie vielleicht wissen, ist die Android-Softwaretastatur nur sichtbar, wenn ein mögliches Tippereignis vorliegt. Mit anderen Worten, die Tastatur wird nur sichtbar, wenn EditText fokussiert ist. Das bedeutet, dass Sie mithilfe von OnFocusChangeListener feststellen können , ob die Tastatur sichtbar ist oder nicht .

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

Jetzt können Sie die Variable isKeyBoardVisible an einer beliebigen Stelle in der Klasse verwenden, um festzustellen , ob die Tastatur geöffnet ist oder nicht. Es hat gut für mich funktioniert.

Hinweis: Dieser Vorgang funktioniert nicht, wenn die Tastatur programmgesteuert mit InputMethodManager geöffnet wird, da dadurch OnFocusChangeListener nicht aufgerufen wird.

Sharath Bhargav
quelle
Nicht wirklich ein Hack, hat in einem verschachtelten Fragment-Fall nicht funktioniert. Kann ich nicht zu Aktivitäten sagen, da ich das noch nicht ausprobiert habe.
Antroid
0

Ich habe die Antwort in Kotlin konvertiert und hoffe, dass dies für Kotlin-Benutzer hilfreich ist.

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

            }
        }
    }
}
Emre Akcan
quelle
0

Es funktioniert mit adjustNothing-Aktivitätsflag und Lebenszyklusereignisse werden verwendet. Auch bei Kotlin:

/**
 * 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)
    }
}

Nützliche Methode, um die Ansicht immer über der Tastatur zu behalten

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

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

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

Wo 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
}
Andrey Tuzov
quelle
-1

Ich habe dies wie folgt gemacht, aber es ist nur relevant, wenn Ihr Ziel darin besteht, die Tastatur zu schließen / zu öffnen.

Beispiel schließen: (Überprüfen, ob die Tastatur bereits geschlossen ist, falls nicht - Schließen)

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);
                    }
                });
Itay verklagt
quelle
Die Frage bezog sich darauf, herauszufinden, ob die Tastatur
angezeigt
-1

a verwendet möglicherweise:

@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) {

}
Milan Jurkulak
quelle
Dies wird nur für Hardware-Tastatur funktionieren, nicht für die Software-One
Anthonymonori
-1

Ich habe Probe geschrieben .

Dieses Repository kann dabei helfen, den Tastaturstatus zu erkennen, ohne davon auszugehen, dass "Tastatur mehr als X Teil des Bildschirms sein sollte".

Аксенов Владимир
quelle
-1

Wenn Sie apis für AndroidR in Ihrer App unterstützen, können Sie die folgende Methode verwenden.

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

Hinweis: Dies ist nur für AndroidR verfügbar und darunter muss die Android-Version einer anderen Antwort folgen, sonst werde ich sie dafür aktualisieren.

Pranav Patel
quelle