Android 自定义View总结 —— onDraw

来源:互联网 发布:淘宝蚂蚁花呗怎么开通 编辑:程序博客网 时间:2024/06/05 20:10

说明:本博客为原创,转载请注明出处 CSDN-ANDROID笔记栈
由于作者水平有限,错误在所难免,请见谅,可以留言,本人会及时改正


索引

  • onDraw
  • Canvas
  • Demo


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中更改默认启动项

运行结果截图
ViewOnDraw示例

// DLCustomCircleView// 这里只是简单的示例,Canvas有许多复杂的操作请自行googleprotected 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);}

0 0
原创粉丝点击