Gli altri hanno già detto che i metodi in onClick vengono cercati in attività, non in frammenti. Tuttavia, se lo vuoi davvero, è possibile.
Fondamentalmente, ogni vista ha un tag (probabilmente nullo). Abbiamo impostato il tag della vista principale sul frammento che ha gonfiato quella vista. Quindi, è facile cercare i genitori della vista e recuperare il frammento contenente il pulsante cliccato. Ora scopriamo il nome del metodo e usiamo la reflection per chiamare lo stesso metodo dal frammento recuperato. Facile!
in una classe che si estende Fragment
:
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_id, container, false);
OnClickFragments.registerTagFragment(rootView, this); // <========== !!!!!
return rootView;
}
public void onButtonSomething(View v) {
Log.d("~~~","~~~ MyFragment.onButtonSomething");
// whatever
}
tutte le attività derivano dalla stessa ButtonHandlingActivity:
public class PageListActivity extends ButtonHandlingActivity
ButtonHandlingActivity.java:
public class ButtonHandlingActivity extends Activity {
public void onButtonSomething(View v) {
OnClickFragments.invokeFragmentButtonHandlerNoExc(v);
//or, if you want to handle exceptions:
// try {
// OnClickFragments.invokeFragmentButtonHandler(v);
// } catch ...
}
}
Deve definire i metodi per tutti i gestori xml onClick.
com / example / customandroid / OnClickFragments.java:
package com.example.customandroid;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import android.app.Fragment;
import android.view.View;
public abstract class OnClickFragments {
public static class FragmentHolder {
Fragment fragment;
public FragmentHolder(Fragment fragment) {
this.fragment = fragment;
}
}
public static Fragment getTagFragment(View view) {
for (View v = view; v != null; v = (v.getParent() instanceof View) ? (View)v.getParent() : null) {
Object tag = v.getTag();
if (tag != null && tag instanceof FragmentHolder) {
return ((FragmentHolder)tag).fragment;
}
}
return null;
}
public static String getCallingMethodName(int callsAbove) {
Exception e = new Exception();
e.fillInStackTrace();
String methodName = e.getStackTrace()[callsAbove+1].getMethodName();
return methodName;
}
public static void invokeFragmentButtonHandler(View v, int callsAbove) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException {
String methodName = getCallingMethodName(callsAbove+1);
Fragment f = OnClickFragments.getTagFragment(v);
Method m = f.getClass().getMethod(methodName, new Class[] { View.class });
m.invoke(f, v);
}
public static void invokeFragmentButtonHandler(View v) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException {
invokeFragmentButtonHandler(v,1);
}
public static void invokeFragmentButtonHandlerNoExc(View v) {
try {
invokeFragmentButtonHandler(v,1);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
public static void registerTagFragment(View rootView, Fragment fragment) {
rootView.setTag(new FragmentHolder(fragment));
}
}
E la prossima avventura sarà l'offuscamento del proguard ...
PS
Spetta ovviamente a te progettare la tua applicazione in modo che i dati risiedano nel Modello piuttosto che in Attività o Frammenti (che sono Controller dal punto di vista MVC , Model-View-Controller ). La vista è ciò che definisci tramite xml, più le classi di visualizzazione personalizzate (se le definisci, la maggior parte delle persone riutilizza semplicemente ciò che è già). Una regola pratica: se alcuni dati devono assolutamente sopravvivere al turno dello schermo, appartengono a Model .