根据网上资料,在android4.0上实现一个简单的锁屏程序。
先贴上布局文件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity" >
<com.wind.dragimg.SliderRelativeLayout
android:id="@+id/slider_layout"
android:layout_width="match_parent"
android:layout_height="63dip"
android:layout_marginTop="200dip"
android:background="@drawable/step2_tip_2">
<ImageView
android:id="@+id/getup_finish_ico"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="10dip"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:background="@drawable/slider_ico_alarm"
android:contentDescription="@string/app_name"/>
<ImageView
android:id="@+id/getup_arrow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="20dip"
android:layout_toLeftOf="@id/getup_finish_ico"
android:layout_alignTop="@id/getup_finish_ico"
android:src="@drawable/slider_tip_anim"
android:contentDescription="@string/app_name"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#ff0000"
android:layout_marginRight="20dip"
android:layout_toLeftOf="@id/getup_arrow"
android:layout_alignTop="@id/getup_finish_ico"
android:text="@string/hint_unlock"/>
<!-- slider img -->
<ImageView android:id="@+id/slider_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="5dip"
android:src="@drawable/getup_slider_ico_normal"
android:contentDescription="@string/app_name"/>
</com.wind.dragimg.SliderRelativeLayout>
</LinearLayout>
布局文件中用了一个自定义的ViewGroup :SliderRelativeLayout,滑动解锁的主要功能就是在这个class文件中实现的。
下边先看下这个class文件
package com.wind.dragimg;
import java.lang.ref.WeakReference;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.os.Handler;
import android.os.Message;
import android.os.Vibrator;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.Toast;
public class SliderRelativeLayout extends RelativeLayout{
private Context mContext;
private ImageView tv_slider_icon;
private Bitmap dragBitmap;
private int mLastMoveX;
private Handler mainHandler;
private Handler mHandler;
private static final int MSG_BACK_SLIDER_IMG = 1;
private static final int DELAY_TIME = 5;
public SliderRelativeLayout(Context context) {
super(context);
mContext = context;
mHandler = new MyHandler(this);
initDragBitmap();
}
private void initDragBitmap() {
if (dragBitmap == null) {
dragBitmap = BitmapFactory.decodeResource(mContext.getResources(),
R.drawable.getup_slider_ico_pressed);
}
}
public SliderRelativeLayout(Context context, AttributeSet attrs,
int defStyle) {
super(context, attrs, defStyle);
mContext = context;
mHandler = new MyHandler(this);
initDragBitmap();
}
public SliderRelativeLayout(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
mHandler = new MyHandler(this);
initDragBitmap();
}
@Override
protected void onFinishInflate() {
// TODO Auto-generated method stub
super.onFinishInflate();
tv_slider_icon = (ImageView)findViewById(R.id.slider_icon);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mLastMoveX = (int)event.getX();
return handleActionDownEvent(event);
case MotionEvent.ACTION_MOVE:
mLastMoveX = (int)event.getX();
invalidate();
return true;
case MotionEvent.ACTION_UP:
handleActionUpEvent(event);
return true;
default:
break;
}
return super.onTouchEvent(event);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
invalidateDragImg(canvas);
}
private void invalidateDragImg(Canvas canvas) {
int drawX = mLastMoveX - dragBitmap.getWidth();
int drawY = tv_slider_icon.getTop();
canvas.drawBitmap(dragBitmap, drawX < 0 ? 5 : drawX, drawY, null);
}
private void handleActionUpEvent(MotionEvent event) {
int x = (int)event.getX();
boolean isSuccess = Math.abs(x - getRight()) <= 15;
if (isSuccess) {
Toast.makeText(mContext, R.string.unlock_success, Toast.LENGTH_LONG).show();
resetViewState();
vibrate();
mainHandler.obtainMessage(MainActivity.MSG_LOCK_SUCCESS).sendToTarget();
} else {
mLastMoveX = x;
int distance = x - tv_slider_icon.getRight();
if (distance > 0) {
mHandler.sendEmptyMessageDelayed(MSG_BACK_SLIDER_IMG, DELAY_TIME);
} else {
resetViewState();
}
}
}
private void vibrate() {
Vibrator vibrator= (Vibrator)mContext.getSystemService(Context.VIBRATOR_SERVICE);
vibrator.vibrate(200);
}
private void resetViewState() {
mLastMoveX = 1000;
tv_slider_icon.setVisibility(View.VISIBLE);
invalidate();
}
private boolean handleActionDownEvent(MotionEvent event) {
Rect rect = new Rect();
tv_slider_icon.getHitRect(rect);
boolean isHit = rect.contains((int)event.getX(), (int)event.getY());
if (isHit) {
tv_slider_icon.setVisibility(View.INVISIBLE);
}
return isHit;
}
private static class MyHandler extends Handler{
private WeakReference<SliderRelativeLayout> mLayout;
public MyHandler(SliderRelativeLayout layout) {
mLayout = new WeakReference<SliderRelativeLayout>(layout);
}
@Override
public void handleMessage(Message msg) {
SliderRelativeLayout layout = mLayout.get();
switch (msg.what) {
case MSG_BACK_SLIDER_IMG:
layout.backSliderImg();
break;
default:
break;
}
}
}
private void backSliderImg() {
mLastMoveX = mLastMoveX - 8;
invalidate();
boolean shoudEnd = Math.abs(mLastMoveX - tv_slider_icon.getRight()) <= 8;
if (!shoudEnd) {
mHandler.sendEmptyMessageDelayed(MSG_BACK_SLIDER_IMG, DELAY_TIME);
} else {
resetViewState();
}
}
public void setMainHandler(Handler handler) {
mainHandler = handler;
}
}
此应用中还用到了一个帧动画。布局文件如下:
<?xml version="1.0" encoding="utf-8"?>
<animation-list
xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="false">
<item android:drawable="@drawable/slider_arrow_1" android:duration="150"></item>
<item android:drawable="@drawable/slider_arrow_2" android:duration="150"></item>
<item android:drawable="@drawable/slider_arrow_3" android:duration="150"></item>
</animation-list>
帧动画的具体实现看以参看我其他的文章
下边看下主activity类,这个类中有一些锁屏功能所需要的必要设置,比如屏蔽Home键等。
package com.wind.dragimg;
import java.lang.ref.WeakReference;
import android.app.Activity;
import android.content.Intent;
import android.graphics.drawable.AnimationDrawable;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.Window;
import android.view.WindowManager;
import android.widget.ImageView;
public class MainActivity extends Activity {
private ImageView animal;
private AnimationDrawable animationDrawable;
public final static int MSG_LOCK_SUCCESS = 1;
public static final int FLAG_HOMEKEY_DISPATCHED = 0x80000000;
private SliderRelativeLayout sliderRelativeLayout;
private Handler mHandler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//窗口无标题
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
//窗口全屏显示
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
this.getWindow().setFlags(FLAG_HOMEKEY_DISPATCHED, FLAG_HOMEKEY_DISPATCHED);
//为窗口添加了这个标志后,当前activity运行的时候不会锁屏
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD,
WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
setContentView(R.layout.activity_main);
animal = (ImageView)this.findViewById(R.id.getup_arrow);
sliderRelativeLayout = (SliderRelativeLayout)this.findViewById(R.id.slider_layout);
animationDrawable = (AnimationDrawable)animal.getDrawable();
animationDrawable.start();
mHandler = new MyHandler(this);
sliderRelativeLayout.setMainHandler(mHandler);
startService(new Intent(MainActivity.this, DragImgService.class));
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
//这个函数可以屏蔽Back键,Menu键
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_BACK:
return true;
case KeyEvent.KEYCODE_MENU:
return true;
default:
break;
}
return super.onKeyDown(keyCode, event);
}
private static class MyHandler extends Handler {
private WeakReference<MainActivity> mActivity;
public MyHandler(MainActivity mainAcvity) {
this.mActivity = new WeakReference<MainActivity>(mainAcvity);
}
@Override
public void handleMessage(Message msg) {
MainActivity activity = mActivity.get();
switch (msg.what) {
case MSG_LOCK_SUCCESS:
activity.closeActivity();
break;
default:
break;
}
}
}
private void closeActivity() {
finish();
}
}
为了能实现手机灭屏后开启锁屏程序,我添加了一个service,具体实现如下
package com.wind.dragimg;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.IBinder;
public class DragImgService extends Service{
private Intent mainIntent;
private BroadcastReceiver screenOffReceiver;
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
@Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
mainIntent = new Intent(DragImgService.this, MainActivity.class);
mainIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
IntentFilter screenOffFilter = new IntentFilter("android.intent.action.SCREEN_OFF");
screenOffReceiver = new ScreenOffReceiver();
registerReceiver(screenOffReceiver, screenOffFilter);
}
@Override
public void onDestroy() {
super.onDestroy();
unregisterReceiver(screenOffReceiver);
startService(new Intent(DragImgService.this, DragImgService.class));
}
private class ScreenOffReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
String screen_off_action = "android.intent.action.SCREEN_OFF";
if (action.equals(screen_off_action)) {
context.startActivity(mainIntent);
}
}
}
}
至此,锁屏的主要功能已经实现