@react-native-hero/dimension 0.0.3 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
|
@@ -40,6 +40,9 @@ $ react-native link @react-native-hero/dimension
|
|
|
40
40
|
|
|
41
41
|
```js
|
|
42
42
|
import {
|
|
43
|
+
init,
|
|
44
|
+
addListener,
|
|
45
|
+
|
|
43
46
|
statusBarHeight,
|
|
44
47
|
navigationBarHeight,
|
|
45
48
|
screenSize,
|
|
@@ -51,6 +54,9 @@ import {
|
|
|
51
54
|
getSafeArea,
|
|
52
55
|
} from '@react-native-hero/dimension'
|
|
53
56
|
|
|
57
|
+
// In your App.js, call init()
|
|
58
|
+
init()
|
|
59
|
+
|
|
54
60
|
// The getXxx methods is used to get the latest dimension info asynchronously.
|
|
55
61
|
// If your app will not change the dimension info, you can just use the corresponding variables.
|
|
56
62
|
|
|
@@ -73,4 +79,12 @@ getSafeArea().then(data => {
|
|
|
73
79
|
data.bottom
|
|
74
80
|
data.left
|
|
75
81
|
})
|
|
82
|
+
|
|
83
|
+
// You have to listen dimension change in android app.
|
|
84
|
+
addListener('change', function (data) {
|
|
85
|
+
data.statusBarHeight
|
|
86
|
+
data.navigationBarHeight
|
|
87
|
+
data.screenSize
|
|
88
|
+
data.safeArea
|
|
89
|
+
})
|
|
76
90
|
```
|
package/android/build.gradle
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
buildscript {
|
|
2
2
|
// Buildscript is evaluated before everything else so we can't use safeExtGet
|
|
3
|
-
def kotlinVersion = rootProject.ext.has('kotlinVersion') ? rootProject.ext.get('kotlinVersion') : '
|
|
3
|
+
def kotlinVersion = rootProject.ext.has('kotlinVersion') ? rootProject.ext.get('kotlinVersion') : '2.0.21'
|
|
4
4
|
|
|
5
5
|
repositories {
|
|
6
6
|
jcenter()
|
|
@@ -19,12 +19,12 @@ def safeExtGet(prop, fallback) {
|
|
|
19
19
|
apply plugin: 'com.android.library'
|
|
20
20
|
|
|
21
21
|
android {
|
|
22
|
-
compileSdkVersion safeExtGet('compileSdkVersion',
|
|
23
|
-
buildToolsVersion safeExtGet('buildToolsVersion', '
|
|
22
|
+
compileSdkVersion safeExtGet('compileSdkVersion', 35)
|
|
23
|
+
buildToolsVersion safeExtGet('buildToolsVersion', '35.0.0')
|
|
24
24
|
|
|
25
25
|
defaultConfig {
|
|
26
|
-
minSdkVersion safeExtGet('minSdkVersion',
|
|
27
|
-
targetSdkVersion safeExtGet('targetSdkVersion',
|
|
26
|
+
minSdkVersion safeExtGet('minSdkVersion', 20)
|
|
27
|
+
targetSdkVersion safeExtGet('targetSdkVersion', 35)
|
|
28
28
|
versionCode 1
|
|
29
29
|
versionName "1.0"
|
|
30
30
|
}
|
|
@@ -35,7 +35,7 @@ android {
|
|
|
35
35
|
|
|
36
36
|
dependencies {
|
|
37
37
|
implementation "com.facebook.react:react-native:${safeExtGet('reactNativeVersion', '+')}"
|
|
38
|
-
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${safeExtGet('kotlinVersion', '
|
|
38
|
+
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${safeExtGet('kotlinVersion', '2.0.21')}"
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
apply plugin: 'kotlin-android'
|
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
package com.github.reactnativehero.dimension
|
|
2
2
|
|
|
3
|
-
import android.
|
|
4
|
-
import android.view.Display
|
|
5
|
-
import android.content.Context.WINDOW_SERVICE
|
|
3
|
+
import android.app.Activity
|
|
6
4
|
import android.graphics.Point
|
|
7
5
|
import android.graphics.Rect
|
|
6
|
+
import android.os.Build
|
|
7
|
+
import android.os.Handler
|
|
8
|
+
import android.os.Looper
|
|
9
|
+
import android.util.Size
|
|
8
10
|
import android.view.WindowManager
|
|
11
|
+
import androidx.core.view.OnApplyWindowInsetsListener
|
|
12
|
+
import androidx.core.view.ViewCompat
|
|
13
|
+
import androidx.core.view.WindowInsetsCompat
|
|
9
14
|
import com.facebook.react.bridge.*
|
|
10
|
-
import
|
|
11
|
-
import java.util.HashMap
|
|
15
|
+
import com.facebook.react.modules.core.DeviceEventManagerModule
|
|
12
16
|
|
|
13
17
|
class RNTDimensionModule(private val reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) {
|
|
14
18
|
|
|
@@ -16,52 +20,132 @@ class RNTDimensionModule(private val reactContext: ReactApplicationContext) : Re
|
|
|
16
20
|
reactApplicationContext.resources.displayMetrics.density
|
|
17
21
|
}
|
|
18
22
|
|
|
23
|
+
private var statusBarHeight = 0
|
|
24
|
+
private var navigationBarHeight = 0
|
|
25
|
+
|
|
26
|
+
private var cutoutTop = 0
|
|
27
|
+
private var cutoutRight = 0
|
|
28
|
+
private var cutoutBottom = 0
|
|
29
|
+
private var cutoutLeft = 0
|
|
30
|
+
|
|
19
31
|
override fun getName(): String {
|
|
20
32
|
return "RNTDimension"
|
|
21
33
|
}
|
|
22
34
|
|
|
23
|
-
override fun getConstants(): Map<String, Any
|
|
35
|
+
override fun getConstants(): Map<String, Any> {
|
|
24
36
|
|
|
25
37
|
val constants: MutableMap<String, Any> = HashMap()
|
|
26
38
|
|
|
27
|
-
constants["STATUS_BAR_HEIGHT"] =
|
|
28
|
-
constants["NAVIGATION_BAR_HEIGHT"] =
|
|
39
|
+
constants["STATUS_BAR_HEIGHT"] = getStatusBarHeightData()
|
|
40
|
+
constants["NAVIGATION_BAR_HEIGHT"] = getNavigationBarHeightData()
|
|
29
41
|
|
|
30
|
-
val screenSize =
|
|
31
|
-
constants["SCREEN_WIDTH"] = screenSize.
|
|
32
|
-
constants["SCREEN_HEIGHT"] = screenSize.
|
|
42
|
+
val screenSize = getScreenSizeData()
|
|
43
|
+
constants["SCREEN_WIDTH"] = screenSize.width
|
|
44
|
+
constants["SCREEN_HEIGHT"] = screenSize.height
|
|
33
45
|
|
|
34
|
-
val safeArea =
|
|
35
|
-
constants["SAFE_AREA_TOP"] = safeArea.
|
|
36
|
-
constants["SAFE_AREA_RIGHT"] = safeArea.
|
|
37
|
-
constants["SAFE_AREA_BOTTOM"] = safeArea.
|
|
38
|
-
constants["SAFE_AREA_LEFT"] = safeArea.
|
|
46
|
+
val safeArea = getSafeAreaData()
|
|
47
|
+
constants["SAFE_AREA_TOP"] = safeArea.top
|
|
48
|
+
constants["SAFE_AREA_RIGHT"] = safeArea.right
|
|
49
|
+
constants["SAFE_AREA_BOTTOM"] = safeArea.bottom
|
|
50
|
+
constants["SAFE_AREA_LEFT"] = safeArea.left
|
|
39
51
|
|
|
40
52
|
return constants
|
|
41
53
|
|
|
42
54
|
}
|
|
43
55
|
|
|
44
56
|
@ReactMethod
|
|
45
|
-
fun
|
|
57
|
+
fun init(promise: Promise) {
|
|
58
|
+
|
|
59
|
+
lateinit var waitActivity: () -> Unit
|
|
60
|
+
|
|
61
|
+
val handler = fun (activity: Activity?) {
|
|
62
|
+
val listener = OnApplyWindowInsetsListener { _, insets ->
|
|
63
|
+
|
|
64
|
+
val systemBarInsets = insets.getInsets(WindowInsetsCompat.Type.systemBars())
|
|
65
|
+
val cutoutInsets = insets.getInsets(WindowInsetsCompat.Type.displayCutout())
|
|
66
|
+
|
|
67
|
+
var isChange = false
|
|
68
|
+
|
|
69
|
+
if (statusBarHeight != systemBarInsets.top) {
|
|
70
|
+
statusBarHeight = systemBarInsets.top
|
|
71
|
+
isChange = true
|
|
72
|
+
}
|
|
73
|
+
if (navigationBarHeight != systemBarInsets.bottom) {
|
|
74
|
+
navigationBarHeight = systemBarInsets.bottom
|
|
75
|
+
isChange = true
|
|
76
|
+
}
|
|
77
|
+
if (cutoutTop != cutoutInsets.top) {
|
|
78
|
+
cutoutTop = cutoutInsets.top
|
|
79
|
+
isChange = true
|
|
80
|
+
}
|
|
81
|
+
if (cutoutRight != cutoutInsets.right) {
|
|
82
|
+
cutoutRight = cutoutInsets.right
|
|
83
|
+
isChange = true
|
|
84
|
+
}
|
|
85
|
+
if (cutoutBottom != cutoutInsets.bottom) {
|
|
86
|
+
cutoutBottom = cutoutInsets.bottom
|
|
87
|
+
isChange = true
|
|
88
|
+
}
|
|
89
|
+
if (cutoutLeft != cutoutInsets.left) {
|
|
90
|
+
cutoutLeft = cutoutInsets.left
|
|
91
|
+
isChange = true
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (isChange) {
|
|
95
|
+
val screenSizeData = getScreenSizeData()
|
|
96
|
+
val screenSizeMap = Arguments.createMap()
|
|
97
|
+
screenSizeMap.putInt("width", screenSizeData.width)
|
|
98
|
+
screenSizeMap.putInt("height", screenSizeData.height)
|
|
99
|
+
|
|
100
|
+
val safeAreaData = getSafeAreaData()
|
|
101
|
+
val safeAreaMap = Arguments.createMap()
|
|
102
|
+
safeAreaMap.putInt("top", safeAreaData.top)
|
|
103
|
+
safeAreaMap.putInt("right", safeAreaData.right)
|
|
104
|
+
safeAreaMap.putInt("bottom", safeAreaData.bottom)
|
|
105
|
+
safeAreaMap.putInt("left", safeAreaData.left)
|
|
106
|
+
|
|
107
|
+
val map = Arguments.createMap()
|
|
108
|
+
map.putInt("statusBarHeight", getStatusBarHeightData())
|
|
109
|
+
map.putInt("navigationBarHeight", getNavigationBarHeightData())
|
|
110
|
+
map.putMap("screenSize", screenSizeMap)
|
|
111
|
+
map.putMap("safeArea", safeAreaMap)
|
|
112
|
+
|
|
113
|
+
sendEvent("change", map)
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
insets
|
|
117
|
+
}
|
|
118
|
+
if (activity != null) {
|
|
119
|
+
activity.runOnUiThread {
|
|
120
|
+
val decorView = activity.window.decorView
|
|
121
|
+
ViewCompat.setOnApplyWindowInsetsListener(decorView, listener)
|
|
122
|
+
decorView.requestApplyInsets()
|
|
123
|
+
|
|
124
|
+
val map = Arguments.createMap()
|
|
125
|
+
promise.resolve(map)
|
|
126
|
+
}
|
|
127
|
+
} else {
|
|
128
|
+
waitActivity()
|
|
129
|
+
}
|
|
130
|
+
}
|
|
46
131
|
|
|
47
|
-
|
|
48
|
-
|
|
132
|
+
waitActivity = fun () {
|
|
133
|
+
Handler(Looper.getMainLooper()).postDelayed({
|
|
134
|
+
handler(reactContext.currentActivity)
|
|
135
|
+
}, 200)
|
|
136
|
+
}
|
|
49
137
|
|
|
50
|
-
|
|
138
|
+
handler(reactContext.currentActivity)
|
|
51
139
|
|
|
52
140
|
}
|
|
53
141
|
|
|
54
|
-
|
|
142
|
+
@ReactMethod
|
|
143
|
+
fun getStatusBarHeight(promise: Promise) {
|
|
55
144
|
|
|
56
|
-
val
|
|
57
|
-
|
|
145
|
+
val map = Arguments.createMap()
|
|
146
|
+
map.putInt("height", getStatusBarHeightData())
|
|
58
147
|
|
|
59
|
-
|
|
60
|
-
(resources.getDimensionPixelSize(resId) / density).toInt()
|
|
61
|
-
}
|
|
62
|
-
else {
|
|
63
|
-
0
|
|
64
|
-
}
|
|
148
|
+
promise.resolve(map)
|
|
65
149
|
|
|
66
150
|
}
|
|
67
151
|
|
|
@@ -69,108 +153,81 @@ class RNTDimensionModule(private val reactContext: ReactApplicationContext) : Re
|
|
|
69
153
|
fun getNavigationBarHeight(promise: Promise) {
|
|
70
154
|
|
|
71
155
|
val map = Arguments.createMap()
|
|
72
|
-
map.putInt("height",
|
|
156
|
+
map.putInt("height", getNavigationBarHeightData())
|
|
73
157
|
|
|
74
158
|
promise.resolve(map)
|
|
75
159
|
|
|
76
160
|
}
|
|
77
161
|
|
|
78
|
-
private fun getNavigationBarHeight(): Int {
|
|
79
|
-
|
|
80
|
-
val window = currentActivity?.window ?: return 0
|
|
81
|
-
|
|
82
|
-
// getScreenSize() 方法在某些手机上返回的是内容区域的尺寸
|
|
83
|
-
// 导致这里返回的是 navigation bar + status bar 的高度
|
|
84
|
-
// 因此我们改变思路,获取内容区域的位置信息,这样就能求出真实的 navigation bar 的高度了
|
|
85
|
-
|
|
86
|
-
val realScreenSize = getRealScreenSize()
|
|
87
|
-
|
|
88
|
-
val rect = Rect()
|
|
89
|
-
|
|
90
|
-
window.decorView.getWindowVisibleDisplayFrame(rect)
|
|
91
|
-
|
|
92
|
-
return ((realScreenSize.y - rect.bottom) / density).toInt()
|
|
93
|
-
|
|
94
|
-
}
|
|
95
|
-
|
|
96
162
|
@ReactMethod
|
|
97
163
|
fun getScreenSize(promise: Promise) {
|
|
98
164
|
|
|
99
|
-
promise.resolve(getScreenSizeMap())
|
|
100
|
-
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
private fun getScreenSizeMap(): WritableMap {
|
|
104
|
-
|
|
105
|
-
// 跟 ios 保持一致,获取的是物理屏尺寸
|
|
106
|
-
val screenSize = getRealScreenSize()
|
|
107
|
-
|
|
108
165
|
val map = Arguments.createMap()
|
|
109
|
-
|
|
110
|
-
map.putInt("height", (screenSize.y / density).toInt())
|
|
166
|
+
val data = getScreenSizeData()
|
|
111
167
|
|
|
112
|
-
|
|
168
|
+
map.putInt("width", data.width)
|
|
169
|
+
map.putInt("height", data.height)
|
|
170
|
+
|
|
171
|
+
promise.resolve(map)
|
|
113
172
|
|
|
114
173
|
}
|
|
115
174
|
|
|
116
175
|
@ReactMethod
|
|
117
176
|
fun getSafeArea(promise: Promise) {
|
|
118
177
|
|
|
119
|
-
promise.resolve(getSafeAreaMap())
|
|
120
|
-
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
private fun getSafeAreaMap(): WritableMap {
|
|
124
|
-
|
|
125
178
|
val map = Arguments.createMap()
|
|
126
|
-
|
|
127
|
-
map.putInt("right", 0)
|
|
128
|
-
map.putInt("bottom", 0)
|
|
129
|
-
map.putInt("left", 0)
|
|
130
|
-
|
|
131
|
-
// P 之前的版本都是厂商私有实现,懒得折腾了
|
|
132
|
-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
|
133
|
-
currentActivity?.window?.decorView?.rootWindowInsets?.displayCutout?.let {
|
|
134
|
-
map.putInt("top", (it.safeInsetTop / density).toInt())
|
|
135
|
-
map.putInt("right", (it.safeInsetRight / density).toInt())
|
|
136
|
-
map.putInt("bottom", (it.safeInsetBottom / density).toInt())
|
|
137
|
-
map.putInt("left", (it.safeInsetLeft / density).toInt())
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
return map
|
|
179
|
+
val data = getSafeAreaData()
|
|
142
180
|
|
|
143
|
-
|
|
181
|
+
map.putInt("top", data.top)
|
|
182
|
+
map.putInt("right", data.right)
|
|
183
|
+
map.putInt("bottom", data.bottom)
|
|
184
|
+
map.putInt("left", data.left)
|
|
144
185
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
val display = (reactContext.getSystemService(WINDOW_SERVICE) as WindowManager).defaultDisplay
|
|
148
|
-
val size = Point()
|
|
149
|
-
|
|
150
|
-
display.getSize(size)
|
|
186
|
+
promise.resolve(map)
|
|
151
187
|
|
|
152
|
-
|
|
188
|
+
}
|
|
153
189
|
|
|
190
|
+
private fun getScreenSizeData(): Size {
|
|
191
|
+
// 跟 ios 保持一致,获取的是物理屏尺寸
|
|
192
|
+
var screenWidth = 0
|
|
193
|
+
var screenHeight = 0
|
|
194
|
+
|
|
195
|
+
val windowManager = reactContext.getSystemService(WindowManager::class.java)
|
|
196
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
|
197
|
+
// Android 11+
|
|
198
|
+
val windowMetrics = windowManager.currentWindowMetrics
|
|
199
|
+
screenWidth = windowMetrics.bounds.width() // 屏幕总宽度(像素)
|
|
200
|
+
screenHeight = windowMetrics.bounds.height() // 屏幕总高度(像素)
|
|
201
|
+
} else {
|
|
202
|
+
// 旧版本兼容方案(Android 5.0~10)
|
|
203
|
+
val point = Point()
|
|
204
|
+
windowManager.defaultDisplay.getRealSize(point)
|
|
205
|
+
screenWidth = point.x
|
|
206
|
+
screenHeight = point.y
|
|
207
|
+
}
|
|
208
|
+
return Size(toReactUnit(screenWidth), toReactUnit(screenHeight))
|
|
154
209
|
}
|
|
155
210
|
|
|
156
|
-
private fun
|
|
211
|
+
private fun getStatusBarHeightData(): Int {
|
|
212
|
+
return toReactUnit(statusBarHeight)
|
|
213
|
+
}
|
|
157
214
|
|
|
158
|
-
|
|
159
|
-
|
|
215
|
+
private fun getNavigationBarHeightData(): Int {
|
|
216
|
+
return toReactUnit(navigationBarHeight)
|
|
217
|
+
}
|
|
160
218
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
|
|
165
|
-
try {
|
|
166
|
-
size.x = Display::class.java.getMethod("getRawWidth").invoke(display) as Int
|
|
167
|
-
size.y = Display::class.java.getMethod("getRawHeight").invoke(display) as Int
|
|
168
|
-
} catch (e: Exception) {
|
|
169
|
-
}
|
|
170
|
-
}
|
|
219
|
+
private fun getSafeAreaData(): Rect {
|
|
220
|
+
return Rect(toReactUnit(cutoutLeft), toReactUnit(statusBarHeight), toReactUnit(cutoutRight), toReactUnit(cutoutBottom))
|
|
221
|
+
}
|
|
171
222
|
|
|
172
|
-
|
|
223
|
+
private fun toReactUnit(value: Int): Int {
|
|
224
|
+
return (value / density).toInt()
|
|
225
|
+
}
|
|
173
226
|
|
|
227
|
+
private fun sendEvent(eventName: String, params: WritableMap) {
|
|
228
|
+
reactContext
|
|
229
|
+
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
|
|
230
|
+
.emit(eventName, params)
|
|
174
231
|
}
|
|
175
232
|
|
|
176
|
-
}
|
|
233
|
+
}
|
package/index.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
|
|
2
|
-
import { NativeModules } from 'react-native'
|
|
2
|
+
import { NativeEventEmitter, NativeModules } from 'react-native'
|
|
3
3
|
|
|
4
4
|
const { RNTDimension } = NativeModules
|
|
5
5
|
|
|
6
|
+
const eventEmitter = new NativeEventEmitter(RNTDimension)
|
|
7
|
+
|
|
6
8
|
export const statusBarHeight = RNTDimension.STATUS_BAR_HEIGHT
|
|
7
9
|
|
|
8
10
|
export const navigationBarHeight = RNTDimension.NAVIGATION_BAR_HEIGHT
|
|
@@ -19,6 +21,10 @@ export const safeArea = {
|
|
|
19
21
|
left: RNTDimension.SAFE_AREA_LEFT,
|
|
20
22
|
}
|
|
21
23
|
|
|
24
|
+
export function init() {
|
|
25
|
+
return RNTDimension.init()
|
|
26
|
+
}
|
|
27
|
+
|
|
22
28
|
export function getStatusBarHeight() {
|
|
23
29
|
return RNTDimension.getStatusBarHeight()
|
|
24
30
|
}
|
|
@@ -33,4 +39,8 @@ export function getScreenSize() {
|
|
|
33
39
|
|
|
34
40
|
export function getSafeArea() {
|
|
35
41
|
return RNTDimension.getSafeArea()
|
|
36
|
-
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function addListener(type, listener) {
|
|
45
|
+
return eventEmitter.addListener(type, listener)
|
|
46
|
+
}
|
|
@@ -68,6 +68,10 @@ static NSDictionary* getSafeArea() {
|
|
|
68
68
|
|
|
69
69
|
RCT_EXPORT_MODULE(RNTDimension);
|
|
70
70
|
|
|
71
|
+
RCT_EXPORT_METHOD(init:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) {
|
|
72
|
+
resolve(@{});
|
|
73
|
+
}
|
|
74
|
+
|
|
71
75
|
RCT_EXPORT_METHOD(getStatusBarHeight:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) {
|
|
72
76
|
|
|
73
77
|
resolve(@{
|