Отображать диалоги с помощью DialogFragment

DialogFragment — это специальный подкласс фрагментов, предназначенный для создания и размещения диалогов . Хотя вам не обязательно размещать диалог внутри фрагмента, это позволяет FragmentManager управлять состоянием диалога и автоматически восстанавливать диалог при изменении конфигурации.

Создать диалоговый фрагмент

Чтобы создать DialogFragment , создайте класс, расширяющий DialogFragment и переопределите onCreateDialog() , как показано в следующем примере.

Котлин

class PurchaseConfirmationDialogFragment : DialogFragment() {
    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog =
            AlertDialog.Builder(requireContext())
                .setMessage(getString(R.string.order_confirmation))
                .setPositiveButton(getString(R.string.ok)) { _,_ -> }
                .create()

    companion object {
        const val TAG = "PurchaseConfirmationDialog"
    }
}

Ява

public class PurchaseConfirmationDialogFragment extends DialogFragment {
   @NonNull
   @Override
   public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
       return new AlertDialog.Builder(requireContext())
               .setMessage(getString(R.string.order_confirmation))
               .setPositiveButton(getString(R.string.ok), (dialog, which) -> {} )
               .create();
   }

   public static String TAG = "PurchaseConfirmationDialog";
}

Подобно тому, как onCreateView() создает корневое View в обычном фрагменте, onCreateDialog() создает Dialog для отображения как часть DialogFragment . DialogFragment обрабатывает отображение Dialog в соответствующих состояниях жизненного цикла фрагмента.

Как и в случае с onCreateView() , вы можете вернуть любой подкласс Dialog из onCreateDialog() и не ограничиваться использованием AlertDialog .

Показать диалоговый фрагмент

Вам не нужно вручную создавать FragmentTransaction для отображения DialogFragment . Вместо этого используйте метод show() для отображения диалога. Вы можете передать ссылку на FragmentManager и String , чтобы использовать ее в качестве тега FragmentTransaction .

При создании DialogFragment из Fragment используйте дочерний FragmentManager фрагмента, чтобы состояние правильно восстанавливалось после изменения конфигурации. Ненулевой тег позволяет использовать findFragmentByTag() для получения DialogFragment позднее.

Котлин

// From another Fragment or Activity where you wish to show this
// PurchaseConfirmationDialogFragment.
PurchaseConfirmationDialogFragment().show(
     childFragmentManager, PurchaseConfirmationDialog.TAG)

Ява

// From another Fragment or Activity where you wish to show this
// PurchaseConfirmationDialogFragment.
new PurchaseConfirmationDialogFragment().show(
       getChildFragmentManager(), PurchaseConfirmationDialog.TAG);

Для большего контроля над FragmentTransaction вы можете использовать перегрузку show() , которая принимает существующий FragmentTransaction .

Жизненный цикл DialogFragment

DialogFragment следует стандартному жизненному циклу фрагмента с несколькими дополнительными обратными вызовами жизненного цикла. Наиболее распространены следующие:

  • onCreateDialog() : переопределить этот обратный вызов, чтобы предоставить Dialog для управления и отображения фрагмента.
  • onDismiss() : переопределите этот обратный вызов, если вам нужно выполнить какую-либо пользовательскую логику при закрытии вашего Dialog , например, освободить ресурсы или отказаться от подписки на наблюдаемые ресурсы.
  • onCancel() : переопределите этот обратный вызов, если вам нужно выполнить какую-либо пользовательскую логику при отмене вашего Dialog .

DialogFragment также содержит методы для закрытия или установки возможности отмены вашего DialogFragment :

  • dismiss() : закрыть фрагмент и его диалог. Если фрагмент был добавлен в задний стек, все состояния обратного стека до этой записи включительно извлекаются. В противном случае фиксируется новая транзакция для удаления фрагмента.
  • setCancelable() : контролирует, можно ли отменить отображаемый Dialog . Используйте этот метод вместо прямого вызова Dialog.setCancelable(boolean) .

Вы не переопределяете onCreateView() или onViewCreated() при использовании DialogFragment с Dialog . Диалоги — это не только представления — у них есть собственное окно. Таким образом, недостаточно переопределить onCreateView() . Более того, onViewCreated() никогда не вызывается для пользовательского DialogFragment , если вы не переопределили onCreateView() и не предоставили ненулевое представление.

Используйте пользовательские представления

Вы можете создать DialogFragment и отобразить диалог, переопределив onCreateView() . Вы можете либо указать ему layoutId , как обычному фрагменту, либо использовать конструктор DialogFragment .

View , возвращаемое функцией onCreateView() автоматически добавляется в диалоговое окно. В большинстве случаев это означает, что вам не нужно переопределять onCreateDialog() , поскольку пустой диалог по умолчанию заполняется вашим представлением.

Некоторые подклассы DialogFragment , такие как BottomSheetDialogFragment , встраивают ваше представление в диалоговое окно, оформленное как нижний лист.