it-swarm.com.de

Erhalten Sie das Ergebnis von DialogFragment

Ich benutze DialogFragments für eine Reihe von Dingen: Auswählen eines Elements aus der Liste, Eingeben von Text. 

Was ist der beste Weg, um einen Wert (d. H. Eine Zeichenfolge oder ein Element aus einer Liste) an die aufrufende Aktivität/das aufrufende Fragment zurückzugeben? 

Derzeit mache ich die aufrufende Aktivität DismissListener und gebe dem DialogFragment einen Verweis auf die Aktivität. Der Dialog ruft dann die OnDimiss-Methode in der Aktivität auf und die Aktivität holt das Ergebnis vom DialogFragment-Objekt. Sehr chaotisch und funktioniert nicht bei Konfigurationsänderungen (Orientierungsänderung), da das DialogFragment den Verweis auf die Aktivität verliert. 

Danke für jede Hilfe.

212
James Cross

Verwenden Sie myDialogFragment.setTargetFragment(this, MY_REQUEST_CODE) von der Stelle aus, an der Sie das Dialogfeld anzeigen, und wenn Ihr Dialog beendet ist, können Sie getTargetFragment().onActivityResult(getTargetRequestCode(), ...) aufrufen und onActivityResult() im enthaltenden Fragment implementieren.

Es scheint ein Missbrauch von onActivityResult() zu sein, zumal es überhaupt keine Aktivitäten beinhaltet. Aber ich habe es von offiziellen Google-Leuten empfohlen, und vielleicht sogar in den API-Demos. Ich denke, dafür wurde g/setTargetFragment() hinzugefügt.

236
Timmmm

Wie Sie sehen, hier gibt es einen sehr einfachen Weg, dies zu tun.

Fügen Sie in Ihrem DialogFragment einen Schnittstellen-Listener hinzu:

public interface EditNameDialogListener {
    void onFinishEditDialog(String inputText);
}

Fügen Sie dann einen Verweis auf diesen Listener hinzu:

private EditNameDialogListener listener;

Dies wird verwendet, um die Listener-Methode (en) zu "aktivieren" und um zu überprüfen, ob die übergeordnete Aktivität/Fragment diese Schnittstelle implementiert (siehe unten).

In der Activity/FragmentActivity/Fragment, die die DialogFragment "aufgerufen" hat, implementieren Sie diese Schnittstelle einfach.

In Ihrem DialogFragment müssen Sie alles hinzufügen, wo Sie das DialogFragment abweisen möchten, und das Ergebnis lautet wie folgt:

listener.onFinishEditDialog(mEditText.getText().toString());
this.dismiss();

Wo mEditText.getText().toString() ist, wird an den aufrufenden Activity zurückgegeben.

Wenn Sie etwas anderes zurückgeben möchten, ändern Sie einfach die Argumente, die der Listener übernimmt.

Zum Schluss sollten Sie prüfen, ob die Schnittstelle tatsächlich von der übergeordneten Aktivität/dem übergeordneten Fragment implementiert wurde:

@Override
public void onAttach(Context context) {
    super.onAttach(context);
    // Verify that the Host activity implements the callback interface
    try {
        // Instantiate the EditNameDialogListener so we can send events to the Host
        listener = (EditNameDialogListener) context;
    } catch (ClassCastException e) {
        // The activity doesn't implement the interface, throw exception
        throw new ClassCastException(context.toString()
                + " must implement EditNameDialogListener");
    }
}

Diese Technik ist sehr flexibel und ermöglicht das Rückrufen mit dem Ergebnis, auch wenn Sie den Dialog noch nicht beenden möchten.

129
Assaf Gamliel

Es ist viel einfacher, ein Ergebnis von einem DialogFragment zu erhalten.

Zunächst müssen Sie in Ihre Aktivität, Ihr Fragment oder Ihre Fragmentaktivität die folgenden Informationen hinzufügen:

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    // Stuff to do, dependent on requestCode and resultCode
    if(requestCode == 1) { // 1 is an arbitrary number, can be any int
         // This is the return result of your DialogFragment
         if(resultCode == 1) { // 1 is an arbitrary number, can be any int
              // Now do what you need to do after the dialog dismisses.
         }
     }
}

requestCode ist im Grunde Ihr int-Label für das von Ihnen aufgerufene DialogFragment. Ich zeige Ihnen, wie das in einer Sekunde funktioniert. Der resultCode ist der Code, den Sie vom DialogFragment zurückschicken, um Ihre aktuellen wartenden Aktivitäten, Fragmente oder FragmentActivity mitzuteilen, was passiert ist.

Der nächste Code, den Sie eingeben müssen, ist der Aufruf von DialogFragment. Ein Beispiel ist hier:

DialogFragment dialogFrag = new MyDialogFragment();
// This is the requestCode that you are sending.
dialogFrag.setTargetFragment(this, 1);     
// This is the tag, "dialog" being sent.
dialogFrag.show(getFragmentManager(), "dialog");

Mit diesen drei Zeilen deklarieren Sie Ihr DialogFragment und setzen einen requestCode (der onActivityResult (...) aufruft, sobald der Dialog geschlossen wird, und Sie zeigen dann den Dialog an. So einfach ist das.

Jetzt müssen Sie in Ihrem DialogFragment einfach eine Zeile direkt vor der dismiss() hinzufügen, damit Sie einen resultCode an onActivityResult () zurücksenden.

getTargetFragment().onActivityResult(getTargetRequestCode(), resultCode, getActivity().getIntent());
dismiss();

Das ist es. Der resultCode ist definiert als int resultCode, den ich in diesem Fall auf resultCode = 1; gesetzt habe. 

Nun können Sie das Ergebnis Ihres DialogFragments an Ihre aufrufende Aktivität, Ihr Fragment oder Ihre FragmentActivity zurücksenden.

Es sieht auch so aus, als ob diese Informationen zuvor gepostet wurden, aber es gab kein ausreichendes Beispiel, also dachte ich, ich würde mehr Details geben.

EDIT 24.06.2016 Ich entschuldige mich für den irreführenden Code oben. Aber Sie können das Ergebnis ganz sicher nicht wieder in die Aktivität aufnehmen, da die Zeile:

dialogFrag.setTargetFragment(this, 1);

legt ein Ziel Fragment und nicht Activity fest. Zu diesem Zweck müssen Sie eine InterfaceCommunicator implementieren. 

Legen Sie in Ihrem DialogFragment eine globale Variable fest

public InterfaceCommunicator interfaceCommunicator;

Erstellen Sie eine öffentliche Funktion, um damit umzugehen

public interface InterfaceCommunicator {
    void sendRequestCode(int code);
}

Wenn Sie dann bereit sind, den Code an Activity zurückzuschicken, wenn die DialogFragment-Ausführung abgeschlossen ist, fügen Sie einfach die Zeile vor dismiss(); Ihrem DialogFragment hinzu:

interfaceCommunicator.sendRequestCode(1); // the parameter is any int code you choose.

In Ihrer Aktivität müssen Sie nun zwei Dinge tun. Zuerst müssen Sie die eine Codezeile entfernen, die nicht mehr anwendbar ist:

dialogFrag.setTargetFragment(this, 1);  

Dann implementieren Sie die Schnittstelle und Sie sind fertig. Sie können dies tun, indem Sie der implements-Klausel ganz oben in Ihrer Klasse die folgende Zeile hinzufügen:

public class MyClass Activity implements MyDialogFragment.InterfaceCommunicator

Und dann @Override die Funktion in der Aktivität, 

@Override
public void sendRequestCode(int code) {
    // your code here
}

Sie verwenden diese Schnittstellenmethode genau wie die onActivityResult()-Methode. Außer die Schnittstellenmethode ist für DialogFragments und die andere für Fragments.

45
Brandon

Nun, es ist zu spät, um antworten zu können, aber hier habe ich getan, um Ergebnisse aus DialogFragment zu erhalten. Die Antwort von @ brandon ist sehr ähnlich. Hier rufe ich DialogFragment von einem Fragment aus. Platzieren Sie diesen Code einfach dort, wo Sie Ihren Dialog aufrufen.

FragmentManager fragmentManager = getFragmentManager();
            categoryDialog.setTargetFragment(this,1);
            categoryDialog.show(fragmentManager, "dialog");

wobei categoryDialog mein DialogFragment ist, den ich anrufen möchte, und danach in Ihrer Implementierung von dialogfragment diesen Code an den Ort setzt, an dem Sie Ihre Daten vorsätzlich festlegen. Der Wert von resultCode ist 1. Sie können ihn festlegen oder das System Defined verwenden.

            Intent intent = new Intent();
            intent.putExtra("listdata", stringData);
            getTargetFragment().onActivityResult(getTargetRequestCode(), resultCode, intent);
            getDialog().dismiss();

jetzt ist es an der Zeit, zum aufrufenden Fragment zurückzukehren und diese Methode zu implementieren. Überprüfen Sie die Gültigkeit der Daten oder das Ergebnis, wenn Sie mit resultCode und requestCode in der if-Bedingung arbeiten möchten. 

 @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);        
        //do what ever you want here, and get the result from intent like below
        String myData = data.getStringExtra("listdata");
Toast.makeText(getActivity(),data.getStringExtra("listdata"),Toast.LENGTH_SHORT).show();
    }
18
vikas kumar

Eine einfache Möglichkeit, die ich gefunden habe, war die folgende: Implementiere dies ist dein dialogFragment,

  CallingActivity callingActivity = (CallingActivity) getActivity();
  callingActivity.onUserSelectValue("insert selected value here");
  dismiss();

Und dann erstellen Sie in der Aktivität, die das Dialogfragment aufgerufen hat, die entsprechende Funktion als solche:

 public void onUserSelectValue(String selectedValue) {

        // TODO add your implementation.
      Toast.makeText(getBaseContext(), ""+ selectedValue, Toast.LENGTH_LONG).show();
    }

Der Toast soll zeigen, dass es funktioniert. Arbeitete für mich.

7
ZeWolfe15

Ein anderer Ansatz, damit ein Fragment bis zu seiner Activity kommunizieren kann:

1) Definiert eine öffentliche Schnittstelle im Fragment und erstellt eine Variable dafür

public OnFragmentInteractionListener mCallback;

public interface OnFragmentInteractionListener {
    void onFragmentInteraction(int id);
}

2) Wandelt die Aktivität in die mCallback-Variable im Fragment um 

try {
    mCallback = (OnFragmentInteractionListener) getActivity();
} catch (Exception e) {
    Log.d(TAG, e.getMessage());
}

3) Implementieren Sie den Listener in Ihrer Aktivität

public class MainActivity extends AppCompatActivity implements DFragment.OnFragmentInteractionListener  {
     //your code here
}

4) Überschreibt OnFragmentInteraction in der Aktivität

@Override
public void onFragmentInteraction(int id) {
    Log.d(TAG, "received from fragment: " + id);
}

Weitere Informationen dazu: https://developer.Android.com/training/basics/fragments/communicating.html

7
lcompare

Ich bin sehr überrascht zu sehen, dass niemand die Verwendung lokaler Broadcasts für die Kommunikation mit DialogFragment in Activity vorgeschlagen hat! Ich finde es so viel einfacher und sauberer als andere Vorschläge. Im Wesentlichen registrieren Sie sich für Ihre Activity, um die Sendungen abzuhören, und Sie senden die lokalen Sendungen von Ihren DialogFragment-Instanzen. Einfach. Eine Schritt-für-Schritt-Anleitung zum Einrichten finden Sie unter hier .

6
Adil Hussain

Oder teilen Sie ViewModel wie hier gezeigt: 

public class SharedViewModel extends ViewModel {
    private final MutableLiveData<Item> selected = new MutableLiveData<Item>();

    public void select(Item item) {
        selected.setValue(item);
    }

    public LiveData<Item> getSelected() {
        return selected;
    }
}


public class MasterFragment extends Fragment {
    private SharedViewModel model;
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        model = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);
        itemSelector.setOnClickListener(item -> {
            model.select(item);
        });
    }
}

public class DetailFragment extends Fragment {
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        SharedViewModel model = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);
        model.getSelected().observe(this, { item ->
           // Update the UI.
        });
    }
}

https://developer.Android.com/topic/libraries/architecture/viewmodel#sharing_data_between_fragments

1
Malachiasz

In meinem Fall musste ich Argumente an ein targetFragment übergeben. Ich bekam aber die Ausnahme "Fragment bereits aktiv". Also habe ich in meinem DialogFragment eine Schnittstelle deklariert, die parentFragment implementiert hat. Wenn parentFragment ein DialogFragment startete, wurde es als TargetFragment festgelegt. Dann habe ich in DialogFragment angerufen 

 ((Interface)getTargetFragment()).onSomething(selectedListPosition);
1
Lanitka

wenn Sie Argumente senden und das Ergebnis vom zweiten Fragment erhalten möchten, können Sie Fragment.setArguments verwenden, um diese Aufgabe auszuführen

static class FirstFragment extends Fragment {
    final Handler mUIHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
            case 101: // receive the result from SecondFragment
                Object result = msg.obj;
                // do something according to the result
                break;
            }
        };
    };

    void onStartSecondFragments() {
        Message msg = Message.obtain(mUIHandler, 101, 102, 103, new Object()); // replace Object with a Parcelable if you want to across Save/Restore
                                                                               // instance
        putParcelable(new SecondFragment(), msg).show(getFragmentManager().beginTransaction(), null);
    }
}

static class SecondFragment extends DialogFragment {
    Message mMsg; // arguments from the caller/FirstFragment

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onViewCreated(view, savedInstanceState);
        mMsg = getParcelable(this);
    }

    void onClickOK() {
        mMsg.obj = new Object(); // send the result to the caller/FirstFragment
        mMsg.sendToTarget();
    }
}

static <T extends Fragment> T putParcelable(T f, Parcelable arg) {
    if (f.getArguments() == null) {
        f.setArguments(new Bundle());
    }
    f.getArguments().putParcelable("extra_args", arg);
    return f;
}
static <T extends Parcelable> T getParcelable(Fragment f) {
    return f.getArguments().getParcelable("extra_args");
}
0
Yessy

In Kotlin

// My DialogFragment

klasse FiltroDialogFragment: DialogFragment (), View.OnClickListener {

var listener: InterfaceCommunicator? = null

override fun onAttach(context: Context?) {
    super.onAttach(context)
    listener = context as InterfaceCommunicator
}

interface InterfaceCommunicator {
    fun sendRequest(value: String)
}   

override fun onClick(v: View) {
    when (v.id) {
        R.id.buttonOk -> {    
    //You can change value             
            listener?.sendRequest('send data')
            dismiss()
        }

    }
}

}

// Meine Aktivität

klasse MyActivity: AppCompatActivity (), FiltroDialogFragment.InterfaceCommunicator {

override fun sendRequest(value: String) {
// :)
Toast.makeText(this, value, Toast.LENGTH_LONG).show()
}

}

Ich hoffe, es dient, wenn Sie es verbessern können, bearbeiten Sie es bitte. Mein Englisch ist nicht sehr gut

0
Irvin Joao