关于九宫格密码的思考

关于九宫格密码的思考
网上有很多关于9宫格密码的资料,比如这篇博客,http://blog.csdn.net/abren32/article/details/48683625,还有视频学习资料,讲的都很好,但是对于我这种菜鸟来说,看起来还是有很多困难的,不知道是他们太牛了不用讲这些细节点还是我太笨了看不懂,我自己把这个代码写了一遍,发现很多小的知识点还是很重要的,对于初学者来说,搞清楚这些要比懂API的使用方法要重要的多。下面就做一个总结,防止自己忘记,也希望大神们拍砖。

  • 居中问题
    在自定义view中,居中问题一直是一个很重要的问题,这个问题也一直很困惑,比如在一个自定义圆中让字体居中,这个我就很懵懂,好像涉及到字体的baseline等乱七八糟的,很多大神在讲自定义view中也是对这方面一带而过,毕竟只是实现效果即可,并没有深入去研究。
    下面我们看一下效果图
    《关于九宫格密码的思考》
    嗯,根据目测,挺居中的,设置一下padding和在上面写几个乱七八糟的布局试试。
    《关于九宫格密码的思考》
    可以看出来,布局并没有因为其他布局问题变乱(其实这个问题在自定义view中很容易出现,设置一下margin啊padding啊等属性就会出现该问题)。
    接下来我们分析一下代码:
private void initPoint() {
        mPaintNormal = new Paint();
        mPaintNormal.setColor(Color.parseColor("#4EC864"));
        mPaintNormal.setFlags(Paint.ANTI_ALIAS_FLAG);
        //按下时候的画笔
        mPaintPressed = new Paint();
        mPaintPressed.setColor(Color.parseColor("#088E1F"));
        mPaintPressed.setFlags(Paint.ANTI_ALIAS_FLAG);
        //错误画笔
        mPaintError = new Paint();
        mPaintError.setColor(Color.RED);
        mPaintError.setFlags(Paint.ANTI_ALIAS_FLAG);
        //竖屏
        if (mWidth < mHeight) {
            mOffsetY = (mHeight - mWidth)/2;
        }
        //横屏
        else if (mWidth > mHeight) {
            mOffsetX = (mWidth - mHeight)/2 ;
            mWidth = mHeight;
        }
        mPoints[0][0] = new NinePoint(mOffsetX+mWidth/4,mOffsetY+mWidth/4,mRadius);
        mPoints[0][1] = new NinePoint(mOffsetX+mWidth/2,mOffsetY+mWidth/4,mRadius);
        mPoints[0][2] = new NinePoint(mOffsetX+mWidth*3/4,mOffsetY+mWidth/4,mRadius);

        mPoints[1][0] = new NinePoint(mOffsetX+mWidth/4,mOffsetY+mWidth/2,mRadius);
        mPoints[1][1] = new NinePoint(mOffsetX+mWidth/2,mOffsetY+mWidth/2,mRadius);
        mPoints[1][2] = new NinePoint(mOffsetX+mWidth*3/4,mOffsetY+mWidth/2,mRadius);

        mPoints[2][0] = new NinePoint(mOffsetX+mWidth/4,mOffsetY+mWidth-mWidth/4,mRadius);
        mPoints[2][1] = new NinePoint(mOffsetX+mWidth/2,mOffsetY+mWidth-mWidth/4,mRadius);
        mPoints[2][2] = new NinePoint(mOffsetX+mWidth*3/4,mOffsetY+mWidth-mWidth/4,mRadius);

    }

可以看到在初始化9个点的时候,我们分别加上了mWidth/4,mWidth/2等一些值,不过,这是什么鬼,我们为什么加上它,不加不行吗?假设我们把第一行代码改成这样:

 mPoints[0][0] = new NinePoint(mOffsetX+mWidth/4,mOffsetY,mRadius);
 mPoints[0][1] = new NinePoint(mOffsetX+mWidth/2,mOffsetY,mRadius);
 mPoints[0][2] = new NinePoint(mOffsetX+mWidth*3/4,mOffsetY,mRadius);

 mPoints[1][0] = new NinePoint(mOffsetX+mWidth/4,mOffsetY+mWidth/4,mRadius);
 mPoints[1][1] = new NinePoint(mOffsetX+mWidth/2,mOffsetY+mWidth/4,mRadius);
 mPoints[1][2] = new NinePoint(mOffsetX+mWidth*3/4,mOffsetY+mWidth/4,mRadius);

 mPoints[2][0] = new NinePoint(mOffsetX+mWidth/4,mOffsetY+mWidth/2,mRadius);
 mPoints[2][1] = new NinePoint(mOffsetX+mWidth/2,mOffsetY+mWidth/2,mRadius);
 mPoints[2][2] = new NinePoint(mOffsetX+mWidth*3/4,mOffsetY+mWidth/2,mRadius);

效果图就是这样了
《关于九宫格密码的思考》
可以看到,9宫格整体上移了,有人说了,这部废话吗,你少加了mWidth/4…巴拉巴拉。。。。。是的,但是我们重点来了,你发现没有,我们这个正方形并不是我们想像中的那样,在我的想象中,或者大家的想象中,我们计算完偏移量之后,直接默认的就是这个清形了,就是这张图:
《关于九宫格密码的思考》
貌似很多博客里讲述的时候也是这样子的,这个应该是错的吧?也许是我理解错了

其实这个理解应该不对吧?事实上真正的图是这样的:《关于九宫格密码的思考》
两条横线我是根据偏移量来画的,所以,不要对它产生怀疑,代码如下:

canvas.drawLine(mOffsetX,mOffsetY,mWidth,mOffsetY,mPaintError);
        canvas.drawLine(mOffsetX,mOffsetY+mWidth,mWidth,mOffsetY+mWidth, mPaintError);

可以看到,实际上偏移量我们都理解错了,如果以画的圆为基准的话,偏移量是mOffsetsX+mWidth/4,而不是简单的mOffsets,很多人(也许只有我。。。)会对这几段代码产生很大的疑问。图和代码写的不一致,明明画的只有偏移量,你丫的为什么还要在后面加上mWidth/4,这是搞什么鬼,这里借用一下这个哥们画的图《关于九宫格密码的思考》
根据它的图来看,要想让圆居中,只需要这样就行了(请具体参照开头博客)

mPoints[0][0] = new Point(offSetX + pointItemWidth, offSetY);

而源代码是这样的

mPoints[0][0] = new Point(offSetX + pointItemWidth, offSetY + pointItemWidth);

加了一个pointItemWidht 也就是1/4的布局宽度(以布局宽度为最小边情况下),我擦,你这我没法理解了,画的是居中的,你加这个值我怎么理解,这里贴一下那个哥们的源代码

// 当前视图的大小
        int width = getWidth();
        int height = getHeight();
        // 九宫格点的偏移量
        int offSet = Math.abs(width - height) / 2;
        // x、y轴上的偏移量
        int offSetX = 0, offSetY = 0;
        int pointItemWidth = 0; // 每个点所占用方格的宽度
        if (width > height){ // 横屏的时候
            offSetX = offSet;
            offSetY = 0;
            pointItemWidth = height / 4;
        }
        if (width < height){ // 竖屏的时候
            offSetX = 0;
            offSetY = offSet;
            pointItemWidth = width / 4;
        }

该段代码中有一句话:

** //九宫格点的偏移量
        int offSet = Math.abs(width - height) / 2;**

这个应该是外面正方形的偏移量,而真正的圆点偏移量应该是

offSetX + pointItemWidth, offSetY + pointItemWidth

巴拉巴拉、、、、、、
说了这么多,我其实也不知道自己说的对不对,也许从一开始就理解错了,但是理解一下也蛮好的,希望走过路过,不要忘记拍砖,下面用一幅图来理解本篇博客:
《关于九宫格密码的思考》

    原文作者:九宫格问题
    原文地址: https://blog.csdn.net/wzlyd1/article/details/48913863
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞