Android 自定义 View 高级 - Canvas 之图片文字

3,135 阅读6分钟
原文链接: blog.csdn.net

一.Canvas的常用操作速查表

操作类型 相关API 备注
绘制颜色 drawColor, drawRGB, drawARGB 使用单一颜色填充整个画布
绘制基本形状 drawPoint, drawPoints, drawLine, drawLines, drawRect, drawRoundRect, drawOval, drawCircle, drawArc 依次为 点、线、矩形、圆角矩形、椭圆、圆、圆弧
绘制图片 drawBitmap, drawPicture 绘制位图和图片
绘制文本 drawText, drawPosText, drawTextOnPath 依次为 绘制文字、绘制文字时指定每个文字位置、根据路径绘制文字
绘制路径 drawPath 绘制路径,绘制贝塞尔曲线时也需要用到该函数
顶点操作 drawVertices, drawBitmapMesh 通过对顶点操作可以使图像形变,drawVertices直接对画布作用、 drawBitmapMesh只对绘制的Bitmap作用
画布剪裁 clipPath, clipRect 设置画布的显示区域
画布快照 save, restore, saveLayerXxx, restoreToCount, getSaveCount 依次为 保存当前状态、 回滚到上一次保存的状态、 保存图层状态、 回滚到指定状态、 获取保存次数
画布变换 translate, scale, rotate, skew 依次为 位移、缩放、 旋转、错切
Matrix(矩阵) getMatrix, setMatrix, concat 实际上画布的位移,缩放等操作的都是图像矩阵Matrix, 只不过Matrix比较难以理解和使用,故封装了一些常用的方法。

二.Canvas基本操作详解

1.绘制图片

绘制有两种方法,drawPicture(矢量图) 和 drawBitmap(位图)。

(1)drawPicture

使用Picture前请关闭硬件加速,以免引起不必要的问题!
在AndroidMenifest文件中application节点下添上 Android:hardwareAccelerated=”false”以关闭整个应用的硬件加速。 更多请参考这里:Android的硬件加速及可能导致的问题

PS:你可以把Picture看作是一个录制Canvas操作的录像机。

Picture的相关方法:

相关方法 简介
public int getWidth () 获取宽度
public int getHeight () 获取高度
public Canvas beginRecording (int width, int height) 开始录制 (返回一个Canvas,在Canvas中所有的绘制都会存储在Picture中)
public void endRecording () 结束录制
public void draw (Canvas canvas) 将Picture中内容绘制到Canvas中
 public CustomView(Context context, AttributeSet attrs)
    {
        super(context, attrs);
        // 调用录制
        recording();
    }
 private void recording()
    {
        // 开始录制
        Canvas canvas = mPicture.beginRecording(500, 500);
        // 创建一个画笔
        Paint paint = new Paint();
        paint.setColor(Color.RED);
        paint.setStyle(Paint.Style.FILL);
        // 在Canvas中具体操作
        canvas.translate(250,250);
        // 绘制一个圆
        canvas.drawCircle(0,0,100,paint);
        //结束录制
        mPicture.endRecording();
    }
   @Override
    protected void onDraw(Canvas canvas)
    {
        mPicture.draw(canvas);
     }

a.jpg

将Picture中的内容绘制出来可以有以下几种方法:

序号 简介
1 使用Picture提供的draw方法绘制
2 使用Canvas提供的drawPicture方法绘制
3 将Picture包装成为PictureDrawable,使用PictureDrawable的draw方法绘制

1.使用Picture提供的draw方法绘制:

 @Override
    protected void onDraw(Canvas canvas)
    {
        mPicture.draw(canvas);
     }

a.jpg
PS:这种方法在比较低版本的系统上绘制后可能会影响Canvas状态,所以这种方法一般不会使用。

2.使用Canvas提供的drawPicture方法绘制

drawPicture有三种方法:

public void drawPicture (Picture picture)

public void drawPicture (Picture picture, Rect dst)

public void drawPicture (Picture picture, RectF dst)

和使用Picture的draw方法不同,Canvas的drawPicture不会影响Canvas状态。


 @Override
    protected void onDraw(Canvas canvas)
    {
          canvas.drawPicture(mPicture,new RectF(0,0,mPicture.getWidth(),200));
     }

b.jpg

3.将Picture包装成为PictureDrawable,使用PictureDrawable的draw方法绘制。

   // 包装成为Drawable
   PictureDrawable drawable = new PictureDrawable(mPicture);
   // 设置绘制区域 -- 注意此处所绘制的实际内容不会缩放    
   drawable.setBounds(0,0,250,mPicture.getHeight());
   // 绘制
   drawable.draw(canvas);

c.jpg

(2)drawBitmap

获取Bitmap方式:

序号 获取方式 备注
1 通过Bitmap创建 复制一个已有的Bitmap(新Bitmap状态和原有的一致) 或者 创建一个空白的Bitmap(内容可改变)
2 通过BitmapDrawable获取 从资源文件 内存卡 网络等地方获取一张图片并转换为内容不可变的Bitmap
3 通过BitmapFactory获取 从资源文件 内存卡 网络等地方获取一张图片并转换为内容不可变的Bitmap

通过BitmapFactory从不同位置获取Bitmap:
资源文件(drawable/mipmap/ic_launcher):

Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(),R.mipmap.ic_launcher);

资源文件(assets):

Bitmap bitmap=null;
try {
    InputStream is = mContext.getAssets().open("bitmap.png");
    bitmap = BitmapFactory.decodeStream(is);
    is.close();
} catch (IOException e) {
    e.printStackTrace();
}

内存卡文件:

Bitmap bitmap = BitmapFactory.decodeFile("/sdcard/bitmap.png");

网络文件:

Bitmap bitmap = BitmapFactory.decodeStream(is);
is.close();

drawBitmap的常用方法:

// 第一种
public void drawBitmap (Bitmap bitmap, Matrix matrix, Paint paint)

// 第二种
public void drawBitmap (Bitmap bitmap, float left, float top, Paint paint)

// 第三种
public void drawBitmap (Bitmap bitmap, Rect src, Rect dst, Paint paint)
public void drawBitmap (Bitmap bitmap, Rect src, RectF dst, Paint paint)

第一种方法中后两个参数(matrix, paint)是在绘制的时候对图片进行一些改变,如果只是需要将图片内容绘制出来只需要如下操作就可以了:
图片左上角位置默认为坐标原点。

canvas.drawBitmap(bitmap,new Matrix(),new Paint());

d.jpg

第二种方法就是在绘制时指定了图片左上角的坐标(距离坐标原点的距离):

注意:此处指定的是与坐标原点的距离

canvas.drawBitmap(bitmap,300,300,new Paint());

e.jpg

第三种方法,上面多了两个矩形区域(src,dst),这两个矩形选区是干什么用的?

名称 作用
Rect src 指定绘制图片的区域
Rect dst 或RectF dst 指定图片在屏幕上显示(绘制)的区域

        // 将画布坐标系移动到画布中央
        canvas.translate(width/2,height/2);
        // 指定图片绘制区域(左上角的四分之一)
        Rect src = new Rect(0,0,bitmap.getWidth()/2,bitmap.getHeight()/2);
        // 指定图片在屏幕上显示的区域
        Rect dst = new Rect(0,0,200,200);
        // 绘制图片
        canvas.drawBitmap(bitmap,src,dst,null);

f.jpg

2.绘制文字


// 第一类
public void drawText (String text, float x, float y, Paint paint)
public void drawText (String text, int start, int end, float x, float y, Paint paint)
public void drawText (CharSequence text, int start, int end, float x, float y, Paint paint)
public void drawText (char[] text, int index, int count, float x, float y, Paint paint)

// 第二类
public void drawPosText (String text, float[] pos, Paint paint)
public void drawPosText (char[] text, int index, int count, float[] pos, Paint paint)

// 第三类
public void drawTextOnPath (String text, Path path, float hOffset, float vOffset, Paint paint)
public void drawTextOnPath (char[] text, int index, int count, Path path, float hOffset, float vOffset, Paint paint)

绘制文字部分大致可以分为三类:

第一类只能指定文本基线位置
第二类可以分别指定每个文字的位置。
第三类是指定一个路径,根据路径绘制文字。

Paint文本相关常用方法表

标题 相关方法 备注
色彩 setColor setARGB setAlpha 设置颜色,透明度
大小 setTextSize 设置文本字体大小
字体 setTypeface 设置或清除字体样式
样式 setStyle 填充(FILL),描边(STROKE),填充加描边(FILL_AND_STROKE)
对齐 setTextAlign 左对齐(LEFT),居中对齐(CENTER),右对齐(RIGHT)
测量 measureText 测量文本大小(注意,请在设置完文本各项参数后调用)

为了绘制文本,我们先创建一个文本画笔:

 private void initPaint()
 {
  // 创建画笔
  Paint textPaint = new Paint();   
  // 设置颜色
  textPaint.setColor(Color.BLACK);     
  // 设置样式
   textPaint.setStyle(Paint.Style.FILL);  
   textPaint.setTextSize(50);             

 }

第一类(drawText)


 // 文本(要绘制的内容)
 String str = "TEXTTEXT";
 // 参数分别为 (文本 基线x 基线y 画笔)
 canvas.drawText(str,230,600,textPaint);

g.jpg

  //参数分别为 (字符串 开始截取位置 结束截取位置 基线x 基线y 画笔)
  canvas.drawText(str,1,3,300,600,textPaint);

h.jpg

第二类(drawPosText)

可以给每一个字符指定位置(不推荐使用)


   String str = "TEXTTEXT";
   canvas.drawPosText(str,new float[]{
                100,100,    // 第一个字符位置
                150,200,    // 第二个字符位置
                200,300,    // ...
                250,400,
                300,500,
                350,600,
                400,700,
                450,800
        },textPaint);

i.jpg

参考文章

@GcsSloop:安卓自定义View进阶-Canvas之图片文字

源码下载

源码下载:https://github.com/zeke123/MyView