【Android】View绘制过程分析之draw
16lz
2022-01-28
续前文“【Android】View绘制过程分析之layout",继续分析View的绘制过程。
本文分析第3阶段,分析过程的注释标记在以下代码中。
/** * 绘制过程 */public void draw(Canvas canvas) { if (mClipBounds != null) { canvas.clipRect(mClipBounds); } 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; /* * 绘制过程依次进行下面的6步处理: * 1. 绘制背景 * 2. If necessary, save the canvas' layers to prepare for fading * 3. 绘制View的内容, 在onDraw(canvas)方法中完成 * 4. 绘制子View的内容 * 5. If necessary, draw the fading edges and restore layers * 6. 绘制装饰品(如滚动条) */ // 第1步,绘制背景 int saveCount; if (!dirtyOpaque) { final Drawable background = mBackground; if (background != null) { final int scrollX = mScrollX; final int scrollY = mScrollY; if (mBackgroundSizeChanged) { background.setBounds(0, 0, mRight - mLeft, mBottom - mTop); mBackgroundSizeChanged = false; } if ((scrollX | scrollY) == 0) { background.draw(canvas); } else { canvas.translate(scrollX, scrollY); background.draw(canvas); canvas.translate(-scrollX, -scrollY); } } } // 一般情况下,会跳过第2步与第5步 final int viewFlags = mViewFlags; boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0; boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0; if (!verticalEdges && !horizontalEdges) { // 第3步,绘制View的内容,自定义View时,这个方法需要我们去实现。 if (!dirtyOpaque) onDraw(canvas); // 第4步,绘制子View的内容,参考ViewGroup中dispatchDraw(canvas)方法的实现, //OK,你猜到了!又是一次遍历子View的过程,子View再调用draw(canvas)方法绘制自己及孙View。 //父View与子View这样的遍历过程,是Android一贯的做法。 dispatchDraw(canvas); // 第6步,绘制装饰品(如滚动条) onDrawScrollBars(canvas); if (mOverlay != null && !mOverlay.isEmpty()) { mOverlay.getOverlayView().dispatchDraw(canvas); } return; }}/** * 绘制View的内容,在View类此方法空实现。但在自定义View类时,要实现此方法。 * 在这个方法中,可做的事情就多了,Canvas提供了丰富的绘图方法,关键是灵活运用! * 通常,你还可以通过调用以下方法或protected属性获取到一次绘制时需要用到的数值: * getMeasuredWidth()与getMeasuredHeight() 获取measure()中计算到的宽度与高度 * mPaddingLeft, mPaddingTop, mPaddingRight, mPaddingBottom, mScrollX, mScrollY等等,直接使用。 */protected void onDraw(Canvas canvas) {}/** * 下面看一下ImageView的绘制: */protected void onDraw(Canvas canvas) { super.onDraw(canvas); if (mDrawable == null) { return; // couldn't resolve the URI } if (mDrawableWidth == 0 || mDrawableHeight == 0) { return; // nothing to draw (empty bounds) } if (mDrawMatrix == null && mPaddingTop == 0 && mPaddingLeft == 0) { mDrawable.draw(canvas); } else { int saveCount = canvas.getSaveCount(); canvas.save(); if (mCropToPadding) { final int scrollX = mScrollX; final int scrollY = mScrollY; canvas.clipRect(scrollX + mPaddingLeft, scrollY + mPaddingTop, scrollX + mRight - mLeft - mPaddingRight, scrollY + mBottom - mTop - mPaddingBottom); } canvas.translate(mPaddingLeft, mPaddingTop); if (mDrawMatrix != null) { canvas.concat(mDrawMatrix); } mDrawable.draw(canvas); canvas.restoreToCount(saveCount); }}
@容新华技术博客 - http://blog.csdn.net/rongxinhua - 原创文章,转载请注明出处
更多相关文章
- Android(安卓)VelocityTracker的使用
- Android(安卓)深入理解 View 的绘制流程和机制
- android 获取路径目录方法以及判断目录是否存在,创建目录
- Android(安卓)获取控件的宽和高
- android读取plist文件
- Android之Handler用法总结
- android获取安装的应用程序
- 浅谈Java中Collections.sort对List排序的两种方法
- Python list sort方法的具体使用