wake-up-neo.com

Übergeben eines Listeners an ein benutzerdefiniertes Fragment in Android

Ich erstelle einen View-Pager in meiner App und verwende eine Klasse, die Fragment erweitert. Wenn ich eine Instanz erstelle, kann ich alle Elemente (ein Bild, Text usw.) übergeben und mit dem Bundle speichern, um sie in onCreate zu verwenden. Ich kann jedoch keinen Listener für die Schaltfläche im Fragment speichern. Hier ist meine Klasse:

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;

}

Wie kann ich also den Listener, den ich in der newInstance bekomme, speichern, um ihn der Schaltfläche in der onCreateView-Methode hinzuzufügen?

Danke für die Hilfe.

Sie können einen Rückruf in Ihrer Fragment verwenden:

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();
            }
        });
    }
}

und implementieren Sie diese neue Schnittstelle in Ihrem übergeordneten Element Activity

Ich nehme an, Sie möchten Fragment mit verschiedenen Hörern wiederverwenden. Daher ist Ihr Ansatz nicht ideal, da Sie Bundle nicht dafür verwenden können. Ein besserer Ansatz wäre die Verwendung des Callback-Entwurfsmusters, z.

public class RegWizardFragmentInfo extends Fragment {

    public interface RegWizardCallback {
        void onClick();
    }
}

Ihr Activity würde diese Schnittstelle implementieren. Da Fragment nur in einer Aktivität lebt, können Sie die Callback-Instanz mithilfe der Lebenszyklusmethode onAttach() von ihr abrufen. Es würde so aussehen

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();
    }
}

Damit können Sie einfach callback.onClick im Listener des Buttons aufrufen.

3
Murat Karagöz

Die anderen Antworten weisen den Listener in onAttach zu. Während dies funktioniert, muss die aufrufende Activity (und nicht etwa eine anonyme Klasse) Ihre Schnittstelle implementieren. Darüber hinaus müssen Sie die Context, die Sie in onAttach erhalten haben, in eine Instanz Ihres Interfaces umwandeln, was Abstürze verursachen kann. Sie können stattdessen eine Methode erstellen, um den Listener in Ihrer Fragment festzulegen:

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... */
}

Ich kann mir drei Nachteile dieses Ansatzes vorstellen:

  1. Sie müssen jedes Mal eine zusätzliche Methode aufrufen, wenn Sie die Fragment instanziieren möchten.
  2. Sie können nicht garantieren, dass mListener jederzeit gesetzt ist. Möglicherweise müssen Sie Ihren Fragment-Code mit Nullprüfungen pflegen.
  3. Sie müssen darauf achten, dass der Listener nach den Lebenszyklusereignissen wie der Bildschirmdrehung festgelegt bleibt.
2
Jack Meister