Recevoir le résultat de DialogFragment
j'utilise DialogFragments pour un certain nombre de choses: choisir un élément de la liste, entrer le texte.
Quelle est la meilleure façon de retourner une valeur (c.-à-d. une chaîne ou un élément d'une liste) à l'activité d'appel/fragment?
actuellement je fais l'implémentation de l'activité appelant DismissListener
et je donne au DialogFragment une référence à l'activité. Le dialogue appelle alors la méthode OnDimiss
dans l'activité et l'activité saisit le résultat de L'objet DialogFragment. Très embrouillé et ne fonctionne pas sur le changement de configuration (changement d'orientation) car le fragment de dialogue perd la référence à l'activité.
Merci pour votre aide.
9 réponses
utilisez myDialogFragment.setTargetFragment(this, MY_REQUEST_CODE)
à partir de l'endroit où vous affichez la boîte de dialogue, puis lorsque votre boîte de dialogue est terminée, vous pouvez appeler getTargetFragment().onActivityResult(getTargetRequestCode(), ...)
, et mettre en œuvre onActivityResult()
dans le fragment contenant.
cela ressemble à un abus de onActivityResult()
, d'autant plus qu'il n'implique aucune activité. Mais je l'ai vu recommandé par les gens officiels de google, et peut-être même dans les démonstrations de l'api. Je pense que c'est pour ça que g/setTargetFragment()
a été ajouté.
comme vous pouvez le voir ici il y a une façon très simple de le faire.
dans votre DialogFragment
ajouter un écouteur d'interface comme:
public interface EditNameDialogListener {
void onFinishEditDialog(String inputText);
}
ensuite, ajouter une référence à cet auditeur:
private EditNameDialogListener listener;
ceci sera utilisé pour" activer " la(Les) méthode (s) d'écoute, et aussi pour vérifier si L'activité/Fragment parent implémente cette interface (voir ci-dessous).
dans le Activity
/ FragmentActivity
/ Fragment
que "appelé" le DialogFragment
simplement mettre en œuvre cette interface.
dans votre DialogFragment
tout ce que vous devez ajouter au point où vous souhaitez rejeter le DialogFragment
et retourner le résultat est ceci:
listener.onFinishEditDialog(mEditText.getText().toString());
this.dismiss();
où mEditText.getText().toString()
est ce qui sera transmis à l'appel Activity
.
notez que si vous voulez retourner quelque chose d'autre simplement changer les arguments auditeur prend.
enfin, vous devez vérifier si l'interface a été réellement implémentée par l'activité/fragment parent:
@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");
}
}
cette technique est très flexible et permet de rappeler avec le résultat même si votre don;t veulent rejeter le dialogue juste pour l'instant.
il y a une façon beaucoup plus simple de recevoir un résultat d'un fragment de dialogue.
tout D'abord, dans votre activité, Fragment ou activité de fragment, vous devez ajouter les informations suivantes:
@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.
}
}
}
le requestCode
est fondamentalement votre étiquette int pour le DialogFragment que vous avez appelé, je vais montrer comment cela fonctionne dans une seconde. Le resultCode est le code que vous renvoyez depuis le DialogFragment et qui indique votre activité d'attente en cours., Fragment, ou Fragmentactivité ce qui s'est passé.
Le prochain morceau de code est l'appel à la DialogFragment. Un exemple est ici:
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");
avec ces trois lignes vous déclarez votre DialogFragment, en définissant un requestCode (qui appellera l'onActivityResult (...) une fois que la boîte de dialogue est désactivée, et vous montrez alors la boîte de dialogue. C'est aussi simple que cela.
maintenant, dans votre fragment de dialogue vous devez juste ajouter une ligne directement avant le dismiss()
de sorte que vous renvoyez un résultatcode à onActivityResult().
getTargetFragment().onActivityResult(getTargetRequestCode(), resultCode, getActivity().getIntent());
dismiss();
C'est ça. Note, le code de résultat est défini comme int resultCode
que j'ai mis à resultCode = 1;
dans ce cas.
C'est tout, vous pouvez maintenant renvoyer le résultat de votre fragment de dialogue à votre activité d'appel, Fragment, ou FragmentActivity.
aussi, il semble que cette information a été affichée précédemment, mais il n'y avait pas d'exemple suffisant donné alors j'ai pensé que je pourrais fournir plus de détails.
EDIT 06.24.2016 Je m'excuse pour le code trompeur ci-dessus. Mais vous ne pouvez certainement pas recevoir le résultat de nouveau à l'activité vu que la ligne:
dialogFrag.setTargetFragment(this, 1);
fixe un objectif Fragment
et non Activity
. Donc, pour ce faire, vous devez utiliser un InterfaceCommunicator
.
Dans votre DialogFragment
définissez une variable globale
public InterfaceCommunicator interfaceCommunicator;
Créer une fonction publique à gérer
public interface InterfaceCommunicator {
void sendRequestCode(int code);
}
ensuite, lorsque vous êtes prêt à renvoyer le code au Activity
lorsque le DialogFragment
est exécuté, vous ajoutez simplement la ligne avant vous dismiss();
votre DialogFragment
:
interfaceCommunicator.sendRequestCode(1); // the parameter is any int code you choose.
dans votre activité Maintenant vous devez faire deux choses, la première est de supprimer cette ligne de code qui n'est pas plus applicable:
dialogFrag.setTargetFragment(this, 1);
alors implémentez l'interface et vous avez terminé. Vous pouvez le faire en ajoutant la ligne suivante à la clause implements
en haut de votre classe:
public class MyClass Activity implements MyDialogFragment.InterfaceCommunicator
puis @Override
la fonction dans l'activité,
@Override
public void sendRequestCode(int code) {
// your code here
}
Vous utilisez cette méthode d'interface comme le onActivityResult()
la méthode. Sauf que la méthode d'interface est pour DialogFragments
et le l'autre est pour Fragments
.
il est peut-être trop tard pour répondre, Mais voici ce que j'ai fait pour obtenir les résultats du DialogFragment
. très similaire à la réponse de @brandon.
Ici j'appelle DialogFragment
à partir d'un fragment, il suffit de placer ce code où vous appelez votre dialogue.
FragmentManager fragmentManager = getFragmentManager();
categoryDialog.setTargetFragment(this,1);
categoryDialog.show(fragmentManager, "dialog");
où categoryDialog
est mon DialogFragment
que je veux appeler et après cela dans votre mise en œuvre de dialogfragment
placez ce code où vous définissez vos données en intention. La valeur de resultCode
est 1 vous pouvez le définir ou utiliser le système défini.
Intent intent = new Intent();
intent.putExtra("listdata", stringData);
getTargetFragment().onActivityResult(getTargetRequestCode(), resultCode, intent);
getDialog().dismiss();
maintenant il est temps de revenir au fragment appelant et d'implémenter cette méthode. vérifiez la validité des données ou le succès du résultat si vous voulez avec resultCode
et requestCode
dans la condition if.
@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();
}
je suis très surpris de voir que personne n'a suggéré d'utiliser des émissions locales pour les communications DialogFragment
à Activity
! Je trouve que c'est tellement plus simple et plus propre que les autres suggestions. Essentiellement, vous vous inscrivez à votre Activity
pour écouter les diffusions et vous envoyez les diffusions locales à partir de vos instances DialogFragment
. Simple. Pour un guide étape par étape sur la façon de tout mettre en place, voir ici .
L'un des moyens faciles que j'ai trouvé était le suivant: Implémenter ceci est votre outil de dialogue,
CallingActivity callingActivity = (CallingActivity) getActivity();
callingActivity.onUserSelectValue("insert selected value here");
dismiss();
et ensuite dans l'activité qui a appelé le Fragment de dialogue Créer la fonction appropriée en tant que telle:
public void onUserSelectValue(String selectedValue) {
// TODO add your implementation.
Toast.makeText(getBaseContext(), ""+ selectedValue, Toast.LENGTH_LONG).show();
}
le Toast est de montrer que ça marche. A travaillé pour moi.
approche différente, pour permettre à un Fragment de communiquer jusqu'à son activité :
1) définir une interface publique dans le fragment et créer une variable pour elle
public OnFragmentInteractionListener mCallback;
public interface OnFragmentInteractionListener {
void onFragmentInteraction(int id);
}
2) Fonte de l'activité pour l'mCallback variable dans le fragment
try {
mCallback = (OnFragmentInteractionListener) getActivity();
} catch (Exception e) {
Log.d(TAG, e.getMessage());
}
3) mettre en œuvre l'auditeur dans votre activité
public class MainActivity extends AppCompatActivity implements DFragment.OnFragmentInteractionListener {
//your code here
}
4) outrepasser L'OnFragmentInteraction dans l'activité
@Override
public void onFragmentInteraction(int id) {
Log.d(TAG, "received from fragment: " + id);
}
Plus d'info sur lui: https://developer.android.com/training/basics/fragments/communicating.html
dans mon cas, j'ai dû passer des arguments à un fragmentcible. Mais j'ai l'exception "Fragment déjà actif". J'ai donc déclaré une Interface dans mon DialogFragment que parentFragment implémentait. Lorsque parentFragment a commencé un DialogFragment , il s'est défini comme TargetFragment. Puis dans DialogFragment j'ai appelé
((Interface)getTargetFragment()).onSomething(selectedListPosition);
juste pour l'avoir comme une des options (puisque personne ne l'a mentionné encore) - vous pourriez utiliser un bus d'événement comme Otto. Donc dans le dialogue vous faites:
bus.post(new AnswerAvailableEvent(42));
et que votre interlocuteur (activité ou Fragment) y souscrive:
@Subscribe public void answerAvailable(AnswerAvailableEvent event) {
// TODO: React to the event somehow!
}