前言
draw是绘制View三个步骤中的最后一步。同measure、layout一样,通常不对draw本身进行重写,draw内部会调用onDraw方法,子类View需要重写onDraw(Canvas),以完成最终的绘制。
如果一定要重写draw(Canvas)的话,需要在方法的开始处调用super.draw(canvas)。
draw过程
draw内部具体做了什么事情,在View.java的源码注释中已经做了非常详细的介绍
/* * Draw traversal performs several drawing steps which must be executed * in the appropriate order: * * 1. Draw the background * 2. If necessary, save the canvas' layers to prepare for fading * 3. Draw view's content * 4. Draw children * 5. If necessary, draw the fading edges and restore layers * 6. Draw decorations (scrollbars for instance) */
- 绘制背景
- 若需要的话,保留画布的图层,以便实现fading效果时使用
- 绘制内容,这一步调用了onDraw方法
- 绘制子View,对于ViewGroup需要实现该方法
- 若需要的话,绘制fading的边缘并且恢复图层
- 绘制附件(譬如滚动条)
一个简单的自定义View
draw这个过程,在目前的阶段能讲的东西并不多。如果深入到具体一个SDK已经实现的View内部去看代码,够我吃一大壶的了——单单是最常用的TextView,它的onDraw就非常复杂。
这里自己实现一个非常简单的Custom View——在一块背景色上显示一行文字。先来看一下完成后的页面截图:
是不是非常简单?下面是自定义的ThreeBodyView.java
public class ThreeBodyiView extends View { private Paint mPaint; private String mText; public ThreeBodyiView(Context context, AttributeSet attrs) { super(context, attrs); mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mText = "nothing to show..."; } @Override protected void onDraw(Canvas canvas) { mPaint.setColor(Color.GREEN); // 背景色 canvas.drawRect(0, 0, getWidth(), getHeight(), mPaint); mPaint.setColor(Color.RED); mPaint.setTextSize(100); // 文字颜色、大小 canvas.drawText(mText, 0, getHeight() / 2, mPaint); } public void setText (String s) { mText = s; super.invalidate(); } }
ThreeBodyView.java在一块矩形区域里显示了一行文字,可以通过setText(String)方法来动态改变所显示的文字。
在使用的时候,是这样用的:
fake_main_activity.xml
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/fake_main_layout" android:layout_width="match_parent" android:layout_height="match_parent" > <com.leili.imhere.view.ThreeBodyiView android:id="@+id/three_body_view" android:layout_width="300dp" android:layout_height="300dp" /> </FrameLayout>
FakeMainActivity.java
public class FakeMainActivity extends Activity { private ThreeBodyiView tbView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); super.setContentView(R.layout.fake_main_activity); tbView = (ThreeBodyiView) super.findViewById(R.id.three_body_view); tbView.setText("世界属于三体!"); } }
小结
分析了draw的过程,在讲解onDraw时,佐以一个简单的demo,demo中实现一个弱化的TextView。
下一篇是本系列的完结篇,会做一个较完整的自定义View/ViewGroup。