Android 使用键盘的自动更正部分获取软键盘高度
我有一个活动使用“adjustPan”作为其调整大小配置,我需要在不使用“adjustResize”的情况下计算键盘高度,因为我需要将一些视图保持为全屏(这意味着它们应该保持在原来的位置,键盘应该隐藏它们),并将视图定位在键盘正上方。我们的应用程序有一个消息按钮,我通过点击按钮打开键盘。发生这种情况时,我使用OnGlobalLayoutListener并使用“getWindowVisibleDisplayFrame”方法来获取键盘的高度。下面是一些代码:Android 使用键盘的自动更正部分获取软键盘高度,android,android-layout,android-softkeyboard,Android,Android Layout,Android Softkeyboard,我有一个活动使用“adjustPan”作为其调整大小配置,我需要在不使用“adjustResize”的情况下计算键盘高度,因为我需要将一些视图保持为全屏(这意味着它们应该保持在原来的位置,键盘应该隐藏它们),并将视图定位在键盘正上方。我们的应用程序有一个消息按钮,我通过点击按钮打开键盘。发生这种情况时,我使用OnGlobalLayoutListener并使用“getWindowVisibleDisplayFrame”方法来获取键盘的高度。下面是一些代码: private void message
private void message()
{
InputMethodManager methodManager =
(InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
if (methodManager != null && !isKeyboardOpen)
{
methodManager.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
if (bottomCoordinate == 0)
{
RelativeLayout layout = findViewById(getFullScreenContainerId());
layout.getViewTreeObserver().addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener()
{
@Override
public void onGlobalLayout()
{
layout.getViewTreeObserver().removeOnGlobalLayoutListener(this);
Rect r = new Rect();
layout.getWindowVisibleDisplayFrame(r);
bottomCoordinate = r.bottom - r.top;
translateMessageView(bottomCoordinate);
}
});
}
else
translateMessageView(bottomCoordinate);
isKeyboardOpen = true;
}
}
“translateMessageView”基本上将视图的Y坐标设置为“bottomCoordinate-view.getHeight()”。直到软键盘应用程序的“自动更正”部分可见为止,这一切都很正常。显然,“getWindowVisibleDisplayFrame”方法似乎没有添加视图的自动更正部分,或者当软键盘的自动更正部分出现时,不会调用“onGlobalLayout”方法,并且定位的视图保持在其下方,使其半可见。我需要能够再次调整它的位置,所以我应该怎么做?正确的方法是什么?任何建议都很有价值,谢谢。(不是原始答案)
Rect r=新的Rect()
视图根视图=this.getWindow().getDecorView();//这=活动
rootview.getWindowVisibleDisplayFrame(r)
其结果是应用程序在屏幕上使用的空间量(即使活动未调整大小也可以工作)。很明显,剩余的屏幕空间将由键盘使用(如果其可见)
在这里找到id:
您可以访问原始答案
以下是我在任何活动中检测键盘高度的方法,如果有缺口/切口高度,这也符合要求
KeyboardHeightProvider.java
import android.content.Context;
import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
import android.util.DisplayMetrics;
import android.view.DisplayCutout;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.WindowInsets;
import android.view.WindowManager;
import android.widget.LinearLayout;
import android.widget.PopupWindow;
import androidx.core.view.DisplayCutoutCompat;
import androidx.core.view.OnApplyWindowInsetsListener;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
public class KeyboardHeightProvider extends PopupWindow implements OnApplyWindowInsetsListener {
private View decorView;
private DisplayMetrics metrics;
private LinearLayout popupView;
private ViewTreeObserver.OnGlobalLayoutListener globalLayoutListener;
private Rect insets = new Rect(0, 0, 0, 0);
public KeyboardHeightProvider(Context context, WindowManager windowManager, View decorView, KeyboardHeightListener listener) {
super(context);
this.decorView = decorView;
metrics = new DisplayMetrics();
windowManager.getDefaultDisplay().getMetrics(metrics);
popupView = new LinearLayout(context);
popupView.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
globalLayoutListener = () -> {
windowManager.getDefaultDisplay().getMetrics(metrics);
int keyboardHeight = getKeyboardHeight();
boolean screenLandscape = metrics.widthPixels > metrics.heightPixels;
if (listener != null) {
listener.onKeyboardHeightChanged(keyboardHeight, screenLandscape);
}
};
setContentView(popupView);
setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE | WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED);
setWidth(0);
setHeight(ViewGroup.LayoutParams.MATCH_PARENT);
setBackgroundDrawable(new ColorDrawable(0));
ViewCompat.setOnApplyWindowInsetsListener(popupView, this);
}
public void start() {
popupView.getViewTreeObserver().addOnGlobalLayoutListener(globalLayoutListener);
decorView.post(() -> showAtLocation(decorView, Gravity.NO_GRAVITY, 0, 0));
}
@Override
public void dismiss() {
popupView.getViewTreeObserver().removeOnGlobalLayoutListener(globalLayoutListener);
super.dismiss();
}
@Override
public WindowInsetsCompat onApplyWindowInsets(View v, WindowInsetsCompat insets) {
DisplayCutoutCompat cutoutCompat = insets.getDisplayCutout();
if (cutoutCompat != null) {
this.insets.set(cutoutCompat.getSafeInsetLeft(), cutoutCompat.getSafeInsetTop(), cutoutCompat.getSafeInsetRight(), cutoutCompat.getSafeInsetBottom());
} else {
this.insets.set(insets.getSystemWindowInsetLeft(), insets.getSystemWindowInsetTop(), insets.getSystemWindowInsetRight(), insets.getSystemWindowInsetBottom());
}
if (decorView != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
WindowInsets rootWindowInsets = decorView.getRootWindowInsets();
if (rootWindowInsets != null) {
DisplayCutout displayCutout = rootWindowInsets.getDisplayCutout();
if (displayCutout != null) {
this.insets.set(displayCutout.getSafeInsetLeft(), displayCutout.getSafeInsetTop(), displayCutout.getSafeInsetRight(), displayCutout.getSafeInsetBottom());
}
}
}
return insets;
}
public int getKeyboardHeight() {
Rect rect = new Rect();
popupView.getWindowVisibleDisplayFrame(rect);
int keyboardHeight = metrics.heightPixels - (rect.bottom - rect.top) - (insets.bottom - insets.top);
int resourceID = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceID > 0) {
keyboardHeight -= context.getResources().getDimensionPixelSize(resourceID);
}
if (keyboardHeight < 100) {
keyboardHeight = 0;
}
return keyboardHeight;
}
public interface KeyboardHeightListener {
void onKeyboardHeightChanged(int height, boolean isLandscape);
}
}
onCreate
中添加行:
keyboardHeightProvider = new KeyboardHeightProvider(this, getWindowManager(), getWindow().getDecorView(), this);
keyboardHeightProvider.start();
keyboardHeightProvider.dismiss();
onResume
中添加以下行:
keyboardHeightProvider = new KeyboardHeightProvider(this, getWindowManager(), getWindow().getDecorView(), this);
keyboardHeightProvider.start();
keyboardHeightProvider.dismiss();
onPause
中添加行:
keyboardHeightProvider = new KeyboardHeightProvider(this, getWindowManager(), getWindow().getDecorView(), this);
keyboardHeightProvider.start();
keyboardHeightProvider.dismiss();
on键盘高度已更改
@Override
public void onKeyboardHeightChanged(int height, boolean isLandscape) {
//This will be called anytime the keyboard height has changed.
boolean keyboardOpen = height > 0;
//do what you want with Keyboard Height
}
我使用几乎完全相同的方法,只使用创建为“match\u parent,match\u parent”的相对布局,因为我需要移动视图。问题是这个计算不包含软键盘的自动更正部分,我也在尝试获取它的高度。你找到解决方案了吗?@Pierre Umm,是的。在使用
EditText
上的TextWatcher
检测到击键后,我在一个Handler.post()
调用中再次获得了可见帧,该调用目前为止似乎仍在工作。但是大约6个月后我发现,这就是为什么我忘记回答我自己的问题。啊,那么当文本发生变化并且额外的一位弹出时,它不会改变隐藏视图的高度,从而部分掩盖了您的输入?@Pierre不完全是这样,onGlobalLayout
不会被调用,而是getWindowVisibleDisplayFrame(r)的值
更改,因此我根据文本更改后的结果移动视图。我只是尝试了一下,然后在显示键盘时调用“onKeyboardHeightChanged”,我想在运行时获得键盘高度time@famfamfam您可以添加键盘高度getter方法。将DisplayMetrics
作为私有局部变量移到顶部。将windowManager.getDefaultDisplay().getMetrics(metrics)
移动到popupView=new…
之前。将所有行从Rect Rect=…
移动到if(keyboardHeight<100){…}
进入getter方法,返回int keyboardHeight
@fam我编辑了这篇文章。谢谢,我尝试了你的代码,我能问一个问题吗,我想在像ios一样启动应用程序时获得键盘高度,安卓版也可以吗?@fam不,必须先构建布局,然后才能测量键盘高度。你只需重新考虑何时以及为什么需要键盘高度。如果要设置视图高度或其他内容,可以在回调函数中进行设置