¿Mostrar diálogo de Fragment?
-
28-10-2019 - |
Pregunta
Tengo algunos fragmentos que necesitan mostrar un diálogo regular. En estos diálogos, el usuario puede elegir una respuesta sí/no, y luego el fragmento debe comportarse en consecuencia.
Ahora el Fragment
La clase no tiene un onCreateDialog()
método para anular, así que supongo que tengo que implementar los diálogos afuera, en la contención Activity
. Está bien, pero luego el Activity
Necesita informar la respuesta elegida de alguna manera al fragmento. Por supuesto, podría usar un patrón de devolución de llamada aquí, por lo que el fragmento se registra en el Activity
con una clase de oyente, y la actividad informaría la respuesta a través de eso, o algo así.
Pero esto parece ser un gran desastre para una tarea simple, ya que muestra un diálogo "simple" sí-no en un fragmento. Además, de esta manera mi Fragment
sería menos autónomo.
¿Hay alguna forma más limpia de hacer esto?
Editar:
La respuesta a esta pregunta realmente no explica en detalle cómo se deben usar fragmentos de diálogo para mostrar diálogos de fragmentos. Entonces Afaik, el camino a seguir es:
- Muestra un fragmento.
- Cuando sea necesario, instanciar un dialogfragment.
- Establezca el fragmento original como el objetivo de este diálogo, con
.setTargetFragment()
. - Muestre el DialogFragment con .show () del fragmento original.
- Cuando el usuario elija alguna opción en este DialogFragment, notifique al fragmento original sobre esta selección (por ejemplo, el usuario hizo clic en 'Sí'), puede obtener la referencia del fragmento original con .GetTarget ().
- Descarte el dialogfragment.
Solución
Deberías usar un Fragmento de diálogo en cambio.
Otros consejos
Debo dudar con cautela de la respuesta previamente aceptada de que usar un dialogfragment es la mejor opción. El propósito (primario) previsto del fragmento de diálogo parece ser mostrar fragmentos que son diálogos mismos, no para mostrar fragmentos que tener diálogo para mostrar.
Creo que usar la actividad del fragmento para mediar entre el diálogo y el fragmento es la opción preferible.
Aquí hay un ejemplo completo de un dialogfragment de sí/no:
La clase:
public class SomeDialog extends DialogFragment {
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
return new AlertDialog.Builder(getActivity())
.setTitle("Title")
.setMessage("Sure you wanna do this!")
.setNegativeButton(android.R.string.no, new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// do nothing (will close dialog)
}
})
.setPositiveButton(android.R.string.yes, new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// do something
}
})
.create();
}
}
Para comenzar el diálogo:
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
// Create and show the dialog.
SomeDialog newFragment = new SomeDialog ();
newFragment.show(ft, "dialog");
También puede dejar que la clase implementa OnClickListener y usarlo en lugar de oyentes integrados.
Devolución de llamada a la actividad
Si desea implementar la devolución de llamada, así es como se hace en su actividad:
YourActivity extends Activity implements OnFragmentClickListener
y
@Override
public void onFragmentClick(int action, Object object) {
switch(action) {
case SOME_ACTION:
//Do your action here
break;
}
}
La clase de devolución de llamada:
public interface OnFragmentClickListener {
public void onFragmentClick(int action, Object object);
}
Luego, para realizar una devolución de llamada desde un fragmento, debe asegurarse de que el oyente esté adjunto así:
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
mListener = (OnFragmentClickListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString() + " must implement listeners!");
}
}
Y una devolución de llamada se realiza así:
mListener.onFragmentClick(SOME_ACTION, null); // null or some important object as second parameter.
Para mí, fue lo siguiente
MyFragment:
public class MyFragment extends Fragment implements MyDialog.Callback
{
ShowDialog activity_showDialog;
@Override
public void onAttach(Activity activity)
{
super.onAttach(activity);
try
{
activity_showDialog = (ShowDialog)activity;
}
catch(ClassCastException e)
{
Log.e(this.getClass().getSimpleName(), "ShowDialog interface needs to be implemented by Activity.", e);
throw e;
}
}
@Override
public void onClick(View view)
{
...
MyDialog dialog = new MyDialog();
dialog.setTargetFragment(this, 1); //request code
activity_showDialog.showDialog(dialog);
...
}
@Override
public void accept()
{
//accept
}
@Override
public void decline()
{
//decline
}
@Override
public void cancel()
{
//cancel
}
}
MyDialog:
public class MyDialog extends DialogFragment implements View.OnClickListener
{
private EditText mEditText;
private Button acceptButton;
private Button rejectButton;
private Button cancelButton;
public static interface Callback
{
public void accept();
public void decline();
public void cancel();
}
public MyDialog()
{
// Empty constructor required for DialogFragment
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View view = inflater.inflate(R.layout.dialogfragment, container);
acceptButton = (Button) view.findViewById(R.id.dialogfragment_acceptbtn);
rejectButton = (Button) view.findViewById(R.id.dialogfragment_rejectbtn);
cancelButton = (Button) view.findViewById(R.id.dialogfragment_cancelbtn);
acceptButton.setOnClickListener(this);
rejectButton.setOnClickListener(this);
cancelButton.setOnClickListener(this);
getDialog().setTitle(R.string.dialog_title);
return view;
}
@Override
public void onClick(View v)
{
Callback callback = null;
try
{
callback = (Callback) getTargetFragment();
}
catch (ClassCastException e)
{
Log.e(this.getClass().getSimpleName(), "Callback of this class must be implemented by target fragment!", e);
throw e;
}
if (callback != null)
{
if (v == acceptButton)
{
callback.accept();
this.dismiss();
}
else if (v == rejectButton)
{
callback.decline();
this.dismiss();
}
else if (v == cancelButton)
{
callback.cancel();
this.dismiss();
}
}
}
}
Actividad:
public class MyActivity extends ActionBarActivity implements ShowDialog
{
..
@Override
public void showDialog(DialogFragment dialogFragment)
{
FragmentManager fragmentManager = getSupportFragmentManager();
dialogFragment.show(fragmentManager, "dialog");
}
}
Diseño de DialogFragment:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:orientation="vertical" >
<TextView
android:id="@+id/dialogfragment_textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:layout_centerHorizontal="true"
android:layout_marginBottom="10dp"
android:text="@string/example"/>
<Button
android:id="@+id/dialogfragment_acceptbtn"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:layout_centerHorizontal="true"
android:layout_below="@+id/dialogfragment_textview"
android:text="@string/accept"
/>
<Button
android:id="@+id/dialogfragment_rejectbtn"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_alignLeft="@+id/dialogfragment_acceptbtn"
android:layout_below="@+id/dialogfragment_acceptbtn"
android:text="@string/decline" />
<Button
android:id="@+id/dialogfragment_cancelbtn"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_marginBottom="20dp"
android:layout_alignLeft="@+id/dialogfragment_rejectbtn"
android:layout_below="@+id/dialogfragment_rejectbtn"
android:text="@string/cancel" />
<Button
android:id="@+id/dialogfragment_heightfixhiddenbtn"
android:layout_width="200dp"
android:layout_height="20dp"
android:layout_marginTop="10dp"
android:layout_marginBottom="20dp"
android:layout_alignLeft="@+id/dialogfragment_cancelbtn"
android:layout_below="@+id/dialogfragment_cancelbtn"
android:background="@android:color/transparent"
android:enabled="false"
android:text=" " />
</RelativeLayout>
Como el nombre dialogfragment_heightfixhiddenbtn
muestra que no pude encontrar una manera de arreglar que la altura del botón inferior se cortó por la mitad a pesar de decir wrap_content
, así que agregué un botón oculto para "cortar" por la mitad. Perdón por el hack.
public void showAlert(){
AlertDialog.Builder alertDialog = new AlertDialog.Builder(getActivity());
LayoutInflater inflater = getActivity().getLayoutInflater();
View alertDialogView = inflater.inflate(R.layout.test_dialog, null);
alertDialog.setView(alertDialogView);
TextView textDialog = (TextView) alertDialogView.findViewById(R.id.text_testDialogMsg);
textDialog.setText(questionMissing);
alertDialog.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
alertDialog.show();
}
donde .test_dialog es de XML personalizado
Yo mismo soy un principiante y, sinceramente, no pude encontrar una respuesta satisfactoria que pueda entender o implementar.
Así que aquí hay un enlace externo que realmente me ayudé a lograr lo que quería. Es muy sencillo y fácil de seguir también.
http://www.helloandroid.com/tutorials/how-display-custom-dialog-your-android-application
Esto es lo que intenté lograr con el código:
Tengo una MainActividad que alberga un fragmento. Quería que apareciera un diálogo en la parte superior del diseño para solicitar la entrada del usuario y luego procesar la entrada en consecuencia.Ver una captura de pantalla
Esto es lo que se ve el OnCreateView de mi fragmento
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_home_activity, container, false);
Button addTransactionBtn = rootView.findViewById(R.id.addTransactionBtn);
addTransactionBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Dialog dialog = new Dialog(getActivity());
dialog.setContentView(R.layout.dialog_trans);
dialog.setTitle("Add an Expense");
dialog.setCancelable(true);
dialog.show();
}
});
Espero que te ayude
Avísame si hay alguna confusión. :)
public static void OpenDialog (Activity activity, DialogFragment fragment){
final FragmentManager fm = ((FragmentActivity)activity).getSupportFragmentManager();
fragment.show(fm, "tag");
}