Androidキーボードの状態を監督してキーボードの高さの実現方法を獲得します。


前言
Androidはまだ適切なAPIを提供していません。キーボードの状態と高さを把握しています。
最近私のプロジェクトの中で、ugcページはキーボードの上で必要として、キーボードにぴったりとくっついて1つのテキストのヒントを表示して、キーボードが消える時隠れます。
そのため、ソフトキーボードのオン/オフを監督して、その高度を取得したいです。
View TreeObserver
A view tree oserver is used to registeners that can be notified of global changes in the view tree.Such global events include,but are not limited to,layout of the whole tree,beginning the of druce。
Androidフレームは、ビューツリーの観察者クラスであるView TreeObserverクラスを提供します。View TreeObserverクラスでは、一連のパブリックインターフェースが定義されています。View atchが一つのウィンドウに来ると、View Tree Observerオブジェクトを作成します。そうすると、一つのビューツリーが変更されると、オブジェクトのある方法を呼び出して、登録された各傍受者にイベントを通知します。
OnGlobal LayoutListenerは、ビューツリーにおけるグローバルレイアウトの変更またはビューツリーにおけるビューの可視状態の変化を監視するために使用される、ビューTree Observerに定義される多くのインターフェースの一つである。ソフトキーボードが隠しから表示に変更されたり、表示から非表示になったりすると、現在のレイアウトに存在するすべてのViewのView Tree Observerオブジェクトのdispatch OnGlobal Layoutを呼び出します。この方法は登録済みのOnGlobal Layout Listenerを巡回して、対応するフィードバック方法を実行して、グローバルレイアウト変更のメッセージを各傍受者に登録します。

view.getViewTreeObserver().addOnGlobalLayoutListener(listener);
get WindowVisible DisplayFrame
Retrieve the overall visible display size in which the window this view is atached to has been positiond in.
get WindowVisible DisplayFrameはウィンドウの可視領域の高さを返します。スクリーンの高さを減らします。ソフトキーボードの高さを得ることができます。
完全な例示コード

package com.cari.cari.promo.diskon.util;


import android.content.Context;
import android.graphics.Rect;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewTreeObserver;

import java.util.LinkedList;
import java.util.List;

public class SoftKeyboardStateWatcher implements ViewTreeObserver.OnGlobalLayoutListener {

 public interface SoftKeyboardStateListener {
  void onSoftKeyboardOpened(int keyboardHeightInPx);

  void onSoftKeyboardClosed();
 }

 private final List<SoftKeyboardStateListener> listeners = new LinkedList<>();
 private final View activityRootView;
 private int lastSoftKeyboardHeightInPx;
 private boolean isSoftKeyboardOpened;
 private Context mContext;

 //          
 public SoftKeyboardStateWatcher(View activityRootView, Context context) {

  this(activityRootView, false);
  this.mContext = context;
 }

 private SoftKeyboardStateWatcher(View activityRootView) {
  this(activityRootView, false);
 }

 private SoftKeyboardStateWatcher(View activityRootView, boolean isSoftKeyboardOpened) {
  this.activityRootView = activityRootView;
  this.isSoftKeyboardOpened = isSoftKeyboardOpened;
  activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(this);
 }

 @Override
 public void onGlobalLayout() {
  final Rect r = new Rect();
  activityRootView.getWindowVisibleDisplayFrame(r);

  final int heightDiff = activityRootView.getRootView().getHeight() - (r.bottom - r.top);
  if (!isSoftKeyboardOpened && heightDiff > dpToPx(mContext, 200)) {
   isSoftKeyboardOpened = true;
   notifyOnSoftKeyboardOpened(heightDiff);
  } else if (isSoftKeyboardOpened && heightDiff < dpToPx(mContext, 200)) {
   isSoftKeyboardOpened = false;
   notifyOnSoftKeyboardClosed();
  }
 }

 public void setIsSoftKeyboardOpened(boolean isSoftKeyboardOpened) {
  this.isSoftKeyboardOpened = isSoftKeyboardOpened;
 }

 public boolean isSoftKeyboardOpened() {
  return isSoftKeyboardOpened;
 }

 /**
  * Default value is zero {@code 0}.
  *
  * @return last saved keyboard height in px
  */
 public int getLastSoftKeyboardHeightInPx() {
  return lastSoftKeyboardHeightInPx;
 }

 public void addSoftKeyboardStateListener(SoftKeyboardStateListener listener) {
  listeners.add(listener);
 }

 public void removeSoftKeyboardStateListener(SoftKeyboardStateListener listener) {
  listeners.remove(listener);
 }

 /**
  * @param keyboardHeightInPx                      
  */
 private void notifyOnSoftKeyboardOpened(int keyboardHeightInPx) {
  this.lastSoftKeyboardHeightInPx = keyboardHeightInPx;

  for (SoftKeyboardStateListener listener : listeners) {
   if (listener != null) {
    listener.onSoftKeyboardOpened(keyboardHeightInPx);
   }
  }
 }

 private void notifyOnSoftKeyboardClosed() {
  for (SoftKeyboardStateListener listener : listeners) {
   if (listener != null) {
    listener.onSoftKeyboardClosed();
   }
  }
 }

 private static float dpToPx(Context context, float valueInDp) {
  DisplayMetrics metrics = context.getResources().getDisplayMetrics();
  return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, valueInDp, metrics);
 }
}
見ることができます。私は自分のListenerを建てました。このlistenerを通じて私達が欲しい傍受を実現して、ここで論理的な問題を処理します。
主なコードはまだonGlobal Layoutにあります。
まず、activityRootView.getWindowVisibleDisplayFrame(r)でこのビューに付加されたウィンドウの位置全体の可視表示サイズを検索し、表示されているビューの高さを差し引いて、表示されているviewの下座標と上座標の差を高さとします。
これで残りの高さを手に入れました。この高さはキーボードの高さかもしれません。なぜ可能ですか?上のステータスバーと下の仮想ナビゲーションバーはまだ考慮されていないので、もちろんキーボードではないかもしれません。
そして、この高さと以前に知られていたキーボードの状態に基づいてキーボードかどうかを判断します。
そして傍受者に戻します。
使用

ScrollView scrollView = findViewById(R.id.ugc_scrollview);
  final SoftKeyboardStateWatcher watcher = new SoftKeyboardStateWatcher(scrollView, this);
  watcher.addSoftKeyboardStateListener(
    new SoftKeyboardStateWatcher.SoftKeyboardStateListener() {

     @Override
     public void onSoftKeyboardOpened(int keyboardHeightInPx) {
      ConstraintLayout.LayoutParams layoutParamsVideo = (ConstraintLayout.LayoutParams) mError1000tv.getLayoutParams();

      layoutParamsVideo.setMargins(0,
        0,
        0,
        keyboardHeightInPx
          - ScreenUtils.getStatusHeight(UGCEditActivity.this)
          - ScreenUtils.getBottomStatusHeight(UGCEditActivity.this));
     }

     @Override
     public void onSoftKeyboardClosed() {
      mError1000tv.setVisibility(View.GONE);
     }
    }
  );
Scrllviewは全ページのルートレイアウトです。それをモニターすることによって、レイアウト全体のモニターを実現します。
mErrror 1000 tvは私が最初に言ったのはキーボードの上にぴったりとくっついて表示するtextviewです。
私はLayoutParaamsを通じて(通って)辺の距離を設定して、ただ底の端の余白だけを設定して、値は帰る“キーボードの高さ”です。頂部のステータスバーの高さです。仮想ナビゲーションバーの高さです。本当のキーボードの高さを得ます。
onSoftKeyboard OpenedとonSoft Keyboard Cloosedのこの二つのリフレクトの中で、自分のロジックを処理すればいいです。
それから、こちらのスクリーンツール類のSreenUtilsのコードを置いて、必要なものをコピーしてください。
SreenUtils

package com.cari.promo.diskon.util;

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Rect;
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.View;
import android.view.WindowManager;

import java.lang.reflect.Method;

public class ScreenUtils {
 private ScreenUtils() {
  /* cannot be instantiated */
  throw new UnsupportedOperationException("cannot be instantiated");
 }

 /**
  *       
  *
  * @param context
  * @return
  */
 public static int getScreenWidth(Context context) {
  WindowManager wm = (WindowManager) context
    .getSystemService(Context.WINDOW_SERVICE);
  DisplayMetrics outMetrics = new DisplayMetrics();
  wm.getDefaultDisplay().getMetrics(outMetrics);
  return outMetrics.widthPixels;
 }

 /**
  *       
  *
  * @param context
  * @return
  */
 public static int getScreenHeight(Context context) {
  WindowManager wm = (WindowManager) context
    .getSystemService(Context.WINDOW_SERVICE);
  DisplayMetrics outMetrics = new DisplayMetrics();
  wm.getDefaultDisplay().getMetrics(outMetrics);
  return outMetrics.heightPixels;
 }

 /**
  *         
  *
  * @param context
  * @return
  */
 public static int getStatusHeight(Context context) {

  int statusHeight = -1;
  try {
   Class<?> clazz = Class.forName("com.android.internal.R$dimen");
   Object object = clazz.newInstance();
   int height = Integer.parseInt(clazz.getField("status_bar_height")
     .get(object).toString());
   statusHeight = context.getResources().getDimensionPixelSize(height);
  } catch (Exception e) {
   e.printStackTrace();
  }
  return statusHeight;
 }

 /**
  *         ,     
  *
  * @param activity
  * @return
  */
 public static Bitmap snapShotWithStatusBar(Activity activity) {
  View view = activity.getWindow().getDecorView();
  view.setDrawingCacheEnabled(true);
  view.buildDrawingCache();
  Bitmap bmp = view.getDrawingCache();
  int width = getScreenWidth(activity);
  int height = getScreenHeight(activity);
  Bitmap bp = null;
  bp = Bitmap.createBitmap(bmp, 0, 0, width, height);
  view.destroyDrawingCache();
  return bp;

 }

 /**
  *         ,      
  *
  * @param activity
  * @return
  */
 public static Bitmap snapShotWithoutStatusBar(Activity activity) {
  View view = activity.getWindow().getDecorView();
  view.setDrawingCacheEnabled(true);
  view.buildDrawingCache();
  Bitmap bmp = view.getDrawingCache();
  Rect frame = new Rect();
  activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);
  int statusBarHeight = frame.top;

  int width = getScreenWidth(activity);
  int height = getScreenHeight(activity);
  Bitmap bp = null;
  bp = Bitmap.createBitmap(bmp, 0, statusBarHeight, width, height
    - statusBarHeight);
  view.destroyDrawingCache();
  return bp;
 }

 /**
  *           
  *
  * @param context    
  * @return      
  */
 public static int getBottomStatusHeight(Context context) {
  int totalHeight = getAbsoluteHeight(context);

  int contentHeight = getScreenHeight(context);

  return totalHeight - contentHeight;
 }

 /**
  *           ,         
  *
  * @param context    
  * @return The absolute height of the available display size in pixels.
  */
 private static int getAbsoluteHeight(Context context) {
  int absoluteHeight = 0;
  WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
  Display display = null;
  if (windowManager != null) {
   display = windowManager.getDefaultDisplay();
  }
  DisplayMetrics displayMetrics = new DisplayMetrics();
  @SuppressWarnings("rawtypes")
  Class c;
  try {
   c = Class.forName("android.view.Display");
   @SuppressWarnings("unchecked")
   Method method = c.getMethod("getRealMetrics", DisplayMetrics.class);
   method.invoke(display, displayMetrics);
   absoluteHeight = displayMetrics.heightPixels;
  } catch (Exception e) {
   e.printStackTrace();
  }
  return absoluteHeight;
 }
}
全文が終わる
締め括りをつける
以上はこの文章の全部の内容です。本文の内容は皆さんの学習や仕事に対して一定の参考学習価値を持ってほしいです。ありがとうございます。