自定义view之九宫格手势解锁空间
来源:互联网 发布:开通淘宝店的流程 编辑:程序博客网 时间:2024/04/20 17:34
主页面 MainActivity
public class MainActivity extends AppCompatActivity { private LockView lockView; // 自定义九宫格手势解锁控件 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } @Override protected void onResume() { super.onResume(); lockView = (LockView) findViewById(R.id.lockview_main_lv_lockview); // 初始化事件 initEvents(); } /** * 初始化事件 */ private void initEvents() { // 为LockView设置监听器 lockView.setOnUnlockListener(new LockView.OnUnlockListener() { @Override public boolean isUnlockSuccess(String result) { return "1122336699".equals(result); } // 当解锁成功时回调的方法 @Override public void onSuccess() { Toast.makeText(MainActivity.this, "Unlock Success!", Toast.LENGTH_SHORT).show(); } // 当解锁失败时回调的方法 @Override public void onFailure() { Toast.makeText(MainActivity.this, "Unlock Failed!", Toast.LENGTH_SHORT).show(); } }); }}
绘画 LockView 继承 view
public class LockView extends View { // 状态常量 private static final int STATE_NORMAL = 0x001; // 默认状态 private static final int STATE_SELECT = 0x002; // 选中状态 private static final int STATE_CORRECT = 0x003; // 正确状态 private static final int STATE_WRONG = 0x004; // 错误状态 // 自定义属性 private int normalColor = Color.GRAY; // 默认显示的颜色 private int selectColor = Color.YELLOW; // 选中时显示的颜色 private int correctColor = Color.GREEN; // 正确时显示的颜色 private int wrongColor = Color.RED; // 错误时显示的颜色 private int lineWidth = -1; // 连线的宽度 // 宽高相关 private int width; // 父布局分配给这个View的宽度 private int height; // 父布局分配给这个View的高度 private int rectRadius; // 每个小圆圈的宽度(直径) // 元素相关 private List<CircleRect> rectList=new ArrayList<>(); // 存储所有圆圈对象的列表 private List<CircleRect> pathList=new ArrayList<>(); // 存储用户绘制的连线上的所有圆圈对象 // 绘制相关 private Canvas mCanvas; // 用于绘制元素的画布 private Bitmap mBitmap; // 用户绘制元素的Bitmap private Path mPath; // 用户绘制的线条 private Path tmpPath; // 记录用户以前绘制过的线条 private Paint circlePaint; // 用户绘制圆圈的画笔 private Paint pathPaint; // 用户绘制连线的画笔 // 触摸相关 private int startX; // 上一个节点的X坐标 private int startY; // 上一个节点的Y坐标 private boolean isUnlocking; // 是否正在解锁(手指落下时是否刚好在一个节点上) // 结果相关 private OnUnlockListener listener; public LockView(Context context) { super(context); } public LockView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); } public LockView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); // 初始化一些对象(List等) /*rectList = new ArrayList<>(); pathList = new ArrayList<>();*/ // 获取自定义属性 TypedArray array = context.getTheme().obtainStyledAttributes(attrs, R.styleable.LockView, defStyleAttr, 0); int count = array.getIndexCount(); for (int i = 0; i < count; i++) { int attr = array.getIndex(i); switch (attr) { case R.styleable.LockView_normalColor: normalColor = array.getColor(attr, Color.GRAY); break; case R.styleable.LockView_selectColor: selectColor = array.getColor(attr, Color.YELLOW); break; case R.styleable.LockView_correctColor: correctColor = array.getColor(attr, Color.GREEN); break; case R.styleable.LockView_wrongColor: wrongColor = array.getColor(attr, Color.RED); break; case R.styleable.LockView_lineWidth: lineWidth = (int) array.getDimension(attr, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 5, context.getResources().getDisplayMetrics())); break; } } if (lineWidth == -1) { lineWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 5, context.getResources().getDisplayMetrics()); } } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); // 获取到控件的宽高属性值 width = getMeasuredWidth(); height = getMeasuredHeight(); } @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { // 初始化绘制相关的元素 mBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); mCanvas = new Canvas(mBitmap); circlePaint = new Paint(); circlePaint.setAntiAlias(true); circlePaint.setDither(true); mPath = new Path(); tmpPath = new Path(); pathPaint = new Paint(); pathPaint.setDither(true); pathPaint.setAntiAlias(true); pathPaint.setStyle(Paint.Style.STROKE); pathPaint.setStrokeCap(Paint.Cap.ROUND); pathPaint.setStrokeJoin(Paint.Join.ROUND); pathPaint.setStrokeWidth(lineWidth); // 初始化一些宽高属性 int horizontalSpacing; int verticalSpacing; if (width <= height) { horizontalSpacing = 0; verticalSpacing = (height - width) / 2; rectRadius = width / 14; } else { horizontalSpacing = (width - height) / 2; verticalSpacing = 0; rectRadius = height / 14; } // 初始化所有CircleRect对象 for (int i = 1; i <= 9; i++) { int x = ((i - 1) % 3 * 2 + 1) * rectRadius * 2 + horizontalSpacing + getPaddingLeft() + rectRadius; int y = ((i - 1) / 3 * 2 + 1) * rectRadius * 2 + verticalSpacing + getPaddingTop() + rectRadius; CircleRect rect = new CircleRect(i, x, y, STATE_NORMAL); rectList.add(rect); } } @Override protected void onDraw(Canvas canvas) { canvas.drawBitmap(mBitmap, 0, 0, null); for (int i = 0; i < rectList.size(); i++) { drawCircle(rectList.get(i), rectList.get(i).getState()); } canvas.drawPath(mPath, pathPaint); } @Override public boolean onTouchEvent(MotionEvent event) { int currX = (int) event.getX(); int currY = (int) event.getY(); CircleRect rect = getOuterRect(currX, currY); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: // 保证手指按下后所有元素都是初始状态 this.reset(); // 判断手指落点是否在某个圆圈中,如果是则设置该圆圈为选中状态 if (rect != null) { rect.setState(STATE_SELECT); startX = rect.getX(); startY = rect.getY(); tmpPath.moveTo(startX, startY); pathList.add(rect); isUnlocking = true; } break; case MotionEvent.ACTION_MOVE: if (isUnlocking) { mPath.reset(); mPath.addPath(tmpPath); mPath.moveTo(startX, startY); mPath.lineTo(currX, currY); if (rect != null) { rect.setState(STATE_SELECT); startX = rect.getX(); startY = rect.getY(); tmpPath.lineTo(startX, startY); pathList.add(rect); } } break; case MotionEvent.ACTION_UP: isUnlocking = false; if (pathList.size() > 0) { mPath.reset(); mPath.addPath(tmpPath); StringBuilder result = new StringBuilder(); for (int i = 0; i < pathList.size(); i++) { result.append(pathList.get(i).getCode()); } if (listener.isUnlockSuccess(result.toString())) { listener.onSuccess(); setWholePathState(STATE_CORRECT); } else { listener.onFailure(); setWholePathState(STATE_WRONG); } } break; } invalidate(); return true; } /** * 根据状态(解锁成功/失败)改变整条路径上所有元素的颜色 * * @param state 状态(解锁成功/失败) */ private void setWholePathState(int state) { pathPaint.setColor(getColorByState(state)); for (CircleRect rect : pathList) { rect.setState(state); } } /** * 通过状态得到应显示的颜色 * * @param state 状态 * @return 给定状态下应该显示的颜色 */ private int getColorByState(int state) { int color = normalColor; switch (state) { case STATE_NORMAL: color = normalColor; break; case STATE_SELECT: color = selectColor; break; case STATE_CORRECT: color = correctColor; break; case STATE_WRONG: color = wrongColor; break; } return color; } /** * 根据参数中提供的圆圈参数绘制圆圈 * * @param rect 存储圆圈所有参数的CircleRect对象 * @param state 圆圈的当前状态 */ private void drawCircle(CircleRect rect, int state) { circlePaint.setColor(getColorByState(state)); mCanvas.drawCircle(rect.getX(), rect.getY(), rectRadius, circlePaint); } /** * 判断参数中的x、y坐标对应的点是否在某个圆圈内,如果在则返回这个圆圈,否则返回null * * @param x 给定的点的X坐标 * @param y 给定的点的Y坐标 * @return 给定点所在的圆圈对象,如果不在任何一个圆圈内则返回null */ private CircleRect getOuterRect(int x, int y) { for (int i = 0; i < rectList.size(); i++) { CircleRect rect = rectList.get(i); if ((x - rect.getX()) * (x - rect.getX()) + (y - rect.getY()) * (y - rect.getY()) <= rectRadius * rectRadius) { if (rect.getState() != STATE_SELECT) { return rect; } } } return null; } /** * 解锁,手指抬起后回调的借口 */ public interface OnUnlockListener { // 由用户来判断解锁是否成功 boolean isUnlockSuccess(String result); // 当解锁成功时回调的方法 void onSuccess(); // 当解锁失败时回调的方法 void onFailure(); } /** * 为当前View设置结果监听器 */ public void setOnUnlockListener(OnUnlockListener listener) { this.listener = listener; } /** * 重置所有元素的状态到初始状态 */ public void reset() { setWholePathState(STATE_NORMAL); pathPaint.setColor(selectColor); mPath.reset(); tmpPath.reset(); pathList = new ArrayList<>(); } /** * 存储圆圈的各种属性的实体类 * Created by ITGungnir on 2017/5/1. */ public class CircleRect { // 圆圈所代表的数字(1~9) private int code; // 圆心的X坐标 private int x; // 圆心的Y坐标 private int y; // 圆圈的当前状态 private int state; public CircleRect() { } public CircleRect(int code, int x, int y, int state) { this.code = code; this.x = x; this.y = y; this.state = state; } public int getCode() { return code; } public void setCode(int code) { this.code = code; } public int getX() { return x; } public void setX(int x) { this.x = x; } public int getY() { return y; } public void setY(int y) { this.y = y; } public int getState() { return state; } public void setState(int state) { this.state = state; } }}
主页面布局
<RelativeLayout android:id="@+id/activity_main" xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.bwie.a05_lian1.MainActivity">
//调用自定义的空间<com.bwie.a05_lian1.view.LockView android:id="@+id/lockview_main_lv_lockview" android:layout_width="match_parent" android:layout_height="match_parent" app:correctColor="#00FF00" app:lineWidth="5.0dip" app:normalColor="#888888" app:selectColor="#FFFF00" app:wrongColor="#FF0000" /></RelativeLayout>
values文件下创建的 attr.xml 代码如下:
<resources> <attr name="normalColor" format="color" /> <!-- 正常状态下圆圈的颜色 --> <attr name="selectColor" format="color" /> <!-- 选中状态下圆圈的颜色 --> <attr name="correctColor" format="color" /> <!-- 正确状态下圆圈的颜色 --> <attr name="wrongColor" format="color" /> <!-- 错误状态下圆圈的颜色 --> <attr name="lineWidth" format="dimension" /> <!-- 连线的宽度 --> <declare-styleable name="LockView"> <attr name="normalColor" /> <attr name="selectColor" /> <attr name="correctColor" /> <attr name="wrongColor" /> <attr name="lineWidth" /> </declare-styleable></resources>
阅读全文
0 0
- 自定义view之九宫格手势解锁空间
- 自定义九宫格手势解锁
- android自定义view之九宫格解锁
- android自定义view之九宫格解锁
- 自定义View----Android九宫格手势密码解锁
- 九点(九宫格)式手势解锁自定义view
- android 自定义view实现九宫格手势解锁
- 九点(九宫格)式手势解锁自定义view
- 自定义View----Android九宫格手势密码解锁
- Android进阶之自定义View实战(二)九宫格手势解锁实现
- 自定义View九宫格手势
- 自定义View--九宫格手势
- 手势解锁-九宫格
- 九宫格手势解锁
- 九宫格手势解锁
- Android九宫格手势解锁
- 自定义view学习-创建自己的九宫格解锁view
- Android手势解锁, 九宫格解锁
- mybatis学习(三)SQL语句映射文件 增删改查、参数、缓存
- Cuda安装步骤记录(超详尽)
- allmake
- Target runtime Apache Tomcat v6.0 is not defined.错误解决方法
- [DP] BZOJ 4621: Tc605
- 自定义view之九宫格手势解锁空间
- mybatis学习(四)动态SQL语句
- jfinal+quartz定时任务
- run/server Configuration & virtualenv 虚拟环境使用问题
- java往数据库添加具体时间
- IntelliJ IDEA debug 调试打开 Evaluate Expression计算表达式窗口
- JAVA IO 之File类
- 深入理解java线程池—ThreadPoolExecutor
- Struts2的常用标签