KeyguardSecurityViewHelper
这个类的作用是帮助所有的KeyguardSecurityView实现两个基本方法:showBouncer和hideBouncer。
public static void showBouncer(SecurityMessageDisplay securityMessageDisplay, final View ecaView, Drawable bouncerFrame, int duration) {
//1st securityMessageDisplay不为空,则直接调用它的showBouncer方法
if (securityMessageDisplay != null) {
securityMessageDisplay.showBouncer(duration);
}
//2nd ecaView不为空,则令其不可见,并设置为完全透明
if (ecaView != null) {
//如果duration>0,则需要渐进地达到不可见和完全透明的效果
if (duration > 0) {
//这里的0f表明最终目标是要达到透明度为0--完全透明
Animator anim = ObjectAnimator.ofFloat(ecaView, "alpha", 0f);
anim.setDuration(duration);
anim.addListener(new AnimatorListenerAdapter() {
private boolean mCanceled;
@Override
public void onAnimationCancel(Animator animation) {
//如果在过程中用户取消,标记mCanceled并设置完全可见
mCanceled = true;
ecaView.setAlpha(1f);
}
@Override
public void onAnimationEnd(Animator animation) {
//动画结束,如果不曾取消过,则设置其不可见
ecaView.setVisibility(mCanceled ? View.VISIBLE : View.INVISIBLE);
}
});
anim.start();
} else {
//不需动画效果,直接设置完全透明和不可见
ecaView.setAlpha(0f);
ecaView.setVisibility(View.INVISIBLE);
}
}
//3nd bouncerFrame不为空,则设置其完全不透明
if (bouncerFrame != null) {
if (duration > 0) {
//需要动画显示,则从0--完全透明到255--完全不透明
Animator anim = ObjectAnimator.ofInt(bouncerFrame, "alpha", 0, 255);
anim.setDuration(duration);
anim.start();
} else {
//不需要动画显示,则直接设置其完全不透明
bouncerFrame.setAlpha(255);
}
}
}
从这里的分析可以看出,这里的操作取决于securityMessageDisplay、ecaView和bouncerFrame是否为空,它们分别代码三个view,执行不同的操作。
如果这三者都是空的,则什么也不做。
hideBouncer与showBouncer方法类似,只是效果刚好相反而已。
下面来看看这三个view到底是什么?
1. securityMessageDisplay
首先,它是SecurityMessageDisplay接口的实例,它其实是个KeyguardMessageArea:
mSecurityMessageDisplay = new KeyguardMessageArea.Helper(this);
//KeyguardMessageArea.java
public static class Helper implements SecurityMessageDisplay {
KeyguardMessageArea mMessageArea;
Helper(View v) {
mMessageArea = (KeyguardMessageArea) v.findViewById(R.id.keyguard_message_area);
if (mMessageArea == null) {
throw new RuntimeException("Can't find keyguard_message_area in " + v.getClass());
}
}
//它的操作很简单,只是要hideMessage
public void showBouncer(int duration) {
mMessageArea.hideMessage(duration, false);
mMessageArea.mShowingBouncer = true;
}
......
}
//这个方法因为调用时thenUpdate为false,因此我就把thenUpdate相关的删除了
//这个方法实际的工作就是令KeyguardMessageArea完全透明(KeyguardMessageArea extends TextView)
private void hideMessage(int duration, boolean thenUpdate) {
if (duration > 0) {
Animator anim = ObjectAnimator.ofFloat(this, "alpha", 0f);
anim.setDuration(duration);
anim.start();
} else {
setAlpha(0f);
}
}
2. ecaView
这个ecaView实际是EmergencyCarrierArea。
以keyguard_pattern_view.xml为例,在它的布局文件中有如下:
<include layout="@layout/keyguard_eca"
android:id="@+id/keyguard_selector_fade_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_gravity="bottom|center_horizontal"
android:gravity="center_horizontal" />
id为keyguard_selector_fade_container,include layout为keyguard_eca,它实际是一个引用,指向另一个layout:
values-land/alias.xml
<resources>
<!-- Alias used to reference one of two possible layouts in keyguard. -->
<item type="layout" name="keyguard_eca">@layout/keyguard_emergency_carrier_area_empty</item>
</resources>
keyguard_emergency_carrier_area_empty.xml
<!-- This is a blank layout to simplify implementation on landscape on phones
it is referenced indirectly by keyguard_eca -->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="0dip"
android:layout_height="0dip"
android:orientation="vertical"
android:gravity="center"
android:layout_gravity="center_horizontal"
android:layout_alignParentBottom="true">
</LinearLayout>
values-port/alias.xml
<resources>
<!-- Alias used to reference one of two possible layouts in keyguard. -->
<item type="layout" name="keyguard_eca">@layout/keyguard_emergency_carrier_area</item>
</resources>
对于alias.xml文件,有横屏和竖屏两种配置。
对于横屏,它指向的布局文件为keyguard_emergency_carrier_area_empty.xml
从文件名称、xml文件中的注释以及layout_width和layout_height的值都为0dip可以看出,这是一个不占空间的布局文件。忽略它。
对于竖屏,它指向的布局文件为keyguard_emergency_carrier_area.xml。
它就比较复杂了,其中有一个TextView和两个Button。
下面来看看各个KeyguardSecurityView的两个方法:showBouncer和hideBouncer
我们知道一共有11个KeyguardSecurityView的实例,这其中有两个比较特殊。
一般地,实现如下:
//onFinishInflate方法中
mEcaView = findViewById(R.id.keyguard_selector_fade_container);
第一个特殊的是KeyguardSelectorView
public void setCarrierArea(View carrierArea) {
mFadeView = carrierArea;
/// M: [ALPS00475227] To avoid blade shade while using marquee with alpha animation @{
mFadeView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
}
public void showBouncer(int duration) {
mIsBouncing = true;
KeyguardSecurityViewHelper.showBouncer(mSecurityMessageDisplay, mFadeView, mBouncerFrame, duration);
}
//KeyguardHostView.java getSecurityView方法
if (view instanceof KeyguardSelectorView) {
KeyguardSelectorView selectorView = (KeyguardSelectorView) view;
View carrierText = selectorView.findViewById(R.id.keyguard_selector_fade_container);
selectorView.setCarrierArea(carrierText);
}
第二个特殊的是KeyguardAccountView
它的布局文件keyguard_account_view.xml中没有定义这个view,有如下注释
<!-- no room for ECA on this screen right now -->
因此它的showBouncer和hideBouncer的实现均为空实现。
3. mBouncerFrame
它是个Background,各view的实现基本与ecaView一致:KeyguardAccountView没有,KeyguardSelectorView使用上特殊一些
一般地:
View bouncerFrameView = findViewById(R.id.keyguard_bouncer_frame);
if (bouncerFrameView != null) {
mBouncerFrame = bouncerFrameView.getBackground();
}
KeyguardSelectorView在布局文件中的id特殊
//onFinishInflate方法
View bouncerFrameView = findViewById(R.id.keyguard_selector_view_frame);
mBouncerFrame = bouncerFrameView.getBackground();
关于透明度设置的API:
1. setAlpha
public void setAlpha (float alpha)
Sets the opacity of the view. This is a value from 0 to 1, where 0 means the view is completely transparent and 1 means the view is completely opaque.
protected boolean onSetAlpha (int alpha)
参数a为透明度,取值范围为0~255,数值越小越透明
2. public static ObjectAnimator ofInt (Object target, String propertyName, int... values)
Constructs and returns an ObjectAnimator that animates between int values.
A single value implies that that value is the one being animated to.
Two values imply a starting and ending values.
More than two values imply a starting value, values to animate through along the way, and an ending value (these values will be distributed evenly across the duration of the animation).