Recibir resultado de DialogFragment


Estoy usando DialogFragments para varias cosas: elegir elemento de la lista, ingresar texto.

¿Cuál es la mejor manera de devolver un valor (es decir, una cadena o un elemento de una lista) a la actividad/fragmento de llamada?

Actualmente estoy haciendo que la actividad que llama implemente DismissListener y dándole al DialogFragment una referencia a la actividad. El Diálogo entonces llama al método OnDimiss en la actividad y la actividad toma el resultado del objeto DialogFragment. Muy desordenado y no funciona en el cambio de configuración (cambio de orientación) ya que el DialogFragment pierde la referencia a la actividad.

Gracias por cualquier ayuda.

Author: ישו אוהב אותך, 2012-06-06

9 answers

Use myDialogFragment.setTargetFragment(this, MY_REQUEST_CODE) desde el lugar donde muestra el diálogo, y luego cuando su diálogo haya terminado, desde él puede llamar a getTargetFragment().onActivityResult(getTargetRequestCode(), ...) e implementar onActivityResult() en el fragmento que lo contiene.

Parece un abuso de onActivityResult(), especialmente porque no involucra actividades en absoluto. Pero lo he visto recomendado por la gente oficial de Google, y tal vez incluso en las demostraciones de api. Creo que es para lo que se agregaron g/setTargetFragment().

 222
Author: Timmmm,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-02-14 14:47:58

Como pueden ver aquí hay una manera muy sencilla de hacerlo.

En su DialogFragment agregue un oyente de interfaz como:

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

Luego, agregue una referencia a ese oyente:

private EditNameDialogListener listener;

Esto se utilizará para "activar" los métodos de escucha, y también para comprobar si la Actividad/Fragmento padre implementa esta interfaz(ver más abajo).

En el Activity/FragmentActivity/Fragment que "llama" el DialogFragment simplemente implementar esta interfaz.

En tu DialogFragment todo lo que necesitas para agregar en el punto donde desea descartar el DialogFragment y devolver el resultado es este:

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

Donde mEditText.getText().toString() es lo que se pasará de nuevo a la llamada Activity.

Tenga en cuenta que si desea devolver algo más, simplemente cambie los argumentos que toma el oyente.

Finalmente, debe comprobar si la interfaz fue realmente implementada por la actividad/fragmento padre:

@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");
    }
}

Esta técnica es muy flexible y permite devolver la llamada con el resultado incluso si su don; no quiere descartar el diálogo por el momento.

 128
Author: Assaf Gamliel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-27 21:27:48

Hay una forma mucho más sencilla de recibir un resultado de un DialogFragment.

Primero, en tu Actividad, Fragmento o FragmentActivity necesitas agregar la siguiente información:

@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.
         }
     }
}

El requestCode es básicamente tu etiqueta int para el DialogFragment al que llamaste, te mostraré cómo funciona esto en un segundo. El resultCode es el código que envías de vuelta desde el DialogFragment indicando lo que ocurrió con tu actividad actual en espera, Fragmento o FragmentActivity.

El el siguiente fragmento de código a ingresar es la llamada al DialogFragment. Un ejemplo está aquí:

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");

Con estas tres líneas estás declarando tu DialogFragment, estableciendo un requestCode (que llamará a onActivityResult (...) una vez que se descarta el diálogo, y luego está mostrando el diálogo. Es así de simple.

Ahora, en su DialogFragment necesita agregar una línea directamente antes de dismiss() para enviar un código de resultado de nuevo a la onActivityResult().

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

Eso es todo. Nota, el código de resultado se define como int resultCode que he establecido en resultCode = 1; en este caso.

Eso es todo, ahora puede enviar el resultado de su DialogFragment a su actividad de llamada, Fragment o FragmentActivity.

Además, parece que esta información se publicó anteriormente, pero no había un ejemplo suficiente dado, así que pensé en proporcionar más detalles.

EDITAR 06.24.2016 Me disculpo por el engaño código anterior. Pero ciertamente no puede recibir el resultado de vuelta a la actividad viendo como la línea:

dialogFrag.setTargetFragment(this, 1);

Establece un objetivo Fragment y no Activity. Así que para hacer esto necesitas usar implementar un InterfaceCommunicator.

En su DialogFragment establezca una variable global

public InterfaceCommunicator interfaceCommunicator;

Crear una función pública para manejarla

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

Luego, cuando esté listo para enviar el código a Activity cuando el DialogFragment haya terminado de ejecutarse, simplemente agregue la línea antes de dismiss(); su DialogFragment:

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

En tu actividad ahora tienes que hacer dos cosas, la primera es eliminar esa línea de código que ya no es aplicable:{[28]]}

dialogFrag.setTargetFragment(this, 1);  

Luego implementa la interfaz y listo. Puedes hacer eso agregando la siguiente línea a la cláusula implements en la parte superior de tu clase:

public class MyClass Activity implements MyDialogFragment.InterfaceCommunicator

Y luego @Override la función en la actividad,

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

Utiliza este método de interfaz como lo haría con el método onActivityResult(). Excepto la interfaz el método es para DialogFragments y el otro es para Fragments.

 45
Author: Brandon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-06-24 13:05:37

Bueno, es demasiado tarde para responder, pero esto es lo que hice para obtener resultados de la DialogFragment. muy similar a la respuesta de @brandon. Aquí estoy llamando DialogFragment desde un fragmento, simplemente coloque este código donde está llamando a su diálogo.

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

Donde categoryDialog es mi DialogFragment que quiero llamar y después de esto en su implementación de dialogfragment coloque este código donde está configurando sus datos en intent. El valor de resultCode es 1 puede configurarlo o usar system Defined.

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

Ahora es es hora de volver al fragmento de llamada e implementar este método. compruebe la validez de los datos o el éxito del resultado si lo desea con resultCode y requestCode en la condición 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();
    }
 16
Author: vikas kumar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-09 08:49:27

Estoy muy sorprendido de ver que nadie ha sugerido el uso de transmisiones locales para DialogFragment a Activity la comunicación! Me parece mucho más simple y más limpio que otras sugerencias. Esencialmente, se registra para su Activity para escuchar las transmisiones y envía las transmisiones locales desde sus instancias DialogFragment. Simple. Para obtener una guía paso a paso sobre cómo configurarlo todo, consulte aquí.

 6
Author: Adil Hussain,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-04 18:20:48

Una manera fácil que encontré fue la siguiente: Implementar este es su DialogFragment,

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

Y luego en la actividad que llamó al Fragmento de Diálogo crear la función apropiada como tal:

 public void onUserSelectValue(String selectedValue) {

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

El Brindis es para mostrar que funciona. Funcionó para mí.

 6
Author: ZeWolfe15,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-12-23 22:44:43

Enfoque diferente, para permitir que un Fragmento se comunique hasta su Actividad :

1) Definir una interfaz pública en el fragmento y crear una variable para él

public OnFragmentInteractionListener mCallback;

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

2) Cast la actividad a la variable mCallback en el fragmento

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

3) Implemente el oyente en su actividad

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

4) Reemplazar el OnFragmentInteraction en la actividad

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

Más información al respecto: https://developer.android.com/training/basics/fragments/communicating.html

 4
Author: lcompare,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-30 19:00:39

En mi caso necesitaba pasar argumentos a un targetFragment. Pero tengo la excepción "Fragmento ya activo". Así que declaré una Interfaz en mi DialogFragment que parentFragment implementó. Cuando parentFragment inicia un DialogFragment, se establece como TargetFragment. Entonces en DialogFragment llamé

 ((Interface)getTargetFragment()).onSomething(selectedListPosition);
 1
Author: Lanitka,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-03 08:51:26

Solo para tenerlo como una de las opciones (ya que nadie lo mencionó todavía), podría usar un bus de eventos como Otto. Así que en el diálogo lo haces:

bus.post(new AnswerAvailableEvent(42));

Y haga que su llamante (Actividad o Fragmento) se suscriba a él:

@Subscribe public void answerAvailable(AnswerAvailableEvent event) {
   // TODO: React to the event somehow!
}
 -3
Author: Dennis K,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-09-20 16:18:36