Получать результат от DialogFragment
Я использую DialogFragments для нескольких вещей: выбор элемента из списка, ввод текста.
Каков наилучший способ вернуть значение (т.е. строку или элемент из списка) обратно в вызывающую активность/фрагмент?
В настоящее время я выполняю реализацию функции вызова DismissListener
и предоставляю DialogFragment ссылку на эту активность. Затем Dialog вызывает метод OnDimiss
в действии, и действие захватывает результат из объекта DialogFragment. Очень беспорядочно, и он не работает при изменении конфигурации (изменение ориентации), поскольку DialogFragment теряет ссылку на активность.
Спасибо за любую помощь.
Ответы
Ответ 1
Используйте myDialogFragment.setTargetFragment(this, MY_REQUEST_CODE)
из того места, где вы показываете диалог, а затем, когда ваше диалоговое окно завершено, из него вы можете вызвать getTargetFragment().onActivityResult(getTargetRequestCode(), ...)
и реализовать onActivityResult()
в содержащем фрагменте.
Это похоже на злоупотребление onActivityResult()
, тем более что оно вообще не связано с действиями. Но я видел, как это рекомендовалось официальными людьми Google, и, возможно, даже в демо-версиях api. Я думаю, что для него было добавлено g/setTargetFragment()
.
Ответ 2
Как вы можете видеть здесь, это очень простой способ сделать это.
В вашем DialogFragment
добавьте прослушиватель интерфейса, например:
public interface EditNameDialogListener {
void onFinishEditDialog(String inputText);
}
Затем добавьте ссылку на этот прослушиватель:
private EditNameDialogListener listener;
Это будет использоваться для "активации" метода (-ов) прослушивателя, а также для проверки того, реализует ли этот родительский Activity/Fragment этот интерфейс (см. ниже).
В 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");
}
}
Этот метод очень гибкий и позволяет перезвонить с результатом, даже если ваш не хочет отклонять диалог еще.
Ответ 3
Существует гораздо более простой способ получить результат из диалогового окна.
Во-первых, в вашей деятельности, фрагменте или фрагментации вам нужно добавить следующую информацию:
@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.
}
}
}
requestCode
- это, в основном, ваша метка int для вызываемого DialogFragment, я покажу, как это работает за секунду. Код результата - это код, который вы отправляете обратно из диалогового окна "Диалог", в котором сообщается, что произошло текущее ожидание активности, фрагмента или фрагментации.
Следующий фрагмент кода для входа - это вызов 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
.
Ответ 4
Хорошо, что слишком поздно можно ответить, но вот что я сделал, чтобы получить результаты от DialogFragment
. очень похоже на ответ @brandon.
Здесь я вызываю DialogFragment
из фрагмента, просто поместите этот код там, где вы вызываете свой диалог.
FragmentManager fragmentManager = getFragmentManager();
categoryDialog.setTargetFragment(this,1);
categoryDialog.show(fragmentManager, "dialog");
где categoryDialog
- мой DialogFragment
, который я хочу вызвать, и после этого в вашей реализации DialogFragment
поместите этот код, где вы устанавливаете свои данные в намерении. Значение resultCode
равно 1, вы можете установить его или использовать System Defined.
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();
}
Ответ 5
Я очень удивлен, увидев, что никто не предложил использовать локальные трансляции для связи DialogFragment
to Activity
! Я считаю, что это намного проще и чище, чем другие предложения. По существу, вы регистрируетесь для своего Activity
, чтобы прослушивать трансляции, и вы отправляете локальные трансляции из своих экземпляров DialogFragment
. Просто. Для пошагового руководства о том, как установить все это, см. здесь.
Ответ 6
Один простой способ, который я нашел, заключался в следующем:
Реализуем это ваш диалог,
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();
}
Toast должен показать, что он работает. Работал для меня.
Ответ 7
Разный подход, позволяющий Фрагмент связываться с его Activity:
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
Ответ 8
В моем случае мне нужно было передать аргументы целевому фрагменту. Но у меня есть исключение "Фрагмент уже активен". Поэтому я объявил интерфейс в моем диалоговомфрагменте, который реализовал parentFragment. Когда parentFragment запустил DialogFragment, он установил себя как TargetFragment. Затем в DialogFragment я назвал
((Interface)getTargetFragment()).onSomething(selectedListPosition);
Ответ 9
Просто чтобы это было как один из вариантов (так как никто еще не упомянул об этом) - вы могли бы использовать такую автобус, как Otto.
Итак, в диалоговом окне:
bus.post(new AnswerAvailableEvent(42));
И пусть ваш абонент (активность или фрагмент) подписался на него:
@Subscribe public void answerAvailable(AnswerAvailableEvent event) {
// TODO: React to the event somehow!
}