Android4.0实现一个简单的锁屏程序
jopen
10年前
在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); } } } }
至此,锁屏的主要功能已经实现