-
-
Notifications
You must be signed in to change notification settings - Fork 153
Expand file tree
/
Copy pathStatusBarManagerCompatModuleImpl.kt
More file actions
140 lines (117 loc) · 4.27 KB
/
StatusBarManagerCompatModuleImpl.kt
File metadata and controls
140 lines (117 loc) · 4.27 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
package com.reactnativekeyboardcontroller.modules.statusbar
import android.animation.ArgbEvaluator
import android.animation.ValueAnimator
import android.annotation.SuppressLint
import android.app.Activity
import android.os.Build
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.WindowInsetsControllerCompat
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.bridge.UiThreadUtil
import com.reactnativekeyboardcontroller.BuildConfig
import com.reactnativekeyboardcontroller.log.Logger
import com.reactnativekeyboardcontroller.views.EdgeToEdgeReactViewGroup
import com.reactnativekeyboardcontroller.views.EdgeToEdgeViewRegistry
import java.lang.ref.WeakReference
private val TAG = StatusBarManagerCompatModuleImpl::class.qualifiedName
class StatusBarManagerCompatModuleImpl(
private val mReactContext: ReactApplicationContext,
) {
private var original = StatusBarModuleProxy(mReactContext)
private var controller: WindowInsetsControllerCompat? = null
private var lastActivity = WeakReference<Activity?>(null)
/**
* This method always uses new API, because original implementation may mess up system insets
* and they will never be restored properly (even if you enabled edge-to-edge mode etc.)
*/
fun setHidden(hidden: Boolean) {
UiThreadUtil.runOnUiThread {
if (hidden) {
getController()?.hide(WindowInsetsCompat.Type.statusBars())
} else {
getController()?.show(WindowInsetsCompat.Type.statusBars())
}
}
}
@SuppressLint("ObsoleteSdkInt")
@Suppress("detekt:ReturnCount")
fun setColor(
color: Int,
animated: Boolean,
) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (!isEnabled()) {
return original.setColor(color.toDouble(), animated)
}
if (BuildConfig.IS_EDGE_TO_EDGE_ENABLED) {
Logger.w(TAG, "StatusBarModule: Ignored status bar change, current activity is edge-to-edge.")
return
}
val activity = mReactContext.currentActivity
if (activity == null) {
Logger.w(
TAG,
"StatusBarManagerCompatModule: Ignored status bar change, current activity is null.",
)
return
}
UiThreadUtil.runOnUiThread {
val window = activity.window
if (animated) {
val curColor: Int = window.statusBarColor
val colorAnimation = ValueAnimator.ofObject(ArgbEvaluator(), curColor, color)
colorAnimation.addUpdateListener { animator ->
window.statusBarColor = animator.animatedValue as Int
}
colorAnimation.setDuration(DEFAULT_ANIMATION_TIME).startDelay = 0
colorAnimation.start()
} else {
window.statusBarColor = color
}
}
}
}
fun setTranslucent(translucent: Boolean) {
if (!isEnabled()) {
return original.setTranslucent(translucent)
}
if (BuildConfig.IS_EDGE_TO_EDGE_ENABLED) {
Logger.w(TAG, "StatusBarModule: Ignored status bar change, current activity is edge-to-edge.")
return
}
UiThreadUtil.runOnUiThread {
view()?.forceStatusBarTranslucent(translucent)
}
}
fun setStyle(style: String) {
if (!isEnabled()) {
return original.setStyle(style)
}
UiThreadUtil.runOnUiThread {
getController()?.isAppearanceLightStatusBars = style == "dark-content"
}
}
fun getConstants(): MutableMap<String, Any>? = original.getConstants()
private fun getController(): WindowInsetsControllerCompat? {
val activity = mReactContext.currentActivity
if (this.controller == null || activity != lastActivity.get()) {
if (activity == null) {
Logger.w(
TAG,
"StatusBarManagerCompatModule: can not get `WindowInsetsControllerCompat` because current activity is null.",
)
return this.controller
}
val window = activity.window
lastActivity = WeakReference(activity)
this.controller = WindowInsetsControllerCompat(window, window.decorView)
}
return this.controller
}
private fun isEnabled(): Boolean = view()?.active ?: false
private fun view(): EdgeToEdgeReactViewGroup? = EdgeToEdgeViewRegistry.get()
companion object {
const val NAME = "StatusBarManager"
private const val DEFAULT_ANIMATION_TIME = 300L
}
}