Android自定义控件探索之旅一5(笔记)

本篇文章是Android自定义控件探索之旅一4的续篇,主要学习的是Canvas绘制图片的第二种实现方式。

Android自定义控件探索之旅一7
Android自定义控件探索之旅一6
Android自定义控件探索之旅一5
Android自定义控件探索之旅一4
Android自定义控件探索之旅一3
Android自定义控件探索之旅一2
Android自定义控件探索之旅一1

绘制图片之Canvas.drawBitmap(Bitmap bitmap,......)

既然关于Canvas绘制方式的第二种实现方式涉及到了Bitmap,那么关于Bitmap,我个人想说的是:很不喜欢一些开发者将Bitmap的概念直接等同于图片,这种概念完全就是混淆视听、让人误解。关于Bitmap很权威的解释如下:Bitmap:也称 位图,又称栅格图(英语:Raster graphics)或点阵图,它是使用像素阵列(Pixel-array/Dot-matrix点阵)来表示的图像。实际上一张图片是由很多个像素点组建而成的。简而言之,Bitmap可以简单理解为一个画架,开发者可以在具体的应用场景,把图片放到Bitmap上接着对图片做一些处理。值得一提的是Bitmap文件的图像显示效果很好,但是非压缩格式,因此会需要占用较大的存储空间,所以在使用Bitmap时,经常会遇到内存溢出等情况,这是因为图片太大或者android系统对单个应用施加的内存限制等原因造成的。

简单说完了Bitmap的基本概念,下面介绍一下Bitmap是如何使用的。

关于Bitmap官方介绍Creates Bitmap objects from various sources, including files, streams, and byte-arrays 这句话翻译过来可以说是非常的简单明了。另外,Bitmap的加载和使用离不开BitmapFactory,BitmapFactory这个类提供了四种方法用来加载和获取Bitmap:

  • 方法一:decodeFile 从文件系统加载
    a.通过Intent打开本地图片或照片
    b.在onActivityResult中获取图片uri
    c.根据uri获取图片的路径
    d.根据路径解析bitmap: Bitmap bm = BitmapFactory.decodeFile(sd_path)

  • 方法二:decodeResource 以R.drawable.xxx的形式从本地资源中加载
    Bitmap bm = BitmapFactory.decodeResource(getResources(), R.drawable.aaa);

  • 方法三:decodeStream 从输入流加载
    a.开启异步线程去获取网络图片
    b.网络返回InputStream
    c.解析:Bitmap bm = BitmapFactory.decodeStream(stream),这是一个耗时操作,要在子线程中执行

  • 方法四:decodeByteArray 从字节数组中加载
    a.开启异步线程去获取网络图片
    b.网络返回InputStream
    c.把InputStream转换成byte[]
    d.解析:Bitmap bm = BitmapFactory.decodeByteArray(myByte,0,myByte.length);
    注意:decodeFile和decodeResource间接调用decodeStream方法。

在使用Bitmap时,经常会遇到内存溢出等情况,内存溢出的原因可能是因为图片太大或者Android系统对单个应用施加的内存限制等原因造成的,所以,高效的使用Bitmap就显得尤为重要,因此Bitmap的效率优化重要性就不言而喻。至于Bitmap内存优化的内容这里就不提及了。那么关于Bitmap的概念就简单介绍到这里。

通常来说,绘制Bitmap都是读取已有的图片,然后将其转换为Bitmap紧接着绘制到Canvas上。那么,Canvas绘制Bitmap的API有以下几种:

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

而且点开Canvas的源码,里面的 drawBitmap()方法,实际上全部是调用父类的BaseCanvas里面的drawBitmap()方法:

   /**
     * Draw the specified bitmap, with its top/left corner at (x,y), using the specified paint,
     * transformed by the current matrix.
     * <p>
     * Note: if the paint contains a maskfilter that generates a mask which extends beyond the
     * bitmap's original width/height (e.g. BlurMaskFilter), then the bitmap will be drawn as if it
     * were in a Shader with CLAMP mode. Thus the color outside of the original width/height will be
     * the edge color replicated.
     * <p>
     * If the bitmap and canvas have different densities, this function will take care of
     * automatically scaling the bitmap to draw at the same density as the canvas.
     *
     * @param bitmap The bitmap to be drawn
     * @param left The position of the left side of the bitmap being drawn
     * @param top The position of the top side of the bitmap being drawn
     * @param paint The paint used to draw the bitmap (may be null)
     */
    public void drawBitmap(@NonNull Bitmap bitmap, float left, float top, @Nullable Paint paint) {
        super.drawBitmap(bitmap, left, top, paint);
    }

针对Canvas绘制Bitmap的三种方法,下面做详细的叙述:

  • 第一种方法中后两个参数(matrix, paint),是在绘制的时候对图片进行一些改变。因此,如果只是需要将图片内容绘制出来只需要如下操作就可以了:
 mCanvas.drawBitmap(bitmap,new Matrix(),new Paint());

注意:图片左上角位置默认为坐标原点。

  • 第二种方法是在绘制时,指定了图片左上角的坐标(距离坐标原点的距离),系统源码如下:
   /**
     * Draw the specified bitmap, with its top/left corner at (x,y), using the specified paint,
     * transformed by the current matrix.
     * <p>
     * Note: if the paint contains a maskfilter that generates a mask which extends beyond the
     * bitmap's original width/height (e.g. BlurMaskFilter), then the bitmap will be drawn as if it
     * were in a Shader with CLAMP mode. Thus the color outside of the original width/height will be
     * the edge color replicated.
     * <p>
     * If the bitmap and canvas have different densities, this function will take care of
     * automatically scaling the bitmap to draw at the same density as the canvas.
     *
     * @param bitmap The bitmap to be drawn
     * @param left The position of the left side of the bitmap being drawn
     * @param top The position of the top side of the bitmap being drawn
     * @param paint The paint used to draw the bitmap (may be null)
     */
    public void drawBitmap(@NonNull Bitmap bitmap, float left, float top, @Nullable Paint paint) {
        super.drawBitmap(bitmap, left, top, paint);
    }

  • 第三种方法较之前的方法多了新参数,分别是 Rect和RectF,这两个参数是用来做什么的?
名称 作用
Rect 指定 绘制 图片的区域
Rect dst 或RectF dst 指定图片在屏幕上 显示 的区域

举个例子,帧动画是Android中的一种动画,所谓的 ,就是影像动画中最小单位的单幅影像画面,相当于电影胶片上的每一格镜头。 一帧就是一副静止的画面,连续的帧就形成动画,如电视图象等。简单点说就是类似幻灯片播放的那种效果,因此帧动画的本质就是将一张张的图片,通过代码对这些图片进行连续的活动(这样就形成了动画)。好了,现在也可以使用drawBitmap搭配Rect和RectF,首先指定 绘制 图片的区域,接着按照开发需求,指定图片在屏幕上 显示 的区域,这样做的好处是把同一个动画效果的所有资源图片整理到一张图片上,会大大的减少资源文件数量,方便管理。因此针对帧动画这种实现方式又提供了一种新的解决思路。

关于Canvas绘制图片的第二种实现方式,Canvas.drawBitmap(...)大概内容就介绍到这里,下一篇文章主要介绍的Canvas如何绘制文字

如果这篇文章对您有开发or学习上的些许帮助,希望各位看官留下宝贵的star,谢谢。

Ps:著作权归作者所有,转载请注明作者, 商业转载请联系作者获得授权,非商业转载请注明出处(开头或结尾请添加转载出处,添加原文url地址),文章请勿滥用,也希望大家尊重笔者的劳动成果,谢谢。

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

推荐阅读更多精彩内容