2013-08-24 20 views
5

Próbuję znaleźć sposób ponownego użycia okna dialogowego, które pokazuje dostosowane tytuły, a następnie wysłać przycisk Tak/Nie do funkcji, która uruchomiła okno dialogowe.Jak mogę ponownie użyć AlertDialog dla Tak/Nie na Androidzie?

Mam dwa przyciski: Zapisz i Odrzuć, a oba wywołają okno dialogowe Tak/Nie, jeden z napisem "Czy chcesz zapisać", a drugi "Odmów zmiany?".

Myślę, że moja procedura jest bardzo "brudna", ale myślę, że może działać, ale moim problemem jest zmienna "Widok widoku", nie wiem jak przekazać ją z Aktywności do okna, więc mogę użyj go, aby przywołać funkcję, która uruchomiła Dialog.

Dzięki z góry, HerniHdez

.java mojej działalności (fragment z nim)

public void open_HH_Fragment_YesNo(View view, String aux_title, String aux_function) 
{ 
    Bundle bundle=new Bundle(); 
    bundle.putString("setMessage", aux_title); 
    bundle.putString("callingFunction", aux_function); 

    DialogFragment newFragment = new HH_Fragment_YesNo(); 
    newFragment.setArguments(bundle); 
    newFragment.show(getSupportFragmentManager(), "HH_Fragment_YesNo"); 
} 

public void SaveChanges(View view, String aux_YesNo) 
{ 
    if (aux_YesNo == "") 
    { 
     Toast.makeText(this, "Save changes?", Toast.LENGTH_SHORT).show(); 
     open_HH_Fragment_YesNo(view, "Save changes?", "SaveChanges"); 
    } 
    else if (aux_YesNo == "Yes") 
    { 
     Toast.makeText(this, "Saving changes", Toast.LENGTH_SHORT).show(); 
    } 
    else if (aux_YesNo == "No") 
    { 
     Toast.makeText(this, "Save Cancelled", Toast.LENGTH_SHORT).show(); 
    } 
} 

public void DismissChanges(View view, String aux_YesNo) 
{ 
    if (aux_YesNo == "") 
    { 
     Toast.makeText(this, "Dismiss changes?", Toast.LENGTH_SHORT).show(); 
     open_HH_Fragment_YesNo(view, "Dismiss changes?", "DismissChanges"); 
    } 
    else if (aux_YesNo == "Yes") 
    { 
     Toast.makeText(this, "Dismiss OK", Toast.LENGTH_SHORT).show(); 
     Close(view); 
    } 
    else if (aux_YesNo == "No") 
    { 
     Toast.makeText(this, "Dismiss Cancelled", Toast.LENGTH_SHORT).show(); 
    } 
} 

// The dialog fragment receives a reference to this Activity through the 
// Fragment.onAttach() callback, which it uses to call the following methods 
// defined by the HH_Fragment_YesNo.YesNoDialogListener interface 
@Override 
public void onDialogPositiveClick(DialogFragment dialog, View view, String aux_function) 
{ 
    // User touched the dialog's positive button 
    Toast.makeText(this, "User clicked on Yes", Toast.LENGTH_SHORT).show(); 

    if (aux_function == "SaveChanges") 
    { 
     SaveChanges(view, "Yes"); 
    } 
    else if (aux_function == "DismissChanges") 
    { 
     DismissChanges(view, "Yes"); 
    } 
} 

@Override 
public void onDialogNegativeClick(DialogFragment dialog, View view, String aux_function) 
{ 
    Toast.makeText(this, "User clicked on NO", Toast.LENGTH_SHORT).show(); 

    if (aux_function == "SaveChanges") 
    { 
     SaveChanges(view, "No"); 
    } 
    else if (aux_function == "DismissChanges") 
    { 
     DismissChanges(view, "No"); 
    } 
} 

.java mojego Dialog (kompletne)

public class HH_Fragment_YesNo extends DialogFragment 
{ 
    @Override 
    public Dialog onCreateDialog(Bundle savedInstanceState) 
    { 
    // Use the Builder class for convenient dialog construction 
    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); 
    String setMessage = getArguments().getString("setMessage"); 
    final String callingFunction = getArguments().getString("callingFuntion"); 

    builder 
     .setMessage(setMessage)            // R.string.dialog_fire_missiles 
     .setPositiveButton("Sí", new DialogInterface.OnClickListener()  // R.string.fire 
     { 
      public void onClick(DialogInterface dialog, int id) 
      { 
       // Exit without saving 
       mListener.onDialogPositiveClick(HH_Fragment_YesNo.this, view, callingFunction); 
      } 
     }) 
     .setNegativeButton("No", new DialogInterface.OnClickListener()  // R.string.cancel 
     { 
      public void onClick(DialogInterface dialog, int id) 
      { 
       // User cancelled the dialog 
       mListener.onDialogNegativeClick(HH_Fragment_YesNo.this, view, callingFunction); 
      } 
     }); 

    // Create the AlertDialog object and return it 
    return builder.create(); 
} 


/* The activity that creates an instance of this dialog fragment must 
* implement this interface in order to receive event callbacks. 
* Each method passes the DialogFragment in case the host needs to query it. */ 
public interface YesNoDialogListener 
{ 
    public void onDialogPositiveClick(DialogFragment dialog, View view, String aux_Function); 
    public void onDialogNegativeClick(DialogFragment dialog, View view, String aux_Function); 
} 


// Use this instance of the interface to deliver action events 
YesNoDialogListener mListener; 


// Override the Fragment.onAttach() method to instantiate the NoticeDialogListener 
@Override 
public void onAttach(Activity activity) 
{ 
    super.onAttach(activity); 
    // Verify that the host activity implements the callback interface 
    try 
    { 
     // Instantiate the NoticeDialogListener so we can send events to the host 
     mListener = (YesNoDialogListener) activity; 
    } 
    catch (ClassCastException e) 
    { 
     // The activity doesn't implement the interface, throw exception 
     throw new ClassCastException(activity.toString() + " must implement NoticeDialogListener"); 
    } 
} 
} 

Odpowiedz

4

Kompletne rozwiązanie Wypróbuj to

1) createa Interfejs

import android.content.DialogInterface; 

public interface AlertMagnatic { 

    public abstract void PositiveMethod(DialogInterface dialog, int id); 
    public abstract void NegativeMethod(DialogInterface dialog, int id); 
} 

2) Generalize sposób okna potwierdzić.

public static void getConfirmDialog(Context mContext,String title, String msg, String positiveBtnCaption, String negativeBtnCaption, boolean isCancelable, final AlertMagnatic target) { 
     AlertDialog.Builder builder = new AlertDialog.Builder(mContext); 

     int imageResource = android.R.drawable.ic_dialog_alert; 
     Drawable image = mContext.getResources().getDrawable(imageResource); 

     builder.setTitle(title).setMessage(msg).setIcon(image).setCancelable(false).setPositiveButton(positiveBtnCaption, new DialogInterface.OnClickListener() { 
      public void onClick(DialogInterface dialog, int id) { 
       target.PositiveMethod(dialog, id); 
      } 
     }).setNegativeButton(negativeBtnCaption, new DialogInterface.OnClickListener() { 
      @Override 
      public void onClick(DialogInterface dialog, int id) { 
       target.NegativeMethod(dialog, id); 
      } 
     }); 

     AlertDialog alert = builder.create(); 
     alert.setCancelable(isCancelable); 
     alert.show(); 
     if (isCancelable) { 
      alert.setOnCancelListener(new OnCancelListener() { 

       @Override 
       public void onCancel(DialogInterface arg0) { 
        target.NegativeMethod(null, 0); 
       } 
      }); 
     } 
    } 

3) Jak używać

getConfirmDialog(getString(R.string.logout), getString(R.string.logout_message), getString(R.string.yes), getString(R.string.no), false, 
       new AlertMagnatic() { 

        @Override 
        public void PositiveMethod(final DialogInterface dialog, final int id) {} 

        @Override 
        public void NegativeMethod(DialogInterface dialog, int id) { 

        } 
       }); 
+0

Dzięki Biraj, Nie jestem pewien, gdzie muszę umieścić każdą część kodu. * Czy interfejs przechodzi do innego pliku lub do pliku java działania? –

+0

Zaleciłem, aby umieścić go jako osobny plik w pakiecie. –

+0

Chyba "Generalize method for confirm dialog" idzie do pliku Java w oknie dialogowym i "jak używać" w pliku aktywności, prawda? –

5

Ponieważ ta strona jest pierwszym hitem w Google, i wydaje się takiego wspólnego zadania z tak mało napisano o nim, będę udostępnić sposób, w jaki znalazłem, aby pokazać wielokrotnego użytku DialogFragment.

Używanie interfejsów staje się naprawdę niepotrzebne, jeśli chcesz wielokrotnie używać tego samego okna z tej samej klasy, ale za każdym razem wykonuj inną akcję. To rozwiązanie jest prostym i bezproblemowym sposobem na obejście tego problemu bez wprowadzania żadnych wad.

Edycja 25.02.2017: Ta odpowiedź została uprzednio przy użyciu klasy abstrakcyjnej wdrożyć confirm() i cancel(), ale nowsze wersje Androida padnie z powodu następującego błędu, jeśli spróbujesz użyć anonimowy klasy jako DialogFragment:

java.lang.IllegalStateException: Fragment null must be a public static class to be properly recreated from instance state.

więc już zmodyfikowane rozwiązanie używać Runnables, który działa naprawdę miły w Java8 ale jest również możliwe bez niego

Najpierw należy utworzyć klasę, która implementuje utworzenie Dialog samego:

/** 
* This is a reusable convenience class which makes it easy to show a confirmation dialog as a DialogFragment. 
* Create a new instance, call setArgs(...), setConfirm(), and setCancel() then show it via the fragment manager as usual. 
*/ 
public class ConfirmationDialog extends DialogFragment { 
    // Do nothing by default 
    private Runnable mConfirm = new Runnable() { 
     @Override 
     public void run() { 
     } 
    }; 
    // Do nothing by default 
    private Runnable mCancel = new Runnable() { 
     @Override 
     public void run() { 
     } 
    }; 

    public void setArgs(String message) { 
     setArgs("" , message); 
    } 

    public void setArgs(String title, String message) { 
     Bundle args = new Bundle(); 
     args.putString("message", message); 
     args.putString("title", title); 
     setArguments(args); 
    } 

    public void setConfirm(Runnable confirm) { 
     mConfirm = confirm; 
    } 

    public void setCancel(Runnable cancel) { 
     mCancel = cancel; 
    } 

    @Override 
    public MaterialDialog onCreateDialog(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     Resources res = getActivity().getResources(); 
     String title = getArguments().getString("title"); 
     return new MaterialDialog.Builder(getActivity()) 
       .title(title.equals("") ? res.getString(R.string.app_name) : title) 
       .content(getArguments().getString("message")) 
       .positiveText(res.getString(R.string.dialog_ok)) 
       .negativeText(res.getString(R.string.dialog_cancel)) 
       .callback(new MaterialDialog.ButtonCallback() { 
        @Override 
        public void onPositive(MaterialDialog dialog) { 
         mConfirm.run(); 
        } 

        @Override 
        public void onNegative(MaterialDialog dialog) { 
         mCancel.run(); 
        } 
       }) 
       .show(); 
    } 
} 

Po drugie, należy dokonać wspólnej metody w swoim Activity który pokazuje DialogFragment pomocą menedżera fragment:

/** 
* Global method to show dialog fragment 
* @param newFragment the DialogFragment you want to show 
*/ 
public void showDialogFragment(DialogFragment newFragment) { 
    // DialogFragment.show() will take care of adding the fragment 
    // in a transaction. We also want to remove any currently showing 
    // dialog, so make our own transaction and take care of that here. 
    FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); 
    Fragment prev = getSupportFragmentManager().findFragmentByTag("dialog"); 
    if (prev != null) { 
     ft.remove(prev); 
    } 
    // save transaction to the back stack 
    ft.addToBackStack("dialog"); 
    newFragment.show(ft, "dialog"); 
} 

Następnie można wyświetlić okno dialogowe z potwierdzeniem z dowolnego miejsca w urządzeniu Activity w następujący sposób:

ConfirmationDialog dialog = new ConfirmationDialog(); 
dialog.setArgs(stringDialogTitle, stringDialogMessage); 
Runnable confirm = new Runnable() { 
    @Override 
    public void run() { 
     doStuff(); 
    } 
}; 
dialog.setConfirm(confirm); 
showDialogFragment(dialog); 

Jeśli używasz Java8, możesz użyć lambdas dla funkcji, które spowodują, że kod będzie mniej szczegółowy. Zobacz przykład here.