android之自定义View和ViewGroup(一)(此篇不讲述代码,只讲述原理和结构,带你走进自定义的世界)

看了之前自己写的两个自定义View的博客,鉴于决定要好好写博客,所以在此写篇讲述博客,因为那两篇自定义View的博客基本都是直接上代码,很多新手肯定不知道为什么这么写,为什么是重写onDraw之类的方法。

View就是视图,你所能看见的控件都是直接或者间接继承自它的,所谓的自定义View就是直接继承View或者间接继承(即继承TextView之类的)然后重新它的相关方法来完成自己需要的样子,自定义View是进阶必须会的,记住是必须。你们可以去看看View的结构,里面有很多方法,当然,我也不是大神,只是一个在那大神路上行走的一个菜B,所以咋们也没必要完全弄明白View里面的各个方法到底是干嘛的,有什么用,因为即使大神也不一定都知道,咋们只需要知道哪些方法是拿来干嘛的就够了,94那么鸡汁~


自定义View需要知道的主要是这几个方法:

1.onMeasure():改方法是用来测量View的大小的

2.onDraw():该方法是用来画View的

这么解释,自定义View需要的步骤是,咋们需要先知道你需要画的东西(View就是用canvas画出来的)多大(在onMeasure中测量),然后才能开始用画笔画(画这个操作是在onDraw方法中)。所以自定义View:先测量大小(重写onMearsure()方法),再画(重写onDraw()方法)。


我们先来看重写的onMeasure()方法,它的方法是这样的:

@Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

这个方法有两个参数,widthMeasureSpec和heightMeasureSpec,Android系统有个类——MeasureSpec类,它里面包含了测量模式和测量的大小,所以这两个参数就是包含了宽和高的测量模式和测量大小,什么是测量模式呢?就是测量大小的方式,说白点就是怎么测大小,比如如果你设置了View的具体大小,那它就直接测View真实大小,如果设置View宽是match_parent,那么它就会测你父View的大小,大概就是这么个意思。测量好大小之后,我们在onMeasure方面里通过setMeasuredDimension(int w,int h)方法来设置大小生效。

扫描二维码关注公众号,回复: 10303892 查看本文章

那么具体怎么测大小呢?我们就需要从widthMeasureSpec和heightMeasureSpec里面提取测量模式和测量的大小了,可能细心点的人就会问了,尼玛,你不是说了里面包含了测量模式和测量的大小吗,为啥还要测量,吃饱了撑的啊,说实话,刚吃完午饭写这篇博客,我现在还真没吃饱~就特么四季豆盖饭,肉都不够吃,好TM惨,咳,扯远了,拉回来。为啥还要测量呢?因为里面确实包含了测量的大小,但是不一样,那个是系统帮我们测量的大小,不是我们自己测的,系统难道测不准?还要我们自己再测?那它有个屁用啊?不要急嘛,慢慢来呀,我给你一张纸,你给我画一头猪,画呀,恩,当然你画出来了,但是你特么画这么大干嘛?此时你就会说了:尼玛,你又没说具体画多大,我咋知道要画多大的。没错,就是这样,你自定义一个View,比如设置了宽度100dp,好办,系统一测很简单100dp,但是你特么给我来个wrap_content,我特么怎么知道具体是多大?但是此时系统还是会给你测,它不知道具体多大会给你默认测量大小为match_parent的长度,很明显不对啊,所以此时才需要自己测量了啊~懂了吧,还不懂?简单,自己百度吧,啊哈哈。比如设置了宽度100dp或者wrap_content这些都可以理解为测量模式。现在我们取出测量模式:

int wSpec = MeasureSpec.getMode(widthMeasureSpec);
int hSpec = MeasureSpec.getMode(heightMeasureSpec);
一个是宽的测量模式,一个是高的,测量模式有三个值:

1.EXACTLY:精确值模式,就是将宽高设为具体值的时或者match_parent时,比如上面的100dp,我说了那么系统测出来的就是跟我们这个值一样。

2.AT_MOST:最大值模式,就是设置为wrap_content时,根据内容的变化而变化,前提是不超过父控件给定的大小。

3.UNSPECIFIED:不定模式,就是不指定大小,View想多大就多大,基本只有自定义View才会用到。

onMeasure()方法分析完了,就是这样,所以我们需要根据不同的模式来进行测量View的大小,所以自定义View有测量大小这个步骤(在onMeasure()方法里进行)。

我们再看看重写的onDraw()方法:

@Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
    }
很简单,画布canvas一个参数,调用这个canvas进行绘画就可以了,这个方法比较简单,不做介绍了。


所以自定义View:重写onMeasure()方法测量大小->在onDraw()方法里画出即可(比如TextView就是画文字),本篇幅只做自定义View的讲述和方法结构分析,所以就不写案例了。之前有两篇自定义View(自定义进度条)的博文,虽然有点粗糙,想看案例的可以去看看,详细的自定义View案例会在后续博文中写出。啊,对了,还有自定义ViewGroup的分析也会在后续博文中写出。


补充:如果自定义View咋们是继承已有的比如TextView或者Button之类的View来实现自定义View,那么background,textsize之类的就不需要咋们自己定义了,因为我们所继承的View已经有了,除非不满意需要自己更改;那么如果直接自定义View继承自View,那么没有所谓的background和textsize之类的属性了,那么此时就需要我们自定义了,那么此时的步骤又是怎么的呢?

1.在res/values文件夹下面新建文件夹attrs.xml,此文件用于自定义属性比如背景色、字体大小等。

2.在我们自定义View的构造方法中获取这些自定义的属性并赋值给对应的属性。

具体方法在后面的代码篇中有涉及到~



发布了33 篇原创文章 · 获赞 49 · 访问量 14万+

猜你喜欢

转载自blog.csdn.net/gsw333/article/details/51860519