Android View绘制原理的初步理解

Posted wjinhhua

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android View绘制原理的初步理解相关的知识,希望对你有一定的参考价值。

在理解View绘制原理之前,我们先要明白View是什么。
android中是这样理解View这个类的

 * This class represents the basic building block for user interface components. A View
 * occupies a rectangular area on the screen and is responsible for drawing and
 * event handling. View is the base class for <em>widgets</em>, which are
 * used to create interactive UI components (buttons, text fields, etc.). The
 * @link android.view.ViewGroup subclass is the base class for <em>layouts</em>, which
 * are invisible containers that hold other Views (or other ViewGroups) and define
 * their layout properties.

大致意思是(翻译可能不标准,大家相互理解):View这个类代表了用户界面组件的基本构建块。一个视图在屏幕上占据一个矩形区域,并负责绘图和事件处理。视图是窗口小部件的基类,它是用于创建交互式的用户界面组件(按钮,文本等)。这类布局的基类,它是看不见的容器持有其他Views(或其他viewgroup)和定义他们的layout的属性。

其次为什么要理解View的绘制原理?个人认为只有理解View的绘制原理,才能学会如何去自定义一个View。我们知道开发中需要用到很多组件,很多时候android给出的组建并不能满足我们的开发需求,于是我们开始组合组件来使用,然而,发现有些特定的需求还是得不到满足,于是自定义View成为解决的首要期望。

接下来我上个特别简单效果,给TextView加个边框

需要说明的是,这个例子没什么实际意义,只是一种假设
看一下代码

public class MyTextView extends TextView 

    protected Paint mPaint = new Paint();

    public MyTextView(Context context, AttributeSet attrs, int defStyle) 
        super(context, attrs, defStyle);

    

    public MyTextView(Context context, AttributeSet attrs) 
        super(context, attrs);

    

    public MyTextView(Context context) 
        super(context);

    

    @Override
    protected void onDraw(Canvas canvas) 
        canvas.save();
        mPaint.setColor(Color.RED);
        //文本
        String text = getText().toString();
        //文本宽度
        int textWidth = (int) mPaint.measureText(text);
        //文本高度
        int textHeight = (int) (mPaint.descent() - mPaint.ascent());
        //drawLine(float startX, float startY, float stopX, float stopY, Paint paint)
        //绘制矩形的上边
        canvas.drawLine(0, 0, textWidth, 0, mPaint);
        //绘制矩形的左边
        canvas.drawLine(0, 0, 0, textHeight, mPaint);
        //绘制矩形的下边
        canvas.drawLine(0, textHeight, textWidth, textHeight, mPaint);
        //绘制矩形的右边
        canvas.drawLine(textWidth, 0, textWidth, textHeight, mPaint);
        mPaint.setColor(Color.BLACK);
        //文本开始的高,相当于baseLine
        int y= textHeight+(int)(mPaint.descent() + mPaint.ascent()/2);
        //绘制文本
        canvas.drawText(text, 0, baseLine, mPaint);
        //保存绘制的状态,一定不能忘记
        canvas.restore();
    

xml引用

 <com.example.testview.MyTextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world" />

说了那么多,好像没提到View的绘制原理,其实已经说了,当然,并没有着重去说,接下来我谈谈自己的理解:
View的绘制主要是三部曲:
onMeasure:测量过程,计算视图的大小,通过setMeasuredDimension保存计算结果。
onLayout:保存位置
onDraw:绘制过程,可以绘制背景,视图本身等
开发中,我们必须去实现onMeasure,onDraw这两个方法。可能有人会问刚刚的MyTextView只实现了onDraw方法呀,额,貌似是的。但是,你要看清楚,MyTextView继承的是View的子类TextView,而不是直接继承View,TextView已经实现onMeasure方法

 @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) 
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
        int width;
        int height;
 ...
        setMeasuredDimension(width, height);
    

最后我认为还需要理解的有MeasureSpec和Canvas (这个类大家应该都掌握)这两个类
MeasureSpec这个类定义了有三种测量模式,EXACTLY(精确),AT_MOST(可获取最大尺寸),UNSPECIFIED(不限制)。这个类在onMeasure中使用。

在面试中我们经常遇到这个问题,我们可以说一下什么是View,然后着重讲一下View绘制的过程,开发中自己如何完成自定View的,再来个总结,这样面试官应该觉得至少自己掌握自定义View。我觉得照自己理解的去说给面试官听就好。。关于View的绘制原理,以后我会剖析源码,有时间再更新。最后,有问题的地方还请大家指出。

以上是关于Android View绘制原理的初步理解的主要内容,如果未能解决你的问题,请参考以下文章

android View的测量和绘制

Android view的测量及绘制

Android View 的测量流程详解

面试一问:关于 View测量布局及绘制原理

android基础-viewgroup的测量,布局,绘制

Android绘制源码分析(下)