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


当前回答

这段代码工作得很好

根视图使用这个类:

public class KeyboardConstraintLayout extends ConstraintLayout {

private KeyboardListener keyboardListener;
private EditText targetEditText;
private int minKeyboardHeight;
private boolean isShow;

public KeyboardConstraintLayout(Context context) {
    super(context);
    minKeyboardHeight = getResources().getDimensionPixelSize(R.dimen.keyboard_min_height);
}

public KeyboardConstraintLayout(Context context, AttributeSet attrs) {
    super(context, attrs);
    minKeyboardHeight = getResources().getDimensionPixelSize(R.dimen.keyboard_min_height);
}

public KeyboardConstraintLayout(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    minKeyboardHeight = getResources().getDimensionPixelSize(R.dimen.keyboard_min_height);
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    if (!isInEditMode()) {
        Activity activity = (Activity) getContext();
        @SuppressLint("DrawAllocation")
        Rect rect = new Rect();
        getWindowVisibleDisplayFrame(rect);

        int statusBarHeight = rect.top;
        int keyboardHeight = activity.getWindowManager().getDefaultDisplay().getHeight() - (rect.bottom - rect.top) - statusBarHeight;

        if (keyboardListener != null && targetEditText != null && targetEditText.isFocused()) {
            if (keyboardHeight > minKeyboardHeight) {
                if (!isShow) {
                    isShow = true;
                    keyboardListener.onKeyboardVisibility(true);
                }
            }else {
                if (isShow) {
                    isShow = false;
                    keyboardListener.onKeyboardVisibility(false);
                }
            }
        }
    }
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}

public boolean isShowKeyboard() {
    return isShow;
}

public void setKeyboardListener(EditText targetEditText, KeyboardListener keyboardListener) {
    this.targetEditText = targetEditText;
    this.keyboardListener = keyboardListener;
}

public interface KeyboardListener {
    void onKeyboardVisibility (boolean isVisible);
}

}

在activity或fragment中设置键盘监听器:

    rootLayout.setKeyboardListener(targetEditText, new KeyboardConstraintLayout.KeyboardListener() {
    @Override
    public void onKeyboardVisibility(boolean isVisible) {

    }
});

其他回答

一个不需要LayoutListener的方法

在我的情况下,我想在替换我的片段之前保存键盘的状态。我调用方法hideSoftInputFromWindow from onSaveInstanceState,它会关闭键盘并返回键盘是否可见。

这个方法很简单,但可能会改变键盘的状态。

也有解决方案与系统嵌入,但它只适用于API >= 21 (Android L)。说你有BottomNavigationView,这是线性布局的孩子,你需要隐藏它时,键盘显示:

> LinearLayout
  > ContentView
  > BottomNavigationView

你所需要做的就是以这样的方式扩展LinearLayout:

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

这个想法是,当键盘显示时,系统insets被改变为相当大的.bottom值。

当在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,如果它有一个值为真(它返回真,如果键盘是可见的,实际上隐藏它之前的片段销毁)。

而不是假设差异编码,我做了这样的事情,因为我在我的应用程序中有菜单选项。

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

你可以使用InputMethodManager。isActive方法,如果键盘可见则返回true:

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

你也可以看到键盘在一个特定的视图中是否处于活动状态:

    imm.isActive(View v);