Android 为自定义 View 添加属性

发布于 2024-06-25 04:54:39 字数 4215 浏览 13 评论 0

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

春风十里

暂无简介

0 文章
0 评论
23 人气
更多

推荐作者

qq_E2Iff7

文章 0 评论 0

Archangel

文章 0 评论 0

freedog

文章 0 评论 0

Hunk

文章 0 评论 0

18819270189

文章 0 评论 0

wenkai

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文