我需要做一件非常简单的事情-找出软件键盘是否显示。这在Android中可行吗?
当前回答
检查元素的高度是不可靠的,因为一些键盘,如WifiKeyboard的高度为零。
相反,您可以使用showSoftInput()和hideSoftInput()的回调结果来检查键盘的状态。完整的细节和示例代码在
https://rogerkeays.com/how-to-check-if-the-software-keyboard-is-shown-in-android
其他回答
在了解了不同分辨率的一些问题后,我决定使用相对大小。正如我所注意到的,可见状态和隐藏状态之间的差异约为30%。所以我决定用0.3代替128 PX。
我添加了这个类监听器来通知任何变化。
这是我的版本
import android.app.*;
import android.graphics.*;
import android.view.*;
public class SoftKeyboardState {
public static final int HIDDEN = 0, VISIBLE = 1;
private OnKeyboardStateChangedListener listener;
private View decorView;
public SoftKeyboardState(Activity activity) {
this.decorView = activity.findViewById(android.R.id.content);
initKeyboardListener();
}
private void initKeyboardListener() {
decorView.getViewTreeObserver().addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener(){
private final Rect windowVisibleDisplayFrame = new Rect();
private int lastVisibleDecorViewHeight;
@Override
public void onGlobalLayout() {
decorView.getWindowVisibleDisplayFrame(windowVisibleDisplayFrame);
final int visibleDecorViewHeight = windowVisibleDisplayFrame.height();
if (lastVisibleDecorViewHeight != 0) {
if ((lastVisibleDecorViewHeight > visibleDecorViewHeight) && (lastVisibleDecorViewHeight / visibleDecorViewHeight >= 0.3f)) {
// visible
if (listener != null)listener.onKeyboardStateChanged(VISIBLE);
} else if ((lastVisibleDecorViewHeight < visibleDecorViewHeight) && (visibleDecorViewHeight / lastVisibleDecorViewHeight >= 0.3f)) {
// hidden
if (listener != null)listener.onKeyboardStateChanged(HIDDEN);
}
}
lastVisibleDecorViewHeight = visibleDecorViewHeight;
}
});
}
public void setOnKeyboardStateChangedListener(OnKeyboardStateChangedListener listener) {
this.listener = listener;
}
public interface OnKeyboardStateChangedListener {
public void onKeyboardStateChanged(int state);
}
}
我的答案基本上与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
}
}
});
注意:只使用一个“寄存器”调用。它们都是一样的,只是为了方便
我发现@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
}
}
});
有一种直接的方法可以找出答案。而且,它不需要任何布局更改。 所以,它也可以在沉浸式全屏模式下工作。 诀窍在于,您尝试隐藏或显示软键盘,并捕获尝试的结果。 没有恐慌,这并不真正显示或隐藏键盘。我们只要求状态。 为了保持最新,您可以简单地重复操作,例如,每200毫秒,使用处理器。 您可以在这里找到一个实现:https://stackoverflow.com/a/27567074/2525452
Reuben Scratton和Kachi提供的解决方案似乎依赖于设备的像素密度,如果你有一个高密度的设备,即使按下键盘,高度差也可能超过100。围绕这一点的工作将是看到初始高度差(键盘向下),然后与当前的差异进行比较。
boolean isOpened = false;
int firstHeightDiff = -1;
public void setListenerToRootView(){
final View activityRootView = getActivity().getWindow().getDecorView().findViewById(android.R.id.content);
Rect r = new Rect();
activityRootView.getWindowVisibleDisplayFrame(r);
firstHeightDiff = activityRootView.getRootView().getHeight() - (r.bottom - r.top);
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
if (isAdded()) {
Rect r = new Rect();
activityRootView.getWindowVisibleDisplayFrame(r);
int heightDiff = activityRootView.getRootView().getHeight() - (r.bottom - r.top);
isOpened = heightDiff>firstHeightDiff+100;
if (isAdded())
if(isOpened) {
//TODO stuff for when it is up
} else {
//TODO stuf for when it is down
}
}
}
});
}
推荐文章
- 警告:API ' variable . getjavacompile()'已过时,已被' variable . getjavacompileprovider()'取代
- 安装APK时出现错误
- 碎片中的onCreateOptionsMenu
- TextView粗体通过XML文件?
- 如何使线性布局的孩子之间的空间?
- DSL元素android.dataBinding。enabled'已过时,已被'android.buildFeatures.dataBinding'取代
- ConstraintLayout:以编程方式更改约束
- PANIC: AVD系统路径损坏。检查ANDROID_SDK_ROOT值
- 如何生成字符串类型的buildConfigField
- Recyclerview不调用onCreateViewHolder
- Android API 21工具栏填充
- Android L中不支持操作栏导航模式
- 如何在TextView中添加一个子弹符号?
- PreferenceManager getDefaultSharedPreferences在Android Q中已弃用
- 在Android Studio中创建aar文件