Получение результата от DialogFragment
Я использую DialogFragments для ряда вещей: выбор пункта из списка, ввод текста.
каков наилучший способ вернуть значение (т. е. строку или элемент из списка) обратно в вызывающее действие/фрагмент?
В настоящее время я делаю вызов activity implement DismissListener
и дать DialogFragment ссылку на действие. Затем диалоговое окно вызывает OnDimiss
метод в действии и действие захватывает результат из Объект DialogFragment. Очень грязный и он не работает на изменение конфигурации (изменение ориентации), поскольку DialogFragment теряет ссылку на действие.
Спасибо за любую помощь.
9 ответов:
использовать
myDialogFragment.setTargetFragment(this, MY_REQUEST_CODE)
из того места, где вы показываете диалог, а затем, когда ваш диалог будет завершен, из него вы можете позвонитьgetTargetFragment().onActivityResult(getTargetRequestCode(), ...)
, и реализоватьonActivityResult()
содержащий фрагмент.это похоже на злоупотребление
onActivityResult()
, тем более, что это не связано с деятельностью вообще. Но я видел, что это рекомендовано официальными людьми google, и, возможно, даже в демонстрациях api. Я думаю, что это то, чтоg/setTargetFragment()
добавлено для.
Как видите,здесь есть очень простой способ сделать это.
в своем
DialogFragment
добавить прослушиватель интерфейса, таких как:public interface EditNameDialogListener { void onFinishEditDialog(String inputText); }
затем добавьте ссылку на этот слушатель:
private EditNameDialogListener listener;
это будет использоваться для" активации " метода(ов) прослушивателя, а также для проверки, реализует ли родительская активность/фрагмент этот интерфейс (см. ниже).
на
Activity
/FragmentActivity
/Fragment
что "под названием"DialogFragment
просто реализовать этот интерфейс.в своем
DialogFragment
все, что вам нужно добавить в тот момент, когда вы хотели бы уволитьDialogFragment
и вернуть результат таков:listener.onFinishEditDialog(mEditText.getText().toString()); this.dismiss();
здесь
mEditText.getText().toString()
это то, что будет передано обратно в вызовActivity
.обратите внимание, что если вы хотите вернуть что-то еще, просто измените аргументы, которые принимает слушатель.
наконец, вы должны проверить, был ли интерфейс фактически реализован родителем активность/фрагмент:
@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"); } }
этот метод является очень гибким и позволяет перезванивать с результатом, даже если ваш Дон;Т хотите, чтобы закрыть диалог только сейчас.
есть гораздо более простой способ получить результат от DialogFragment.
во-первых, в вашей деятельности, фрагмент, или FragmentActivity вам нужно добавить в следующей информации:
@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. } } }
The
requestCode
это в основном ваша метка int для DialogFragment, которую вы назвали, я покажу, как это работает через секунду. В resultCode-код, который вы отправить обратно из DialogFragment говорю текущей активности в ожидании, фрагмент, или FragmentActivity, что получилось.следующий фрагмент кода для входа-это вызов DialogFragment. Пример здесь:
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");
С помощью этих трех строк вы объявляете свой DialogFragment, устанавливая requestCode (который вызовет onActivityResult (...) после того, как диалог будет отклонен, и вы затем показываете диалог. Все так просто.
теперь в вашем DialogFragment вам нужно просто добавить одну строку непосредственно перед
dismiss()
так что вы отправляете resultCode вернемся к onActivityResult ().getTargetFragment().onActivityResult(getTargetRequestCode(), resultCode, getActivity().getIntent()); dismiss();
вот и все. Обратите внимание, что resultCode определяется как
int resultCode
который я установил вresultCode = 1;
в этом случае.вот и все, теперь вы можете отправить результат вашего DialogFragment обратно в вашу вызывающую активность, фрагмент или FragmentActivity.
кроме того, похоже, что эта информация была размещена ранее, но не было достаточного примера, поэтому я подумал, что предоставлю более подробную информацию.
изменить 06.24.2016 Я прошу прощения за вводящий в заблуждение код выше. Но вы, безусловно, не можете получить результат обратно в действие, видя как строка:
dialogFrag.setTargetFragment(this, 1);
задает элемент
Fragment
, а неActivity
. Поэтому для того, чтобы сделать это, вы должны использовать реализацииInterfaceCommunicator
.в своем
DialogFragment
установить глобальную переменнуюpublic InterfaceCommunicator interfaceCommunicator;
создать публичную функцию для ее обработки
public interface InterfaceCommunicator { void sendRequestCode(int code); }
затем, когда вы будете готовы отправить код обратно
Activity
когдаDialogFragment
выполняется запуск, вы просто добавляете строку перед вамиdismiss();
кодDialogFragment
:interfaceCommunicator.sendRequestCode(1); // the parameter is any int code you choose.
в вашей деятельности теперь вам нужно сделать две вещи, первая-удалить эту одну строку кода, которая больше не применима:
dialogFrag.setTargetFragment(this, 1);
затем реализовать интерфейс, и вы все сделали. Вы можете сделать это, добавив следующую строку
implements
предложение в самом верху вашего класса:public class MyClass Activity implements MyDialogFragment.InterfaceCommunicator
а то
@Override
в функция в деятельности@Override public void sendRequestCode(int code) { // your code here }
вы используете этот метод интерфейса так же, как и
onActivityResult()
метод. За исключением того, что метод интерфейса предназначен дляDialogFragments
иFragments
.
ну ее слишком поздно может быть, чтобы ответить, но вот что я сделал, чтобы получить результаты из
DialogFragment
. очень похоже на ответ @brandon. Вот я и звонюDialogFragment
из фрагмента, просто поместите этот код, где вы вызываете ваш диалог.FragmentManager fragmentManager = getFragmentManager(); categoryDialog.setTargetFragment(this,1); categoryDialog.show(fragmentManager, "dialog");
здесь
categoryDialog
мойDialogFragment
который я хочу назвать и после этого в вашей реализацииdialogfragment
поместите этот код, где вы устанавливаете свои данные в intent. ЗначениеresultCode
равен 1, Вы можете установить его или использовать систему Определенный.Intent intent = new Intent(); intent.putExtra("listdata", stringData); getTargetFragment().onActivityResult(getTargetRequestCode(), resultCode, intent); getDialog().dismiss();
теперь пришло время вернуться к вызывающему фрагменту и реализовать этот метод. проверьте правильность данных или результат успеха, если вы хотите с
resultCode
иrequestCode
в состоянии 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(); }
Я очень удивлен, что никто не предложил использовать местные трансляции для
DialogFragment
доActivity
общение! Я считаю, что это намного проще и чище, чем другие предложения. По сути, вы регистрируетесь для вашегоActivity
чтобы слушать радиопередачи, и вы отправляете местные трансляции с вашегоDialogFragment
экземпляров. Простой. Пошаговое руководство по настройке всего этого см. В разделе здесь.
один простой способ, который я нашел, был следующим: Реализовать это ваш dialogFragment,
CallingActivity callingActivity = (CallingActivity) getActivity(); callingActivity.onUserSelectValue("insert selected value here"); dismiss();
и затем в действии, которое вызвало фрагмент диалога, создайте соответствующую функцию как таковую:
public void onUserSelectValue(String selectedValue) { // TODO add your implementation. Toast.makeText(getBaseContext(), ""+ selectedValue, Toast.LENGTH_LONG).show(); }
тост должен показать, что он работает. Работать на меня.
другой подход, чтобы позволить фрагмент общаться до его активность:
1) определите открытый интерфейс во фрагменте и создайте для него переменную
public OnFragmentInteractionListener mCallback; public interface OnFragmentInteractionListener { void onFragmentInteraction(int id); }
2) приведите действие к переменной mCallback в фрагменте
try { mCallback = (OnFragmentInteractionListener) getActivity(); } catch (Exception e) { Log.d(TAG, e.getMessage()); }
3) реализовать слушателя в вашей деятельности
public class MainActivity extends AppCompatActivity implements DFragment.OnFragmentInteractionListener { //your code here }
4) переопределить OnFragmentInteraction в деятельности
@Override public void onFragmentInteraction(int id) { Log.d(TAG, "received from fragment: " + id); }
подробнее об этом:https://developer.android.com/training/basics/fragments/communicating.html
в моем случае мне нужно было передать аргументы в targetFragment. Но я получил исключение "фрагмент уже активен". Поэтому я объявил интерфейс в своем DialogFragment, который реализовал parentFragment. Когда parentFragment запустил DialogFragment, он установил себя как TargetFragment. Затем в DialogFragment я позвонил
((Interface)getTargetFragment()).onSomething(selectedListPosition);
просто чтобы иметь его в качестве одного из вариантов (так как никто еще не упоминал об этом) - вы можете использовать шину событий, такую как Otto. Итак, в диалоговом окне вы делаете:
bus.post(new AnswerAvailableEvent(42));
и ваш абонент (активность или фрагмент) подписаться на него:
@Subscribe public void answerAvailable(AnswerAvailableEvent event) { // TODO: React to the event somehow! }
Comments