`两点一线 ,首先想要怎么画一条线,画线前解决点的问题,点的情况分为两种:两个点的连接,点根据手势的移动线的长短
重写ontouchEvent方法
监听手势的移动 按下 松开的 动作,根据不同的动作 处理不同的事件图案
连线将点放入点的集合
//存放连线后放入的点
private List<Point> pointList = new ArrayList<>();
获取手势的坐标 通过event.getX();event.getY();
* 重写view的ontouchEvent的方法
* 监听手势的触摸状态
* @param event
* @return
*/
@Override
public boolean onTouchEvent(MotionEvent event) {
//获取手势的坐标
eventX = event.getX();
eventY = event.getY();
switch (event.getAction()){
case MotionEvent.ACTION_DOWN://按下的状态
break;
case MotionEvent.ACTION_MOVE://移动状态
break;
case MotionEvent.ACTION_UP://松开后的状态
break;
}
return true;
}
在自定义的点的类中,添加方法判断手势是否和图案重合(isCoincide()
)
/**
* 判断连线和图案是否重合
* @param pointX 参考点的x坐标
* @param pointY 参考点的y坐标
* @param bitmapR 图案的半径
* @param eventX 手势的x坐标
* @param eventY 手势的y坐标
* @return 是否在图案的范围内
*/
public boolean isCoincide(float pointX,float pointY,float bitmapR,float eventX,float eventY){
return Math.sqrt((pointX-eventX)*(pointX-eventX)+(pointY-eventY)*(pointY-eventY))<bitmapR;
}
通过连线获取屏幕上的点
当手势处于按下的状态,将点返回;
/**
* 当连接线点击了图案后将点返回
* @return
*/
private Point checkSelectPoint(){
for(int i = 0;i<points.length;i++){
for(int j = 0;j<points[i].length;j++){
Point point = points[i][j];
// 手势是否滑到了图案的范围内
if(point.isCoincide(point.x,point.y,bitmapR,eventX,eventY)){
return point;
}
}
}
return null;
}
判断手势按下去的地方是否是九宫格之内,如果在范围外是不可以出现连线的
如果我们的选择在范围内,说明我们开始绘制连线了
Boolean isSelectPoint;
/**
* 重写view的ontouchEvent的方法
* 监听手势的触摸状态
* @param event
* @return
*/
@Override
public boolean onTouchEvent(MotionEvent event) {
//获取手势的坐标
eventX = event.getX();
eventY = event.getY();
Point point = null;
switch (event.getAction()){
case MotionEvent.ACTION_DOWN://按下的状态
//每次按下清空点的集合
resetPoint();
point = checkSelectPoint();
if(point !=null){//如果此点不为null,通过标记设置它为选中状态
isSelectPoint = true;
}
break;
case MotionEvent.ACTION_MOVE://移动状态
//判断手势移动到的点是否重复选中
if(isSelectPoint){
point = checkSelectPoint();
}
break;
case MotionEvent.ACTION_UP://松开后的状态
//当手指抬起,判断绘制是否完成
isFinsh = true;
isSelectPoint = false;
break;
}
//判断选中的点是否重复选择
if(!isFinsh&&isSelectPoint&&point!=null){
}
//如果绘制完成,判断绘制选中点的结果
if(isFinsh){
if(pointList.size()==1){
//如果只选中一个点,条件不成立,将集合清空
resetPoint();
}else if(pointList.size()>1&&pointList.size()<5){
//绘制错误的状态,图案太简单
errorPoint();
}else if(pointList.size()>=5){
}
}
//每次刷新view
postInvalidate();
return true;
}
/**
* 条件不成立清空集合
*/
public void resetPoint(){
pointList.clear();
}
/**
* 绘制错误的方法
*/
public void errorPoint(){
//遍历点的集合,将选中的点设置成错误的图案
for(Point point : pointList){
point.state = Point.STATE_ERROR;
}
}
交叉点的判断,当我们选择时进行判断
/**
* 交叉点的判断
* @param point 滑动到的点
* @return
*/
private boolean crossPoint(Point point){
if(pointList.contains(point)){
//如果集合中包含此点,返回true 否着返回flase
return true;
}else {
return false;
}
}
//判断选中的点是否重复选择
if (!isFinsh && isSelectPoint && point != null) {
if (crossPoint(point)) {
//如果重复,不添加到集合中,但绘制并没有结束,添加标记,此标记在重复选择时为true,在九宫格范围外为true
moveNoPint = true;
} else {
// 如果是新点,将新点的状态设置为按下状态,添加进集合,
point.state = Point.STATE_PRESSED;
pointList.add(point);
}
}
接下来回到onDraw方法,进行画线
@Override
protected void onDraw(Canvas canvas) {
if (!isInit) {
initPoints();//初始化图案的点
}
canvasPoints(canvas);//绘制点到画布
//绘制九宫格内的点的连线
if(pointList.size()>0){
Point a = pointList.get(0);
for(int i = 0;i<pointList.size();i++){
Point b = pointList.get(i);
lineCanvas(canvas,a,b);
a = b;
}
//如果连线时,手势超出了九宫格的范围,线还是要继续画的
if(moveNoPint){
lineCanvas(canvas,a,new Point(eventX,eventY));
}
}
}
/**
* 画线
* @param canvas 画布
* 画线需要两点一线,
* @param a 点a
* @param b 点 b
*/
private void lineCanvas(Canvas canvas,Point a,Point b){
//计算线的长度
float lineLenght = (float) Point.distance(a,b);
if(a.state == Point.STATE_PRESSED){
//缩放的比例
matrix.setScale(lineLenght/linePressed.getWidth(),1);
//设置矩阵偏移量
matrix.postTranslate(a.x-linePressed.getWidth()/2,a.y-linePressed.getHeight()/2);
//画线
canvas.drawBitmap(linePressed,matrix,paint);
}else {
//缩放的比例
matrix.setScale(lineLenght/lineError.getWidth(),1);
//设置矩阵偏移量
matrix.postTranslate(a.x-lineError.getWidth()/2,a.y-lineError.getHeight()/2);
//画线
canvas.drawBitmap(lineError,matrix,paint);
}
}
在自定义点的类中的计算两点间距离的方法
/**
* 两点间的距离
* @param a 点 a
* @param b 点 b
* @return 距离
*/
public static double distance(Point a,Point b){
return Math.sqrt(Math.abs(a.x-b.x)*Math.abs(a.x-b.x)+Math.abs(a.y-b.y)*Math.abs(a.y-b.y));
}```
注意:
如果绘制的线有问题,可能是线的图片的问题,后续我会贴出源码
未完待续···
有关文章:
android开发图案解锁学习记录一(九宫格的绘制)://www.greatytc.com/p/47c731df655a
android开发图案解锁学习记录三(设置图案监听)://www.greatytc.com/p/7ab2a8dea3b1
图案锁源码:https://github.com/z1060932884/LockDemo.git