一、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 操作,从而更加灵活地开发。