android 自定义view实现九宫格手势解锁
来源:互联网 发布:淘宝防排查 编辑:程序博客网 时间:2024/04/26 19:43
刚才我使用银行APP时,看见了这个效果,趁着下班时间,就写了。
先看下效果图:
我先说下我的思路:
1: 先计算每个点 XY坐标点,然后存储在integerList中,然后画九个点,此时我把它叫为:画板的原始状态!
2:复写onTouchEvent事件, 然后每次监听ACTION_DOWN,ACTION_MOVE,ACTION_UP状态;
- ACTION_DOWN:我们需要将画板至于原始状态。
- ACTION_MOVE:我们需要计算遍历integerList的点,然后跟move点做比较,如果距离distance < radius , 就表明有选中了该点,此时我们把改点的下标放进indexList中;然后每一次都刷新一次view。
- ACTION_UP:离开动作,就涉及到自己的业务逻辑了,在这我写了一个回调,可以根据回调做相应的业务逻辑。对了,我写的点不能小于4个,也就是indexList.size()>=4;
对了,integerList里点的存储的顺序是:从左上角开始为第一个,然后,第二个……..第九个;
具体的看下图:
具体的看下代码:
package com.app.test.testlineproject;import android.content.Context;import android.graphics.Bitmap;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.RectF;import android.graphics.drawable.Drawable;import android.os.Handler;import android.os.Message;import android.support.v4.content.ContextCompat;import android.util.AttributeSet;import android.view.MotionEvent;import android.view.View;import android.widget.Toast;import java.util.ArrayList;import java.util.List;/** * Created by ${liumegnqiang} on 2017/6/28. */public class LockLineView extends View { private float height;// view的高度 private float wight; private float radius ;//圆的半径 private float companyWidth;//因为是三个点,所以将width分为三分 也就是 companyWidth = width / 3; private float companyHeight; private List<PaintBean> integerList = new ArrayList<>();//九个点的坐标 private List<Integer> indexList = new ArrayList<>();//连接的点(不重复) private float moveX;//每次移动的X坐标 private float moveY;//每次移动的Y坐标 private OnLessPaintListener onLessPaintListener; private boolean isUP = false;//判断是否是UP状态,是的话,就去除多余的连接 , 只连接点与点 private int widthLine = 4;//线的宽度 //R.color.line 可以自定义color private int selectColor = ContextCompat.getColor(getContext(),R.color.line);//圆选中的颜色 private int unSelectColor = Color.GRAY;//圆未选中的颜色 private int lineColor = ContextCompat.getColor(getContext(),R.color.line);//线的颜色 public LockLineView(Context context) { super(context); } public LockLineView(Context context, AttributeSet attrs) { super(context, attrs); } public LockLineView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); height = getMeasuredHeight(); wight = getMeasuredWidth(); /** * 这三个数值的计算比例,可根据自己的需求, 更改!!! */ companyWidth = wight / 3; companyHeight = height / 3; radius = wight / 16; } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); Paint paint = new Paint(); paint.setAntiAlias(true); paint.setStyle(Paint.Style.FILL); /** * 画九宫格 */ paint.setColor(unSelectColor);//原点的颜色 for(int i = 0;i < 3;i++){ for(int j = 0;j < 3 ;j++ ){ RectF rectF = new RectF(); rectF.left = j * companyWidth + companyWidth / 2 - radius; rectF.right = j * companyWidth + companyWidth / 2 + radius; rectF.top = i * companyHeight + companyHeight / 2 - radius; rectF.bottom = i * companyHeight + companyHeight / 2 + radius; integerList.add(new PaintBean(j * companyWidth + companyWidth / 2, i * companyHeight + companyHeight / 2)); canvas.drawOval(rectF, paint); } } /** * 画连接的线 */ if(indexList.size() == 0){ return; } paint.setColor(lineColor);//线的颜色 paint.setStrokeWidth(widthLine);//线的宽度 for(int i = 1;i < indexList.size();i++){ canvas.drawLine(integerList.get(indexList.get(i - 1)).getPaintX(), integerList.get(indexList.get(i - 1)).getPaintY(), integerList.get(indexList.get(i)).getPaintX(),integerList.get(indexList.get(i)).getPaintY(), paint); } if(!isUP){ canvas.drawLine(integerList.get(indexList.get(indexList.size() - 1)).getPaintX(), integerList.get(indexList.get(indexList.size() - 1)).getPaintY(), moveX, moveY, paint); } /** * 画选中的点 */ paint.setColor(selectColor);//选中圆的颜色 for(int i = 0;i < indexList.size();i++){ PaintBean paintBean = integerList.get(indexList.get(i)); RectF rectF = new RectF(); rectF.left = paintBean.getPaintX() - radius; rectF.right = paintBean.getPaintX() + radius; rectF.top = paintBean.getPaintY() - radius; rectF.bottom = paintBean.getPaintY() + radius; canvas.drawOval(rectF, paint); } } @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()){ case MotionEvent.ACTION_DOWN:{ Message message = new Message(); message.what = 3; handler.sendMessage(message); break; } case MotionEvent.ACTION_MOVE:{ moveX = event.getX(); moveY = event.getY(); for(int i = 0;i < integerList.size();i++){ PaintBean paintBean = integerList.get(i); float distance = (float)Math.sqrt((paintBean.getPaintX()-moveX) * (paintBean.getPaintX()-moveX) + (paintBean.getPaintY() - moveY) * (paintBean.getPaintY() - moveY)); /** * 有一个问题: * 就是当你测试时,可以中间隔一个原点, * 也就是该原点没有被选中,这时你可以修改该下面的判断,进行修改; * 当然 你感觉没问题的话 就不用改了。。。 */ if(distance < radius){ if(!indexList.contains(i)){ indexList.add(i); } } } Message message = new Message(); message.what = 1; handler.sendMessage(message); break; } case MotionEvent.ACTION_UP:{ Message message = new Message(); message.what = 2; handler.sendMessage(message); break; } } return true; } private Handler handler = new Handler(){ @Override public void handleMessage(Message msg) { super.handleMessage(msg); switch (msg.what){ case 1:{ isUP = false; integerList.clear(); invalidate(); break; } case 2:{ isUP = true; if(indexList.size() < 4){ /** * TODO 连点数少于四个时,业务逻辑处理 */ Toast.makeText(getContext(),"连点数不能少于4个", Toast.LENGTH_SHORT).show(); if(onLessPaintListener != null){ onLessPaintListener.onLessPaintListener();//少于四个时,回调给view层 } integerList.clear(); indexList.clear(); }else{ /** * TODO 连点数大于四个时,业务逻辑处理 */ } invalidate(); break; } case 3:{ isUP = false; integerList.clear(); indexList.clear(); invalidate(); break; } } } }; /** * 在view层设置参数之后(比如:setWidthLine(4)),可调用此方法,刷新LockLineView; */ public void setPaint(){ postInvalidate(); } /** * 少于四个点数时,回调 */ interface OnLessPaintListener{ void onLessPaintListener(); } public OnLessPaintListener getOnLessPaintListener() { return onLessPaintListener; } public void setOnLessPaintListener(OnLessPaintListener onLessPaintListener) { this.onLessPaintListener = onLessPaintListener; } public float getRadius() { return radius; } public void setRadius(float radius) { this.radius = radius; } public int getWidthLine() { return widthLine; } public void setWidthLine(int widthLine) { this.widthLine = widthLine; } public int getLineColor() { return lineColor; } public void setLineColor(int lineColor) { this.lineColor = lineColor; } public int getUnSelectColor() { return unSelectColor; } public void setUnSelectColor(int unSelectColor) { this.unSelectColor = unSelectColor; } public int getSelectColor() { return selectColor; } public void setSelectColor(int selectColor) { this.selectColor = selectColor; }}
有的小伙伴可能会问:为什么不用postInvalidate()呢?
其实我刚开始用的就是这个方法,但是我发现滑动的move和刷新view不同步,所以就用了invalidate(),自己控制刷新view。
至于颜色的,可以通过相应的get方法进行设置。对了 这个view的宽高,需要自己去调试!
最后附上源码:
http://download.csdn.net/detail/lmq121210/9884371
阅读全文
0 0
- android 自定义view实现九宫格手势解锁
- 自定义View----Android九宫格手势密码解锁
- 自定义View----Android九宫格手势密码解锁
- Android进阶之自定义View实战(二)九宫格手势解锁实现
- 自定义九宫格手势解锁
- 九点(九宫格)式手势解锁自定义view
- 九点(九宫格)式手势解锁自定义view
- 自定义view之九宫格手势解锁空间
- android自定义view之九宫格解锁
- android自定义view之九宫格解锁
- Android九宫格手势解锁
- Android手势解锁, 九宫格解锁
- 【Android】自定义控件实现九宫格解锁
- Android自定义控件实现九宫格解锁
- android自定义手势解锁View
- 自定义View九宫格手势
- 自定义View--九宫格手势
- 手势解锁-九宫格
- 【数据库】mysql移植
- 第四天
- 背包问题VI
- shell1--变量定义
- PAT甲级 1016
- android 自定义view实现九宫格手势解锁
- OAuth认证原理以及长链变短链(以微博为例)
- activemq
- [Prufer序列推论] SRM 697 div1 ConnectedStates
- 阅读HashMap源码
- MongoDB 如何选择查询结果指定字段 去掉_id字段
- 背包问题IV
- beeline 使用
- 字符编码