说明:本博客为原创,转载请注明出处 优快云-ANDROID笔记栈
由于作者水平有限,错误在所难免,请见谅,可以留言,本人会及时改正
索引
onDraw
自定义View最后显示的内容就是通过重载这个方法来实现的
protected void onDraw(Canvas canvas) {
// 在View中这个方法留空了,交给实现类去做了
}
在xml中添加如下代码,运行结果还是能看到一个大小48x48(dp)、背景为红色的View,但是我们在自定义View的onDraw中什么都没做,这个红色背景是什么来的呢?
<com.neulion.android.dl.customviewdemo.widget.DLCustomView
android:layout_width="48dp"
android:layout_height="48dp"
android:background="#ff0000" />
View呈现图像的入后是draw方法
public void draw(Canvas canvas) {
...
// Step 1, draw the background, if needed
int saveCount;
if (!dirtyOpaque) {
drawBackground(canvas);
}
// skip step 2 & 5 if possible (common case)
if (!verticalEdges && !horizontalEdges) {
// Step 3, draw the content
if (!dirtyOpaque) onDraw(canvas);
// 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;
}
...
}
在draw方法中,步骤写的很详细了
1.先画背景 (#2,#5略过,所以在Demo中还是能看到红色背景)
3.绘制自己
4.绘制子View
6.绘制前景
Canvas
知道了View的绘制过程,在onDraw中只要操作canvas就可以实现你想要的结果了
下面看一下ImageView的onDraw方法
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mDrawable == null) {
return; // couldn't resolve the URI
}
if (mDrawMatrix == null && mPaddingTop == 0 && mPaddingLeft == 0) {
mDrawable.draw(canvas);// 在画布上把Drawable画上去了
}
else {
final int saveCount = canvas.getSaveCount();
canvas.save();
...
mDrawable.draw(canvas);
canvas.restoreToCount(saveCount);
}
}
在Canvas中定义了许多方法
// 矩形
public void drawRect(...);
// 图片
public void drawBitmap(...)
// 圆
public void drawCircle(...)
// 线
public void drawLine(...)
// ...
Demo
GitHub地址: GitHub
环境: Windows7+JAVA8
IDE: AndroidStdio2.2.2
compileSdkVersion:24
测试设备:Nexus5(6.0.1)
demo中有多个示例,请在Manifest中更改默认启动项
运行结果截图
// DLCustomCircleView
// 这里只是简单的示例,Canvas有许多复杂的操作请自行google
protected void onDraw(Canvas canvas){
// 居中,以中心点开始画圆
if (mCircleGravity == GRAVITY_CENTER){
canvas.drawCircle(getWidth() / 2, getHeight() / 2, mCircleRadius, mPaint);
}
// 以左上角为原点
else if (mCircleGravity == GRAVITY_START){
canvas.drawCircle(0, 0, mCircleRadius, mPaint);
}
// 以右下角为原点,
else if (mCircleGravity == GRAVITY_END){
canvas.drawCircle(getWidth(), getHeight(), mCircleRadius, mPaint);
}
}
// 测量View的小大
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
int width;
int height;
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
// 如果是wrap_content,大小就是圆直径
if (widthMode != MeasureSpec.EXACTLY){
width = mCircleRadius * 2;
}
else{
width = MeasureSpec.getSize(widthMeasureSpec);
}
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
if (heightMode != MeasureSpec.EXACTLY){
height = mCircleRadius * 2;
}
else{
height = MeasureSpec.getSize(heightMeasureSpec);
}
setMeasuredDimension(width, height);
}
// 初始化的时候,读取xml属性
private void initialize(Context context, AttributeSet attrs){
TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.DLCustomCircleView);
mCircleGravity = array.getInt(R.styleable.DLCustomCircleView_circleGravity, GRAVITY_CENTER);
int mCircleColor = array.getColor(R.styleable.DLCustomCircleView_circleColor, 0);
mCircleRadius = array.getInt(R.styleable.DLCustomCircleView_circleRadius, 16);
array.recycle();
// 初始化Paint,画笔也有很多属性 自行google
mPaint = new Paint();
mPaint.setColor(mCircleColor);
}