SafeAreaUtils.java 2.9KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. package com.th3rdwave.safeareacontext;
  2. import android.graphics.Rect;
  3. import android.os.Build;
  4. import android.view.Surface;
  5. import android.view.View;
  6. import android.view.ViewGroup;
  7. import android.view.WindowInsets;
  8. import android.view.WindowManager;
  9. import androidx.annotation.Nullable;
  10. /* package */ class SafeAreaUtils {
  11. static @Nullable EdgeInsets getSafeAreaInsets(
  12. WindowManager windowManager,
  13. View rootView,
  14. View view
  15. ) {
  16. // Window insets are parts of the window that are covered by system views (status bar,
  17. // navigation bar, notches). There are no apis the get these values for android < M so we
  18. // do a best effort polyfill.
  19. EdgeInsets windowInsets;
  20. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
  21. WindowInsets insets = rootView.getRootWindowInsets();
  22. if (insets == null) {
  23. return null;
  24. }
  25. windowInsets = new EdgeInsets(
  26. insets.getSystemWindowInsetTop(),
  27. insets.getSystemWindowInsetRight(),
  28. insets.getSystemWindowInsetBottom(),
  29. insets.getSystemWindowInsetLeft());
  30. } else {
  31. int rotation = windowManager.getDefaultDisplay().getRotation();
  32. int statusBarHeight = 0;
  33. int resourceId = rootView.getResources().getIdentifier("status_bar_height", "dimen", "android");
  34. if (resourceId > 0) {
  35. statusBarHeight = rootView.getResources().getDimensionPixelSize(resourceId);
  36. }
  37. int navbarHeight = 0;
  38. resourceId = rootView.getResources().getIdentifier("navigation_bar_height", "dimen", "android");
  39. if (resourceId > 0) {
  40. navbarHeight = rootView.getResources().getDimensionPixelSize(resourceId);
  41. }
  42. windowInsets = new EdgeInsets(
  43. statusBarHeight,
  44. rotation == Surface.ROTATION_90 ? navbarHeight : 0,
  45. rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180 ? navbarHeight : 0,
  46. rotation == Surface.ROTATION_270 ? navbarHeight : 0);
  47. }
  48. // Calculate the part of the view that overlaps with window insets.
  49. float windowWidth = rootView.getWidth();
  50. float windowHeight = rootView.getHeight();
  51. Rect visibleRect = new Rect();
  52. view.getGlobalVisibleRect(visibleRect);
  53. windowInsets.top = Math.max(windowInsets.top - visibleRect.top, 0);
  54. windowInsets.left = Math.max(windowInsets.left - visibleRect.left, 0);
  55. windowInsets.bottom = Math.max(visibleRect.top + view.getHeight() + windowInsets.bottom - windowHeight, 0);
  56. windowInsets.right = Math.max(visibleRect.left + view.getWidth() + windowInsets.right - windowWidth, 0);
  57. return windowInsets;
  58. }
  59. static com.th3rdwave.safeareacontext.Rect getFrame(ViewGroup rootView, View view) {
  60. Rect offset = new Rect();
  61. view.getDrawingRect(offset);
  62. rootView.offsetDescendantRectToMyCoords(view, offset);
  63. return new com.th3rdwave.safeareacontext.Rect(offset.left, offset.top, view.getWidth(), view.getHeight());
  64. }
  65. }