web-dev-qa-db-de.com

Wie versende ich Daten von DialogFragment an ein Fragment?

Ich habe ein Fragment, das eine Dialogfragment öffnet, um Benutzereingaben zu erhalten (eine Zeichenfolge und eine Ganzzahl). Wie schicke ich diese beiden Dinge zurück zum Fragment?

Hier ist mein DialogFragment:

public class DatePickerFragment extends DialogFragment {
    String Month;
    int Year;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        getDialog().setTitle(getString(R.string.Date_Picker));
        View v = inflater.inflate(R.layout.date_picker_dialog, container, false);

        Spinner months = (Spinner) v.findViewById(R.id.months_spinner);
        ArrayAdapter<CharSequence> monthadapter = ArrayAdapter.createFromResource(getActivity(),
                R.array.Months, R.layout.picker_row);
              months.setAdapter(monthadapter);
              months.setOnItemSelectedListener(new OnItemSelectedListener(){
                  @Override
                  public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int monthplace, long id) {
                      Month = Integer.toString(monthplace);
                  }
                  public void onNothingSelected(AdapterView<?> parent) {
                    }
              });

        Spinner years = (Spinner) v.findViewById(R.id.years_spinner);
        ArrayAdapter<CharSequence> yearadapter = ArrayAdapter.createFromResource(getActivity(),
             R.array.Years, R.layout.picker_row);
        years.setAdapter(yearadapter);
        years.setOnItemSelectedListener(new OnItemSelectedListener(){
          @Override
          public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int yearplace, long id) {
              if (yearplace == 0){
                  Year = 2012;
              }if (yearplace == 1){
                  Year = 2013;
              }if (yearplace == 2){
                  Year = 2014;
              }
          }
          public void onNothingSelected(AdapterView<?> parent) {}
        });

        Button button = (Button) v.findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
           public void onClick(View v) {
               getDialog().dismiss();
            }
        });

        return v;
    }
}

Ich muss die Daten nach dem Klicken der Schaltfläche und vor getDialog().dismiss() senden.

Hier ist das Fragment, an das die Daten gesendet werden müssen:

public class CalendarFragment extends Fragment {
int Year;
String Month;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    int position = getArguments().getInt("position");
    String[] categories = getResources().getStringArray(R.array.categories);
    getActivity().getActionBar().setTitle(categories[position]);
    View v = inflater.inflate(R.layout.calendar_fragment_layout, container, false);    

    final Calendar c = Calendar.getInstance();
    SimpleDateFormat month_date = new SimpleDateFormat("MMMMMMMMM");
    Month = month_date.format(c.getTime());
    Year = c.get(Calendar.YEAR);

    Button button = (Button) v.findViewById(R.id.button);
    button.setText(Month + " "+ Year);
    button.setOnClickListener(new View.OnClickListener() {
        public void onClick(View v) {
           new DatePickerFragment().show(getFragmentManager(), "MyProgressDialog");
        }
    });
   return v;
  }
}

sobald der Benutzer in der Variablen Dialogfragment ein Datum auswählt, muss er den Monat und das Jahr zurückgeben. 

Dann sollte sich der Text auf der Schaltfläche in dem vom Benutzer angegebenen Monat und Jahr ändern.

32
trickedoutdavid

HINWEIS: Abgesehen von einem oder zwei spezifischen Android-Fragment-Aufrufen ist dies ein generischer Ansatz für die Implementierung des Datenaustauschs zwischen lose gekoppelten Komponenten. Sie können diesen Ansatz verwenden, um Daten buchstäblich zwischen allem auszutauschen, sei es Fragmente Aktivitäten, Dialoge oder andere Elemente Ihrer Anwendung.


Hier ist das Rezept:

  1. Erstellen Sie interface (d. H. Mit MyContract), das eine Signatur der Methode zum Weiterleiten der Daten enthält, d. H. methodToPassData(... data);.
  2. Stellen Sie sicher, dass Ihre DialogFragment-Datei diesen Vertrag erfüllt (was normalerweise bedeutet, dass die gewünschte Schnittstelle implementiert wird): class MyFragment extends Fragment implements MyContract {....}
  3. Bei der Erstellung von DialogFragment setzen Sie Ihr aufrufendes Fragment als Zielfragment , indem Sie myDialogFragment.setTargetFragment(this, 0); aufrufen. Dies ist das Objekt, mit dem Sie später sprechen werden.
  4. Rufen Sie in Ihrer Variable DialogFragment das aufrufende Fragment auf, indem Sie getTargetFragment(); aufrufen und das zurückgegebene Objekt an die in Schritt 1 erstellte Vertragsschnittstelle senden, indem Sie Folgendes tun: MyContract mHost = (MyContract)getTargetFragment();. Durch das Casting können wir sicherstellen, dass das Zielobjekt den erforderlichen Vertrag implementiert, und wir können erwarten, dass methodToPassData() dabei ist. Wenn nicht, erhalten Sie regelmäßig ClassCastException. Dies sollte normalerweise nicht passieren, es sei denn, Sie machen zuviel Copy-Paste-Coding. :) Wenn Ihr Projekt externen Code, Bibliotheken oder Plugins usw. verwendet, sollten Sie in diesem Fall eher die Ausnahme abfangen und dem Benutzer mitteilen, dass das Plugin nicht kompatibel ist Lassen Sie die App einfach abstürzen.
  5. Wenn die Zeit für das Zurücksenden von Daten kommt, rufen Sie methodToPassData() für das zuvor erhaltene Objekt auf: ((MyContract)getTargetFragment()).methodToPassData(data);. Wenn Ihr onAttach() bereits eine Klassenvariable (d. H. mHost) umwandelt und einem Zielfragment zuordnet, ist dieser Code nur mHost.methodToPassData(data);.
  6. Voilà.

Sie haben gerade Ihre Daten erfolgreich vom Dialog an den Aufruf des Fragments übergeben.

82
Marcin Orlowski

Hier ist ein anderes Rezept ohne Verwendung einer Schnittstelle. Verwenden Sie einfach die Variablen setTargetFragment und Bundle, um Daten zwischen DialogFragment und Fragment zu übergeben.

public static final int DATEPICKER_FRAGMENT = 1; // class variable

1 . Rufen Sie die DialogFragment wie folgt auf:

// create dialog fragment
DatePickerFragment dialog = new DatePickerFragment();

// optionally pass arguments to the dialog fragment
Bundle args = new Bundle();
args.putString("pickerStyle", "fancy");
dialog.setArguments(args);

// setup link back to use and display
dialog.setTargetFragment(this, DATEPICKER_FRAGMENT);
dialog.show(getFragmentManager().beginTransaction(), "MyProgressDialog")

2 . Verwenden Sie die zusätzliche Bundle in einer Intent in der DialogFragment, um alle Informationen an das Zielfragment zurückzugeben. Der folgende Code im Button#onClick()-Ereignis von DatePickerFragment übergibt einen String und eine Ganzzahl.

Intent i = new Intent()
        .putExtra("month", getMonthString())
        .putExtra("year", getYearInt());
getTargetFragment().onActivityResult(getTargetRequestCode(), Activity.RESULT_OK, i);
dismiss();

3 . Verwenden Sie die onActivityResult()-Methode von CalendarFragment, um die Werte zu lesen:

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    switch (requestCode) {
        case DATEPICKER_FRAGMENT:
            if (resultCode == Activity.RESULT_OK) {
                Bundle bundle = data.getExtras();
                String mMonth = bundle.getString("month", Month);
                int mYear = bundle.getInt("year");
                Log.i("PICKER", "Got year=" + year + " and month=" + month + ", yay!");
            } else if (resultCode == Activity.RESULT_CANCELED) {
                ...
            }
            break;
    }
}
35
blizzard

Ein guter Tipp ist die Verwendung des ViewModel- und LiveData-Ansatzes, der der beste Weg ist. Bellow ist das Codebeispiel zum Freigeben von Daten zwischen Fragmenten:

class SharedViewModel : ViewModel() {
    val selected = MutableLiveData<Item>()

    fun select(item: Item) {
        selected.value = item
    }
}

class MasterFragment : Fragment() {

    private lateinit var itemSelector: Selector

    private lateinit var model: SharedViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        model = activity?.run {
            ViewModelProviders.of(this).get(SharedViewModel::class.Java)
        } ?: throw Exception("Invalid Activity")
        itemSelector.setOnClickListener { item ->
            // Update the UI
        }
    }
}

class DetailFragment : Fragment() {

    private lateinit var model: SharedViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        model = activity?.run {
            ViewModelProviders.of(this).get(SharedViewModel::class.Java)
        } ?: throw Exception("Invalid Activity")
        model.selected.observe(this, Observer<Item> { item ->
            // Update the UI
        })
    }
}

Probieren Sie es aus, diese neuen Komponenten helfen uns, ich denke, es ist effizienter als andere Ansätze.

Lesen Sie mehr darüber: https://developer.Android.com/topic/libraries/architecture/viewmodel

0
Pedro Massango

Hier ist ein Ansatz, der die in Kotlin implementierte Antwort von Marcin veranschaulicht.

1.Erstellen Sie eine Schnittstelle mit einer Methode zum Übergeben von Daten in Ihrer dialogFragment-Klasse.

interface OnCurrencySelected{
    fun selectedCurrency(currency: Currency)
}

2.Fügen Sie Ihre Schnittstelle in Ihrem dialogFragment-Konstruktor hinzu.

class CurrencyDialogFragment(val onCurrencySelected :OnCurrencySelected)    :DialogFragment() {}

3.Lassen Sie Ihr Fragment nun die gerade erstellte Schnittstelle implementieren

class MyFragment : Fragment(), CurrencyDialogFragment.OnCurrencySelected {

override fun selectedCurrency(currency: Currency) {
//this method is called when you pass data back to the fragment
}}

4.Um dann Ihren Dialog anzuzeigen, rufen Sie einfach CurrencyDialogFragment(this).show(fragmentManager,"dialog") auf. this ist das Interface-Objekt, mit dem Sie sprechen, um Daten an Ihr Fragment zurückzugeben.

5.Wenn Sie Daten an Ihr Fragment zurücksenden möchten, rufen Sie einfach die Methode auf, um Daten an das Schnittstellenobjekt zu übergeben, das Sie im dialogFragment-Konstruktor übergeben haben.

onCurrencySelected.selectedCurrency(Currency.USD)
dialog.dismiss()
0
DAVID KATHOH