Android 4.0 自定义锁屏

          在Android 4.0上做锁屏有一段时间了,期间改了很多bug,也按不同需求做了不少锁屏,其中比较满意的作品包括两个。一是,添加一个锁屏可以和原生锁屏进行切换;二是,自己写一个锁屏view去替换原生锁屏。在这里,先把第二种实现方法写出来。

         先介绍下这个锁屏view:

        

       锁屏效果如图所示。功能简介如下:

               1.相机、电话、home、短信四个icon向中间拖拽会进入相应的应用程序,拖拽的同时有波纹动画。

               2.拖拽中间的图案向外任意方向解锁。

               3.可以在相册中选取一张图片或者用相机拍摄一张图片作为中心的图案。

               4.进入home解锁和中心图案解锁的区别是:进入home,就是进入launcher,比如有两个launcher,会弹出选择框。锁屏之前如果打开了应用程序,home解锁不会进入打开的应用程序,而中心图案解锁会进入之前打开的程序。

       实现这个锁屏主要在framework中修改,当然,设置锁屏图案功能是在settings中修改。在framework中主要有三个文件:

    1.frameworks\base\core\java\com\android\internal\widget\multiwaveview\FxFloatImageView.java

    2.frameworks\base\core\res\res\layout\keyguard_screen_tab_unlock.xml

    3.frameworks\base\policy\src\com\android\internal\policy\impl\ LockScreen.java

    这三个文件其实就是自定义view、加载自定义view的xml文件、锁屏的逻辑处理。其中,自定义view一般放在frameworks\base\core\java\com\android\internal\widget\目录下,我为了利用4.0的波纹动画,才放在子目录multiwaveview下面的。

    下面逐一道来。

   一、自定义锁屏view:

这里给出部分代码,完整代码可以通过连接下载
final AlphaAnimation animation = new AlphaAnimation(1, 0);
private TimeInterpolator mChevronAnimationInterpolator = Ease.Quad.easeOut;
private ArrayList<TargetDrawable> mTargetDrawables = new ArrayList<TargetDrawable>();
private ArrayList<TargetDrawable> mChevronDrawables = new ArrayList<TargetDrawable>();
private ArrayList<Tweener> mChevronAnimations = new ArrayList<Tweener>();
private static final int CHEVRON_INCREMENTAL_DELAY = 160;
private static final int CHEVRON_ANIMATION_DURATION = 850;
private AnimatorUpdateListener mUpdateListener = new AnimatorUpdateListener() {
public void onAnimationUpdate(ValueAnimator animation) {
invalidate();
}
};

public interface OnTriggerListener {
/**
* The interface was triggered because the user let go of the handle
* without reaching the threshold.
*/
public static final int NO_HANDLE = 0;
public static final int SMS_HANDLE = 1;
public static final int DIAR_HANDLE = 2;
public static final int CAM_HANDLE = 3;
public static final int UNLOCK_HANDLE = 4;
public static final int HOME_HANDLE = 5;

/**
* Called when the user moves a handle beyond the threshold.
*
* @param v
* The view that was triggered.
* @param whichHandle
* Which "dial handle" the user grabbed, either
* {@link #LEFT_HANDLE}, {@link #RIGHT_HANDLE}.
*/
void onTrigger(View v, int mHandle);

/**
* Called when the "grabbed state" changes (i.e. when the user either
* grabs or releases one of the handles.)
*
* @param v
* the view that was triggered
* @param grabbedState
* the new state: {@link #NO_HANDLE}, {@link #LEFT_HANDLE},
* or {@link #RIGHT_HANDLE}.
*/
}

public FxFloatImageView(Context context) {
super(context);
// TODO Auto-generated constructor stub
logv("FxFloatImageView(Context context)");

}

public FxFloatImageView(Context context, AttributeSet attrs) {
super(context, attrs);
logv("FxFloatImageView(Context context, AttributeSet attrs)");
Resources res = context.getResources();
TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.MultiWaveView);
mTracking = false;
mInit = true;
isFinish = false;
mContext = context;
resetScreenState(mTracking);
getBitmapFromQueryDB();
loadView(context);

this.setWillNotDraw(false);
// Read chevron animation drawables
final int chevrons[] = { R.styleable.MultiWaveView_leftChevronDrawable,
R.styleable.MultiWaveView_rightChevronDrawable,
R.styleable.MultiWaveView_topChevronDrawable,
R.styleable.MultiWaveView_bottomChevronDrawable };
for (int chevron : chevrons) {
Drawable chevronDrawable = a.getDrawable(chevron);
for (int i = 0; i < 3; i++) {
mChevronDrawables
.add(chevronDrawable != null ? new TargetDrawable(res,
chevronDrawable) : null);
}
}
hideChevrons();

// handler.postDelayed(runnable, 150);
// handler.postDelayed(runnableIndication, 500);
}
private void hideChevrons() {
for (TargetDrawable chevron : mChevronDrawables) {
if (chevron != null) {
chevron.setAlpha(0.0f);
}
}
}

protected void onDraw(Canvas canvas) {
int i =0;
for (TargetDrawable target : mChevronDrawables) {
if (target != null ) {
target.draw(canvas);
}
}

}

private void startChevronAnimation() {

final float chevronAnimationDistance = 80;
final float from[][] = {
{
mWidth / 2 - 150 + 20,
mCircleBgViewY + mCircleBgViewHeight / 2
- mChevronHeight / 2 + 20 }, // left
{
mWidth / 2 + 150 - mChevronWidth + 20,
mCircleBgViewY + mCircleBgViewHeight / 2
- mChevronHeight / 2 + 20 }, // right
{ mWidth / 2 - mChevronHeight / 2 + 25,
mCircleBgViewY + mCircleBgViewHeight / 2 - 135 + 10, }, // top
{ mWidth / 2 - mChevronHeight / 2 + 25,
mCircleBgViewY + mCircleBgViewHeight / 2 + 100 + 20 } }; // bottom
final float to[][] = {
{
mWidth / 2 - 150 + 80 + 20,
mCircleBgViewY + mCircleBgViewHeight / 2
- mChevronHeight / 2 + 20 }, // left
{
mWidth / 2 + 150 - mChevronWidth - 80 + 20,
mCircleBgViewY + mCircleBgViewHeight / 2
- mChevronHeight / 2 + 20 }, // right
{
mWidth / 2 - mChevronHeight / 2 + 25,
mCircleBgViewY + mCircleBgViewHeight / 2 - 135 + 80
+ 10, }, // top
{
mWidth / 2 - mChevronHeight / 2 + 25,
mCircleBgViewY + mCircleBgViewHeight / 2 + 100 - 80
+ 20 } }; // bottom

mChevronAnimations.clear();
final float startScale = 0.5f;
final float endScale = 2.0f;


for (int direction = 0; direction < 4; direction++) {
if(show[direction]){
for (int count = 0; count < 3; count++) {
int delay = count * CHEVRON_INCREMENTAL_DELAY;
final TargetDrawable icon = mChevronDrawables.get(direction * 3
+ count);
if (icon == null) {
continue;
}
mChevronAnimations.add(Tweener.to(icon,
CHEVRON_ANIMATION_DURATION, "ease",
mChevronAnimationInterpolator, "delay", delay, "x",
new float[] { from[direction][0], to[direction][0] },
"y",
new float[] { from[direction][1], to[direction][1] },
"alpha", new float[] { 1.0f, 0.0f }, "scaleX",
new float[] { startScale, endScale }, "scaleY",
new float[] { startScale, endScale }, "onUpdate",
mUpdateListener));
}
show[direction] = false;

}

}
}

@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
// TODO Auto-generated method stub

logv("onLayout");
logv("onLayout changed=" + String.valueOf(changed));
if (changed) {

mUnlockView.measure(View.MeasureSpec.makeMeasureSpec(0,
View.MeasureSpec.UNSPECIFIED), View.MeasureSpec
.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
mUnlockViewWidth = mUnlockView.getMeasuredWidth();
mUnlockViewHeight = mUnlockView.getMeasuredHeight();

mUnlockBgView.measure(View.MeasureSpec.makeMeasureSpec(0,
View.MeasureSpec.UNSPECIFIED), View.MeasureSpec
.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
mUnlockBgViewWidth = mUnlockBgView.getMeasuredWidth();
mUnlockBgViewHeight = mUnlockBgView.getMeasuredWidth();

mCircleBgView.measure(View.MeasureSpec.makeMeasureSpec(0,
View.MeasureSpec.UNSPECIFIED), View.MeasureSpec
.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
mCircleBgViewWidth = mCircleBgView.getMeasuredWidth();
mCircleBgViewHeight = mCircleBgView.getMeasuredHeight();

mSmsView.measure(View.MeasureSpec.makeMeasureSpec(0,
View.MeasureSpec.UNSPECIFIED), View.MeasureSpec
.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
mCommonViewWidth = mSmsView.getMeasuredWidth();
mCommonViewHeight = mSmsView.getMeasuredHeight();

mChevronLeft.measure(View.MeasureSpec.makeMeasureSpec(0,
View.MeasureSpec.UNSPECIFIED), View.MeasureSpec
.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
mChevronWidth = mChevronLeft.getMeasuredWidth();
mChevronHeight = mChevronLeft.getMeasuredHeight();

logv("onLayout l=" + String.valueOf(l));
logv("onLayout t=" + String.valueOf(t));
logv("onLayout r=" + String.valueOf(r));
logv("onLayout b=" + String.valueOf(b));
logv("onLayout mUnlockViewWidth="
+ String.valueOf(mUnlockViewWidth));
logv("onLayout mUnlockViewHeight="
+ String.valueOf(mUnlockViewHeight));
logv("onLayout mUnlockBgViewWidth="
+ String.valueOf(mUnlockBgViewWidth));
logv("onLayout mUnlockBgViewHeight="
+ String.valueOf(mUnlockBgViewHeight));
Log.v(TAG,
"onLayout mCircleBgViewWidth="
+ String.valueOf(mCircleBgViewWidth));
logv("onLayout mCircleBgViewHeigh="
+ String.valueOf(mCircleBgViewHeight));
logv("onLayout mBotWidth=" + String.valueOf(mBotWidth));
logv("onLayout mBotHeight=" + String.valueOf(mBotHeight));
logv("onLayout mCommonViewWidth="
+ String.valueOf(mCommonViewWidth));
logv("onLayout mCommonViewHeight="
+ String.valueOf(mCommonViewHeight));
logv("the center X is:" + String.valueOf(mWidth / 2));
logv("the center Y is:"
+ String.valueOf(mCircleBgViewY + mCircleBgViewHeight / 2));

mWidth = r - l;
mHeight = b - t;

// mBgview.layout(l + (mWidth - mCircleBgViewWidth) / 2, t + top, r
// - (mWidth - mCircleBgViewWidth) / 2, t + top
// + mCircleBgViewHeight);

mUnlockViewX = l + (mWidth - mUnlockViewWidth) / 2;
mUnlockViewY = t + top + 3
+ (mCircleBgViewHeight - mUnlockViewHeight) / 2;
mUnlockBg

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值