Android 自定义View步骤
1 良好的自定义view
易用,标准,开放。
一个设计良好的自定义view和其他设计良好的类很像。封装了某个具有易用性接口的功能组合,这些功能能够有效地使用cpu和内存,并且十分开放的。但是,除了开始一个设计良好的类之外,一个自定义view应该:
l 符合安卓标准
l 提供能够在android xml布局中工作的自定义样式属性
l 发送可访问的事件
l 与多个android平台兼容。
android框架提供了一套基本的类和xml标签来帮您创建一个新的,满足这些要求的view。忘记提供属性和事件是很容易的,尤其是当您是这个自定义view的唯一用户时。请花一些时间来仔细的定义您view的接口以减少未来维护时所耗费的时间。一个应该遵从的准则是:暴露您view中所有影响可见外观的属性或者行为。
2 创建自定义view (步骤)
2.1 继承view完全自定义或继承view的派生子类
必须提供一个能够获取context和作为属性的attributeset对象的构造函数,获取属性,当view从xml布局中创建了之后,xml标签中所有的属性都从资源包中读取出来并作为一个attributeset传递给view的构造函数。
view 派生出来的直接或间接子类:imageview, button, checkbox, surfaceview, textview, viewgroup, abslistview
viewgourp 派生出来的直接或间接子类:absolutelayout, framelayout, relativelayout, linearlayout
所有基类、派生类都是android framework层集成的标准系统类, 可直接引用sdk中这些系统类及其api
2.2 定义自定义属性
l 在资源元素<declare-styleable>中为您的view定义自定义属性。
在项目组添加<declare-styleable>资源。这些资源通常是放在res/values/attrs.xm文件里。如下是attrs.xml文件的一个例子:
<resources>; <declare-styleable name="piechart"> <attr name="showtext" format="boolean" /> <attr name="labelposition" format="enum"> <enum name="left" value=""/> <enum name="right" value=""/> </attr> </declare-styleable> </resources>
l 在您的xml布局中使用指定属性的值。
布局xml文件中可以像内建属性一样使用它们。唯一不同是自定义属性属于不同的命名空间。
[你的自定义view所在的包路径]
<?xml version="." encoding="utf-"?> <linearlayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:custom="http://schemas.android.com/apk/res/com.example.customviews"> <com.example.customviews.charting.piechart custom:showtext="true" custom:labelposition="left" /> </linearlayout>
l 在运行时取得属性值。
l 将取回的属性值应用到您的view中。
2.3 获取自定义属性
当view从xml布局中创建了之后,xml标签中所有的属性都从资源包中读取出来并作为一个attributeset传递给view的构造函数。尽管从attributeset中直接读取值是可以的,但是这样做有一些缺点:
l 带有值的资源引用没有进行处理
l 样式并没有得到允许
取而代之的是,将attributeset传递给obtainstyledattributes()方法。这个方法传回了一个typedarray数组,包含了已经解除引用和样式化的值。
为了时能能够更容易的调用obtainstyledattributes()方法,android资源编译器做了大量的工作。res文件夹 中的每个<declare-styleable>资源,生成的r.java都定义了一个属性id的数组以及一套定义了指向数组中的每一个属性 的常量。您可以使用预定义的常量从typedarry中读取属性。下例是piechart类是如何读取这些属性的:
public piechart(context ctx, attributeset attrs) { super(ctx, attrs); typedarray a = context.gettheme().obtainstyledattributes( attrs, r.styleable.piechart, , ); try { mshowtext = a.getboolean(r.styleable.piechart_showtext, false); mtextpos = a.getinteger(r.styleable.piechart_labelposition, ); } finally { a.recycle(); } }
注意,typedarry对象是一个共享的资源,使用完毕必须回收它。
2.4 添加属性和事件
属性是控制view的行为和外观的强有力的方式,但是只有view在初始化后这些属性才可读。为了提供动态的行为,需要暴露每个自定义属性的一对getter和setter。下面的代码片段显示piechart是如何提供showtext属性的。
public boolean isshowtext() { return mshowtext; } public void setshowtext(boolean showtext) { mshowtext = showtext; invalidate(); requestlayout(); }
注意,setshowtext调用了invalidate()和requestlayout()。这些调用关键是为了保证view行为是可靠的。你必须在改变这个可能改变外观的属性后废除这个view,这样系统才知道需要重绘。同样,如果属性的变化可能影响尺寸或者view的形状,您需要请求一个新的布局。忘记调用这些方法可能导致难以寻找的bug。
自定义view同样需要支持和重要事件交流的事件监听器。
2.5 自定义绘制(实施)
绘制自定义视图里最重要的一步是重写ondraw()方法. ondraw()的参数是视图可以用来绘制自己的canvas对象. canvas定义用来绘制文本、线条、位图和其他图像单元. 你可以在ondraw()里使用这些方法创建你的自定义用户界面(ui).
android.graphics框架把绘图分成了两部分:
l 画什么, 由canvas处理
l 怎么画, 由paint处理
例如, canvas提供画线条的方法, 而paint提供定义线条颜色的方法. canvas提供画矩形的方法, 而paint定义是否用颜色填充矩形或让它为空. 简而言之, canvas定义你可以在屏幕上画的形状, 而paint为你画的每个形状定义颜色、样式、字体等等.
ondraw()不提供3d图形api的支持。如果你需要3d图形支持,必须继承surfaceview而不是view,并且通过单独的线程画图。
3 优化
3.1 降低刷新频率
为了提高view的运行速度,减少来自于频繁调用的程序的不必要的代码。从ondraw()方法开始调用,这会给你带来最好的回报。特别地,在ondraw()方法中你应该减少冗余代码,冗余代码会带来使你view不连贯的垃圾回收。初始化的冗余对象,或者动画之间的,在动画运行时,永远都不会有所贡献。
加之为了使ondraw()方法更有依赖性,你应该尽可能的不要频繁的调用它。大部分时候调用 ondraw()方法就是调用invalidate()的结果,所以减少不必要的调用invalidate()方法。有可能的,调用四种参数不同类型的invalidate(),而不是调用无参的版本。无参变量需要刷新整个view,而四种参数类型的变量只需刷新指定部分的view.这种高效的调用更加接近需求,也能减少落在矩形屏幕外的不必 要刷新的页面。
3.2 使用硬件加速
作为android3.0,android2d图表系统可以通过大部分新的android装置自带gpu(图表处理单元)来增加,对于许多应用程序 来说,gpu硬件加速度能带来巨大的性能增加,但是对于每一个应用来讲,并不都是正确的选择。android框架层更好地为你提供了控制应用程序部分硬件 是否增加的能力。
怎样在你的应用,活动,或者窗体级别中使用加速度类,请查阅android开发者指南中的hardware acceleration类。注意到在开发者指南中的附加说明,你必须在你的androidmanifest.xml 文件中的<uses-sdk android:targetsdkversion="11"/>中将应用目标api设置到11或者更高的级别。
一旦你使用硬件加速度类,你可能没有看到性能的增长,手机gpus非常擅长某些任务,例如测量,翻转,和平移位图类的图片。特别地,他们不擅长其他的任务,例如画直线和曲线。为了利用gpu加速度类,你应该增加gpu擅长的操作数量,和减少gpu不擅长的操作数量。
上一篇: PHP下载远程图片的几种方法总结