|  | @@ -0,0 +1,85 @@
 | 
	
		
			
			|  | 1 | +package com.th3rdwave.safeareacontext;
 | 
	
		
			
			|  | 2 | +
 | 
	
		
			
			|  | 3 | +import android.graphics.Rect;
 | 
	
		
			
			|  | 4 | +import android.os.Build;
 | 
	
		
			
			|  | 5 | +import android.view.Surface;
 | 
	
		
			
			|  | 6 | +import android.view.View;
 | 
	
		
			
			|  | 7 | +import android.view.WindowInsets;
 | 
	
		
			
			|  | 8 | +import android.view.WindowManager;
 | 
	
		
			
			|  | 9 | +
 | 
	
		
			
			|  | 10 | +import com.facebook.react.bridge.Arguments;
 | 
	
		
			
			|  | 11 | +import com.facebook.react.bridge.ReadableMap;
 | 
	
		
			
			|  | 12 | +import com.facebook.react.bridge.WritableMap;
 | 
	
		
			
			|  | 13 | +import com.facebook.react.common.MapBuilder;
 | 
	
		
			
			|  | 14 | +import com.facebook.react.uimanager.PixelUtil;
 | 
	
		
			
			|  | 15 | +
 | 
	
		
			
			|  | 16 | +import java.util.Map;
 | 
	
		
			
			|  | 17 | +
 | 
	
		
			
			|  | 18 | +/* package */ class SafeAreaUtils {
 | 
	
		
			
			|  | 19 | +  static ReadableMap edgeInsetsToJsMap(EdgeInsets insets) {
 | 
	
		
			
			|  | 20 | +    WritableMap insetsMap = Arguments.createMap();
 | 
	
		
			
			|  | 21 | +    insetsMap.putDouble("top", PixelUtil.toDIPFromPixel(insets.top));
 | 
	
		
			
			|  | 22 | +    insetsMap.putDouble("right", PixelUtil.toDIPFromPixel(insets.right));
 | 
	
		
			
			|  | 23 | +    insetsMap.putDouble("bottom", PixelUtil.toDIPFromPixel(insets.bottom));
 | 
	
		
			
			|  | 24 | +    insetsMap.putDouble("left", PixelUtil.toDIPFromPixel(insets.left));
 | 
	
		
			
			|  | 25 | +    return insetsMap;
 | 
	
		
			
			|  | 26 | +  }
 | 
	
		
			
			|  | 27 | +
 | 
	
		
			
			|  | 28 | +  static Map<String, Float> edgeInsetsToJavaMap(EdgeInsets insets) {
 | 
	
		
			
			|  | 29 | +    return MapBuilder.of(
 | 
	
		
			
			|  | 30 | +        "top",
 | 
	
		
			
			|  | 31 | +        PixelUtil.toDIPFromPixel(insets.top),
 | 
	
		
			
			|  | 32 | +        "right",
 | 
	
		
			
			|  | 33 | +        PixelUtil.toDIPFromPixel(insets.right),
 | 
	
		
			
			|  | 34 | +        "bottom",
 | 
	
		
			
			|  | 35 | +        PixelUtil.toDIPFromPixel(insets.bottom),
 | 
	
		
			
			|  | 36 | +        "left",
 | 
	
		
			
			|  | 37 | +        PixelUtil.toDIPFromPixel(insets.left));
 | 
	
		
			
			|  | 38 | +  }
 | 
	
		
			
			|  | 39 | +
 | 
	
		
			
			|  | 40 | +  static EdgeInsets getSafeAreaInsets(WindowManager windowManager, View rootView) {
 | 
	
		
			
			|  | 41 | +    // Window insets are parts of the window that are covered by system views (status bar,
 | 
	
		
			
			|  | 42 | +    // navigation bar, notches). There are no apis the get these values for android < M so we
 | 
	
		
			
			|  | 43 | +    // do a best effort polyfill.
 | 
	
		
			
			|  | 44 | +    EdgeInsets windowInsets;
 | 
	
		
			
			|  | 45 | +    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
 | 
	
		
			
			|  | 46 | +      WindowInsets insets = rootView.getRootWindowInsets();
 | 
	
		
			
			|  | 47 | +      windowInsets = new EdgeInsets(
 | 
	
		
			
			|  | 48 | +          insets.getSystemWindowInsetTop(),
 | 
	
		
			
			|  | 49 | +          insets.getSystemWindowInsetRight(),
 | 
	
		
			
			|  | 50 | +          insets.getSystemWindowInsetBottom(),
 | 
	
		
			
			|  | 51 | +          insets.getSystemWindowInsetLeft());
 | 
	
		
			
			|  | 52 | +    } else {
 | 
	
		
			
			|  | 53 | +      int rotation = windowManager.getDefaultDisplay().getRotation();
 | 
	
		
			
			|  | 54 | +      int statusBarHeight = 0;
 | 
	
		
			
			|  | 55 | +      int resourceId = rootView.getResources().getIdentifier("status_bar_height", "dimen", "android");
 | 
	
		
			
			|  | 56 | +      if (resourceId > 0) {
 | 
	
		
			
			|  | 57 | +        statusBarHeight = rootView.getResources().getDimensionPixelSize(resourceId);
 | 
	
		
			
			|  | 58 | +      }
 | 
	
		
			
			|  | 59 | +      int navbarHeight = 0;
 | 
	
		
			
			|  | 60 | +      resourceId = rootView.getResources().getIdentifier("navigation_bar_height", "dimen", "android");
 | 
	
		
			
			|  | 61 | +      if (resourceId > 0) {
 | 
	
		
			
			|  | 62 | +        navbarHeight = rootView.getResources().getDimensionPixelSize(resourceId);
 | 
	
		
			
			|  | 63 | +      }
 | 
	
		
			
			|  | 64 | +
 | 
	
		
			
			|  | 65 | +      windowInsets = new EdgeInsets(
 | 
	
		
			
			|  | 66 | +          statusBarHeight,
 | 
	
		
			
			|  | 67 | +          rotation == Surface.ROTATION_90 ? navbarHeight : 0,
 | 
	
		
			
			|  | 68 | +          rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180 ? navbarHeight : 0,
 | 
	
		
			
			|  | 69 | +          rotation == Surface.ROTATION_270 ? navbarHeight : 0);
 | 
	
		
			
			|  | 70 | +    }
 | 
	
		
			
			|  | 71 | +
 | 
	
		
			
			|  | 72 | +    // Calculate the part of the root view that overlaps with window insets.
 | 
	
		
			
			|  | 73 | +    View contentView = rootView.findViewById(android.R.id.content);
 | 
	
		
			
			|  | 74 | +    float windowWidth = rootView.getWidth();
 | 
	
		
			
			|  | 75 | +    float windowHeight = rootView.getHeight();
 | 
	
		
			
			|  | 76 | +    Rect visibleRect = new Rect();
 | 
	
		
			
			|  | 77 | +    contentView.getGlobalVisibleRect(visibleRect);
 | 
	
		
			
			|  | 78 | +
 | 
	
		
			
			|  | 79 | +    windowInsets.top = Math.max(windowInsets.top - visibleRect.top, 0);
 | 
	
		
			
			|  | 80 | +    windowInsets.left = Math.max(windowInsets.left - visibleRect.left, 0);
 | 
	
		
			
			|  | 81 | +    windowInsets.bottom = Math.max(visibleRect.top + contentView.getHeight() + windowInsets.bottom - windowHeight, 0);
 | 
	
		
			
			|  | 82 | +    windowInsets.right = Math.max(visibleRect.left + contentView.getWidth() + windowInsets.right - windowWidth, 0);
 | 
	
		
			
			|  | 83 | +    return windowInsets;
 | 
	
		
			
			|  | 84 | +  }
 | 
	
		
			
			|  | 85 | +}
 |