説明なし

SafeAreaView.java 4.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. package com.th3rdwave.safeareaview;
  2. import android.app.Activity;
  3. import android.content.Context;
  4. import android.content.ContextWrapper;
  5. import android.os.Build;
  6. import android.view.Surface;
  7. import android.view.View;
  8. import android.view.ViewTreeObserver;
  9. import android.view.Window;
  10. import android.view.WindowInsets;
  11. import android.view.WindowManager;
  12. import com.facebook.infer.annotation.Assertions;
  13. import com.facebook.react.views.view.ReactViewGroup;
  14. import androidx.annotation.Nullable;
  15. public class SafeAreaView extends ReactViewGroup implements ViewTreeObserver.OnGlobalLayoutListener {
  16. public interface OnInsetsChangeListener {
  17. void onInsetsChange(SafeAreaView view, EdgeInsets insets);
  18. }
  19. private @Nullable OnInsetsChangeListener mInsetsChangeListener;
  20. private WindowManager mWindowManager;
  21. private @Nullable EdgeInsets mLastInsets;
  22. public SafeAreaView(Context context) {
  23. super(context);
  24. mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
  25. }
  26. private Activity getActivity() {
  27. Context context = getContext();
  28. while (context instanceof ContextWrapper) {
  29. if (context instanceof Activity) {
  30. return (Activity)context;
  31. }
  32. context = ((ContextWrapper)context).getBaseContext();
  33. }
  34. return null;
  35. }
  36. private EdgeInsets getSafeAreaInsets() {
  37. // Window insets are parts of the window that are covered by system views (status bar,
  38. // navigation bar, notches). There are no apis the get these values for android < M so we
  39. // do a best effort polyfill.
  40. EdgeInsets windowInsets;
  41. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
  42. WindowInsets insets = getRootWindowInsets();
  43. windowInsets = new EdgeInsets(
  44. insets.getSystemWindowInsetTop(),
  45. insets.getSystemWindowInsetRight(),
  46. insets.getSystemWindowInsetBottom(),
  47. insets.getSystemWindowInsetLeft());
  48. } else {
  49. int rotation = mWindowManager.getDefaultDisplay().getRotation();
  50. int statusBarHeight = 0;
  51. int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
  52. if (resourceId > 0) {
  53. statusBarHeight = getResources().getDimensionPixelSize(resourceId);
  54. }
  55. int navbarHeight = 0;
  56. resourceId = getResources().getIdentifier("navigation_bar_height", "dimen", "android");
  57. if (resourceId > 0) {
  58. navbarHeight = getResources().getDimensionPixelSize(resourceId);
  59. }
  60. windowInsets = new EdgeInsets(
  61. statusBarHeight,
  62. rotation == Surface.ROTATION_90 ? navbarHeight : 0,
  63. rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180 ? navbarHeight : 0,
  64. rotation == Surface.ROTATION_270 ? navbarHeight : 0);
  65. }
  66. // Calculate the part of the root view that overlaps with window insets.
  67. View rootView = getRootView();
  68. View contentView = rootView.findViewById(android.R.id.content);
  69. float windowWidth = rootView.getWidth();
  70. float windowHeight = rootView.getHeight();
  71. int[] windowLocation = new int[2];
  72. contentView.getLocationInWindow(windowLocation);
  73. windowInsets.top = Math.max(windowInsets.top - windowLocation[1], 0);
  74. windowInsets.left = Math.max(windowInsets.left - windowLocation[0], 0);
  75. windowInsets.bottom = Math.max(windowLocation[1] + contentView.getHeight() + windowInsets.bottom - windowHeight, 0);
  76. windowInsets.right = Math.max(windowLocation[0] + contentView.getWidth() + windowInsets.right - windowWidth, 0);
  77. return windowInsets;
  78. }
  79. @Override
  80. protected void onAttachedToWindow() {
  81. super.onAttachedToWindow();
  82. getRootView().getViewTreeObserver().addOnGlobalLayoutListener(this);
  83. }
  84. @Override
  85. protected void onDetachedFromWindow() {
  86. super.onDetachedFromWindow();
  87. getRootView().getViewTreeObserver().removeOnGlobalLayoutListener(this);
  88. }
  89. @Override
  90. public void onGlobalLayout() {
  91. EdgeInsets edgeInsets = getSafeAreaInsets();
  92. if (mLastInsets == null || !mLastInsets.equalsToEdgeInsets(edgeInsets)) {
  93. Assertions.assertNotNull(mInsetsChangeListener).onInsetsChange(this, edgeInsets);
  94. mLastInsets = edgeInsets;
  95. }
  96. }
  97. public void setOnInsetsChangeListener(OnInsetsChangeListener listener) {
  98. mInsetsChangeListener = listener;
  99. }
  100. }