android 中滑动九宫格开机密码

原文链接:

九宫格开机密码(源代码)

http://www.eoeandroid.com/thread-245395-1-1.html

 

效果图由于网站占时不能上传,以后补上。

 

NinePointLineView.java

package org.demo.custon_view;

import org.demo.utils.MLog;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Cap;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

public class NinePointLineView extends View {

    Paint linePaint = new Paint();

    Paint whiteLinePaint = new Paint();

    Paint textPaint = new Paint();

    // 由于两个图片都是正方形,所以获取一个长度就行了
    Bitmap defaultBitmap = BitmapFactory.decodeResource(getResources(),
            R.drawable.lock);
    int defaultBitmapRadius = defaultBitmap.getWidth() / 2;

    // 初始化被选中图片的直径、半径
    Bitmap selectedBitmap = BitmapFactory.decodeResource(getResources(),
            R.drawable.indicator_lock_area);
    int selectedBitmapDiameter = selectedBitmap.getWidth();
    int selectedBitmapRadius = selectedBitmapDiameter / 2;

    // 定义好9个点的数组
    PointInfo[] points = new PointInfo[9];

    // 相应ACTION_DOWN的那个点
    PointInfo startPoint = null;

    // 屏幕的宽高
    int width, height;

    // 当ACTION_MOVE时获取的X,Y坐标
    int moveX, moveY;

    // 是否发生ACTION_UP
    boolean isUp = false;

    // 最终生成的用户锁序列
    StringBuffer lockString = new StringBuffer();

    public NinePointLineView(Context context) {
        super(context);
        this.setBackgroundColor(Color.WHITE);
        initPaint();
    }

    public NinePointLineView(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.setBackgroundColor(Color.WHITE);
        initPaint();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        MLog.i("onMeasure");
        // 初始化屏幕大小
        width = getWidth();
        height = getHeight();
        if (width != 0 && height != 0) {
            initPoints(points);
        }
        MLog.i("width、height = " + width + "、" + height);
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right,
            int bottom) {
        MLog.i("onLayout");
        super.onLayout(changed, left, top, right, bottom);
    }

    private int startX = 0, startY = 0;

    @Override
    protected void onDraw(Canvas canvas) {

        canvas.drawText("用户的滑动顺序:" + lockString, 0, 40, textPaint);

        if (moveX != 0 && moveY != 0 && startX != 0 && startY != 0) {
            // 绘制当前活动的线段
            drawLine(canvas, startX, startY, moveX, moveY);
        }

        drawNinePoint(canvas);

        super.onDraw(canvas);
    }

    // 记住,这个DOWN和MOVE、UP是成对的,如果没从UP释放,就不会再获得DOWN;
    // 而获得DOWN时,一定要确认消费该事件,否则MOVE和UP不会被这个View的onTouchEvent接收
    @Override
    public boolean onTouchEvent(MotionEvent event) {

        boolean flag = true;

        if (isUp) {// 如果已滑完,重置每个点的属性和lockString

            finishDraw();

            // 当UP后,要返回false,把事件释放给系统,否则无法获得Down事件
            flag = false;

        } else {// 没滑完,则继续绘制

            handlingEvent(event);

            // 这里要返回true,代表该View消耗此事件,否则不会收到MOVE和UP事件
            flag = true;

        }
        return flag;
    }

    private void handlingEvent(MotionEvent event) {
        switch (event.getAction()) {
        case MotionEvent.ACTION_MOVE:
            moveX = (int) event.getX();
            moveY = (int) event.getY();
            MLog.i("onMove:" + moveX + "、" + moveY);
            for (PointInfo temp : points) {
                if (temp.isInMyPlace(moveX, moveY) && temp.isNotSelected()) {
                    temp.setSelected(true);
                    startX = temp.getCenterX();
                    startY = temp.getCenterY();
                    int len = lockString.length();
                    if (len != 0) {
                        int preId = lockString.charAt(len - 1) - 48;
                        points[preId].setNextId(temp.getId());
                    }
                    lockString.append(temp.getId());
                    break;
                }
            }

            invalidate(0, height - width, width, height);
            break;

        case MotionEvent.ACTION_DOWN:
            int downX = (int) event.getX();
            int downY = (int) event.getY();
            MLog.i("onDown:" + downX + "、" + downY);
            for (PointInfo temp : points) {
                if (temp.isInMyPlace(downX, downY)) {
                    temp.setSelected(true);
                    startPoint = temp;
                    startX = temp.getCenterX();
                    startY = temp.getCenterY();
                    lockString.append(temp.getId());
                    break;
                }
            }
            invalidate(0, height - width, width, height);
            break;

        case MotionEvent.ACTION_UP:
            MLog.i("onUp");
            startX = startY = moveX = moveY = 0;
            isUp = true;
            invalidate();
            break;
        default:
            MLog.i("收到其他事件!!");
            break;
        }
    }

    private void finishDraw() {
        for (PointInfo temp : points) {
            temp.setSelected(false);
            temp.setNextId(temp.getId());
        }
        lockString.delete(0, lockString.length());
        isUp = false;
        invalidate();
    }

    private void initPoints(PointInfo[] points) {

        int len = points.length;

        int seletedSpacing = (width - selectedBitmapDiameter * 3) / 4;

        // 被选择时显示图片的左上角坐标
        int seletedX = seletedSpacing;
        int seletedY = height - width + seletedSpacing;

        // 没被选时图片的左上角坐标
        int defaultX = seletedX + selectedBitmapRadius - defaultBitmapRadius;
        int defaultY = seletedY + selectedBitmapRadius - defaultBitmapRadius;

        // 绘制好每个点
        for (int i = 0; i < len; i++) {
            if (i == 3 || i == 6) {
                seletedX = seletedSpacing;
                seletedY += selectedBitmapDiameter + seletedSpacing;

                defaultX = seletedX + selectedBitmapRadius
                        - defaultBitmapRadius;
                defaultY += selectedBitmapDiameter + seletedSpacing;

            }
            points[i] = new PointInfo(i, defaultX, defaultY, seletedX, seletedY);

            seletedX += selectedBitmapDiameter + seletedSpacing;
            defaultX += selectedBitmapDiameter + seletedSpacing;

        }
    }

    private void initPaint() {
        initLinePaint(linePaint);
        initTextPaint(textPaint);
        initWhiteLinePaint(whiteLinePaint);
    }

    /**
     * 初始化文本画笔
     * @param paint
     */
    private void initTextPaint(Paint paint) {
        textPaint.setTextSize(30);
        textPaint.setAntiAlias(true);
        textPaint.setTypeface(Typeface.MONOSPACE);
    }

    /**
     * 初始化黑线画笔
     * 
     * @param paint
     */
    private void initLinePaint(Paint paint) {
        paint.setColor(Color.GRAY);
        paint.setStrokeWidth(defaultBitmap.getWidth());
        paint.setAntiAlias(true);
        paint.setStrokeCap(Cap.ROUND);
    }

    /**
     * 初始化白线画笔
     * 
     * @param paint
     */
    private void initWhiteLinePaint(Paint paint) {
        paint.setColor(Color.WHITE);
        paint.setStrokeWidth(defaultBitmap.getWidth() - 5);
        paint.setAntiAlias(true);
        paint.setStrokeCap(Cap.ROUND);

    }

    /**
     * 绘制已完成的部分
     * 
     * @param canvas
     */
    private void drawNinePoint(Canvas canvas) {

        if (startPoint != null) {
            drawEachLine(canvas, startPoint);
        }

        // 绘制每个点的图片
        for (PointInfo pointInfo : points) {
            if (pointInfo.isSelected()) {// 绘制大圈
                canvas.drawBitmap(selectedBitmap, pointInfo.getSeletedX(),
                        pointInfo.getSeletedY(), null);
            }
            // 绘制点
            canvas.drawBitmap(defaultBitmap, pointInfo.getDefaultX(),
                    pointInfo.getDefaultY(), null);
        }

    }

    /**
     * 递归绘制每两个点之间的线段
     * 
     * @param canvas
     * @param point
     */
    private void drawEachLine(Canvas canvas, PointInfo point) {
        if (point.hasNextId()) {
            int n = point.getNextId();
            drawLine(canvas, point.getCenterX(), point.getCenterY(),
                    points[n].getCenterX(), points[n].getCenterY());
            // 递归
            drawEachLine(canvas, points[n]);
        }
    }

    /**
     * 先绘制黑线,再在上面绘制白线,达到黑边白线的效果
     * 
     * @param canvas
     * @param startX
     * @param startY
     * @param stopX
     * @param stopY
     */
    private void drawLine(Canvas canvas, float startX, float startY,
            float stopX, float stopY) {
        canvas.drawLine(startX, startY, stopX, stopY, linePaint);
        canvas.drawLine(startX, startY, stopX, stopY, whiteLinePaint);
    }

    /**
     * 用来表示一个点
     * 
     * @author zkwlx
     * 
     */
    private class PointInfo {

        // 一个点的ID
        private int id;

        // 当前点所指向的下一个点的ID,当没有时为自己ID
        private int nextId;

        // 是否被选中
        private boolean selected;

        // 默认时图片的左上角X坐标
        private int defaultX;

        // 默认时图片的左上角Y坐标
        private int defaultY;

        // 被选中时图片的左上角X坐标
        private int seletedX;

        // 被选中时图片的左上角Y坐标
        private int seletedY;

        public PointInfo(int id, int defaultX, int defaultY, int seletedX,
                int seletedY) {
            this.id = id;
            this.nextId = id;
            this.defaultX = defaultX;
            this.defaultY = defaultY;
            this.seletedX = seletedX;
            this.seletedY = seletedY;
        }

        public boolean isSelected() {
            return selected;
        }

        public boolean isNotSelected() {
            return !isSelected();
        }

        public void setSelected(boolean selected) {
            this.selected = selected;
        }

        public int getId() {
            return id;
        }

        public int getDefaultX() {
            return defaultX;
        }

        public int getDefaultY() {
            return defaultY;
        }

        public int getSeletedX() {
            return seletedX;
        }

        public int getSeletedY() {
            return seletedY;
        }

        public int getCenterX() {
            return seletedX + selectedBitmapRadius;
        }

        public int getCenterY() {
            return seletedY + selectedBitmapRadius;
        }

        public boolean hasNextId() {
            return nextId != id;
        }

        public int getNextId() {
            return nextId;
        }

        public void setNextId(int nextId) {
            this.nextId = nextId;
        }

        /**
         * 坐标(x,y)是否在当前点的范围内
         * 
         * @param x
         * @param y
         * @return
         */
        public boolean isInMyPlace(int x, int y) {
            boolean inX = x > seletedX
                    && x < (seletedX + selectedBitmapDiameter);
            boolean inY = y > seletedY
                    && y < (seletedY + selectedBitmapDiameter);

            return (inX && inY);
        }

    }

}

 

NinePointView.java

package org.demo.custon_view;

import org.demo.utils.MLog;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Paint.Cap;
import android.graphics.Path;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

public class NinePointView extends View {

    Paint linePaint = new Paint();

    Paint textPaint = new Paint();

    Path path = new Path();

    // 由于两个图片都是正方形,所以获取一个长度就行了
    Bitmap defaultBitmap = BitmapFactory.decodeResource(getResources(),
            R.drawable.lock);
    int defaultBitmapRadius = defaultBitmap.getWidth() / 2;

    // 初始化被选中图片的直径、半径
    Bitmap selectedBitmap = BitmapFactory.decodeResource(getResources(),
            R.drawable.indicator_lock_area);
    int selectedBitmapDiameter = selectedBitmap.getWidth();
    int selectedBitmapRadius = selectedBitmapDiameter / 2;

    // 初始化指示器的图片
    Bitmap indicateBitmap = BitmapFactory.decodeResource(getResources(),
            R.drawable.indicator_lock_area_next);
    Bitmap tempBitmap = null;

    // 定义好9个点的数组
    PointInfo[] points = new PointInfo[9];

    // 屏幕的宽高
    int width, height;

    // 当ACTION_MOVE时获取的X,Y坐标
    int moveX, moveY;

    // 是否发生ACTION_UP
    boolean isUp = false;

    // 最终生成的用户锁序列
    StringBuffer lockString = new StringBuffer();

    Matrix matrix = new Matrix();

    public NinePointView(Context context) {
        super(context);
        this.setBackgroundColor(Color.WHITE);
        initLinePaint(linePaint);
        initTextPaint(textPaint);
    }

    public NinePointView(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.setBackgroundColor(Color.WHITE);
        initLinePaint(linePaint);
        initTextPaint(textPaint);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        MLog.i("onMeasure");
        width = getWidth();
        height = getHeight();
        if (width != 0 && height != 0) {
            initPoints(points);
        }
        MLog.i("width、height = " + width + "、" + height);
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right,
            int bottom) {
        MLog.i("onLayout");
        super.onLayout(changed, left, top, right, bottom);
    }

    private int startX = 0, startY = 0;

    @Override
    protected void onDraw(Canvas canvas) {

        canvas.drawText("用户的滑动顺序:" + lockString, 0, 40, textPaint);

        if (moveX != 0 && moveY != 0 && startX != 0 && startY != 0) {
            // 绘制当前活动的线段
            canvas.drawLine(startX, startY, moveX, moveY, linePaint);
        }

        drawNinePoint(canvas, linePaint);

        super.onDraw(canvas);
    }

    // 记住,这个DOWN和MOVE、UP是成对的,如果没从UP释放,就不会再获得DOWN;
    // 而获得DOWN时,一定要确认消费该事件,否则MOVE和UP不会被这个VIEW的onTouchEvent接收
    @Override
    public boolean onTouchEvent(MotionEvent event) {

        boolean flag = true;

        if (isUp) {// 如果已滑完,则把整个Canvas重置

            finishDraw();

            // 当UP后,要返回false,把事件释放给系统,否则无法获得Down事件
            flag = false;

        } else {// 没滑完,则继续绘制

            handlingEvent(event);

            // 这里要返回true,否则代表该View不消耗此事件,交给系统处理,则不会再收到MOVE和UP事件
            flag = true;

        }
        return flag;
    }

    private void handlingEvent(MotionEvent event) {
        switch (event.getAction()) {
        case MotionEvent.ACTION_MOVE:
            moveX = (int) event.getX();
            moveY = (int) event.getY();
            MLog.i("onMove:" + moveX + "、" + moveY);
            for (PointInfo temp : points) {
                if (temp.isInMyPlace(moveX, moveY) && temp.isNotSelected()) {
                    temp.setSelected(true);
                    startX = temp.getCenterX();
                    startY = temp.getCenterY();
                    int len = lockString.length();
                    if (len != 0) {
                        int preId = lockString.charAt(len - 1) - 48;
                        points[preId].setNextId(temp.getId());
                    }
                    lockString.append(temp.getId());
                    break;
                }
            }

            invalidate(0, height - width, width, height);
            break;

        case MotionEvent.ACTION_DOWN:
            int downX = (int) event.getX();
            int downY = (int) event.getY();
            MLog.i("onDown:" + downX + "、" + downY);
            for (PointInfo temp : points) {
                if (temp.isInMyPlace(downX, downY)) {
                    temp.setSelected(true);
                    startX = temp.getCenterX();
                    startY = temp.getCenterY();
                    lockString.append(temp.getId());
                    break;
                }
            }
            invalidate(0, height - width, width, height);
            break;

        case MotionEvent.ACTION_UP:
            MLog.i("onUp");
            startX = startY = moveX = moveY = 0;
            isUp = true;
            invalidate();
            break;
        default:
            MLog.i("收到其他事件!!");
            break;
        }
    }

    private void finishDraw() {
        for (PointInfo temp : points) {
            temp.setSelected(false);
            temp.setNextId(temp.getId());
        }
        lockString.delete(0, lockString.length());
        isUp = false;
        invalidate();
    }

    private void initPoints(PointInfo[] points) {

        int len = points.length;

        int seletedSpacing = (width - selectedBitmapDiameter * 3) / 4;

        // 被选择时显示图片的左上角坐标
        int seletedX = seletedSpacing;
        int seletedY = height - width + seletedSpacing;

        // 没被选时图片的左上角坐标
        int defaultX = seletedX + selectedBitmapRadius - defaultBitmapRadius;
        int defaultY = seletedY + selectedBitmapRadius - defaultBitmapRadius;

        for (int i = 0; i < len; i++) {
            if (i == 3 || i == 6) {
                seletedX = seletedSpacing;
                seletedY += selectedBitmapDiameter + seletedSpacing;

                defaultX = seletedX + selectedBitmapRadius
                        - defaultBitmapRadius;
                defaultY += selectedBitmapDiameter + seletedSpacing;

            }
            points[i] = new PointInfo(i, defaultX, defaultY, seletedX, seletedY);

            seletedX += selectedBitmapDiameter + seletedSpacing;
            defaultX += selectedBitmapDiameter + seletedSpacing;

        }
    }

    private void initTextPaint(Paint paint) {
        textPaint.setTextSize(30);
        textPaint.setAntiAlias(true);
        textPaint.setTypeface(Typeface.MONOSPACE);
    }

    /**
     * 初始化线画笔
     * 
     * @param paint
     */
    private void initLinePaint(Paint paint) {
        paint.setColor(Color.GRAY);
        paint.setStrokeWidth(defaultBitmap.getWidth());
        paint.setAntiAlias(true);
        paint.setStrokeCap(Cap.ROUND);
    }

    /**
     * 绘制已完成的部分
     * 
     * @param canvas
     */
    private void drawNinePoint(Canvas canvas, Paint paint) {

        // 先把用户画出的线绘制好
        for (PointInfo pointInfo : points) {
            if (pointInfo.hasNextId()) {
                int n = pointInfo.getNextId();
                canvas.drawLine(pointInfo.getCenterX(), pointInfo.getCenterY(),
                        points[n].getCenterX(), points[n].getCenterY(), paint);
            }
        }

        // 绘制每个点的图片
        for (PointInfo pointInfo : points) {
            if (pointInfo.isSelected()) {
                if (pointInfo.hasNextId()) {
                    matrix.reset();
                    int i = (int) Math.abs(Math.random() * 1000 - 640);
                    MLog.i("随机到的角度:" + i);
                    matrix.setRotate(i);
                    tempBitmap = Bitmap.createBitmap(indicateBitmap, 0, 0,
                            indicateBitmap.getWidth(),
                            indicateBitmap.getHeight(), matrix, false);
                    canvas.drawBitmap(tempBitmap, pointInfo.getSeletedX(),
                            pointInfo.getSeletedY(), paint);
                } else {
                    canvas.drawBitmap(selectedBitmap, pointInfo.getSeletedX(),
                            pointInfo.getSeletedY(), paint);
                }
            }
            canvas.drawBitmap(defaultBitmap, pointInfo.getDefaultX(),
                    pointInfo.getDefaultY(), paint);
        }

    }

    private class PointInfo {

        // 一个点的ID
        private int id;

        // 当前点所指向的下一个点的ID,当没有时为自己ID
        private int nextId;

        // 是否被选中
        private boolean selected;

        // 默认时图片的左上角X坐标
        private int defaultX;

        // 默认时图片的左上角Y坐标
        private int defaultY;

        // 被选中时图片的左上角X坐标
        private int seletedX;

        // 被选中时图片的左上角Y坐标
        private int seletedY;

        public PointInfo(int id, int defaultX, int defaultY, int seletedX,
                int seletedY) {
            this.id = id;
            this.nextId = id;
            this.defaultX = defaultX;
            this.defaultY = defaultY;
            this.seletedX = seletedX;
            this.seletedY = seletedY;
        }

        public boolean isSelected() {
            return selected;
        }

        public boolean isNotSelected() {
            return !isSelected();
        }

        public void setSelected(boolean selected) {
            this.selected = selected;
        }

        public int getId() {
            return id;
        }

        public int getDefaultX() {
            return defaultX;
        }

        public int getDefaultY() {
            return defaultY;
        }

        public int getSeletedX() {
            return seletedX;
        }

        public int getSeletedY() {
            return seletedY;
        }

        public int getCenterX() {
            return seletedX + selectedBitmapRadius;
        }

        public int getCenterY() {
            return seletedY + selectedBitmapRadius;
        }

        public boolean hasNextId() {
            return nextId != id;
        }

        public int getNextId() {
            return nextId;
        }

        public void setNextId(int nextId) {
            this.nextId = nextId;
        }

        /**
         * 坐标(x,y)是否在当前点的范围内
         * 
         * @param x
         * @param y
         * @return
         */
        public boolean isInMyPlace(int x, int y) {
            boolean inX = x > seletedX
                    && x < (seletedX + selectedBitmapDiameter);
            boolean inY = y > seletedY
                    && y < (seletedY + selectedBitmapDiameter);

            if (inX && inY) {
                return true;
            } else {
                return false;
            }
        }

    }

}

 

 

posted on 2013-01-05 15:47  nuliniao  阅读(814)  评论(1编辑  收藏  举报