package com.example.lockdemo.lock;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.os.Debug;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.SystemClock;
import android.util.AttributeSet;
import android.util.Log;
import android.view.HapticFeedbackConstants;
import android.view.MotionEvent;
import android.view.View;
import android.view.accessibility.AccessibilityEvent;
import com.example.lockdemo.R;
import java.util.ArrayList;
import java.util.List;
/**
* Displays and detects the user's unlock attempt, which is a drag of a finger
* across 9 regions of the screen.
* <p/>
* Is also capable of displaying a static pattern in "in progress", "wrong" or
* "correct" states.
*
* @author way
*/
public class LockPatternView extends View {
// TODO: make this common with PhoneWindow
static final int STATUS_BAR_HEIGHT = 25;
private static final String TAG = "LockPatternView";
// Aspect to use when rendering this view
private static final int ASPECT_SQUARE = 0; // View will be the minimum of
// width/height
private static final int ASPECT_LOCK_WIDTH = 1; // Fixed width; height will
// be minimum of (w,h)
// be minimum of (w,h)
private static final int ASPECT_LOCK_HEIGHT = 2; // Fixed height; width will
private static final boolean PROFILE_DRAWING = false;
/**
* How many milliseconds we spend animating each circle of a lock pattern if
* the animating mode is set. The entire animation should take this constant
* * the length of the pattern to complete.
*/
private static final int MILLIS_PER_CIRCLE_ANIMATING = 700;
private final int mStrokeAlpha = 128;
private final Path mCurrentPath = new Path();
private final Rect mInvalidate = new Rect();
private final Matrix mCircleMatrix = new Matrix();
private boolean mDrawingProfilingStarted = false;
private Paint mPaint = new Paint();
private Paint mPathPaint = new Paint();
private OnPatternListener mOnPatternListener;
private ArrayList<Cell> mPattern = new ArrayList<Cell>(9);
/**
* Lookup table for the circles of the pattern we are currently drawing.
* This will be the cells of the complete pattern unless we are animating,
* in which case we use this to hold the cells we are drawing for the in
* progress animation.
*/
private boolean[][] mPatternDrawLookup = new boolean[3][3];
/**
* the in progress point: - during interaction: where the user's finger is -
* during animation: the current tip of the animating line
*/
private float mInProgressX = -1;
private float mInProgressY = -1;
private long mAnimatingPeriodStart;
private DisplayMode mPatternDisplayMode = DisplayMode.Correct;
private boolean mInputEnabled = true;
private boolean mInStealthMode = false;
private boolean mEnableHapticFeedback = true;
private boolean mPatternInProgress = false;
private float mDiameterFactor = 0.10f; // TODO: move to attrs
private float mHitFactor = 0.6f;
private float mSquareWidth;
private float mSquareHeight;
private Bitmap mBitmapCircleDefault;
private Bitmap mBitmapCircleGreen;
private Bitmap mBitmapCircleRed;
private int mBitmapWidth;
private int mBitmapHeight;
private int mAspect;
public LockPatternView(Context context) {
this(context, null);
}
public LockPatternView(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.LockPatternView);
final String aspect = a.getString(R.styleable.LockPatternView_aspect);
if ("square".equals(aspect)) {
mAspect = ASPECT_SQUARE;
} else if ("lock_width".equals(aspect)) {
mAspect = ASPECT_LOCK_WIDTH;
} else if ("lock_height".equals(aspect)) {
mAspect = ASPECT_LOCK_HEIGHT;
} else {
mAspect = ASPECT_SQUARE;
}
setClickable(true);
mPathPaint.setAntiAlias(true);
mPathPaint.setDither(true);
mPathPaint.setColor(Color.WHITE);
mPathPaint.setAlpha(mStrokeAlpha);
mPathPaint.setStyle(Paint.Style.STROKE);
mPathPaint.setStrokeJoin(Paint.Join.ROUND);
mPathPaint.setStrokeCap(Paint.Cap.ROUND);
mPathPaint.setStrokeWidth(10);
mBitmapCircleDefault = getBitmapFor(R.drawable.gesture_pattern_item_bg);
mBitmapCircleGreen = getBitmapFor(R.drawable.gesture_pattern_selected);
mBitmapCircleRed = getBitmapFor(R.drawable.gesture_pattern_selected_wrong);
// bitmaps have the size of the largest bitmap in this group
final Bitmap bitmaps[] = {mBitmapCircleDefault, mBitmapCircleGreen, mBitmapCircleRed};
for (Bitmap bitmap : bitmaps) {
mBitmapWidth = Math.max(mBitmapWidth, bitmap.getWidth());
mBitmapHeight = Math.max(mBitmapHeight, bitmap.getHeight());
}
a.recycle();
}
private Bitmap getBitmapFor(int resId) {
return BitmapFactory.decodeResource(getContext().getResources(), resId);
}
/**
* @return Whether the view is in stealth mode.
*/
public boolean isInStealthMode() {
return mInStealthMode;
}
/**
* Set whether the view is in stealth mode. If true, there will be no
* visible feedback as the user enters the pattern.
*
* @param inStealthMode Whether in stealth mode.
*/
public void setInStealthMode(boolean inStealthMode) {
mInStealthMode = inStealthMode;
}
/**
* @return Whether the view has tactile feedback enabled.
*/
public boolean isTactileFeedbackEnabled() {
return mEnableHapticFeedback;
}
/**
* Set whether the view will use tactile feedback. If true, there will be
* tactile feedback as the user enters the pattern.
*
* @param tactileFeedbackEnabled Whether tactile feedback is enabled
*/
public void setTactileFeedbackEnabled(boolean tactileFeedbackEnabled) {
mEnableHapticFeedback = tactileFeedbackEnabled;
}
/**
* Set the call back for pattern detection.
*
* @param onPatternListener The call back.
*/
public void setOnPatternListener(OnPatternListener onPatternListener) {
mOnPatternListener = onPatternListener;
}
/**
* Set the pattern explicitely (rather than waiting for the user to input a
* pattern).
*
* @param displayMode How to display the pattern.
* @param pattern The pattern.
*/
public void setPattern(DisplayMode displayMode, List<Cell> pattern) {
mPattern.clear();
mPattern.addAll(pattern);
clearPatternDrawLookup();
for (Cell cell : pattern) {
mPatternDrawLookup[cell.getRow()][cell.getColumn()] = true;
}
setDisplayMode(displayMode);
}
/**
* Set the display mode of the current pattern. This can be useful, for
* instance, after detecting a pattern to tell this view whether change the
* in progress result to correct or wrong.
*
* @param displayMode The display mode.
*/
public void setDisplayMode(DisplayMode displayMode) {
mPatternDisplayMode = displayMode;
if (displayMode == DisplayMode.Animate) {
if (mPattern.size() == 0) {
throw new IllegalStateException(
"you must have a pattern to "
+ "animate if you want to set the display mode to animate");
}
mAnimatingPeriodStart = SystemClock.elapsedRealtime();
final Cell first = mPattern.ge
asmcvc
- 粉丝: 723
- 资源: 102
最新资源
- LuckyFrame测试平台是一款免费开源的测试平台,最大的特点是全纬度覆盖了接口自动化、WEB UI自动化、APP自动化,并且支持分布式测试,测试关键字驱动也很大程度上解决了测试同学代码基础弱的问题
- 西门子200smart热站程序西门子200smart热站程序 有 变量表 源程序代码 CAD图纸 威伦屏 程序
- 慧集通(DataLinkX)集成客户案例:水泥行业海运运输业务致远OA与畅捷通TCloud集成解决方案
- 西门子恒压供水程序,有详细的注释和图纸,一拖多2-6泵自由组合,水箱无负压共18种模式自由选择,画面根据选择自动切画面,pld由plc调节不限变频器型号,西门子smart sr20+am03最多提供3
- win32汇编环境下,窗口程序中生成listview列表控件,点击标题栏自动排序的示例
- 物流搬运机器人(sw18可编辑+工程图+cad)全套技术资料100%好用.zip
- “萌宠知识宝库”:网站设计与用户体验
- HCIA-openEuler 欧拉认证V1.0 培训教材
- MATLAB代码:基于分时电价条件下家庭能量管理策略研究 关键词:家庭能量管理模型 分时电价 空调 电动汽车 可平移负荷 参考文档:《基于分时电价和蓄电池实时控制策略的家庭能量系统优化》参考部分模型
- nosql分布式数据库期末考试题a.docx
- 物流工厂往复式升降机2018可编辑全套技术资料100%好用.zip
- “招聘智能化”:线上招聘问答系统的功能开发
- 密码学11-23.pdf
- BookStack,基于MinDoc,使用Beego开发的在线文档管理系统,功能类似Gitbook和看云
- 串口调试助手源代码 qt编写 带协议解析 帧判断 通信数据保存等功能 使用说明介绍 1.功能介绍: 采用Qt编写的串口调试助手工具,功能齐全,除了具备十六进制收发及文件保存等基本功能外,还具有以下功能
- “服务之心”:大学生自愿者服务网系统的功能开发
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
- 1
- 2
前往页