web-dev-qa-db-fra.com

Passer un auditeur à un fragment personnalisé sous Android

Je crée un pager de vue dans mon application et j'utilise une classe qui étend Fragment. Lorsque je crée une instance, je peux transmettre tous les éléments (une image, du texte, etc.) et les stocker dans l’ensemble pour l’utiliser dans onCreate. Mais je ne peux pas stocker d'auditeur pour le bouton dans le fragment. Voici ma classe:

public class RegWizardFragmentInfo extends Fragment {

private static final String IMAGE = "image";
private static final String TEXT = "text";
private static final String BUTTON = "buttonText";
private View.OnClickListener buttonCallBack;

private Button button;
private int image;
private int text;
private int buttonText;


public RegWizardFragmentInfo newInstance(int image, int text, int buttonText, View.OnClickListener callback) {

    RegWizardFragmentInfo fragment = new RegWizardFragmentInfo();
    Bundle bundle = new Bundle();
    bundle.putInt(IMAGE, image);
    bundle.putInt(BUTTON, buttonText);
    bundle.putInt(TEXT, text);
    fragment.setArguments(bundle);
    fragment.setRetainInstance(true);
    return fragment;

}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    super.onActivityCreated(savedInstanceState);
    this.image = getArguments().getInt(IMAGE);
    this.text = (getArguments() != null) ? getArguments().getInt(TEXT)
            : -1;
    this.buttonText = (getArguments() != null) ? getArguments().getInt(BUTTON)
            : -1;
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    ViewGroup rootView = (ViewGroup) inflater.inflate(
            R.layout.fragment, container, false);
    //Extract all the views and add the image and texts

    return rootView;

}

Alors, comment puis-je stocker l'écouteur que j'ai dans l'instance newInstance pour l'ajouter au bouton de la méthode onCreateView?

Merci pour l'aide.

Vous pouvez utiliser un rappel dans votre Fragment:

public class RegWizardFragmentInfo extends Fragment {

    private Button button;

    private OnClickCallback callback;

    public interface OnClickCallback {
        void onClick();
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        callback = (OnClickCallback) context;
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
                             @Nullable Bundle savedInstanceState) {
        return super.onCreateView(inflater, container, savedInstanceState);

        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                callback.onClick();
            }
        });
    }
}

et implémenter cette nouvelle interface dans votre parent Activity

6

Je suppose que vous voulez réutiliser la Fragment avec différents auditeurs. Votre approche n’est donc pas idéale car vous ne pouvez pas utiliser la Bundle pour cela. Une meilleure approche consisterait à utiliser le modèle de conception de rappel, par exemple.

public class RegWizardFragmentInfo extends Fragment {

    public interface RegWizardCallback {
        void onClick();
    }
}

Votre Activity implémenterait cette interface. Etant donné qu'une Fragment ne vit qu'à l'intérieur d'une activité, vous pouvez obtenir l'instance de rappel à l'aide de la méthode de cycle de vie onAttach(). Ça ressemblerait à ça

public class RegWizardFragmentInfo extends Fragment {
    private RegWizardCallback callback;

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

    public interface RegWizardCallback {
        void onClick();
    }
}

Avec cela, vous pouvez simplement appeler callback.onClick dans l'écouteur du bouton.

3
Murat Karagöz

Les autres réponses attribuent l'auditeur dans onAttach. Bien que cela fonctionne, cela nécessite que l'appelant Activity (et non, par exemple, une classe anonyme) implémente votre interface. De plus, cela vous oblige à convertir la Context donnée dans onAttach en une instance de votre interface, ce qui peut provoquer des plantages et est généralement considéré comme une mauvaise forme. Vous pouvez plutôt créer une méthode pour définir le programme d'écoute dans votre Fragment:

public class RegWizardFragmentInfo extends Fragment {

    private OnClickListener mListener;

    public interface OnClickListener {
        void onClick();
    }

    /**
     * Call at any time after this fragment has been constructed.
     */
    public void setListener(OnClickListener listener) {
        mListener = listener;
    }

    /* ...other stuff... */
}

Je peux penser à trois inconvénients à cette approche:

  1. Vous devez appeler une méthode supplémentaire chaque fois que vous souhaitez instancier la Fragment.
  2. Vous ne pouvez pas garantir que mListener est défini à tout moment. Vous devrez peut-être pimenter votre code Fragment avec des contrôles nuls.
  3. Vous devez veiller à ce que l'écouteur reste défini après des événements de cycle de vie tels que la rotation d'écran.
2
Jack Meister