android_自定义控件第一炮

来源:互联网 发布:java svn版本号 编辑:程序博客网 时间:2024/05/17 22:57

自定义控件常见的几种方式:

Android View类是所有view的超类。
* 自定义类直接继承View或者ViewGroup。
* 这种方式需要自己去处理AT_MOST的情况。
* 自定义类继承已有的View,例如Button。
* 系统已经帮你处理好AT_MOST的情况,开发人员直接在其基础上去添加新功能即可。
* 自定义组合控件。
* 将需要的布局转化为一个ViewGroup去管理
*自定义类去继承该布局的根元素,例如LinearLayout,RelativeLayout等ViewGroup

自定义的View属性(建立View的内置属性)

步骤

  • 在values/attrs.xml建立创建自定义属性。
  • 在XML文件中指定属性的值。
  • 在自定义类中获取属性的值。
  • 将获取到的属性值应用到自定义View中。

创建自定义属性

创建values/attrs.xml文件,添加如下代码即可。

<?xml version="1.0" encoding="utf-8"?><!-- string,color,dimension,integer,enum,reference,float,boolean,fraction,flag; --><resources>    <declare-styleable name="CustomView">        <attr name="textColor" format="color" />        <attr name="textSize" format="dimension" />        <attr name="name" format="string" />        <attr name="isShow" format="boolean" />        <attr name="Oriental" format="enum">            <enum name="Horizontal" value="1"></enum>            <enum name="Vertical" value="0"></enum>        </attr>    </declare-styleable></resources>

可以将一些公共的属性抽取到外面,那么多个自定义控件都可公用这个属性了

<?xml version="1.0" encoding="utf-8"?><resources>    <attr name="textColor" format="color" />    <declare-styleable name="CustomView">            <attr name="textColor" />    </declare-styleable></resources>

使用自定义属性

  • 自定义的属性与系统提供的属性用法有一点不一样,那就是命名空间不一样。
  • 系统属性的namespace:
xmlns:android="http://schemas.android.com/apk/res/android"
  • 我们需要给自定义的View也加上namespace
xmlns:custom="http://schemas.android.com/apk/res/com.example.customviews"或者是xmlns:custom="http://schemas.android.com/apk/res-auto"(推荐使用)

完整例子

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    xmlns:custom="http://schemas.android.com/apk/res-auto"    android:layout_width="match_parent"    android:layout_height="match_parent"    tools:context=".MainActivity" >   <com.example.view.CustomView        android:layout_width="160dip"        android:layout_height="wrap_content"        custom:name="123456789"        custom:Oriental="Horizontal"        custom:textSize="15sp" /></RelativeLayout>

在自定义类中获取属性值

  • 在自定义类中必须有带有AttributeSet参数的构造函数,这样是为了方便获取通过布局文件实例化的自定义View对象。
  • 一般情况下的模版写法(相互调用,最终都由第三个构造去处理)
public CustomView(Context context) {        this(context, null);}public CustomView(Context context, AttributeSet attrs) {        this(context, attrs, 0);}public CustomView(Context context, AttributeSet attrs, int defStyle) {    super(context, attrs, defStyle);}

从AttributeSet中直接获取属性值

int attributeCount = attrs.getAttributeCount();for(int i = 0; i<attributeCount;i++) {    String name = attrs.getAttributeName(i);    String value = attrs.getAttributeValue(i);    Log.d("CustomView", name+"..."+value);}04-12 10:37:45.357: D/CustomView(27360): paddingLeft...10.0dip04-12 10:37:45.358: D/CustomView(27360): paddingRight...10.0dip04-12 10:37:45.358: D/CustomView(27360): layout_width...160.0dip04-12 10:37:45.358: D/CustomView(27360): layout_height...-204-12 10:37:45.358: D/CustomView(27360): textSize...15.0sp04-12 10:37:45.358: D/CustomView(27360): name...12345678904-12 10:37:45.358: D/CustomView(27360): Oriental...1

结果可以看到获取到的是所有的属性
* 根据官方文档介绍,虽然可以直接从AttributeSet中直接获取到属性值,但是有两个弊端
* Resource references within attribute values are not resolved
* Styles are not applied

google建议将将AttributeSet传递给obtainStyledAttributes()中

* 该方法会返回一个TypeArray对象。* 已经dereferenced and styled。* 系统在之前就已经做了很多准备工作,只等你去调用obtainStyledAttributes()方法    * 在R.java文件中已经定义自定义属性的ids值。    * 在Array中为每一个属性定义了index去表示指定的定义属性。    * 开发者只需要拿预定义的常量值去获取属性即可。
public CustomView(Context context, AttributeSet attrs, int defStyle) {    super(context, attrs, defStyle);    // 得到自定义属性的值    TypedArray a = context.getTheme().obtainStyledAttributes(attrs,            R.styleable.CustomView, defStyle, 0);    int count = a.getIndexCount();    for (int i = 0; i < count; i++) {        int index = a.getIndex(i);//得到表示属性值的常量标记        switch (index) {        case R.styleable.CustomView_name:            mName = a.getString(index);            break;        case R.styleable.CustomView_textSize:            mTextSize = a.getDimensionPixelSize(index, 16);            break;        default:            break;        }    }    // 回收    a.recycle();}
  • 注意:TypeArray是一个share resource使用后必须记得关闭回收。

提供可供外界触发的事件

  • 为什么要暴露属性给外界?
    • 为了让view具备动态的效果,就得通过修改View中的某一些属性,从而从新去绘制和布局View达到动态的效果。也就是去调用invalidate或者postInvalidate方法去进行view的重绘。
  • 怎么暴露?
    • getter/setter方法。
  • 暴露什么属性比较适合?
    • 规则就是暴露影响自定义View外观和行为的属性。
  • getter/setter方法一般会通过某些事件去触发执行,例如监控手势滑动事件不断修改View属性。
1 0
原创粉丝点击