在视图寻呼机上方显示具有嵌套片段的对话框

2023-12-25

我设置了一个非常简单的测试项目https://github.com/ArtworkAD/ViewPagerDialogTest https://github.com/ArtworkAD/ViewPagerDialogTest评估以下情况:主要活动有一个视图分页器,它使用支持片段管理器托管单个片段:

public class MainActivity extends AppCompatActivity {

    // ...

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // ...
        viewPager.setAdapter(new ViewPagerAdapter(getSupportFragmentManager()));
        // ...
        tabLayout.setupWithViewPager(viewPager);
    }

    @Override
    protected void onResume() {
        super.onResume();

        MainActivity.CustomDialog dialog = (MainActivity.CustomDialog) getSupportFragmentManager().findFragmentByTag(MainActivity.CustomDialog.TAG);

        if (dialog == null) {
            new MainActivity.CustomDialog().show(getSupportFragmentManager().beginTransaction(), MainActivity.CustomDialog.TAG);
        }
    }
    // ...
}

当活动恢复时,主活动内会显示一个对话框片段。

视图分页器内的单个片段定义如下:

public class RootFragment extends Fragment {

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View root = inflater.inflate(R.layout.root_fragment, container, false);
        if (savedInstanceState == null) {
            getFragmentManager().beginTransaction().add(R.id.root_frame, new FirstLevelFragment(), "ROOT").commit();
        }
        return root;
    }
}

这个根片段允许我们在“root_frame”上堆叠其他片段。所以我们堆叠一个又一个:

public class FirstLevelFragment extends Fragment {

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        setRetainInstance(true);
        View root = inflater.inflate(R.layout.first_level_fragment, container, false);
        root.findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                SecondLevelFragment f = (SecondLevelFragment) getActivity().getSupportFragmentManager().findFragmentByTag("NESTED");
                if (f == null) {
                    getActivity().getSupportFragmentManager().beginTransaction().add(R.id.root_frame, new SecondLevelFragment(), "NESTED").addToBackStack(null).commit();
                }
            }
        });
        return root;
    }

    public static class SecondLevelFragment extends Fragment {

        @Nullable
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            setRetainInstance(true);
            return inflater.inflate(R.layout.second_level_fragment, container, false);
        }
    }
}

这太棒了!堆叠的想法取自https://stackoverflow.com/a/21453571/401025 https://stackoverflow.com/a/21453571/401025。但是,当显示对话框并且用户转到第二级片段并旋转屏幕时,我收到以下异常:

E/AndroidRuntime:java.lang.RuntimeException:无法启动活动 ComponentInfo{de.azzoft.viewpagerdialogtest/de.azzoft.viewpagerdialogtest.MainActivity}: java.lang.IllegalArgumentException:找不到 id 0x7f0c0083 的视图 (de.azzoft.viewpagerdialogtest:id/root_frame) 片段 SecondLevelFragment{15c0db38 #0 id=0x7f0c0083 嵌套}

E/AndroidRuntime:由以下原因引起:java.lang.IllegalArgumentException:否 找到 id 0x7f0c0083 的视图 (de.azzoft.viewpagerdialogtest:id/root_frame) 片段 SecondLevelFragment{15c0db38 #0 id=0x7f0c0083 嵌套}

完整的堆栈跟踪:https://github.com/ArtworkAD/ViewPagerDialogTest/blob/master/README.md https://github.com/ArtworkAD/ViewPagerDialogTest/blob/master/README.md

如果没有出现对话框,一切都会很好。您可以通过下载测试项目进行测试。

看起来对话框实际上是一个片段,当它添加到活动中时,它会弄乱片段层次结构。任何想法如何解决这一问题?

保留第二个片段很重要。


No view found for id 0x7f0c0083 (de.azzoft.viewpagerdialogtest:id/root_frame) for fragment SecondLevelFragment

When Activity旋转时重新创建,Activity FragmentManger尝试添加SecondLevelFragment into R.id.root_frame。但是root_frame视图不在 Activity 布局中,它在FirstLevelFragment布局。这就是应用程序崩溃的原因。

您必须进行两项更改才能解决此问题。

Add the FirstLevelFragment进入RootFragment使用getChildFragmentManager

getChildFragmentManager().beginTransaction().add(R.id.root_frame, new FirstLevelFragment(), "ROOT").commit();

Add the SecondLevelFragment using FragmentManager

getFragmentManager().beginTransaction().add(R.id.root_frame, new SecondLevelFragment(), "NESTED").addToBackStack(null).commit();

最后删除setRetainInstance from FirstLevelFragment and SecondLevelFragment因为嵌套片段不需要设置保留。

如果您需要弹回SecondLevelFragment在后按时,您需要将后按事件传递给根片段并从后台弹出。

覆盖活动的后按

@Override
public void onBackPressed() {
    Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.viewpager);
    if(fragment instanceof RootFragment){
        boolean handled = ((RootFragment)fragment).onBackPressed();
        if(handled){
            return;
        }
    }
    super.onBackPressed();
}

并处理后按RootFragment

public boolean onBackPressed() {
    int count = getChildFragmentManager().getBackStackEntryCount();
    if(count > 0){
        getChildFragmentManager().popBackStackImmediate();
        return true;
    }
    return false;
} 

我向您的存储库创建了一个 Pull 请求。请检查https://github.com/ArtworkAD/ViewPagerDialogTest/pull/1 https://github.com/ArtworkAD/ViewPagerDialogTest/pull/1

如有任何疑问请告诉我。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在视图寻呼机上方显示具有嵌套片段的对话框 的相关文章

随机推荐