Android绘图之Paint的使用方法详解
前言
大家都知道在android中,自定义控件是一个非常重要的知识点,而自定义控件对android开发者是一个难点,考验开发人员对view原理的理解,对于继承view的自定义控件,一般都需要重写ondraw方法,而且往往需要开发人员能够掌握paint这个类。
简介
the paint class holds the style and color information about how to draw geometries, text and bitmaps.
paint:该类保存了绘制几何图形、文本和位图的样式和颜色信息。也就是说我们可以使用paint保存的样式和颜色,来绘制图形、文本和bitmap,这就是paint的强大之处。接下来我们使用paint来绘图,并且看看该类有哪些样式和颜色。
paint的使用
使用paint之前需要初始化
mpaint = new paint();
设置笔(paint)的颜色和alpha值:
mpaint.setcolor(color.blue); mpaint.setalpha(255);
注意:alpha的范围是[0..255],而不是[0..1],是一个int值。
设置画笔的样式:通过mpaint.setstyle()来设置样式。
public enum style { /** * geometry and text drawn with this style will be filled, ignoring all * stroke-related settings in the paint. */ fill (0), /** * geometry and text drawn with this style will be stroked, respecting * the stroke-related fields on the paint. */ stroke (1), /** * geometry and text drawn with this style will be both filled and * stroked at the same time, respecting the stroke-related fields on * the paint. this mode can give unexpected results if the geometry * is oriented counter-clockwise. this restriction does not apply to * either fill or stroke. */ fill_and_stroke (2); style(int nativeint) { this.nativeint = nativeint; } final int nativeint; }
总共有三种画笔的样式
fill:填充内容;
stroke:描边;
fill_and_stroke:填充内容并描边。
设置画笔的宽度
mpaint.setstrokewidth(50);
设置画笔的线帽
通过mpaint.setstrokecap
来设置线帽,总共有三种线帽
/** * the cap specifies the treatment for the beginning and ending of * stroked lines and paths. the default is butt. */ public enum cap { /** * the stroke ends with the path, and does not project beyond it. */ butt (0), /** * the stroke projects out as a semicircle, with the center at the * end of the path. */ round (1), /** * the stroke projects out as a square, with the center at the end * of the path. */ square (2); private cap(int nativeint) { this.nativeint = nativeint; } final int nativeint; }
butt:没有线帽,默认模式
round:圆形
square:方形
三种线帽对比:
@override protected void ondraw(canvas canvas) { super.ondraw(canvas); mpaint.setcolor(color.blue); mpaint.setalpha(255); //设置画笔的样式 mpaint.setstyle(paint.style.fill_and_stroke); //画笔的宽度 mpaint.setstrokewidth(50); mpaint.setstrokecap(paint.cap.square);//方形 mpaint.setstrokejoin(paint.join.bevel);//直线 path path = new path(); path.moveto(100, 100); path.lineto(300, 100); canvas.drawpath(path, mpaint); mpaint.reset();//重置 mpaint.setcolor(color.red); mpaint.setstyle(paint.style.fill_and_stroke); mpaint.setstrokewidth(50); mpaint.setstrokecap(paint.cap.round);//圆形 mpaint.setstrokejoin(paint.join.bevel);//直线 path path1 = new path(); path1.moveto(100, 200); path1.lineto(300, 200); canvas.drawpath(path1, mpaint); mpaint.reset();//重置 mpaint.setcolor(color.green); mpaint.setstyle(paint.style.fill_and_stroke); mpaint.setstrokewidth(50); mpaint.setstrokecap(paint.cap.butt);//没有 mpaint.setstrokejoin(paint.join.bevel);//直线 path path2 = new path(); path2.moveto(100, 300); path2.lineto(300, 300); canvas.drawpath(path2, mpaint); }
上面代码中有个重置画笔,这时候需要重新设置画笔。
线帽对比
设置join
使用setstrokejoin方法来设置join,join有三种类型:
bevel:直线
round:圆角
miter:锐角
@override protected void ondraw(canvas canvas) { super.ondraw(canvas); mpaint.setcolor(color.blue); mpaint.setalpha(255); mpaint.setstyle(paint.style.stroke);//设置画笔的样式 mpaint.setstrokewidth(50);//画笔的宽度 mpaint.setstrokecap(paint.cap.butt);//线帽 mpaint.setstrokejoin(paint.join.bevel); path path = new path(); path.moveto(100, 100); path.lineto(300, 100); path.lineto(100, 300); path.close(); canvas.drawpath(path, mpaint); mpaint.reset();//重置 mpaint.setcolor(color.red); mpaint.setstyle(paint.style.fill_and_stroke); mpaint.setstrokewidth(50); mpaint.setstrokecap(paint.cap.butt);//圆形 mpaint.setstrokejoin(paint.join.round);//圆弧 path path1 = new path(); path1.moveto(100, 400); path1.lineto(300, 400); path1.lineto(100, 700); path1.close(); canvas.drawpath(path1, mpaint); mpaint.reset();//重置 mpaint.setcolor(color.green); mpaint.setstyle(paint.style.fill_and_stroke); mpaint.setstrokewidth(50); mpaint.setstrokecap(paint.cap.butt);//没有 mpaint.setstrokejoin(paint.join.miter);//锐角 path path2 = new path(); path2.moveto(100, 800); path2.lineto(300, 800); path2.lineto(100, 1100); path2.close(); canvas.drawpath(path2, mpaint); }
join对比
以上就是join三种类型对比。
设置防锯齿
mpaint.setantialias(true);
如果设置防锯齿,会损失一定的性能
抖动处理
使用mpaint.setdither()方法,设置是否使用图像抖动处理。会使绘制的图片等颜色更加的清晰以及饱满,也是损失性能。
使用path绘制图形
path绘制图形
点组成线,线组成面,这样path可以绘制各种各样的图形,可以说是无所不能的了,但是path也提供了很多方法,来绘制图形。
文本绘制
上文中,介绍了paint画笔,和绘制了一些图形。但是介绍paint的时候,我们知道它可以绘制图形,文本和bitmap,所以paint是非常强大的了,我们看下paint是如何绘制文本的。
设置字符之间的间距
setletterspacing
设置文本删除线
mpaint.setstrikethrutext(true);
是否设置下划线
mpaint.setunderlinetext(true);
设置文本大小
mpaint.settextsize(textsize);
设置字体类型
mpaint.settypeface(typeface.bold); // style public static final int normal = 0;//常规 public static final int bold = 1;//粗体 public static final int italic = 2; //斜体 public static final int bold_italic = 3;//粗斜体
字体类型有以上四种类型可以设置。
加载自定义字体
typeface.create(familyname, style)
文字倾斜
mpaint.settextskewx(-0.25f);
文字倾斜默认为0,官方推荐的-0.25f是斜体
文本对齐方式
mpaint.settextalign(align.left)
有三种:
public enum align { /** * the text is drawn to the right of the x,y origin */ left (0),//左对齐 /** * the text is drawn centered horizontally on the x,y origin */ center (1),//居中 /** * the text is drawn to the left of the x,y origin */ right (2);//右对齐 private align(int nativeint) { this.nativeint = nativeint; } final int nativeint; }
计算制定长度的字符串
int breadtext = mpaint.breaktext(text, measureforwards, maxwidth, measuredwidth)
注意:字符长度、字符个数、显示的时候是真实的长度
rect bounds获取文本的矩形区域(宽高) mpaint.gettextbounds(text, index, count, bounds) mpaint.gettextbounds(text, start, end, bounds) //获取文本的宽度,和上面类似,但是是一个比较粗略的结果 float measuretext = mpaint.measuretext(str); //获取文本的宽度,和上面类似,但是是比较精准的。 float[] measuredwidth = new float[10]; //measuredwidth得到每一个字符的宽度;textwidths字符数 int textwidths = mpaint.gettextwidths(str, measuredwidth); mpaint.gettextwidths(text, start, end, widths)
使用drawtext绘制文本
public class paintview extends view { private paint mpaint; private string text = "你是我世界之光,我心另一半"; public paintview(context context) { this(context,null); } public paintview(context context, @nullable attributeset attrs) { this(context, attrs,0); } public paintview(context context, @nullable attributeset attrs, int defstyleattr) { super(context, attrs, defstyleattr); init(context, attrs, defstyleattr); } private void init(context context, attributeset attrs, int defstyleattr) { mpaint = new paint(); } @override protected void ondraw(canvas canvas) { super.ondraw(canvas); mpaint.setcolor(color.blue); mpaint.setstyle(paint.style.stroke);//设置画笔的样式 mpaint.setstrokecap(paint.cap.butt);//线帽 mpaint.setstrokejoin(paint.join.bevel); int top = 100; int baselinex = 0; mpaint.settextsize(50); mpaint.settextalign(paint.align.left); canvas.drawline(0, top, 2000, top, mpaint); //文本metrics paint.fontmetrics fontmetrics = mpaint.getfontmetrics(); float baseliney = top - fontmetrics.top; canvas.drawtext(text, baselinex, baseliney, mpaint); } }
绘制文本
绘制文本时,还有一个很重要的知识点就是基线的确定
drawtext 基线的确定
在自定义控件的时候,有时候会用到drawtext 方法.
先把自定义textview的贴出来
@override protected void ondraw(canvas canvas) { super.ondraw(canvas); int x = getpaddingleft(); //dy 代表的是:高度的一半到 baseline的距离 paint.fontmetricsint fontmetrics = paint.getfontmetricsint(); // top 是一个负值 bottom 是一个正值 top,bttom的值代表是 bottom是baseline到文字底部的距离(正值) // 必须要清楚的,可以自己打印就好 int dy = (fontmetrics.bottom - fontmetrics.top)/2 - fontmetrics.bottom; int baseline = getheight()/2 + dy; canvas.drawtext(costom_text,x,baseline,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) { native_drawtext(mnativecanvaswrapper, text, 0, text.length(), x, y, paint.mbidiflags, paint.getnativeinstance(), paint.mnativetypeface); }
x,y 分别表示 基线的开始坐标,并不是 文字左上角的坐标,因为文字的绘制是以基线为基础的
图中的 五角星 所在的线 就是基线 baseline,那么如何确定基线的x,y坐标呢?
首写我们先确定一下x坐标 :int x = getpaddingleft();
也就是文字距左边的距离
y坐标:
1、我们先计算一下文字高度的一半到 baseline的距离。
int dy = (fontmetrics.bottom - fontmetrics.top)/2 - fontmetrics.bottom;
2、之后我们再使用控件高度的一般,加上文字高度的一半到 baseline的距离,就是基线的y坐标
int baseline = getheight()/2 + dy;
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对的支持。
上一篇: SQL 注入式攻击的本质
下一篇: Android 给控件添加边框阴影效果
推荐阅读
-
Android之ImageSwitcher的实例详解
-
React Native学习之Android的返回键BackAndroid详解
-
Android自带emoji表情的使用方法详解
-
Android开发之瀑布流控件的实现与使用方法示例
-
python开发之IDEL(Python GUI)的使用方法图文详解
-
Android开发之MediaPlayer基本使用方法详解
-
Android 中RxPermissions 的使用方法详解
-
Android之采用execSQL与rawQuery方法完成数据的添删改查操作详解
-
Android ListView之EfficientAdapte的使用详解
-
深入Android MediaPlayer的使用方法详解