我正在处理片段,但是当我从一个片段切换到另一个视图时出现问题,彼此重叠。
我使用以下代码来切换片段。
getSupportFragmentManager()
.beginTransaction()
.add(R.id.mainContainer, new SecondsFragment())
.addToBackStack(null)
.commit();
我知道使用add()
只会在前一个片段的基础上添加更新的片段。我不想使用replace
,因为当我使用onBackPress()
返回该片段时它会重新加载所有内容,例如,当我使用函数打开第二个片段并返回到第一个片段时,我在第一个片段中有 REST API 调用replace()
它将再次调用该 REST API,这对UX
不利。
如果我使用add()
加载第二个片段,则第二个片段的视图与第一个片段的视图重叠,并且返回第一个片段不调用该 REST API(我想要的行为)。
我也知道,通过设置片段xml父视图的背景,这个问题可以解决,但它也会导致意外点击第一个片段视图再次对UX
不利,我也通过在SO中通过将父视图可点击设置为true来阅读这个问题,但正如其他开发人员所说,这只是一个黑客而不是一个正确的解决方案。
我希望像commonsware这样的用户能够解决这个问题。
非常欢迎任何建议/意见。
提前谢谢。
我会尝试一下,我认为您误解了FragmentTransaction
中add()
的语义,您正在add
另一个片段,这应该不会对已经添加的片段产生任何影响。这意味着您的两个片段在FragmentManager
状态方面都处于活动状态或RESUMED
状态。
事实上,你的第二个片段和你的第一个片段一样大,并且位于它上面,这只是一个只有你关心的实现细节,就FragmentManager
而言,你的两个片段都是RESUMED
的,活跃的,并且用户难以处理。
基本上,如果add()
应该在添加新片段之前以某种方式暂停当前添加的片段,为什么我们需要另一个 API 来replace()
您正在通过滥用其他功能(添加片段)来解决一个问题(不想重新执行网络请求)。
如果希望一次只有一个片段处于活动状态,则需要先删除旧片段,方法是显式调用remove()
或通过调用replace()
来完成它。
为了避免再次执行网络请求的问题,您可以:
- 将第一个片段添加到后退堆栈添加中,并使用
pop()
返回到片段的同一实例,这将需要片段中的一些逻辑来检查某个状态是否未null
,然后无需进行网络调用。 - 将片段的实例手动保存在包含
Fragment
/Activity
中,然后在再次添加旧片段时,添加现有实例,而不是创建一个全新的实例。
但是,如果你的意图确实是让它们都added
,但你想限制用户查看/与第一个片段交互的能力,你使用show()
,hide()
这样做。
您可以实例化第一个片段并将其设置为活动片段。选择第二个片段时,隐藏活动片段(片段 1),并将第二个片段设置为活动。
前任。
fragment1 = Fragment1.newInstance();
active = fragment1;
getFragmentManager()
.beginTransaction()
.add(R.id.fragment_container, fragment1, "1")
.commit();
选择第二个片段时,可以执行以下操作:
if (isFirstTimeLoading) {
fragment2 = Fragment2.newInstance();
getFragmentManager()
.beginTransaction()
.add(R.id.fragment_container, fragment2)
.hide(active)
.commit();
active = fragment2;
isFirstTimeLoading = false;
} else {
getFragmentManager()
.beginTransaction()
.hide(active)
.show(fragment2)
.commit();
active = fragment2;
}