放回堆栈上的DialogFragment仍使用后退按钮

时间:2018-12-07 14:34:54

标签: android android-fragments fragment dialogfragment

好的,我面临一个奇怪的问题,我似乎无法解决,所以我想问一下。

简而言之,我面临的问题是:

关闭后,我创建的全屏对话框将消耗(一次)后按按钮。结果什么也没发生,用户需要再次按下“后退”按钮以关闭“活动”。

全文: 我有一个活动和两个片段。下面是一些代码...:

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来查看正在发生的事情(more details here)。

  • 当用户关闭DialogFragment时,最后一个呼叫是onFragmentViewDestroyed。到目前为止一切顺利。
  • 当我按下“后退”按钮(在视觉上什么都没发生)时,实际上是碎片被破坏了:
    • onFragmentDestroyed被调用,然后onFragmentDetached
  • 一旦DialogFragment被销毁,再次按返回按钮,将关闭活动(按预期)。

因此,我认为我们可以通过以下技巧或肮脏的骇客(inspired by this post)来强制破坏Fragment:

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();
        }
    }

    (...)
}

但是什么也没发生!我没有看到对onFragmentDestroyedonFragmentDetached的任何呼叫。当然,问题仍然存在。

然后我看到了这篇文章:"What is difference between FragmentTransaction.add().commit() and DialogFragment.show()?"。声称它们是相同的。好吧,就我而言,它们不是:

  • DialogFragment不再是全屏显示,而是一个很小的覆盖。
  • 后退按钮现在可以神奇地“起作用”!

然后我认为可以...让我们找出一种使全屏显示的方法。 I read this post。没事。我能得到的最接近的是几乎是全屏对话框(我仍然可以看到前一个片段的很小一部分)。

我的问题:

  • 为什么在我的情况下后退按钮会发生这种情况?
    • 现在使用时是否有办法克服它?
  • 为什么tr.remove(f).commit()不破坏片段as claimed here
  • 在我的情况下,.show()blah blah.commit()为什么表现不同?

我迷路了!任何帮助表示赞赏!谢谢! (顺便说一句,我只保留了看似相关的信息。如果我缺少什么,请告诉我)

0 个答案:

没有答案