Android自定义View绘图基础

原创 2016年12月13日 16:15:00

转载请说明出处!
作者:kqw攻城狮
出处:个人站 | CSDN


Android自定义View绘图基础

View的测量

控件的测量可以说是固定写法,原生的View只支持EXACTLY的测量模式,我们自定义的控件可以重写onMeasure方法

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    setMeasuredDimension(getMeasuredSize(widthMeasureSpec), getMeasuredSize(heightMeasureSpec));
}

onMeasure方法给我们返回的widthMeasureSpecheightMeasureSpec,我们并不能直接拿过来使用,需要使用MeasureSpec类进行解析,来获取测量后的具体值。
首先需要获取测量模式

MeasureSpec.getMode(measureSpec)

getMode方法返回是测量的模式,有以下3种类型:
- MeasureSpec.EXACTLY : 精确值模式(指定值/match_parent)
- MeasureSpec.AT_MOST : 最大值模式(wrap_content)
- MeasureSpec.UNSPECIFIED : 不指定大小的测量模式(一般用不上)

获取到了测量模式以后,获取测量后的大小

MeasureSpec.getSize(measureSpec)

根据上面的意思,可以封装我们的getMeasuredSize方法

// 默认大小
private static final int DEFAULT_SIZE = 200;

/**
 * 获取测量后的大小
 *
 * @param measureSpec measureSpec
 * @return measuredSize
 */
private int getMeasuredSize(int measureSpec) {
    switch (MeasureSpec.getMode(measureSpec)) {
        case MeasureSpec.EXACTLY: // 精确值模式(指定值/match_parent)
            Log.i(TAG, "getMeasuredSize: 精确值模式");
            return MeasureSpec.getSize(measureSpec);
        case MeasureSpec.AT_MOST: // 最大值模式(wrap_content)
            Log.i(TAG, "getMeasuredSize: 最大值模式");
            return Math.min(DEFAULT_SIZE, MeasureSpec.getSize(measureSpec));
        case MeasureSpec.UNSPECIFIED: // 不指定大小的测量模式
            return DEFAULT_SIZE;
        default:
            return DEFAULT_SIZE;
    }
}

现在我们自定义的View就支持自定义的大小了,包括match_parentwrap_content具体值

View的绘制

画笔属性

创建画笔

Paint paint = new Paint();
方法 描述 举例
public void setAntiAlias(boolean aa) 设置画笔锯齿效果 true 无锯齿效果
public void setColor(@ColorInt int color) 设置画笔颜色
public void setARGB(int a, int r, int g, int b) 设置画笔的A、R、G、B值
public void setAlpha(int a) 设置画笔的Alpha值
public void setTextSize(float textSize) 设置字体的尺寸
public void setStyle(Style style) 设置画笔的风格(空心或实心) paint.setStyle(Paint.Style.STROKE);// 空心 paint.setStyle(Paint.Style.FILL); // 实心
public void setStrokeWidth(float width) 设置空心边框的宽度

Shader

BitmapShader, ComposeShader, LinearGradient, RadialGradient, SweepGradient

/**
 * Helper for drawPoints() for drawing a single point.
 */
public void drawPoint(float x, float y, @NonNull Paint paint)
canvas.drawPoint(10, 10, paint);

直线

绘制一条直线

/**
 * Draw a line segment with the specified start and stop x,y coordinates,
 * using the specified paint.
 *
 * <p>Note that since a line is always "framed", the Style is ignored in the paint.</p>
 *
 * <p>Degenerate lines (length is 0) will not be drawn.</p>
 *
 * @param startX The x-coordinate of the start point of the line
 * @param startY The y-coordinate of the start point of the line
 * @param paint  The paint used to draw the line
 */
public void drawLine(float startX, float startY, float stopX, float stopY, @NonNull Paint paint)

绘制多条直线

public void drawLines(@Size(multiple=4) @NonNull float[] pts, @NonNull Paint paint)

矩形

/**
 * Draw the specified Rect using the specified paint. The rectangle will
 * be filled or framed based on the Style in the paint.
 *
 * @param left   The left side of the rectangle to be drawn
 * @param top    The top side of the rectangle to be drawn
 * @param right  The right side of the rectangle to be drawn
 * @param bottom The bottom side of the rectangle to be drawn
 * @param paint  The paint used to draw the rect
 */
public void drawRect(float left, float top, float right, float bottom, @NonNull Paint paint)
canvas.drawRect(100, 100, 200, 200, paint);

这里写图片描述

圆角矩形

/**
 * Draw the specified round-rect using the specified paint. The roundrect
 * will be filled or framed based on the Style in the paint.
 *
 * @param rx    The x-radius of the oval used to round the corners
 * @param ry    The y-radius of the oval used to round the corners
 * @param paint The paint used to draw the roundRect
 */
public void drawRoundRect(float left, float top, float right, float bottom, float rx, float ry, @NonNull Paint paint)
canvas.drawRoundRect(100, 100, 200, 200, 20, 20, paint);

这里写图片描述

/**
 * Draw the specified circle using the specified paint. If radius is <= 0,
 * then nothing will be drawn. The circle will be filled or framed based
 * on the Style in the paint.
 *
 * @param cx     The x-coordinate of the center of the cirle to be drawn
 * @param cy     The y-coordinate of the center of the cirle to be drawn
 * @param radius The radius of the cirle to be drawn
 * @param paint  The paint used to draw the circle
 */
public void drawCircle(float cx, float cy, float radius, @NonNull Paint paint)
// 画圆
canvas.drawCircle(200, 200, 100, paint);

这里写图片描述

扇形

/**
 * <p>Draw the specified arc, which will be scaled to fit inside the
 * specified oval.</p>
 *
 * <p>If the start angle is negative or >= 360, the start angle is treated
 * as start angle modulo 360.</p>
 *
 * <p>If the sweep angle is >= 360, then the oval is drawn
 * completely. Note that this differs slightly from SkPath::arcTo, which
 * treats the sweep angle modulo 360. If the sweep angle is negative,
 * the sweep angle is treated as sweep angle modulo 360</p>
 *
 * <p>The arc is drawn clockwise. An angle of 0 degrees correspond to the
 * geometric angle of 0 degrees (3 o'clock on a watch.)</p>
 *
 * @param startAngle Starting angle (in degrees) where the arc begins
 * @param sweepAngle Sweep angle (in degrees) measured clockwise
 * @param useCenter If true, include the center of the oval in the arc, and
                    close it if it is being stroked. This will draw a wedge
 * @param paint      The paint used to draw the arc
 */
public void drawArc(float left, float top, float right, float bottom, float startAngle, float sweepAngle, boolean useCenter, @NonNull Paint paint)
// 扇形 起始角度0度 旋转角度120度
canvas.drawArc(100, 100, 200, 200, 0, 120, true, paint);

这里写图片描述

弧形

扇形通过调整属性,可以实现弧形的效果,首先画笔设置成空心

// 空心
paint.setStyle(Paint.Style.STROKE);

设置画扇形的useCenter参数为false

// 弧形 起始角度0度 旋转角度120度
canvas.drawArc(100, 100, 200, 200, 0, 120, false, paint);

这里写图片描述

椭圆

/**
 * Draw the specified oval using the specified paint. The oval will be
 * filled or framed based on the Style in the paint.
 */
public void drawOval(float left, float top, float right, float bottom, @NonNull Paint paint)
// 椭圆
canvas.drawOval(100, 100, 500, 300, paint);

这里写图片描述

文字

/**
 * Draw the text, with origin at (x,y), using the specified paint. The
 * origin is interpreted based on the Align setting in the paint.
 *
 * @param text  The text to be drawn
 * @param x     The x-coordinate of the origin of the text being drawn
 * @param y     The y-coordinate of the baseline of the text being drawn
 * @param paint The paint used for the text (e.g. color, size, style)
 */
public void drawText(@NonNull String text, float x, float y, @NonNull Paint paint)
// 文字
paint.setTextSize(30);
paint.setColor(Color.BLACK);
canvas.drawText("KongQingwei", 100, 100, paint);

这里写图片描述

在指定位置显示每个字符

/**
 * Draw the text in the array, with each character's origin specified by
 * the pos array.
 *
 * @param text  The text to be drawn
 * @param pos   Array of [x,y] positions, used to position each character
 * @param paint The paint used for the text (e.g. color, size, style)
 *
 * @deprecated This method does not support glyph composition and decomposition and
 * should therefore not be used to render complex scripts. It also doesn't
 * handle supplementary characters (eg emoji).
 */
@Deprecated
public void drawPosText(@NonNull String text, @NonNull @Size(multiple=2) float[] pos, @NonNull Paint paint)
canvas.drawPosText("KongQingwei", new float[]{
        30,30,
        60,60,
        90,90,
        120,120,
        150,150,
        180,180,
        210,210,
        240,240,
        270,270,
        300,300,
        330,330
}, paint);

这里写图片描述

绘制路径

可以自定义画出想要的任意图形

五角星

/**
 * Draw the specified path using the specified paint. The path will be
 * filled or framed based on the Style in the paint.
 *
 * @param path  The path to be drawn
 * @param paint The paint used to draw the path
 */
public void drawPath(@NonNull Path path, @NonNull Paint paint)
Path path = new Path();
path.moveTo(0,100);
path.lineTo(250,300);
path.lineTo(150,0);
path.lineTo(50,300);
path.lineTo(300,100);
path.lineTo(0,100);
canvas.drawPath(path,paint);

这里写图片描述

空心

paint.setStyle(Paint.Style.STROKE);

这里写图片描述

图形裁剪

以上面的实心五角星为例,以五角星的中心为圆心,裁剪出一个半径为100的圆形

/**
    * Modify the current clip with the specified path.
 *
 * @param path The path to operate on the current clip
 * @param op   How the clip is modified
 * @return     true if the resulting is non-empty
 */
public boolean clipPath(@NonNull Path path, @NonNull Region.Op op)
// 裁剪一个圆形
Path path = new Path();
path.reset();
path.addCircle(150, 150, 100, Path.Direction.CCW);
canvas.clipPath(path, Region.Op.INTERSECT);
// canvas.save();
// 画五角星
path.reset();
path.moveTo(0,100);
path.lineTo(250,300);
path.lineTo(150,0);
path.lineTo(50,300);
path.lineTo(300,100);
path.lineTo(0,100);
canvas.drawPath(path,paint);

这里写图片描述

Region.Op 描述 样式
INTERSECT 裁剪内部交集 这里写图片描述
DIFFERENCE 外部 这里写图片描述
版权声明:本文为博主原创文章,未经博主允许不得转载。

0916Android基础自定义View(Canvas绘图)

自定义View创建一个类继承View  自定义一个类继承View,然后将这个View添加到布局文件中 ,然后在活动中对这个View进行UI操作。然后在onDraw方法中需要用到Canvas来画各种形状...

Android自定义View绘图基础(摘自技术前沿)

Android自定义View绘图基础View的测量控件的测量可以说是固定写法,原生的View只支持 EXACTLY 的测量模式,我们自定义的控件可以 重写 onMeasure 方法   @Over...

Android 自定义View绘图篇之基础

自定义View一直是新手难以逾越的障碍,这段时间我也要开始走进这座大山了,至于能否跨越这些险峻的峭壁,不掉落山谷(害怕状ヽ( ̄︿ ̄ )),敬请期待吧!...
  • lcv587
  • lcv587
  • 2016年10月01日 17:30
  • 106

Android绘图机制(一)——自定义View的基础属性和方法

自定义View看起来,确实看起来高深莫测,很多Android开发都不是特别在行这一块,这里面的逻辑以及一些绘画都是有一点难的,说一下我目前的状况吧,结束了一个项目,现在接手一个新的项目,老项目的时候自...

Android绘图系列(一)——自定义View基础

这个系列主要是介绍下Android自定义和Android绘图机制,自己能力有限,如果在介绍过程中有什么错误,欢迎指正 一.自定义View常用的方法首先用一张图来表示自定义View绘制流程函数调用链(简...

Android绘图机制(一)——自定义View的基础属性和方法

标签: android动画实例图形数据 2016-01-04 17:36 1832人阅读 评论(6) 收藏 举报  分类: Android(110)  版权声明:本...

Android 绘图基础:Canvas画布——自定义View基础(绘制表盘、矩形、圆形、弧、渐变)

今天学习了Canvas画布,感觉挺好玩的,通过它我们可以自定义一个View,设置View的相关效果之类的。感觉用法差不多,重要的是要理解方法中传入的参数的含义,比如float类型的参数,传递的是坐标,...

Android 绘图基础:Canvas画布——自定义View基础(绘制表盘、矩形、圆形、弧、渐变)

(转自:http://blog.csdn.net/danfengw/article/details/48503619)     今天学习了Canvas画布,感觉挺好玩的,通过它我们可以自定...
  • Baby_T
  • Baby_T
  • 2016年10月17日 10:55
  • 544

自定义view—绘图基础Canvas+Paint

学习导航本章讲解: 自定义视图,我们需要做哪些准备!对于一些中级的开发者来说就要接触到自定义视图,由于Android自带的视图无法满足自己需求,又或者美观度不够自己的要求,我们就要自来亲自设计自己的视...

自定义View之绘图篇(一):基础图形的绘制

生活是一面镜子,你对它笑,它就对你笑;你对它哭,它也对你哭。——萨克雷在正文开始之前,我先抛一个脑洞大开的题目给大家:商人以45元一双进购了2双鞋子,然后亏本30一双出售。某个顾客给了他100买了2双...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Android自定义View绘图基础
举报原因:
原因补充:

(最多只允许输入30个字)