最近的一个项目里面需要使用锁屏页,实现的方法是用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"> |
这里为止,我们就可以实现一个完整的锁屏页了(^-^)。