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

前言

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

一,文字的绘制

在做UI的时候,常常会绘制文字,Canvas绘制文字时,主要考虑到字体的宽度和高度问题。字体的宽度比较好理解,这里我们主要考虑一下字体的高度。

先看一张图,网上搜的:

这里说明了在安卓中绘制字体时对于高度的划分:top,ascent,baseLine,descent,bottom.有点类似我们刚开始学英语的时候的练习本。字体的高度我们取得是ascent到descent的距离。经过我测试,系统自带的TextView中,绘制的背景高度为top到bottom的距离。字体的起始坐标点默认是baseLine中最左边的一个点,可以通过调用Paint.setTextAlign(Paint.Align align)方法设置中间还是最右边。

我们先来绘制一个正确的文字居中的一个效果:

代码:

    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.

我都以画一段圆弧来说明,效果:

从左至右分别是: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。

效果:

从左至右分别是: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个的值为负。

时间: 2024-10-10 00:04:07

Android_2D绘图的学习Paint,Canvas(二)的相关文章

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

前言 上一节,学习了Paint的高级用法后,这一节我们将canvas的用法.主要涉及到canvas的绘制坐标变换translate,rotate.还没看过上一节的请点击这里:Android_2D绘图的学习Paint,Canvas(二). 一,translate translate在很多语言的图像处理中都存在,意思是平移,在canvas中,他表示平移坐标原点.比如说,你要在一个View的中心点画一个半径为r圆.你可以这样直接画:canvas.drawCircle(getWidth()/2,getH

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

前言 安卓2D绘图,都是主要涉及到2个类:Paint,Canvas. 一,Paint Paint画笔,用于指定图形或者文字的颜色,大小等. 常用方法: setAntiAlias: 设置画笔的锯齿效果. setColor: 设置画笔颜色 setAlpha: 设置Alpha值 setTextSize: 设置字体尺寸. setStyle: 设置画笔风格,空心或者实心. setStrokeWidth: 设置空心的边框宽度. 1,HelloWorld 先从经典的helloworld开始,我们画出一个蓝色,

自定义View时,用到Paint Canvas的一些温故,讲讲平时一些效果是怎么画的(基础篇 二,图像遮盖,Canvas静态变化)

转载请注明出处:王亟亟的大牛之路 上一篇把简单的一些概念理一理,还画了个圈,那这一篇讲一下图像遮盖"Xfermode"和Canvas的旋转.平移等效果 Xfermode: AvoidXfermode 指定了一个颜色和容差,强制Paint避免在它上面绘图(或者只在它上面绘图). PixelXorXfermode 当覆盖已有的颜色时,应用一个简单的像素异或操作. PorterDuffXfermode 这是一个非常强大的转换模式,使用它,可以使用图像合成的16条Porter-Duff规则的任

Android Path, Region, Paint, Canvas API篇

从这篇文章开始,准备学习Android Canvas相关的一些知识点,因为Canvas使用的时候还经常要用到Path,Region,Paint.所以这里我们先熟悉Path,Region,Paint,Canvas常用的一些API,为后续的学习做好准备. 在列出Path,Region,Paint,Canvas这些API之前先展示一个具体的实例.一个仪表盘.主要用到的是Canvas的API,和一些三角函数的运算.具体效果图如下 仪表盘分成了三段(2:1:2),每一段显示不同的颜色.刻度分成8大份每小份

Numpy学习笔记(二)

最近一直在学HTML5和CSS3,Numpy的东西都有些生疏,那本书是已经看完了的,紧跟着相关的代码也都敲了一遍,还是发现了一些问题,因为这样的学习方式,总感觉太被动,紧紧跟着示例代码,缺少了整体观,即使你现在问我Numpy可以处理什么问题,我还是回答不出.所以,有必要回头重来一遍,再一次审视代码背后的意义,写博客真的是一个很不错的方式,毕竟,如果你不懂,写出来的文字必然也是混乱的. 那,下面记录一下Numpy学习笔记(二) Example1 文件读写:数据不应该仅仅存在内存里,应该及时保存在硬

【猪猪-前端】微信打飞机高质量Demo,学习HTML5+Canvas技术编写,下载即可使用,注释齐全。

原文:[猪猪-前端]微信打飞机高质量Demo,学习HTML5+Canvas技术编写,下载即可使用,注释齐全. 源代码下载地址:http://www.zuidaima.com/share/1553027668610048.htm //获取绘图环境 02 var canvas=document.getElementById('canvas'); 03 var context=canvas.getContext('2d'); 04   05   06 //创建对象集合 (集合所有精灵) 07 var 

学习HTML5 canvas遇到的问题

学习HTML5 canvas遇到的问题 1. 非零环绕原则(nonzZero rule) 非零环绕原则是canvas在进行填充的时候是否要进行填充的判断依据. 在判断填充的区域拉一条线出来,拉到图形的外面,这条拉出来的线就是辅助线.判断绘制的线是否是从辅助线的左边穿过到辅助线的右边,此时这种穿过的方式记录为+1;如果是从辅助线的右边穿到辅助线的左边,就记做-1.最后将所有记录的数字进行求和,如果求和的结果为0,代表这块区域不要填充,否则,必须填充 上面的原理较难理解,可以这样理解,当在大矩形中绘

转载《学习HTML5 canvas遇到的问题》

学习HTML5 canvas遇到的问题 1. 非零环绕原则(nonzZero rule) 非零环绕原则是canvas在进行填充的时候是否要进行填充的判断依据. 在判断填充的区域拉一条线出来,拉到图形的外面,这条拉出来的线就是辅助线.判断绘制的线是否是从辅助线的左边穿过到辅助线的右边,此时这种穿过的方式记录为+1;如果是从辅助线的右边穿到辅助线的左边,就记做-1.最后将所有记录的数字进行求和,如果求和的结果为0,代表这块区域不要填充,否则,必须填充 上面的原理较难理解,可以这样理解,当在大矩形中绘

WPF路由事件学习转(二)

在传统的.net中已经有了事件机制了,为什么在WPF中要加入路由事件来取代事件呢,最直观的原因就是典型的WPF应用程序使用很多元素关联和组合起来,从而有了两个概念,LogicalTree 和 VisualTree,那么它们分别是什么呢,举个例子: 这就是LogicalTree,一个Grid里面镶嵌了其他控件或布局组件,这相当于一棵树中的叶子.而VisualTree呢?它就是一个树中的叶子里面的结构,用放大镜看一下,其实叶子里面的结构也是一颗树结构,这就是VisualTree了,例如 好了,既然W