android系统锁屏详解

 谷歌的代码写的确实不错,我很幸运,一开始接触代码就赶上了谷歌这个开源的系统,让我的视野开阔了很多,也让我看到了优秀的代码工程师写到的代码。心怀感恩之心

                                                                                                                          ----题记

       我的有篇文章说了这个锁屏,但当时写的有点匆忙,没有细说。

                      AndroidICS4.0---->LockScreen锁屏流程【Android源码解析九】

        好了,开始正题,系统原声的锁屏界面,先来看一张图片:

                           

再上一张选中中间解锁的图片:
                           

这个圆形的解锁界面,左边是照相机,右边是解锁。下面我们来说说这个功能的具体实现,以及怎么修改成为上下左右四个方向的解锁界面。

Step1:先看LockScreen.java这个类加载的布局

[java]  view plain copy print ?
  1. inflater.inflate(R.layout.keyguard_screen_tab_unlock, thistrue);  

然后看对应的布局文件:

[html]  view plain copy print ?
  1. <com.android.internal.widget.multiwaveview.MultiWaveView  
  2.             android:id="@+id/unlock_widget"  
  3.             android:orientation="horizontal"  
  4.             android:layout_width="match_parent"  
  5.             android:layout_height="match_parent"  
  6.             android:layout_alignParentBottom="true"  
  7.   
  8.             android:targetDrawables="@array/lockscreen_targets_with_camera"  
  9.             android:targetDescriptions="@array/lockscreen_target_descriptions_with_camera"  
  10.             android:directionDescriptions="@array/lockscreen_direction_descriptions"  
  11.             android:handleDrawable="@drawable/ic_lockscreen_handle"  
  12.             android:waveDrawable="@drawable/ic_lockscreen_outerring"  
  13.             android:outerRadius="@dimen/multiwaveview_target_placement_radius"  
  14.             android:snapMargin="@dimen/multiwaveview_snap_margin"  
  15.             android:hitRadius="@dimen/multiwaveview_hit_radius"  
  16.             android:rightChevronDrawable="@drawable/ic_lockscreen_chevron_right"  
  17.             android:horizontalOffset="0dip"  
  18.             android:verticalOffset="60dip"  
  19.             android:feedbackCount="3"  
  20.             android:vibrationDuration="20"  
  21.             />  

下面我们来细细研究这些属性的含义:

        空行上面的属性都是android常用的一些属性,相信不用我说了;

   (1) android:targetDrawables="@array/lockscreen_targets_with_camera"

        这个属性表示目标的图标有几个,android默认是2个,不过我们可以修改这个array的值,我们看看这个值

         

[html]  view plain copy print ?
  1. <array name="lockscreen_targets_with_camera">  
  2.         <item>@drawable/ic_lockscreen_unlock</item>  
  3.         <item>@null</item>  
  4.         <item>@drawable/ic_lockscreen_camera</item>  
  5.         <item>@null</item>  
  6.     </array>  
        我相信你这样表示就应该明白该怎么修改了,这四个item分别对应圆圈的位置是右,上,左,下。

        想加几个图片,这个完全取决你自己,像小米的锁屏是四个,就是修改的这里。其实也没什么的,so easy!


  (2) android:targetDescriptions="@array/lockscreen_target_descriptions_with_camera"

        这个属性是对应的描述语言,

[html]  view plain copy print ?
  1. <array name="lockscreen_target_descriptions_with_camera">  
  2.         <item>@string/description_target_unlock</item>  
  3.         <item>@null</item>  
  4.         <item>@string/description_target_camera</item>  
  5.         <item>@null</item>  
  6.     </array>  
        你要是修改(1)的话,你也就相应的修改这些字符串就可以了。这个没什么可说的了。


  (3) android:directionDescriptions="@array/lockscreen_direction_descriptions"

       这个属性和(2)差不多,

[html]  view plain copy print ?
  1. <array name="lockscreen_direction_descriptions">  
  2.         <item>@string/description_direction_right</item>  
  3.         <item>@null</item>  
  4.         <item>@string/description_direction_left</item>  
  5.         <item>@null</item>  
  6.     </array>  
       这个表示的含义就是:对应四个位置,右,上,左,下这四个位置,提示语言:向哪个方向滑的问题。


  (4) android:handleDrawable="@drawable/ic_lockscreen_handle"
       这个属性对应的就是中间的那个解锁的图标,对应2张图片,一张选中的图片,一张默认没有选中的图片。

[html]  view plain copy print ?
  1. <selector xmlns:android="http://schemas.android.com/apk/res/android">  
  2.   
  3.     <item  
  4.         android:state_enabled="true"  
  5.         android:state_active="false"  
  6.         android:state_focused="false"  
  7.         android:drawable="@drawable/ic_lockscreen_handle_normal" />  
  8.   
  9.     <item  
  10.         android:state_enabled="true"  
  11.         android:state_active="true"  
  12.         android:state_focused="false"  
  13.         android:drawable="@drawable/ic_lockscreen_handle_pressed" />  
  14.   
  15. </selector>  

  (5) android:waveDrawable="@drawable/ic_lockscreen_outerring"

       这个属性对应的就是最外面的圆圈,是用shape属性画出来的。如:

[html]  view plain copy print ?
  1. <shape xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     android:shape="oval"  
  3.     >  
  4.     <size android:height="@dimen/keyguard_lockscreen_outerring_diameter" android:width="@dimen/keyguard_lockscreen_outerring_diameter" />  
  5.     <solid android:color="#00000000" />  
  6.     <stroke android:color="#1affffff" android:width="2dp" />  
  7. </shape>  
         以上的这些值都可以修改的。


  (6) android:outerRadius="@dimen/multiwaveview_target_placement_radius"

       这个属性表示默认圆的半径的大小;

[html]  view plain copy print ?
  1. <!-- Default target placement radius for MultiWaveView -->  
  2.     <dimen name="multiwaveview_target_placement_radius">135dip</dimen>  

  (7) android:snapMargin="@dimen/multiwaveview_snap_margin"

       这个属性是默认超越MultiWaveView捕捉到目标半径距离  

[html]  view plain copy print ?
  1. <!-- Default distance beyond which MultiWaveView snaps to the target radius -->  
  2.     <dimen name="multiwaveview_snap_margin">20dip</dimen>  

  (8) android:hitRadius="@dimen/multiwaveview_hit_radius"

      这个属性表示:每个单元目标预设距离,MultiWaveView认为选中

[html]  view plain copy print ?
  1. <!-- Default distance from each snap target that MultiWaveView considers a "hit" -->  
  2.     <dimen name="multiwaveview_hit_radius">60dip</dimen>  

  (9)android:rightChevronDrawable="@drawable/ic_lockscreen_chevron_right"

     这个属性表示:动态画的波纹的图片,这个属性共有四个,分别为,左,上,右,下四个方位的。

    

  (10) android:horizontalOffset="0dip"
         android:verticalOffset="60dip"

        这2个属性表示:距离圆圈水平和垂直的距离。你就明白为什么圆的下方少一块的原因了。


  (11) android:feedbackCount="3"

         表示:反馈数量3个;


  (12) android:vibrationDuration="20"

          表示:默认震动的时间,20毫秒;


更多属性请参考:core/res/res/values/attrs.xml中

[html]  view plain copy print ?
  1. <!-- =============================== -->  
  2.     <!-- MultiWaveView class attributes -->  
  3.     <!-- =============================== -->  
  4.     <eat-comment />  
  5.     <declare-styleable name="MultiWaveView">  
  6.         <!-- Reference to an array resource that be shown as targets around a circle. -->  
  7.         <attr name="targetDrawables" format="reference"/>  
  8.   
  9.         <!-- Reference to an array resource that be used as description for the targets around the circle. -->  
  10.         <attr name="targetDescriptions" format="reference"/>  
  11.   
  12.         <!-- Reference to an array resource that be used to announce the directions with targets around the circle. -->  
  13.         <attr name="directionDescriptions" format="reference"/>  
  14.   
  15.         <!-- Sets a drawable as the drag center. -->  
  16.         <attr name="handleDrawable" format="reference" />  
  17.   
  18.         <!-- Drawable to use for chevron animation on the left. May be null. -->  
  19.         <attr name="leftChevronDrawable" format="reference" />  
  20.   
  21.         <!-- Drawable to use for chevron animation on the right. May be null. -->  
  22.         <attr name="rightChevronDrawable" format="reference" />  
  23.   
  24.         <!-- Drawable to use for chevron animation on the top. May be null. -->  
  25.         <attr name="topChevronDrawable" format="reference" />  
  26.   
  27.         <!-- Drawable to use for chevron animation on the bottom. May be null. -->  
  28.         <attr name="bottomChevronDrawable" format="reference" />  
  29.   
  30.         <!-- Drawable to use for wave ripple animation. -->  
  31.         <attr name="waveDrawable" format="reference" />  
  32.   
  33.         <!-- Outer radius of target circle. Icons will be drawn on this circle. -->  
  34.         <attr name="outerRadius" format="dimension" />  
  35.   
  36.         <!-- Size of target radius. Points within this distance of target center is a "hit". -->  
  37.         <attr name="hitRadius" format="dimension" />  
  38.   
  39.         <!-- Tactile feedback duration for actions. Set to '0' for no vibration. -->  
  40.         <attr name="vibrationDuration" format="integer"/>  
  41.   
  42.         <!-- How close we need to be before snapping to a target. -->  
  43.         <attr name="snapMargin" format="dimension" />  
  44.   
  45.         <!-- Number of waves/chevrons to show in animation. -->  
  46.         <attr name="feedbackCount" format="integer" />  
  47.   
  48.         <!-- Used to shift center of pattern vertically. -->  
  49.         <attr name="verticalOffset" format="dimension" />  
  50.   
  51.         <!-- Used to shift center of pattern horizontally. -->  
  52.         <attr name="horizontalOffset" format="dimension" />  
  53.     </declare-styleable>  
这些属性能帮助你自定义自己的锁屏,如果不够的话,你也可以自己添加,然后在MultiWaveView.java中添加自己的方法或属性。


step2、介绍MultiWaveView.java这个类的方法,这个类除了锁屏用外,来电界面也用到了这个类,这就是谷歌的代码的高效的利用率,能写一个类,让2个,或多个界面利用。不得不再次佩服下谷歌的设计这个类的人。

  这个类的方法基本看名字就能看明白,先不写了,等有人留言了,再写出来,基本上ste1的属性配置好了,就能定制自己的锁屏界面了,想要更炫的效果,就只能修改MultiWaveView.java这个类了,像小米的锁屏界面就是修改了这个类,把自己的锁屏界面弄了个音乐播放器的view,可以和锁屏界面切换,其实小米就是修改了这个MultiWaveView.java就能达到想要的效果了。

上一张修改后的图片:

                                                                      


step 3 :我看到文章被推荐了,就再写点东西,分析以下MultiWaveView.java这个类,其实看java代码先看类的写法,看类继承了哪些类,实现了哪些接口,这样心理就有个大概了,大概就知道代码会走哪些方法了。

[java]  view plain copy print ?
  1. public class MultiWaveView extends View {  

其实这个类就是一个view类;


再来看看这个类中有没有内部类,或者内部接口什么的?

大致浏览以下发现这个类中有内部接口:

[java]  view plain copy print ?
  1. public interface OnTriggerListener {  
  2.         int NO_HANDLE = 0;  
  3.         int CENTER_HANDLE = 1;  
  4.         public void onGrabbed(View v, int handle);  
  5.         public void onReleased(View v, int handle);  
  6.         public void onTrigger(View v, int target);  
  7.         public void onGrabbedStateChange(View v, int handle);  
  8.     }  

通过单词的翻译大概就了解这些方法的作用了,

onGrabbed():抓起handler的触发方法;   onReleased():释放handler的触发方法;

onTrigger():触发方法,就是最后滑动到哪个app了,就会回调这个方法;

[java]  view plain copy print ?
  1. <span style="font-size:18px;">onGrabbedStateChange():这个就是触发状态改变的时候回调这个方法;</span>  

接口的方法都是回调方法,回调给实现这个接口的类的实现方法;


其实看到这里还有个重要的没有说到:就是状态,有如下几种状态;比如:空闲的状态,刚开始触发,move追踪,抢占触发,结束,对应的静态的final类型的常量如下:

[java]  view plain copy print ?
  1. private static final int STATE_IDLE = 0;  
  2.     private static final int STATE_FIRST_TOUCH = 1;  
  3.     private static final int STATE_TRACKING = 2;  
  4.     private static final int STATE_SNAP = 3;  
  5.     private static final int STATE_FINISH = 4;  
这几个状态搞明白了,就来看看触摸事件怎么处理的?


Step 4 :view的触摸事件可以通过onTouchEvent()来监听,来看看庐山真面目:

[java]  view plain copy print ?
  1. @Override  
  2.     public boolean onTouchEvent(MotionEvent event) {  
  3.         final int action = event.getAction();  
  4.   
  5.         boolean handled = false;  
  6.         switch (action) {  
  7.             case MotionEvent.ACTION_DOWN:  
  8.                 Xlog.i(TAG,"ACTION_DOWN");   
  9.                 handleDown(event);  
  10.                 handled = true;  
  11.                 break;  
  12.   
  13.             case MotionEvent.ACTION_MOVE:  
  14.                 handleMove(event);  
  15.                 handled = true;  
  16.                 break;  
  17.   
  18.             case MotionEvent.ACTION_UP:  
  19.                 Xlog.i(TAG,"ACTION_UP");  
  20.                 mActionCancel = false;  
  21.                 handleMove(event);  
  22.                 handleUp(event);  
  23.                 handled = true;  
  24.                 break;  
  25.   
  26.             case MotionEvent.ACTION_CANCEL:  
  27.                 Xlog.i(TAG,"ACTION_CANCEL");  
  28.                 mActionCancel = true;  
  29.                 handleMove(event);  
  30.                 handleUp(event);  
  31.                 handled = true;  
  32.                 break;  
  33.         }  
  34.         invalidate();  
  35.         return handled ? true : super.onTouchEvent(event);  
  36.     }  
从谷歌的方法命名上就能大概知道这个方法有什么作用,谷歌的命名很规范,我们要学习这种命名,简单、明了;

相应的方法会调用一个方法switchToState(),这个是改变状态做相应处理方法,然后根据传入什么的状态常量,做什么处理就可以了。这个细节大家可以看一眼就明白怎么回事了。


step 5:另外补充几个方法:

private void showTargets(boolean animate) { }显示目标target的方法,传入true:表示有动画,false:无动画;

private void hideTargets(boolean animate) { } 隐藏目标target的方法,出入true:表示有动画,false:无动画;

这个显示和隐藏的实现谷歌的实现是:改变Alpha的值来实现的,setAlpha(0.0f)表示隐藏,setAlpha(1.0f) 显示;

private void updateTargetPositions() {  } 这个方法是更新target目标的坐标的方法;


尾声:这些重点方法和流程都说了一下,我相信剩下的细节就没什么了。想做什么修改这个根据客户的需求就可以了。像小米的锁屏,双击出音乐的界面,有播放,上一首,下一首,这个都可以在这个类中做修改;

上传一张图片,看看效果:

                                       



  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值