Android 自定义九宫格锁

来源:互联网 发布:那些年流行的网络歌曲 编辑:程序博客网 时间:2024/04/29 14:43

学写了好些个自定义view了,想试试这个能不能自己写一个,发现基本成功了大笑



package com.stone.ninegridlock.view;import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.Point;import android.graphics.RectF;import android.util.AttributeSet;import android.view.MotionEvent;import android.view.View;import java.util.ArrayList;import java.util.LinkedHashSet;/** * 九宫格锁 * 关于画外圆,可以先直接算出圆心点和半径,以绘制。本例先算的是圆的外矩形 * 连线时如果感觉突兀,可记录内圆心点,以内圆心作碰撞检测 * 可以完善的地方:保存点的顺序,onmeasure中,判断是否匹配,用于解锁方案 * * author : stone * email  : aa86799@163.com * time   : 15/12/25 22 55 */public class NineGridLockView extends View {    private int mCount = 3; //n行n列    private ArrayList<RectF> mListRectFs; //圆的外矩形    private ArrayList<Point> mListCircle; //外圆心点    private LinkedHashSet<Integer> mSetPoints; //记录需要连线的外圆心点在mListCircle中的索引值。LinkedHashSet线性不可重复集合,FIFO    private Paint mPaint;    private float mRadius; //外圆半径    private float mMinRadius = 20; //内圆半径    private float mStrokeWidth = 10; //绘制时的画笔宽度    private Point mMovePoint; //记录一个手势移动时的  实时点    public NineGridLockView(Context context) {        this(context, null);    }    public NineGridLockView(Context context, AttributeSet attrs) {        this(context, attrs, 0);    }    public NineGridLockView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        mPaint = new Paint();        mPaint.setAntiAlias(true);        mPaint.setDither(true);        mPaint.setStrokeCap(Paint.Cap.ROUND);        mPaint.setStrokeJoin(Paint.Join.ROUND);        mPaint.setStyle(Paint.Style.STROKE);        mPaint.setColor(Color.BLACK);        mPaint.setStrokeWidth(mStrokeWidth);        mListRectFs = new ArrayList<RectF>();        mListCircle = new ArrayList<Point>();        mSetPoints = new LinkedHashSet<Integer>();    }    @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;        RectF rectF;        for (int i = 0; i < mCount; i++) {            for (int j = 0; j < mCount; j++) {                rectF = new RectF(mRadius + 3 * j * mRadius, mRadius + 3 * i * mRadius,                        mRadius + 3 * j * mRadius + rectWH, mRadius + 3 * i * mRadius + rectWH);                mListRectFs.add(rectF);                //item外框//                canvas.drawRect(rectF, mPaint);//                canvas.drawArc(rectF, 0, 360, true, mPaint);                mListCircle.add(new Point((int) (rectF.left + mRadius), (int) (rectF.top + mRadius)));            }        }    }    @Override    protected void onDraw(Canvas canvas) {        for (int i = 0; i < mListCircle.size(); i++) {            Point p = mListCircle.get(i);            mPaint.setColor(Color.GRAY);            //外圆            canvas.drawCircle(p.x, p.y, mRadius, mPaint);            //小圆点            mPaint.setStyle(Paint.Style.FILL);            canvas.drawCircle(p.x, p.y, mMinRadius, mPaint);            //重置绘边样式            mPaint.setStyle(Paint.Style.STROKE);        }        //重新绘制 需要连线的外圆  变色        mPaint.setColor(Color.RED);        for (int index : mSetPoints) {            Point p = mListCircle.get(index);            canvas.drawCircle(p.x, p.y, mRadius, mPaint);        }        //绘制连线        mPaint.setColor(Color.BLACK);        Point p1 = null, p2 = null;        for (int index : mSetPoints) {            if (p1 == null) {                p1 = mListCircle.get(index);                continue;            }            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);        }    }    @Override    public boolean onTouchEvent(MotionEvent event) {        float x = event.getX();        float y = event.getY();        switch (event.getAction()) {            case MotionEvent.ACTION_DOWN:                break;            case MotionEvent.ACTION_MOVE:                int index = touchIndex(x, y);                if (index != -1) {                    mSetPoints.add(index);                }                mMovePoint = new Point((int) event.getX(), (int) event.getY());                invalidate();                break;            case MotionEvent.ACTION_UP:                mMovePoint = null;                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;    }}

我的自定义View项目地址: https://github.com/aa86799/MyCustomView (欢迎start&fork)

本文地址:https://github.com/aa86799/MyCustomView/tree/master/ninegridlock

0 0
原创粉丝点击