當(dāng)前位置:
首頁 >
[Android]解决Fragment无法使用android:onClick属性
發(fā)布時(shí)間:2025/3/15
54
豆豆
生活随笔
收集整理的這篇文章主要介紹了
[Android]解决Fragment无法使用android:onClick属性
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
有過MFC或者WinForm或者WPF經(jīng)驗(yàn)的程序員一定對(duì)于Button的Click事件綁定情有獨(dú)鐘,然而當(dāng)轉(zhuǎn)移到
Android平臺(tái)開發(fā)的時(shí)候會(huì)發(fā)現(xiàn),之前的種種便利全都不在,只有看著鬧心的setOnClickListener()。
實(shí)際上Android里面也有同樣的功能,在布局文件中同樣可以給Button綁定Click時(shí)間的響應(yīng)函數(shù)。如:
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="OnClick"
android:text="Button" />
然后在Activity里面實(shí)現(xiàn)OnClick()函數(shù):
public void OnClick(View v) {
System.out.println("Click");
}
真的很方便,不是嗎?但是你千萬不要高興的太早,因?yàn)檎幸粋€(gè)很大的坑在等著你!不信你瞧著。
Android中有很多很多的布局器,它們帶來了極大的靈活性。與此同時(shí),也出現(xiàn)了一種叫做Fragment的東西——它不是布局器,卻可以管理布局器。Fragment為開發(fā)靈活的界面組件庫提供了可能,同樣的我們也想到在Fragment管理的布局文件中使用按鈕的onClick屬性。多么自然!
問題就出在Fragment身上,前面說了它不是布局器,所以它不具備渲染視圖的能力,它管理的布局器最終要加載到一個(gè)ViewGroup對(duì)象內(nèi),由ViewGroup對(duì)象來渲染。而視圖樹并不知道每一個(gè)子控件來源于哪里,這就導(dǎo)致了一個(gè)結(jié)果:不管是在什么地方定義的onClick屬性,都必須在包含該Button的Activity中去尋找OnClick()方法。
可能有人說,API中對(duì)onClick早有說明:設(shè)置點(diǎn)擊時(shí)從上下文中調(diào)用指定的方法,只是你不知道而已。事實(shí)確實(shí)是這樣,但是我是一個(gè)追根溯源的人,如果我沒有遇到這么多的問題,我可能只知道應(yīng)該怎么做,卻不知道為何應(yīng)該這樣做。
拋開onClick屬性,我們?nèi)匀豢梢允褂么a的方式實(shí)現(xiàn)對(duì)Click的事件響應(yīng),但是畢竟——不優(yōu)雅——了。
曾經(jīng)我想到了一種辦法——使用約定:讓使用該Fragment的Activity實(shí)現(xiàn)一個(gè)包含所有OnClick()函數(shù)的接口。但是那樣做仍然不夠優(yōu)雅!
對(duì)于Java程序員來說,反射有時(shí)候是一種水到渠成的方案。下面的ParseButtonIdClick()函數(shù)就是從配置文件中讀取指定id的Button的OnClick實(shí)現(xiàn)函數(shù),然后使用setOnClickListener()將實(shí)現(xiàn)函數(shù)和Button的Click事件進(jìn)行綁定。
/**
* 解析按鈕的Click事件響應(yīng)
*/
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(); }
我不是一個(gè)Java高手,所以如果有人能優(yōu)化上面的代碼,我會(huì)十分高興。
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(); }
我不是一個(gè)Java高手,所以如果有人能優(yōu)化上面的代碼,我會(huì)十分高興。
總結(jié)
以上是生活随笔為你收集整理的[Android]解决Fragment无法使用android:onClick属性的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java中执行存储过程和函数(web基础
- 下一篇: Android开发:5-2、ListVi