我需要做一件非常简单的事情-找出软件键盘是否显示。这在Android中可行吗?
当前回答
我知道这是一篇老文章,但我认为这是我所知道的最简单的方法,我的测试设备是Nexus 5。我还没有在其他设备上尝试过。希望其他人会分享他们的方法,如果他们发现我的代码不好:)
public static boolean isKeyboardShown(Context context, View view) {
if (context == null || view == null) {
return false;
}
InputMethodManager imm = (InputMethodManager) context
.getSystemService(Context.INPUT_METHOD_SERVICE);
return imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
imm。hideSoftInputFromWindow返回布尔值。
谢谢,
其他回答
2012年1月25日新增答案
写了下面的答案后,有人告诉我ViewTreeObserver和其他api的存在,这些api从版本1开始就潜伏在SDK中。
而不是需要一个自定义的布局类型,一个更简单的解决方案是给你的活动的根视图一个已知的ID,比如@+ ID /activityRoot,钩子一个GlobalLayoutListener到ViewTreeObserver,并从那里计算你的活动的视图根和窗口大小之间的大小差:
final View activityRootView = findViewById(R.id.activityRoot);
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
int heightDiff = activityRootView.getRootView().getHeight() - activityRootView.getHeight();
if (heightDiff > dpToPx(this, 200)) { // if more than 200 dp, it's probably a keyboard...
// ... do something here
}
}
});
使用一个实用程序,如:
public static float dpToPx(Context context, float valueInDp) {
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, valueInDp, metrics);
}
简单!
注意: 你的应用程序必须在Android Manifest中设置这个标志Android:windowSoftInputMode=" adjuststresize "否则上述解决方案将无法工作。
原来的答案
是的,这是可能的,但它比应该的要难得多。
如果我需要关心键盘何时出现和消失(这是相当经常的),那么我所做的是自定义我的顶级布局类为一个覆盖onMeasure()。基本逻辑是,如果布局发现自己填充的面积明显小于窗口的总面积,那么可能显示了软键盘。
import android.app.Activity;
import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.widget.LinearLayout;
/*
* LinearLayoutThatDetectsSoftKeyboard - a variant of LinearLayout that can detect when
* the soft keyboard is shown and hidden (something Android can't tell you, weirdly).
*/
public class LinearLayoutThatDetectsSoftKeyboard extends LinearLayout {
public LinearLayoutThatDetectsSoftKeyboard(Context context, AttributeSet attrs) {
super(context, attrs);
}
public interface Listener {
public void onSoftKeyboardShown(boolean isShowing);
}
private Listener listener;
public void setListener(Listener listener) {
this.listener = listener;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int height = MeasureSpec.getSize(heightMeasureSpec);
Activity activity = (Activity)getContext();
Rect rect = new Rect();
activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);
int statusBarHeight = rect.top;
int screenHeight = activity.getWindowManager().getDefaultDisplay().getHeight();
int diff = (screenHeight - statusBarHeight) - height;
if (listener != null) {
listener.onSoftKeyboardShown(diff>128); // assume all soft keyboards are at least 128 pixels high
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
然后在活动课上…
public class MyActivity extends Activity implements LinearLayoutThatDetectsSoftKeyboard.Listener {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
LinearLayoutThatDetectsSoftKeyboard mainLayout = (LinearLayoutThatDetectsSoftKeyboard)findViewById(R.id.main);
mainLayout.setListener(this);
...
}
@Override
public void onSoftKeyboardShown(boolean isShowing) {
// do whatever you need to do here
}
...
}
不要编写任何硬代码。最好的方法是,你必须调整你的视图,而Get Focus on EditText与键盘显示。 您可以使用下面的代码将活动上的resize属性添加到清单文件中。
android: windowSoftInputMode = adjustResize”
这是我的解决方案,它很有效。而不是寻找像素大小,只是检查内容视图的高度是否改变:
// 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();
}
这段代码工作得很好
根视图使用这个类:
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) {
}
});
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文件