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


当前回答

你可以试试这个,对我来说很管用:

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

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

其他回答

我发现@Reuben_Scratton的方法与@Yogesh的方法的组合似乎效果最好。将他们的方法结合起来会产生如下结果:

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

你可以通过使用活动的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);
    }
}

我的答案基本上与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
                    }
                }
            });

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

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

检查系统上正在运行的服务 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,表示键盘绑定到系统。

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

当在viewpager中改变片段的方向时,我很难保持键盘状态。我不知道为什么,但它似乎是不稳定的,行为不同于标准的活动。

在这种情况下,要保持键盘状态,首先你应该添加android:windowSoftInputMode = "stateUnchanged"到你的AndroidManifest.xml。不过,您可能会注意到,这实际上并没有解决整个问题——如果在方向改变之前打开了键盘,那么键盘就不会为我打开。在其他所有情况下,这种行为似乎都是正确的。

然后,我们需要实现这里提到的解决方案之一。 我发现的最干净的一个是George Maisuradze的——使用hideSoftInputFromWindow中的布尔回调:

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

我将这个值存储在我的Fragment的onSaveInstanceState方法中,并在onCreate中检索它。然后,我强制显示键盘在onCreateView,如果它有一个值为真(它返回真,如果键盘是可见的,实际上隐藏它之前的片段销毁)。