您现在的位置是:群英 > 开发技术 > 移动开发
Android如何自定义九宫格解锁的控件,思路是什么
Admin发表于 2022-05-16 17:17:14491 次浏览
在实际案例的操作过程中,我们可能会遇到“Android如何自定义九宫格解锁的控件,思路是什么”这样的问题,那么我们该如何处理和解决这样的情况呢?这篇小编就给大家总结了一些方法,具有一定的借鉴价值,希望对大家有所帮助,接下来就让小编带领大家一起了解看看吧。

   

本文实例为大家分享了android自制九宫格解锁控件的具体代码,供大家参考,具体内容如下

前两天从网上学习了下如何自定义一个九宫格解锁的控件,于是自己根据逻辑写了一遍,自定义控件的代码如下:

public class lockedview extends view {
 
    private boolean isfirst = true;//设置第一次加载时为true,后面重新画图不再执行
    private int width, height;//获取控件的宽度和高度
    private int offsetx, offsety;//获取点坐标时的x轴和y轴的偏移量
    private point[][] pointlist;//每个点的坐标存放的数组
    private int r;//每个圆的半径
    private bitmap map1, map2, map3;//3种状态的bitmap
    private float eventx, eventy;//触摸控件时的x坐标和y坐标
    private boolean ispressed;//判断是否触摸着控件
    private boolean moveonpoint;//判断是否移动到一个点上了
    private boolean isfinish;//判断手势是否结束
    private list<point> list = new arraylist<>();//存放经过的点的集合
    private point checkedpoint;
    private paint paint;//画笔
    public static final int locked_first=0;//第一次加载acitivity时设置密码时的返回值
    public static final int locked_true=1;//解锁成功时的返回值
    public static final int locked_false=2;//解锁失败的返回值
    private onlockedchangedlistener onlocked;//接口回调
 
    public lockedview(context context, attributeset attrs) {
        super(context, attrs);
 
    }
 
    @override
    protected void ondraw(canvas canvas) {
        super.ondraw(canvas);
        //判断是否第一次加载
        if (isfirst) {
            //初始化点坐标
            initpoints();
            //初始化画笔
            initpaint();
            isfirst = false;
        }
        //根据每个点的状态来画对应的bitmap
        drawpoints(canvas);
        //画手势滑动过程中的线
        drawlines(canvas);
    }
 
    //初始化画笔
    private void initpaint() {
        paint = new paint(paint.anti_alias_flag);
        //设置画笔颜色为蓝色
        paint.setcolor(getresources().getcolor(r.color.lockedcolor));
        //设置画笔的宽度为8
        paint.setstrokewidth(8);
    }
 
    //画线
    private void drawlines(canvas canvas) {
        //如果集合有值
        if (list.size() > 0) {
            //获得起始点的实例
            point startpoint = list.get(0);
            for (int i = 1; i < list.size(); i++) {
                //获得停止点的实例
                point stoppoint = list.get(i);
                //根据起始点坐标跟停止点坐标来画线
                canvas.drawline(startpoint.getx(), startpoint.gety(), stoppoint.getx(), stoppoint.gety(), paint);
                //把停止点赋值给起始点,这样每次遍历的时候起始点都是上一个点
                startpoint = stoppoint;
            }
            //如果没有移动到一个点上
            if (moveonpoint == false) {
                //则根据最后个点的坐标跟当前手势移动的坐标画线
                canvas.drawline(startpoint.getx(), startpoint.gety(), eventx, eventy, paint);
            }
 
        }
    }
 
    //设置触摸事件
    @override
    public boolean ontouchevent(motionevent event) {
        //获得触摸的x坐标
        eventx = event.getx();
        //获得触摸的y坐标
        eventy = event.gety();
        //每次触摸到离开屏幕之前都默认为没有完成
        isfinish = false;
        //默认移动到点上了
        moveonpoint = true;
        //选中的点
        checkedpoint = null;
        switch (event.getaction()) {
            case motionevent.action_down:
                //如果按下,重置下点
                reset();
                //根据触摸的x,y坐标以及圆的半径来判断是否触摸到了一个圆上,如果有则返回实例,没有则返回空
                checkedpoint = checkpoint(eventx, eventy, r);
                if (checkedpoint != null) {
                    //如果实例不为空,则设置选中点的状态为选中
                    checkedpoint.setstate(point.point_xuanzhong);
                    //第一次按下按到点上时设置为true
                    ispressed = true;
                }
                break;
            case motionevent.action_move:
                //如果按下在一个点上,就会执行移动动作的逻辑
                if (ispressed) {
                    //同上
                    checkedpoint = checkpoint(eventx, eventy, r);
                    if (checkedpoint != null) {
                        checkedpoint.setstate(point.point_xuanzhong);
                        //如果实例不为空,则设置移动到了点上
                        moveonpoint = true;
                    } else {
                        //否则设置没有移动到点上
                        moveonpoint = false;
                    }
                }
                break;
            case motionevent.action_up:
                //抬起时,设置第一次按在点上的参数为false以及完成了触摸过程
                ispressed = false;
                isfinish = true;
                break;
            case motionevent.action_cancel:
                ispressed = false;
                isfinish = true;
                break;
        }
        //如果第一下按在了点上并且没有完成触摸并且选中的点的实例不为空
        if (ispressed && !isfinish && checkedpoint != null) {
            //判断这个实例是否在list集合中
            if (isinlist(checkedpoint)) {
                //如果在,则设置没有移动在点上
                moveonpoint = false;
            } else {
                //否则就添加到集合里面
                list.add(checkedpoint);
            }
            //如果完成了触摸
        } else if (isfinish) {
            if (list.size() > 0) {
                //如果集合长度为1,则表示只是摸到了一个点,直接重置
                if(list.size()==1){
                    reset();
                    //如果集合长度小于5,则表示密码太短了不符合要求,把选中的点设置为错误状态,并且通过接口回调返回数据
                }else if(list.size()<5){
                    errorpoint();
                    if(onlocked!=null){
                        onlocked.onresult("密码太短");
                    }
                    //如果集合长度满足要求,则通过接口的返回值,来判断不同的情况
                }else if(list.size()>=5){
                    stringbuffer buffer=new stringbuffer();
                    for(int i=0;i<list.size();i++){
                        buffer.append(list.get(i).getindex());
                    }
                    if(onlocked!=null){
                        switch (onlocked.onpassword(buffer.tostring())){
                            //第一次打开activity时,shared里面没有值,则把当前的密码存到shared里
                            case locked_first:
                                onlocked.onresult("设置密码成功");
                                reset();
                                break;
                            //如果shared里面有值,则根据值对比下当前的密码值,如果一样则解锁成功,不一样则失败
                            case locked_true:
                                onlocked.onresult("解锁成功");
                                reset();
                                break;
                            case locked_false:
                                onlocked.onresult("解锁失败");
                                errorpoint();
                                break;
                        }
                        //重新调用ondraw方法
                        postinvalidate();
                        //此次触摸消费掉
                        return true;
                    }
 
                }
            }
        }
 
        postinvalidate();
        return true;
    }
 
    //设置错误的点的状态
    private void errorpoint() {
        for(int i=0;i<list.size();i++){
            list.get(i).setstate(point.point_xuancuo);
        }
    }
 
    //判断点是否在集合里面
    private boolean isinlist(point checkedpoint) {
        return list.contains(checkedpoint);
    }
 
    //根据触摸点的x,y轴坐标以及圆半径判断是否触摸到了一个圆
    private point checkpoint(float eventx, float eventy, int r) {
        for (int i = 0; i < pointlist.length; i++) {
            for (int j = 0; j < pointlist[i].length; j++) {
                point point = pointlist[i][j];
                double juli = getpointjuli(eventx, eventy, point.getx(), point.gety());
                if (juli < r) {
                    return point;
                }
            }
        }
        return null;
    }
 
    //重置点
    private void reset() {
        for (int i = 0; i < list.size(); i++) {
            list.get(i).setstate(point.point_moren);
        }
        list.clear();
    }
 
    //获取两点之间的距离
    private double getpointjuli(float eventx, float eventy, int x, int y) {
        return math.sqrt(math.abs(eventx - x) * math.abs(eventx - x) + math.abs(eventy - y) * math.abs(eventy - y));
    }
 
 
    //根据点的状态来画点
    private void drawpoints(canvas canvas) {
        for (int i = 0; i < pointlist.length; i++) {
            for (int j = 0; j < pointlist[i].length; j++) {
                point point = pointlist[i][j];
                switch (point.getstate()) {
                    case point.point_moren:
                        canvas.drawbitmap(map1, point.getx() - r, point.gety() - r, null);
                        break;
                    case point.point_xuanzhong:
                        canvas.drawbitmap(map2, point.getx() - r, point.gety() - r, null);
                        break;
                    case point.point_xuancuo:
                        canvas.drawbitmap(map3, point.getx() - r, point.gety() - r, null);
                        break;
                }
            }
        }
    }
 
    //初始化点坐标和bitmap
    private void initpoints() {
        //获得控件的宽度
        width = getwidth();
        //获得控件的高度
        height = getheight();
        //设置x的偏移量为0
        offsetx = 0;
        //设置y的偏移量为0
        offsety = 0;
        //如果是竖屏则
        if (width < height) {
            offsety = (height - width) / 2;
            height = width;
        } else {
            offsetx = (width - height) / 2;
            width = height;
        }
        //创建一个point数组存放点的坐标
        pointlist = new point[3][3];
        //设置索引,好判断密码
        int index=1;
        //遍历,用算法算出每个点的坐标
        for (int i = 0; i < pointlist.length; i++) {
            for (int j = 0; j < pointlist[i].length; j++) {
                pointlist[i][j] = new point(offsetx + width / 4 * (i + 1), offsety + height / 4 * (j + 1));
                pointlist[i][j].setindex(index);
                index++;
            }
        }
        //设置3个bitmap,分别是默认状态的,选中状态的,错误状态的
        map1 = bitmapfactory.decoderesource(getresources(), r.drawable.aa);
        map2 = bitmapfactory.decoderesource(getresources(), r.drawable.bb);
        map3 = bitmapfactory.decoderesource(getresources(), r.drawable.cc);
        //获得圆的半径
        r = map1.getwidth() / 2;
    }
 
    public void setonlockedchangedlistener(onlockedchangedlistener onlocked){
        this.onlocked=onlocked;
    }
 
    //设置回调接口
    public interface onlockedchangedlistener{
        public int onpassword(string password);
        public void onresult(string result);
    }
}

activity代码:

public class lockedactivity extends activity {
 
    private lockedview lockedview;
    private textview textview;
    private sharedpreferences preferences;
    private string pass;
    @override
    protected void oncreate(bundle savedinstancestate) {
        super.oncreate(savedinstancestate);
        setcontentview(r.layout.activity_locked);
        //初始化控件
        lockedview= (lockedview) findviewbyid(r.id.lockedview);
        textview= (textview) findviewbyid(r.id.textview);
        //获得shared
        preferences=getsharedpreferences("locked",mode_private);
        //根据存储在shared里的键获得密码值
        pass=preferences.getstring("password","");
        //如果没有代表第一次启动activity,则textview设置文本为情设置密码,如果不是第一次启动,则设置文本为请解锁
        if(pass.equals("")){
            textview.settext("请设置密码");
        }else{
            textview.settext("请解锁");
        }
        lockedview.setonlockedchangedlistener(new lockedview.onlockedchangedlistener() {
            @override
            public int onpassword(string password) {
                //从shared里取值
                pass=preferences.getstring("password","");
                //如果值为空,则把接口返回的password存入shared里
                if(pass.equals("")){
                    sharedpreferences.editor editor=preferences.edit();
                    editor.putstring("password",password);
                    editor.commit();
                    textview.settext("请解锁");
                    return 0;
                }else if(pass.equals(password)){
                    //如果匹配了密码,则返回数字1代表解锁成功
                    return 1;
                }
                //如果不匹配密码返回2
                return 2;
            }
 
            @override
            public void onresult(string result) {
                //根据密码匹配情况再从接口获得要toast的数据
                toast.maketext(lockedactivity.this,result,toast.length_short).show();
                //数据是解锁成功,则跳转activity
                if(result.equals("解锁成功")){
                    intent intent=new intent(lockedactivity.this,mainactivity.class);
                    startactivity(intent);
                }
            }
        });
    }
}

布局代码如下:

<?xml version="1.0" encoding="utf-8"?>
<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">
 
    <com.example.chaohengdai.test922.lockedview
        android:id="@+id/lockedview"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
    <textview
        android:id="@+id/textview"
        android:textsize="20sp"
        android:layout_centerhorizontal="true"
        android:layout_margintop="50dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</relativelayout>

关于“Android如何自定义九宫格解锁的控件,思路是什么”的内容就介绍到这,感谢各位的阅读,相信大家对Android如何自定义九宫格解锁的控件,思路是什么已经有了进一步的了解。大家如果还想学习更多知识,欢迎关注群英网络,小编将为大家输出更多高质量的实用文章!

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:mmqy2019@163.com进行举报,并提供相关证据,查实之后,将立刻删除涉嫌侵权内容。

相关信息推荐
2022-05-11 16:09:35 
摘要:在bootstrap中,popover插件用于生成指定内容和标记的弹出框,可以利用data属性和JavaScript添加弹出框,语法分别为“data-toggle="popover"”和“$(元素).popover(options)”。
2021-11-09 17:53:41 
摘要:这篇文章主要介绍了PHP unset函数原理及使用方法解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
2022-10-09 18:12:07 
摘要:OCSP在线证书状态协议是为了替换CRL而提出来的。对于现代web服务器来说一般都是支持OCSP的,OCSP也是现代web服务器的标配,这篇文章主要介绍了Java使用openssl检测网站是否支持ocsp,需要的朋友可以参考下
云活动
推荐内容
热门关键词
热门信息
群英网络助力开启安全的云计算之旅
立即注册,领取新人大礼包
  • 联系我们
  • 24小时售后:4006784567
  • 24小时TEL :0668-2555666
  • 售前咨询TEL:400-678-4567

  • 官方微信

    官方微信
Copyright  ©  QY  Network  Company  Ltd. All  Rights  Reserved. 2003-2019  群英网络  版权所有   茂名市群英网络有限公司
增值电信经营许可证 : B1.B2-20140078   粤ICP备09006778号
免费拨打  400-678-4567
免费拨打  400-678-4567 免费拨打 400-678-4567 或 0668-2555555
微信公众号
返回顶部
返回顶部 返回顶部