针对imageview的扩展(转)

本文介绍如何在Android中创建自定义的圆角ImageView组件。通过继承ImageView并重写绘制方法,结合Canvas与Drawable实现圆角效果。探讨不同实现方案及其优缺点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这次的总结主要涉及到Dev Guide/User Interface中的Building Custom ComponentsHow Android Draws Views内容和部分Graphics内容。围绕实现一个自定义圆角的ImageView控件(我将它叫做RoundedImageView)展开。

首先说明How自定义控件。

在Android中用于人机交互的组件叫做widget,比如Button,TextView之类,都直接或间接继承自View。

说到这,自定义组件的方法就明朗了,就是使用继承,具体继承什么类根据你的需求定,当然直接继承自View类的话,这个就属于完全自定义了。这里有一个快速一点入门的方法,看Android提供的widget的源码。关于Android提供的类库的源码都在platform/frameworks/base.git这个工程下(至于git的使用方法不在本文范围内,所以略去不写了)。至于自定义控件的,更为详细内容可以查看官方文档Building Custom Components

此外,对于在xml定义圆角属性,这个我建议查看一些widget的源码,主要思想是在你的View的构造函数中通过解析AttributeSet参数获得相应的值来获取参数。还有一些命名控件的细节,可以查看API Demos里的LabelView这个Demos的代码获得细节,或者Google。

那么对于这个圆角ImageView具体问题,应该怎么做呢?

由于需求是做圆角的ImageView,所以我们自然而然的想到扩展ImageView类了。所以,首先必须先简介一下ImageView。

Displays an arbitrary image, such as an icon. The ImageView class can load images from various sources (such as resources or content providers), takes care of computing its measurement from the image so that it can be used in any layout manager, and provides various display options such as scaling and tinting.

顾名思义,就是一显示图片的控件。图片源提供了丰富的选项,可以使Bitmap,Drawable,ResouceId,Uri,Matrix。

方法的想法我想到了两个:

重写所有设定图片源的方法,将传入的图片改成圆角,在传给父类相应方法。重写onDraw()方法,当该RoundedImageView由于某些原因触发这个回调函数时,Draw一个圆角的图。

第一个方法显然过于麻烦。而且维护代价高,十分不优雅。并且需要很多类型之间相互转换,性能上也带来一定额外的开销。

第二个方法是理想中的不错的想法。但是对于我这个新手,由于涉及到很多东西,所以技术上带来了一定难度。

首先,这就涉及到How Android Draws Views。我摘录了几段话,合并起来如下。

When an Activity receives focus, it will be requested to draw its layout. You can force a View to draw, by calling invalidate(). If the view is visible, onDraw(Canvas) will be called at some point in the future.

得知三点:

当Activity获得焦点是,Activity会请求画它的布局。可以通过调用invalidate()方法强制一个View重绘。如果View可见那么invalidate()会回调onDraw(Canvas)方法。

此外,我通过查看ImageView的源码,得知4. 每一个set一种类型的图片资源的时候,最后都会调用invalidate()方法来请求重绘。比如说当你调用setBitmap()方法后,onDraw()方法就会回调。

还有,5. ImageView每一种setXX()图片的方法调用后,最终都会将图像资源它转成Drawable类型。(A Drawable is a general abstraction for "something that can be drawn. 更进一步信息可以查看Dev Guide中Graphics )

6. 并且ImageView类提供了getDrawable()获取这个Drawable对象的方法

根据以上6点,于是,我们可以在继承自ImageView的RoundedImageView方法中先获取这个Drawable对象,然后把它圆角化,然后再通过一些方法画出来

新问题又来了,怎么画?

一直未提到的一个事情是onDraw()回调函数会传入这个Canvas对象,Draw with a Canvas。

When you're writing an application in which you would like to perform specialized drawing and/or control the animation of graphics, you should do so by drawing through a Canvas. A Canvas works for you as a pretense, or interface, to the actual surface upon which your graphics will be drawn — it holds all of your "draw" calls. Via the Canvas, your drawing is actually performed upon an underlying Bitmap, which is placed into the window.

还是StackOverflow,有人给出了个一个pretty awesome的方法,地址在这里。(但是我说的这个方法是没有成为提问人的答案的那个方法)

题外话:似乎最近一些问题的关键解答,每次都是StackOverflow上求助解决的,悲剧(还是喜剧)。

最后,对于图形Graphics这个话题,我所知甚少,也许以后会写一个详细一点的总结吧。今天就先到这里了。

补注:按照StackOverflow上的做法可能会有性能上的多余开销,可以考虑将圆角图片cache到本类的一个私有成员上,这样不用每次重绘都进行圆角转换。但是还有一个问题,就是如果客户调用更新Bitmap或者Drawable的方法,那么如何判断Cache失效也是一个问题,暂时还没有想好。

注:本人初学,可能一些细节上会有纰漏,如果你有什么迷惑可以留言或者可以Google,谢谢!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值