Получить результат от DialogFragment
Я использую DialogFragments для ряда вещей: выбор пункта из списка, ввод текста.
каков наилучший способ вернуть значение (т. е. строку или элемент из списка) обратно в вызывающее действие/фрагмент?
В настоящее время я делаю вызов activity implement DismissListener
и предоставление DialogFragment ссылки на действие. Затем диалоговое окно вызывает OnDimiss
метод в activity и activity захватывает результат из Объект 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");
}
}
этот метод очень гибкий и позволяет перезванивать с результатом, даже если ваш Дон;t хочет закрыть диалог только сейчас.
есть гораздо более простой способ получить результат от 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.
}
}
}
на requestCode
в основном ваш ярлык int для DialogFragment, который вы вызвали, я покажу, как это работает через секунду. ResultCode-это код, который вы отправляете обратно из 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
. Поэтому для этого вам нужно использовать implement an 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.
Вот я и зову!--3--> из фрагмента, просто поместите этот код, где вы вызываете ваш диалог.
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!
}