Frage

Ich brauche eine sehr einfache Sache zu tun - herauszufinden, ob die Software-Tastatur angezeigt wird. Ist das möglich in Android?

War es hilfreich?

Lösung

NEW ANTWORT hinzugefügt 25. Januar 2012

Da die unten Antwort schreiben, clued mir jemand in der Existenz von ViewTreeObserver und Freunde, APIs, die in der SDK seit Version 1 lauern wurden.

als vielmehr einen benutzerdefinierten Layout-Typen erfordern, eine viel einfachere Lösung ist Ihre Aktivität der Wurzel eine bekannte ID anzeigen zu geben, sagt @+id/activityRoot, einen GlobalLayoutListener in die ViewTreeObserver Haken und von dort berechnet die Größe diff zwischen Ihrer Tätigkeit Sicht Wurzel und der Fenstergröße:

final View activityRootView = findViewById(R.id.activityRoot);
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {
        int heightDiff = activityRootView.getRootView().getHeight() - activityRootView.getHeight();
        if (heightDiff > dpToPx(this, 200)) { // if more than 200 dp, it's probably a keyboard...
            // ... do something here
        }
     }
});

Mit einem Dienstprogramm wie:

public static float dpToPx(Context context, float valueInDp) {
    DisplayMetrics metrics = context.getResources().getDisplayMetrics();
    return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, valueInDp, metrics);
}

Easy!

Hinweis: Ihre Anwendung muss diesen Flag im Android Manifest gesetzt android:windowSoftInputMode="adjustResize" sonst obige Lösung wird nicht funktionieren.

ORIGINAL ANTWORT

Ja, es ist möglich, aber es ist viel schwieriger, als es sein sollte.

Wenn ich über, wenn die Tastatur erscheint und verschwindet zu kümmern (was recht oft ist) dann, was ich tue, ist meine Top-Level-Layout-Klasse in eine anpassen, die onMeasure() außer Kraft setzt. Die grundlegende Logik ist, dass, wenn das Layout selbst deutlich weniger als die Gesamtfläche des Fensters Füllung findet, dann eine Soft-Tastatur wahrscheinlich angezeigt wird.

import android.app.Activity;
import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.widget.LinearLayout;

/*
 * LinearLayoutThatDetectsSoftKeyboard - a variant of LinearLayout that can detect when 
 * the soft keyboard is shown and hidden (something Android can't tell you, weirdly). 
 */

public class LinearLayoutThatDetectsSoftKeyboard extends LinearLayout {

    public LinearLayoutThatDetectsSoftKeyboard(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public interface Listener {
        public void onSoftKeyboardShown(boolean isShowing);
    }
    private Listener listener;
    public void setListener(Listener listener) {
        this.listener = listener;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int height = MeasureSpec.getSize(heightMeasureSpec);
        Activity activity = (Activity)getContext();
        Rect rect = new Rect();
        activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);
        int statusBarHeight = rect.top;
        int screenHeight = activity.getWindowManager().getDefaultDisplay().getHeight();
        int diff = (screenHeight - statusBarHeight) - height;
        if (listener != null) {
            listener.onSoftKeyboardShown(diff>128); // assume all soft keyboards are at least 128 pixels high
        }
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);       
    }

    }

Dann in Ihrer Aktivitätsklasse ...

public class MyActivity extends Activity implements LinearLayoutThatDetectsSoftKeyboard.Listener {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ...
        LinearLayoutThatDetectsSoftKeyboard mainLayout = (LinearLayoutThatDetectsSoftKeyboard)findViewById(R.id.main);
        mainLayout.setListener(this);
        ...
    }


    @Override
    public void onSoftKeyboardShown(boolean isShowing) {
        // do whatever you need to do here
    }

    ...
}

Andere Tipps

So hoffentlich hilft das jemand aus.

Die neue Antwort, dass Reuben Scratton gab, ist großartig und sehr effizient, aber es ist wirklich nur funktioniert, wenn Sie Ihre windowSoftInputMode auf adjustResize gesetzt. Wenn Sie es auf adjustPan gesetzt, ist es noch nicht möglich zu erkennen, ob die Tastatur sichtbar ist sein Codeausschnitt verwenden. Zum Umgehen dieses habe ich diese kleine Änderung an den Code oben.

final View activityRootView = findViewById(R.id.activityRoot);
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
    Rect r = new Rect();
    //r will be populated with the coordinates of your view that area still visible.
    activityRootView.getWindowVisibleDisplayFrame(r);

    int heightDiff = activityRootView.getRootView().getHeight() - (r.bottom - r.top);
    if (heightDiff > 100) { // if more than 100 pixels, its probably a keyboard...
        ... do something here
    }
 }
}); 

Es war für immer in Bezug auf Computer, aber diese Frage ist nach wie vor unglaublich relevant!

So habe ich die oben genannten Antworten genommen und kombiniert und verfeinert sie ein wenig ...

public interface OnKeyboardVisibilityListener {


    void onVisibilityChanged(boolean visible);
}

public final void setKeyboardListener(final OnKeyboardVisibilityListener listener) {
    final View activityRootView = ((ViewGroup) getActivity().findViewById(android.R.id.content)).getChildAt(0);

    activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {

        private boolean wasOpened;

        private final int DefaultKeyboardDP = 100;

        // From @nathanielwolf answer...  Lollipop includes button bar in the root. Add height of button bar (48dp) to maxDiff
        private final int EstimatedKeyboardDP = DefaultKeyboardDP + (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ? 48 : 0);

        private final Rect r = new Rect();

        @Override
        public void onGlobalLayout() {
            // Convert the dp to pixels.
            int estimatedKeyboardHeight = (int) TypedValue
                    .applyDimension(TypedValue.COMPLEX_UNIT_DIP, EstimatedKeyboardDP, activityRootView.getResources().getDisplayMetrics());

            // Conclude whether the keyboard is shown or not.
            activityRootView.getWindowVisibleDisplayFrame(r);
            int heightDiff = activityRootView.getRootView().getHeight() - (r.bottom - r.top);
            boolean isShown = heightDiff >= estimatedKeyboardHeight;

            if (isShown == wasOpened) {
                Log.d("Keyboard state", "Ignoring global layout change...");
                return;
            }

            wasOpened = isShown;
            listener.onVisibilityChanged(isShown);
        }
    });
}

Arbeiten für mich:)

Hinweis: Wenn Sie feststellen, dass die DefaultKeyboardDP passt nicht Ihr Gerät Spiel mit dem Wert und schreiben Sie einen Kommentar für alle zu wissen, was der Wert sein sollte ... irgendwann werden wir den richtigen Wert erhalten alle Geräte passen!

Für weitere Informationen Besuche die Umsetzung auf Cyborg

Sorry für die späte Antwort, aber ich eine kleine Hilfsklasse geschaffen hatte, mit anmelde Zuhörern und anderen nützlichen Dingen zum Öffnen / Schließen-Ereignisse zu behandeln, kann jemand finden würde es hilfreich:

import android.graphics.Rect;
import android.view.View;
import android.view.ViewTreeObserver;

import java.util.LinkedList;
import java.util.List;

public class SoftKeyboardStateWatcher implements ViewTreeObserver.OnGlobalLayoutListener {

    public interface SoftKeyboardStateListener {
        void onSoftKeyboardOpened(int keyboardHeightInPx);
        void onSoftKeyboardClosed();
    }

    private final List<SoftKeyboardStateListener> listeners = new LinkedList<SoftKeyboardStateListener>();
    private final View activityRootView;
    private int        lastSoftKeyboardHeightInPx;
    private boolean    isSoftKeyboardOpened;

    public SoftKeyboardStateWatcher(View activityRootView) {
        this(activityRootView, false);
    }

    public SoftKeyboardStateWatcher(View activityRootView, boolean isSoftKeyboardOpened) {
        this.activityRootView     = activityRootView;
        this.isSoftKeyboardOpened = isSoftKeyboardOpened;
        activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(this);
    }

    @Override
    public void onGlobalLayout() {
        final Rect r = new Rect();
        //r will be populated with the coordinates of your view that area still visible.
        activityRootView.getWindowVisibleDisplayFrame(r);

        final int heightDiff = activityRootView.getRootView().getHeight() - (r.bottom - r.top);
        if (!isSoftKeyboardOpened && heightDiff > 100) { // if more than 100 pixels, its probably a keyboard...
            isSoftKeyboardOpened = true;
            notifyOnSoftKeyboardOpened(heightDiff);
        } else if (isSoftKeyboardOpened && heightDiff < 100) {
            isSoftKeyboardOpened = false;
            notifyOnSoftKeyboardClosed();
        }
    }

    public void setIsSoftKeyboardOpened(boolean isSoftKeyboardOpened) {
        this.isSoftKeyboardOpened = isSoftKeyboardOpened;
    }

    public boolean isSoftKeyboardOpened() {
        return isSoftKeyboardOpened;
    }

    /**
     * Default value is zero {@code 0}.
     *
     * @return last saved keyboard height in px
     */
    public int getLastSoftKeyboardHeightInPx() {
        return lastSoftKeyboardHeightInPx;
    }

    public void addSoftKeyboardStateListener(SoftKeyboardStateListener listener) {
        listeners.add(listener);
    }

    public void removeSoftKeyboardStateListener(SoftKeyboardStateListener listener) {
        listeners.remove(listener);
    }

    private void notifyOnSoftKeyboardOpened(int keyboardHeightInPx) {
        this.lastSoftKeyboardHeightInPx = keyboardHeightInPx;

        for (SoftKeyboardStateListener listener : listeners) {
            if (listener != null) {
                listener.onSoftKeyboardOpened(keyboardHeightInPx);
            }
        }
    }

    private void notifyOnSoftKeyboardClosed() {
        for (SoftKeyboardStateListener listener : listeners) {
            if (listener != null) {
                listener.onSoftKeyboardClosed();
            }
        }
    }
}

Anwendungsbeispiel:

final SoftKeyboardStateWatcher softKeyboardStateWatcher 
    = new SoftKeyboardStateWatcher(findViewById(R.id.activity_main_layout);

// Add listener
softKeyboardStateWatcher.addSoftKeyboardStateListener(...);
// then just handle callbacks

Einige Verbesserungen zu Unrecht zu vermeiden, die Sichtbarkeit der Soft-Tastatur auf hohe Dichte Geräte erkennen:

  1. Schwelle der Höhendifferenz sollte als definiert werden 128 dp , nicht 128 Pixel .
    Siehe Google Design doc über Metriken und Grid , 48 dp ist komfortable Größe für Touch-Objekt und 32 dp ist Minimum für Tasten. Generisches Soft-Tastatur sollte 4 Reihen von Tastenknöpfen umfassen, so Mindesttastaturhöhe sollte sein: dp 32 * 4 = 128 dp , daß Mittel Schwellengröße zu Pixeln, die durch mehrfach Vorrichtungsdichte übertragen sollte. Für xxxhdpi Vorrichtungen (Dichte 4) sollte das Soft-Tastatur sein Höhenschwelle 128 * 4 = 512 Pixel.

  2. Höhendifferenz zwischen Stammansicht und seiner sichtbaren Fläche:
    Stammansicht Höhe - Statusleiste Höhe - sichtbare Rahmenhöhe = root Sicht Unter - sichtbarer Rahmenboden, da Statusleiste Höhe der Spitze der Wurzelansicht sichtbarer Rahmen entspricht.

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

habe ich eine wenig Zeit, um dies herauszufinden ... Ich lief es einige CastExceptions, aber herausgefunden, dass man Ihnen Linearlayout im layout.xml mit dem Namen der Klasse ersetzen kann.

Wie folgt aus:

<?xml version="1.0" encoding="UTF-8"?>
<LinearLayout android:layout_width="fill_parent" android:layout_height="fill_parent"
    xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/llMaster">

<com.ourshoppingnote.RelativeLayoutThatDetectsSoftKeyboard android:background="@drawable/metal_background"
    android:layout_width="fill_parent" android:layout_height="fill_parent"
    android:id="@+id/rlMaster" >
    <LinearLayout android:layout_width="fill_parent"
        android:layout_height="1dip" android:background="@drawable/line"></LinearLayout>

          ....

</com.ourshoppingnote.RelativeLayoutThatDetectsSoftKeyboard>    


</LinearLayout>

So können Sie nicht in irgendwelche Besetzungsausgaben führen.

... und wenn Sie nicht wünschen, auf jeder Seite zu tun, empfehle ich, dass Sie „Master in Android“ zu verwenden. Siehe den Link hier: http://jnastase.alner.net/archive /2011/01/08/ldquomaster-pagesrdquo-in-android.aspx

Überprüfen Sie die Höhe der Elemente ist nicht zuverlässig, weil einige Tastaturen wie WifiKeyboard Nullhöhe haben.

Sie können stattdessen den Rückruf Ergebnis showSoftInput () und hideSoftInput () verwenden, um den Status der Tastatur zu überprüfen. Ausführliche Angaben und Beispielcode auf

https: // rogerkeays .com / how-to-Check-wenn-der-Software-Tastatur-ist-dargestellt-in-android

Die Idee ist, wenn Sie Ihre Tastatur verstecken und Soft-Input-Zustand in der gleichen Zeit zu überprüfen, verwenden Sie die folgende Lösung:

public boolean hideSoftInput() {
    InputMethodManager imm = (InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE);
    return imm.hideSoftInputFromWindow(mViewPager.getWindowToken(), 0);
}

Diese Methode gibt true, wenn Tastatur vor Versteck gezeigt wurde.

Sie können mit Aktivität des decorView Softkeyboard Haut beobachten.

public final class SoftKeyboardUtil {
    public static final String TAG = "SoftKeyboardUtil";
    public static void observeSoftKeyBoard(Activity activity , final OnSoftKeyBoardHideListener listener){
        final View decorView = activity.getWindow().getDecorView();
        decorView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                Rect rect = new Rect();
                decorView.getWindowVisibleDisplayFrame(rect);
                int displayHight = rect.bottom - rect.top;
                int hight = decorView.getHeight();
                boolean hide = (double)displayHight / hight > 0.8 ;
                if(Log.isLoggable(TAG, Log.DEBUG)){
                    Log.d(TAG ,"DecorView display hight = "+displayHight);
                    Log.d(TAG ,"DecorView hight = "+ hight);
                    Log.d(TAG, "softkeyboard visible = " + !hide);
                }

                listener.onSoftKeyBoardVisible(!hide);

            }
        });
    }



    public interface OnSoftKeyBoardHideListener{
        void onSoftKeyBoardVisible(boolean visible);
    }
}

Statt den Unterschied von der Annahme Codierung ich so etwas wie dies tat, als ich die Menüoptionen in meiner Anwendung hatte DINT.

final View root= findViewById(R.id.myrootview); 
root.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
@Override
    public void onGlobalLayout() {
        int heightDiff = root.getRootView().getHeight() - root.getHeight();

        Rect rectgle= new Rect();
        Window window= getWindow();
        window.getDecorView().getWindowVisibleDisplayFrame(rectgle);
        int contentViewTop=                     
          window.findViewById(Window.ID_ANDROID_CONTENT).getTop();
        if(heightDiff <= contentViewTop){
            //Soft KeyBoard Hidden
        }else{
            //Soft KeyBoard Shown
        }
     }
});

Ich fand, dass eine Kombination von @ Reuben_Scratton Methode zusammen mit @ Yogesh Methode scheint am besten zu funktionieren. ihre Methoden Die Kombination von in etwa so ergeben würde:

final View activityRootView = findViewById(R.id.activityRoot);
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
  @Override
  public void onGlobalLayout() {
    if (getResources().getConfiguration().keyboardHidden == Configuration.KEYBOARDHIDDEN_NO) { // Check if keyboard is not hidden
       // ... do something here
    }
  }
});

Es gibt auch Lösung mit System Einsätzen, aber es funktioniert nur mit API >= 21 (Android L). Angenommen, Sie haben BottomNavigationView, das Kind von LinearLayout ist und Sie müssen es verstecken, wenn Tastatur angezeigt wird:

> LinearLayout
  > ContentView
  > BottomNavigationView

Alles, was Sie tun müssen, ist LinearLayout in einer solchen Art und Weise zu erweitern:

public class KeyboardAwareLinearLayout extends LinearLayout {
    public KeyboardAwareLinearLayout(Context context) {
        super(context);
    }

    public KeyboardAwareLinearLayout(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public KeyboardAwareLinearLayout(Context context,
                                     @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    public KeyboardAwareLinearLayout(Context context, AttributeSet attrs,
                                     int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    @Override
    public WindowInsets onApplyWindowInsets(WindowInsets insets) {
        int childCount = getChildCount();
        for (int index = 0; index < childCount; index++) {
            View view = getChildAt(index);
            if (view instanceof BottomNavigationView) {
                int bottom = insets.getSystemWindowInsetBottom();
                if (bottom >= ViewUtils.dpToPx(200)) {
                    // keyboard is shown
                    view.setVisibility(GONE);
                } else {
                    // keyboard is hidden
                    view.setVisibility(VISIBLE);
                }
            }
        }
        return insets;
    }
}

Die Idee ist, dass, wenn Tastatur angezeigt wird, System-Einsätze mit ziemlich großem .bottom Wert geändert werden.

Es gibt eine versteckte Methode kann helfen, für diese, InputMethodManager.getInputMethodWindowVisibleHeight. Aber ich weiß nicht, warum es versteckt.

import android.content.Context
import android.os.Handler
import android.view.inputmethod.InputMethodManager

class SoftKeyboardStateWatcher(private val ctx: Context) {
  companion object {
    private const val DELAY = 10L
  }

  private val handler = Handler()
  private var isSoftKeyboardOpened: Boolean = false

  private val height: Int
    get() {
      val imm = ctx.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
      val method = imm.javaClass.getMethod("getInputMethodWindowVisibleHeight")
      method.isAccessible = true
      return method.invoke(imm) as Int
    }

  private val task: Runnable by lazy {
    Runnable {
      start()
      if (!isSoftKeyboardOpened && height > 0) {
        isSoftKeyboardOpened = true
        notifyOnSoftKeyboardOpened(height)
      } else if (isSoftKeyboardOpened && height == 0) {
        isSoftKeyboardOpened = false
        notifyOnSoftKeyboardClosed()
      }
    }
  }

  var listener: SoftKeyboardStateListener? = null

  interface SoftKeyboardStateListener {
    fun onSoftKeyboardOpened(keyboardHeightInPx: Int)
    fun onSoftKeyboardClosed()
  }

  fun start() {
    handler.postDelayed(task, DELAY)
  }

  fun stop() {
    handler.postDelayed({
      if (!isSoftKeyboardOpened) handler.removeCallbacks(task)
    }, DELAY * 10)
  }

  private fun notifyOnSoftKeyboardOpened(keyboardHeightInPx: Int) {
    listener?.onSoftKeyboardOpened(keyboardHeightInPx)
  }

  private fun notifyOnSoftKeyboardClosed() {
    listener?.onSoftKeyboardClosed()
  }
}

Keine dieser Lösungen wird für Lollipop arbeiten wie. In Lollipop activityRootView.getRootView().getHeight() enthält die Höhe der Knopfleiste, während die Ansicht Messung nicht. Ich habe die beste / einfachste Lösung oben auf der Arbeit mit Lollipop angepasst.

    final View activityRootView = findViewById(R.id.activityRoot);
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
  @Override
  public void onGlobalLayout() {
    Rect r = new Rect();
    //r will be populated with the coordinates of your view that area still visible.
    activityRootView.getWindowVisibleDisplayFrame(r);

    int heightDiff = activityRootView.getRootView().getHeight() - (r.bottom - r.top);
    Resources res = getResources();
    // The status bar is 25dp, use 50dp for assurance
    float maxDiff =
        TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 50, res.getDisplayMetrics());

    //Lollipop includes button bar in the root. Add height of button bar (48dp) to maxDiff
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
      float buttonBarHeight =
          TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 48, res.getDisplayMetrics());
      maxDiff += buttonBarHeight;
    }
    if (heightDiff > maxDiff) { // if more than 100 pixels, its probably a keyboard...
      ...do something here
    }
  }
});

habe ich eine leichte Variante von Reuban Antwort, die unter bestimmten Umständen mehr hilfreich erwiesen, vor allem mit hochauflösenden Geräten.

final View activityRootView = findViewById(android.R.id.content);
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
                }
            }
        });

Es war für immer in Bezug auf den Computer, aber diese Frage ist immer noch unglaublich relevant! So habe ich die oben genannten Antworten genommen und kombiniert und verfeinert sie ein wenig ...

public interface OnKeyboardVisibilityListener {
    void onVisibilityChanged(boolean visible);
}

public final void setKeyboardListener(final OnKeyboardVisibilityListener listener) {
    final View activityRootView = ((ViewGroup) getActivity().findViewById(android.R.id.content)).getChildAt(0);
    activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {

        private boolean wasOpened;

    private final Rect r = new Rect();

        @Override
        public void onGlobalLayout() {
            activityRootView.getWindowVisibleDisplayFrame(r);

            int heightDiff = activityRootView.getRootView().getHeight() - (r.bottom - r.top);
            boolean isOpen = heightDiff > 100;
            if (isOpen == wasOpened) {
                logDebug("Ignoring global layout change...");
                return;
            }

            wasOpened = isOpen;
            listener.onVisibilityChanged(isOpen);
        }
    });
}

Es funktioniert für mich.

Meine Antwort ist im Grunde die gleiche wie Kachi Antwort, aber ich wickelte es in eine schöne Hilfsklasse den Weg, um aufzuräumen es während meiner App verwendet wird.

import android.app.Activity;
import android.app.Fragment;
import android.graphics.Rect;
import android.view.View;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;

/**
 * Detects Keyboard Status changes and fires events only once for each change
 */
public class KeyboardStatusDetector {
    KeyboardVisibilityListener visibilityListener;

    boolean keyboardVisible = false;

    public void registerFragment(Fragment f) {
        registerView(f.getView());
    }

    public void registerActivity(Activity a) {
        registerView(a.getWindow().getDecorView().findViewById(android.R.id.content));
    }

    public KeyboardStatusDetector registerView(final View v) {
        v.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                Rect r = new Rect();
                v.getWindowVisibleDisplayFrame(r);

                int heightDiff = v.getRootView().getHeight() - (r.bottom - r.top);
                if (heightDiff > 100) { // if more than 100 pixels, its probably a keyboard...
                    /** Check this variable to debounce layout events */
                    if(!keyboardVisible) {
                        keyboardVisible = true;
                        if(visibilityListener != null) visibilityListener.onVisibilityChanged(true);
                    }
                } else {
                    if(keyboardVisible) {
                        keyboardVisible = false;
                        if(visibilityListener != null) visibilityListener.onVisibilityChanged(false);
                    }
                }
            }
        });

        return this;
    }

    public KeyboardStatusDetector setVisibilityListener(KeyboardVisibilityListener listener) {
        visibilityListener = listener;
        return this;
    }

    public static interface KeyboardVisibilityListener {
        public void onVisibilityChanged(boolean keyboardVisible);
    }
}

Sie können diese verwenden Tastatur zu erkennen ändert überall im ganzen App wie folgt aus:

    new KeyboardStatusDetector()
            .registerFragment(fragment)  //register to a fragment 
            .registerActivity(activity)  //or register to an activity
            .registerView(view)          //or register to a view
            .setVisibilityListener(new KeyboardVisibilityListener() {
                @Override
                public void onVisibilityChanged(boolean keyboardVisible) {
                    if(keyboardVisible) {
                       //Do stuff for keyboard visible
                    }else {
                       //Do stuff for keyboard hidden
                    }
                }
            });

Hinweis: Verwenden Sie nur eine der „Register“ Anrufe. Sie arbeiten alle gleich sind und dort nur für Bequemlichkeit

Sie können dies versuchen, große Arbeit für mich:

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

if (imm.isAcceptingText()) {
    //Software Keyboard was shown..
} else {
    //Software Keyboard was not shown..
}

Ich habe gerade einen Fehler festgestellt, während die meisten der oben genannten Lösungen, die unter Verwendung vorschlagen Zugabe eine feste Zahl.

S4 ist eine hohe dpi, die in der Navigationsleiste des Höhe geführt wird 100px so mein app denkt, dass die Tastatur ist die ganze Zeit offen.

So mit allen neuen hochauflösenden Telefone ich glaube freigegeben wird, um eine hartcodierte Wert verwendet, ist keine gute Idee, für langfristig.

Ein besserer Ansatz, dass ich nach einigen Tests auf verschiedenen Bildschirmen und Geräten zu finden war Prozentsatz zu verwenden. Holen Sie sich den Unterschied zwischen decorView und ur App-Inhalte und danach überprüfen, was der Prozentsatz dieser Differenz ist. Aus den Statistiken, dass ich habe, die meisten Navigationsleisten (unabhängig von der Größe, Auflösung etc ..) zwischen 3% bis 5% des Bildschirms nehmen. Wo, wie, wenn die Tastatur geöffnet wurde zwischen 47% bis 55% des Bildschirms einnimmt.

Als Schlussfolgerung war meine Lösung zu überprüfen, ob der Unterschied mehr als 10%, dann nehme ich an seine eine Tastatur geöffnet.

I hatte Schwierigkeiten Tastatur Zustand aufrechterhalten wird, wenn innerhalb eines viewpager Orientierung von Fragmenten zu verändern. Ich bin mir nicht sicher, warum, aber es scheint nur wackelig zu sein und wirkt anders als eine Standard-Aktivität.

Um Tastaturstatus in diesem Fall zu erhalten, sollten Sie zunächst android:windowSoftInputMode = "stateUnchanged" zu Ihrem AndroidManifest.xml hinzufügen. Sie können feststellen, obwohl, dass dies tatsächlich nicht das gesamte Problem lösen - die Tastatur für mich nicht geöffnet, wenn sie vorher vor Orientierungsänderung geöffnet wurde. In allen anderen Fällen schien das Verhalten korrekt zu sein.

Dann müssen wir eine der Lösungen hier erwähnt implementieren. Die sauberste, den ich fand, war George Maisuradze's - verwenden Sie den boolean Rückruf von hideSoftInputFromWindow:

InputMethodManager imm = (InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE);
return imm.hideSoftInputFromWindow(mViewPager.getWindowToken(), 0);

ich diesen Wert in meinem Fragmente der onSaveInstanceState Methode gespeichert und abgerufen es onCreate. Dann habe ich mit Gewalt die Tastatur in onCreateView zeigte, wenn es einen Wert von true hatte (es gibt true zurück, wenn die Tastatur sichtbar ist, bevor es tatsächlich vor dem Fragment Zerstörung versteckt).

Versuchen Sie diese:

final View activityRootView = getWindow().getDecorView().getRootView();
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {
        Rect r = new Rect();
        //r will be populated with the coordinates of your view that area still visible.
        activityRootView.getWindowVisibleDisplayFrame(r);

        int heightDiff = activityRootView.getRootView().getHeight() - (r.bottom - r.top);
        if (heightDiff < activityRootView.getRootView().getHeight() / 4 ) { // if more than 100 pixels, its probably a keyboard...
             // ... do something here ... \\
        }
    }
});

Hier ist meine Lösung, und es funktioniert. Statt für Pixel suchen Größe nur prüfen, ob die Höhe des Inhalts Ansicht geändert hat oder nicht:

// Scroll to the latest comment whenever the keyboard is shown
commentsContent.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {

        private int oldHeight;

        @Override
        public void onGlobalLayout() {
            int newHeight = commentsContent.getMeasuredHeight();
            if (newHeight < oldHeight) {
                // Check for the keyboard showing in case the height difference
                // is a result of orientation change
                if (isSoftKeyboardShowing(CommentsActivity.this)) {
                    // Keyboard is showing so scroll to the latest comment
                    scrollToLatestComment();
                }
            }
            oldHeight = newHeight;
        }

    });


public static boolean isSoftKeyboardShowing(Activity activity) {
    InputMethodManager inputMethodManager = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
    return inputMethodManager.isActive();
}

Sie keinen harten Code machen. Der beste Weg ist, müssen Sie Ihre Ansichten Größe ändern, während auf Get Fokus auf EditText mit Keybord Show. Sie können auf der Aktivität in Manifest-Datei mit folgendem Code, um dieses Hinzufügen Resize-Eigenschaft tun.

android:windowSoftInputMode="adjustResize"

Es gibt eine direkte Methode, um diese heraus zu finden. Und es erfordert keine Änderungen am Layout.
So funktioniert es in immersiver Vollbild-Modus, auch.
Der Trick ist, dass Sie versuchen sie zu verstecken oder die Soft-Tastatur zeigen, und das Ergebnis dieses Versuchs erfassen.
Keine Panik, bedeutet dies nicht wirklich ein- oder ausblenden die Tastatur. Wir bitten nur für den Staat.
Bleiben up-to-date, können Sie einfach den Vorgang wiederholen, z.B. alle 200 Millisekunden, mit einem Handler.
Sie finden eine Implementierung hier: https://stackoverflow.com/a/27567074/2525452

Ich denke, diese Methode wird Ihnen helfen, herauszufinden, ob Tastatur sichtbar ist oder nicht.

 public Boolean isSoftKeyBoardVisible(){
    InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);

    if (imm.isAcceptingText()) {
        Log.d(TAG,"Software Keyboard was shown");
        return true;
    } else {
        Log.d(TAG,"Software Keyboard was not shown");
        return false;
    }

}

Reuben Scratton die neue Antwort (Berechnung der HeightDiff int heightDiff = activityRootView.getRootView().getHeight() - activityRootView.getHeight();) wird nicht funktionieren in Tätigkeit, wenn Sie setzen die durchscheinend Statusleiste Modus.

Wenn Sie durchscheinend Statusleiste verwenden, activityRootView.getHeight() wird nie die Soft-Tastatur sichtbar Wetter ändern. es wird die Höhe der Aktivität und Statusleiste immer zurück.

Zum Beispiel Nexus 4, Android 5.0.1, Satz android:windowTranslucentStatus auf true, wird es 1184 Rückkehr für immer, auch die ime opend hat. Wenn Sie Satz android:windowTranslucentStatus auf false, wird es richtig Höhe zurückkehren, wenn ime unsichtbar, es zurückgeben 1134 (nicht die Statusleiste) .close den ime, wird es vielleicht zurückkehren 5xx (abhängig von ime Höhe)

Ich weiß nicht, Wetter dies ein Fehler ist, ich habe versucht auf 4.4.4 und 5.0.1, das Ergebnis ist das gleiche.

Also, bis jetzt, die zweiten am vereinbarten Antwort, Kachi-Lösung ist der sicherste Weg, um die Höhe von ime Calcute. Hier ist eine Kopie:

final View activityRootView = findViewById(R.id.activityRoot);
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new        OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
Rect r = new Rect();
//r will be populated with the coordinates of your view that area still visible.
activityRootView.getWindowVisibleDisplayFrame(r);

int heightDiff = activityRootView.getRootView().getHeight() - (r.bottom - r.top);
if (heightDiff > 100) { // if more than 100 pixels, its probably a keyboard...
    ... do something here
    }
 }
}); 

Eine Methode, die braucht keine LayoutListener

In meinem Fall würde Ich mag den Zustand der Tastatur speichern, bevor mein Fragment zu ersetzen. Ich nenne die Methode hideSoftInputFromWindow von onSaveInstanceState, die die Tastatur schließt und gibt mir, ob die Tastatur sichtbar war oder nicht.

Diese Methode ist einfach, aber kann den Zustand der Tastatur ändern.

Ich weiß, dass dies eine alte Post, aber ich denke, das ist der einfachste Ansatz ist, dass ich weiß, und mein Testgerät ist Nexus 5. Ich habe es nicht in anderen Geräten ausprobiert. Hoffnung, dass andere ihren Ansatz teilen, wenn sie meinen Code finden, ist nicht gut:)

public static boolean isKeyboardShown(Context context, View view) {
        if (context == null || view == null) {
            return false;
        }
        InputMethodManager imm = (InputMethodManager) context
                .getSystemService(Context.INPUT_METHOD_SERVICE);
        return imm.hideSoftInputFromWindow(view.getWindowToken(), 0); 
}

imm.hideSoftInputFromWindow kehrt boolean.

Danke,

if (keyopen())
{
                InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
                imm.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY,0);            
}

Die obige Funktion ist, was ich überprüfen verwenden, wenn eine Tastatur sichtbar ist. Wenn ja, dann schließe ich es.

Im Folgenden zeigt die beiden Methoden erforderlich.

Zunächst definieren die bearbeitbar Fensterhöhe in onCreate.

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

//  add to onCreate method
    Rect rectgle= new Rect();
    Window window= getWindow();
    window.getDecorView().getWindowVisibleDisplayFrame(rectgle);
    sheight= rectgle.bottom;
//

} 

Dann fügen Sie eine boolean Methode, die die Fensterhöhe in diesem Fall bekommt. Wenn es nicht das Original übereinstimmt (vorausgesetzt, Sie ändern sich nicht auf dem Weg ...), dann ist die Tastatur geöffnet ist.

public boolean keyopen()
{
    Rect rectgle= new Rect();
    Window window= getWindow();
    window.getDecorView().getWindowVisibleDisplayFrame(rectgle);
    int curheight= rectgle.bottom;

    if (curheight!=sheight)
    {
        return true;
    }
    else
    {
        return false;
    }
}

Frotz!

Ich weiß, wie genau Sie feststellen können, ob Tastatur versteckt ist oder nicht.

public int getStatusBarHeight() {
    int result = 0;
    int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
    if (resourceId > 0) {
        result = getResources().getDimensionPixelSize(resourceId);
    }
    return result;
}

public int getNavigationBarHeight() {
    int result = 0;
    int resourceId = getResources().getIdentifier("navigation_bar_height", "dimen", "android");
    if (resourceId > 0) {
        result = getResources().getDimensionPixelSize(resourceId);
    }
    return result;
}

public boolean isKeyboardHidden() {
    int delta = mRootView.getRootView().getHeight() - mRootView.getHeight() - getNavigationBarHeight() - getStatusBarHeight()
            - getSupportActionBar().getHeight();
    return delta <= 0;
}

Dies funktioniert für Tabletten. Wenn navigationbar horizontal dargestellt.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top