您的位置:

Android View绘制流程详解

一、View的生命周期

1、onMeasure:设置View的测量尺寸,对应 xml 文件中的布局宽高模式以及 getWidth()、getHeight() 等

2、onLayout:ViewGroup 中的子 View 安排位置,对应 xml 文件中的布局文件结构以及 layout() 方法

3、onDraw:绘制自己,支持自定义绘制。

二、View的测量

1、测量模式:EXACTLY(具体大小)、AT_MOST(wrap_content)、UNSPECIFIED(设置为 0)

2、测量过程

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

        int width = 0;
        int height = 0;

        // 根据测量模式计算出尺寸
        if (widthMode == MeasureSpec.EXACTLY) {
            width = widthSize;
        } else {
            // 对于 match_parent 或者未指定大小的控件,使用默认值,比如控件的最低宽度等。
        }

        if (heightMode == MeasureSpec.EXACTLY) {
            height = heightSize;
        } else {
            // 同上,根据测量模式计算出尺寸,对于自适应大小的控件,尺寸为默认值。
        }

        setMeasuredDimension(width, height);
    }

三、View的布局

1、ViewGroup 需要实现 onLayout() 方法,对子 View 进行布局。

2、可以通过 getMeasuredWidth()、getMeasuredHeight()、getWidth()、getHeight() 等方法获得尺寸信息。

3、可以通过 getChildCount()、getChildAt(int index)、removeView(View view)、addView(View view) 等方法对子 View 进行操作。

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        int childCount = getChildCount();
        int topOffset = 0;
        for (int i = 0; i < childCount; i++) {
            View childView = getChildAt(i);
            // 对于一些不想占用区域的控件,可以通过 childView.getVisibility() 等判断。
            if (childView.getVisibility() == VISIBLE) {
                int childWidth = childView.getMeasuredWidth();
                int childHeight = childView.getMeasuredHeight();
                childView.layout(0, topOffset, childWidth, topOffset + childHeight);
                topOffset += childHeight;
            }
        }
    }

四、View的绘制

1、View 首先会调用 onDraw(Canvas canvas) 方法,传入一个 Canvas 对象,让开发人员自行绘制。

2、如果不重写 onDraw,则 View 会直接绘制自己的背景以及指定的 Drawable。

3、View 的绘制和布局都是在 UI 线程中执行,因此需要注意 UI 线程的性能。

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        // 自定义绘制
        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setColor(Color.GREEN);
        canvas.drawCircle(getWidth() / 2f, getHeight() / 2f, getWidth() / 2f, paint);
    }

五、View的绘制流程总结

View 的绘制流程可以概括为:以 onDraw 为核心在 UI 线程中绘制 View,调用 onMeasure 和 onLayout 方法给出 View 的尺寸和位置。

通过了解 View 的生命周期、测量、布局、绘制等方面,可以更好地理解 Android 的 View 操作,从而更加灵活地开发。