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


当前回答

参考@TacB0sS的回答,我在Kotlin中开发了一个类。希望这对你有所帮助。如果需要改进,请告诉我。

class KeyboardVisibilityObserver(val layRootContainer: View?, val keyboardVisibilityListener: KeyboardVisibilityListener?) {
    var isKeyboardOpen = false
        private set

    private var keyBoardObserver = object : ViewTreeObserver.OnGlobalLayoutListener {

        private val DefaultKeyboardDP = 100

        // Lollipop includes button bar in the root. Add height of button bar (48dp) to maxDiff
        private val EstimatedKeyboardDP = DefaultKeyboardDP + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) 48 else 0

        private val r = Rect()

        override fun onGlobalLayout() {
            if (layRootContainer != null) {
                // Convert the dp to pixels.
                val estimatedKeyboardHeight = TypedValue
                        .applyDimension(TypedValue.COMPLEX_UNIT_DIP, EstimatedKeyboardDP.toFloat(), layRootContainer.resources.displayMetrics).toInt()

                // Conclude whether the keyboard is shown or not.
                layRootContainer.getWindowVisibleDisplayFrame(r)
                val heightDiff = layRootContainer.rootView.height - (r.bottom - r.top)
                val isShown = heightDiff >= estimatedKeyboardHeight

                if (isShown == isKeyboardOpen) {
                    //  Log.d("Keyboard state", "Ignoring global layout change...");
                    return
                }

                isKeyboardOpen = isShown

                keyboardVisibilityListener?.onKeyboardVisibilityChanged(isKeyboardOpen)
            }
        }
    }

    init {
        layRootContainer?.viewTreeObserver?.addOnGlobalLayoutListener(keyBoardObserver)
    }

    // call this in onDestroy
    fun removeObserver(){
        layRootContainer?.viewTreeObserver?.removeOnGlobalLayoutListener(keyBoardObserver)
    }

    interface KeyboardVisibilityListener {
        fun onKeyboardVisibilityChanged(isKeyboardOpen: Boolean)
    }
}

其他回答

if (keyopen())
{
                InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
                imm.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY,0);            
}

上面的函数是我用来检查键盘是否可见的。如果是,那我就关上。

下面显示了所需的两种方法。

首先,在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;
//

} 

然后,添加一个布尔方法来获取该实例的窗口高度。如果它与原来的不匹配(假设您没有在此过程中更改它……),那么键盘是打开的。

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 !

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

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

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

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

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上的实现

这是我的解决方案,它很有效。而不是寻找像素大小,只是检查内容视图的高度是否改变:

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

也许这对你有帮助:

InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);