public
class
NineGridLockView
extends
View {
private
Context context;
int
index_point =
0
;
private
float
mDensity;
private
int
mCount =
3
;
private
ArrayList<RectF> mListRectFs;
private
ArrayList<Point> mListCircle;
private
LinkedHashSet<Integer> mSetPoints;
private
Paint mPaint, miniPaint;
private
float
mRadius;
private
float
mMinRadius;
private
float
mStrokeWidth =
10
;
private
Point mMovePoint;
public
NineGridLockView(Context context) {
this
(context,
null
);
}
public
NineGridLockView(Context context, AttributeSet attrs) {
super
(context, attrs);
this
.context = context;
mDensity = getContext().getResources().getDisplayMetrics().density;
mListRectFs =
new
ArrayList<>();
mListCircle =
new
ArrayList<>();
mPaint =
new
Paint();
mPaint.setStrokeWidth(
5
);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setAntiAlias(
true
);
mPaint.setColor(Color.BLUE);
miniPaint =
new
Paint();
miniPaint.setColor(Color.BLACK);
miniPaint.setAntiAlias(
true
);
miniPaint.setStyle(Paint.Style.STROKE);
miniPaint.setStrokeWidth(
5
);
mMinRadius = dp(
5
);
mSetPoints =
new
LinkedHashSet<>();
}
@Override
protected
void
onDraw(Canvas canvas) {
super
.onDraw(canvas);
drawAll_Cicle(canvas);
draw_line(canvas);
}
private
int
dp(
int
dp) {
return
(
int
) (dp * mDensity +
0
.5f);
}
void
draw_line(Canvas canvas) {
Point p1 =
null
;
Point p2 =
null
;
for
(
int
index : mSetPoints) {
if
(p1 ==
null
) {
p1 = mListCircle.get(index);
}
else
if
(p2 ==
null
) {
p2 = mListCircle.get(index);
canvas.drawLine(p1.x, p1.y, p2.x, p2.y, mPaint);
p1 = p2;
}
else
{
p2 = mListCircle.get(index);
canvas.drawLine(p1.x, p1.y, p2.x, p2.y, mPaint);
p1 = p2;
}
}
if
(mMovePoint !=
null
&& p1 !=
null
) {
canvas.drawLine(p1.x, p1.y, mMovePoint.x, mMovePoint.y, mPaint);
}
}
void
drawAll_Cicle(Canvas canvas) {
for
(
int
i =
0
; i < mListRectFs.size(); i++) {
Point point = mListCircle.get(i);
if
(mSetPoints.contains(i)) {
canvas.drawCircle(point.x, point.y, mRadius, miniPaint);
canvas.drawCircle(point.x, point.y, mMinRadius, mPaint);
}
else
{
canvas.drawCircle(point.x, point.y, mRadius, mPaint);
canvas.drawCircle(point.x, point.y, mMinRadius, miniPaint);
}
}
}
@Override
protected
void
onMeasure(
int
widthMeasureSpec,
int
heightMeasureSpec) {
super
.onMeasure(widthMeasureSpec, heightMeasureSpec);
float
w = Math.min(getMeasuredWidth(), getMeasuredHeight());
mRadius = getMeasuredWidth() *
1
.00f / (mCount *
3
+
1
);
float
rectWH = mRadius *
2
;
mListRectFs.clear();
mListCircle.clear();
for
(
int
i =
0
; i < mCount; i++) {
for
(
int
j =
0
; j < mCount; j++) {
RectF rectF =
new
RectF((
3
* i +
1
) * mRadius, (
3
* j +
1
) * mRadius, (
3
* i +
3
) * mRadius, (
3
* j +
3
) * mRadius);
mListRectFs.add(rectF);
Point point =
new
Point((
3
* i +
2
) * (
int
) mRadius, (
3
* j +
2
) * (
int
) mRadius);
mListCircle.add(point);
}
}
}
@Override
public
boolean
onTouchEvent(MotionEvent event) {
float
point_x = event.getX();
float
point_y = event.getY();
switch
(event.getAction()) {
case
MotionEvent.ACTION_DOWN:
break
;
case
MotionEvent.ACTION_UP:
mMovePoint =
null
;
mSetPoints.clear();
invalidate();
break
;
case
MotionEvent.ACTION_MOVE:
int
index = touchIndex(point_x, point_y);
if
(mMovePoint ==
null
) {
mMovePoint =
new
Point((
int
) point_x, (
int
) point_y);
}
else
{
mMovePoint.set((
int
) point_x, (
int
) point_y);
}
if
(index != -
1
) {
mSetPoints.add(index);
if
(index_point != mSetPoints.size()) {
index_point = mSetPoints.size();
performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
}
}
invalidate();
break
;
}
return
true
;
}
/**
* 判断触摸点在哪个item上
*
* @param x
* @param y
* @return
*/
private
int
touchIndex(
float
x,
float
y) {
for
(
int
i =
0
; i < mListCircle.size(); i++) {
Point p = mListCircle.get(i);
if
(isCollision(x, y, p.x, p.y, mRadius)) {
return
i;
}
}
return
-
1
;
}
/**
* 点和圆形碰撞检测
*
* @param x1 手指接触点
* @param y1 手指接触点
* @param x2 外圆
* @param y2 外圆
* @param radius 半径
* @return
*/
private
boolean
isCollision(
float
x1,
float
y1,
float
x2,
float
y2,
float
radius) {
if
(Math.sqrt(Math.pow(x1 - x2,
2
) + Math.pow(y1 - y2,
2
)) <= radius) {
return
true
;
}
return
false
;
}
}