Android ソフト キーボード ブロック インターフェイスの問題の概要

シーン1

問題の説明

通常、EditText入力ボックスをクリックするとソフトキーボードが表示されますが、キーボードがEditText表示をブロックします。

解決

AndroidManifestファイルでは、次のようにActivity が新しく構成されandroid:windowSoftInputMode、設定値はadjustPanまたは になります。adjustResize

<activity
    android:name="xxx"
    android:windowSoftInputMode="adjustPan"  />

AdjustPanとadjustResizeの違い

  • adjustPanこのパラメータを設定すると、インターフェイス全体が上に移動し、入力ボックスが表示されますが、インターフェイスのレイアウトは変更されません。
  • adjustResizeこのパラメータを設定すると、システムはソフト キーボードを削除した後にインターフェイス サイズを再計算し、入力ボックスを含むコンテンツの表示に使用するインターフェイス領域を減らします。



シーン2

問題の説明

ハイブリッド開発では、アプリケーションが非全画面モードで Web ページをロードしWebView、入力ボックスをクリックすると、ソフト キーボードがブロックされます。

解決

操作方法は上記と同様ですが、設定値のみサポートされておりadjustResize、設定はadjustPan無効となります。



シーン3

問題の説明

  • ハイブリッド開発では、アプリケーションは全画面モード (アプリケーションまたはアクティビティは全画面テーマ、イマーシブ ステータス バーImmersive Modeなどを使用)であり、WebView は Web ページを読み込み、入力ボックスをクリックし、ソフト キーボードはブロックされます。
  • android:windowSoftInputMode値をadjustPanまたはに設定してもadjustResize効果はありません。
  • これはシステムレベルの落とし穴です

解決

プラン1

コントロールがActivity含まれている場合は、パノラマ モードの使用を避けるようにしてください。(もちろん、この方法は症状を治すものではありますが、根本的な原因を取り除くものではありません)WebView

シナリオ 2

stackflow解決策を提供してくれた素晴らしい人がいます。(スタックフローアドレス)

具体的なコードは次のとおりです。

import android.app.Activity;
import android.graphics.Rect;
import android.os.Build;
import android.view.View;
import android.view.ViewTreeObserver;
import android.widget.FrameLayout;

/**
 * 修复WebView全屏模式下,软键盘遮挡问题
 */
public final class AndroidBug5497Workaround {
    private View mChildOfContent;
    private int usableHeightPrevious;
    private FrameLayout.LayoutParams frameLayoutParams;
    private int contentHeight;
    private boolean isFirst = true;
    private int statusBarHeight;

    public static void assistActivity(Activity activity) {
        new AndroidBug5497Workaround(activity);
    }

    private AndroidBug5497Workaround(Activity activity) {
        //获取状态栏的高度
        int resourceId = activity.getResources().getIdentifier("status_bar_height", "dimen", "android");
        statusBarHeight = activity.getResources().getDimensionPixelSize(resourceId);
        FrameLayout content = (FrameLayout) activity.findViewById(android.R.id.content);
        mChildOfContent = content.getChildAt(0);
        //界面出现变动都会调用这个监听事件
        mChildOfContent.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            public void onGlobalLayout() {
                if (isFirst) {
                    contentHeight = mChildOfContent.getHeight();//兼容华为等机型
                    isFirst = false;
                }
                possiblyResizeChildOfContent();
            }
        });
        frameLayoutParams = (FrameLayout.LayoutParams) mChildOfContent.getLayoutParams();
    }

    /**
     * 重新调整布局的高度
     */
    private void possiblyResizeChildOfContent() {
        int usableHeightNow = computeUsableHeight();
        //当前可见高度和上一次可见高度不一致 布局变动
        if (usableHeightNow != usableHeightPrevious) {
            int usableHeightSansKeyboard = mChildOfContent.getRootView().getHeight();
            int heightDifference = usableHeightSansKeyboard - usableHeightNow;
            if (heightDifference > (usableHeightSansKeyboard / 4)) {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                    frameLayoutParams.height = usableHeightSansKeyboard - heightDifference + statusBarHeight;
                } else {
                    frameLayoutParams.height = usableHeightSansKeyboard - heightDifference;
                }
            } else {
                frameLayoutParams.height = contentHeight;
            }
            mChildOfContent.requestLayout();
            usableHeightPrevious = usableHeightNow;
        }
    }

    /**
     * 计算mChildOfContent可见高度
     *
     * @return
     */
    private int computeUsableHeight() {
        Rect r = new Rect();
        mChildOfContent.getWindowVisibleDisplayFrame(r);
        return (r.bottom - r.top);
    }
}
  • このクラスをプロジェクトに追加し、対応するメソッドで呼び出すだけですActivityonCreate()
        AndroidBug5497Workaround.assistActivity(this);

AndroidBug5497Workaroundクラス分析:

  1. findViewById(android.R.id.content)アクティビティ インターフェイスの開発者が制御可能な領域のルート ビューを取得することによって。(フルスクリーンモードの場合は画面全体、非フルスクリーンモードの場合はステータスバーを除いたエリア)

  2. mChildOfContent = content.getChildAt(0); Activity レイアウトを取得しますView (つまり、 をsetContentView() 設定しますView )。

  3. View.getViewTreeObserver()現在の View ツリー内の変更を特に監視するオブザーバー オブジェクトを取得します。

  4. ソフト キーボードのポップアップにより View ツリーのグローバル レイアウト (GlobalLayout) が変更されるため、現在の View ツリーの変更を監視するためにオブザーバー オブジェクトaddOnGlobalLayoutListenerをバインドします。

  5. addOnGlobalLayoutListener監視がトリガーされると、主な方法possiblyResizeChildOfContent()はメソッドを呼び出し、インターフェイスの変更後に使用可能な領域をリセットすることです。

  6. possiblyResizeChildOfContent()この方法では、heightDifference > (usableHeightSansKeyboard / 4)インターフェースの高さが 1/4 以上変化した場合にのみ、ソフトキーボードのポップアップに応答するように高さをリセットし、その他のインターフェースの変更は除外されると判断します。

  7. computeUsableHeight()キーボードを取り外した後にレイアウトを再調整するために利用可能な高さを計算するためです。



ソフト キーボード ブロック インターフェイスの問題の概要

Android 入力ボックスのソフト キーボード オクルージョンの問題には、通常、次の 3 つの状況があります。

  • WebView を使用しないインターフェイスの場合:
    必要に応じてandroid:windowSoftInputModeadjustPanまたはとして設定しますadjustResize

  • WebView とのインターフェイス:
    非全画面モード:として
    設定されますフルスクリーン モード:新しいクラスがプロジェクトに追加されます。これは完璧なソリューションです。android:windowSoftInputModeadjustResize

    AndroidBug5497Workaround

参考記事

おすすめ

転載: blog.csdn.net/qq_22255311/article/details/129446787