上接:

Android 锁屏实现与总结 (二)

系列文章链接如下:

[Android] Android 锁屏实现与总结 (一)

[Android] Android 锁屏实现与总结 (二)

[Android] Android 锁屏实现与总结 (三)

代码文件地址:

https://github.com/wukong1688/Android-BaseLockScreen

3、按键的屏蔽

当自定义锁屏页最终出现在手机上时,我们希望它像系统锁屏页那样屹立不倒,所有的按键都不能触动它,只有通过划屏或者指纹才能解锁,因此有必要对按键进行一定程度上的屏蔽。针对只有虚拟按键的手机,我们可以通过隐藏虚拟按键的方式部分解决这个问题。但是当用户在锁屏页底部滑动,隐藏后的虚拟按键还是会滑出,而且如果用户是物理按键的话就必须进行屏蔽了。需要重写Activity的onBackPressed()方法即可。

public boolean onKeyDown(int keyCode, KeyEvent event) {
        int key = event.getKeyCode();
        switch (key) {
            case KeyEvent.KEYCODE_BACK: {
                return true;
            }
            case KeyEvent.KEYCODE_MENU: {
                return true;
            }
        }
        return super.onKeyDown(keyCode, event);
    }

 
Home键 与Recent键的点击事件是在framework层进行处理的,因此onKeyDown()与dispatchKeyEvent()都捕获不到点击事件。关于这两个按键的屏蔽方法,网上相关的资料有很多,有的用到了反射,有的通过改变Window的标志位和Type等,总的来说这些方法只对部分android版本有效,有的则完全无法编译通过。其实这么做的目的无非是为了实现一个纯粹的锁屏页,但是这种做法容易造成锁屏页的异常崩溃,我们要满足的是用户在锁屏页的快捷操作,Home键和Recent键无关痛痒,基本可以不管。

4、滑屏解锁

 
做完以上几步,当屏幕熄灭后,再打开屏幕就能够看到我们的自定义锁屏页了。接下来要实现划屏解锁。
 
实现滑屏解锁的类LockScreenView.java:
package com.jack.applockscreen.activity;

import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.graphics.Paint.Style;
import android.graphics.Point;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.support.v4.view.ViewConfigurationCompat;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.view.Display;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.WindowManager; import com.jack.applockscreen.R; /**
* 解锁按钮控件
*
* @author chenglei
*/
public class LockScreenView extends View { private int mWidth;
private int mHeight; private int mScreenWidth;
private int mScreenHeight;
private WindowManager mWindowManager;
private Display mDisplay;
private float mTouchPadRadius;
private float mTouchPadBorderWidthNormal;
private float mTouchPadBorderWidthPressed;
private Paint mPaintNormal;
private TextPaint mTextPaint;
private Paint mBackgroundPaint; private Point mTouchPadCenter = new Point(); private int mTouchSlop;
private int mStartX;
private int mCurrX;
private int mOffectX;
private boolean mCanMove; private Drawable mDrawableLeft;
private Drawable mDrawableRight;
private Drawable mDrawableCenter;
private String mTextLeft;
private String mTextRight; private Point mTargetDrawableLeftPosition = new Point();
private Point mTargetDrawableRightPosition = new Point();
private Point mTargetTextLeftPosition = new Point();
private Point mTargetTextRightPosition = new Point();
private float mDensity;
private static final float TOUCH_PAD_BORDER_WIDTH_NORMAL = ;
private static final float TOUCH_PAD_BORDER_WIDTH_PRESSED = ;
private static final float TARGET_DRAWABLE_PADDING = ;
private static final float TARGET_TEXT_SIZE = ; private static final int STATE_TRIGGER_NONE = ;
private static final int STATE_TRIGGER_LEFT = ;
private static final int STATE_TRIGGER_RIGHT = ;
private int mTouchPadTriggerState = STATE_TRIGGER_NONE; private OnTriggerListener mOnTriggerListener; private Drawable mDotsLeft;
private Drawable mDotsRight; public LockScreenView(Context context) {
this(context, null, );
} public LockScreenView(Context context, AttributeSet attrs) {
this(context, attrs, );
} public LockScreenView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
} private void init() {
mWindowManager = ((Activity) getContext()).getWindowManager();
mDisplay = mWindowManager.getDefaultDisplay();
mScreenWidth = mDisplay.getWidth();
mScreenHeight = mDisplay.getHeight(); // mTouchPadBorderWidthNormal = DensityUtil.dip2px(getContext(), 8);
// mTouchPadBorderWidthPressed = DensityUtil.dip2px(getContext(), 2); mDensity = getResources().getDisplayMetrics().density;
mTouchPadBorderWidthNormal = TOUCH_PAD_BORDER_WIDTH_NORMAL * mDensity;
mTouchPadBorderWidthPressed = TOUCH_PAD_BORDER_WIDTH_PRESSED * mDensity; final ViewConfiguration configuration = ViewConfiguration.get(getContext());
mTouchSlop = ViewConfigurationCompat.getScaledPagingTouchSlop(configuration); mDrawableCenter = getResources().getDrawable(R.mipmap.ic_launcher);
mDotsLeft = getResources().getDrawable(R.mipmap.keyguaid_dots_left);
mDotsRight = getResources().getDrawable(R.mipmap.keyguaid_dots_right); initNormalPaint();
initTextPaint();
} private void initNormalPaint() {
mPaintNormal = new Paint();
mPaintNormal.setFlags(Paint.ANTI_ALIAS_FLAG);
mPaintNormal.setColor(Color.WHITE);
mPaintNormal.setStyle(Style.STROKE);
mPaintNormal.setStrokeWidth(mTouchPadBorderWidthNormal);
mBackgroundPaint = new Paint();
mBackgroundPaint.setColor(Color.parseColor("#66000000"));
} private void initTextPaint() {
mTextPaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
mTextPaint.setColor(Color.WHITE);
mTextPaint.setTextAlign(Align.CENTER);
mTextPaint.setTextSize(TARGET_TEXT_SIZE * mDensity);
} @Override
protected void onDraw(Canvas canvas) {
drawBackground(canvas);
drawDots(canvas);
drawTouchPad(canvas);
drawTargetDrawablesAndTexts(canvas);
} private void drawBackground(Canvas canvas) {
canvas.drawRect(, mHeight / , mWidth, mHeight * / , mBackgroundPaint);
} private void drawDots(Canvas canvas) {
if (!mTouchDown) {
BitmapDrawable dotsLeft = (BitmapDrawable) mDotsLeft;
BitmapDrawable dotsRight = (BitmapDrawable) mDotsRight;
canvas.drawBitmap(dotsLeft.getBitmap(),
mWidth / - mDotsLeft.getIntrinsicWidth() / ,
mHeight / - mDotsLeft.getIntrinsicHeight() / ,
mPaintNormal);
canvas.drawBitmap(dotsRight.getBitmap(),
mWidth * / - mDotsRight.getIntrinsicWidth() / ,
mHeight / - mDotsRight.getIntrinsicHeight() / ,
mPaintNormal);
}
} private void drawTouchPad(Canvas canvas) {
BitmapDrawable bd = (BitmapDrawable) mDrawableCenter;
if (mTouchDown) {
canvas.drawCircle(mTouchPadCenter.x, mTouchPadCenter.y, mDrawableCenter.getIntrinsicWidth() - , mPaintNormal);
} else {
canvas.drawBitmap(bd.getBitmap(),
mTouchPadCenter.x - mDrawableCenter.getIntrinsicWidth() / ,
mTouchPadCenter.y - mDrawableCenter.getIntrinsicHeight() / ,
mPaintNormal);
canvas.drawCircle(mTouchPadCenter.x, mTouchPadCenter.y, mDrawableCenter.getIntrinsicWidth() - , mPaintNormal);
}
} private void drawTargetDrawablesAndTexts(Canvas canvas) {
if (mDrawableLeft != null) {
BitmapDrawable bd = (BitmapDrawable) mDrawableLeft;
canvas.drawBitmap(
bd.getBitmap(),
mTargetDrawableLeftPosition.x - mDrawableLeft.getIntrinsicWidth() / ,
mTargetDrawableLeftPosition.y - mDrawableLeft.getIntrinsicHeight() / ,
mPaintNormal);
} if (mDrawableRight != null) {
BitmapDrawable bd = (BitmapDrawable) mDrawableRight;
canvas.drawBitmap(
bd.getBitmap(),
mTargetDrawableRightPosition.x - mDrawableRight.getIntrinsicWidth() / ,
mTargetDrawableRightPosition.y - mDrawableRight.getIntrinsicHeight() / ,
mPaintNormal);
} if (mTextLeft != null) {
canvas.drawText(mTextLeft, mTargetTextLeftPosition.x, mTargetTextLeftPosition.y, mTextPaint);
} if (mTextRight != null) {
canvas.drawText(mTextRight, mTargetTextRightPosition.x, mTargetTextRightPosition.y, mTextPaint);
}
} @Override
public boolean performClick() {
return super.performClick();
} private boolean mTouchDown = false; @Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mStartX = (int) event.getX();
if (mStartX > mTouchPadCenter.x - mTouchPadRadius && mStartX < mTouchPadCenter.x + mTouchPadRadius) {
mPaintNormal.setStrokeWidth(mTouchPadBorderWidthPressed);
mTouchDown = true;
invalidate();
} else {
return false;
}
break;
case MotionEvent.ACTION_MOVE:
mCurrX = (int) event.getX();
// mOffectX = mCurrX - mStartX;
//
// if (!mCanMove && Math.abs(mOffectX) < mTouchSlop) {
// return false;
// } else {
// mCanMove = true;
// if (mOffectX > mTouchSlop) {
// mOffectX += mTouchSlop;
// } else if (mOffectX < -mTouchSlop) {
// mOffectX -= mTouchSlop;
// }
// } mStartX = mCurrX;
if (mDrawableRight != null && mCurrX < mWidth * / /*mTargetDrawableLeftPosition.x + mDrawableRight.getIntrinsicWidth() * 2.5*/) {
mTouchPadCenter.set(mTargetDrawableLeftPosition.x, mTargetDrawableLeftPosition.y);
mTouchPadTriggerState = STATE_TRIGGER_LEFT;
} else if (mDrawableRight != null && mCurrX > mWidth * / /*mTargetDrawableRightPosition.x - mDrawableRight.getIntrinsicWidth() * 2.5*/) {
mTouchPadCenter.set(mTargetDrawableRightPosition.x, mTargetDrawableRightPosition.y);
mTouchPadTriggerState = STATE_TRIGGER_RIGHT;
} else {
mTouchPadCenter.x = mCurrX;
mTouchPadCenter.set(mTouchPadCenter.x + mOffectX, mTouchPadCenter.y);
mTouchPadTriggerState = STATE_TRIGGER_NONE;
} invalidate();
break;
case MotionEvent.ACTION_UP:
mCanMove = false;
if (STATE_TRIGGER_NONE == mTouchPadTriggerState) {
mTouchPadCenter.set(mWidth / , mHeight / );
//mPaintNormal.setStrokeWidth(mTouchPadBorderWidthNormal);
mTouchDown = false;
invalidate();
} else if (STATE_TRIGGER_LEFT == mTouchPadTriggerState) {
if (mOnTriggerListener != null) {
mOnTriggerListener.onTriggerLeft();
}
} else if (STATE_TRIGGER_RIGHT == mTouchPadTriggerState) {
if (mOnTriggerListener != null) {
mOnTriggerListener.onTriggerRight();
}
}
break;
}
return true;
} @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec); if (widthMode == MeasureSpec.EXACTLY) {
// Parent has told us how big to be. So be it.
mWidth = widthSize;
} else {
mWidth = mScreenWidth; // Check against our minimum width
mWidth = Math.max(mWidth, getSuggestedMinimumWidth()); if (widthMode == MeasureSpec.AT_MOST) {
mWidth = Math.min(widthSize, mWidth);
}
} if (heightMode == MeasureSpec.EXACTLY) {
mHeight = heightSize;
} else {
mHeight = mScreenHeight / ; // Check against our minimum width
mHeight = Math.max(mHeight, getSuggestedMinimumHeight()); if (heightMode == MeasureSpec.AT_MOST) {
mHeight = Math.min(heightSize, mHeight);
}
} setMeasuredDimension(mWidth, mHeight);
mTouchPadRadius = mDrawableCenter.getIntrinsicWidth(); mTouchPadCenter.set(mWidth / , mHeight / ); mTargetDrawableLeftPosition.set((int) (TARGET_DRAWABLE_PADDING * mDensity), mHeight / );
mTargetDrawableRightPosition.set((int) (mWidth - TARGET_DRAWABLE_PADDING * mDensity), mHeight / );
mTargetTextLeftPosition.set((int) (TARGET_DRAWABLE_PADDING * mDensity), (int) (mHeight / - * mDensity));
mTargetTextRightPosition.set((int) (mWidth - TARGET_DRAWABLE_PADDING * mDensity), (int) (mHeight / - * mDensity));
} public void setTargetDrawablesAndTexts(Drawable drawableLeft, Drawable drawableRight, String textLeft, String textRight) {
mDrawableLeft = drawableLeft;
mDrawableRight = drawableRight;
mTextLeft = textLeft;
mTextRight = textRight;
invalidate();
} public void setTargetDrawablesAndTexts(int drawableLeftId, int drawableRightId, String textLeft, String textRight) {
mDrawableLeft = drawableLeftId > ? getResources().getDrawable(drawableLeftId) : null;
mDrawableRight = drawableRightId > ? getResources().getDrawable(drawableRightId) : null;
mTextLeft = textLeft;
mTextRight = textRight;
invalidate();
} public interface OnTriggerListener {
public void onTriggerLeft(); public void onTriggerRight();
} public void setOnTriggerListener(OnTriggerListener l) {
mOnTriggerListener = l;
} }

很多朋友私下问我代码文件的位置,这里也贴出来分享给大家!

Github地址:

https://github.com/wukong1688/Android_BaseLockScreen

本博客地址: wukong1688

本文原文地址:https://www.cnblogs.com/wukong1688/p/10725092.html

转载请著名出处!谢谢~~

 

[Android] Android 锁屏实现与总结 (三)的更多相关文章

  1. Android逆向之旅---Android中锁屏密码算法解析以及破解方案

    一.前言 最近玩王者荣耀,下载了一个辅助样本,结果被锁机了,当然破解它很简单,这个后面会详细分析这个样本,但是因为这个样本引发出的欲望就是解析Android中锁屏密码算法,然后用一种高效的方式制作锁机 ...

  2. Android忘记锁屏密码如何进入手机?

    Android忘记锁屏密码如何进入手机?     1.关闭手机 2.进入recovery模式(即恢复模式,记住不是挖煤模式.进入恢复模式不同手机有不同方法,三星的话安主页键,关机键和音量+(或-键), ...

  3. Android一键锁屏源码

    APK下载 源程序下载 锁屏流程如下(参考于Android一键锁屏开发全过程[源码][附图]) 源码参考于一键锁屏 源码 一共有2个Java文件: package com.example.onekey ...

  4. 【腾讯Bugly干货分享】浅谈Android自定义锁屏页的发车姿势

    本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/57875330c9da73584b025873 一.为什么需要自定义锁屏页 锁屏 ...

  5. 浅谈 Android 自定义锁屏页的发车姿势

    作者:blowUp,原文链接:http://mp.weixin.qq.com/s?__biz=MzA3NTYzODYzMg==&mid=2653577446&idx=2&sn= ...

  6. 浅谈Android自定义锁屏页的发车姿势

    一.为什么需要自定义锁屏页 锁屏作为一种黑白屏时代就存在的手机功能,至今仍发挥着巨大作用,特别是触屏时代的到来,锁屏的功用被发挥到了极致.多少人曾经在无聊的时候每隔几分钟划开锁屏再关上,孜孜不倦,其酸 ...

  7. Android定时锁屏功能实现(AlarmManager定时部分)

    菜鸟入坑记——第一篇 关键字:AlarmManager 一.AlarmManager简介: 参考网址:https://www.jianshu.com/p/8a2ce9d02640        参考网 ...

  8. android开发 锁屏 真正的锁屏,是go锁屏那种。

    想做个锁屏界面很久了,最近一周,历经千辛万苦,越过种种挫折,终于完美实现了这一要求,在此将锁屏思路分享出来. 注意:这不是什么一键锁屏,是类似“go锁屏”那样的锁屏界面. 准备:本程序共需要 两个ac ...

  9. Android LockScreen (锁屏弹窗)

    在要弹窗的Activity需要进行以下设置,才可以在锁屏状态下弹窗 @Override protected void onCreate(Bundle savedInstanceState) { fin ...

  10. Android一键锁屏APP

    题记: 这个app完全是拾人牙慧,作为练手用的,其实没有什么原创的东西.当然,博客还是我自己写的,记录下来,对自己也算是一种成长吧. 转载请注明原文地址: http://www.cnblogs.com ...

随机推荐

  1. PE文件格式对定位病毒特征码的作用

    本文主要从杀毒软件查杀病毒的原理出发,分析PE文件格式在杀毒软件定位病毒特征码中的作用.杀毒软件通过快速准确定位病毒特征码,对伪装,隐藏,变种病毒进行查杀. 一.杀毒软件查杀病毒的原理概述 对于操作系 ...

  2. Java多线程与并发相关问题

    1.什么是线程? 2.线程和进程有什么区别? 3.如何在Java中实现线程? 4.Java关键字volatile与synchronized作用与区别? volatile修饰的变量不保留拷贝,直接访问主 ...

  3. 构建高性能服务 Java高性能缓冲设计 vs Disruptor vs LinkedBlockingQueue

    一个仅仅部署在4台服务器上的服务,每秒向Database写入数据超过100万行数据,每分钟产生超过1G的数据.而每台服务器(8核12G)上CPU占用不到100%,load不超过5.这是怎么做到呢?下面 ...

  4. IO 模型 IO 多路复用

    IO 模型 IO 多路复用 IO多路复用:模型(解决问题的方案) 同步:一个任务提交以后,等待任务执行结束,才能继续下一个任务 异步:不需要等待任务执行结束, 阻塞:IO阻塞,程序卡住了 非阻塞:不阻 ...

  5. 【js】this问题

    var obj = { a: 10, b: () => { console.log(this.a); // undefined console.log(this); // Window {pos ...

  6. exgcd

    int exgcd(int a,int b,int &x,int &y){ if (b==0){ x=1,y=0; return a; } int d=exgcd(b,a%b,y,x) ...

  7. TortoiseGit 安装

    1.TortoiseGit 下载安装 2.语言包下载安装 3.配置语言 一 TortoiseGit 下载安装 官网下载地址:https://download.tortoisegit.org/tgit/ ...

  8. mongo分片集群部署

    测试环境192.168.56.101-213 前期准备: openssl rand -base64 756 > /home/software/mongodb/mongodbkey chmod   ...

  9. SpringBoot中各配置文件的优先级及加载顺序

    我们在写程序的时候会碰到各种环境(开发.测试.生产),因而,在我们切换环境的时候,我们需要手工切换配置文件的内容.这大大的加大了运维人员的负担,同时会带来一定的安全隐患. 为此,为了能更合理地重写各属 ...

  10. 解决hash冲突的三个方法

    通过构造性能良好的哈希函数,可以减少冲突,但一般不可能完全避免冲突,因此解决冲突是哈希法的另一个关键问题.创建哈希表和查找哈希表都会遇到冲突,两种情况下解决冲突的方法应该一致.下面以创建哈希表为例,说 ...