Android 自定义View

Creating a View class

一个精心设计的自定以View就好比其他精心设计的Class。它封装一组特定并且容易使用的接口,充分利用cpu和内存,等等。除了是一个精心设计的类,一个定制的View应该:

---符合Android标准

---提供自定义属性为xml布局服务

---发送可访问事件

---兼容Android多平台

SubClass a View

在Frameworks 中定义的所有视图类都是继承与View,你的自定义View可以继承View,或者节约时间继承其他视图类,比如Button

你必须至少提供Context和AttrbuteSet作为参数的构造函数,目的是为了ADT与自定义View交互。这个构造函数允许视图编辑器创建和编辑你的View实例。

class PieChart extends View {
    public PieChart(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
}

Define Custom Attributes

为了添加内置View到用户界面,你应该指定该View到XML布局文件中,通过属性来控制View的显示和行为。良好的自定义View还能添加到XML和样式化。

要实现这样的自定义View,你必须:

---在资源文件中用 <declare-styleable>为你的View定义属性

---在你的XML布局文件中指定属性的值

---运行时检索属性的值

---将检索出来的属性值应用到你的View


这个节点讨论怎么定义自定义属性和指定自定义属性的值。下个节点讨论检索属性值以及应用属性值。


增加<declare-styleable>资源到你的Project来定义自定义属性。一般做法是将这些资源放到res/values/attr.xml文件中。例子如下:

<resources>
   <declare-styleable name="PieChart">
       <attr name="showText" format="boolean" />
       <attr name="labelPosition" format="enum">
           <enum name="left" value="0"/>
           <enum name="right" value="1"/>
       </attr>
   </declare-styleable>
</resources>

这段代码定义了属于PieChart实体节点的showText和labelosition两个属性,按照惯例<declare-styleable>实体节点命名和自定义View的Class命名相同。

虽然没有必要严格遵守这个惯例,很多流行的代码编辑器取决于该命名惯例来完成语法。


一旦你成功定义属性,就能在XML布局文件中像Android内置属性一样使用他们。唯一的不同就是自定义属性属于不同的名称空间,而不是属于

http://schemas.android.com/apk/res/android名称空间,而是属于http://schemas.android.com/apk/res/[your package name]。

例如,piehart实体节点定义的属性使用范例如下:

<?xml version="1.0" encoding="utf-8"?>
<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>

为了避免重复使用这么长的名称空间标识符,请参照上面的xmlns节点写法。具体做法是给名称空间 http://schemas.android.com/apk/res/com.example.customviews

指定一个别名,即custom。这样你就能选择所需要的名称空间别名。


PS:添加自定义View到XML布局文件中时,必须加上Class的全路径,如果Class是一个内部类还的加上$标识符。

比如PieChart中有一个叫PieView的内部类,要使用这个类的自定义属性,的这样指定:

com.example.customviews.charting.PieChart$PieView


Apply Custom Attributes

当XML布局文件中的View被创建时,在xml标签中定义的所有属性从资源包中读取,以AttributeSet对象的方式传到自定义View的构造函数中。

虽然可以从AttributeSet中直接读取值,但是有这样做有如下缺点:

---资源引用中的属性值没有被解决(没整明白)

---样式不能被应用


代替方法是将AttributeSet传到obtainStyledAttributes(),该方法会返回一个已经被引用和样式化的TypedArray数组。

Android资源编译器通过调用obtainStyledAttributes()可以为你更容易的做更多工作。

在res下的每一个<declare-styleable>资源生成R.java定义了一个属性ids的数组和常量集合,即为数组中的每个属性定义一个索引。

你使用预先定义的常量从TypedArray中读取属性,这里是PieChart类读取属性的范例:

public PieChart(Context context, AttributeSet attrs) {
   super(context, attrs);
   TypedArray a = context.getTheme().obtainStyledAttributes(
        attrs,
        R.styleable.PieChart,
        0, 0);

   try {
       mShowText = a.getBoolean(R.styleable.PieChart_showText, false);
       mTextPos = a.getInteger(R.styleable.PieChart_labelPosition, 0);
   } finally {
       a.recycle();
   }
}
PS:TypedArray是一个共享资源,用完了记得释放



Add Properties and Events

属性集合是控制View显示和行为的一个强有力方式,但是他们只能在View初始化的时候被读取。

为每一个属性暴露get()和set()来动态改变View的行为。下面的代码片段向你展示PieChart怎样暴露showText属性:

public boolean isShowText() {
   return mShowText;
}

public void setShowText(boolean showText) {
   mShowText = showText;
   invalidate();
   requestLayout();
}
PS:setShowText()调用invalidate()和requestLayout()是保证View正确展现,这至关重要。任何属性改变导致的View外观变化都必须使View无效,

这样系统才能知道该View需要被重新绘制,即invalidate()。同样的,任何属性改变导致View尺寸和边框变化后必须请求一个新的布局,即requestLayout()。

如果你忘掉这些可能出现比较难发现的Bug。


Design For Accessibility

没整明白这个


自定义View样式这篇文章讲解的非常详细,推荐之


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值