Jak sprawdzić widoczność klawiatury programowej w Androidzie?

Muszę zrobić bardzo prostą rzecz - dowiedzieć się, czy klawiatura programowa jest pokazana. Czy jest to możliwe w Androidzie?

Author: Ironman, 2010-01-27

30 answers

Nowa odpowiedź dodano Styczeń 25th 2012

Od czasu napisania poniższej odpowiedzi, ktoś przykuł mnie do istnienia ViewTreeObserver i friends, API, które czają się w SDK od wersji 1.

Zamiast wymagać niestandardowego typu układu, znacznie prostszym rozwiązaniem jest nadanie widokowi głównemu Twojej aktywności znanego identyfikatora, powiedzmy @+id/activityRoot, zaczepić GlobalLayoutListener do serwera ViewTreeObserver i stamtąd obliczyć różnicę wielkości między Twoim główny widok aktywności i rozmiar okna:

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

Używając narzędzia takiego jak:

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

Uwaga: Twoja aplikacja musi ustawić tę flagę w manifeście Androida android:windowSoftInputMode="adjustResize" w przeciwnym razie powyższe rozwiązanie nie będzie działać.

ORYGINALNA ODPOWIEDŹ

Tak, to możliwe, ale to o wiele trudniejsze niż powinno być.

Jeśli muszę dbać o to, kiedy pojawi się i zniknie klawiatura (co jest dość często), to to, co robię, to dostosowywanie mojego najwyższego poziomu Klasa układu w jedną, która nadpisuje onMeasure(). Podstawową logiką jest to, że jeśli układ znajdzie się wypełniający znacznie mniej niż całkowita powierzchnia okna, to prawdopodobnie wyświetla się miękka klawiatura.

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

    }

Potem na zajęciach z aktywności...

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
    }

    ...
}
 629
Author: Reuben Scratton,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-20 10:12:19

Mam nadzieję, że to komuś pomoże.

Nowa odpowiedź, którą dał Reuben Scratton jest świetna i naprawdę skuteczna, ale naprawdę działa tylko wtedy, gdy ustawisz windowSoftInputMode na adjustResize. Jeśli ustawisz go na adjustPan, nadal nie jest możliwe wykrycie, czy klawiatura jest widoczna za pomocą jego fragmentu kodu. Aby obejść ten problem, wprowadziłem małą modyfikację do powyższego kodu.

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
    }
 }
}); 
 290
Author: Kachi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-02 06:45:31

Przepraszam za późną odpowiedź, ale stworzyłem małą klasę pomocniczą do obsługi zdarzeń open/close z powiadomieniami słuchaczy i innymi przydatnymi rzeczami, może ktoś uzna to za pomocne:

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

Przykład użycia:

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

// Add listener
softKeyboardStateWatcher.addSoftKeyboardStateListener(...);
// then just handle callbacks
 51
Author: Artem Zinnatullin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-06 12:52:03

To było od zawsze w odniesieniu do komputera, ale to pytanie jest nadal niewiarygodnie istotne!

Więc wziąłem powyższe odpowiedzi i połączyłem je i nieco dopracowałem...
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);
        }
    });
}

U mnie działa:)

Uwaga: Jeśli zauważysz, że DefaultKeyboardDP nie pasuje do Twojego urządzenia, Zagraj z wartością i opublikuj komentarz, aby wszyscy wiedzieli, jaka powinna być wartość... ostatecznie otrzymamy poprawną wartość, aby pasowała do wszystkich urządzeń!

 47
Author: TacB0sS,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-25 08:28:25

Niektóre ulepszenia, aby uniknąć nieprawidłowego wykrywania widoczności miękkiej klawiatury na urządzeniach o dużej gęstości:

  1. Próg różnicy wysokości powinien być zdefiniowany jako 128 dp, a nie 128 pikseli.
    Zobacz Google design doc o metrykach i siatce, 48 dp jest wygodnym rozmiarem dla obiektu dotykowego, a 32 dp jest minimalnym rozmiarem dla przycisków. Ogólna miękka klawiatura powinna zawierać 4 rzędy klawiszy, więc minimalna wysokość klawiatury powinna wynosić: 32 dp * 4 = 128 dp , co oznacza, że wielkość progu powinna być przenoszona na piksele przez mnożenie gęstości urządzenia. Dla urządzeń xxxhdpi (gęstość 4) próg wysokości miękkiej klawiatury powinien wynosić 128 * 4 = 512 pikseli.

  2. Różnica wysokości między widokiem głównym a jego widocznym obszarem:
    widok root height-wysokość paska stanu-widoczna wysokość ramki = widok root bottom-widoczne dno ramki, ponieważ wysokość paska stanu jest równa górnej części widoku root view widoczna ramka.

    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;
    }
    
 30
Author: Orchard Cafe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-02 00:00:01

Wykorzystałem trochę czasu, żeby to rozgryźć... Uruchomiłem kilka CastExceptions, ale zorientowałem się, że możesz zastąpić LinearLayout w układzie.xml z nazwą klasy.

Tak:

<?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>

W ten sposób nie napotkasz żadnych problemów z obsadą.

... a jeśli nie chcesz tego robić na każdej stronie, polecam użycie "MasterPage w Androidzie". Zobacz link tutaj: http://jnastase.alner.net/archive/2011/01/08/ldquomaster-pagesrdquo-in-android.aspx

 8
Author: Janus Kamp Hansen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-07-09 07:39:14

Chodzi o to, że jeśli chcesz ukryć klawiaturę i jednocześnie sprawdzić stan miękkiego wejścia, użyj następującego rozwiązania:

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

Ta metoda zwraca true, jeśli klawiatura została pokazana przed ukryciem.

 5
Author: George Maisuradze,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-06 21:25:11

Sprawdzanie wysokości elementów nie jest wiarygodne, ponieważ niektóre klawiatury, takie jak WifiKeyboard, mają zerową wysokość.

Zamiast tego możesz użyć wyniku wywołania zwrotnego showSoftInput() i hideSoftInput (), aby sprawdzić status klawiatury. Pełne szczegóły i przykładowy kod na

Https://rogerkeays.com/how-to-check-if-the-software-keyboard-is-shown-in-android

 5
Author: Roger Keays,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-28 23:58:04

Zamiast zakładać kodowanie różnicy zrobiłem coś takiego, ponieważ miałem opcje menu w mojej aplikacji.

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
        }
     }
});
 4
Author: Santhosh Shettigar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-31 10:05:23

Odkryłem, że połączenie metody @ Reuben_Scratton wraz z metodą @ Yogesh wydaje się działać najlepiej. Połączenie ich metod daje coś takiego:

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
    }
  }
});
 3
Author: cbradley,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-31 21:44:16

Możesz obserwować ukrycie softkeyboard za pomocą activity ' s decorView.

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);
    }
}
 3
Author: Zebulon Li,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-23 08:40:30

Istnieje również rozwiązanie z wstawkami systemowymi, ale działa tylko z API >= 21 (Android L). Powiedzmy, że posiadasz BottomNavigationView, który jest potomkiem LinearLayout i musisz go ukryć, gdy pojawi się klawiatura:

> LinearLayout
  > ContentView
  > BottomNavigationView

Wystarczy rozszerzyć LinearLayout w taki sposób:

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

Chodzi o to, że gdy wyświetlana jest klawiatura, wkładki systemowe są zmieniane z dość dużą wartością .bottom.

 3
Author: nikis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-15 18:38:27

Żadne z tych rozwiązań nie będzie działać dla lizaka tak jak jest. W Lollipop activityRootView.getRootView().getHeight() zawiera wysokość paska przycisków, podczas gdy pomiar widoku nie. Przystosowałem najlepsze / najprostsze rozwiązanie powyżej do pracy z lizakiem.

    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
    }
  }
});
 2
Author: nathanielwolf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-04 08:21:12

Użyłem lekkiego wariantu odpowiedzi Reubana, który okazał się bardziej pomocny w pewnych okolicznościach, szczególnie w przypadku urządzeń o wysokiej rozdzielczości.

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
                }
            }
        });
 2
Author: PearsonArtPhoto,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-01 00:43:59

To było od zawsze w odniesieniu do komputera, ale to pytanie jest nadal niewiarygodnie istotne! Więc wziąłem powyższe odpowiedzi i połączyłem i udoskonaliłem je trochę...

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);
        }
    });
}
U mnie działa.
 2
Author: Roselyn Soffer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-16 09:16:20

Moja odpowiedź jest zasadniczo taka sama jak odpowiedź Kachi, ale owinąłem ją w miłą klasę pomocniczą, aby oczyścić sposób, w jaki jest używana w całej mojej aplikacji.

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

Możesz tego użyć do wykrywania zmian klawiatury w dowolnym miejscu w aplikacji, jak to:

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

Uwaga: używaj tylko jednego z wywołań "register". Wszystkie działają tak samo i są tam tylko dla wygody

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

Możesz tego spróbować, działa dla mnie świetnie:

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

if (imm.isAcceptingText()) {
    //Software Keyboard was shown..
} else {
    //Software Keyboard was not shown..
}
 1
Author: IRvanFauziE,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-16 00:12:53

Właśnie napotkałem błąd podczas korzystania z większości powyższych rozwiązań, które sugerują dodanie stałego numeru.

S4 is ma wysokie dpi, co spowodowało, że wysokość paska nawigacyjnego wynosi 100px, więc moja aplikacja myśli, że klawiatura jest otwarta cały czas.

Więc ze wszystkimi nowymi telefonami wysokiej rozdzielczości są wypuszczane wierzę, że używanie twardo zakodowanej wartości nie jest dobrym pomysłem na dłuższą metę.

Lepszym podejściem, które znalazłem po testach na różnych ekranach i urządzeniach było użycie procent. Uzyskaj różnicę między zawartością aplikacji decorView i UR, a następnie sprawdź, jaki jest procent tej różnicy. Z statystyk, które dostałem, większość paska nav (niezależnie od rozmiaru, rozdzielczości itp..) zajmie od 3% do 5% ekranu. Tam, gdzie klawiatura jest otwarta, zajmowało od 47% do 55% ekranu.

Jako wniosek moim rozwiązaniem było sprawdzenie, czy różnica jest większa niż 10%, to zakładam, że klawiatura jest otwarta.

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

Miałem problemy z utrzymaniem stanu klawiatury podczas zmiany orientacji fragmentów w viewpagerze. Nie jestem pewien dlaczego, ale to po prostu wydaje się być chwiejne i działa inaczej niż standardowa aktywność.

Aby zachować stan klawiatury w tym przypadku, najpierw należy dodać android:windowSoftInputMode = "stateUnchanged" do swojego AndroidManifest.xml. Możesz jednak zauważyć, że to nie rozwiązuje całego problemu-klawiatura nie otworzyła się dla mnie, jeśli była wcześniej otwarta przed zmianą orientacji. We wszystkich innych przypadkach zachowanie wydawało się poprawne.

Następnie musimy wdrożyć jedno z wymienionych tutaj rozwiązań. Najczystszym, jaki znalazłem, był George Maisuradze--użyj boolean callback z hideSoftInputFromWindow: {]}

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

Zapisałem tę wartość w metodzie onSaveInstanceState mojego fragmentu i pobrałem ją onCreate. Następnie siłą pokazałem klawiaturę w onCreateView, jeśli miała wartość true (zwraca true, jeśli klawiatura jest widoczna przed ukryciem jej przed zniszczeniem fragmentu).

 1
Author: Quantum Dot,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-21 00:13:50

Try this:

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 ... \\
        }
    }
});
 1
Author: Ofek Ashery,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-24 15:33:51

Istnieje ukryta metoda, która może w tym pomóc, InputMethodManager.getInputMethodWindowVisibleHeight. Ale nie wiem, dlaczego jest ukryty.

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()
  }
}
 1
Author: Kevin Du,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-22 04:30:43

Oto moje rozwiązanie i działa. Zamiast szukać rozmiaru piksela po prostu sprawdź, czy wysokość widoku zawartości się zmieniła, czy nie:

// 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();
}
 0
Author: Meanman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-03 16:04:46

Nie twarda szyfr. Najlepszym sposobem jest zmiana rozmiaru widoków podczas gdy NA Get Focus on EditText with keybord Show. Możesz to zrobić dodając właściwość zmiany rozmiaru aktywności do pliku manifestu za pomocą poniższego kodu.

android:windowSoftInputMode="adjustResize"

 0
Author: Rahul Mandaliya,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-14 22:57:44

Istnieje bezpośrednia metoda, aby to sprawdzić. I nie wymaga żadnych zmian układu.
Działa więc również w trybie pełnoekranowym.

Sztuczka polega na tym, że próbujesz ukryć lub pokazać miękką klawiaturę i uchwycić wynik tej próby.
Bez paniki, to tak naprawdę nie pokazuje ani nie ukrywa klawiatury. Pytamy tylko o stan.

Aby być na bieżąco, możesz po prostu powtórzyć operację, np. co 200 milisekund, używając funkcji obsługi.

Znajdziesz implementację tutaj: https://stackoverflow.com/a/27567074/2525452

 0
Author: fies,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 10:31:12

Myślę, że ta metoda pomoże Ci dowiedzieć się, czy Keyboard jest widoczny, czy nie.

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

}
 0
Author: John smith,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-01-27 10:38:25

Nowa odpowiedź Reubena Scrattona (Oblicz Wysokość int heightDiff = activityRootView.getRootView().getHeight() - activityRootView.getHeight();) nie będzie działać w aktywności, Jeśli ustawisz tryb półprzezroczystego paska stanu.

Jeśli używasz półprzezroczystego paska stanu, activityRootView.getHeight() nigdy nie zmieni pogody, widoczna jest miękka klawiatura. zawsze zwróci wysokość aktywności i pasek stanu.

Na przykład, Nexus 4, Android 5.0.1, ustaw android:windowTranslucentStatus na true, zwróci 1184 na zawsze, nawet ime mają opend. Jeśli ustawisz android:windowTranslucentStatus Na false, zwróci poprawnie wysokość, jeśli IME invisible, zwraca 1134 (nie zawiera paska stanu).Zamknij ime, może zwróci 5xx (zależy od wysokości ime)

Nie wiem pogoda to jest błąd, próbowałem na 4.4.4 i 5.0.1, wynik jest taki sam.

Więc, do tej pory, druga najbardziej uzgodniona odpowiedź, rozwiązanie Kachi będzie najbezpieczniejszym sposobem obliczenia wysokości ime. Oto Kopia:

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
    }
 }
}); 
 0
Author: Loyea,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-24 12:45:49

Metoda, która nie wymaga LayoutListener

W moim przypadku chciałbym zapisać stan klawiatury przed zastąpieniem mojego fragmentu. Wywołuję metodę hideSoftInputFromWindow z onSaveInstanceState, która zamyka klawiaturę i zwraca mi, czy klawiatura była widoczna, czy nie.

Ta metoda jest prosta, ale może zmienić stan klawiatury.

 0
Author: Gordak,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-26 08:24:37

Wiem, że to stary post, ale myślę, że jest to najprostsze podejście, które znam i moim urządzeniem TESTOWYM jest Nexus 5. Nie próbowałem tego w innych urządzeniach. Mam nadzieję, że inni podzielą się swoim podejściem, jeśli odkryją, że mój kod nie jest dobry:)]}

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 Zwraca wartość logiczną.

Dzięki,

 0
Author: Fran Ceriu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-20 08:17:42
if (keyopen())
{
                InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
                imm.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY,0);            
}

Powyższa funkcja służy do sprawdzania, czy klawiatura jest widoczna. Jeśli tak, to zamykam.

Poniżej przedstawiono dwie wymagane metody.

Najpierw zdefiniuj funkcjonalną wysokość okna w 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;
//

} 

Następnie dodaj metodę logiczną, która pobiera wysokość okna w danej instancji. Jeśli nie pasuje do oryginału (zakładając, że nie zmienisz go po drodze...) następnie klawiatura jest otwarta.

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!
 0
Author: Belboz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-11 18:58:22

Wiem, jak dokładnie można określić, czy klawiatura jest ukryta, czy nie.

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;
}
To działa na tablety. Gdy pasek nawigacyjny jest wyświetlany w poziomie.
 0
Author: Valentin Baryshev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-30 06:15:46