| 
				
			 | 
			
			
				@@ -1,25 +1,29 @@ 
			 | 
		
	
		
			
			| 
				1
			 | 
			
				1
			 | 
			
			
				 package com.th3rdwave.safeareaview; 
			 | 
		
	
		
			
			| 
				2
			 | 
			
				2
			 | 
			
			
				  
			 | 
		
	
		
			
			| 
				
			 | 
			
				3
			 | 
			
			
				+import android.app.Activity; 
			 | 
		
	
		
			
			| 
				3
			 | 
			
				4
			 | 
			
			
				 import android.content.Context; 
			 | 
		
	
		
			
			| 
				
			 | 
			
				5
			 | 
			
			
				+import android.content.ContextWrapper; 
			 | 
		
	
		
			
			| 
				4
			 | 
			
				6
			 | 
			
			
				 import android.os.Build; 
			 | 
		
	
		
			
			| 
				5
			 | 
			
				
			 | 
			
			
				-import android.util.DisplayMetrics; 
			 | 
		
	
		
			
			| 
				6
			 | 
			
				7
			 | 
			
			
				 import android.view.Surface; 
			 | 
		
	
		
			
			| 
				
			 | 
			
				8
			 | 
			
			
				+import android.view.View; 
			 | 
		
	
		
			
			| 
				
			 | 
			
				9
			 | 
			
			
				+import android.view.ViewTreeObserver; 
			 | 
		
	
		
			
			| 
				
			 | 
			
				10
			 | 
			
			
				+import android.view.Window; 
			 | 
		
	
		
			
			| 
				7
			 | 
			
				11
			 | 
			
			
				 import android.view.WindowInsets; 
			 | 
		
	
		
			
			| 
				8
			 | 
			
				12
			 | 
			
			
				 import android.view.WindowManager; 
			 | 
		
	
		
			
			| 
				9
			 | 
			
				13
			 | 
			
			
				  
			 | 
		
	
		
			
			| 
				10
			 | 
			
				14
			 | 
			
			
				 import com.facebook.infer.annotation.Assertions; 
			 | 
		
	
		
			
			| 
				11
			 | 
			
				
			 | 
			
			
				-import com.facebook.react.uimanager.DisplayMetricsHolder; 
			 | 
		
	
		
			
			| 
				12
			 | 
			
				15
			 | 
			
			
				 import com.facebook.react.views.view.ReactViewGroup; 
			 | 
		
	
		
			
			| 
				13
			 | 
			
				16
			 | 
			
			
				  
			 | 
		
	
		
			
			| 
				14
			 | 
			
				17
			 | 
			
			
				 import androidx.annotation.Nullable; 
			 | 
		
	
		
			
			| 
				15
			 | 
			
				18
			 | 
			
			
				  
			 | 
		
	
		
			
			| 
				16
			 | 
			
				
			 | 
			
			
				-public class SafeAreaView extends ReactViewGroup { 
			 | 
		
	
		
			
			| 
				
			 | 
			
				19
			 | 
			
			
				+public class SafeAreaView extends ReactViewGroup implements ViewTreeObserver.OnGlobalLayoutListener { 
			 | 
		
	
		
			
			| 
				17
			 | 
			
				20
			 | 
			
			
				   public interface OnInsetsChangeListener { 
			 | 
		
	
		
			
			| 
				18
			 | 
			
				21
			 | 
			
			
				     void onInsetsChange(SafeAreaView view, EdgeInsets insets); 
			 | 
		
	
		
			
			| 
				19
			 | 
			
				22
			 | 
			
			
				   } 
			 | 
		
	
		
			
			| 
				20
			 | 
			
				23
			 | 
			
			
				  
			 | 
		
	
		
			
			| 
				21
			 | 
			
				24
			 | 
			
			
				   private @Nullable OnInsetsChangeListener mInsetsChangeListener; 
			 | 
		
	
		
			
			| 
				22
			 | 
			
				
			 | 
			
			
				-  WindowManager mWindowManager; 
			 | 
		
	
		
			
			| 
				
			 | 
			
				25
			 | 
			
			
				+  private WindowManager mWindowManager; 
			 | 
		
	
		
			
			| 
				
			 | 
			
				26
			 | 
			
			
				+  private @Nullable EdgeInsets mLastInsets; 
			 | 
		
	
		
			
			| 
				23
			 | 
			
				27
			 | 
			
			
				  
			 | 
		
	
		
			
			| 
				24
			 | 
			
				28
			 | 
			
			
				   public SafeAreaView(Context context) { 
			 | 
		
	
		
			
			| 
				25
			 | 
			
				29
			 | 
			
			
				     super(context); 
			 | 
		
	
	
		
			
			| 
				
			 | 
			
			
				@@ -27,6 +31,17 @@ public class SafeAreaView extends ReactViewGroup { 
			 | 
		
	
		
			
			| 
				27
			 | 
			
				31
			 | 
			
			
				     mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); 
			 | 
		
	
		
			
			| 
				28
			 | 
			
				32
			 | 
			
			
				   } 
			 | 
		
	
		
			
			| 
				29
			 | 
			
				33
			 | 
			
			
				  
			 | 
		
	
		
			
			| 
				
			 | 
			
				34
			 | 
			
			
				+  private Activity getActivity() { 
			 | 
		
	
		
			
			| 
				
			 | 
			
				35
			 | 
			
			
				+    Context context = getContext(); 
			 | 
		
	
		
			
			| 
				
			 | 
			
				36
			 | 
			
			
				+    while (context instanceof ContextWrapper) { 
			 | 
		
	
		
			
			| 
				
			 | 
			
				37
			 | 
			
			
				+      if (context instanceof Activity) { 
			 | 
		
	
		
			
			| 
				
			 | 
			
				38
			 | 
			
			
				+        return (Activity)context; 
			 | 
		
	
		
			
			| 
				
			 | 
			
				39
			 | 
			
			
				+      } 
			 | 
		
	
		
			
			| 
				
			 | 
			
				40
			 | 
			
			
				+      context = ((ContextWrapper)context).getBaseContext(); 
			 | 
		
	
		
			
			| 
				
			 | 
			
				41
			 | 
			
			
				+    } 
			 | 
		
	
		
			
			| 
				
			 | 
			
				42
			 | 
			
			
				+    return null; 
			 | 
		
	
		
			
			| 
				
			 | 
			
				43
			 | 
			
			
				+  } 
			 | 
		
	
		
			
			| 
				
			 | 
			
				44
			 | 
			
			
				+ 
			 | 
		
	
		
			
			| 
				30
			 | 
			
				45
			 | 
			
			
				   private EdgeInsets getSafeAreaInsets() { 
			 | 
		
	
		
			
			| 
				31
			 | 
			
				46
			 | 
			
			
				     // Window insets are parts of the window that are covered by system views (status bar, 
			 | 
		
	
		
			
			| 
				32
			 | 
			
				47
			 | 
			
			
				     // navigation bar, notches). There are no apis the get these values for android < M so we 
			 | 
		
	
	
		
			
			| 
				
			 | 
			
			
				@@ -60,21 +75,40 @@ public class SafeAreaView extends ReactViewGroup { 
			 | 
		
	
		
			
			| 
				60
			 | 
			
				75
			 | 
			
			
				     } 
			 | 
		
	
		
			
			| 
				61
			 | 
			
				76
			 | 
			
			
				  
			 | 
		
	
		
			
			| 
				62
			 | 
			
				77
			 | 
			
			
				     // Calculate the part of the root view that overlaps with window insets. 
			 | 
		
	
		
			
			| 
				
			 | 
			
				78
			 | 
			
			
				+    View rootView = getRootView(); 
			 | 
		
	
		
			
			| 
				
			 | 
			
				79
			 | 
			
			
				+    View contentView = rootView.findViewById(android.R.id.content); 
			 | 
		
	
		
			
			| 
				
			 | 
			
				80
			 | 
			
			
				+    float windowWidth = rootView.getWidth(); 
			 | 
		
	
		
			
			| 
				
			 | 
			
				81
			 | 
			
			
				+    float windowHeight = rootView.getHeight(); 
			 | 
		
	
		
			
			| 
				63
			 | 
			
				82
			 | 
			
			
				     int[] windowLocation = new int[2]; 
			 | 
		
	
		
			
			| 
				64
			 | 
			
				
			 | 
			
			
				-    getLocationInWindow(windowLocation); 
			 | 
		
	
		
			
			| 
				65
			 | 
			
				
			 | 
			
			
				-    DisplayMetrics screenMetrics = DisplayMetricsHolder.getScreenDisplayMetrics(); 
			 | 
		
	
		
			
			| 
				
			 | 
			
				83
			 | 
			
			
				+    contentView.getLocationInWindow(windowLocation); 
			 | 
		
	
		
			
			| 
				66
			 | 
			
				84
			 | 
			
			
				     windowInsets.top = Math.max(windowInsets.top - windowLocation[1], 0); 
			 | 
		
	
		
			
			| 
				67
			 | 
			
				85
			 | 
			
			
				     windowInsets.left = Math.max(windowInsets.left - windowLocation[0], 0); 
			 | 
		
	
		
			
			| 
				68
			 | 
			
				
			 | 
			
			
				-    windowInsets.bottom = Math.max(windowLocation[1] + getHeight() + windowInsets.bottom - screenMetrics.heightPixels, 0); 
			 | 
		
	
		
			
			| 
				69
			 | 
			
				
			 | 
			
			
				-    windowInsets.right = Math.max(windowLocation[0] + getWidth() + windowInsets.right - screenMetrics.widthPixels, 0); 
			 | 
		
	
		
			
			| 
				
			 | 
			
				86
			 | 
			
			
				+    windowInsets.bottom = Math.max(windowLocation[1] + contentView.getHeight() + windowInsets.bottom - windowHeight, 0); 
			 | 
		
	
		
			
			| 
				
			 | 
			
				87
			 | 
			
			
				+    windowInsets.right = Math.max(windowLocation[0] + contentView.getWidth() + windowInsets.right - windowWidth, 0); 
			 | 
		
	
		
			
			| 
				70
			 | 
			
				88
			 | 
			
			
				     return windowInsets; 
			 | 
		
	
		
			
			| 
				71
			 | 
			
				89
			 | 
			
			
				   } 
			 | 
		
	
		
			
			| 
				72
			 | 
			
				90
			 | 
			
			
				  
			 | 
		
	
		
			
			| 
				73
			 | 
			
				91
			 | 
			
			
				   @Override 
			 | 
		
	
		
			
			| 
				74
			 | 
			
				
			 | 
			
			
				-  protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 
			 | 
		
	
		
			
			| 
				75
			 | 
			
				
			 | 
			
			
				-    super.onLayout(changed, left, top, right, bottom); 
			 | 
		
	
		
			
			| 
				
			 | 
			
				92
			 | 
			
			
				+  protected void onAttachedToWindow() { 
			 | 
		
	
		
			
			| 
				
			 | 
			
				93
			 | 
			
			
				+    super.onAttachedToWindow(); 
			 | 
		
	
		
			
			| 
				
			 | 
			
				94
			 | 
			
			
				+ 
			 | 
		
	
		
			
			| 
				
			 | 
			
				95
			 | 
			
			
				+    getRootView().getViewTreeObserver().addOnGlobalLayoutListener(this); 
			 | 
		
	
		
			
			| 
				
			 | 
			
				96
			 | 
			
			
				+  } 
			 | 
		
	
		
			
			| 
				
			 | 
			
				97
			 | 
			
			
				+ 
			 | 
		
	
		
			
			| 
				
			 | 
			
				98
			 | 
			
			
				+  @Override 
			 | 
		
	
		
			
			| 
				
			 | 
			
				99
			 | 
			
			
				+  protected void onDetachedFromWindow() { 
			 | 
		
	
		
			
			| 
				
			 | 
			
				100
			 | 
			
			
				+    super.onDetachedFromWindow(); 
			 | 
		
	
		
			
			| 
				
			 | 
			
				101
			 | 
			
			
				+ 
			 | 
		
	
		
			
			| 
				
			 | 
			
				102
			 | 
			
			
				+    getRootView().getViewTreeObserver().removeOnGlobalLayoutListener(this); 
			 | 
		
	
		
			
			| 
				
			 | 
			
				103
			 | 
			
			
				+  } 
			 | 
		
	
		
			
			| 
				76
			 | 
			
				104
			 | 
			
			
				  
			 | 
		
	
		
			
			| 
				77
			 | 
			
				
			 | 
			
			
				-    Assertions.assertNotNull(mInsetsChangeListener).onInsetsChange(this, getSafeAreaInsets()); 
			 | 
		
	
		
			
			| 
				
			 | 
			
				105
			 | 
			
			
				+  @Override 
			 | 
		
	
		
			
			| 
				
			 | 
			
				106
			 | 
			
			
				+  public void onGlobalLayout() { 
			 | 
		
	
		
			
			| 
				
			 | 
			
				107
			 | 
			
			
				+    EdgeInsets edgeInsets = getSafeAreaInsets(); 
			 | 
		
	
		
			
			| 
				
			 | 
			
				108
			 | 
			
			
				+    if (mLastInsets == null || !mLastInsets.equalsToEdgeInsets(edgeInsets)) { 
			 | 
		
	
		
			
			| 
				
			 | 
			
				109
			 | 
			
			
				+      Assertions.assertNotNull(mInsetsChangeListener).onInsetsChange(this, edgeInsets); 
			 | 
		
	
		
			
			| 
				
			 | 
			
				110
			 | 
			
			
				+      mLastInsets = edgeInsets; 
			 | 
		
	
		
			
			| 
				
			 | 
			
				111
			 | 
			
			
				+    } 
			 | 
		
	
		
			
			| 
				78
			 | 
			
				112
			 | 
			
			
				   } 
			 | 
		
	
		
			
			| 
				79
			 | 
			
				113
			 | 
			
			
				  
			 | 
		
	
		
			
			| 
				80
			 | 
			
				114
			 | 
			
			
				   public void setOnInsetsChangeListener(OnInsetsChangeListener listener) { 
			 |