(六)Paint 绘画文字

版权声明:本文为博主原创文章,未经博主允许不得转载。

本文纯个人学习笔记,由于水平有限,难免有所出错,有发现的可以交流一下。

在绘画文字之前,先来看一下 Paint.FontMetrics 这个内部类

一.Paint.FontMetrics

  /**
     * 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;
    }

绘画文字中有几条重要的线 :top,ascent,baseline,desent, bottom 以及一条不被记录的文字中心线。

1.文字绘画都在 top 与 buttom 之间,这里面不包括 margin。
2.top 与 ascent 之间绘制字母的音标。
3.baseline 为字母的基线。
4.descent 与 buttom 之间正常不绘制东西。
5.文字中心线处于 top 与 buttom 中间。

这里写图片描述

Paint.FontMetricsInt 里面有 top,ascent,desent, bottom, leading 这几个属性。top,ascent,desent, bottom 这几个值分别表示对应线的 Y 坐标 - baseline 的 Y 坐标

二.圆形进度条 Demo

绘制文字时候很经常处理不好文字的绘制高度问题,要么偏高要么偏低,这边绘制一个圆形进度条,在圆中心绘制进度文字。

1.分析

这里写图片描述
1.该圆形进度条支持一系列自定义属性设置。
2.先绘制背后圆环。
3.绘制中间文字。
4.绘制进度。

2.创建自定义 View

在 attrs.xml 中定义自定义属性

   <declare-styleable name="CustomProgressBar">
        <!-- 进度圆圈背景颜色 -->
        <attr name="roundColor" format="color"></attr>
        <!-- 进度颜色 -->
        <attr name="roundProgressColor" format="color"></attr>
        <!-- 进度条宽度 -->
        <attr name="roundWidth" format="dimension"></attr>
        <!-- 进度最大值  -->
        <attr name="max" format="integer"></attr>
        <!-- 是否显示文字  -->
        <attr name="textShow" format="boolean"></attr>
        <!-- 中间文字大小 -->
        <attr name="textSize" format="dimension"></attr>
        <!-- 中间文字颜色  -->
        <attr name="textColor" format="color"></attr>
        
    </declare-styleable>

自定义 View 继承 View,这时候会要求重写 View 的构造函数。View 的构造函数中比较重要的两个是 。一般就用到这两个,其他比较少。

//供程序内部实例化时候用的
public View(Context context){...}
//用于layout文件实例化,会把XML内的参数通过AttributeSet带入到View内
public View(Context context, @Nullable AttributeSet attrs){...}

在这边,我们重写第二个构造函数。这个做过自定义的都懂,就不多讲。

    public CircleProgressBar(Context context, AttributeSet attrs) {
        super(context, attrs);

        paint = new Paint();
    
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CustomProgressBar);
        roundColor = typedArray.getColor(R.styleable.CustomProgressBar_roundColor, Color.RED);
        roundProgressColor = typedArray.getColor(R.styleable.CustomProgressBar_roundProgressColor, Color.GREEN);
        roundWidth = typedArray.getDimension(R.styleable.CustomProgressBar_roundWidth, 10);
        max = typedArray.getInt(R.styleable.CustomProgressBar_max, 100);
        textSize = typedArray.getDimension(R.styleable.CustomProgressBar_textSize, 12);
        textShow = typedArray.getBoolean(R.styleable.CustomProgressBar_textShow, true);
        textColor = typedArray.getColor(R.styleable.CustomProgressBar_textColor, Color.GREEN);

        typedArray.recycle();
    }

在最后要进行 typedArray.recycle():按官方说法是说:对 TypedArray 进行回收,以便再次试用。点进去可以发现就是释放资源,
TypedArray 要是每次都创建 array ,对系统来说是一笔不小的开销,所以创建的方法一直点进去会发现是一个简单地单例 + 使用池的模式,每次使用完要释放资源。

3.绘制背后圆环

        /*
         * 画背景圆环
         */
        //获取圆环半径
        float radius = (getWidth() - roundWidth) / 2;

        //设置抗锯齿
        paint.setAntiAlias(true);
        //设置画笔样式填充内部
        paint.setStyle(Paint.Style.STROKE);
        //设置颜色
        paint.setColor(roundColor);
        //设置圆环宽度
        paint.setStrokeWidth(roundWidth);
        //画进度条背后圆环
        canvas.drawCircle(getWidth() / 2, getWidth() / 2, radius, paint);

运行效果:
这里写图片描述

4.绘制中间文字

这里主要麻烦是在计算 baseline 的 Y 坐标。需要用文字中心线算出 buttom 的 Y 坐标,从而算出 baseline 的 Y 坐标。

        /*
         * 中间文字
         */
        if (textShow) {
            
            paint.setStrokeWidth(0);
            paint.setTextSize(textSize);
            paint.setColor(textColor);
            paint.setTypeface(Typeface.DEFAULT_BOLD);
            
            //计算百分比
            int percent = (int) ((float)progress / max * 100);
            //要显示的百分比字符串
            String strPercent = percent + "%";
            
            //获取 Paint.FontMetricsInt 对象
            Paint.FontMetricsInt fm = paint.getFontMetricsInt();
            //计算字符串起始的 X 坐标
            float strX = getWidth() / 2 - paint.measureText(strPercent) / 2;
            
            //计算字符串起始的  Y 坐标
            //中心线到 bottom 的距离  = (fm.bottom - fm.top) / 2
            //bottom 的 Y 坐标 = 中心线  + 中心线到 bottom 的距离
            //baseline 的 Y 坐标 = bottom 的 Y 坐标 - fm.bottom
            float strY = getWidth() / 2 + (fm.bottom - fm.top) / 2 - fm.bottom;
            
            //绘制文字
            //第二个参数是绘制起始的 x 坐标
            //第三个参数是 baseline 的 Y 坐标
            canvas.drawText(strPercent, strX, strY, paint);
            
        }

这里写图片描述

5.绘制进度

绘制进度的弧形

        /*
         * 进度
         */
        //设置抗锯齿
        paint.setAntiAlias(true);
        //设置画笔样式填充内部
        paint.setStyle(Paint.Style.STROKE);
        //设置颜色
        paint.setColor(roundProgressColor);
        //设置圆环宽度
        paint.setStrokeWidth(roundWidth);
        
        //传入圆形的左上右下四个边沿
        RectF oval = new RectF(getWidth() / 2 - radius, getWidth() / 2 - radius, 
                getWidth() / 2 + radius, getWidth() / 2 + radius);
        
        //画进度条弧形
        canvas.drawArc(oval, 0, 360 * progress / max, false, paint);

给自定义属性添加个设置进度方法,这样就可以在外部进行传值了。

    public void setProgress(int progress){
        if (progress < 0) {
            this.progress = 0;
        } else if (progress > max) {
            this.progress = max;
        } else {
            this.progress = progress;
        }
        
        postInvalidate();
    }

这里写图片描述

6.添加样式

  <com.xiaoyue.circleprogressbar.CircleProgressBar
        android:id="@+id/progressbar"
        android:layout_width="100dip"
        android:layout_height="100dip"
        app:roundProgressColor="#ff00ff"
        app:textColor="#666666"
        app:textSize="20dp"
        app:roundWidth="15dp"
        />

这里写图片描述

三、附

代码链接:http://download.csdn.net/detail/qq_18983205/9852164

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值