解锁界面效果类似如下

其实这也是我后面做出的效果,样机因为没有ROOT不好调试截图,功能是将解锁的图标添加了最近运行的运用的图标,这样的话更方便用户去使用

1.分析 
1.1.Android锁屏功能分析

Android锁屏相关的代码在以下几个路径:

锁屏的具体实现:

 

\frameworks\base\policy\src\com\android\internal\policy\impl

其中的主要代码如下:

锁屏控件的View类

\frameworks\base\core\java\com\android\internal\widget\multiwaveview

锁屏控件使用到的资源

\frameworks\base\core\res\res\values-sw600dp-land\arrays.xml

\frameworks\base\core\res\res\drawableXXX

Android上常用的锁屏方法有以下几种:默认锁屏方式(LockScreen)、SIM卡解锁方式(SimUnlockScreen)、图案解锁方式(PatternUnlockScreen)、密码解锁方式(PasswordUnlockScreen)、账号解锁方式(AccountUnlockScreen),这些解锁方式都有对应的源码实现,我们这里讨论的是最常用的默认解锁方式,在Android4.0之后,解锁控件变为“波纹解锁”,即如概述介绍的那样,通过控制中心的圆圈来实现解锁,这种解锁方式,实际上可以进一步增强。

1.1.1.  Android启动后从窗口管理器运行到解锁界面的动作

1.开机启动后执行到PhoneWindowManager.systemReady()。

2.调用KeyguardViewMediator.onSystemReady()进行待机锁屏及解锁逻辑。

3.KeyguardViewMediator是整个待机解锁屏业务的调度器,负责调度锁屏界面的相关动作及查询解锁屏状态。

1.1.2.  KeyguardViewMediator的作用

1.查询锁屏状态,及当前处于锁屏状态还是已解锁状态,PhoneWindowManager持有KeyguardViewMediator的引用,当用户触摸屏幕或者按下某个键是,PhoneWindowManager会通过KeyguardViewMediator查询锁屏状态(锁定/解锁),进行不同的响应处理。如果处于锁定状态,系统输入事件会受到限制。

2.响应电源事件(黑/亮屏)。判断锁屏界面应该处于什么状态(显示或者重置)。手机黑屏后,锁屏界面马上就会显示出来,以便下一次亮屏后,马上就能显示锁屏界面,而不会出现闪烁或延时。

3.其他应用程序或者服务也可以请求禁止锁屏(通过调用KeyguardViewMediator的setKeyguardEnabled(boolean)方法)。例如接听来电界面。

KeyguardViewMediator类在WindowManagerPolicy(在手机系统中是PhoneWindowManager实例)初始化时被创建,并运行在它的线程上,锁屏的UI界面也是在这个线程上创建及显示的。KeyguardViewMediator类提供的状态查询api可以被诸如android.view.WindowManager、com.android.server.InputManager等其它线程调用,所以,KeyguardViewMediator类上的这些api方法都是线程同步的(synchronized)。

1.1.3.  KeyguardViewMediator可以进行的调度操作

1) 点亮屏幕pokeWakelock();

2) 报告锁屏权限验证是否成功keyguardDone(boolean);

3) 响应SIM卡状态变化并对锁屏界面做相应的调整onSimStateChanged()。

4) 调度待机锁屏UI界面的管理,包括:

1.显示handleShow ()、

2.隐藏handleHide ()、

3.重置handleReset ()、

4.点亮屏幕handleWakeWhenReady()等。

KeyguardViewMediator实现这部分调度是通过持有一个KeyguardViewManager来实现的。总之KeyguardUpdateMonitor是所有会影响整个待机解/锁屏业务的事件的监控器。(除了作为监控器,它还发挥着类似上下文的作用,也许我们应该把这个类命名为(KeyguardContext)。它监控诸如时间改变、电池状态改变、时区改变、SIM卡状态变化、电话状态变化、电话信号变化等事件。它是一个观察者模式的被观察对象。观察者通过调用KeyguardUpdateMonitor的以下方法进行注册,观察自己感兴趣的变化。

registerInfoCallback(InfoCallback)registerSimStateCallback(SimStateCallback)

KeyguardUpdateMonitor的观察者包括KeyguardViewMediator、LockScreen、PatternUnlockScreen、AccountUnlockScreen、PasswordUnlockScreen、SimUnlockScreen等。观察者通过调用KeyguardUpdateMonitor的removeCallback(Object)取消观察。

KeyguardViewManager负责管理待机屏UI界面的创建、显示、隐藏、重置以及通过一个回调KeyguardViewCallback通知调度器KeyguardViewMediator进行相关的调度。

LockPatternKeyguardView(KeyguardViewBase)是所有锁屏和解锁UI界面的宿主。它有2个模式Mode. LockScreen和Mode. UnlockScreen。它负责根据当前上下文环境切换当前应该显示的待机屏。

它提供一个回调给当前显示的待机屏并处理其回调,如果回调动作是自己处理不了的,则继续报告给KeyguardViewMediator进行处理。

锁屏界面就是LockScreen;解锁界面包括SIM卡解锁SimUnlockScreen、图案解锁PatternUnlockScreen、密码解锁PasswordUnlockScreen、帐号解锁AccountUnlockScreen

解锁成功后,锁屏流程转到KeyguardViewMediator的keyguardDone(boolean, boolean) 进行后续的流程(如转到Launcher桌面)。

1.2. 解锁界面布局

解锁界面布局在LockScreen类的构造函数中进行,LockScreen构造函数内容如下:

点击(此处)折叠或打开

  1. LockScreen(Context context, Configuration configuration, LockPatternUtils lockPatternUtils,
  2. KeyguardUpdateMonitor updateMonitor,
  3. KeyguardScreenCallback callback) {
  4. super(context);
  5. mLockPatternUtils = lockPatternUtils;
  6. mUpdateMonitor = updateMonitor;
  7. mCallback = callback;
  8. mEnableMenuKeyInLockScreen = shouldEnableMenuKey();
  9. mCreationOrientation = configuration.orientation;
  10. mKeyboardHidden = configuration.hardKeyboardHidden;
  11. if (LockPatternKeyguardView.DEBUG_CONFIGURATION) {
  12. Log.v(TAG, "***** CREATING LOCK SCREEN", new RuntimeException());
  13. Log.v(TAG, "Cur orient=" + mCreationOrientation
  14. + " res orient=" + context.getResources().getConfiguration().orientation);
  15. }
  16. final LayoutInflater inflater = LayoutInflater.from(context);
  17. if (DBG) Log.v(TAG, "Creation orientation = " + mCreationOrientation);
  18. if (mCreationOrientation != Configuration.ORIENTATION_LANDSCAPE) {
  19. inflater.inflate(R.layout.keyguard_screen_tab_unlock, this, true);
  20. } else {
  21. inflater.inflate(R.layout.keyguard_screen_tab_unlock_land, this, true);
  22. }
  23. mStatusViewManager = new KeyguardStatusViewManager(this, mUpdateMonitor, mLockPatternUtils,
  24. mCallback, false);
  25. setFocusable(true);
  26. setFocusableInTouchMode(true);
  27. setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
  28. mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
  29. mSilentMode = isSilentMode();
  30. mUnlockWidget = findViewById(R.id.unlock_widget);
  31. if (mUnlockWidget instanceof SlidingTab) {
  32. SlidingTab slidingTabView = (SlidingTab) mUnlockWidget;
  33. slidingTabView.setHoldAfterTrigger(true, false);
  34. slidingTabView.setLeftHintText(R.string.lockscreen_unlock_label);
  35. slidingTabView.setLeftTabResources(
  36. R.drawable.ic_jog_dial_unlock,
  37. R.drawable.jog_tab_target_green,
  38. R.drawable.jog_tab_bar_left_unlock,
  39. R.drawable.jog_tab_left_unlock);
  40. SlidingTabMethods slidingTabMethods = new SlidingTabMethods(slidingTabView);
  41. slidingTabView.setOnTriggerListener(slidingTabMethods);
  42. mUnlockWidgetMethods = slidingTabMethods;
  43. } else if (mUnlockWidget instanceof WaveView) {
  44. WaveView waveView = (WaveView) mUnlockWidget;
  45. WaveViewMethods waveViewMethods = new WaveViewMethods(waveView);
  46. waveView.setOnTriggerListener(waveViewMethods);
  47. mUnlockWidgetMethods = waveViewMethods;
  48. } else if (mUnlockWidget instanceof MultiWaveView) {
  49. MultiWaveView multiWaveView = (MultiWaveView) mUnlockWidget;
  50. MultiWaveViewMethods multiWaveViewMethods = new MultiWaveViewMethods(multiWaveView);
  51. multiWaveView.setOnTriggerListener(multiWaveViewMethods);
  52. mUnlockWidgetMethods = multiWaveViewMethods;
  53. } else {
  54. throw new IllegalStateException("Unrecognized unlock widget: " + mUnlockWidget);
  55. }
  56. // Update widget with initial ring state
  57. mUnlockWidgetMethods.updateResources(context);
  58. if (DBG) Log.v(TAG, "*** LockScreen accel is "
  59. + (mUnlockWidget.isHardwareAccelerated() ? "on":"off"));
  60. }

通过添加打印发现在480分辨率下采用的Layout文件为\layout-sw480dp\keyguard_screen_tab_unlock_land.xml,此文件的内容如下:

点击(此处)折叠或打开

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <!--
  3. **
  4. ** Copyright 2009, The Android Open Source Project
  5. **
  6. ** Licensed under the Apache License, Version 2.0 (the "License")
  7. ** you may not use this file except in compliance with the License.
  8. ** You may obtain a copy of the License at
  9. **
  10. ** http://www.apache.org/licenses/LICENSE-2.0
  11. **
  12. ** Unless required by applicable law or agreed to in writing, software
  13. ** distributed under the License is distributed on an "AS IS" BASIS,
  14. ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. ** See the License for the specific language governing permissions and
  16. ** limitations under the License.
  17. */
  18. -->
  19. <!-- This is the general lock screen which shows information about the
  20. state of the device, as well as instructions on how to get past it
  21. depending on the state of the device.-->
  22. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  23. xmlns:tabunlock="http://schemas.android.com/apk/res/com.android.tabunlock"
  24. android:layout_width="match_parent"
  25. android:layout_height="match_parent"
  26. android:orientation="horizontal"
  27. android:id="@+id/root">
  28. <!-- left side: status and music -->
  29. <RelativeLayout
  30. android:layout_height="match_parent"
  31. android:layout_weight="1"
  32. android:layout_width="0dip"
  33. android:gravity="center">
  34. <RelativeLayout android:id="@+id/transport_bg_protect"
  35. android:layout_width="512dip"
  36. android:layout_height="wrap_content">
  37. <!-- Music transport control underneath -->
  38. <include android:id="@+id/transport"
  39. layout="@layout/keyguard_transport_control"
  40. android:layout_row="0"
  41. android:layout_column="0"
  42. android:layout_rowSpan="3"
  43. android:layout_columnSpan="1"
  44. android:layout_gravity="fill"
  45. android:layout_width="match_parent"
  46. android:layout_height="512dip"
  47. />
  48. <include layout="@layout/keyguard_screen_status_land"
  49. android:layout_width="match_parent"
  50. android:layout_height="wrap_content"
  51. android:layout_marginLeft="50dip"
  52. android:layout_marginTop="50dip"
  53. android:layout_marginBottom="82dip"
  54. android:layout_marginRight="64dip"
  55. android:layout_alignParentTop="true"
  56. android:layout_alignParentLeft="true"/>
  57. </RelativeLayout>
  58. </RelativeLayout>
  59. <!-- right side -->
  60. <RelativeLayout
  61. android:layout_height="match_parent"
  62. android:layout_weight="1"
  63. android:layout_width="0dip"
  64. android:gravity="center_horizontal|center_vertical">
  65. <TextView
  66. android:id="@+id/screenLocked"
  67. android:layout_width="wrap_content"
  68. android:layout_height="wrap_content"
  69. android:textAppearance="?android:attr/textAppearanceMedium"
  70. android:gravity="center"
  71. android:layout_marginTop="12dip"
  72. android:layout_alignParentLeft="true"
  73. android:layout_alignParentTop="true"
  74. android:drawablePadding="4dip"/>
  75. <com.android.internal.widget.multiwaveview.MultiWaveView
  76. android:id="@+id/unlock_widget"
  77. android:layout_width="match_parent"
  78. android:layout_height="match_parent"
  79. android:layout_rowSpan="7"
  80. android:layout_gravity="center_vertical|center_horizontal"
  81. android:targetDrawables="@array/lockscreen_targets_with_camera"
  82. android:targetDescriptions="@array/lockscreen_target_descriptions_with_camera"
  83. android:directionDescriptions="@array/lockscreen_direction_descriptions"
  84. android:handleDrawable="@drawable/ic_lockscreen_handle"
  85. android:waveDrawable="@drawable/ic_lockscreen_outerring"
  86. android:outerRadius="@dimen/multiwaveview_target_placement_radius"
  87. android:snapMargin="@dimen/multiwaveview_snap_margin"
  88. android:hitRadius="@dimen/multiwaveview_hit_radius"
  89. android:rightChevronDrawable="@drawable/ic_lockscreen_chevron_right"
  90. android:feedbackCount="3"
  91. android:vibrationDuration="20"
  92. android:horizontalOffset="0dip"
  93. android:verticalOffset="0dip"
  94. />
  95. <!-- emergency call button shown when sim is PUKd and tab_selector is hidden -->
  96. <Button
  97. android:id="@+id/emergencyCallButton"
  98. android:layout_width="wrap_content"
  99. android:layout_height="wrap_content"
  100. android:layout_marginRight="80dip"
  101. android:layout_marginBottom="80dip"
  102. android:layout_alignParentRight="true"
  103. android:layout_alignParentBottom="true"
  104. android:drawableLeft="@drawable/ic_emergency"
  105. style="@style/Widget.Button.Transparent"
  106. android:drawablePadding="8dip"
  107. android:visibility="gone"/>
  108. </RelativeLayout>>
  109. </LinearLayout>

从文件中可以看出,解锁界面的数字时钟、充电状态、波纹解锁等控件均在其中布局,对解锁控件的大小修改也是通过修改该文件进行的。

1.3. MultiWaveView控件分析

对于Android4.0默认的LockScreen,采用的是MultiWaveView控件,LockScreen中创建该控件的代码如下:

点击(此处)折叠或打开

  1. mUnlockWidget = findViewById(R.id.unlock_widget);
  2. if (mUnlockWidget instanceof SlidingTab) {
  3. SlidingTab slidingTabView = (SlidingTab) mUnlockWidget;
  4. slidingTabView.setHoldAfterTrigger(true, false);
  5. slidingTabView.setLeftHintText(R.string.lockscreen_unlock_label);
  6. slidingTabView.setLeftTabResources(
  7. R.drawable.ic_jog_dial_unlock,
  8. R.drawable.jog_tab_target_green,
  9. R.drawable.jog_tab_bar_left_unlock,
  10. R.drawable.jog_tab_left_unlock);
  11. SlidingTabMethods slidingTabMethods = new SlidingTabMethods(slidingTabView);
  12. slidingTabView.setOnTriggerListener(slidingTabMethods);
  13. mUnlockWidgetMethods = slidingTabMethods;
  14. } else if (mUnlockWidget instanceof WaveView) {
  15. WaveView waveView = (WaveView) mUnlockWidget;
  16. WaveViewMethods waveViewMethods = new WaveViewMethods(waveView);
  17. waveView.setOnTriggerListener(waveViewMethods);
  18. mUnlockWidgetMethods = waveViewMethods;
  19. } else if (mUnlockWidget instanceof MultiWaveView) {
  20. MultiWaveView multiWaveView = (MultiWaveView) mUnlockWidget;
  21. MultiWaveViewMethods multiWaveViewMethods = new MultiWaveViewMethods(multiWaveView);
  22. multiWaveView.setOnTriggerListener(multiWaveViewMethods);
  23. mUnlockWidgetMethods = multiWaveViewMethods;
  24. } else {
  25. throw new IllegalStateException("Unrecognized unlock widget: " + mUnlockWidget);
  26. }

这是LockScreen的构造函数中的代码,函数根据R.id.unlock_widget定义的类型选择不同的控件类,其中第一种是Android2.3的滑动解锁类,第二种的简单的波纹解锁类,第三种才是我们使用的MultiWaveView类,函数并创建了一个MultiWaveViewMethods类,这个类实际上是为了更好地使用而进行的封装,它的代码如下:

点击(此处)折叠或打开

  1. class MultiWaveViewMethods implements MultiWaveView.OnTriggerListener,
  2. UnlockWidgetCommonMethods {
  3. private final MultiWaveView mMultiWaveView;
  4. private boolean mCameraDisabled;
  5. MultiWaveViewMethods(MultiWaveView multiWaveView) {
  6. mMultiWaveView = multiWaveView;
  7. final boolean cameraDisabled = mLockPatternUtils.getDevicePolicyManager()
  8. .getCameraDisabled(null);
  9. if (cameraDisabled) {
  10. Log.v(TAG, "Camera disabled by Device Policy");
  11. mCameraDisabled = true;
  12. } else {
  13. // Camera is enabled if resource is initially defined for MultiWaveView
  14. // in the lockscreen layout file
  15. mCameraDisabled = mMultiWaveView.getTargetResourceId()
  16. != R.array.lockscreen_targets_with_camera;
  17. }
  18. }
  19. public void updateResources() {
  20. int resId;
  21. if (mCameraDisabled) {
  22. // Fall back to showing ring/silence if camera is disabled by DPM...
  23. resId = mSilentMode ? R.array.lockscreen_targets_when_silent
  24. : R.array.lockscreen_targets_when_soundon;
  25. } else {
  26. resId = R.array.lockscreen_targets_with_camera;
  27. }
  28. mMultiWaveView.setTargetResources(resId);
  29. }
  30. public void onGrabbed(View v, int handle) {
  31. }
  32. public void onReleased(View v, int handle) {
  33. }
  34. public void onTrigger(View v, int target) {
  35. if (target == 0 || target == 1) { // 0 = unlock/portrait, 1 = unlock/landscape
  36. mCallback.goToUnlockScreen();
  37. } else if (target == 2 || target == 3) { // 2 = alt/portrait, 3 = alt/landscape
  38. if (!mCameraDisabled) {
  39. // Start the Camera
  40. Intent intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);
  41. intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
  42. mContext.startActivity(intent);
  43. mCallback.goToUnlockScreen();
  44. } else {
  45. toggleRingMode();
  46. mUnlockWidgetMethods.updateResources();
  47. mCallback.pokeWakelock();
  48. }
  49. }
  50. }
  51. public void onGrabbedStateChange(View v, int handle) {
  52. // Don't poke the wake lock when returning to a state where the handle is
  53. // not grabbed since that can happen when the system (instead of the user)
  54. // cancels the grab.
  55. if (handle != MultiWaveView.OnTriggerListener.NO_HANDLE) {
  56. mCallback.pokeWakelock();
  57. }
  58. }

这个类有两个方法特别重要,一个是更新MultiWaveView的资源,即public void updateResources(),另一个是对解锁后的响应,即public void onTrigger(View v, int target),这方法传入的第二个参数为解锁选择的图标编号,图标是从右向左逆时针编号的,即最右边的图标编号为0,在此函数中即可进行解锁的处理,选择是进入主界面还是启动其他的Activity。Android4.0默认target = 0对应的是进入主界面,

target = 2或者target = 3启动Camera,其解锁界面的图标是每次都是使用固定的资源,在完成解锁后按下Power键或者系统再次进入锁定状态,LockScreen都会再构造一次,会重新布局并加载资源,因此可以使每次解锁界面都不一样。

2. 实现
2.1. 获取最近运行程序

在Android中可以通过ActivityManager获取到最近运行的Activity,详细的用法如下:

输入参数是需要查询的最大最近运行任务个数,查询的方式(默认采用ActivityManager.RECENT_IGNOR_UNAVAILABLE),返回ActivityManager.RecentTaskInfo对象,其定义如下:

其中的baseIntent为启动最近运行任务的Intent,通过它我们可以很方便地获取Activity的图标并启动最近运行的Activity。

相关的代码如下:

final ActivityManager am = (ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE);

List<ActivityManager.RecentTaskInfo> recentLs = am.getRecentTasks(7, ActivityManager.RECENT_IGNORE_UNAVAILABLE);

2.1.1. 获取Activity图标的方法

通过PackManager我们可以很方便地获取到Activity的图标,对应的代码如下:

final PackageManager pm = context.getPackageManager();

pm.getActivityIcon(recentLs.get(i).baseIntent)

2.2.          修改/system/build.prop文件

这个文件中包含了大量Android中的配置信息,其中也有和显示分辨率相关的,修改的方法如下:

1.通过ADB将文件获取到主机任意文件夹。

adb pull /system/build.prop

2.用编辑软件打开build.prop,找到如下行

2.将ro.sf.lcd_density=120修改为=160或者直接删除掉这一行(这样就使用默认160)。

3.执行

adb push build.prop /system/

2.3. 修改MultiWaveView控件

修改以下位置的源文件:

Z:\exdroid\android4.0.1\frameworks\base\core\java\com\android\internal\widget\multiwaveview\MultiWaveView.java

重载setTargetResources方法,重载后的方法如下:

点击(此处)折叠或打开

  1. public void setTargetResources(ArrayList<Drawable> drawables)
  2. {
  3. Resources res = getContext().getResources();
  4. int count = drawables.size();
  5. ArrayList<TargetDrawable> targetDrawables = new ArrayList<TargetDrawable>(count);
  6. for (int i = 0; i < count; i++) {
  7. Drawable drawable = drawables.get(i);
  8. targetDrawables.add(new TargetDrawable(res, drawable));
  9. Log.v(TAG,"Add a Drawable");
  10. }
  11. mTargetDrawables = targetDrawables;
  12. updateTargetPositions();
  13. }

重载后的方法支持直接传入图片链表。这个方法是提供给LockScreen调用的

2.4.修改LockScreen.java文件

重载其中的MultiWaveViewMethods类的updateResources方法,重载后的方法如下:

点击(此处)折叠或打开

  1. public void updateResources(Context context)
  2. {
  3. ArrayList<Drawable> drawableAl = new ArrayList();
  4. final ActivityManager am = (ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE);
  5. final PackageManager pm = context.getPackageManager();
  6. drawableAl.add(getView().getResources().getDrawable(R.drawable.ic_lockscreen_unlock));
  7. List<ActivityManager.RecentTaskInfo> recentLs = am.getRecentTasks(7, ActivityManager.RECENT_IGNORE_UNAVAILABLE);
  8. for(int i=0;i<recentLs.size();i++)
  9. {
  10. try
  11. {
  12. drawableAl.add(pm.getActivityIcon(recentLs.get(i).baseIntent));
  13. mIntentList.add(recentLs.get(i).baseIntent);
  14. }
  15. catch(Exception e)
  16. {
  17. Log.v(TAG,"Catch Exception");
  18. }
  19. }
  20. mMultiWaveView.setTargetResources(drawableAl);
  21. }

重载后的updateResources函数实际上先获取最近运行的任务列表,再获取任务图标,最后用获取的图标设置MultiWaveView控件。

修改解锁响应onTigger:

点击(此处)折叠或打开

  1. public void onTrigger(View v, int target) {
  2. Log.v(TAG,"onTrigger = " + target);
  3. if(target ==0)
  4. {
  5. mCallback.goToUnlockScreen();
  6. }
  7. else
  8. {
  9. if(mIntentList.get(target-1)!=null)
  10. {
  11. Intent intent = mIntentList.get(target-1);
  12. mContext.startActivity(intent);
  13. mCallback.goToUnlockScreen();
  14. }
  15. }
  16. }

这样解锁事件的响应被修改成0号图标解锁,其余启动对应的Activity。

2.5. 调整解锁圆圈大小

启动应用程序的功能实现了,但是解锁圆圈的大小还是太大,特别是在更改dpi之后,圆圈几乎占据了半个显示屏,显得并不雅观。

实际上,解锁圆圈的资源就是/framework/cors/res/res/drawable-xxx中的unlock_ring.png,对于不同分辨率的设备,会采用不同的大小。我们可以通过修改位图的大小来进行更改,但在实际测试中修改了所有的unlock_ring.png,也未见解锁图标变小。

决定采用代码配合更改图案大小的功能,如图:

mOuterRing为外圆圈的资源,mOuterRadius为解锁圆圈的活动半径,修改代码后直接从图片获取,这样将采用drawable-sw480dp-mdpi下的图片,通过PhotoShop等软件将圆圈图片缩小,最终显示出的圆圈就变小了。

3. 关于Android屏幕的知识(摘自网上)
 3.1. density

density表示每英寸有多少个显示点(逻辑值),它的单位是dpi:dot per inch,通常屏幕大时,density就大,屏幕小时,density就小,通常:

屏幕实际分辨率为240px*400px时,density=120

屏幕实际分辨率为320px*533px,density=160

屏幕实际分辨率为480px*800px,density=240

3.2. 分辨率

是整个屏是多少点,比如800x480,它是软件的显示单位,实际上会因为不同的显示屏的像素大小不同,造成density不同。

3.3. 资源目录名称

res/xxx-hdpi          当density为240时,使用此目录下的资源

res/xxx-mdpi          当density为160时,使用此目录下的资源

res/xxx-ldpi          当density为120时,使用此目录下的资源

res/xxx                不常后缀,为默认设置,同xxx-mdpi

3.4. 资源单位(xml文件中定义大小的单位)

a)dp=dip=dx (Density independent pixel)

基于屏幕密度的抽象单位,设备无关的点,用于说明与密度无关的尺寸和位置。这些单位是相对于一个160dpi的屏幕,所有一个dp是160dpi屏幕上的一个点。

b)px (Pixel)

px指软件的单位点,设备相关的点

3.5. 获取屏幕信息的相关代码片段

  1. public static String getDisplayMetrics(Context cx) {
  2. String str = "";
  3. DisplayMetrics dm = new DisplayMetrics();
  4. dm = cx.getApplicationContext().getResources().getDisplayMetrics();
  5. int screenWidth = dm.widthPixels;
  6. int screenHeight = dm.heightPixels;
  7. float density = dm.density;
  8. float xdpi = dm.xdpi;
  9. float ydpi = dm.ydpi;
  10. str += "The absolute width:" + String.valueOf(screenWidth) + "pixels\n";
  11. str += "The absolute heightin:" + String.valueOf(screenHeight)
  12. + "pixels\n";
  13. str += "The logical density of the display.:" + String.valueOf(density)
  14. + "\n";
  15. str += "X dimension :" + String.valueOf(xdpi) + "pixels per inch\n";
  16. str += "Y dimension :" + String.valueOf(ydpi) + "pixels per inch\n";
  17. return str;
  18. }

3.6.  获取状态栏和标题栏的高度

点击(此处)折叠或打开

  1. TextView tv1;
  2. @Override
  3. protected void onCreate(Bundle savedInstanceState) {
  4. super.onCreate(savedInstanceState);
  5. setContentView(R.layout.layout_test2);
  6. tv1 = (TextView) findViewById(R.id.TextView01);
  7. tv1.post(new Runnable(){
  8. public void run()
  9. {
  10. processLayout();
  11. }
  12. });
  13. }
  14. private void processLayout(){
  15. Rect rect= new Rect();
  16. Window window= getWindow();
  17. tv1.getWindowVisibleDisplayFrame(rect);
  18. //状态栏高度
  19. int statusBarHeight= rect.top;
  20. int contentViewTop= window.findViewById(Window.ID_ANDROID_CONTENT).getTop();
  21. //标题栏高度
  22. int titleBarHeight= contentViewTop - statusBarHeight;
  23. //测试结果:ok之后 100多 ms 才运行了
  24. Log.v("test", "=-init-=  statusBarHeight="+statusBarHeight+
  25. " contentViewTop="+contentViewTop+
  26. " titleBarHeight="+titleBarHeight);
  27. }

修改Android解锁界面的更多相关文章

  1. 【转】修改Android解锁界面

    背景      先说说背景吧,这是本人从WinCE系统转到Android之后,接到的第一个任务就是修改Android原生的解锁界面,之前看了两个星期的书和网络博客,Java的也有.Android应用开 ...

  2. Android 修改屏幕解锁方式

    Android 修改屏幕解锁方式 问题 在手机第一次开机的时候,运行手机激活的APP 在激活APP允许过程中,当用户按电源键的时候,屏幕黑掉,进入锁屏状态 手机默认的锁屏是滑动解锁 用户这个时候再一次 ...

  3. 修改Android系统字号(二)

    /*********************************************************************** * 修改Android系统字号(二) * 说明: * ...

  4. Android Studio 使用笔记:[转] Mac下修改Android Studio 所用的JDK版本

    原文链接:http://www.jianshu.com/p/d8d1d72d0248# 最近项目从Eclipse+Ant构建模式转移到了Android Studio+Gradle构建模式,自然的JDK ...

  5. Android系统移植与调试之------->如何修改Android手机NFC模块,使黑屏时候能够使用NFC

    我们都知道在不修改源代码的情况下,只能是解锁之后才能使用NFC功能.而在锁屏和黑屏2个状态下是没办法用NFC的,但是最近有个客户要求手机在黑屏状态下能够使用NFC,因此我们需要去修改Android源代 ...

  6. Android流行界面结构——Fragment通过ViewPager(带指示器)嵌套Fragment结构的创建方法详解

    原创文章,转载请注明出处http://www.cnblogs.com/baipengzhan/p/6287213.html 当前Android流行界面结构的一种——Fragment通过ViewPage ...

  7. 这才是Android设置界面的正确做法👌👌👌

    话不多说,先上效果图 本文参考简书博客:<这才是Android设置界面的正确做法>一文写成,在其基础上删改并增加了一些内容.建议新窗口打开原文,在本文讲述不清楚的地方参考原文去寻找答案. ...

  8. 修改Android系统属性SystemProperties.set("sys.powerctl", "shutdown")关机分析

    简介: 从之前的博文中我们提到过,关机流程中最后是通过修改Android属性进行关机操作(SystemProperties.java通过JNI调用访问系统属性),当然我们也可以通过adb命令修改And ...

  9. Windows下修改Android手机的hosts

    Windows下修改Android手机的hosts 1.首先,手机是Root过的. 2.连接手机和电脑, adb shell 进入命令行. 3.获取root用户权限: su -root 4.不知道为何 ...

随机推荐

  1. React + Python 七月小说网 功能设计(二)

    概述 在通过对世面上的各种小说网站简单了解之后(PS:好多盗版网站真的好丑哦.),去除花里胡哨的功能,保留实用功能. 初步制定了以下几个功能需求,当然,所有需求功能都是我自己设计.自己评审,大不了到时 ...

  2. C#操作excel打印

    using System; using System.Data; using System.IO; using System.Runtime.InteropServices; using System ...

  3. 《C#多线程编程实战》2.4 SemaphoreSlim

    这个简单多了. 理解也是很好理解. 比上一个mutex好理解多了. 这个SemaphoreSlim是干什么呢? 就是限制线程的来访问. 好比说一次只有两个,一次只有三个  这样的线程来访问资源. 有点 ...

  4. mysql相关的软件

    数据库采用mysql,那么问题来了,mysql的部署是采用主备模式?主主模式?集群模式?在然后采取分库.分表模式? 其次:在外围的辅助开源软件的选择mycat?mybatis?keepalived?r ...

  5. 下载azure website的code

    1.登陆kudu直接下载. http://www.concurrency.com/blog/use-azure-kudu-debug-azure-websites/ 2.FTP链接拷贝(可以忽略) 3 ...

  6. c语言数据结构学习心得——树

    树 一对多的树型结构,有且只有一个特定的根结点. 结点的度:结点拥有子树的数量{ 度为0:叶子结点/终端结点. 度不为0:非终端结点/分支结点(除去根结点其它称为内部结点).} 树的度:树中所有结点的 ...

  7. Linux系统管理之硬盘管理

    硬盘是计算的重要组成部件之一,硬盘为操作系统提供持久话存储的功能,在Linux硬盘设备的性能和好坏可能关系到生成线的安全和用户体验等等.熟练的掌握硬盘管理相关的信息能让我们处理起这些问题来得心应手. ...

  8. Query on a tree 树链剖分 [模板]

    You are given a tree (an acyclic undirected connected graph) with N nodes, and edges numbered 1, 2, ...

  9. vector<vector<int>> 使用简单示例

    #include <iostream> #include <vector> using namespace std; int main() { vector<vector ...

  10. C++_IO与文件1-输入与输出概述

    为了方便起步先从istream类对象cin和ostream类对象cout开始,了解输入和输出的基本方法: 同时使用ifstream和ofstream对象进行文件的输入和输出: 然后详细学习cin和co ...