Android_2D绘图的学习Paint,Canvas(2)

Android_2D绘图的学习Paint,Canvas(二)

前言

上一节,学会了Paint,Canvas的基本用法后,这一节,学习Paint的高级用法。还没看过上一节的请点击这里:Android_2D绘图的学习Paint,Canvas(一)。

一,文字的绘制

在做UI的时候,常常会绘制文字,Canvas绘制文字时,主要考虑到字体的宽度和高度问题。字体的宽度比较好理解,这里我们主要考虑一下字体的高度。
先看一张图,网上搜的:
Android_2D绘图的学习Paint,Canvas(2)
这里说明了在安卓中绘制字体时对于高度的划分:top,ascent,baseLine,descent,bottom.有点类似我们刚开始学英语的时候的练习本。字体的高度我们取得是ascent到descent的距离。经过我测试,系统自带的TextView中,绘制的背景高度为top到bottom的距离。字体的起始坐标点默认是baseLine中最左边的一个点,可以通过调用Paint.setTextAlign(Paint.Align align)方法设置中间还是最右边。
我们先来绘制一个正确的文字居中的一个效果:
Android_2D绘图的学习Paint,Canvas(2)
代码:

    private Paint mPaint;
    private String mText = "Android Paint学习";

    public PaintView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        mPaint = new Paint();
        mPaint.setColor(Color.BLACK);
        mPaint.setTextSize(TypedValue.applyDimension(
                TypedValue.COMPLEX_UNIT_SP, 20, getResources()
                        .getDisplayMetrics()));
    }
    public PaintView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
        // TODO Auto-generated constructor stub
    }

    public PaintView(Context context) {
        this(context, null);
        // TODO Auto-generated constructor stub
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        //得到文字宽度
        int textWidth = (int) mPaint.measureText(mText);
        //得到文字高度
        int textHeight = (int) (mPaint.descent() - mPaint.ascent());
        // 设置View的高度和宽度为字体的高度和宽度
        widthMeasureSpec = MeasureSpec.makeMeasureSpec(textWidth,
                MeasureSpec.EXACTLY);
        heightMeasureSpec = MeasureSpec.makeMeasureSpec(textHeight,
                MeasureSpec.EXACTLY);
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        //这里减去了一个descent主要是画笔画文字的基准线为baseLine,如果不剪,就会出现底部有一部分看不到的情况
        canvas.drawText(mText, 0, getHeight() - mPaint.descent(), mPaint);
    }

明显可以看出系统的TextView要高一点。注意top和ascent的值都是负值,所以在获取高度时,是减去ascent。如果要像TextView一样的高度的方法代码:

FontMetrics fm = mPaint.getFontMetrics();
int textHeight = (int) (fm.descent - fm.top+2);

因为Paint没有top()这个方法所以我们用FontMetrics中的top属性。
这里参考了一篇博文:Android字体高度的研究讲的很详细的。

二,Paint.Cap

The Cap specifies the treatment for the beginning and ending of stroked lines and paths. The default is BUTT.

cap是帽子,覆盖的意思,在画笔中,就是指定边缘点(画笔第一点,和画笔最后一点)的样式。
一共有3种样式:BUTT,ROUND,SQUARE.
我都以画一段圆弧来说明,效果:
Android_2D绘图的学习Paint,Canvas(2)
从左至右分别是:SQUARE,ROUND,BUTT一看图,就了然了。
代码:

        mPaint.setColor(Color.RED);
        mPaint.setStrokeWidth(2);
        canvas.drawLine(0, 50, getWidth(), 50, mPaint);

        mPaint.setStrokeWidth(30);
        mPaint.setStyle(Style.STROKE);
        mPaint.setAntiAlias(true);
        mPaint.setColor(Color.BLACK);

        mPaint.setStrokeCap(Cap.BUTT);
        canvas.drawArc(new RectF(-getWidth() + 150, -getHeight() + 150,
                getWidth() - 50, getHeight() - 50), 0, 50, false, mPaint);

        mPaint.setStrokeCap(Cap.ROUND);
        canvas.drawArc(new RectF(-getWidth() + 100, -getHeight() + 150,
                getWidth() - 100, getHeight() - 50), 0, 50, false, mPaint);

        mPaint.setStrokeCap(Cap.SQUARE);
        canvas.drawArc(new RectF(-getWidth() + 50, -getHeight() + 150,
                getWidth() - 150, getHeight() - 50), 0, 50, false, mPaint);

三,Paint.join

The Join specifies the treatment where lines and curve segments join on a stroked path. The default is MITER.
摘自官方文档,就是说路径在转弯的时候指定其样式。
一共有3种样式:MITER,ROUND,BEVEL。
效果:
Android_2D绘图的学习Paint,Canvas(2)
从左至右分别是:MITER,ROUND,BEVEL。
代码:

        mPaint.setStrokeWidth(40);
        mPaint.setStyle(Style.STROKE);
        mPaint.setStrokeJoin(Join.MITER);
        Path path = new Path();
        path.moveTo(0, 30);
        path.lineTo(100, 30);
        path.lineTo(100, 100);
        canvas.drawPath(path, mPaint);

        mPaint.setStrokeJoin(Join.ROUND);
        Path path1 = new Path();
        path1.moveTo(200, 30);
        path1.lineTo(300, 30);
        path1.lineTo(300, 100);
        canvas.drawPath(path1, mPaint);

        mPaint.setStrokeJoin(Join.BEVEL);
        Path path2 = new Path();
        path2.moveTo(400, 30);
        path2.lineTo(500, 30);
        path2.lineTo(500, 100);
        canvas.drawPath(path2, mPaint);

四,Paint.FontMetrics

调用Paint.getFontMetrics()会返回一个FontMetrics对象,调用前记得先设置字体大小,该对象有5个属性,分别是:top,ascent,descent,bottom,leading(行间距).注意前2个的值为负。