from - fullscreen dialogfragment android
Recibe el resultado de DialogFragment (11)
¡Estoy muy sorprendido de ver que nadie ha sugerido usar transmisiones locales para la DialogFragment
de DialogFragment
to Activity
! Me parece que es mucho más simple y más limpio que otras sugerencias. Esencialmente, te registras en tu Activity
para escuchar las transmisiones y envías las transmisiones locales desde tus instancias de DialogFragment
. Sencillo. Para obtener una guía paso a paso sobre cómo configurarlo todo, consulte here .
Estoy utilizando DialogFragments para varias cosas: elegir un 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 de llamada implemente DismissListener
y le ofrezco al DialogFragment una referencia a la actividad El diálogo luego 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 DialogFragment pierde la referencia a la actividad.
Gracias por cualquier ayuda.
Como puedes ver here hay una manera muy simple de hacerlo.
En su DialogFragment
agregue un escucha 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 verificar si la actividad / fragmento principal implementa esta interfaz (ver más abajo).
En Activity
/ FragmentActivity
/ Fragment
que "llamó" a DialogFragment
simplemente implementa esta interfaz.
En su DialogFragment
todo lo que necesita agregar en el punto donde desea descartar DialogFragment
y devolver el resultado es este:
listener.onFinishEditDialog(mEditText.getText().toString());
this.dismiss();
Donde mEditText.getText().toString()
es lo que se devolverá a la Activity
llamada.
Tenga en cuenta que si desea devolver algo más, simplemente cambie los argumentos que toma el oyente.
Finalmente, debe verificar si la interfaz fue implementada realmente por la actividad / fragmento principal:
@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 volver a llamar con el resultado incluso si aún no desea cerrar el diálogo.
En Kotlin
// My DialogFragment
clase 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()
}
}
}
}
// Mi actividad
clase MyActivity: AppCompatActivity (), FiltroDialogFragment.InterfaceCommunicator {
override fun sendRequest(value: String) {
// :)
Toast.makeText(this, value, Toast.LENGTH_LONG).show()
}
}
Espero que sirva, si puedes mejorar edítalo por favor. Mi Inglés no es muy bueno
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 inició un DialogFragment, se configuró como TargetFragment. Luego en DialogFragment llamé
((Interface)getTargetFragment()).onSomething(selectedListPosition);
Enfoque diferente, para permitir que un Fragmento se comunique hasta su Actividad :
1) Defina una interfaz pública en el fragmento y cree una variable para ella
public OnFragmentInteractionListener mCallback;
public interface OnFragmentInteractionListener {
void onFragmentInteraction(int id);
}
2) Convertir la actividad a la variable mCallback en el fragmento
try {
mCallback = (OnFragmentInteractionListener) getActivity();
} catch (Exception e) {
Log.d(TAG, e.getMessage());
}
3) Implementa el oyente en tu actividad.
public class MainActivity extends AppCompatActivity implements DFragment.OnFragmentInteractionListener {
//your code here
}
4) Anular 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
Hay una forma mucho más sencilla de recibir un resultado de un DialogFragment.
Primero, en su Actividad, Fragmento o FragmentActivity, debe 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 código de solicitud es básicamente su etiqueta int para el DialogFragment al que llamó, le mostraré cómo funciona esto en un segundo. El código de resultado es el código que envía desde DialogFragment y le informa a su actividad actual en espera, Fragmento o FragmentActivity lo que sucedió.
El siguiente código para ingresar es la llamada al DialogFragment. Un ejemplo es 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á declarando su DialogFragment, configurando un código de solicitud (que llamará onActivityResult (...) una vez que se descarte el cuadro de diálogo, y luego se muestra el cuadro de diálogo. Es así de simple.
Ahora, en su DialogFragment solo necesita agregar una línea directamente antes de la dismiss()
para que envíe un código de resultado al onActivityResult ().
getTargetFragment().onActivityResult(getTargetRequestCode(), resultCode, getActivity().getIntent());
dismiss();
Eso es. Tenga en cuenta que el código de resultado se define como int resultCode
que he establecido como resultCode = 1;
de resultCode = 1;
en este caso.
Eso es todo, ahora puede enviar el resultado de su DialogFragment a su Actividad de llamada, Fragmento o FragmentActivity.
Además, parece que esta información se publicó anteriormente, pero no se dio un ejemplo suficiente, así que pensé en proporcionar más detalles.
EDITAR 06.24.2016 Pido disculpas por el código engañoso anterior. Pero ciertamente no puede recibir el resultado de nuevo en la actividad, ya que se trata de la línea:
dialogFrag.setTargetFragment(this, 1);
establece un Fragment
objetivo y no una Activity
. Entonces para hacer esto necesitas usar implementar un InterfaceCommunicator
.
En tu DialogFragment
establece una variable global
public InterfaceCommunicator interfaceCommunicator;
Crea una función pública para manejarlo.
public interface InterfaceCommunicator {
void sendRequestCode(int code);
}
Luego, cuando esté listo para enviar el código nuevamente a la Activity
cuando se haya ejecutado el DialogFragment
, simplemente agregue la línea antes de dismiss();
su DialogFragment
:
interfaceCommunicator.sendRequestCode(1); // the parameter is any int code you choose.
En su actividad ahora tiene que hacer dos cosas, la primera es eliminar esa línea de código que ya no es aplicable:
dialogFrag.setTargetFragment(this, 1);
Luego implementa la interfaz y ya está todo listo. Puede hacerlo agregando la siguiente línea a la cláusula de implements
en la parte superior de su 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
}
Utilice este método de interfaz como lo haría con el método onActivityResult()
. Excepto que el método de interfaz es para DialogFragments
y el otro es para Fragments
.
O comparte ViewModel como se muestra aquí:
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
Puede que sea demasiado tarde para responder, pero esto es lo que hice para obtener resultados del DialogFragment
. Muy similar a la respuesta de @ Brandon. Aquí estoy llamando a DialogFragment
desde un fragmento, solo 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 de forma intencionada. El valor de resultCode
es 1, puede configurarlo o usar el sistema definido.
Intent intent = new Intent();
intent.putExtra("listdata", stringData);
getTargetFragment().onActivityResult(getTargetRequestCode(), resultCode, intent);
getDialog().dismiss();
ahora es el momento de volver al fragmento de llamada e implementar este método. verifique la validez de los datos o el resultado exitoso si desea con resultCode
y resultCode
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();
}
Solo para tenerlo como una de las opciones (dado que nadie lo ha mencionado aún), puede usar un bus de eventos como Otto. Así que en el diálogo haces:
bus.post(new AnswerAvailableEvent(42));
Y haga que su interlocutor (Actividad o Fragmento) se suscriba:
@Subscribe public void answerAvailable(AnswerAvailableEvent event) {
// TODO: React to the event somehow!
}
Una forma fácil que encontré fue la siguiente: Implementar esto es su diálogoFragmento,
CallingActivity callingActivity = (CallingActivity) getActivity();
callingActivity.onUserSelectValue("insert selected value here");
dismiss();
Y luego, en la actividad que llamó Fragmento de diálogo, cree la función apropiada como tal:
public void onUserSelectValue(String selectedValue) {
// TODO add your implementation.
Toast.makeText(getBaseContext(), ""+ selectedValue, Toast.LENGTH_LONG).show();
}
El Toast es para demostrar que funciona. Trabajó para mi.
Use myDialogFragment.setTargetFragment(this, MY_REQUEST_CODE)
desde el lugar donde se muestra el cuadro de diálogo, y luego, cuando finaliza su cuadro de diálogo, desde él puede llamar a getTargetFragment().onActivityResult(getTargetRequestCode(), ...)
onActivityResult()
en el fragmento que 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 agregó g/setTargetFragment()
.