最近的一个项目里面需要使用锁屏页,实现的方法是用Activity
来伪装锁屏页,网上对这个方面的教程不多,大多数都是基于这篇文章,但是这篇文章有些细节点没有关注到,所以我在这里进行一些完善和补充,并把整个完整的过程写出来,供大家参考。
我们怎么做到锁屏的时候显示Activity
首先我们在这里创建一个Activity
,名字叫作LockScreenActivity
,然后我们来着手解决如何知道屏幕锁屏,思路可以看下面的流程图(这里借鉴QQ音乐的资料图)😁。
通过上图的流程可知屏幕关闭会发出一个叫作SCREEN_OFF
的系统广播,然后在Service
里面去监听这个系统广播,一旦App
启动,就启动这个Service
,然后一旦系统发出SCREEN_OFF
的广播,Receiver
就会接受到。
接着,我们按上面得出来的步骤,来完成程序的设计,首先new
一个Service
,这个Service
主要用来注册一个广播来监听SCREEN_OFF
这一系统广播,但在此之前我们还得创建一个广播的接受器(LockScreenReceiver
),其具体代码如下:
1 | public class LockScreenReceiver extends BroadcastReceiver { |
接着我们来创建用来注册监听广播的Service
(LockService
),其具体代码如下:
1 | public class LockService extends Service { |
当然注意了,在Service
被Destroy
的时候别忘了调用unregisterReceiver
来解除注册的广播。
我们只用在App启动的时候来启动这个服务,具体的代码如下:
1 | Intent intent = new Intent(this,LockService.class); |
当然上面的这一些还不够,我们要加一个权限,加上使锁屏失效(当然如果你设置了密码是不能失效的)。
1 | <uses-permission android:name="android.permission.DISABLE_KEYGUARD"/> |
同时你还得在Activity
里面设置一大堆属性:
1 | getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); |
这上面的属性分别设置使布局锁屏的时候出现,去掉锁屏,全屏,去掉导航栏和状态栏等等,具体一些属性的效果有些我也说不清楚,大家有兴趣的可以自行Google
一下。
实现锁屏的滑动效果
这里我们定义一个UnderView
来处理滑动逻辑。在这里盗一张QQ音乐团队的图,我觉得它的图解释的很清楚。
这里把视图分为MoveView
和UnderView
,废话不多说,上完整的代码:
1 | public class UnderView extends View { |
接下来我们来分析一下这个自定义View
,在handleMoveView
里面处理当手在屏幕上面滑动时mMoveView
随着手指滑动,doTriggerEvent
是处理松开手指时mMoveView
的反应,当滑动的距离不超过屏幕的40%时,mMoveView
返回到原处,超过了就直接划过去。
当然重点是要在UnderView
里面获取mMoveView
和设置OnSlideFinishListener
来处理当锁屏划开的时候finish
掉当前的Activity
。
细节处理
完成了上面的两步,大家可以运行一下程序,这时候会出现两个问题,滑动时,滑动过的背景不是透明的,如果你没退出Activity
又反复打开屏幕关闭屏幕,会有多个LockScreenActivity
在Activity
栈里面。
首先第二个问题比较好解决,直接在Manifest里面指定LockScreenActivity
的launchMode
为singleInstance
,即单例模式。这样栈里面就只会有一个LockScreenActivity
存在。
第二个问题就需要设置Activity
的背景为透明色,接着在Activity
的theme
,我们需要在style
文件里为LockScreenActivity
指定一个theme,具体的代码如下:
1 | <style name="LockScreenTheme" parent="AppTheme"> |
这里为止,我们就可以实现一个完整的锁屏页了(^-^)。