一、无锁屏;
二、锁屏:
1、UnLockScreen:
图案锁、 PIN锁, 密码锁;
2、LockScreen:
波纹锁;
接着我们来看看LockScreen的时序图:
综上所述:
1、createUnlockScreenFor()方法创建的是UnLockScreen界面,代码如下:
- View createUnlockScreenFor(UnlockMode unlockMode) {
- View unlockView = null;
- if (DEBUG) Log.d(TAG,
- "createUnlockScreenFor(" + unlockMode + "): mEnableFallback=" + mEnableFallback);
- if (unlockMode == UnlockMode.Pattern) {
- PatternUnlockScreen view = new PatternUnlockScreen(
- mContext,
- mConfiguration,
- mLockPatternUtils,
- mUpdateMonitor,
- mKeyguardScreenCallback,
- mUpdateMonitor.getFailedAttempts());
- view.setEnableFallback(mEnableFallback);
- unlockView = view;
- } else if (unlockMode == UnlockMode.SimPuk) {
- unlockView = new SimPukUnlockScreen(
- mContext,
- mConfiguration,
- mUpdateMonitor,
- mKeyguardScreenCallback,
- mLockPatternUtils, MSimTelephonyManager.getDefault().getDefaultSubscription());
- } else if (unlockMode == UnlockMode.SimPin) {
- unlockView = new SimUnlockScreen(
- mContext,
- mConfiguration,
- mUpdateMonitor,
- mKeyguardScreenCallback,
- mLockPatternUtils);
- } else if (unlockMode == UnlockMode.Account) {
- try {
- unlockView = new AccountUnlockScreen(
- mContext,
- mConfiguration,
- mUpdateMonitor,
- mKeyguardScreenCallback,
- mLockPatternUtils);
- } catch (IllegalStateException e) {
- Log.i(TAG, "Couldn't instantiate AccountUnlockScreen"
- + " (IAccountsService isn't available)");
- // TODO: Need a more general way to provide a
- // platform-specific fallback UI here.
- // For now, if we can't display the account login
- // unlock UI, just bring back the regular "Pattern" unlock mode.
- // (We do this by simply returning a regular UnlockScreen
- // here. This means that the user will still see the
- // regular pattern unlock UI, regardless of the value of
- // mUnlockScreenMode or whether or not we're in the
- // "permanently locked" state.)
- return createUnlockScreenFor(UnlockMode.Pattern);
- }
- } else if (unlockMode == UnlockMode.Password) {
- unlockView = new PasswordUnlockScreen(
- mContext,
- mConfiguration,
- mLockPatternUtils,
- mUpdateMonitor,
- mKeyguardScreenCallback);
- } else {
- throw new IllegalArgumentException("unknown unlock mode " + unlockMode);
- }
- initializeTransportControlView(unlockView);
- initializeFaceLockAreaView(unlockView); // Only shows view if FaceLock is enabled
- mUnlockScreenMode = unlockMode;
- return unlockView;
- }
2、createLockScreen()就是创建LockScreen界面:
- View createLockScreen() {
- /*View lockView = new LockScreen(
- mContext,
- mConfiguration,
- mLockPatternUtils,
- mUpdateMonitor,
- mKeyguardScreenCallback);
- initializeTransportControlView(lockView);
- return lockView;*/
- long lockscreenType = 0;
- try{
- lockscreenType = android.provider.Settings.Secure.
- getLong(mContext.getContentResolver(), "lockscreen.disabled");
- }catch(Exception e){
- e.printStackTrace();
- }
- View lockView = null;
- lockView = new LockScreen(
- mContext,
- mConfiguration,
- mLockPatternUtils,
- mUpdateMonitor,
- mKeyguardScreenCallback);
- initializeTransportControlView(lockView);
- return lockView;
- }
我们来看看锁屏界面的流程:
step 1:创建LockScreen.java类——>先看看构造函数:
- LockScreen(Context context, Configuration configuration, LockPatternUtils lockPatternUtils,
- KeyguardUpdateMonitor updateMonitor,
- KeyguardScreenCallback callback) {
- super(context);
- mLockPatternUtils = lockPatternUtils;
- mUpdateMonitor = updateMonitor;
- mCallback = callback;
- mEnableMenuKeyInLockScreen = shouldEnableMenuKey();
- mCreationOrientation = configuration.orientation;
- mKeyboardHidden = configuration.hardKeyboardHidden;
- if (LockPatternKeyguardView.DEBUG_CONFIGURATION) {
- Log.v(TAG, "***** CREATING LOCK SCREEN", new RuntimeException());
- Log.v(TAG, "Cur orient=" + mCreationOrientation
- + " res orient=" + context.getResources().getConfiguration().orientation);
- }
- final LayoutInflater inflater = LayoutInflater.from(context);
- if (DBG) Log.v(TAG, "Creation orientation = " + mCreationOrientation);
- if (mCreationOrientation != Configuration.ORIENTATION_LANDSCAPE) {
- inflater.inflate(R.layout.keyguard_screen_tab_unlock, this, true);
- } else {
- inflater.inflate(R.layout.keyguard_screen_tab_unlock_land, this, true);
- }
- if (TelephonyManager.getDefault().isMultiSimEnabled()) {
- mStatusViewManager = new MSimKeyguardStatusViewManager(this, mUpdateMonitor,
- mLockPatternUtils, mCallback, false);
- } else {
- mStatusViewManager = new KeyguardStatusViewManager(this, mUpdateMonitor,
- mLockPatternUtils, mCallback, false);
- }
- setFocusable(true);
- setFocusableInTouchMode(true);
- setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
- mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
- // modify by wangxianming in 2012-06-22
- if (mAudioManager != null) {
- mSilentMode = isSilentMode();
- }
- mUnlockWidget = findViewById(R.id.unlock_widget);
- if (mUnlockWidget instanceof SlidingTab) {
- SlidingTab slidingTabView = (SlidingTab) mUnlockWidget;
- slidingTabView.setHoldAfterTrigger(true, false);
- slidingTabView.setLeftHintText(R.string.lockscreen_unlock_label);
- slidingTabView.setLeftTabResources(
- R.drawable.ic_jog_dial_unlock,
- R.drawable.jog_tab_target_green,
- R.drawable.jog_tab_bar_left_unlock,
- R.drawable.jog_tab_left_unlock);
- SlidingTabMethods slidingTabMethods = new SlidingTabMethods(slidingTabView);
- slidingTabView.setOnTriggerListener(slidingTabMethods);
- mUnlockWidgetMethods = slidingTabMethods;
- } else if (mUnlockWidget instanceof WaveView) {
- WaveView waveView = (WaveView) mUnlockWidget;
- WaveViewMethods waveViewMethods = new WaveViewMethods(waveView);
- waveView.setOnTriggerListener(waveViewMethods);
- mUnlockWidgetMethods = waveViewMethods;
- } else if (mUnlockWidget instanceof MultiWaveView) {
- MultiWaveView multiWaveView = (MultiWaveView) mUnlockWidget;
- MultiWaveViewMethods multiWaveViewMethods = new MultiWaveViewMethods(multiWaveView);
- multiWaveView.setOnTriggerListener(multiWaveViewMethods);
- mUnlockWidgetMethods = multiWaveViewMethods;
- } else {
- throw new IllegalStateException("Unrecognized unlock widget: " + mUnlockWidget);
- }
- // Update widget with initial ring state
- mUnlockWidgetMethods.updateResources();
- if (DBG) Log.v(TAG, "*** LockScreen accel is "
- + (mUnlockWidget.isHardwareAccelerated() ? "on":"off"));
- }
Step 2:在Step 1步骤中根据横竖屏来加载横竖屏的布局:
- if (mCreationOrientation != Configuration.ORIENTATION_LANDSCAPE) {
- inflater.inflate(R.layout.keyguard_screen_tab_unlock, this, true);
- } else {
- inflater.inflate(R.layout.keyguard_screen_tab_unlock_land, this, true);
- }
Step 3:来看看竖屏的布局文件的代码:
- <GridLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:gravity="center_horizontal">
- <!-- 锁屏界面加载数字时钟 -->
- <com.android.internal.widget.DigitalClock android:id="@+id/time"
- android:layout_marginTop="@dimen/keyguard_lockscreen_status_line_clockfont_top_margin"
- android:layout_marginBottom="12dip"
- android:layout_marginRight="@dimen/keyguard_lockscreen_status_line_font_right_margin"
- android:layout_gravity="right">
- <!-- Because we can't have multi-tone fonts, we render two TextViews, one on
- top of the other. Hence the redundant layout... -->
- <TextView android:id="@+id/timeDisplayBackground"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:singleLine="true"
- android:ellipsize="none"
- android:textSize="@dimen/keyguard_lockscreen_clock_font_size"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:layout_marginBottom="6dip"
- android:textColor="@color/lockscreen_clock_background"
- />
- <TextView android:id="@+id/timeDisplayForeground"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:singleLine="true"
- android:ellipsize="none"
- android:textSize="@dimen/keyguard_lockscreen_clock_font_size"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:layout_marginBottom="6dip"
- android:textColor="@color/lockscreen_clock_foreground"
- android:layout_alignLeft="@id/timeDisplayBackground"
- android:layout_alignTop="@id/timeDisplayBackground"
- />
- </com.android.internal.widget.DigitalClock>
- <LinearLayout
- android:orientation="horizontal"
- android:layout_gravity="right"
- android:layout_marginRight="@dimen/keyguard_lockscreen_status_line_font_right_margin">
- <!-- 锁屏界面加载日期 -->
- <TextView
- android:id="@+id/date"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:singleLine="true"
- android:ellipsize="marquee"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
- />
- <!-- 锁屏界面加载闹钟状态 -->
- <TextView
- android:id="@+id/alarm_status"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginLeft="16dip"
- android:singleLine="true"
- android:ellipsize="marquee"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
- android:drawablePadding="4dip"
- />
- </LinearLayout>
- <!-- 锁屏界面加载充电状态 -->
- <TextView
- android:id="@+id/status1"
- android:layout_gravity="right"
- android:layout_marginRight="@dimen/keyguard_lockscreen_status_line_font_right_margin"
- android:singleLine="true"
- android:ellipsize="marquee"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
- android:drawablePadding="4dip"
- />
- <Space android:layout_gravity="fill" />
- <RelativeLayout
- android:layout_width="match_parent"
- android:layout_height="302dip">
- <!-- 锁屏界面加载波纹的锁屏 -->
- <com.android.internal.widget.multiwaveview.MultiWaveView
- android:id="@+id/unlock_widget"
- android:orientation="horizontal"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_alignParentBottom="true"
- android:targetDrawables="@array/lockscreen_targets_with_camera"
- android:targetDescriptions="@array/lockscreen_target_descriptions_with_camera"
- android:directionDescriptions="@array/lockscreen_direction_descriptions"
- android:handleDrawable="@drawable/ic_lockscreen_handle"
- android:waveDrawable="@drawable/ic_lockscreen_outerring"
- android:outerRadius="@dimen/multiwaveview_target_placement_radius"
- android:snapMargin="@dimen/multiwaveview_snap_margin"
- android:hitRadius="@dimen/multiwaveview_hit_radius"
- android:rightChevronDrawable="@drawable/ic_lockscreen_chevron_right"
- android:horizontalOffset="0dip"
- android:verticalOffset="60dip"
- android:feedbackCount="3"
- android:vibrationDuration="20"
- />
- <!-- 锁屏界面加载运营商状态 -->
- <TextView
- android:id="@+id/carrier"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_alignParentBottom="true"
- android:layout_marginBottom="12dip"
- android:gravity="center_horizontal"
- android:singleLine="true"
- android:ellipsize="marquee"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
- android:textColor="?android:attr/textColorSecondary"
- />
- </RelativeLayout>
- <LinearLayout
- android:orientation="horizontal"
- android:layout_width="match_parent"
- style="?android:attr/buttonBarStyle"
- android:gravity="center"
- android:weightSum="2">
- <!-- 锁屏界面加载紧急拨号按钮 -->
- <Button android:id="@+id/emergencyCallButton"
- android:layout_gravity="center_horizontal"
- android:layout_width="0dip"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- style="?android:attr/buttonBarButtonStyle"
- android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"
- android:text="@*android:string/lockscreen_emergency_call"
- android:drawableLeft="@*android:drawable/lockscreen_emergency_button"
- android:drawablePadding="0dip"
- android:visibility="gone"
- />
- </LinearLayout>
- </GridLayout>
Step 4:在Step 3中重点看com.android.internal.widget.multiwaveview.MultiWaveView这个自定义的view,这个view是处理ICS4.0锁屏的拖拽的功能,具体代码如下:
- public MultiWaveView(Context context, AttributeSet attrs) {
- super(context, attrs);
- Resources res = context.getResources();
- 。。。 。。。
- 加载资源
- 。。。 。。。
- }
通过onMeasure()来计算自定义view的大小:
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- final int minimumWidth = getSuggestedMinimumWidth();
- final int minimumHeight = getSuggestedMinimumHeight();
- int viewWidth = resolveMeasured(widthMeasureSpec, minimumWidth);
- int viewHeight = resolveMeasured(heightMeasureSpec, minimumHeight);
- setMeasuredDimension(viewWidth, viewHeight);
- }
通过onLayout()来加载布局:
- protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
- super.onLayout(changed, left, top, right, bottom);
- final int width = right - left;
- final int height = bottom - top;
- float newWaveCenterX = mHorizontalOffset + Math.max(width, mOuterRing.getWidth() ) / 2;
- float newWaveCenterY = mVerticalOffset + Math.max(height, mOuterRing.getHeight()) / 2;
- if (newWaveCenterX != mWaveCenterX || newWaveCenterY != mWaveCenterY) {
- if (mWaveCenterX == 0 && mWaveCenterY == 0) {
- performInitialLayout(newWaveCenterX, newWaveCenterY);
- }
- mWaveCenterX = newWaveCenterX;
- mWaveCenterY = newWaveCenterY;
- mOuterRing.setX(mWaveCenterX);
- mOuterRing.setY(Math.max(mWaveCenterY, mWaveCenterY));
- updateTargetPositions();
- }
- if (DEBUG) dump();
- }
Step 5:来看看触摸屏幕时的事件处理onTouchEvent()代码如下:
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- final int action = event.getAction();
- boolean handled = false;
- switch (action) {
- case MotionEvent.ACTION_DOWN:
- handleDown(event);
- handled = true;
- break;
- case MotionEvent.ACTION_MOVE:
- handleMove(event);
- handled = true;
- break;
- case MotionEvent.ACTION_UP:
- handleMove(event);
- handleUp(event);
- handled = true;
- break;
- case MotionEvent.ACTION_CANCEL:
- handleMove(event);
- handled = true;
- break;
- }
- invalidate();
- return handled ? true : super.onTouchEvent(event);
- }
通过handleMove()来处理移动事件:
- private void handleMove(MotionEvent event) {
- if (!mDragging) {
- trySwitchToFirstTouchState(event);
- return;
- }
- int activeTarget = -1;
- final int historySize = event.getHistorySize();
- for (int k = 0; k < historySize + 1; k++) {
- float x = k < historySize ? event.getHistoricalX(k) : event.getX();
- float y = k < historySize ? event.getHistoricalY(k) : event.getY();
- float tx = x - mWaveCenterX;
- float ty = y - mWaveCenterY;
- float touchRadius = (float) Math.sqrt(dist2(tx, ty));
- final float scale = touchRadius > mOuterRadius ? mOuterRadius / touchRadius : 1.0f;
- float limitX = mWaveCenterX + tx * scale;
- float limitY = mWaveCenterY + ty * scale;
- boolean singleTarget = mTargetDrawables.size() == 1;
- if (singleTarget) {
- // Snap to outer ring if there's only one target
- float snapRadius = mOuterRadius - mSnapMargin;
- if (touchRadius > snapRadius) {
- activeTarget = 0;
- x = limitX;
- y = limitY;
- }
- } else {
- // If there's more than one target, snap to the closest one less than hitRadius away.
- float best = Float.MAX_VALUE;
- final float hitRadius2 = mHitRadius * mHitRadius;
- for (int i = 0; i < mTargetDrawables.size(); i++) {
- // Snap to the first target in range
- TargetDrawable target = mTargetDrawables.get(i);
- float dx = limitX - target.getX();
- float dy = limitY - target.getY();
- float dist2 = dx*dx + dy*dy;
- if (target.isValid() && dist2 < hitRadius2 && dist2 < best) {
- activeTarget = i;
- best = dist2;
- }
- }
- x = limitX;
- y = limitY;
- }
- if (activeTarget != -1) {
- switchToState(STATE_SNAP, x,y);
- float newX = singleTarget ? limitX : mTargetDrawables.get(activeTarget).getX();
- float newY = singleTarget ? limitY : mTargetDrawables.get(activeTarget).getY();
- moveHandleTo(newX, newY, false);
- TargetDrawable currentTarget = mTargetDrawables.get(activeTarget);
- if (currentTarget.hasState(TargetDrawable.STATE_FOCUSED)) {
- currentTarget.setState(TargetDrawable.STATE_FOCUSED);
- mHandleDrawable.setAlpha(0.0f);
- }
- } else {
- switchToState(STATE_TRACKING, x, y);
- moveHandleTo(x, y, false);
- mHandleDrawable.setAlpha(1.0f);
- }
- }
- // Draw handle outside parent's bounds
- invalidateGlobalRegion(mHandleDrawable);
- if (mActiveTarget != activeTarget && activeTarget != -1) {
- dispatchGrabbedEvent(activeTarget);
- if (AccessibilityManager.getInstance(mContext).isEnabled()) {
- String targetContentDescription = getTargetDescription(activeTarget);
- announceText(targetContentDescription);
- }
- }
- mActiveTarget = activeTarget;
- }
以上主要工作是绘制拖拽的参数以及绘制出来。通过invalidate()来主动刷屏幕;
在onDraw()方法中实现绘制图形,代码如下:
- @Override
- protected void onDraw(Canvas canvas) {
- mOuterRing.draw(canvas);
- for (TargetDrawable target : mTargetDrawables) {
- if (target != null) {
- target.draw(canvas);
- }
- }
- for (TargetDrawable target : mChevronDrawables) {
- if (target != null) {
- target.draw(canvas);
- }
- }
- mHandleDrawable.draw(canvas);
- }
在handleMove()方法中——>trySwitchToFirstTouchState(event);——>switchToState()——>doFinish();
——>setGrabbedState() ————> mOnTriggerListener.onGrabbedStateChange(this, mGrabbedState);
设置回调。
Step 6: LockScreen.java中有个内部类,监听这个移动事件的状态,——> 代码如下:
- class MultiWaveViewMethods implements MultiWaveView.OnTriggerListener,
- UnlockWidgetCommonMethods {
- private final MultiWaveView mMultiWaveView;
- private boolean mCameraDisabled;
- MultiWaveViewMethods(MultiWaveView multiWaveView) {
- mMultiWaveView = multiWaveView;
- final boolean cameraDisabled = mLockPatternUtils.getDevicePolicyManager()
- .getCameraDisabled(null);
- if (cameraDisabled) {
- Log.v(TAG, "Camera disabled by Device Policy");
- mCameraDisabled = true;
- } else {
- // Camera is enabled if resource is initially defined for MultiWaveView
- // in the lockscreen layout file
- mCameraDisabled = mMultiWaveView.getTargetResourceId()
- != R.array.lockscreen_targets_with_camera;
- }
- }
- public void updateResources() {
- int resId;
- if (mCameraDisabled) {
- // Fall back to showing ring/silence if camera is disabled by DPM...
- resId = mSilentMode ? R.array.lockscreen_targets_when_silent
- : R.array.lockscreen_targets_when_soundon;
- } else {
- resId = R.array.lockscreen_targets_with_camera;
- }
- mMultiWaveView.setTargetResources(resId);
- }
- public void onGrabbed(View v, int handle) {
- }
- public void onReleased(View v, int handle) {
- }
- public void onTrigger(View v, int target) {
- if (target == 0 || target == 1) { // 0 = unlock/portrait, 1 = unlock/landscape
- mCallback.goToUnlockScreen();
- } else if (target == 2 || target == 3) { // 2 = alt/portrait, 3 = alt/landscape
- if (!mCameraDisabled) {
- // Start the Camera
- Intent intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- mContext.startActivity(intent);
- mCallback.goToUnlockScreen();
- } else {
- toggleRingMode();
- mUnlockWidgetMethods.updateResources();
- mCallback.pokeWakelock();
- }
- }
- }
- public void onGrabbedStateChange(View v, int handle) {
- // Don't poke the wake lock when returning to a state where the handle is
- // not grabbed since that can happen when the system (instead of the user)
- // cancels the grab.
- if (handle != MultiWaveView.OnTriggerListener.NO_HANDLE) {
- mCallback.pokeWakelock();
- }
- }
- public View getView() {
- return mMultiWaveView;
- }
- public void reset(boolean animate) {
- mMultiWaveView.reset(animate);
- }
- public void ping() {
- mMultiWaveView.ping();
- }
- }
重点看public void onTrigger()这个方法,用于处理拖拽启动那个activity,一个启动camera,一个正常解锁。
锁屏的大概这个流程就是这个样子了,大家应该会一目了然了。由于时间仓促,难免有点纰漏,希望大家指正错误,如有不解的地方,欢迎留言探讨!!!
来源:oschina
链接:https://my.oschina.net/u/250247/blog/68663