实现TextView的onClick的xml配置

看到button的android:onClick=""很方便,试了试TextView的,虽然可以设置onClick属性,但是点击的时候总是不能相应,onClick属性的配置是在View级别设置的,难道是TextView给屏蔽了?等看到TextView的源码再来解决这个疑问。

既然不能用, 那么咱们就仿照着View的源码自己实现个onClick

既然是增强版的TextView,那么首先建立一个类让它继承自TextView

publicclassMyTextViewextendsTextView{
publicMyTextView(Contextcontext,AttributeSetattrs){
this(context,attrs,0);
}
publicMyTextView(Contextcontext,AttributeSetattrs,intdefStyle){
super(context,defStyle);
TypedArrayta=context.obtainStyledAttributes(attrs,R.styleable.MyTextView,defStyle,0);
finalintCOUNT=ta.getIndexCount();
for(inti=0;i<COUNT;i++){
intattr=ta.getIndex(i);
switch(attr){
caseR.styleable.MyTextView_onClick:
finalStringhandlerName=ta.getString(attr);
if(null!=handlerName){
setOnClickListener(newOnClickListener(){
@Override
publicvoidonClick(Viewv){
Methodhandler=null;
try{
handler=getContext().getClass()
.getMethod(handlerName,View.class);
handler.invoke(getContext(),MyTextView.this);
}catch(Exceptione){
e.printStackTrace();
}
}
});
}
break;
}
}
ta.recycle();
}
}

短短几行代码,我们需要功能已经实现了,可以看到我们使用了反射机制,不用想也知道,android源码肯定也是使用了反射机制。

下面一点点的来分析吧:

首先是加载attr,因为我们要实现onClick的xml配置,所以必须要自定义属性

<?xmlversion="1.0"encoding="utf-8"?>
<resources>
<declare-styleablename="MyTextView">
<attrname="onClick"format="string"/>
</declare-styleable>
</resources>

这里我们定义了一个名称为onClick的属性,格式为string类型, 当你配置到xml布局的时候,我们还需要在自定义TextView中获取它的值,首先我们获取TypedArray对象:

TypedArrayta=context.obtainStyledAttributes(attrs,0);

接下来是获取ta的总个数:

finalintCOUNT=ta.getIndexCount();

接着一个熟悉的for循环,我们来取所有的我们自定义的attr,使用一个swith...case...语句来判断是不是我们需要的那个attr,当然我们只有一个attr,所以这么写有点多次一举,但是有利于以后扩展吧。

注意:

intattr=ta.getIndex(i);

这句话是获取当前attr的索引,即:R.styleable.xxx。

然后我们通过:

finalStringhandlerName=ta.getString(attr);

获取方法名称(xxx:onClick="method")

接下来就是设置onClick事件了,因为当前我的是在一个TextView中,所以直接:

setOnClickListener(newOnClickListener(){
@Override
publicvoidonClick(Viewv){
}
}

就ok了。关键的步骤来了,我们需要根据获取方法名通过反射机制来调用方法,在使用button的onClick时,我们映射的方法有一个参数是View,我们这也来一个。

通过参数名获取方法

Methodhandler=getContext().getClass().getMethod(handlerName,View.class);

这里不难理解,因为该Method是在使用该xml布局的Activity中定义的,所以需要getContext()来获取上下文,getMethod的第一个参数是方法名,第二个参数是方法的参数类型。

最后一步,就是调用这个方法了:

handler.invoke(getContext(),MyTextView.this);

现在我们扩展的TextView已经写完了,接下来就是使用了:

<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
xmlns:click="http://schemas.android.com/apk/res/com.example.onclick"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<com.example.onclick.MyTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="50dip"
android:background="@android:color/darker_gray"
android:text="IamCustomTextView..."
click:onClick="click"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="50dip"
android:background="@android:color/darker_gray"
android:onClick="click2"
android:text="IamTextView..."/>
</LinearLayout>

我们定义了两个TextView,第一个是我们自定义的,第二个是一个普通的TextView,两个我们都给了onClick配置,需要注意的是:自定义TextView的onClick配置我们使用的是:

click:onClick="click"

我们使用了一个click命名空间,所以要声明该命名空间:

xmlns:click="http://schemas.android.com/apk/res/com.example.onclick"

我们的activity代码很简单:

publicclassMainActivityextendsActivity{
@Override
protectedvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
publicvoidclick(Viewview){
Toast.makeText(this,"helloandroid",Toast.LENGTH_SHORT).show();
}
publicvoidclick2(Viewview){
Toast.makeText(this,"helloworld",Toast.LENGTH_SHORT).show();
}
}

相关文章

引言 NOKIA 有句著名的广告语:“科技以人为本”。任何技术都是为了满足人的生产生活需要而产生的。具体...
Writer:BYSocket(泥沙砖瓦浆木匠) 微博:BYSocket 豆瓣:BYSocket Reprint it anywhere u want. 文章...
Writer:BYSocket(泥沙砖瓦浆木匠) 微博:BYSocket 豆瓣:BYSocket Reprint it anywhere u want. 文章...
http://blog.jobbole.com/79252/ 引言 NOKIA 有句著名的广告语:“科技以人为本”。任何技术都是为了满...
(点击上方公众号,可快速关注) 公众号:smart_android 作者:耿广龙|loonggg 点击“阅读原文”,可查看...
一、xml与xslt 相信所有人对xml都不陌生,其被广泛的应用于数据数据传输、保存与序列化中,是一种极为强...