通过键盘的自动更正部分获取软键盘高度

问题描述 投票:0回答:2

我有一个使用“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”方法,并且定位的视图保留在其下方,这使其半可见。我需要能够再次调整它的位置,那么我该怎么办?正确的做法是什么?任何建议都很有价值,谢谢。

android android-layout android-softkeyboard
2个回答
5
投票

这是我在任何活动中检测键盘高度的方法,这也适合凹口/切口高度(如果有的话)。

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);
    }
}

0
投票

(非原创答案)

矩形 r = new 矩形();

View rootview = this.getWindow().getDecorView(); // 这 = 活动

rootview.getWindowVisibleDisplayFrame(r);

其结果是您的应用程序在屏幕上使用的空间量(即使活动未调整大小也有效)。显然剩余的屏幕空间将被键盘使用(如果它可见)

在这里找到ID:https://github.com/freshplanet/ANE-KeyboardSize/blob/master/android/src/com/freshplanet/ane/KeyboardSize/getKeyboardY.java

您可以访问原答案

获取软键盘尺寸

© www.soinside.com 2019 - 2024. All rights reserved.