Android懸浮窗的實現(xiàn)步驟
最近想做一個懸浮窗秒表的功能,所以看下懸浮窗具體的實現(xiàn)步驟
1、初識WindowManager
實現(xiàn)懸浮窗主要用到的是WindowManager
@SystemService(Context.WINDOW_SERVICE)
public interface WindowManager extends ViewManager {
...
}WindowManager是接口類,繼承自接口ViewManager,可以通過獲取WINDOW_SERVICE系統(tǒng)服務(wù)得到。而ViewManager接口有addView方法,我們就是通過這個方法將懸浮窗控件加入到屏幕中去。
2、設(shè)置權(quán)限
當API Level >= 23,顯示懸浮窗功能,需要在清單文件AndroidManifest.xml中添加SYSTEM_ALERT_WINDOW權(quán)限,添加這個權(quán)限后才可以在其他應(yīng)用上顯示懸浮窗。
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
通過getSystemService方式獲取WindowManager
val windowManager = getSystemService(WINDOW_SERVICE) as WindowManager
3、LayoutParam設(shè)置
WindowManager的addView方法有兩個參數(shù),一個是需要加入的控件對象,另一個參數(shù)是WindowManager.LayoutParams對象。
// view – The view to be added to this window. // params – The LayoutParams to assign to view. public void addView(View view, ViewGroup.LayoutParams params);
其中LayoutParams的type變量,這個變量是用來指定窗口的類型。在設(shè)置這個變量時,需要對不同版本的Android系統(tǒng)進行適配。
val layoutParams = WindowManager.LayoutParams()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
layoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
} else {
layoutParams.type = WindowManager.LayoutParams.TYPE_PHONE
}在Android 8.0之前,懸浮窗口設(shè)置可以為TYPE_PHONE,這種類型是用于提供用戶交互操作的非應(yīng)用窗口,現(xiàn)在這個類型已棄用了。
而Android 8.0對系統(tǒng)和API行為做了修改,包括使用SYSTEM_ALERT_WINDOW權(quán)限的應(yīng)用無法再使用窗口類型來在其他應(yīng)用和窗口上方顯示提醒窗口:
TYPE_PHONE(已棄用)
TYPE_PRIORITY_PHONE
TYPE_SYSTEM_ALERT
TYPE_SYSTEM_OVERLAY
TYPE_SYSTEM_ERROR
如果需要實現(xiàn)在其他應(yīng)用和窗口上方顯示提醒窗口,那么必須該為TYPE_APPLICATION_OVERLAY的新類型。
4、檢測是否允許開啟懸浮窗
開啟懸浮窗之前,還需要檢測用戶是否允許開啟懸浮窗,通過系統(tǒng)提供的canDrawOverlays來檢測
//檢測是否允許開啟懸浮窗 Settings.canDrawOverlays(context)
如果沒有允許開啟,需要跳轉(zhuǎn)開啟頁面,讓用戶允許開啟懸浮窗
startActivity(Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION))
5、FloatingService服務(wù)
懸浮窗一直顯示在其他應(yīng)用上層,需要新建FloatingService服務(wù)類,用于處理懸浮窗相關(guān)邏輯。
class FloatingService : Service() {
override fun onCreate() {
super.onCreate()
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
showFloatingWindow();
return super.onStartCommand(intent, flags, startId)
}
override fun onBind(intent: Intent?): IBinder? {
return null
}
/**
* 顯示懸浮窗
*/
private fun showFloatingWindow() {
// 獲取WindowManager服務(wù)
val windowManager = getSystemService(WINDOW_SERVICE) as WindowManager
// 新建懸浮窗控件
val button = Button(applicationContext)
button.text = "Floating Window"
button.setBackgroundColor(Color.BLUE)
// 設(shè)置LayoutParam
val layoutParams = WindowManager.LayoutParams()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
layoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
} else {
layoutParams.type = WindowManager.LayoutParams.TYPE_PHONE
}
layoutParams.format = PixelFormat.RGBA_8888
layoutParams.flags =
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL or WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
layoutParams.width = ActionBar.LayoutParams.WRAP_CONTENT
layoutParams.height = ActionBar.LayoutParams.WRAP_CONTENT
layoutParams.x = 300
layoutParams.y = 300
// 將懸浮窗控件添加到WindowManager
windowManager.addView(button, layoutParams);
}
}6、啟動FloatingService
viewBinding.btnFloating.setOnClickListener {
if (Settings.canDrawOverlays(this)) {//檢測是否具有懸浮窗權(quán)限
startService(Intent(this,FloatingService::class.java))
} else {
startActivity(Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION));
}
}開啟效果如下:

7、增加拖動功能
懸浮窗顯示的位置可能會遮擋其他信息,這時就需要新增拖動功能,可以拖動到任何位置,實現(xiàn)的邏輯就是給布局View添加觸摸事件,根據(jù)觸摸和移動的位置來決定懸浮窗顯示的位置。
var x = 0
var y = 0
button.setOnTouchListener { view, event ->
when (event.action) {
MotionEvent.ACTION_DOWN -> {
x = event.rawX.toInt()
y = event.rawY.toInt()
}
MotionEvent.ACTION_MOVE -> {
val nowX = event.rawX.toInt()
val nowY = event.rawY.toInt()
val movedX = nowX - x
val movedY = nowY - y
x = nowX
y = nowY
layoutParams.x = layoutParams.x + movedX
layoutParams.y = layoutParams.y + movedY
// 更新懸浮窗控件布局
windowManager.updateViewLayout(view, layoutParams)
}
else -> {}
}
false
}到此這篇關(guān)于Android懸浮窗的實現(xiàn)的文章就介紹到這了,更多相關(guān)Android懸浮窗內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android進階CameraX與Camera2使用比對詳解
這篇文章主要為大家介紹了Android進階CameraX與Camera2使用比示例對詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-01-01
Android實現(xiàn)圖片自動切換功能(實例代碼詳解)
這篇文章主要介紹了Android實現(xiàn)圖片自動切換功能,本文通過實例代碼給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下2020-02-02
uni-app Android離線打包的多環(huán)境配置方案
本文介紹uni-app項目Android多環(huán)境打包方案,通過productFlavors區(qū)分包名和key、利用flavor覆蓋資源和資產(chǎn)、規(guī)范變體命名和產(chǎn)物命名等方法,確保開發(fā)、測試、線上包穩(wěn)定并行,發(fā)版更可控,需要的朋友可以參考下2026-04-04
Android自定義控件EditText實現(xiàn)清除和抖動功能
這篇文章主要為大家詳細介紹了Android自定義控件EditText實現(xiàn)清除和抖動功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-12-12
Android系統(tǒng)的五種數(shù)據(jù)存儲形式實例(二)
Android系統(tǒng)有五種數(shù)據(jù)存儲形式,分別是文件存儲、SP存儲、數(shù)據(jù)庫存儲、contentprovider 內(nèi)容提供者、網(wǎng)絡(luò)存儲。本文介紹了Android系統(tǒng)的五種數(shù)據(jù)存儲形式,有興趣的可以了解一下。2016-12-12

