写点什么

android 自定义 View——仿九宫格解锁,kotlin 缺点

用户头像
Android架构
关注
发布于: 刚刚

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {


super.onMeasure(widthMeasureSpec, heightMeasureSpec);


}


@Override


protected void onDraw(Canvas canvas) {


if (!initFlag) {


initCell();


initFlag = true;


}


drawCircle(canvas);


drawLine(canvas);


}


//绘制两个点之间的连线以及箭头


private void drawLine(Canvas canvas) {


if (mSelectData != null && mSelectData.size() != 0) {


// System.out.println(mSelectData.size());


myPoint lastPoint = mSelectData.get(0);


if (isWrongFlag){


linePressPaint.setColor(errorColor);


}else {


linePressPaint.setColor(downColor);


}


for (int i = 1; i < mSelectData.size(); i++) {


myPoint curPoint = mSelectData.get(i);


float d = (float) twoPointDistace(lastPoint.x, lastPoint.y, curPoint.x, curPoint.y);


float cos_a = (curPoint.x - lastPoint.x) * 1.0f / d;


float sin_a = (curPoint.y - lastPoint.y) * 1.0f / d;


canvas.drawLine(lastPoint.x + inCircleR * cos_a, lastPoint.y + inCircleR * sin_a,


curPoint.x - inCircleR * cos_a, curPoint.y - inCircleR * sin_a, linePressPaint);


//绘制箭头


drawArrow(lastPoint.x, lastPoint.y, d, cos_a, sin_a, canvas);


lastPoint = curPoint;


}


if (isPressFlag){


//绘制射线


float d = (float) twoPointDistace(lastPoint.x, lastPoint.y, downPointX, downPointY);


float cos_a = (downPointX - lastPoint.x) * 1.0f / d;


float sin_a = (downPointY - lastPoint.y) * 1.0f / d;


canvas.drawLine(lastPoint.x + inCircleR * cos_a, lastPoint.y + inCircleR * sin_a,


downPointX, downPointY, linePressPaint);


}


}


}


private void drawArrow(float startX, float startY, float d, float cos_a, float sin_a, Canvas canvas) {


float l = (float) (arrowHeight * (Math.tan(Math.toRadians(angle))));


float x0 = startX + (d - outCircleR - arrowHeight) * cos_a;


float y0 = startY + (d - outCircleR - arrowHeight) * sin_a;


float x1 = startX + (d - outCircleR) * cos_a;


float y1 = startY + (d - outCircleR) * sin_a;


float x2 = x0 + l * sin_a;


float y2 = y0 - l * cos_a;


float x3 = x0 - l * sin_a;


float y3 = y0 + l * cos_a;


Path path = new Path();


path.moveTo(x1, y1);


path.lineTo(x2, y2);


path.lineTo(x3, y3);


path.close();


linePressPaint.setStyle(Paint.Style.FILL);


canvas.drawPath(path, linePressPaint);


}


private double twoPointDistace(float startX, float startY, float endX, float endY) {


return Math.sqrt(Math.pow(startX - endX, 2) + Math.pow(startY - endY, 2));


}


@Override


public boolean onTouchEvent(MotionEvent event) {


downPointX = event.getX();


downPointY = event.getY();


System.out.println(event.getAction());


switch (event.getAction()) {


case MotionEvent.ACTION_DOWN:


isPressFlag = true;


for (int i = 0; i < mPointData.size(); i++) {


myPoint currentPoint = mPointData.get(i);


if (checkIsInCircle(downPointX, downPointY, currentPoint.x, currentPoint.y, outCircleR)) {


//记录按下的那个点,等下要以密码的形式返回出去


mSelectData.add(currentPoint);


currentPoint.state = myPoint.STATE_DOWN;


}


}


invalidate();


break;


case MotionEvent.ACTION_MOVE:


for (int i = 0; i < mPointData.size(); i++) {


myPoint currentPoint = mPointData.get(i);


if (checkIsInCircle(downPointX, downPointY, currentPoint.x, currentPoint.y, outCircleR)) {


//防止反复记下重复点


if (!mSelectData.contains(currentPoint)) {


mSelectData.add(currentPoint);


currentPoint.state = myPoint.STATE_DOWN;


}


}


}


invalidate();


break;


case MotionEvent.ACTION_UP:


isPressFlag = false;


if (mSelectData != null && mSelectData.size() != 0) {


//抬起的时候,密码回调


StringBuilder stringBuilder = new StringBuilder();


for (int i = 0; i < mSelectData.size(); i++) {


stringBuilder.append(mSelectData.get(i).i);


}


// System.out.println("stringBuilder.toString() ->" + stringBuilder.toString());


mOnTouchResult.result(stringBuilder.toString());


}


//清除状态


postDelayed(new Runnable() {


@Override


public void run() {


clearState();


invalidate();


}


},1000);


break;


}


return true;


}


private void clearState() {


isWrongFlag = false;


mSelectData.clear();


for (int i = 0; i < mPointData.size(); i++) {


mPointData.get(i).state = myPoint.STATE_NORMAL;


}


}


//检查是否在圈内


private boolean checkIsInCircle(float downPointX, float downPointY, float centerX, float centerY, float R) {


return Math.sqrt(Math.pow(downPointX - centerX, 2) + Math.pow(downPointY - centerY, 2)) < R;


}


//初始化画笔


private Paint initPaint(int color) {


Paint paint = new Paint();


paint.setDither(true);


paint.setAntiAlias(true);


paint.setStyle(Paint.Style.STROKE);


paint.setColor(color);


paint.setStrokeWidth(5);


return paint;


}


//画圈


private void drawCircle(Canvas canvas) {


System.out.println("drawCircle mSelectData ->" + mSelectData);


System.out.println("drawCircle mPointData ->" + mPointData);


for (int i = 0; i < mPointData.size(); i++) {


if (mPointData.get(i).state == myPoint.STATE_NORMAL) {


canvas.drawCircle(mPointData.get(i).x, mPointData.get(i).y, outCircleR, normalPaint);


canvas.drawCircle(mPointData.get(i).x, mPointData.get(i).y, inCircleR, normalPaint);


} else if (mPointData.get(i).state == myPoint.STATE_DOWN) {


canvas.drawCircle(mPointData.get(i).x, mPointData.get(i).y, outCircleR, downPaint);


canvas.draw


《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码


Circle(mPointData.get(i).x, mPointData.get(i).y, inCircleR, downPaint);


}else if (mPointData.get(i).state == myPoint.STATE_ERROR) {


canvas.drawCircle(mPointData.get(i).x, mPointData.get(i).y, outCircleR, errorPaint);


canvas.drawCircle(mPointData.get(i).x, mPointData.get(i).y, inCircleR, errorPaint);


}


}


}


//初始化九个单元格


private void initCell() {


mPointData = new ArrayList<>();


//获取布局宽高


int width = getWidth();


int height = getHeight();


//第一个点的位置


float possionX = 0;


float possionY = 0;


//横竖屏兼容,计算第一个点的坐标


if (width < height) {


possionX = width * 1.0f / 6;


possionY = (height - width) * 1.0f / 2 + width * 1.0f / 6;


height = width;


} else {


possionX = (width - height) * 1.0f / 2 + height * 1.0f / 6;


possionY = height * 1.0f / 6;


width = height;


}


//设置内外圆的半径


outCircleR = width * 1.0f / 12;


inCircleR = width * 1.0f / 50;


//循环产生九个点


int n = 1;


for (int i = 0; i < 3; i++) {


for (int j = 0; j < 3; j++) {


mPointData.add(new myPoint(possionX + j * width * 1.0f / 3, possionY + i * height * 1.0f / 3, n++));


}


}


}


public void setOnTouchResultListener(onTouchResult onTouchResult) {


this.mOnTouchResult = onTouchResult;


}


public interface onTouchResult {


void result(String s);


}


public void pwdError() {


isWrongFlag = true;


for (int i = 0; i < mSelectData.size(); i++) {


mSelectData.get(i).state = myPoint.STATE_ERROR;


}


System.out.println("mSelectData ->" + mSelectData);


invalidate();


}


}


//创建一个点类 里面主要存储 点的位置和序号 这里为了减少代码量 我就不用 get 和 set 方法了


class myPoint {


public float x;


public float y;


public int i;


public static final int STATE_NORMAL = 0;


public static final int STATE_DOWN = 1;


public static final int STATE_ERROR = 2;


public int state = STATE_NORMAL;


public myPoint(float x, float y, int i) {


this.x = x;


this.y = y;


this.i = i;


}


@Override


public String toString() {


return "myPoint{" +


"x=" + x +


", y=" + y +


", i=" + i +


", state=" + state +


'}';


}


}


二、编写 xml 文件


<?xml version="1.0" encoding="utf-8"?>


<LinearLayout


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=".MainActivity">


<com.wust.nineview.selfNineView


android:id="@+id/snv_selfnineview"


android:layout_width="match_parent"


android:layout_height="match_parent"/>

用户头像

Android架构

关注

还未添加个人签名 2021.10.31 加入

还未添加个人简介

评论

发布
暂无评论
android自定义View——仿九宫格解锁,kotlin缺点