这几天虽然笔试很多,但是还是抽时间看了一下Android的小例子。看看有没有好玩的,看到九宫格解锁的时候,因为它所用到的技术为自定义的View,让我想到了之前看的面经上也有要问自定义的View的问题。打算趁机学一下再做个编程,一举两得美滋滋<开心>,因为之前看的面试经验上写着“项目不用太多,但是一定要懂得深”。所以就看了一天的View源码,之后再实现的程序。看源码真的很痛苦,但真的挺有用的。建议大家也看一下。那就先给大家说一下博主思路:先实现九宫格的本体,再实现九宫格的线,最后再对比画的线与预先保存的是否一样(如果一样的话跳转,不一样的话显示错误并清除画的线)。博主也会顺便分享一下自己编程时候遇到的问题。(博主用的是Android studio来进行编程的,好像不是3.2就是3.3,忘记了)

  先来看对于九宫格本体的绘制把:

     

androidstudio gridview 九宫格实战 用android studio编写一个九宫格_Android编程

这是博主绘制的九宫格,每一个格由两个圆组成,一个为外圆一个为内圆。(也可以只画一个圆,或者三个圆,实现方法是一样的的,这里就按博主的双园来实现了)

再看看实现需要了解的技术(感觉多可以先看下边,不会的时候再来这里找):

需要定义一个类,使它继承View类,然后重写里面的方法就可以获得自己想要的九宫格的View。至于必须重写的方法会一边讲解一边列出来的。

ArrayList<Point> 集合,用来储存每个圆心的坐标,便于绘画出圆。

Point类,是一个坐标系的类里面用来存储坐标,比如Point  point=new Point(1,2);这样的话就存了(1,2)的坐标。

在View中的坐标系:

androidstudio gridview 九宫格实战 用android studio编写一个九宫格_构造方法_02

比如第一个圆心的做标为(2,2)(这里就是打个比方,真正的坐标是根据半径来定的,后边会解释的)

Paint类,是对于画笔的定义,说白了就是对圆的定义,可以改变属性使外边变宽,或者改变圆的颜色,或者使圆为空心的。(这里的圆都是空心的)

Canvas类,是画布的定义,可以画各种图形,或者线之类的。比如这里用的为canvas.drawCircle()方法,接收四个参数,分别为圆心的横坐标,圆心的纵坐标,圆的半径,画圆的画笔(Paint)。比如canvas.drawCircle(X,Y,R,paint)。

具体的实现:

//注意:对变量的定义要在所有方法的上边,这样才能让所有方法都可以操作这个变量。定义变量有两种定义方法(拿Point举个例子):1.在方法外定义Point  pont=new  Point();这样的话比较浪费空间(因为一些你暂时用不到的变量都初始化了)。   2.在方法外边定义Point   point;在方法中再初始化point=new  Point();这样的话需要注意了,因为如果你没在方法中初始化的话,在程序调试的时候是不会报错的,但是在app运行的时候会使app直接崩溃。

首先要先写重写View的构造方法,这里先来看一下View的构造方法:View有4种构造方法

class LockView extends View
{
public LockView(Context context){super(context);}                                                                                                                           //用于java中创建View时用的构造函数,这里把逻辑都定义在View中了,不用在Activity中写逻辑,本例中可以不去书写。
public LockView(Context context, AttributeSet attrs){super(context,attrs);}                                                                                      //用于xml文件中创建View时用的函数,这个是要写的,本例中这个为主要的。
public LockView(Context context, AttributeSet attrs,int style){super(context,attrs,style);}                                                                 //多出的int style为View的初始属性,就是如果没有定义View的属性的话,显示的默认属性。
public LockView(Context context, AttributeSet attrs,int style,int style2){super(context,attrs,style,style2);}                                        //第二个style,为当第一个style为null时所表现出来的属性,这个构造函数如果要用的的话需要判断Android的版本,因为这个构造函数是在比较往后的Android版本里出现的,如要使用前面需要加一个if()作为判断才行,要么会出异常。
}

虽然我们在这里只用重写第二个构造方法,但是多了解一下总是好的,以免面试的时候真问到就很尴尬了。下面我们在重写的第二个构造方法中来对变量初始化。

public LockView(Context context, AttributeSet attrs) {
    super(context, attrs);//千万不要忘记了
    list=new ArrayList<>();//list里面存的是圆心坐标,所以前面定义时是:ArrayList<Point> list;
    //外圆的线的定义
    bigPaint=new Paint();
    bigPaint.setStyle(Paint.Style.STROKE);//变为空心的
    bigPaint.setStrokeWidth(3);//外圈线宽为3
    //内圆线的定义
    smallPaint=new Paint();
    smallPaint.setStyle(Paint.Style.STROKE);//变为空心的
    smallPaint.setStrokeWidth(10);//外圈线为10
}

用构造方法初始化完之后,开始重写第二个View的方法:onDraw(Canvas canvas){},这个方法就是画图的方法啦,里面的参数有一个Canvas(画布),用它来实现圆的绘制(上边技术中有介绍)。在此之前还需要说一下list中圆心的坐标怎么形成的。

androidstudio gridview 九宫格实战 用android studio编写一个九宫格_Android_03

                                                                                                                                                              如图所示分为若干个正方形(可能画的不像正方形<尴尬>),每个正方形的边都为外圆的半径bigR。所以第一个圆心为(2*bigR,2*bigR)依次类推就可以啦。

//其实这个圆心定义怎么都可以啦,没有固定的规范,博主只不过感觉这样定义美观而已。(还是比较注重外观的啦)                  所以onDraw方法的代码为:

@Override//标识为父类方法的重写
public void onDraw(Canvas canvas)
{
    super.onDraw(canvas);//这个千万不要忘
    bigR=100;//外圆半径
    smallR=30;//外圆半径
    //通过上边的分析,求出每个圆心的坐标保存在集合中。
    for(int i=1;i<=3;i++)
    {
        for(int j=1;j<=3;j++)
        {
            Point point=new Point((3*(i-1)+2)*(int)bigR,(3*(j-1)+2)*(int)bigR);
            list.add(point);
        }
    }
    //遍历集合,用圆心坐标来确定位置来画圆
    //这里注意如果集合的边界出问题也是会使app闪退的,集合如果里面有8个,get()的话就是0到7(虽然大家都知道但是还是说一下把)
    for(int i=0;i<list.size();i++)
    {
        Point point=list.get(i);
        canvas.drawCircle(point.x,point.y,bigR,bigPaint);//画出外圆
        canvas.drawCircle(point.x,point.y,smallR,smallPaint);//画出内圆
    }
}

最后写完了LockView之后别忘了在布局文件中引用啊,最好将默认布局改为流线布局LinearLayout。

<com.example.lock_test.LockView//com.example.lock_test为工程文件的包名,也可以直接打上LockView,代码提示会找到的。
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
/>

实现了这些方法就可以达到一个九宫格的本体的绘制啦,但绘制之后的小伙伴会发现,在xml文件中,对他的宽高不论设为  match_parent或者wrap_content,显示的效果都为match_parent的效果(与父控件一样大),出现这种原因是因为没有重写View中的onMerasure方法,所以用的是View中的onMerasure方法,在View的onMerasure方法中,match_parent与wrap_content是没有区别的,解决方法有两种:1.重写onMerasure方法(在这个例子中不太重要,不详细说明了,喜欢的小伙伴可以了解一下)  2.很简单,在xml文件中把宽高写死就行了。(要是为了美观还可以把默认的布局改成LinearLayout(流线布局),改变布局属性android:orientation="vertical"(为竖着排列),之后改变LockView属性android:layout_gravity="center"(居中))。

//最后跟大家分享一下android studio的使用小技巧把,如果你设置了代码提示发现还没有的话,可能是这个红色的被打开了,再点一下对号没了就好了   。

   

androidstudio gridview 九宫格实战 用android studio编写一个九宫格_Android_04

 

      由于这些代码是博主在自己完整的九宫格解锁上边截取后修改的,如果直接复制的话可能会有问题,但思路都是正确的,代码不保证正确,如果按照上边的操作还是做不出来或者是哪里出问题的话,可以私信博主或留言,博主会实时关注的,如果真的是博主代码错误的话,会马上改正的。