@@ -24,22 +24,41 @@ import kotlinx.coroutines.delay
2424import kotlinx.coroutines.withContext
2525import java.util.Collections
2626
27+ /* *
28+ * 浮窗管理器
29+ * 提供全局浮窗的添加、删除、显示、隐藏等管理功能
30+ */
2731object 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