“片段重叠”的具体原因是什么?

时间:2017-04-26 11:15:47

标签: android android-fragments

我没有找到一个问题,答案详细说明为什么就Android运行时而言,会出现此问题。谁能提供这种解释?我对减轻这个问题的方法不感兴趣(例如设置片段的根视图背景颜色),但是想要为什么的具体解释。

(我正在使用v4支持FragmentManager,FragmentTransaction,Fragment API)。

我有一个由FrameLayout(R.id.fragment_container)和BottomNavigationView组成的Activity。

最初在Activity中我将一个片段实例添加到FrameLayout:

FragmentTransaction transaction = 
getSupportFragmentManager().beginTransaction();
transaction.add(R.id.fragment_container, donsListFragment);
transaction.commit();

donsListFragment(我的DonationsListFragment.class的一个实例)显示一条消息(“目前没有捐赠。”)和一个刷新指示符(使用SwipeRefreshLayout)(参见第一个屏幕截图),直到它从网页检索数据为止 - 服务(见第二个截图)。我使用DonationsListFragment.class中的ObservableList实例成员来保存从Web服务检索到的数据,并通过数据绑定框架控制消息的可见性和RecyclerView(用于显示列表)。

first screenshot second screenshot

如果用户点击BottomNavigationView中的项目(例如“Schedule”),则以下代码将FrameLayout中的片段替换为与用户选择对应的片段(frag):

FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
        transaction.replace(R.id.fragment_container, frag);
        transaction.commit();

有时,在这种情况下,存在“片段重叠”(我自己的术语 :)),请参阅下面的第三个屏幕截图(“目前没有捐赠。”消息{{1}仍然可见(在屏幕截图中下划线),即使前面的代码应该使用Schedule片段将完全替换为donsListFragment

third screenshot

这里发生了什么完全

我在我的Activity中覆盖了donsListFragment的BottomNavigationView上的用户点击(它实现了BottomNavigationView.OnNavigationItemSelectedListener):

onNavigationItemSelected(MenuItem)

我的switch (item.getItemId()) { case R.id.actions_item_donations: if (donsListFragment == null) { donsListFragment = new DonationsListFragment(); } if (!donsListFragment.isVisible()) { // posting a sticky event will prompt a refresh in DonationsListFragment's onResume() EventBus.getDefault().postSticky(new RefreshDonationsEvent()); displayFragment(donsListFragment); } else { donsListFragment.refreshDonations(); } break; case R.id.actions_item_schedule: if (schFragment == null) { schFragment = ScheduleFragment.getInstance(orgType); } if (!schFragment.isVisible()) { // posting a sticky event will prompt a refresh in ScheduleFragment's onResume() EventBus.getDefault().postSticky(new RefreshSchDaysEvent()); displayFragment(schFragment); } else { schFragment.refreshDays(); } break; ... 方法定义如下:

displayFragment(Fragment)

您之前会在我的 private void displayFragment(Fragment frag) { // update title in app bar accordingly appBarTitleTV.setText(fragTitles.get(frag.getClass())); FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); transaction.replace(R.id.fragment_container, frag); transaction.commit(); } 声明中看到我使用刷新事件对象的GreenRobot EventBus粘贴帖子来触发switch的{​​{1}}中的刷新。这是[{1}} DonationsListFragment

onResume()

我的DonationsListFragment方法启动异步 Web服务调用(使用基于Retrofit的Web客户端),然后在SwipeRefreshLayout上调用onResume()包装片段布局。底层Web客户端回调处理代码通过GreenRobot事件总线将从服务器检索到的捐赠发送回public void onResume() { EventBus.getDefault().register(this); OneSignal.setInFocusDisplaying(OneSignal.OSInFocusDisplayOption.None); if (EventBus.getDefault().removeStickyEvent(RefreshDonationsEvent.class) != null) { refreshDonations(); } super.onResume(); }

refreshDonations()

3 个答案:

答案 0 :(得分:1)

使用transaction.replace(R.id.fragment_container, donsListFragment);代替transaction.add(R.id.fragment_container, donsListFragment);

答案 1 :(得分:1)

<强>原因

您的问题是,.replace()的行为并不像您期望的那样。

在此方案中,您从名为FrameLayout的{​​{1}}开始。

当您致电fragment_container时,您需要为活动状态添加新视图。

即。您现在有2个观看次数(transaction.add(R.id.fragment_container, donsListFragment);R.id.fragment_container的观看次数),其中您有1个观看次数(仅donsListFragment)。

但是,当您在容器视图R.id.fragment_container上调用.replace()时,它不会删除之前添加的视图。

即。您仍然可以看到2个观看次数(R.id.fragment_container的观看次数和donsListFragment的观看次数)。这会导致重叠。

<强>解决方案

有两种可能的解决方案:

  1. 使用frag在您的(推测)初始transaction.replace()中插入donsListFragment

  2. 导航到FragmentTransaction Fragment .remove()的{​​{1}} donsFragment来电FragmentTransaction

答案 2 :(得分:0)

我发现从片段各自的布局中删除if (msie && propName && element[0].tagName !== 'IFRAME') element.prop(propName, attr[name]); s而不是将SwipeRefreshLayout(包围片段'swap-in-out FrameLayout)添加到包含Activity的布局中已经停止了“重叠”发生。

所以我似乎已经停止了这个问题,但不幸的是,我无法明确地说出原因。感谢CommonsWare提出的SwipeRefreshLayout建议,但是在阅读它之前我已经开始进行布局重构,遗憾的是无法报告日志记录(发生问题时)。

出现让每个片段的View层次结构包含一个SwipeRefreshLayout(表示数据检索进度,如我的第一个屏幕截图所示)干扰了片段进出容器的交换。