您的位置:首页 > 移动开发 > Android开发

自定义组件使用总结

2016-04-22 22:39 344 查看

一 概述

自定义组件有三种方式:

1. 继承现有组件,拓展其功能;

2. 组合现有控件,实现模板化;

3. 继承View,重写onDraw()方法,进行重绘;继承ViewGroup,重写相关方法,实现布局。

二 继承现有组件,拓展其功能

项目位置:E:\code\CustomViews\StudyTextView 以及 E:\code\CustomViews\StudyTextView0

运行效果:StudyTextView 通过点击自定义组件RotateTextView,实现其文字内容的旋转

StudyTextView0 实现自定义组件PaintDoubleWordsTextView,使其中的文字可随手指移动

总结:

以上两个自定义组件的实现原理均为继承现有组件,并在现有组件的基础上进行功能拓展。

具体而言,步骤如下:

1. 根据需要实现的功能选择所要拓展的组件;

2. 自定义类继承所要拓展的组件,这时,有以下几个重要的方法需要重写或使用:

重写:

构造方法 – 如果要在XML文件中直接使用自定义组件,需要实现具有两个参数的构造方法。这两个参数分别为:Context 与 AttributeSet。

在构造方法中,主要实现获取XML布局文件中写入的自定义属性的值。

在这之前,需要在res/values目录下定义attrs.xml文件,该文件中定义了自定义组件支持的自定义属性。具体写法为:在resources标签下加入declare-styleable标签,并给其一个标签名,一般选择自定义类名作为标签名;然后,在后面自定义属性,以标签attr包裹,内容包括自定义属性名name与自定义属性的类型format。形式如下所示:

<resources>
<declare-styleable name="一般为自定义控件类名">
<attr name="自定义属性名" format="">
<attr name="自定义属性名" format="">
... ...
</declare-styleable>
</resources>


这就定义了自定义控件的自定义属性,之后就可以在XML布局文件中使用这些自定义属性了。

使用的时候,要在xml文件中写入xmlns,即xml命名空间,形式为:

xmlns:custom=”http://schemas.android.com/apk/res-auto”

或:

xmlns:custom=”http://schemas.android.com/apk/manifest中的package名”

之后就可以“custom:自定义属性名”来使用自定义属性了。

在构造方法中,通过操作TypedArray来获取自定义属性内容,代码如下:

TypedArray options = context.obtainStyledAttributes(attrs, R.styleable.PaintDoubleWordsTextView, 0, 0);

int numOfOptions = options.getIndexCount();

for (int i = 0; i < numOfOptions; ++i) {
int index = options.getIndex(i);
switch (i) {
case R.styleable.PaintDoubleWordsTextView_word0 :
word0 = options.getString(index);
break;
case R.styleable.PaintDoubleWordsTextView_word0Size :
word0Size = options.getInt(index, DEFAULT_TEXT_SIZE);
break;
case R.styleable.PaintDoubleWordsTextView_word1 :
word1 = options.getString(index);
break;
case R.styleable.PaintDoubleWordsTextView_word1Size :
word1Size = options.getInt(index, DEFAULT_TEXT_SIZE);
break;
}
}
options.recycle(); // 勿忘


onDraw()
– 在该方法中绘制需要显示的内容

onDraw()
方法的参数是一个Canvas对象,通过该对象即可实现自定义组件的内容绘制。

使用:

invalidate()
– 导致onDraw()被调用,刷新View

requestLayout()
– 当前View的布局失效时就需要进行调用

以上两个方法更新过View后就要进行调用。

format包括:

类型含义
boolean布尔值
integer整数值
float浮点值
fraction百分数
string字符串
color颜色
dimension尺寸值
enum枚举
flag位或运算
reference资源引用
使用情况:

enum:

<attr name="属性名">
<enum name="名称" value="值" />
<enum name="名称" value="值" />
</attr>


flag:

<attr name="属性名">
<flag name="名称" value="值" />
<flag name="名称" value="值" />
... ...
</attr>


format参考:http://blog.csdn.net/mayingcai1987/article/details/6216655

//////

以上内容可参考:http://blog.csdn.net/allen315410/article/details/39343401

//////

三 控件组合,模板化使用

这种自定义组件的方式并不创建新的组件,只是将已有组件进行组合,然后将组合好的整体当做模板来使用。

关键方法:

1

LayoutInflater.from(Context).inflate(自定义布局id, 为加载好的布局指定父布局);


通过以上关键代码来将自定义布局载入程序中,之后就可以通过
findViewById
来获取自定义布局文件中的组件了。

步骤如下:

1. 根据需求进行组件组合

根据需求对组件进行组合,构成模板。此处主要是实现一个XML布局文件。

2. 拓展Layout类

实现Layout类的子类,在其具有两个参数的构造方法中加载上一步实现的布局文件,然后获取其中定义的组件。

3. 控制组件显示,实现事件响应

根据需求,操作上一步获取的组件,控制组件显示并实现具体的事件响应。

示例程序:E:\code\ExampleBest\test_selfdefinewidget

四 继承View,重写onDraw()方法,进行重绘;继承ViewGroup,重写相关方法,实现布局

继承View与继承ViewGroup是不同的。继承View是要自定义组件,而继承ViewGroup则要自定义布局

对于自定义组件而言,所需要考虑比较少,只有两点需要注意:

1. 对于Touch事件的处理;

根据事件处理机制,当重写了
onTouch
方法后,要注意返回true之后会导致
onTouchEvent
方法不再执行,进而影响到click的执行与滑动的效果;同时,还要注意对ACTION的DOWN处理后返回false时,会导致后续的UP、MOVE事件无法获取,也就是会阻止事件的层级传递。

2. 重写
onDraw
方法绘制需要的UI。

根据Android绘制原理,对于自定义View的绘制,只需要重写
onDraw
方法即可,在其中使用所提供的Canvas画布绘制所需要的效果。

至于测量与布局,自定义组件不需要考虑太多,这是由布局组件来考虑的问题。事实上,View类中的
measure
方法是一个final方法,子类无法重写,对于子类,只需要重写真正进行测量的
onMeasure
方法即可,在View类中的
onMeasure
实现里,只是去调用了
setMeasuredDimension
这个final方法去保存了组件的宽、高信息。从直接继承自View的TextView源码情况来看,其重写了
onMeasure
方法去根据padding等信息来计算宽、高数据。View类中的
layout
方法则直接在注释中说明,子类不需要重写该方法,具有子组件的子类,需要重写
onLayout
方法,在其中调用子组件的
layout
方法
,而View类中的
onLayout
方法则是一个空方法。从TextView源码来看,其并没有重写
layout
方法(因为不需要),所重写的
onLayout
方法也没有进行重要的操作。所以,在自定义View组件时,为了实现较精细的测量,一般需要重写
onMeasure
方法,对于
onLayout
方法,一般不用实现


对于自定义布局,就要考虑对于测量与布局的处理问题

1. 测量

这一步根据Android绘制原理,需要重写
onMeasure
方法,在其中获取各个子组件的dimension,计算出布局的dimension,然后调用
setMeasuredDimension
方法设置好布局的尺寸。ViewGroup中没有重写
onMeasure
方法,子类必须自己进行实现。

2. 布局

这一步需要重写
onLayout
方法,在其中调用各个子组件的
layout
方法,让子组件完成对自己的布局。在ViewGroup中,
onLayout
方法是一个抽象方法,自定义的布局必须实现该方法,在其中对子组件的
layout
方法进行调用。而ViewGroup中的
layout
方法是一个final方法,不能被重写,其中则简单的调用了Super的
layout
方法(
super.layout()
)。关于View的
layout
方法,一般在进行继承View自定义组件时不需要重写,至于View类中的
onLayout
方法,是一个空方法,不进行任何操作。

至于绘制,则由ViewRootImpl类中的
performTraversals
方法调用
performDraw
进而调用组件的
onDraw
方法实现,不需要在ViewGroup中考虑。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息