我没有找到一个问题,答案详细说明为什么,就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(用于显示列表)。
如果用户点击BottomNavigationView中的项目(例如“Schedule”),则以下代码将FrameLayout中的片段替换为与用户选择对应的片段(frag
):
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.fragment_container, frag);
transaction.commit();
有时,在这种情况下,存在“片段重叠”(我自己的术语 :)),请参阅下面的第三个屏幕截图(“目前没有捐赠。”消息{{1}仍然可见(在屏幕截图中下划线),即使前面的代码应该使用Schedule片段将完全替换为donsListFragment
:
这里发生了什么完全?
我在我的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()
答案 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
的观看次数)。这会导致重叠。
<强>解决方案强>
有两种可能的解决方案:
使用frag
在您的(推测)初始transaction.replace()
中插入donsListFragment
。
导航到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(表示数据检索进度,如我的第一个屏幕截图所示)干扰了片段进出容器的交换。