Skip to content

Commit 19d0336

Browse files
committed
feat(window): 添加浮窗管理器和浮窗包装类
- 新增 AssistsWindowManager 对象,提供浮窗管理功能 - 新增 AssistsWindowWrapper 类,封装浮窗行为 - 实现了浮窗的添加、删除、显示、隐藏等操作 - 支持浮窗的拖动、缩放和关闭功能 - 增加了临时 Toast 样式浮窗功能
1 parent d45eff9 commit 19d0336

File tree

2 files changed

+163
-7
lines changed

2 files changed

+163
-7
lines changed

assists/src/main/java/com/ven/assists/window/AssistsWindowManager.kt

Lines changed: 108 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,22 +24,41 @@ import kotlinx.coroutines.delay
2424
import kotlinx.coroutines.withContext
2525
import java.util.Collections
2626

27+
/**
28+
* 浮窗管理器
29+
* 提供全局浮窗的添加、删除、显示、隐藏等管理功能
30+
*/
2731
object AssistsWindowManager {
32+
/** 系统窗口管理器 */
2833
private lateinit var windowManager: WindowManager
34+
/** 显示度量信息 */
2935
private lateinit var mDisplayMetrics: DisplayMetrics
36+
/** 浮窗视图列表,使用线程安全的集合 */
3037
private val viewList = Collections.synchronizedList(arrayListOf<ViewWrapper>())
3138

39+
/**
40+
* 初始化窗口管理器
41+
* @param accessibilityService 无障碍服务实例
42+
*/
3243
fun init(accessibilityService: AccessibilityService) {
3344
windowManager = accessibilityService.getSystemService(Context.WINDOW_SERVICE) as WindowManager
3445
mDisplayMetrics = DisplayMetrics()
3546
windowManager.defaultDisplay.getMetrics(mDisplayMetrics)
3647
}
3748

49+
/**
50+
* 获取系统窗口管理器实例
51+
* @return WindowManager实例,如果未初始化则返回null
52+
*/
3853
fun getWindowManager(): WindowManager? {
3954
AssistsService.instance?.getSystemService(Context.WINDOW_SERVICE)?.let { return (it as WindowManager) }
4055
return null
4156
}
4257

58+
/**
59+
* 创建默认的浮窗布局参数
60+
* @return 配置好的WindowManager.LayoutParams实例
61+
*/
4362
fun createLayoutParams(): WindowManager.LayoutParams {
4463
val layoutParams = WindowManager.LayoutParams()
4564
layoutParams.flags = (WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
@@ -59,6 +78,10 @@ object AssistsWindowManager {
5978
return layoutParams
6079
}
6180

81+
/**
82+
* 隐藏所有浮窗
83+
* @param isTouchable 隐藏后是否可触摸,默认为true
84+
*/
6285
suspend fun hideAll(isTouchable: Boolean = true) {
6386
withContext(Dispatchers.Main) {
6487
viewList.forEach {
@@ -72,6 +95,10 @@ object AssistsWindowManager {
7295
}
7396
}
7497

98+
/**
99+
* 隐藏最顶层浮窗
100+
* @param isTouchable 隐藏后是否可触摸,默认为true
101+
*/
75102
suspend fun hideTop(isTouchable: Boolean = true) {
76103
withContext(Dispatchers.Main) {
77104
viewList.lastOrNull()?.let {
@@ -85,6 +112,10 @@ object AssistsWindowManager {
85112
}
86113
}
87114

115+
/**
116+
* 显示最顶层浮窗
117+
* @param isTouchable 显示后是否可触摸,默认为true
118+
*/
88119
suspend fun showTop(isTouchable: Boolean = true) {
89120
withContext(Dispatchers.Main) {
90121
viewList.lastOrNull()?.let {
@@ -98,6 +129,10 @@ object AssistsWindowManager {
98129
}
99130
}
100131

132+
/**
133+
* 显示所有浮窗
134+
* @param isTouchable 显示后是否可触摸,默认为true
135+
*/
101136
suspend fun showAll(isTouchable: Boolean = true) {
102137
withContext(Dispatchers.Main) {
103138
viewList.forEach {
@@ -111,12 +146,24 @@ object AssistsWindowManager {
111146
}
112147
}
113148

114-
149+
/**
150+
* 添加浮窗包装器
151+
* @param windowWrapper 浮窗包装器
152+
* @param isStack 是否堆叠显示,默认为true
153+
* @param isTouchable 是否可触摸,默认为true
154+
*/
115155
fun add(windowWrapper: AssistsWindowWrapper?, isStack: Boolean = true, isTouchable: Boolean = true) {
116156
windowWrapper ?: return
117157
add(view = windowWrapper.getView(), layoutParams = windowWrapper.wmlp, isStack = isStack, isTouchable = isTouchable)
118158
}
119159

160+
/**
161+
* 添加浮窗视图
162+
* @param view 要添加的视图
163+
* @param layoutParams 布局参数
164+
* @param isStack 是否堆叠显示,默认为true
165+
* @param isTouchable 是否可触摸,默认为true
166+
*/
120167
fun add(view: View?, layoutParams: WindowManager.LayoutParams = createLayoutParams(), isStack: Boolean = true, isTouchable: Boolean = true) {
121168
view ?: return
122169
if (!isStack) {
@@ -131,15 +178,28 @@ object AssistsWindowManager {
131178
viewList.add(ViewWrapper(view, layoutParams))
132179
}
133180

181+
/**
182+
* 添加浮窗并隐藏之前的浮窗
183+
* @param view 要添加的视图
184+
* @param params 布局参数
185+
*/
134186
fun push(view: View?, params: WindowManager.LayoutParams = createLayoutParams()) {
135187
add(view, params, isStack = false)
136188
}
137189

190+
/**
191+
* 移除最顶层浮窗并显示下一个浮窗
192+
* @param showTop 是否显示下一个浮窗,默认为true
193+
*/
138194
suspend fun pop(showTop: Boolean = true) {
139195
viewList.lastOrNull()?.let { removeView(it.view) }
140196
if (showTop) showTop()
141197
}
142198

199+
/**
200+
* 移除指定浮窗
201+
* @param view 要移除的视图
202+
*/
143203
fun removeView(view: View?) {
144204
view ?: return
145205
try {
@@ -154,20 +214,35 @@ object AssistsWindowManager {
154214
}
155215
}
156216

217+
/**
218+
* 检查指定视图是否已添加为浮窗
219+
* @param view 要检查的视图
220+
* @return 是否存在于浮窗列表中
221+
*/
157222
fun contains(view: View?): Boolean {
158223
view ?: return false
159224
return viewList.find {
160225
return@find view == it.view
161226
} != null
162227
}
163228

229+
/**
230+
* 检查指定浮窗包装器是否已添加
231+
* @param wrapper 要检查的浮窗包装器
232+
* @return 是否存在于浮窗列表中
233+
*/
164234
fun contains(wrapper: AssistsWindowWrapper?): Boolean {
165235
wrapper ?: return false
166236
return viewList.find {
167237
return@find wrapper.getView() == it.view
168238
} != null
169239
}
170240

241+
/**
242+
* 检查指定浮窗是否可见
243+
* @param view 要检查的视图
244+
* @return 是否可见
245+
*/
171246
fun isVisible(view: View): Boolean {
172247
return viewList.find {
173248
return@find view == it.view
@@ -176,65 +251,93 @@ object AssistsWindowManager {
176251
} ?: false
177252
}
178253

254+
/**
255+
* 更新浮窗布局
256+
* @param view 要更新的视图
257+
* @param params 新的布局参数
258+
*/
179259
suspend fun updateViewLayout(view: View, params: ViewGroup.LayoutParams) {
180260
runMain { windowManager.updateViewLayout(view, params) }
181261
}
182262

263+
/**
264+
* 设置所有浮窗为可触摸状态
265+
*/
183266
suspend fun touchableByAll() {
184267
viewList.forEach { it.touchableByWrapper() }
185268
}
186269

270+
/**
271+
* 设置所有浮窗为不可触摸状态
272+
*/
187273
suspend fun nonTouchableByAll() {
188274
viewList.forEach { it.nonTouchableByWrapper() }
189275
}
190276

277+
/**
278+
* 设置布局参数为可触摸状态
279+
*/
191280
fun WindowManager.LayoutParams.touchableByLayoutParams() {
192281
flags = (WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
193282
or WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL or WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
194283
or WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN)
195284
}
196285

286+
/**
287+
* 设置布局参数为不可触摸状态
288+
*/
197289
fun WindowManager.LayoutParams.nonTouchableByLayoutParams() {
198290
flags = (WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or
199291
WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE or WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS or
200292
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL or WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN)
201293
}
202294

295+
/**
296+
* 设置浮窗包装器为可触摸状态
297+
*/
203298
suspend fun ViewWrapper.touchableByWrapper() {
204299
layoutParams.touchableByLayoutParams()
205300
updateViewLayout(view, layoutParams)
206301
}
207302

303+
/**
304+
* 设置浮窗包装器为不可触摸状态
305+
*/
208306
suspend fun ViewWrapper.nonTouchableByWrapper() {
209307
layoutParams.nonTouchableByLayoutParams()
210308
updateViewLayout(view, layoutParams)
211309
}
212310

311+
/**
312+
* 显示一个临时的Toast样式浮窗
313+
* @param delay 显示时长,默认2000毫秒
314+
*/
213315
fun String.overlayToast(delay: Long = 2000) {
214316
AssistsService.instance?.let {
215317
CoroutineWrapper.launch(isMain = true) {
216318
val textView = TextView(it).apply {
217319
text = this@overlayToast
218320
setTextColor(Color.WHITE)
219321
setPadding(SizeUtils.dp2px(10f))
220-
// setBackgroundColor(Color.BLACK)
221322
}
222323
val assistsWindowWrapper = AssistsWindowWrapper(textView, wmLayoutParams = createLayoutParams().apply {
223324
width = -2
224325
height = -2
225326
}).apply {
226327
showOption = false
227328
initialCenter = true
228-
// showBackground = false
229329
}
230330
add(assistsWindowWrapper, isTouchable = false)
231331
runIO { delay(delay) }
232332
removeView(assistsWindowWrapper.getView())
233333
}
234334
}
235-
236335
}
237336

337+
/**
338+
* 浮窗视图包装类
339+
* @param view 浮窗视图
340+
* @param layoutParams 布局参数
341+
*/
238342
class ViewWrapper(val view: View, val layoutParams: WindowManager.LayoutParams)
239-
240343
}

0 commit comments

Comments
 (0)