DialogFragment, который был помещен обратно в стек, по-прежнему использует кнопку возврата - PullRequest
0 голосов
/ 07 декабря 2018

ОК. Я столкнулся со странной проблемой, которую, похоже, не могу решить, поэтому я решил спросить.

В двух словах проблема, с которой я сталкиваюсь, заключается в следующем:

Полноэкранный диалог, который я создаю после закрытия, будет использовать (один раз) кнопку «назад»,В результате ничего не происходит, и пользователю нужно снова нажать кнопку «Назад», чтобы закрыть «Активность».

Полная история: У меня есть Активность и два фрагмента.Ниже сначала код ...:

public class AppActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main_app);

        if (savedInstanceState == null) {
            showMainFragment();
        }
    }

    (...)

    private void showMainFragment() {
        FragmentManager fragmentManager = getSupportFragmentManager();
        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
        EditAppActivityFragment fr = new MainAppActivityFragment();
        fragmentTransaction.add(R.id.fragment_container_main_app, fr, "main");
        fragmentTransaction.commit();
    }

    private void showDialogFullscreen() {
        AppConfigDialogFragment newFragment = new AppConfigDialogFragment();
        FragmentManager fragmentManager = getSupportFragmentManager();
        FragmentTransaction transaction = fragmentManager.beginTransaction();
        transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
         transaction.add(R.id.fragment_container_main_app, newFragment, "dialog")
            .addToBackStack("dialog").commit();
    }

}

activity_main_app.xml:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/fragment_container_main_app"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
</FrameLayout>

Вот MainAppActivityFragment:

public class MainAppActivityFragment extends Fragment implements {

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
                             @Nullable Bundle savedInstanceState) {
        binding = DataBindingUtil.inflate(inflater, R.layout.fragment_main_app, container, false);
        initToolbar();
        updateActionBar();
        setViewModel();
        return binding.getRoot();
    }

}

И fragment_main_app.xml:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/layout_main_app"
    tools:context=".ui.activity.fragment.EditAppActivityFragment">

    <data>

        <variable
            name="viewModel"
            type="..." />

    </data>

    <android.support.design.widget.CoordinatorLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        (...)

    </android.support.design.widget.CoordinatorLayout>
</layout>

Вот AppDialogFragment:

public class AppDialogFragment extends DialogFragment {
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        binding = DataBindingUtil.inflate(inflater, R.layout.dialog_configure_app, container, false);
        getBundleData();
        setAppBarButtonListeners();
        setViewModel();
        return binding.getRoot();
    }

    @Override
    public void onStart() {
        super.onStart();
        Dialog dialog = getDialog();
        if (dialog != null) {
            dialog.getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
        }
    }

    @NonNull
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        Dialog dialog = super.onCreateDialog(savedInstanceState);
        dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
        return dialog;
    }

    private void setAppBarButtonListeners() {
        binding.imageButtonConfigClose
                .setOnClickListener(v -> dismiss());

        binding.imageButtonConfigSave
                .setOnClickListener(v -> {
                    (...)
                    dismiss();
                });
    }
}

Итак, что происходит:

  • запускается AppActivity, который затем создаетMainAppActivityFragment.
  • в какой-то момент, скажем, после нажатия кнопки вызывается showDialogFullscreen(), создавая таким образом AppDialogFragment.
  • Появляется полный экран DialogFragment, и пользователь может либо сохранитьили отмените внесенные изменения.( Обратите внимание, что мне нужен полноэкранный диалог )
  • Все еще при той же активности, конечно, снова появляется MainAppActivityFragment.Пока все хорошо.
  • Теперь вот проблема: если я нажимаю кнопку возврата, ничего не происходит (на самом деле что-то происходит, см. Ниже).Мне нужно нажать еще раз, чтобы выйти из текущей активности.И это моя проблема.Фактически, если я создаю диалоговое окно x раз, мне нужно нажать x раз кнопку «Назад», прежде чем я смогу выйти из действия.

Что происходит?

Я использовал registerFragmentLifecycleCallbacks на FragmentManager, чтобы увидеть, что происходит ( подробнее здесь ).

  • Когда пользователь закрывает DialogFragment, последний вызов - onFragmentViewDestroyed.Пока все хорошо.
  • Когда я нажимаю кнопку "назад" (визуально ничего не происходит), фактически фрагмент уничтожается: вызывается
    • onFragmentDestroyed и затем onFragmentDetached
  • Как только DialogFragment будет уничтожено, снова нажмите кнопку «Назад», чтобы закрыть действие (как и предполагалось).

Так что я подумал, давайте сделаем следующий трюк или грязный хак( вдохновленный этим постом ) для принудительного уничтожения фрагмента:

fragmentManager.registerFragmentLifecycleCallbacks(new FragmentManager.FragmentLifecycleCallbacks() {

    (...)

    @Override
    public void onFragmentViewDestroyed(FragmentManager fm, Fragment f) {
        super.onFragmentViewDestroyed(fm, f);
        if (f.getTag().equals("dialog") {
            // Yes, this is being called...
            FragmentTransaction tr = fm.beginTransaction();
            tr.remove(f).commit();
        }
    }

    (...)
}

Но ничего не происходит !!Я не вижу звонков на onFragmentDestroyed и onFragmentDetached.Естественно, проблема все еще существует.

Затем я увидел этот пост: "В чем разница между FragmentTransaction.add (). Commit () и DialogFragment.show ()?" .Утверждают, что они одинаковы.Ну, в моем случае это не так:

  • DialogFragment больше не является полноэкранным режимом, а имеет небольшой оверлей.
  • Кнопка возврата теперь волшебным образом "работает"!

Тогда я подумал, хорошо ... давайте найдем способ сделать этот полноэкранный режим. Я прочитал этот пост .Ничего не получалось.Самым близким, что я мог получить, был почти полноэкранный диалог (я все еще мог видеть очень небольшую часть предыдущего фрагмента).

Итак, на мои вопросы:

  • Почему это происходит с кнопкой возврата в моем случае?
    • Есть ли способ, которым я могу преодолеть это, используя его сейчас?
  • Почему tr.remove(f).commit() не уничтожает фрагмент , как утверждается здесь ?
  • Почему .show() и blah blah.commit() действуют по-разному в моем случае?

Я потерян!Любая помощь приветствуется!Спасибо!(Кстати, я сохранил только ту информацию, которая показалась мне актуальной. Если я что-то упустил, пожалуйста, дайте мне знать)

...