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


当前回答

一些改进,以避免在高密度设备上错误地检测软键盘的可见性:

Threshold of height difference should be defined as 128 dp, not 128 pixels. Refer to Google design doc about Metrics and Grid, 48 dp is comfortable size for touch object and 32 dp is minimum for buttons. Generic soft keyboard should include 4 rows of key buttons, so minimum keyboard height should be: 32 dp * 4 = 128 dp, that means threshold size should transfer to pixels by multiply device density. For xxxhdpi devices (density 4), the soft keyboard height threshold should be 128 * 4 = 512 pixels. Height difference between root view and its visible area: root view height - status bar height - visible frame height = root view bottom - visible frame bottom, since status bar height equal to the top of root view visible frame. 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; }

其他回答

就计算机而言,这是永远的问题,但这个问题仍然令人难以置信地相关!

所以我把上面的答案结合起来,做了一些改进……

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

对我有用:)

注意: 如果你注意到DefaultKeyboardDP不适合你的设备播放的值,并发表评论,让每个人都知道应该是什么值…最终我们将得到适合所有设备的正确值!

要了解更多细节,请查看Cyborg上的实现

这个想法是,如果你需要隐藏你的键盘,同时检查软输入状态,使用以下解决方案:

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

如果在隐藏之前显示键盘,则此方法返回true。

试试这个:

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

这个解决方案可能会重新打开键盘,但它是有效的。

InputMethodManager inputManager = ( (InputMethodManager) this.getSystemService(Context.INPUT_METHOD_SERVICE) );

private boolean isKeyboardShowing() {

    boolean isKeyboardShowing = inputManager.hideSoftInputFromWindow(irrelevantView.getWindowToken(), 0);
    if (isKeyboardShowing) {
        inputManager.showSoftInput(this.getCurrentFocus(), 0);
    }
    return isKeyboardShowing;
}

一些改进,以避免在高密度设备上错误地检测软键盘的可见性:

Threshold of height difference should be defined as 128 dp, not 128 pixels. Refer to Google design doc about Metrics and Grid, 48 dp is comfortable size for touch object and 32 dp is minimum for buttons. Generic soft keyboard should include 4 rows of key buttons, so minimum keyboard height should be: 32 dp * 4 = 128 dp, that means threshold size should transfer to pixels by multiply device density. For xxxhdpi devices (density 4), the soft keyboard height threshold should be 128 * 4 = 512 pixels. Height difference between root view and its visible area: root view height - status bar height - visible frame height = root view bottom - visible frame bottom, since status bar height equal to the top of root view visible frame. 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; }