web-dev-qa-db-fra.com

Android Fragment onClick button Méthode

J'essaie d'appeler la méthode dans mon XML onClick (View v), mais ne fonctionne pas avec Fragment. C'est l'erreur.

01-17 12:38:36.840: E/AndroidRuntime(4171): Java.lang.IllegalStateException: 
Could not find a method insertIntoDb(View) in the activity class main.MainActivity 
for onClick handler on view class Android.widget.Button with id 'btn_conferma'

Code Java:

public void insertIntoDb(View v) {
...
} 

XML:

<Button
        Android:id="@id/btn_conferma"
        style="?android:attr/borderlessButtonStyle"
        Android:layout_width="0.0dip"
        Android:layout_height="45dp"
        Android:layout_marginLeft="2dp"
        Android:layout_weight="1.0"
        Android:background="@drawable/bottoni"
        Android:gravity="center_horizontal|center_vertical"
        Android:onClick="insertIntoDb"
        Android:text="SALVA"
        Android:textColor="#ffffff"
        Android:textSize="16sp" />
85
user3160725

Votre activité doit avoir

public void insertIntoDb(View v) {
...
} 

pas fragment.

Si vous ne voulez pas que ce qui précède soit en activité. initialiser le bouton dans le fragment et définir le même auditeur.

<Button
    Android:id="@+id/btn_conferma" // + missing

Ensuite

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {

   View view = inflater.inflate(R.layout.fragment_rssitem_detail,
    container, false);
   Button button = (Button) view.findViewById(R.id.btn_conferma);
   button.setOnClickListener(new OnClickListener()
   {
             @Override
             public void onClick(View v)
             {
                // do something
             } 
   }); 
   return view;
}
174
Raghunandan

Une autre option peut être que votre fragment implémente View.OnClickListener et remplace onClick (View v) dans votre fragment. Si vous avez besoin que votre fragment parle à l'activité, ajoutez simplement une interface avec la ou les méthodes souhaitées et demandez à l'activité de l'implémenter et de la remplacer par la ou les méthodes.

public class FragName extends Fragment implements View.OnClickListener { 
    public FragmentCommunicator fComm;
    public ImageButton res1, res2;
    int c;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_test, container, false);
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        try {
            fComm = (FragmentCommunicator) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString()
                    + " must implement FragmentCommunicator");
        }
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        res1 = (ImageButton) getActivity().findViewById(R.id.responseButton1);
        res1.setOnClickListener(this);
        res2 = (ImageButton) getActivity().findViewById(R.id.responseButton2);
        res2.setOnClickListener(this);
    }
    public void onClick(final View v) { //check for what button is pressed
            switch (v.getId()) {
                case R.id.responseButton1:
                  c *= fComm.fragmentContactActivity(2);
                  break;
                case R.id.responseButton2:
                  c *= fComm.fragmentContactActivity(4);
                  break;
                default:
                  c *= fComm.fragmentContactActivity(100);
                  break;
    }
    public interface FragmentCommunicator{
        public int fragmentContactActivity(int b);
    }



public class MainActivity extends FragmentActivity implements FragName.FragmentCommunicator{
    int a = 10;
    //variable a is update by fragment. ex. use to change textview or whatever else you'd like.

    public int fragmentContactActivity(int b) {
        //update info on activity here
        a += b;
        return a;
    }
}

http://developer.Android.com/training/basics/firstapp/starting-activity.htmlhttp://developer.Android.com/training/basics/fragments/communicating. html

13
cjayem13

Ce n'est pas un problème, c'est une conception d'Android. Voir ici :

Vous devez concevoir chaque fragment comme un composant d'activité modulaire et réutilisable. En effet, chaque fragment définissant sa propre présentation et son propre comportement avec ses propres rappels de cycle de vie, vous pouvez inclure un fragment dans plusieurs activités. Vous devez donc les concevoir pour les réutiliser et éviter de manipuler directement un fragment à partir d'un autre fragment.

Une solution de contournement possible serait de faire quelque chose comme ceci dans votre MainActivity:

Fragment someFragment;    

...onCreate etc instantiating your fragments

public void myClickMethod(View v){
    someFragment.myClickMethod(v);
}

et ensuite dans votre classe Fragment:

public void myClickMethod(View v){
    switch(v.getid()){
       // Your code here
    }
 } 
6
CzarMatt
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {

    View view = inflater.inflate(R.layout.writeqrcode_main, container, false);
    // Inflate the layout for this fragment

    txt_name = (TextView) view.findViewById(R.id.name);
    txt_usranme = (TextView) view.findViewById(R.id.surname);
    txt_number = (TextView) view.findViewById(R.id.number);
    txt_province = (TextView) view.findViewById(R.id.province);
    txt_write = (EditText) view.findViewById(R.id.editText_write);
    txt_show1 = (Button) view.findViewById(R.id.buttonShow1);

    txt_show1.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Log.e("Onclick","Onclick");

            txt_show1.setVisibility(View.INVISIBLE);
            txt_name.setVisibility(View.VISIBLE);
            txt_usranme.setVisibility(View.VISIBLE);
            txt_number.setVisibility(View.VISIBLE);
            txt_province.setVisibility(View.VISIBLE);
        }
    });
    return view;
}

Ça va !!!!

3
Pong Petrung

Les autres ont déjà indiqué que les méthodes dans onClick sont recherchées dans des activités et non des fragments. Néanmoins, si vous le voulez vraiment, c'est est possible.

Fondamentalement, chaque vue a une balise (probablement nulle). Nous plaçons la balise de la vue racine sur le fragment qui a gonflé cette vue. Ensuite, il est facile de rechercher les parents de la vue et de récupérer le fragment contenant le bouton cliqué. Maintenant, nous découvrons le nom de la méthode et utilisons réflexion pour appeler la même méthode à partir du fragment récupéré. Facile!

dans une classe qui étend 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
}

toutes les activités sont dérivées de la même 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 ...
    }

}

Il doit définir des méthodes pour tous les gestionnaires 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));
    }
}

Et la prochaine aventure sera l’obfuscation de Proguard ...

PS

C’est bien sûr à vous de concevoir votre application de manière à ce que les données résident dans le Modèle plutôt que dans Activités ou Fragments (qui sont Contrôleurs à partir du MVC, modèle-vue-contrôleur point de vue). Le View correspond à ce que vous définissez via XML, plus les classes de vues personnalisées (si vous les définissez, la plupart des gens ne font que réutiliser ce qui est déjà). Une règle de base: si certaines données doivent absolument survivre au tour de l'écran, elles appartiennent à Model.

3