我需要做一件非常简单的事情-找出软件键盘是否显示。这在Android中可行吗?
当前回答
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 !
其他回答
就计算机而言,这是永远的问题,但这个问题仍然令人难以置信地相关!
所以我把上面的答案结合起来,做了一些改进……
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上的实现
希望这能帮助到大家。
Reuben Scratton给出的新答案非常棒,而且非常有效,但它只在你将windowSoftInputMode设置为adjuststresize时才有效。如果你将它设置为adjustPan,使用他的代码片段仍然无法检测键盘是否可见。为了解决这个问题,我对上面的代码做了微小的修改。
final View activityRootView = findViewById(R.id.activityRoot);
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new 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.height();
if (heightDiff > 0.25*activityRootView.getRootView().getHeight()) { // if more than 25% of the screen, its probably a keyboard...
... do something here
}
}
});
哇,安卓极客们有好消息了。是时候向旧的方式说再见了。 首先我将添加官方发布说明来阅读和了解更多关于这些方法/类,然后我们将看到这些神奇的方法/类
注意:在这些类/方法发布之前,不要将它们添加到你的发布应用中
如何检查键盘可见性
val insets = ViewCompat.getRootWindowInsets(view)
val isKeyboardVisible = insets.isVisible(Type.ime())
其他用途很少
如何获取键盘的高度
val insets = ViewCompat.getRootWindowInsets(view)
val keyboardHeight = insets.getInsets(Type.ime()).bottom
如何显示/隐藏键盘
val controller = view.windowInsetsController
// Show the keyboard
controller.show(Type.ime())
// Hide the keyboard
controller.hide(Type.ime())
注意:WindowInsetsController是在API-30中添加的,所以要等到向后兼容类不可用。
如何听键盘隐藏/显示事件
ViewCompat.setOnApplyWindowInsetsListener(view) { v, insets ->
val isKeyboardVisible = insets.isVisible(Type.ime())
if (isKeyboardVisible) {
// Do it when keyboard is being shown
} else {
// Do it when keyboard is hidden
}
// Return the insets to keep going down this event to the view hierarchy
insets
}
我知道如何准确地确定键盘是否隐藏。
public int getStatusBarHeight() {
int result = 0;
int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
result = getResources().getDimensionPixelSize(resourceId);
}
return result;
}
public int getNavigationBarHeight() {
int result = 0;
int resourceId = getResources().getIdentifier("navigation_bar_height", "dimen", "android");
if (resourceId > 0) {
result = getResources().getDimensionPixelSize(resourceId);
}
return result;
}
public boolean isKeyboardHidden() {
int delta = mRootView.getRootView().getHeight() - mRootView.getHeight() - getNavigationBarHeight() - getStatusBarHeight()
- getSupportActionBar().getHeight();
return delta <= 0;
}
这适用于平板电脑。当导航栏水平显示时。
也有解决方案与系统嵌入,但它只适用于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值。
推荐文章
- 警告: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文件