相较于 iOS,安卓在 Q 以前并无原生支持护眼模式,因此咱们得本身实现一套。java
其实网上代码也挺多的,甚至有些公司的产品就是这个功能。app
先来说下实现的思路,不想先听思路的能够直接跳到代码那块,代码也不难。ide
Window
上覆盖一个 View
,作到跨 App 及状态栏和导航栏总体覆盖建立一个 EyeCareService
,该 Service 用来添加 Window 上的滤光层ui
class EyeCareService : Service() {
private lateinit var windowManager: WindowManager
private lateinit var coverLayout: FrameLayout
override fun onBind(intent: Intent?): IBinder? {
return null
}
override fun onCreate() {
super.onCreate()
windowManager = getSystemService(Context.WINDOW_SERVICE) as WindowManager
val params = WindowManager.LayoutParams().apply {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
this.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY or
WindowManager.LayoutParams.TYPE_STATUS_BAR
} else {
this.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY
}
this.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL or
WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE or
WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS or
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN or
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
this.format = PixelFormat.TRANSLUCENT
}
windowManager.defaultDisplay.apply {
params.gravity = Gravity.START or Gravity.TOP
val point = Point()
this.getRealSize(point)
params.width = point.x
params.height = point.y
}
coverLayout = FrameLayout(this)
coverLayout.setBackgroundColor(Utils.getColor(30))
windowManager.addView(coverLayout, params)
}
override fun onDestroy() {
windowManager.removeViewImmediate(coverLayout)
super.onDestroy()
}
}
复制代码
滤光层设置获取颜色方法的方法,通常传入 30 便可this
/** * 过滤蓝光 * * @param blueFilterPercent 蓝光过滤比例[10-80] */
public static @ColorInt
int getColor(int blueFilterPercent) {
int realFilter = blueFilterPercent;
if (realFilter < 10) {
realFilter = 10;
} else if (realFilter > 80) {
realFilter = 80;
}
int a = (int) (realFilter / 80f * 180);
int r = (int) (200 - (realFilter / 80f) * 190);
int g = (int) (180 - (realFilter / 80f) * 170);
int b = (int) (60 - realFilter / 80f * 60);
return Color.argb(a, r, g, b);
}
复制代码
activity 中调用启动方法spa
private fun openEyeCareMode() {
if (Build.VERSION.SDK_INT >= 23) {
if (Settings.canDrawOverlays(this)) { //有悬浮窗权限开启服务绑定 绑定权限
val intent = Intent(this, EyeCareService::class.java)
startService(intent)
} else { //没有悬浮窗权限,去开启悬浮窗权限
try {
val intent = Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION)
startActivityForResult(intent, OVERLAY_PERMISSION_REQ_CODE)
} catch (e: Exception) {
e.printStackTrace()
}
}
} else { //默认有悬浮窗权限 可是 华为, 小米,oppo等手机会有本身的一套Android6.0如下 会有本身的一套悬浮窗权限管理 也须要作适配
val intent = Intent(this, EyeCareService::class.java)
startService(intent)
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == OVERLAY_PERMISSION_REQ_CODE) {
if (Build.VERSION.SDK_INT >= 23) {
if (!Settings.canDrawOverlays(this)) {
//权限授予失败,没法开启悬浮窗
return
} else {
//权限授予成功
}//有悬浮窗权限开启服务绑定 绑定权限
}
val intent = Intent(this, EyeCareService::class.java)
startService(intent)
}
}
复制代码
剩下一些考虑点,在这我就不贴代码了,稍微讲下code