Android 实现图形解锁

来源:互联网 发布:python实战 编辑:程序博客网 时间:2024/06/05 05:36
前一久写了一个图形锁的view,实现的难度不是很大,不过对初学者学习自定义view,觉得还是一个很好的例子吧,当然每个人实现的图形锁界面有不同的逻辑,对界面之间的连接也有不一样的控制能力。如果本文有功能没有达到读者的需求或者是与读者需求不一样的,可以自己改一下代码,都很简单

先上图片

![没有划线的时候]

这里写图片描述
![匹配错误的时候]

这里写图片描述

代码

##点的类,在里面实现draw方法。##/** * Created by sunshine */public class Point  {    //私有属性    private int id;    private float x;    private float y;    private boolean isTouched;    private boolean isError;    private Paint paint;    /**     * 共有属性     */    //圆环的画笔大小    private static int STROKE_WIDTH=10;    //普通颜色    private static int COLOR_DEFAULT= Color.YELLOW;    //点击之后的颜色    private static  int COLOR_CHOOSED=Color.GREEN;    //错误之后的颜色    private static int COLOR_ERROR=Color.RED;    //圆环的半径    private float radious;    public Point(){}    public Point(float x,float y,int id){        this.x=x;        this.y=y;        this.isError=false;        this.isTouched=false;        radious=60;        paint=new Paint();        this.id=id;    }    public void setTouched(boolean isTouched){        this.isTouched=isTouched;    }    public void setIsError(boolean isError){        this.isError=isError;    }    public void draw(Canvas canvas){        paint.setColor(isTouched ? (isError ? COLOR_ERROR : COLOR_CHOOSED) : COLOR_DEFAULT);        paint.setStrokeWidth(STROKE_WIDTH);        paint.setAntiAlias(true);        canvas.drawPoint(x, y, paint);        paint.setStyle(Paint.Style.STROKE);        canvas.drawCircle(x,y,radious,paint);    }    public static void setColorChoosed(int colorChoosed) {        COLOR_CHOOSED = colorChoosed;    }    public static void setColorDefault(int colorDefault) {        COLOR_DEFAULT = colorDefault;    }    public static void setColorError(int colorError) {        COLOR_ERROR = colorError;    }    public static void setStrokeWidth(int strokeWidth) {        STROKE_WIDTH = strokeWidth;    }    public void setRadious(float radious) {        this.radious = radious;    }    public void setX(float x) {        this.x = x;    }    public void setY(float y) {        this.y = y;    }    public void setIsTouched(boolean isTouched) {        this.isTouched = isTouched;    }    public float getX() {        return x;    }    public float getY() {        return y;    }    public int getId() {        return id;    }    public boolean getTouchState(){        return isTouched;    }    public void setLocation(float x, float y) {        this.x=x;        this.y=y;    }}

接下来就是主要的ImageLock的view了

首先我们的ImageLock 要继承自View 然后重写onlayout 方法,在onlayout方法中进行布局。将9个点的分布处理好

  @Override    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {        super.onLayout(changed, left, top, right, bottom);        height=getHeight();        width=getWidth();        pointList.clear();        //进行点的布局        for(int i=0;i<3;i++){            for (int j=0;j<3;j++){                Point point=new Point((2*j+1)*width/6,(2*i+1)*width/6,i*3+j);                pointList.add(point);            }        }    }

然后就是画点划线了,在这里我们定义一个划线的方法,然后监视手指触摸的那个点跟九个点的距离,这个距离在小于预先设定的一个值的时候就判定那个点被选中

 @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        //画一般的点        for(int i=0;i<pointList.size();i++){            Point point=pointList.get(i);            point.draw(canvas);        }        //划线        if(pointQueue.size()>0){            drawTouchedLine(canvas);        }    }
    public void drawTouchedLine(Canvas canvas){        //设置画笔的粗细        linePaint.setStrokeWidth(painWidth);        //设置画笔的颜色        if(isMatch){            linePaint.setColor(matchColor);        }else{            linePaint.setColor(errorColor);        }        //设置画笔的透明度        linePaint.setAlpha(100);        for(int j=0;j<pointQueue.size()-1;j++){            Point point1=pointQueue.get(j);            Point point2=pointQueue.get(j+1);            canvas.drawLine(point1.getX(),point1.getY(),point2.getX(),point2.getY(),linePaint);        }        //最后一条能动的线        if(isMatch&&isTouched){            Point latePoint=pointQueue.get(pointQueue.size()-1);            canvas.drawLine(latePoint.getX(),latePoint.getY(),eventPoint.getX(),eventPoint.getY(),linePaint);        }else{            return ;        }    }

最后将视图的手势抬起设置一个接口

 private OnTouchUpListener listener;    public interface OnTouchUpListener{        public void onTouchUp();    }
    public void setTouchUpListener(OnTouchUpListener listener){        this.listener=listener;    }

这里将所有的代码贴出来吧,不难,也没有什么写的

public class ImageLock extends View {    //视图的整体宽高    private int height;    private int width;    /**     *     存放所有点的集合     */    private List<Point> pointList=new ArrayList<Point>();    /**     *被选择点的顺序队列     */    private List<Point> pointQueue=new ArrayList<Point>();    /**     * 是否是对的     */    private boolean isMatch;    /**     * 事件的点     */    private Point eventPoint;    /**     * 圆的半径     */    private int radious;    /**     * 画线的画笔     */    private Paint linePaint;    /**     * 划线的颜色     */    private int matchColor;    private int errorColor;    /**     * 划线的粗细     */    private int painWidth;    /**     * 是否抬起来     */    private boolean isTouched;    private OnTouchUpListener listener;    public interface OnTouchUpListener{        public void onTouchUp();    }    public ImageLock(Context context) {        super(context);        init();    }    public ImageLock(Context context, AttributeSet attrs) {        super(context, attrs);        init();    }    public ImageLock(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        init();    }    public void init(){        isMatch=true;        radious=50;        linePaint=new Paint();        eventPoint=new Point();        matchColor=Color.CYAN;        errorColor=Color.RED;        painWidth=20;    }    @Override    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {        super.onLayout(changed, left, top, right, bottom);        height=getHeight();        width=getWidth();        pointList.clear();        //进行点的布局        for(int i=0;i<3;i++){            for (int j=0;j<3;j++){                Point point=new Point((2*j+1)*width/6,(2*i+1)*width/6,i*3+j);                pointList.add(point);            }        }    }    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        //画一般的点        for(int i=0;i<pointList.size();i++){            Point point=pointList.get(i);            point.draw(canvas);        }        //划线        if(pointQueue.size()>0){            drawTouchedLine(canvas);        }    }    @Override    public boolean onTouchEvent(MotionEvent event) {        switch (event.getAction())        {            case MotionEvent.ACTION_DOWN:            case MotionEvent.ACTION_MOVE:                eventPoint.setLocation(event.getX(), event.getY());                isTouched=true;                //判断是不是触碰到点                pointTouchEvent(eventPoint);                break;            case MotionEvent.ACTION_UP:                isTouched=false;                if(listener!=null){                    listener.onTouchUp();                }                invalidate();                break;        }        return true;    }    public void drawTouchedLine(Canvas canvas){        //设置画笔的粗细        linePaint.setStrokeWidth(painWidth);        //设置画笔的颜色        if(isMatch){            linePaint.setColor(matchColor);        }else{            linePaint.setColor(errorColor);        }        //设置画笔的透明度        linePaint.setAlpha(100);        for(int j=0;j<pointQueue.size()-1;j++){            Point point1=pointQueue.get(j);            Point point2=pointQueue.get(j+1);            canvas.drawLine(point1.getX(),point1.getY(),point2.getX(),point2.getY(),linePaint);        }        //最后一条能动的线        if(isMatch&&isTouched){            Point latePoint=pointQueue.get(pointQueue.size()-1);            canvas.drawLine(latePoint.getX(),latePoint.getY(),eventPoint.getX(),eventPoint.getY(),linePaint);        }else{            return ;        }    }    public void pointTouchEvent(Point point){        for(int i=0;i<pointList.size();i++){            Point currenPoint=pointList.get(i);            //判断是否触碰到点            if(Math.sqrt(Math.pow(point.getX()-currenPoint.getX(),2)+Math.pow(point.getY()-currenPoint.getY(),2))<=radious){                //给触碰到的点进行压栈                for(int j=0;j<pointQueue.size();j++){                    if(pointQueue.get(j).getId()==currenPoint.getId()){                        return;//如果这个点已经在这个队列中就不让他可以压栈,从而进行事件的消费                    }                }                pointList.get(i).setTouched(true);                currenPoint.setTouched(true);                pointQueue.add(currenPoint);            }        }        invalidate();    }    public void setMatch(boolean isMatch){        this.isMatch=isMatch;        for(int i=0;i<pointQueue.size();i++){            pointQueue.get(i).setIsError(!isMatch);        }        invalidate();    }    public void resetChooseList(){        pointQueue.clear();        for(int i=0;i<pointList.size();i++){            pointList.get(i).setTouched(false);            pointList.get(i).setIsError(false);        }        isMatch=true;        invalidate();    }   public String getSecret(){       String secret=new String();       for(int i=0;i<pointQueue.size();i++){           secret+=pointQueue.get(i).getId();       }       return secret;   }    public void setTouchUpListener(OnTouchUpListener listener){        this.listener=listener;    }    public void setErrorColor(int errorColor) {        this.errorColor = errorColor;    }    public void setLinePaint(Paint linePaint) {        this.linePaint = linePaint;    }    public void setMatchColor(int matchColor) {        this.matchColor = matchColor;    }    public void setPainWidth(int painWidth) {        this.painWidth = painWidth;    }    public void setRadious(int radious) {        this.radious = radious;    }    public void setWidth(int width) {        this.width = width;    }    public void setHeight(int height) {        this.height = height;    }}

最后在主函数中调用

具体怎么设置视图都有接口,还可以对数据进行一些加密保存在本地,具体也就不在阐述了,一下是我测试的时候的代码以及布局文件

public class MainActivity extends AppCompatActivity {    private ImageLock imageLock;    private Button btn;    String str;    private String key="123";    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        imageLock= (ImageLock) findViewById(R.id.iamgeLock_main);        btn= (Button) findViewById(R.id.btn_main_clear);        btn.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                imageLock.resetChooseList();            }        });        imageLock.setTouchUpListener(new ImageLock.OnTouchUpListener() {            @Override            public void onTouchUp() {                imageLock.setMatch(false);                str = imageLock.getSecret();                if(str.equals(key)){                    Toast.makeText(MainActivity.this,"right",Toast.LENGTH_SHORT).show();                    imageLock.setMatch(true);                }else{                    imageLock.setMatch(false);                }            }        });    }}

布局文件

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:paddingBottom="@dimen/activity_vertical_margin"    android:paddingLeft="@dimen/activity_horizontal_margin"    android:paddingRight="@dimen/activity_horizontal_margin"    android:paddingTop="@dimen/activity_vertical_margin"    tools:context=".activity.MainActivity">  <com.happysmile.imagelock.custom.ImageLock      android:layout_marginBottom="150dp"      android:id="@+id/iamgeLock_main"      android:layout_width="wrap_content"      android:layout_height="wrap_content" />    <RelativeLayout        android:layout_alignParentBottom="true"        android:layout_width="wrap_content"        android:layout_height="150dp">        <Button            android:background="@color/colorPrimary"            android:textSize="50dp"            android:gravity="center"            android:layout_alignParentBottom="true"            android:text="clear"            android:id="@+id/btn_main_clear"            android:layout_width="match_parent"            android:layout_height="wrap_content" />    </RelativeLayout>

最后:本人写博客经验不足,水平有限,还望大家多指正,共同学习

0 0
原创粉丝点击