View 的绘制流程
2016-08-20 23:23
369 查看
对于View绘制这一块,其实是老生常谈了,网上的的讲解也比较多,自己看了一些总结一下
1.View的绘制
对于View的绘制,最主要需要了解的方法就是onDraw(Canvas c)方法, 系统通知View进行绘制的时候,是调用View的Draw方法:
这里需要注意的是onDraw方法,方法的文档写的也很清楚了, 我们要写自定义View的时候需要继承View并且Override这个方法,
参数Canvas 被绘制的内容就是这个控件显示的内容 。接下来, 需要知道的就是如何绘制我们自己想要的东西呢? 我们需要了解两个类:
一个是画笔, 一个是画布, 这样就很直观了, 就是通过画笔在画布上画你想要的东西, 做了一个小的Demo
代码:
布局:
效果:
链接: Canvas
绘制讲解
2.View的重绘
ok到这里, 基本的绘制就算掌握了, 还有一个方法需要了解, 就是View的invalidate()方法. 通常也叫作view的重绘, 顾名思义就是把画板擦干净重新画
说明文档告诉我们, 调用这个方法的时候, 如果这个view是visible的状态,那么就会调用它的onDraw方法
Demo:
这样一个触摸时就会产生一个跟随触摸点移动的圆形的控件就完成了, 挺简单的吧, 动手尝试一下吧.
以上就是view的绘制和重绘, 那么接下来了解一下ViewGroup的绘制流程是什么样的呢?
3.ViewGroup绘制流程
view树结构:
view树绘制流程
——|onMeasure(测量)
1.递归执行字View的onMeasure进行测量
2.执行方法setMeasuredDimension(width, heigh); 告诉父View自己需要的宽高
——|——|MeasureSpec
MeasureSpec.getSize(measureSpec);
获取父类空间传过来的可用大小
MeasureSpec.getMode(measureSpec);
获取父类空间传过来的mode
1:UNSPECIFIED(未指定),父元素不对子元素施加任何束缚,子元素可以得到任意想要的大小
2:EXACTLY(完全),父元素决定子元素的确切大小,子元素将被限定在给定的边界里而忽略它本身大小
3:AT_MOST(至多),子元素至多达到指定大小的值
参考blog: 自定义View之onMeasure()
——|onLayout(布局)
1.通过childView.layout(l, t, r, b); 将子view进行布局
——|onDraw(绘制)
1.进行View的绘制工作
Tips:
ViewGroup 主要操作的两个方法是onMeasure(测量) onLayout(布局)
View 主要操作的两个方法是onMeasure(测量) onDraw(绘制)
View 控件不被ViewGroup包裹的话 它是没有大小的
常用方法:
1.dispatchDraw() 会通知每一个子view 进行绘制 调用draw 方法
2.requestLayout(); 会进行重新的布局
1.View的绘制
对于View的绘制,最主要需要了解的方法就是onDraw(Canvas c)方法, 系统通知View进行绘制的时候,是调用View的Draw方法:
public void draw(Canvas canvas) { final int privateFlags = mPrivateFlags; final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE && (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState); mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN; // Step 1, draw the background, if needed int saveCount; if (!dirtyOpaque) { drawBackground(canvas); //绘制背景 } // skip step 2 & 5 if possible (common case) final int viewFlags = mViewFlags; boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0; boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0; if (!verticalEdges && !horizontalEdges) { // Step 3, draw the content if (!dirtyOpaque) onDraw(canvas); <strong> //调用onDraw(Canvas c)方法</strong> // Step 4, draw the children dispatchDraw(canvas); // Overlay is part of the content and draws beneath Foreground if (mOverlay != null && !mOverlay.isEmpty()) { mOverlay.getOverlayView().dispatchDraw(canvas); } // Step 6, draw decorations (foreground, scrollbars) onDrawForeground(canvas); // we're done... return; }
/** * Implement this to do your drawing. * * @param canvas the canvas on which the background will be drawn */ protected void onDraw(Canvas canvas) { }
这里需要注意的是onDraw方法,方法的文档写的也很清楚了, 我们要写自定义View的时候需要继承View并且Override这个方法,
参数Canvas 被绘制的内容就是这个控件显示的内容 。接下来, 需要知道的就是如何绘制我们自己想要的东西呢? 我们需要了解两个类:
1) Canvas (画布) 2) Paint (画笔)
一个是画笔, 一个是画布, 这样就很直观了, 就是通过画笔在画布上画你想要的东西, 做了一个小的Demo
代码:
public class SelfView extends View{ public SelfView(Context context) { super(context); } public SelfView(Context context, AttributeSet attrs) { super(context, attrs); } public SelfView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } public SelfView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); Log.e("Seeyou", "View onMeasure"); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { Log.e("Seeyou", "View onLayout"); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); Log.e("Seeyou", "View onDraw"); canvas.drawCircle(getMeasuredWidth() / 2 ,getMeasuredWidth() / 2, getMeasuredWidth() / 2, new Paint()); // 在画布上画圆 Paint textPaint = new Paint(); textPaint.setColor(Color.WHITE); textPaint.setTextSize(200.0f); canvas.drawText("View", getMeasuredWidth() / 2 / 2, getMeasuredWidth() / 2, textPaint); // 在画布上写字 } }
布局:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="cn.jj.www.viewteachdemo.MainActivity"> <cn.demo.view.SelfView android:layout_width="match_parent" android:layout_height="match_parent" android:layout_margin="15dp" android:background="#223344" /> </RelativeLayout>
效果:
链接: Canvas
绘制讲解
2.View的重绘
ok到这里, 基本的绘制就算掌握了, 还有一个方法需要了解, 就是View的invalidate()方法. 通常也叫作view的重绘, 顾名思义就是把画板擦干净重新画
public void invalidate () Added in API level 1 Invalidate the whole view. If the view is visible, onDraw(android.graphics.Canvas) will be called at some point in the future. This must be called from a UI thread. To call from a non-UI thread, call postInvalidate().
说明文档告诉我们, 调用这个方法的时候, 如果这个view是visible的状态,那么就会调用它的onDraw方法
Demo:
@Override protected void onDraw(Canvas canvas) { canvas.drawCircle(center_x, center_y, 150, paint); super.onDraw(canvas); } @Override public boolean onTouchEvent(MotionEvent event) { center_x = event.getX(); center_y = event.getY(); //记录触摸事件的x y坐标; invalidate(); //每次产生触摸事件的时候都会让我们的控件进行重绘 return true; }
这样一个触摸时就会产生一个跟随触摸点移动的圆形的控件就完成了, 挺简单的吧, 动手尝试一下吧.
以上就是view的绘制和重绘, 那么接下来了解一下ViewGroup的绘制流程是什么样的呢?
3.ViewGroup绘制流程
view树结构:
view树绘制流程
Measure(测量) -> Layout(布局) -> Draw(绘制)
——|onMeasure(测量)
1.递归执行字View的onMeasure进行测量
2.执行方法setMeasuredDimension(width, heigh); 告诉父View自己需要的宽高
——|——|MeasureSpec
MeasureSpec.getSize(measureSpec);
获取父类空间传过来的可用大小
MeasureSpec.getMode(measureSpec);
获取父类空间传过来的mode
1:UNSPECIFIED(未指定),父元素不对子元素施加任何束缚,子元素可以得到任意想要的大小
2:EXACTLY(完全),父元素决定子元素的确切大小,子元素将被限定在给定的边界里而忽略它本身大小
3:AT_MOST(至多),子元素至多达到指定大小的值
参考blog: 自定义View之onMeasure()
——|onLayout(布局)
1.通过childView.layout(l, t, r, b); 将子view进行布局
——|onDraw(绘制)
1.进行View的绘制工作
Tips:
ViewGroup 主要操作的两个方法是onMeasure(测量) onLayout(布局)
View 主要操作的两个方法是onMeasure(测量) onDraw(绘制)
View 控件不被ViewGroup包裹的话 它是没有大小的
常用方法:
1.dispatchDraw() 会通知每一个子view 进行绘制 调用draw 方法
2.requestLayout(); 会进行重新的布局
相关文章推荐
- 13问13答全面学习Android View绘制
- MeasureSpec介绍及使用
- Android View的Measure过程(一)
- Android应用层View绘制流程与源码分析
- 类似短信中添加人的layout
- Android View绘制过程
- Android LinearLayout,RelativeLayout,FrameLayout onlayout()方法介绍
- 自定义View实现
- 源码分析Android中View的绘制流程
- Android绘制View相关的几个问题
- Android 手把手教你View绘制过程--自动排列View的容器
- 安卓绘制视图的流程
- view的流程(测量,布局,绘制)
- 戏说View的绘制流程
- View绘制1-工具类
- View绘制2-onMeasure
- android view绘制原理
- Android绘制文本之获取宽高笔记
- Android中View绘制流程以及invalidate()等相关方法分析
- android怎么样绘制view的