你好,游客 登录
背景:
阅读新闻

Android自定义View绘图基础

[日期:2017-01-05] 来源:  作者: [字体: ]

  Android自定义View绘图基础

  View的测量

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

  @Override

  protectedvoidonMeasure(intwidthMeasureSpec,intheightMeasureSpec){

  setMeasuredDimension(getMeasuredSize(widthMeasureSpec), getMeasuredSize(heightMeasureSpec));

  }

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

  首先需要获取测量模式

  MeasureSpec.getMode(measureSpec)

  ```

  getMode方法返回是测量的模式,有以下3种类型:

  - MeasureSpec.EXACTLY : 精确值模式(指定值/match_parent)

  - MeasureSpec.AT_MOST : 最大值模式(wrap_content)

  - MeasureSpec.UNSPECIFIED : 不指定大小的测量模式(一般用不上)

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

  ``` java

  MeasureSpec.getSize(measureSpec)

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

  // 默认大小

  private static final int DEFAULT_SIZE = 200;

  /**

  * 获取测量后的大小

  *

  * @param measureSpec measureSpec

  * @return measuredSize

  */

  privateintgetMeasuredSize(intmeasureSpec){

  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_parent 、 wrap_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.

  */

  publicvoiddrawPoint(floatx,floaty, @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.

  *

  *

Note that since a line is always "framed", the Style is ignored in the paint.

 

  *

  *

Degenerate lines (length is 0) will not be drawn.

 

  *

  * @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

  */

  publicvoiddrawLine(floatstartX,floatstartY,floatstopX,floatstopY, @NonNull Paint paint)

  绘制多条直线

  publicvoiddrawLines(@Size(multiple=4)@NonNullfloat[] 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

  */

  publicvoiddrawRect(floatleft,floattop,floatright,floatbottom, @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

  */

  publicvoiddrawRoundRect(floatleft,floattop,floatright,floatbottom,floatrx,floatry, @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

  */

  publicvoiddrawCircle(floatcx,floatcy,floatradius, @NonNull Paint paint)

  // 画圆

  canvas.drawCircle(200, 200, 100, paint);

  扇形

  /**

  *

Draw the specified arc, which will be scaled to fit inside the

  * specified oval.

 

  *

  *

If the start angle is negative or >= 360, the start angle is treated

  * as start angle modulo 360.

 

  *

  *

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

 

  *

  *

The arc is drawn clockwise. An angle of 0 degrees correspond to the

  * geometric angle of 0 degrees (3 o'clock on a watch.)

 

  *

  * @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

  */

  publicvoiddrawArc(floatleft,floattop,floatright,floatbottom,floatstartAngle,floatsweepAngle,booleanuseCenter, @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.

  */

  publicvoiddrawOval(floatleft,floattop,floatright,floatbottom, @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)

  */

  publicvoiddrawText(@NonNull String text,floatx,floaty, @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

  publicvoiddrawPosText(@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

  */

  publicvoiddrawPath(@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

  */

  publicbooleanclipPath(@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 裁剪内部交集 #FormatImgID_11#
DIFFERENCE 外部 #FormatImgID_12#  
收藏 推荐 打印 | 录入: | 阅读:
本文评论   查看全部评论 (0)
表情: 表情 姓名: 字数
点评:
       
评论声明
  • 尊重网上道德,遵守中华人民共和国的各项有关法律法规
  • 承担一切因您的行为而直接或间接导致的民事或刑事法律责任
  • 本站管理人员有权保留或删除其管辖留言中的任意内容
  • 本站有权在网站内转载或引用您的评论
  • 参与本评论即表明您已经阅读并接受上述条款