自定义View之Paint(画笔)的使用

我们在自定义View的时候总是会用到Paint画笔对象和Canvas对象,我是这么理解的,你要画一个自定义View就必须要有水彩笔和你的A4纸(当然我只是这么一说,也可以使任何纸),水彩笔就相当于Paint画笔对象,可以设置它的颜色,粗细,想要画的字的大小,形状以及一些样式,接下来,我们来看一下这个画笔对象是什么以及怎么使用.

Paint是什么?

首先来看一下官方解释:

The Paint class holds the style and color information about how to draw geometries, text and bitmaps.

用我粗略的英语水平翻译一下,Paint对象保存了样式,颜色信息以及如何画几何图形,写文字和画图片的信息.就可以简单的理解为我上面开篇所说的,就理解成你画画时用的水彩笔就可以了,它有粗细颜色等信息,Paint就是用来保存这些信息.

来看一下Paint的构造函数

总共有三个,我们一一来看一下:

1.创建一个空的Paint,里面什么信息都没有保存

2.根据特殊的flags创建Paint(比如扛锯齿等等),下面介绍怎么用时会说到,莫急

3.创建一个Paint,里面有你创建的上一个Paint对象的一下信息,用来避免重复赋值以及节省代码时间

在来看一下对于Paint来说比较重要的它的6个枚举内部类(可以理解为只有五个)

1.Align  文字的对齐方式

2.Cap    线帽,可能你在此处不怎么理解,下面看效果图就一目了然

3.FontMetrics    字体矩阵,用来控制文字的矩阵变换,里面包含了一些文字的参数变量

4.FontMetricsInt   其实和FontMetrics是差不多的,只不过精度改为了int而已,方法什么的都差不多

5.Join    我理解为线段折弯处的变现,看下面效果也会一目了然

6.Style   样式,这个简单,设置画笔的样式

好了,啰嗦完了,现在可以进入主题了

Paint怎么用?

使用Paint,就意味着要初始化,一般分为这几个步骤,在前几个博客也有讲过

1.继承View

2.重写构造函数

3.初始化Paint对象

4.重写onMeasure(这里我们不重写,以后我们会经常用到)

5.重写onDraw函数

6.(不要忘了在xml文件中运用,需要用包名,不然肯定是没有效果的,是中只有hello world,小错误没必要犯)

我们一般都会选择在构造函数中初始化画笔等的对象,这样每次创建对象的时候都能初始化,而且只有一次,后续需要修改也可以.在onDraw函数中,会有一个画布Canvas对象的使用,如果你不懂,那就请看我的这篇文章--->

自定义View之Cancas的使用

我们就从他的6个内部枚举开始讲起,从最简单的开始

Style

public enum Style {
        FILL            (0),      //填充内部
        STROKE          (1),      //描边
        FILL_AND_STROKE (2);      //描边和填充内部
}

这里第一个给出全部的代码,之后修改的代码就是在两个地方,为了避免重复,你们自己改一下就行了

STROKE

直接上代码,效果跟下面对比很明显

public class MyPaintView extends View {

    private Paint mPaint;

    public MyPaintView(Context context) {
        this(context,null);
    }

    //这个都构造函数是必须的,我是采用调用下面那个的方式
    public MyPaintView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs,0);
    }

    public MyPaintView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initControl();                                     //初始化画笔
    }

    private void initControl() {
        mPaint = new Paint();
        mPaint.setStyle(Paint.Style.STROKE);               //设置成描边的效果,也就是画边框
        mPaint.setStrokeWidth(10);                         //设置描边的宽度粗细
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.translate(getWidth()/2,getHeight()/2);      //把画布移动到中间
        canvas.drawCircle(0,0,200,mPaint);                 //画圆
    }
}

效果图

额,这图片怎么看起来有点不舒服,总感觉不够圆,毛毛草草的,是吧,(不信你就放大了看,会很明显的),其实圆也是无数条线段画出来的,所以这就会出现一种齿轮的感觉,我们要去掉这种状态就叫做抗锯齿,既然我们都看出来了,那安卓早就想到了,下面我们来解决他.come on~

    private void initControl() {
        mPaint = new Paint();
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(10);
        mPaint.setAntiAlias(true);                 //设置抗锯齿
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.translate(getWidth()/2,getHeight()/2);
        canvas.drawCircle(0,0,200,mPaint);
    }

效果图

现在图片看上去是不是舒服多了~圆滑,顺溜,舒服~

就是这样,你没看错,这里就多了一句话,上面用注释标出来了,现在来讲下上面说的根据构造函数来创建Paint对象的方法.

其实flags就是在Paint类下的一些常量,你可以在源码中看到,这里我就介绍一个,其他的类似,自己琢磨一下很容易就懂啦~

    private void initControl() {
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);       //创建对象时传入flag
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(10);
//        mPaint.setAntiAlias(true);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.translate(getWidth()/2,getHeight()/2);
        canvas.drawCircle(0,0,200,mPaint);
    }

这里的效果和上面的那个抗锯齿的效果是一样的.就不给效果图了,自己尝试吧~加油宝贝~

除此之外,下面还有很多这样的常量,也可以使用setXXX的方式设置进去,看你自己喜欢咯~

这里有设置图像是否抖动等等的方式,我是认为现在我也不是很了解图像这方面的知识,有点像是PS的内容,(说实话我也不知道是不是,如果你们知道,请你们告诉我,学习是我喜欢做的事情~),现在暂时放一放,日后等我研读完启舰大神的《Android自定义控件入门与实战》再来跟你们回头狠狠分析一波~ok,next~

FILL

直接看代码和效果图吧

    private void initControl() {
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setStyle(Paint.Style.FILL);           //改为FILL样式
        mPaint.setStrokeWidth(10);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.translate(getWidth()/2,getHeight()/2);
        canvas.drawCircle(0,0,200,mPaint);
    }

效果图

效果很明显,就不多说什么了,自己体会~这里顺带说一下,我没有设置画笔的颜色,默认就是黑色的,下面我会设置成其他的颜色.

 FILL_AND_STROKE

    private void initControl() {
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setColor(Color.RED);                        //设置画笔颜色为红色
        mPaint.setStyle(Paint.Style.FILL_AND_STROKE);      //描边和填充内部
        mPaint.setStrokeWidth(10);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.translate(getWidth()/2,getHeight()/2);
        canvas.drawCircle(0,0,200,mPaint);
    }

效果图

这里看不出来有没有描边,和填充的看上去没什么区别,下面,我们来区别一下,我们把三种效果合在一起看就很明显了.

    private void initControl() {
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setColor(Color.RED);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(30);                                        //边宽度
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.translate(getWidth()/2,getHeight()/2);
        canvas.drawCircle(0,-300,100,mPaint);                             //STROKE样式

        mPaint.setStyle(Paint.Style.FILL);                                //FILL样式
        canvas.drawCircle(0,0,100,mPaint);

        mPaint.setStyle(Paint.Style.FILL_AND_STROKE);                     //FILL_AND_STROKE
        canvas.drawCircle(0,300,100,mPaint);

        mPaint.setColor(Color.BLACK);                                     //设置画笔颜色
        mPaint.setStrokeWidth(3);                                         //设置画笔为黑色
        canvas.drawLine(-100,-getHeight()/2,-100,getHeight()/2,mPaint);   //辅助线
        canvas.drawLine(100,-getHeight()/2,100,getHeight()/2,mPaint);     //辅助线
    }    

效果图

我们画的是半径为100的圆,我故意把边的粗细改为30,让效果更佳明显,通过辅助线,可以看的很明显了吧~我就不多说什么了,下面我在演示Cap和Join的时候也会直接上对比图,这里是带你慢慢理解,最后还是要放在一起对比,如果你想一一尝试的话自己去尝试,很简单,我就直接给对比图了~请理解,不懂的话联系我~

 Cap(线帽)

直接上代码看效果吧~讲不清楚~so sorry~

还是一样,先看一下源码,然后我就直接展示所有了,对比着学更容易些,我是这么觉得,你要是不理解的话自行分开来画一下

源码:(总共三个常量)

    public enum Cap {
        BUTT    (0),       //这里都是我理解的,没有线帽
        ROUND   (1),       //圆的
        SQUARE  (2);       //方的
    }

效果代码: 

    private void initControl() {
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setColor(Color.RED);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(100);
        mPaint.setStrokeCap(Paint.Cap.SQUARE);                           //SQUARE线帽
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.translate(getWidth()/2,getHeight()/2);
        canvas.drawLine(-100,-200,100,-200,mPaint);                      //画直线

        mPaint.setStrokeCap(Paint.Cap.ROUND);                            //ROUND线帽
        canvas.drawLine(-100,0,100,0,mPaint);

        mPaint.setStrokeCap(Paint.Cap.BUTT);                             //BUTT线帽
        canvas.drawLine(-100,200,100,200,mPaint);

        mPaint.setColor(Color.BLACK);                                    //以下是辅助线
        mPaint.setStrokeWidth(3);
        canvas.drawLine(-100,-getHeight()/2,-100,getHeight()/2,mPaint);
        canvas.drawLine(100,-getHeight()/2,100,getHeight()/2,mPaint);
    }

效果图

这里我故意设置描边的宽度为100,为了效果,说白了就是给线条带了顶帽子,Cap的三个常量就代表帽子的样式而已~

 Join

这个我也不知道如何解释,我能解释的就是线条折弯处的圆角还是其他样式,直接看效果吧,也是非常明显的

还是一样,源码:(也是3个)

    public enum Join {
        MITER   (0),
        ROUND   (1),
        BEVEL   (2);
    }

效果代码:(因为是线段折弯处的效果,所以这里我画一个类似字码Z来让你看清楚折弯处的表现)

    private void initControl() {
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setColor(Color.RED);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(30);
        mPaint.setStrokeJoin(Paint.Join.BEVEL);            //折弯处表现为BEVEL
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.translate(getWidth()/2,getHeight()/2);
        Path path = new Path();              
        path.moveTo(-100,-100);
        path.lineTo(100,-100);
        path.lineTo(-100,100);
        path.lineTo(100,100);
        canvas.drawPath(path,mPaint);

        mPaint.setStrokeJoin(Paint.Join.MITER);            //折弯处表现为MITER
        path.reset();
        path.moveTo(-100,-400);
        path.lineTo(100,-400);
        path.lineTo(-100,-200);
        path.lineTo(100,-200);
        canvas.drawPath(path,mPaint);

        mPaint.setStrokeJoin(Paint.Join.ROUND);            //折弯处表现为ROUND
        path.reset();
        path.moveTo(-100,200);
        path.lineTo(100,200);
        path.lineTo(-100,400);
        path.lineTo(100,400);
        canvas.drawPath(path,mPaint);

        mPaint.setColor(Color.BLACK);
        mPaint.setStrokeWidth(3);
        canvas.drawLine(-100,-getHeight()/2,-100,getHeight()/2,mPaint);
        canvas.drawLine(100,-getHeight()/2,100,getHeight()/2,mPaint);
    }

效果图

效果一眼就全知道了,不多说了,至于不明白Path的使用的同学,可以看我的文章---->   自定义View之Path的使用

 在这里,首先恭喜你,关于线段和几何图形的内部枚举类,你已经学习完了,现在我们来看文字的内部枚举类吧,总共有三个,但我们只要说两个,还有个无非就是精度上的差别~小意思嘛~

一个简单,一个有点难度,那让我们先来看简单的

Align

学过html的你一下子就知道什么意思了吧,文字对齐方式嘛~这里就不给源码了,总共三个left,right和center

    private void initControl() {
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setColor(Color.RED);
        mPaint.setTextAlign(Paint.Align.CENTER);                        //居中
        mPaint.setTextSize(30);                                         //设置字体大小
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.translate(getWidth()/2,getHeight()/2);
        canvas.drawText("我是一个热爱学习的好孩子",0,0,mPaint);

        mPaint.setTextAlign(Paint.Align.LEFT);                           //靠左对齐
        canvas.drawText("我是一个热爱学习的好孩子",0,-300,mPaint);

        mPaint.setTextAlign(Paint.Align.RIGHT);                          //靠右对齐
        canvas.drawText("我是一个热爱学习的好孩子",0,300,mPaint);

        mPaint.setColor(Color.BLACK);                                    //下面是辅助线
        canvas.drawLine(0,-getHeight()/2,0,getHeight()/2,mPaint);
        canvas.drawLine(-getWidth()/2,0,getWidth()/2,0,mPaint);
        canvas.drawLine(-getWidth()/2,-300,getWidth()/2,-300,mPaint);
        canvas.drawLine(-getWidth()/2,300,getWidth()/2,300,mPaint);
    }

 效果图

效果很明显,咦~你为什么要画辅助线呀,这个辅助线有意思吗,你不是在浪费时间吗?不,不是的,我是想引出下一个要将的FontMatrics的用法,你有没有发现虽然文字在水平的方向是对齐的,但是文字在垂直方向上,始终画在我的辅助线的上方,细心的你发现了吗?那么你就说了,既然水平方向有这样的方法,那垂直方向就肯定有咯,在这里我很遗憾的告诉你,并没有这样的方法,那怎么做呢?不要急嘛,马上就手把手教会你.

 FontMatrics

首先来看下源码的注释,凑合着还能翻译一下

    /**
     * Class that describes the various metrics for a font at a given text size.
     * Remember, Y values increase going down, so those values will be positive,
     * and values that measure distances going up will be negative. This class
     * is returned by getFontMetrics().
     */
    public static class FontMetrics {
        /**
         * The maximum distance above the baseline for the tallest glyph in
         * the font at a given text size.
         */
        public float   top;
        /**
         * The recommended distance above the baseline for singled spaced text.
         */
        public float   ascent;
        /**
         * The recommended distance below the baseline for singled spaced text.
         */
        public float   descent;
        /**
         * The maximum distance below the baseline for the lowest glyph in
         * the font at a given text size.
         */
        public float   bottom;
        /**
         * The recommended additional space to add between lines of text.
         */
        public float   leading;
    }

FontMetrics这个类是用来记录已经给出的字体的矩阵的.你要记住,在y轴往下y值会增加,移动的话就是正数,往上,y值会减小,也就是说移动的话这个数是负数,和数学上的相反,比如y-5表示想上移动5,y+5表示向下移5.

top : 在基线以上的最大距离,为什么说会有最大距离呢,你要知道,世界上有n多种文字,每种文字的高度和书写格式是不一样的,所以会存在最大值

ascent : 建议的在基线之上的距离,为负数(英文为上坡的意思),我觉得就是实际的文字在基线之上的距离

descent : 建议的在基线之下的距离,为正数(英文为下坡的意思),我觉得就是实际的文字在基线之下的距离

特别记忆法 : 上坡y值跟数学相反,减小为负,下坡则相反,so easy~~~

bottom : 在基线之下最大的距离,原因类似于top

leading : 这个就简单了,行间距

其实啊,我们的drawText方法是根据基线来写的文字,那么这个基线(baseLine)又是什么呢?现在我告诉你一个公式:

baseLine = 文本中线 - descent ; 我们如果要让文字看上去居中,就必须要算出baseLine的位置才行.

我使用的记忆方法是把画布移动中间,然后以中心点为原点,就中间有个x轴和y轴,(0,0)就好考虑,先算出基于原点的baseLine,然后进行移动不就完事了,不然计算太麻烦了,如果你的数学好,那可以,不然我觉得我的这个方法记忆比较好~

 首先我们来画一个图来更好的理解这几个参数的意思,leading就不说了,word中就有,自己去尝试一下吧~来吧,激动人心的时刻~

    private void initControl() {
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setColor(Color.RED);
        mPaint.setTextAlign(Paint.Align.CENTER);
        mPaint.setTextSize(100);
        mPaint.setStrokeWidth(2);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.translate(getWidth() / 2, getHeight() / 2);
        String text = "xyz";
        Paint.FontMetrics fontMetrics = mPaint.getFontMetrics();
        mPaint.setColor(Color.BLACK);
        canvas.drawLine(-getWidth() / 2,                  //画top线
                fontMetrics.top,
                getWidth() / 2,
                fontMetrics.top, mPaint);

        mPaint.setColor(Color.RED);
        canvas.drawLine(-getWidth() / 2,                  //画ascent线
                fontMetrics.ascent,
                getWidth() / 2,
                fontMetrics.ascent, mPaint);

        mPaint.setColor(Color.parseColor("#00ff00"));
        canvas.drawLine(-getWidth() / 2,                  //画基线
                0,
                getWidth() / 2,
                0, mPaint);

        mPaint.setColor(Color.parseColor("#f89e6f"));
        canvas.drawLine(-getWidth() / 2,                   //画descent线
                fontMetrics.descent,
                getWidth() / 2,
                fontMetrics.descent, mPaint);

        mPaint.setColor(Color.RED);
        canvas.drawLine(-getWidth() / 2,                    //画bottom线
                fontMetrics.bottom,
                getWidth() / 2,
                fontMetrics.bottom, mPaint);

        canvas.drawText(text, 0, 0, mPaint);

    }

效果图

 其实,我们是不需要关注这么多线的,我们要知道它是怎么绘制的,重点在于三根线,我们并不需要很关注最大的top和bottom

baseLine : 基线,也就是你在drawText的时候写入的坐标

ascent(在基线之上的距离) 还有 descent(在基线之下的距离) ,这两个我就在图中表示出来,如下:

 图上就已经表明的很清楚,"{"就是指ascent和baseLine的距离,"}"就是指baseLine和descent之间的距离,可以用绝对值表示

那么问题来了,说来说去,知道这些有什么用呢?这个问题好,加下来我们可以用上面学到的知识来写字写在垂直据中的位置上,come on~

Step 1 : 既然要画在中间,就需要知道中线,文字的中线计算出baseLine的距离,我这里是相对于原点计算的,其他的话只要一动一下就可以了,很方便~原先的中线要一动到baseline的位置才能居中显示

Step 2 : 根据baseLine来drawText,直接上代码和效果图

公式: 移动的距离 = 中线(这里不能像其他博客所说的中线,而是text文本的高度的一半) - descent(这个是正数)

多打几遍你就知道了.

先来看代码,我会给出辅助线对比居中和不居中的形式:

    private void initControl() {
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setColor(Color.RED);
        mPaint.setTextAlign(Paint.Align.CENTER);
        mPaint.setTextSize(100);
        mPaint.setStrokeWidth(2);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.translate(getWidth() / 2, getHeight() / 2);               //移动画布
        String text = "abp";                                             //要写的内容
        Paint.FontMetrics fontMetrics = mPaint.getFontMetrics();         //获取FontMetrics

        Rect rect = new Rect();                             //用来测量文本框大小,计算高度一半
        mPaint.getTextBounds(text, 0, text.length(), rect);              //获取文字矩形框大小

        int baseX = -200;                                                //baseLine坐标
        int baseY = 0;
        int textHeight = rect.height();                                  //获取文字高度
        canvas.drawText(text, baseX, baseY, mPaint);                     //写字,没有居中的
        int moveDistance = (int) (textHeight / 2 - fontMetrics.descent); //计算中线下移距离
        canvas.drawText(text, -baseX, baseY + moveDistance, mPaint);     //写字居中

        mPaint.setColor(Color.BLACK);                                    //辅助线
        canvas.drawLine(-getWidth() / 2, 0, getWidth() / 2, 0, mPaint);

    }

效果图

额额,写到上面,我保存了草稿,然后之后回来看,突然发现好像没有讲的很清楚,于是盯着上面这图看了半天,还是不知道怎么解释,突然我把英文字母写在了本子上,也不知道怎么,盯着看了半小时之后,突然怎么想的,我想到了小时候练英文字符的本子,然后豁然开朗.看到这里的你是否也有一种朦胧的感觉,没有看懂?半知半解?没关系,下面一张图保管你明白~

 小时候写英文字母的格子总知道吧,就是这样子的,假设他们的行间距都是一样的,注意最上面的那条不是ascent,不信你可以用ascent - descent来算一算是不是和rect.height()一样,很遗憾的告诉你不是的,很明显,我们需要把center下移到baseLine的地方就可以了,那么一看就知道,需要下移的距离公式   distance = text的高度(rect.height()) - descent ,生活处处有惊喜,哈哈哈,至少我解决了这个问题是很开心的!现在彻底明白了是怎么回事了吧,这里我试了一下descent和bottom几乎都是重合的,有时间再回头好好研究一下!

到此为止,Paint的几个内部枚举类就还剩下一个FontMatricsInt,只是精度上和FontMatrics有区别,别的没有大的区别,好了~本篇博客的内容你已经学的差不多了,最后说一些方法,我觉得最重要的都在上面了.

api中Paint的一些方法归类讲解

第1组:字体的测量方法

public float measureText(char[] text, int index, int count)
public float measureText(String text, int start, int end)
public float measureText(String text)
public float measureText(CharSequence text, int start, int end)

用来测量字体的宽度,都是重载的方法,三个参数的无非就是让你选择测量的字符格式而已,没有后两个参数的就是全部测量

public int breakText(char[] text, int index, int count,
                                float maxWidth, float[] measuredWidth)
public int breakText(CharSequence text, int start, int end,
                         boolean measureForwards,
                         float maxWidth, float[] measuredWidth)
public int breakText(String text, boolean measureForwards,
                                float maxWidth, float[] measuredWidth)

从名字就可以看出来,这是一个break(阻断)测量的方法,给出一个字符串,可选择测量字符串的长度,measureForward参数的意思就是是否向前测量,测量的结果保存在float数组中,如果超过设置的maxWidth,就不再进行测量,很简单~自己去尝试吧~

public int getTextWidths(char[] text, int index, int count,
                             float[] widths)
public int getTextWidths(CharSequence text, int start, int end,
                             float[] widths)
public int getTextWidths(String text, int start, int end, float[] widths)
public int getTextWidths(String text, float[] widths)

获取文本的宽度,,测量的结果保存在float数组中,也就是最后一个参数中,看参数名也就全知道了,很简洁

这里你会发现measureText好像也是测量字体的宽度,再打印出来看一下,measureText的值总是比getTextWidth要大

这是因为measureText是没有显示之前原始的View的大小,getTextWidths是显示出来后调用的,所以前者总是比后者大,不是其他博客所说的精确测量和非精确测量!在api中也说了getTextWidths是获取当前的text的宽度,也就是显示的,不是原本的View(或者说rect的宽度),懂了吗?(记忆,要有原本的显示的框才能显示呀,预留给它的空间总要比实际使用的大一些才行吧,哈哈~)

public void getTextPath(char[] text, int index, int count,
                            float x, float y, Path path)
public void getTextPath(String text, int start, int end,
                            float x, float y, Path path)

这个就是把你文字绘制的路径保存到最后一个参数Path中,一般都传入空,上面的float数组也是传入空的就可以

public void getTextBounds(String text, int start, int end, Rect bounds)
public void getTextBounds(CharSequence text, int start, int end, Rect bounds)
public void getTextBounds(char[] text, int index, int count, Rect bounds)

获取text(文本)的大小,text其实也是在一个Rect中绘制的,如果你对Rect不熟悉,可以看我写的文章,这里就不多说了.也是传入空的Rect对象.就能获取到文本框的大小,在使用Canvas画图画和写字的时候很有用,需要计算的,可以看我写的自定义View之Canvas的使用,在里面我画的自定义时钟就用到了,虽然我故意把它写了几个字上去,但是锻炼是很好的~

第2组

set(Paint src)和reset()

1.set() 把参数Paint中的画笔属性传给调用的Paint

2.reset() 重置画笔属性

第3组

setXXX方法,想简单的一眼就能看明白的(setARGB,setAlpha)这种的我就不多说了,浪费篇幅

1.setAntiAlias(boolean aa)     设置抗锯齿,以上说过了,不多介绍

2.setColorFilter(ColorFilter filter)   设置颜色过滤器,然后我也不知道他是怎么用,应该也不会经常用到~

3.setDither(boolean dither)   设置图像是否抖动,自己百度了解一下

4.setFlags(int flags)     设置flags,其实就是跟new Paint参入构造器中的flags是一个道理的

5.setShadowLayer(float radius, float dx, float dy, int shadowColor)  设置阴影

radius是阴影角度,dx为阴影x轴移动距离,dy为阴影y轴移动距离,shadowColor是阴影颜色

下面来看一下效果

    private void initControl() {
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setColor(Color.RED);
        mPaint.setTextAlign(Paint.Align.CENTER);
        mPaint.setTextSize(80);
        mPaint.setStrokeWidth(2);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.translate(getWidth() / 2, getHeight() / 2);
        String text = "abp";
        canvas.drawText(text,0,-200,mPaint);
        mPaint.setShadowLayer(10,5,5,R.color.colorAccent);
        canvas.drawText(text,0,200,mPaint);
    }

效果图

怎么样,是不是下面的abp看起来有一种立体的感觉,就是这么神奇~android真好玩~

6.setStrikeThruText(boolean strikeThruText)    设置删除线,在构造函数中也可传入对应的flags

7.setTextLocale(Locale locale)     设置text文本的当地语言

8.setTextScaleX(float scaleX) , setTextSkewX(float skewX)  设置text的缩放和错切变换(倾斜)

9.setTypeface(Typeface typeface)   设置字体样式,在TypeFace中有常量来描述,这里就不说了,自己去看

10.setXfermode(Xfermode xfermode)  设置重叠时候的样式,在里面输入Mode类中有18个,自己一一去尝试吧,给点挑战,我就不示范了.

最后两组

这两组就是isXXX和getXXX,这里我就不多说了,都很简单,判断true还是false,get到一些东西,和setXXX基本都是对应的,自行查看api就能搞懂了~

最后,感谢大家的观看,谢谢大家,请期待我的下一篇文章,如有意见,欢迎来稿1012351395@qq.com,新手写博客,希望大家多多给评论,多多给我提意见,我会改进,好好写博客,分享技术给每一个需要的人,我们都是能成大事的人~再见啦~

 


版权声明:本文为weixin_42352543原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。