Android 为自定义 View 添加属性
Android 自定义 View 己经不是什么新鲜话题,Android Api 提供了一大堆基础组件给我们,需要什么特定功能还需要我们继承它们然后定制更加丰富的功能。那么如何给自定义的 View 添加一些自定义 xml 属性呢,如 one:textTitle=""
,不仅如此,我们知道 xml 中有一个 android:onClick="onClickMethod"
,这样在 Activity 中就不需要给该 View 设置监听器了,那么有没有类似的自定义 listener 的属性呢?答案是肯定的。
先来看下我们最后想要定义的格式:
<com.boohee.view.Navbar
android:id="@+id/navbar"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
one:textTitle="@string/tab_more_text"
one:onAction="onAction" />
接着便会有如下的效果:
其中 textTitle 是定义 navbar 的标题,onAction 是 navbar 上 保存
按钮的事件。好了,下面就来看下代码实现:
定义 attrs.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="Navbar">
<attr name="textTitle" format="string|reference" />
<attr name="onAction" format="string" />
</declare-styleable>
</resources>
上面 attrs.xml
文件中定义了两个属性。
自定义 View 的初始化下添加代码
public class Navbar extends FrameLayout {
private Context ctx;
private Button left_btn, right_btn;
private TextView title;
public Navbar(Context context) {
super(context);
setUp();
}
public Navbar(Context context, AttributeSet attrs) {
super(context, attrs);
setUp();
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.Navbar);
final int N = a.getIndexCount();
for (int i = 0; i < N; ++i) {
int attr = a.getIndex(i);
switch (attr) {
case R.styleable.Navbar_textTitle:
title.setText(a.getString(attr));
break;
case R.styleable.Navbar_onAction:
...
break;
}
}
a.recycle();
}
void setUp() {
ctx = getContext();
addView(LayoutInflater.from(this.getContext()).inflate(R.layout.navbar, null));
left_btn = (Button) findViewById(R.id.left_btn);
title = (TextView) findViewById(R.id.title);
right_btn = (Button) findViewById(R.id.right_btn);
}
}
在 XML 布局文件中使用
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:one="http://schemas.android.com/apk/res/com.boohee.one"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@drawable/main_bg"
android:orientation="vertical" >
<com.boohee.myview.Navbar
android:id="@+id/navbar"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
one:textTitle="@string/tab_more_text" />
</LinearLayout>
需要注意的是根布局要加上命名空间 xmlns:one="http://schemas.android.com/apk/res/com.boohee.one"
添加一个回调属性
上面说明了如何自定义一些基础属性,那么如何像 android:onClick
属性一样自定义一个方法回调属性呢,这个一开始实在不晓得如何下手,还好 android 是开源的,通过看源码后终于有了方法,废话不多说,看代码:
case R.styleable.Navbar_onAction:
if (context.isRestricted()) {
throw new IllegalStateException();
}
right_btn.setVisibility(View.VISIBLE);
final String handlerName = a.getString(attr);
if (handlerName != null) {
right_btn.setOnClickListener(new OnClickListener() {
private Method mHandler;
public void onClick(View v) {
if (mHandler == null) {
try {
mHandler = getContext().getClass().getMethod(handlerName,
View.class);
} catch (NoSuchMethodException e) {
throw new IllegalStateException("NoSuchMethodException");
}
}
try {
mHandler.invoke(getContext(), right_btn);
} catch (IllegalAccessException e) {
throw new IllegalStateException();
} catch (InvocationTargetException e) {
throw new IllegalStateException();
}
}
});
}
break;
代码倒是不难理解,只是上述代码用到了 java 的反射机制。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
上一篇: Android 中自定义属性格式详解
下一篇: 彻底找到 Tomcat 启动速度慢的元凶
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论