我需要做一件非常简单的事情-找出软件键盘是否显示。这在Android中可行吗?


当前回答

这些解决方案都不适用于棒棒糖。在Lollipop activityRootView.getRootView(). getheight()包含按钮栏的高度,而测量视图则不包含。我已经采用了上面最好/最简单的解决方案来处理棒棒糖。

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

其他回答

Reuben Scratton的新答案(计算HeightDiff int HeightDiff = activityRootView.getRootView().getHeight() - activityRootView.getHeight();)如果您设置半透明状态栏模式,将无法在活动中工作。

如果你使用半透明状态栏,activityRootView.getHeight()将永远不会改变软键盘是否可见。它将始终返回活动和状态栏的高度。

例如,Nexus 4, Android 5.0.1,将Android:windowTranslucentStatus设置为true,它将永远返回1184,即使ime已经打开。如果你设置android:windowTranslucentStatus为false,它将正确返回高度,如果ime不可见,它将返回1134(不包括状态栏)。关闭ime,它可能会返回5xx(取决于ime的高度)

我不知道这是否是一个bug,我已经尝试了4.4.4和5.0.1,结果是一样的。

所以,到目前为止,第二个最被认可的答案,Kachi的解决方案将是最安全的方法来计算ime的高度。以下是一份复印件:

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

这里有一个工作区,以了解软键盘是否可见。

检查系统上正在运行的服务 ActivityManager.getRunningServices (max_count_of_services); 从返回的ActivityManager。运行ningserviceinfo实例,检查软键盘服务的clientCount值。 前面提到的clientCount将在每次显示软键盘时递增。例如,如果clientCount为 一开始是1,显示键盘时是2。 在键盘撤销时,clientCount递减。在本例中,它重置为1。

一些流行的键盘在它们的classname中有特定的关键字:

Google AOSP = IME
Swype = IME
Swiftkey = KeyboardService
Fleksy = keyboard
Adaptxt = IME (KPTAdaptxtIME)
Smart = Keyboard (SmartKeyboard)

从ActivityManager。RunningServiceInfo,在ClassNames中检查上述模式。同时,ActivityManager。RunningServiceInfo的clientPackage=android,表示键盘绑定到系统。

可以将上述信息进行严格的组合,以判断软键盘是否可见。

InputMethodManager有关于软键盘的信息。你从一个活动中获得它:

((InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE))

你可以摆弄一下,看看它能告诉你什么。你可以用它来显示或隐藏软输入…

我的答案基本上与Kachi的答案相同,但我将它包装到一个很好的helper类中,以清理它在整个应用程序中的使用方式。

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

你可以使用它来检测整个应用程序中的键盘变化,如下所示:

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

注意:只使用一个“寄存器”调用。它们都是一样的,只是为了方便

试试这个:

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