转载自;http://blog.csdn.net/zhiyuan0932/article/details/51472289
代码参考地址 https://github.com/liuzhiyuan0932/SlideUnLock
代码效果图>
自定义滑动解锁的控件继承自View
public class SlideUnlockView extends View
自定义SlideUnLockView的属性
<?xml version="1.0" encoding="utf-8"?><resources> <declare-styleable name="SlideUnlockButton"> <attr name="slideUnlockBackgroundResource" format="reference" /> <attr name="slideUnlockBlockResource" format="reference" /> </declare-styleable></resources>
<com.zhiyuan.slideunlockdemo.view.SlideUnlockView android:id="@+id/slideUnlockView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" test:slideUnlockBackgroundResource="@drawable/jiesuo_bg" test:slideUnlockBlockResource="@drawable/jiesuo_button" />
定义滑块的几种状态
/** * 滑块当前的状态 */ public int currentState; /** * 未解锁 */ public static final int STATE_LOCK = 1; /** * 解锁 */ public static final int STATE_UNLOCK = 2; /** * 正在拖拽 */ public static final int STATE_MOVING = 3;
获取图片资源,并进行初始绘制
public SlideUnlockView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); currentState = STATE_LOCK; String namespace = "http://schemas.android.com/apk/res/com.zhiyuan.slideunlockdemo"; int slideUnlockBackgroundResource = attrs.getAttributeResourceValue( namespace, "slideUnlockBackgroundResource", -1); int slideUnlockBlockResource = attrs.getAttributeResourceValue( namespace, "slideUnlockBlockResource", -1); /** * 当取出自定义属性的背景时,设置背景 */ setSlideUnlockBackground(slideUnlockBackgroundResource); /** * 当取出自定义属性的滑块时,设置滑块的图片 */ setSlideUnlockBlock(slideUnlockBlockResource); /** * 执行onDraw方法,进行界面绘制 */ postInvalidate(); }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 设置图片的方法,设置好图片之后,进行界面的初始 绘制
/** * 设置背景图 * @param slideUnlockBackgroundResource */ public void setSlideUnlockBackground(int slideUnlockBackgroundResource) { slideUnlockBackground = BitmapFactory.decodeResource(getResources(), slideUnlockBackgroundResource); blockBackgoundWidth = slideUnlockBackground.getWidth(); } /** * 设置滑块图 * @param slideUnlockBlockResource */ public void setSlideUnlockBlock(int slideUnlockBlockResource) { slideUnlockBlock = BitmapFactory.decodeResource(getResources(), slideUnlockBlockResource); blockWidth = slideUnlockBlock.getWidth(); blockHeight = slideUnlockBlock.getHeight(); }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
通过测量背景图的宽高设置SlideUnLockView的宽高
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); setMeasuredDimension(slideUnlockBackground.getWidth(), slideUnlockBackground.getHeight()); }
处理onTouch事件
/** * 计算手指是否是落在了滑块上(默认是按照滑块在未解锁的初始位置来计算的) */ public boolean isDownOnBlock(float x1, float x2, float y1, float y2) { float sqrt = FloatMath.sqrt(Math.abs(x1 - x2) * Math.abs(x1 - x2) + Math.abs(y1 - y2) * Math.abs(y1 - y2)); if (sqrt <= blockWidth / 2) { return true; } return false; }
@Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: if (currentState != STATE_MOVING) { x = event.getX(); y = event.getY(); float blockCenterX = blockWidth * 1.0f / 2; float blockCenterY = blockHeight * 1.0f / 2; downOnBlock = isDownOnBlock(blockCenterX, x, blockCenterY, y); Log.i(TAG, "down......................"); postInvalidate(); } break; case MotionEvent.ACTION_MOVE: if (downOnBlock) { x = event.getX(); y = event.getY(); currentState = STATE_MOVING; Log.i(TAG, "move......................"); postInvalidate(); } break; case MotionEvent.ACTION_UP: if (currentState == STATE_MOVING) { if (x < blockBackgoundWidth - blockWidth) { handler.sendEmptyMessageDelayed(0, 10); onUnLockListener.setUnLocked(false); } else { currentState = STATE_UNLOCK; onUnLockListener.setUnLocked(true); } downOnBlock = false; postInvalidate(); } break; default: break; } return true; }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
调用OnDraw方法并根据状态进行绘制
@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.drawBitmap(slideUnlockBackground, 0, 0, null); /** * 判断当前状态 */ switch (currentState) { case STATE_LOCK: canvas.drawBitmap(slideUnlockBlock, 0, 0, null); break; case STATE_UNLOCK: int unlockX = blockBackgoundWidth - blockWidth; canvas.drawBitmap(slideUnlockBlock, unlockX, 0, null); break; case STATE_MOVING: if (x < 0) { x = 0; } else if (x > blockBackgoundWidth - blockWidth) { x = blockBackgoundWidth - blockWidth; } canvas.drawBitmap(slideUnlockBlock, x, 0, null); break; default: break; } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
设置手指抬起未解锁时滑块缓慢回到初始位置
/** * 通过handler来控制滑块在未解锁的时候,平缓的滑动到左端 */ Handler handler = new Handler() { public void handleMessage(android.os.Message msg) { if (msg.what == 0) { if (x > 0) { x = x - blockBackgoundWidth * 1.0f / 100; postInvalidate(); handler.sendEmptyMessageDelayed(0, 10); } else { handler.removeCallbacksAndMessages(null); currentState = STATE_LOCK; Log.i(TAG, "state---lock....."); } } }; };
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
case MotionEvent.ACTION_UP: if (currentState == STATE_MOVING) { if (x < blockBackgoundWidth - blockWidth) { handler.sendEmptyMessageDelayed(0, 10); onUnLockListener.setUnLocked(false); } else { currentState = STATE_UNLOCK; onUnLockListener.setUnLocked(true); } downOnBlock = false; postInvalidate(); } break;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
设置滑动解锁的监听
public interface OnUnLockListener { public void setUnLocked(boolean lock); }
public void setOnUnLockListener(OnUnLockListener onUnLockListener) { this.onUnLockListener = onUnLockListener; }
if (currentState == STATE_MOVING) { if (x < blockBackgoundWidth - blockWidth) { handler.sendEmptyMessageDelayed(0, 10); onUnLockListener.setUnLocked(false); } else { currentState = STATE_UNLOCK; onUnLockListener.setUnLocked(true); } downOnBlock = false; postInvalidate(); }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
定义滑动解锁时手机震动的震动器
vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE); vibrator.vibrate(100);
在类中使用SlideUnLockView
slideUnlockView = (SlideUnlockView) findViewById(R.id.slideUnlockView); slideUnlockView.setOnUnLockListener(new OnUnLockListener() { @Override public void setUnLocked(boolean unLock) { if (unLock) { vibrator.vibrate(100); imageView.setVisibility(View.VISIBLE); slideUnlockView.reset(); slideUnlockView.setVisibility(View.GONE); } } }); }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
用户屏幕锁屏的监听
/** * 注册一个屏幕锁屏的广播 */ private void registScreenOffReceiver() { receiver = new ScreenOnOffReceiver(); IntentFilter filter = new IntentFilter(); filter.addAction("android.intent.action.SCREEN_OFF"); this.registerReceiver(receiver, filter); }
class ScreenOnOffReceiver extends BroadcastReceiver { private static final String TAG = "ScreenOnOffReceiver"; @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if ("android.intent.action.SCREEN_OFF".equals(action)) { slideUnlockView.setVisibility(View.VISIBLE); imageView.setVisibility(View.GONE); } } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
以上是Android自定义控件–滑动解锁的所有代码逻辑