[Android]解决Fragment无法使用android:onClick属性
生活随笔
收集整理的這篇文章主要介紹了
[Android]解决Fragment无法使用android:onClick属性
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
有過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高手,所以如果有人能優化上面的代碼,我會十分高興。
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无法使用android:onClick属性的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java中执行存储过程和函数(web基础
- 下一篇: easyui中的datagrid的数据加