golia-expo-utils 1.0.5 → 1.0.6

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.
@@ -1,5 +1,6 @@
1
1
  package expo.modules.goliaexpoutils.segmentedControl
2
2
 
3
+ // 引入扩展
3
4
  import android.annotation.SuppressLint
4
5
  import android.content.Context
5
6
  import android.view.ViewGroup
@@ -33,10 +34,7 @@ class ReactSegmentedControl(context: Context, appContext: AppContext) :
33
34
  private var isContentSet = false
34
35
 
35
36
  private val composeView = ComposeView(context).apply {
36
- layoutParams = ViewGroup.LayoutParams(
37
- LayoutParams.MATCH_PARENT,
38
- LayoutParams.MATCH_PARENT
39
- )
37
+ layoutParams = ViewGroup.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)
40
38
  setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnDetachedFromWindow)
41
39
  }
42
40
 
@@ -56,7 +54,7 @@ class ReactSegmentedControl(context: Context, appContext: AppContext) :
56
54
  addView(composeView)
57
55
  }
58
56
 
59
- // 3. 设置内容
57
+ // 3. 设置内容 (或复活)
60
58
  if (!isContentSet) {
61
59
  composeView.setContent {
62
60
  SegmentedControl(
@@ -89,13 +87,18 @@ class ReactSegmentedControl(context: Context, appContext: AppContext) :
89
87
  }
90
88
 
91
89
  override fun onDetachedFromWindow() {
90
+ // 4. 必须移除,防止后台 Crash
92
91
  if (composeView.parent == this) {
93
92
  removeView(composeView)
94
93
  }
94
+
95
+ // 5. 标记复活
96
+ isContentSet = false
97
+
95
98
  super.onDetachedFromWindow()
96
99
  }
97
100
 
98
- // 终极修正:手动接管布局
101
+ // 6. 手动布局修正
99
102
  override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
100
103
  super.onLayout(changed, left, top, right, bottom)
101
104
 
@@ -1,6 +1,6 @@
1
1
  package expo.modules.goliaexpoutils.waterView
2
2
 
3
- // 引入扩展
3
+ // 引入扩展函数
4
4
  import android.annotation.SuppressLint
5
5
  import android.content.Context
6
6
  import android.view.View
@@ -55,6 +55,7 @@ class ReactWaterView(context: Context, appContext: AppContext) : ExpoView(contex
55
55
  private val onPressOut by EventDispatcher()
56
56
  private val commandChannel = Channel<WaterCommand>(Channel.BUFFERED)
57
57
 
58
+ // 标记 Compose 内容是否已设置
58
59
  private var isContentSet = false
59
60
 
60
61
  private val childContainer = FrameLayout(context).apply {
@@ -63,6 +64,7 @@ class ReactWaterView(context: Context, appContext: AppContext) : ExpoView(contex
63
64
 
64
65
  private val composeView = ComposeView(context).apply {
65
66
  layoutParams = ViewGroup.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)
67
+ // 策略:Detach 时自动销毁 Composition 释放资源
66
68
  setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnDetachedFromWindow)
67
69
  }
68
70
 
@@ -74,15 +76,15 @@ class ReactWaterView(context: Context, appContext: AppContext) : ExpoView(contex
74
76
  override fun onAttachedToWindow() {
75
77
  super.onAttachedToWindow()
76
78
 
77
- // 1. 注入生命周期
79
+ // 1. 注入生命周期 (防崩关键)
78
80
  composeView.enforceLifecycle(context)
79
81
 
80
- // 2. 动态挂载 View
82
+ // 2. 动态挂载 View (此时 Activity 肯定存在)
81
83
  if (composeView.parent == null) {
82
84
  addView(composeView)
83
85
  }
84
86
 
85
- // 3. 设置内容
87
+ // 3. 设置内容 (或复活)
86
88
  if (!isContentSet) {
87
89
  composeView.setContent {
88
90
  WaterViewEntry(
@@ -90,6 +92,7 @@ class ReactWaterView(context: Context, appContext: AppContext) : ExpoView(contex
90
92
  props = props,
91
93
  commandFlow = commandChannel.receiveAsFlow(),
92
94
  onMoveDispatch = { x, y ->
95
+ // 空安全保护,防止 Bridgeless 模式下 NPE
93
96
  if (appContext.reactContext != null) {
94
97
  try {
95
98
  onMove(mapOf("x" to x, "y" to y))
@@ -104,38 +107,41 @@ class ReactWaterView(context: Context, appContext: AppContext) : ExpoView(contex
104
107
  isContentSet = true
105
108
  }
106
109
 
107
- // 4. 强制请求重新布局
110
+ // 4. 请求布局刷新
108
111
  requestLayout()
109
112
  }
110
113
 
111
114
  override fun onDetachedFromWindow() {
112
- // 必须移除,防止 Fabric 对离屏 View 进行测量导致崩溃
115
+ // 5. 必须移除!防止 RNSAC 等库导致 View 处于 detached 状态时被 Fabric 测量从而引发 Crash
113
116
  if (composeView.parent == this) {
114
117
  removeView(composeView)
115
118
  }
119
+
120
+ // 6. 标记复活:重置状态,允许下次 Attach 时重新 setContent (因为 DisposeOnDetached 已经销毁了引擎)
121
+ isContentSet = false
122
+
116
123
  super.onDetachedFromWindow()
117
124
  }
118
125
 
119
- // ✅ 终极修正:手动接管布局
120
- // 解决“View加上去了但是宽高为0不显示”的问题
126
+ // ✅ 7. 终极修正:手动接管布局
127
+ // 解决“View加上去了但是宽高为0不显示”的问题,无视 Fabric 的测量延迟
121
128
  override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
122
129
  super.onLayout(changed, left, top, right, bottom)
123
130
 
124
- // 如果 composeView 已经挂载,强行设置它的尺寸等于父容器
125
131
  if (composeView.parent == this) {
126
132
  val width = right - left
127
133
  val height = bottom - top
128
134
 
129
- // 1. 手动测量
135
+ // 强行设置 ComposeView 的大小等于父容器
130
136
  composeView.measure(
131
137
  MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
132
138
  MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)
133
139
  )
134
- // 2. 手动布局 (放在 (0,0) 位置)
135
140
  composeView.layout(0, 0, width, height)
136
141
  }
137
142
  }
138
143
 
144
+ // View 管理:确保 composeView 在底部,RN 子 View 在 childContainer 中
139
145
  override fun addView(child: View?, index: Int) {
140
146
  if (child == composeView) {
141
147
  super.addView(child, index)
@@ -157,7 +163,7 @@ class ReactWaterView(context: Context, appContext: AppContext) : ExpoView(contex
157
163
  if (childContainer.isNotEmpty()) {
158
164
  try {
159
165
  childContainer.removeViewAt(0)
160
- } catch (_: Throwable) {
166
+ } catch (_: Exception) {
161
167
  }
162
168
  }
163
169
  }
@@ -167,6 +173,7 @@ class ReactWaterView(context: Context, appContext: AppContext) : ExpoView(contex
167
173
  }
168
174
  }
169
175
 
176
+ // ... 下面的 Composable 代码保持不变 ...
170
177
  @Composable
171
178
  private fun WaterViewEntry(
172
179
  childContainer: FrameLayout,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "golia-expo-utils",
3
- "version": "1.0.5",
3
+ "version": "1.0.6",
4
4
  "description": "expo utils provided by golia.jp",
5
5
  "main": "build/index.js",
6
6
  "homepage": "https://expo.golia.jp/golia-expo-utils",