我有一个使用“adjustPan”作为其调整大小配置的活动,并且我需要计算键盘高度而不使用“adjustResize”,因为我需要将一些视图保留为全屏(这意味着它们应该保持在原来的位置,键盘应该隐藏它们),并将视图放置在键盘正上方。我们的应用程序有一个消息按钮,我通过单击按钮打开键盘。当发生这种情况时,我使用 OnGlobalLayoutListener 并使用“getWindowVisibleDisplayFrame”方法来获取键盘的高度。这是一些代码:
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 坐标设置为“bottomCooperative - view.getHeight()”。在软键盘应用程序的自动更正部分变得可见之前,这种方法一直有效。显然,“getWindowVisibleDisplayFrame”方法似乎没有添加视图的自动更正部分,或者当软键盘的自动更正部分显示时,不会调用“onGlobalLayout”方法,并且定位的视图保留在其下方,这使其半可见。我需要能够再次调整它的位置,那么我该怎么办?正确的做法是什么?任何建议都很有价值,谢谢。
这是我在任何活动中检测键盘高度的方法,这也适合凹口/切口高度(如果有的话)。
KeyboardHeightProvider.java
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
import android.os.Build;
import android.util.DisplayMetrics;
import android.util.Size;
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.view.WindowMetrics;
import android.widget.LinearLayout;
import android.widget.PopupWindow;
import androidx.annotation.NonNull;
import androidx.core.graphics.Insets;
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 final View decorView;
private Size displaySize;
private final LinearLayout popupView;
private final ViewTreeObserver.OnGlobalLayoutListener globalLayoutListener;
private final Rect insets = new Rect(0, 0, 0, 0);
public KeyboardHeightProvider(
Context context,
WindowManager windowManager,
View decorView,
KeyboardHeightListener listener
) {
super(context);
this.decorView = decorView;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
WindowMetrics windowMetrics = windowManager.getCurrentWindowMetrics();
Rect windowBounds = windowMetrics.getBounds();
displaySize = new Size(
windowBounds.width(),
windowBounds.height()
);
} else {
DisplayMetrics displayMetrics = new DisplayMetrics();
windowManager.getDefaultDisplay().getMetrics(displayMetrics);
displaySize = new Size(
displayMetrics.widthPixels,
displayMetrics.heightPixels
);
}
popupView = new LinearLayout(context);
popupView.setLayoutParams(
new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT
)
);
globalLayoutListener = () -> {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
WindowMetrics windowMetrics = windowManager.getCurrentWindowMetrics();
Rect windowBounds = windowMetrics.getBounds();
displaySize = new Size(
windowBounds.width(),
windowBounds.height()
);
} else {
DisplayMetrics displayMetrics = new DisplayMetrics();
windowManager.getDefaultDisplay().getMetrics(displayMetrics);
displaySize = new Size(
displayMetrics.widthPixels,
displayMetrics.heightPixels
);
}
int keyboardHeight = getKeyboardHeight();
boolean screenLandscape = displaySize.getWidth() > displaySize.getHeight();
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();
}
@NonNull
@Override
public WindowInsetsCompat onApplyWindowInsets(
@NonNull View v,
WindowInsetsCompat insets
) {
DisplayCutoutCompat cutoutCompat = insets.getDisplayCutout();
if (cutoutCompat != null) {
this.insets.set(
cutoutCompat.getSafeInsetLeft(),
cutoutCompat.getSafeInsetTop(),
cutoutCompat.getSafeInsetRight(),
cutoutCompat.getSafeInsetBottom()
);
} else {
Insets systemBarInsets = insets.getInsets(
WindowInsetsCompat.Type.systemBars()
);
this.insets.set(
systemBarInsets.left,
systemBarInsets.top,
systemBarInsets.right,
systemBarInsets.bottom
);
}
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 = displaySize.getHeight()
- (rect.bottom - rect.top)
- (insets.bottom - insets.top);
@SuppressLint({"InternalInsetResource", "DiscouragedApi"})
int resourceID = getContentView()
.getContext()
.getResources()
.getIdentifier(
"status_bar_height",
"dimen",
"android"
);
if (resourceID > 0) {
keyboardHeight -= getContentView()
.getContext()
.getResources()
.getDimensionPixelSize(resourceID);
}
if (keyboardHeight < 100) {
keyboardHeight = 0;
}
return keyboardHeight;
}
public interface KeyboardHeightListener {
void onKeyboardHeightChanged(int height, boolean isLandscape);
}
}
(非原创答案)
矩形 r = new 矩形();
View rootview = this.getWindow().getDecorView(); // 这 = 活动
rootview.getWindowVisibleDisplayFrame(r);
其结果是您的应用程序在屏幕上使用的空间量(即使活动未调整大小也有效)。显然剩余的屏幕空间将被键盘使用(如果它可见)
您可以访问原答案