安卓自定义View基础-开篇

书是要看的,但是看完了书没什么卵用——你依然对自定义View感觉朦朦胧胧,该如何下手?嗯,答案比较长,想要捷径可以直接看最后面。
纸上得来终觉浅,绝知此事要躬行。(我这里并不是真的说看书没用,而是强调自定义View这种没有办法纸上谈兵)
大概说下思路:
首先,为什么需要自定义View?
1. 现有的View满足不了你的需求,也没有办法从已有控件派生一个出来;界面元素需要自己绘制。
2. 现有View可以满足要求,把它做成自定义View只是为了抽象:为这个自定义View提供若干方法,方便调用着操纵View。通常做法是派生一个已有View,或者结合xml文件直接inflate。
目前常用的基本上是第二种方式,这种方式非常简单,与通常的View使用方法基本相同,但是作用却异常强大,拥有了这一层抽象,代码更加整洁也更容易维护,通过抽取自定义View的公共操作方法也减少了冗余代码,虽然简单,但不可忽视。
大多数人感觉神秘的应该是第一种,自绘控件,完全自定义;但其实这两种方式归根结底全部都是自绘;不信你去看看TextView的源码。只不过通常情况下系统帮我们绘制好了一些控件给开发者使用;OK,接下来就是一个问题。
在讲述之前我还是啰嗦地重申一下,复用已有View是最最常用也最有效的自定义View方式,必须熟练使用。
其次,如何自定义View?
想一下,一个View给用户最直观的感知是什么?静止的形态动态的操作。静止的形态意思就是一个View呈现到用户眼里长成啥样子?动态操作指的是,用户与View之间可以有哪些交互?点击滑动View的不同地方会有什么反应?
1. 静态
如果一个自定义View的样式都没有办法绘制出来,那么后续的交互就是空谈了;我们一步步分解这个问题。
1.1 你的自定义View分为哪几个部分?是所有的部分都需要手动绘制还是只有一部分——找出需要完全自定义的部分,其他的部分用已有View实现。
1.2 你的自定义View的每个部分长成什么样,占用多大空间——结合理论知识View的measure过程,比如match_parent, wrap_content结合父View的laout_params参数最终测量大小是多少?
1.3 你的自定义View每个部分摆放在哪?相对位置如何?——View的layout过程。
1.4 你的自定义View那些完全需要手动绘制的部分是什么样,如何绘制?
你得学会操纵Canvas,学会2D绘图,什么?你跟我说3D,OpenGL?学会这些再说。
这是我之前整理的Android 2D绘图的基本要素,直接看官方文档和ApiDemos就能理解了。

2D绘图基本要素
Canvas
Paint
Bitmap,BitmapFactory,BitmapRegionDecoder,ImageFormat,Movie,NinePatch

过度模式 
Xfermode 主要子类 PoterDuffXfermode

过滤
RGB过滤 ColorFilter的三个子类 ColorMatrixFilter, PoterDuffColorFilter, LightingColorFilter
alpha过滤 MaskFilter的两个实现类 BlurMaskFiler, EmbossMaskFilter
DrawFilter的实现 PaintFlagsDrawFilter

变换
Matrix
Camera
ColorMAtrix

渐变 
Shader的五个实现 BitmapShader, LinearGradient, SweepGradient, RadialGradient, ComposeShader

路径
Path
PathEffect
PathMeasure
Rasterizer

区域 
Region

Drawable系列
BitmapDrawable,ShapeDrawable,LayerDrawable等等

这些API这么多,你没有必要一个个看完,心中有个大概每个能做什么就行;然后我举个简单的例子:

当时有一个webview界面要做一个loading动画,不是进度条也不是点点点的那种,而是一个小人在跑步,很常见吧。一般的情况下弄一个帧动画就完事了,但是这里有个很蛋疼的事情:我们发现在有的手机上面,这个loading比一般的时候长,而且基本都是高端机,没有loading秒开,有了loading要等好几秒。原因很明显,罪魁祸首在这个loading,动画的执行是在主线程的,而webview的一些事件调度也是在主线程的,很有可能是这个动画阻碍了这个webview某些事件的执行,从而导致加载变慢。最终决定用SurfaceView解决:你不是不想在主线程刷新界面么,好,我单独给你开个线程专门执行动画;这个SurfaceView只给了你一个Canvas怎么办?每隔16ms draw一下界面,然后用Canvas.drawBitmap把小人画上去,然后隔一定的时机绘制下一个小人形态;这个自定义View就搞定了。最终loading流畅无比,完美解决问题。这就是一个非常简单的自定义View,没有处理layout,wrap_content等各种问题,但是你应该能感受到,自定义View不是什么神秘的事情。

2. 动态

假设你的自定View写好了,那么用户点击和滑动的时候会发生什么?如何处理点击事件和滑动事件?嵌套ScrollView会不会卡?喂猫点击某个View没反应?为什么在listView里面放button和imageView点击反应有区别?

这些问题归根结底,是View事件传递的问题;所以你得学习Android View的事件分发机制,相关教程网上非常之多,《艺术探索》和《群英传》都有讲,不赘述。

另外,可能有一些View还有动画,这就是另外一个话题了;酷炫的动画也是一个漂亮的App必不可少的内容,篇幅所限,略。

最后,我依然想强调一点:

最重要的是自己动手!

最重要的是自己动手!

你就算把我列的那些东西全学完了,书全看完了,API和ApiDemos也全都看过了;自己不真正写一个出来那就是扯淡,也浪费我扯这么多的时间。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值