Android自定义view之基础知识
虽然Android已经自带了很多实用的view和layout,加以调教能实现很美观的界面,但是有一些情况下,需要实现特殊的界面效果,比如我们比较熟悉的各种播放器的滑动条环节音量的界面,不同的音量对应不同的格数,但是不必要为每个格都单独开辟一个ImageView,如果只使用一个ImageView,那么又需要准备很多的图片,这样显然是不划算的,这个时候就需要自己去实现一个自定义view。再比如侧滑菜单,之前的android并没有自带侧滑菜单(现在已经有了,是DrawerLayout),但各大应用已经有了侧滑菜单,显然都是自定义的。
1. 自定义view的分类
自定义view实际上就是继承特定的view或者layout,甚至干脆直接继承基类View或者ViewGroup,重写其中的一些方法来实现特定的效果。
自定义view从继承的类来说有以下四种分类。
- 继承特定的view,重写其中的一些方法。
通常是需求本身不复杂,往往一些现成的View稍加改动就可以实现。比如很简单的自动滚动的TextView,要设置text为跑马灯效果的循环滚动,在layout文件中要设置如下关键属性。
<TextView
...
android:maxLine=1
android:ellipsize="marquee"
android:marqueeRepeatLimit="marquee_forever"/>
设置最大行数为1行,否则TextView会自动折行。然后设置当文字过长时文字的缩略方式,有缩略中间、末尾、无以及跑马灯效果,如果不设置则默认缩略末尾,也就是文字过长时会将多出的文字以...
代替。最后设置跑马灯的循环次数为无限循环。但是这样还是不够的,因为TextView在获取到焦点的时候才会触发跑马灯效果,没有焦点的时候不会滚动。TextView中有个boolean isFocused()
方法,来判断当前TextView是否获取了焦点,我们只要继承TextView并且让这个方法一直返回true就行了。
package com.example.zu.myapp.layout;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.TextView;
public class AutoScrollTextView extends TextView
{
public AutoScrollTextView(Context context) {
super(context);
}
public AutoScrollTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean isFocused() {
return true;
}
}
这样一来,在需要滚动的地方使用这个自定义的TextView来代替TextView即可。
这种方法通常是最省力的,因为只是修改了某些地方,至于View本身怎么布局怎么呈现,仍然没有改变。
继承特定的Layout
就像开头提到的侧滑菜单,显然无论LinearLayout还是RelativeLayout都无法满足要求,而需求本身更像是一种特殊布局,因此我们会选择继承一个Layout并重写一些方法。而Layout根据特点的不同,一般选择继承的会是RelativeLayout或者FrameLayout。直接继承View
这种情况实际上用得比较少,毕竟View是所有视图空间的基类,只包含一些必要的方法。但是在处理一些相对比较简单的视图效果的时候,比如文字、特殊的图片显示效果,就可以选择直接继承View来实现,这样反而更能减少干扰。不过一些细枝末节的工作需要自己手动处理,你比如padding属性。直接继承ViewGroup
ViewGroup是所楼Layout的基类,而View是它的基类。ViewGroup和View的主要区别就在于measure、layout和draw的不同,ViewGroup增加了对子View的布局考虑。和直接继承View的目的一样,如果不想特定的Layout的自身特点所带来的干扰,并且要实现的效果也不是很复杂,则可以直接继承ViewGroup。当然,像padding和wrap_content等这些工作就需要自己来处理。
以上是从继承的类来说,如果从目的和重写的重点方法来看,则可分为两类。
- 实现特殊的视图效果
这种最典型的就是需要实现一个有特殊显示效果的View,举例来说,小米的时钟界面的仪表盘,做得很精美。显然它是一个独立的控件,而不是Layout。这种情况更多的侧重点在绘制,也就是onDraw
方法。这也是对应着上面所说的继承View。
- 实现特殊的布局效果
现在制作比较精美的应用随着点击、滑动等各种操作,界面会有各种非常漂亮的变化效果,这往往都是通过自定义layout实现的,通过控制子View的测量(measure)和布局(layout),来达到特殊的排版效果,最简单的例子就是侧滑菜单,,它通过控制菜单和主页的位置来达到侧滑的效果。这也对应着上面说的继承ViewGroup。
以上基本就概括了常用的自定义View的分类,而上面提到的一些自定义view的例子会在后面的实战环节中一一展示。
2. 自定义View的两条知识线
一个view它主要的作用有两个,一是显示内容,二是响应(操作)事件,自定义view也是如此。通常,如果功能不是太简单或者太复杂的话,基本都会涉及到这两方面,这就使得想要自定义view必须学会两方面知识,一个是view的显示流程,另外一个就是view的事件分发机制。
一个view显示出来,需要经过measure、layout和draw的过程,meausre负责确定view的大小;layout负责确定view本身以及子view的位置;draw则负责将view绘制出来。最后才是我们所看到的view。
而事件分发机制其实更多的是ViewGroup中的内容,毕竟ViewGroup中有子view,才需要分发事件。
由于这两方面的内容都比较繁杂(毕竟和视图扯上关系的工作量都比较大),因此会在后面的文章中分别详细讨论这两条线上的内容。
声明:本系列文章部分知识点来自于《Android开发艺术探索》,在此对作者表示感谢。部分内容可能会有错误和遗漏,欢迎大家留言讨论。