|
@@ -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) {
|