【第22期】观点:IT 行业加班,到底有没有价值?

[Android]解决Fragment无法使用android:onClick属性

转载 2015年07月09日 16:22:55

有过MFC或者WinForm或者WPF经验的程序员一定对于Button的Click事件绑定情有独钟,然而当转移到Android平台开发的时候会发现,之前的种种便利全都不在,只有看着闹心的setOnClickListener()。
实际上Android里面也有同样的功能,在布局文件中同样可以给Button绑定Click时间的响应函数。如:
<Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="OnClick"
        android:text="Button" />
然后在Activity里面实现OnClick()函数:
public void OnClick(View v) {
System.out.println("Click");
}
真的很方便,不是吗?但是你千万不要高兴的太早,因为正有一个很大的坑在等着你!不信你瞧着。
Android中有很多很多的布局器,它们带来了极大的灵活性。与此同时,也出现了一种叫做Fragment的东西——它不是布局器,却可以管理布局器。Fragment为开发灵活的界面组件库提供了可能,同样的我们也想到在Fragment管理的布局文件中使用按钮的onClick属性。多么自然!
问题就出在Fragment身上,前面说了它不是布局器,所以它不具备渲染视图的能力,它管理的布局器最终要加载到一个ViewGroup对象内,由ViewGroup对象来渲染。而视图树并不知道每一个子控件来源于哪里,这就导致了一个结果:不管是在什么地方定义的onClick属性,都必须在包含该Button的Activity中去寻找OnClick()方法。
可能有人说,API中对onClick早有说明:设置点击时从上下文中调用指定的方法,只是你不知道而已。事实确实是这样,但是我是一个追根溯源的人,如果我没有遇到这么多的问题,我可能只知道应该怎么做,却不知道为何应该这样做。
抛开onClick属性,我们仍然可以使用代码的方式实现对Click的事件响应,但是毕竟——不优雅——了。
曾经我想到了一种办法——使用约定:让使用该Fragment的Activity实现一个包含所有OnClick()函数的接口。但是那样做仍然不够优雅!
对于Java程序员来说,反射有时候是一种水到渠成的方案。下面的ParseButtonIdClick()函数就是从配置文件中读取指定id的Button的OnClick实现函数,然后使用setOnClickListener()将实现函数和Button的Click事件进行绑定。
/**
* 解析按钮的Click事件响应
*/
protected void ParseButtonIdClick() {
XmlResourceParser xmlParser = rootView.getResources().getXml(
R.xml.button_id_click);

int event = XmlPullParser.START_DOCUMENT;

try {
event = xmlParser.getEventType();
} catch (XmlPullParserException e) {
e.printStackTrace();
}

String pkgName = (new Throwable()).getStackTrace()[0].getClassName();
System.out.println(pkgName);

do {
switch (event) {
case XmlPullParser.START_TAG: {
if (xmlParser.getName().equals("Button")) {
String id_str = xmlParser.getAttributeValue(0);
String click = xmlParser.getAttributeValue(1);

try {
Class<?> classRId = Class
.forName("com.abc.keyboard.R$id");
Field filedId = classRId.getField(id_str);
int id_int = filedId.getInt(null);
Button idButton = (Button) rootView
.findViewById(id_int);

final Method method = getClass().getDeclaredMethod(
click, View.class);
idButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
try {
method.invoke(KeyboardFragmentBase.this, v);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
});

} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
break;
}

try {
event = xmlParser.next();
} catch (XmlPullParserException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}

} while (event != XmlPullParser.END_DOCUMENT);

xmlParser.close();
}

我不是一个Java高手,所以如果有人能优化上面的代码,我会十分高兴。
举报

相关文章推荐

Android fragment XML中的button找不到Onclick函数的解决方法

开始学习安卓时,被XML中的onClick方法深深吸引,只需在Java文件中定义好相关函数,然后在onClick属性中设置要调用的函数名即可,每次都被这种简单而高效的神奇方法折服……一直很好奇为什么有...

Android:在Fragment中,onClick失效的解决方法

平时习惯写onclic方法, 但是有时候不是在Activity中,比如:Fragment中用onclick无效, 只能用 id 跳转或者弹框: 比如按钮 Button 或者 Lineayout ...

Android Fragment 真正的完全解析(上)

自从Fragment出现,曾经有段时间,感觉大家谈什么都能跟Fragment谈上关系,做什么都要问下Fragment能实现不~~~哈哈,是不是有点过~~~ 本篇博客力求为大家说明Fragment如何产...

fragment中设置点击事件(onclick)使用intent进行通信

今天在学习安卓的过程中,需要实现一个功能通信,就是需要在一个fragment中设置一个按钮,点击之后会跳转到一个新的页面,我首先想到是给按钮设置一个onclick属性, 按照以往写了这样的代码 pu...

Android Fragment 真正的完全解析(下)

上篇博客中已经介绍了Fragment产生原因,以及一些基本的用法和各种API,如果你还不了解,请看:Android Fragment 真正的完全解析(上)。 本篇将介绍上篇博客提到的:如何管理Frag...

Android Fragment解析以及Fragment中碰到的各种坑

对Fragment 的梳理和总结,从Fragment 的坑中脱离出来。

Android Fragment不显示,但是依然能点击到的BUG(已解决)

最近在做项目的时候,用了最熟悉的Fragment,但是每次程序出现BUG,程序重新加载的时候该Fragment就不再显示了,但是依然能点击到,让人很是头疼,一开始一直在寻找原因,排除了代码不规范的情况...

新东西011--Android Fragment常见错误分析

Fragment的onResume和onHiddenChanged差异解析         OnResume:跟activity生命周期相似,也跟activity的生命周期相关,当activity调...

Error:(26, 117) 错误: 不兼容的类型: Fragment无法转换为NewsContentFragment 解决方法

在用Android Studio 编写碎片程序的时候出现了以下错误: ...

Fragment中onOptionsItemSelected方法不起作用的解决方法

以前一般都是在Activity中添加menu菜单,一般是重写onCreateOptionsMenu和onOptionsItemSelected方法。 现在Fragment用的多了,就在Fragmen...
  • ican87
  • ican87
  • 2014-07-21 10:45
  • 5418
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)