自定义View(五)Canvas 绘制图片 文字

绘制图片

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

drawPicture

picture:翻译过来就是图片的意思。但是在这里你可以将它理解成录像机一样的功能。因为它是将一系列绘制操作记录下来,保存成一个对象,在你想绘制的时候,拿着这个对象进行一些操作就可以讲之前保存的操作绘制出来。
也可以理解成将一系列的绘制操作,绘制到一张图片上,当你想要讲这张图片展示的时候,可以随便复制,展示。
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 static Picture createFromStream (InputStream stream) (已废弃)通过输入流创建一个Picture
public void writeToStream (OutputStream stream) (已废弃)将Picture中内容写出到输出流中

上边的方法解释的很清楚,主要流程:

  • 先实例化一个picture对象;
  • 再调用beginRecording(int width,int height)方法得到canvas,设定绘制区域,获得画板,开始绘制操作;
  • 使用canvas对象进行具体操作;
  • 绘制完成,调用endRecording();结束绘制。这个时候所有绘制的操作都保存在picture对象里边。
  • 在想要调用这些绘制的时候,使用picture的draw(Canvas canvas)方法进行展示。

具体看代码:

        //先实例化picture对象
        Picture mPicture = new Picture();
        ...
       private void recording() {
          Canvas canvas = mPicture.beginRecording(500, 500);
          canvas.translate(250, 250);
          canvas.drawCircle(0, 0, 100, paint);
          canvas.rotate(90);
          mPicture.endRecording();
        }
        ...

       private void initView() {
          //在view初始化的时候调用录制
          recording();
      }

上边的操作只是录制操作,录制的内容不会自动展示到手机上,就像录制的视频不点击播放也不会自己自定播放一样,只是在存储可中存着一样。所以我们需要手动调用这些录制的操作。下边有三种方法可以将录制的内容展示出来。

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

上边三种方法不建议使用第一种,后边两种根据具体需求使用。
下边介绍一下三种方法的用法:

第一种绘制方法:使用Picture提供的draw方法绘制

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        mPicture.draw(canvas);
    }
使用Picture提供的draw方法绘制

第二种绘制方法:使用Canvas提供的drawPicture方法绘制

drawPicture(Picture picture);
drawPicture(Picture picture,Rect rect);
drawPicture(Picture picture,RectF rectf);

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawPicture(mPicture,new Rect(0,0,300,400));
    }
使用canvas的drawPicture方法绘制

后边两种重载方法是指定绘制的区域,在指定区域中调用之前录制的绘制图片,如果指定区域尺寸比之前绘制的图片小的话,会等比例缩小;如果指定区域尺寸比之前绘制的图片大的话,会等比例放大。

第三种绘制方法:将Picture包装成为PictureDrawable,使用PictureDrawable的draw方法绘制

   @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
         PictureDrawable pictureDrawable = new PictureDrawable(mPicture);
        //设置绘制区域,此处绘制的实际内容不会缩放   如果不设置这个绘制区域,将不会进行绘制。默认绘制区域为0
        pictureDrawable.setBounds(0, 0, 300, 300);
        pictureDrawable.draw(canvas);
    }
将Picture包装成PoctureDrawable,使用PictureDrawable的draw方法绘制

这里setBounds()设置的绘制区域,与上边一种方法不同。不会根据区域缩放picture,而是每次都会左上角点开始绘制,绘制整个区域的大小。相当于在电视上覆盖一个区域,只能看到这个区域中的图像,图像被没有被剪裁,也没有缩放。

注意:在使用Picture之前请关闭硬件加速,以免引起不必要的问题

drawBitmap

Bitmap是一个图片的对象,这里的图片是真正的图片,不是录制之类的东西。
bitmap是一系列像素点的数据,是一张图片的数据载体。
drawBitmap();是canvas里边的方法,作用就是绘制图片,比如你的自拍,等等。

// 第一种 这种方法在绘制的时候很根据matrix和paint对图片进行一些改变,如果只是简单的绘制下来,后边两个参数直接使用简单的对象就行
public void drawBitmap (Bitmap bitmap, Matrix matrix, Paint paint)

// 第二种  这种方法后边两个参数的作用就是指定图片绘制的位置距离原点的距离
public void drawBitmap (Bitmap bitmap, float left, float top, Paint paint)

// 第三种  src表示图片的区域    dst表示在屏幕上绘制的区域
public void drawBitmap (Bitmap bitmap, Rect src, Rect dst, Paint paint)
public void drawBitmap (Bitmap bitmap, Rect src, RectF dst, Paint paint)

第一种:drawBitmap (bitmap, matrix, paint)

简单绘制,没有对里边的Matrix和Paint 进行操作。

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

图片的左上角默认为左边原点


drawBitmap (bitmap, matrix, paint)

第二种:drawBitmap(bitmap,left,top,paint)

canvas.drawBitmap(mBitmap, 200,300, new Paint());

这里边的距离是距坐标原点的距离


drawBitmap(bitmap,left,top,paint)

第三种:drawBitmap ( bitmap, src, dst, paint)

名称 作用
Rect src 指定绘制图片的区域
Rect dst 或RectF dst 指定图片在屏幕上显示(绘制)的区域
// 指定图片绘制区域(左上角的四分之一)
Rect src = new Rect(0,0,bitmap.getWidth()/2,bitmap.getHeight()/2);

// 指定图片在屏幕上显示的区域
Rect dst = new Rect(0,0,200,400);

// 绘制图片
canvas.drawBitmap(bitmap,src,dst,null);
drawBitmap ( bitmap, src, dst, paint)

上边代码里边的src其实是这张卡通图片的左上角的1/4;dst是屏幕上的一块区域,大概长200,宽400。
我们看到绘制出来的效果确实只有原来图片的一部分,可是有点缩放了。这是因为图片1/4的区域比dst要大,但是还要将这src绘制到dst内部,就要进行缩放了。

src: 指定要绘制的图片的区域

图片的区域

dst:屏幕绘制区域

屏幕绘制区域

这种方法还可以进行一些炫酷动画效果的制作,也就是依次绘制一张图片的不同位置。具体操作参照:安卓自定义View进阶-Canvas之图片文字

文字绘制

绘制文字的几种方法:

// 第一类
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)

这里只讲第一种,第二种不经常使用,看一下有个印象,第三种涉及到path,后边再讲。
我先总结一下第一种方法:其中x,y两个参数是文字左下角离坐标原点的距离;文字的左边为和下边为基线;当第一个参数为string类型或者CharSequence时,后边两个参数,start和end表示text字符串的两个位置;当地一个参数为char[]时,后边两个参数index和count表示text的index和index+count两个位置。

下边看一下具体操作:

指定文本开始的位置

// 文本(要绘制的内容)
String str = "ABCDEFG";

// 参数分别为 (文本 基线x 基线y 画笔)
canvas.drawText(str,200,500,textPaint);
指定文本开始的位置

图中文字下边的红线就是两条基线其中之一

String CharSequence两种类型的绘制

// 文本(要绘制的内容)
String str = "ABCDEFG";

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

1和3表示从字符串中截取[1,3)


String CharSequence两种类型的绘制

Char[] 字符数组的绘制

// 字符数组(要绘制的内容)
char[] chars = "ABCDEFG".toCharArray();

// 参数为 (字符数组 起始坐标 截取长度 基线x 基线y 画笔)
canvas.drawText(chars,1,3,200,500,textPaint);

这里边的1和3表示从字符数组中截取[1,1+3)


Char[] 字符数组的绘制
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,911评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,014评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 142,129评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,283评论 1 264
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,159评论 4 357
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,161评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,565评论 3 382
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,251评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,531评论 1 292
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,619评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,383评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,255评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,624评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,916评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,199评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,553评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,756评论 2 335

推荐阅读更多精彩内容