片段 BackStack。碎片甚至在 pop 后重叠。
Fragments BackStack. Fragments overlap even after pop.
问题在于正确管理返回堆栈,以便弹出(或删除)前一个片段。问题在于它们重叠..
程序结构如下:
- 每个部分有 3 个片段的滑动菜单:
CatalogFragment
、NewsFragment
、BlogFragment
;
- 每个片段都是一个带有项目的列表视图(从 JSON 解析);
- 在
CatalogFragment
的项目上单击 我需要将此 CatalogFragment
替换为 LessonsFragment
,这也是列表。
p.s。项目是俄语,但我想你可以理解
这是(动态)添加这些片段的方式:
@Override
public void onNavigationDrawerItemSelected(int position) {
FragmentManager fragmentManager = getSupportFragmentManager();
// fragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE); //this also doesn't work
switch (position+1) {
case 1:
//getSupportFragmentManager().popBackStack(); // this doesnt work
fragmentManager.beginTransaction().replace(R.id.container,
CatalogFragment.newInstance(position + 1)).addToBackStack("catalog").commit();
break;
case 2:
fragmentManager.beginTransaction().replace(R.id.container,
NewsFragment.newInstance(position + 1)).addToBackStack("news").commit();
break;
case 3:
fragmentManager.beginTransaction().replace(R.id.container,
BlogFragment.newInstance(position + 1)).addToBackStack("blog").commit();
break;
}
}
这就是我在 onCatalogFragmentInteraction
接口方法中用新片段替换片段的方式:
/** Methods for interaction with list items*/
@Override
public void onCatalogFragmentInteraction(String id){
//pop previous
getSupportFragmentManager().popBackStack("catalog", FragmentManager.POP_BACK_STACK_INCLUSIVE);
//add new
FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.container, LessonsFragment.newInstance());
fragmentTransaction.addToBackStack("lessons");
fragmentTransaction.commit();
}
...这很好用:
但是当我从滑动菜单返回片段时,片段重叠。
我认为问题出在适当的 BackStack 管理上,但我不知道我做错了什么。另一个建议是在这种情况下我需要以某种方式更好地使用 add/replace
。
我已经尝试过按名称从堆栈中删除。也许需要通过 ID 删除它们?
P.S。告诉是否需要更多代码。
提前致谢。
尝试仅传递一个空字符串作为 addToBackStack 中的片段标识符。
而不是
getSupportFragmentManager().popBackStack("catalog", FragmentManager.POP_BACK_STACK_INCLUSIVE
只需使用
getSupportFragmentManager().popBackStack();
我认为你的所有片段都有透明背景或者你没有设置任何东西(所以默认是透明的)。因此,当您 add/replace 一个片段位于另一个片段上方时,您可以看到下方片段。所以尝试为每个片段布局设置背景颜色。
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffffff"
android:orientation="vertical" >
</LinearLayout>
我猜这是你的xml片段,它可能是其他类型的布局(Relative,Frame或其他),尝试把你的背景颜色片段 xml 的 父布局 。
例如,我将白色作为背景。
我认为这不是完美的解决方案,但这对我有用。
long back_pressed;
@Override
public void onBackPressed()
{
Log.d(TAG, "HERE WAS PRESSED BACK");
int backStackEntryCount = getSupportFragmentManager().getBackStackEntryCount();
final Fragment fragment = getSupportFragmentManager().findFragmentByTag(TAG_ANSWERS_FRAGMENT);
if(null != fragment && fragment.isVisible()) {
Log.d(TAG, "visible");
showLeaveTest();
}
else {
Log.d(TAG, "invisible");
if (backStackEntryCount == 0) {
if (back_pressed + 2000 > System.currentTimeMillis()) super.onBackPressed();
else try {
Toast.makeText(this, R.string.double_press, Toast.LENGTH_SHORT).show();
} catch (Exception e) {
e.printStackTrace();
}
back_pressed = System.currentTimeMillis();
} else {
getSupportFragmentManager().popBackStack();
removeCurrentFragment(TAG_RESULT_FRAGMENT);
}
}
}
public void removeCurrentFragment(String fragmentTag)
{
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
Fragment currentFrag = getSupportFragmentManager().findFragmentByTag(fragmentTag);
String fragName = "NONE";
if (currentFrag != null)
fragName = currentFrag.getClass().getSimpleName();
Log.d(TAG, "flag name " + fragName);
if (currentFrag != null && currentFrag.isVisible())
transaction.remove(currentFrag);
transaction.commit();
}
所以,我在 activity 中捕捉到后退按钮按下,并且在弹出 backstack 之后,当片段与另一个片段重叠时,这个重叠的片段是可见的,所以我只是通过事务将其删除。
发生这种情况还有另一个原因:
您正在将所有片段替换到 ID 为:R.id.container
.
的视图中
假设您正在推送一个 Fragment A
,其顶级布局分配了一个 id,例如<LinearLayout android:id="@+id/rootLayout">
现在,您推送到 R.id.container
的任何其他片段都将与片段 A
重叠。
所以只要确保被推送的片段的根布局没有分配给它的 id。
只需为每个片段的父布局设置背景颜色
问题在于正确管理返回堆栈,以便弹出(或删除)前一个片段。问题在于它们重叠..
程序结构如下:
- 每个部分有 3 个片段的滑动菜单:
CatalogFragment
、NewsFragment
、BlogFragment
; - 每个片段都是一个带有项目的列表视图(从 JSON 解析);
- 在
CatalogFragment
的项目上单击 我需要将此CatalogFragment
替换为LessonsFragment
,这也是列表。
p.s。项目是俄语,但我想你可以理解
这是(动态)添加这些片段的方式:
@Override
public void onNavigationDrawerItemSelected(int position) {
FragmentManager fragmentManager = getSupportFragmentManager();
// fragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE); //this also doesn't work
switch (position+1) {
case 1:
//getSupportFragmentManager().popBackStack(); // this doesnt work
fragmentManager.beginTransaction().replace(R.id.container,
CatalogFragment.newInstance(position + 1)).addToBackStack("catalog").commit();
break;
case 2:
fragmentManager.beginTransaction().replace(R.id.container,
NewsFragment.newInstance(position + 1)).addToBackStack("news").commit();
break;
case 3:
fragmentManager.beginTransaction().replace(R.id.container,
BlogFragment.newInstance(position + 1)).addToBackStack("blog").commit();
break;
}
}
这就是我在 onCatalogFragmentInteraction
接口方法中用新片段替换片段的方式:
/** Methods for interaction with list items*/
@Override
public void onCatalogFragmentInteraction(String id){
//pop previous
getSupportFragmentManager().popBackStack("catalog", FragmentManager.POP_BACK_STACK_INCLUSIVE);
//add new
FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.container, LessonsFragment.newInstance());
fragmentTransaction.addToBackStack("lessons");
fragmentTransaction.commit();
}
...这很好用:
但是当我从滑动菜单返回片段时,片段重叠。
我认为问题出在适当的 BackStack 管理上,但我不知道我做错了什么。另一个建议是在这种情况下我需要以某种方式更好地使用 add/replace
。
我已经尝试过按名称从堆栈中删除。也许需要通过 ID 删除它们?
P.S。告诉是否需要更多代码。 提前致谢。
尝试仅传递一个空字符串作为 addToBackStack 中的片段标识符。
而不是
getSupportFragmentManager().popBackStack("catalog", FragmentManager.POP_BACK_STACK_INCLUSIVE
只需使用
getSupportFragmentManager().popBackStack();
我认为你的所有片段都有透明背景或者你没有设置任何东西(所以默认是透明的)。因此,当您 add/replace 一个片段位于另一个片段上方时,您可以看到下方片段。所以尝试为每个片段布局设置背景颜色。
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffffff"
android:orientation="vertical" >
</LinearLayout>
我猜这是你的xml片段,它可能是其他类型的布局(Relative,Frame或其他),尝试把你的背景颜色片段 xml 的 父布局 。 例如,我将白色作为背景。
我认为这不是完美的解决方案,但这对我有用。
long back_pressed;
@Override
public void onBackPressed()
{
Log.d(TAG, "HERE WAS PRESSED BACK");
int backStackEntryCount = getSupportFragmentManager().getBackStackEntryCount();
final Fragment fragment = getSupportFragmentManager().findFragmentByTag(TAG_ANSWERS_FRAGMENT);
if(null != fragment && fragment.isVisible()) {
Log.d(TAG, "visible");
showLeaveTest();
}
else {
Log.d(TAG, "invisible");
if (backStackEntryCount == 0) {
if (back_pressed + 2000 > System.currentTimeMillis()) super.onBackPressed();
else try {
Toast.makeText(this, R.string.double_press, Toast.LENGTH_SHORT).show();
} catch (Exception e) {
e.printStackTrace();
}
back_pressed = System.currentTimeMillis();
} else {
getSupportFragmentManager().popBackStack();
removeCurrentFragment(TAG_RESULT_FRAGMENT);
}
}
}
public void removeCurrentFragment(String fragmentTag)
{
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
Fragment currentFrag = getSupportFragmentManager().findFragmentByTag(fragmentTag);
String fragName = "NONE";
if (currentFrag != null)
fragName = currentFrag.getClass().getSimpleName();
Log.d(TAG, "flag name " + fragName);
if (currentFrag != null && currentFrag.isVisible())
transaction.remove(currentFrag);
transaction.commit();
}
所以,我在 activity 中捕捉到后退按钮按下,并且在弹出 backstack 之后,当片段与另一个片段重叠时,这个重叠的片段是可见的,所以我只是通过事务将其删除。
发生这种情况还有另一个原因:
您正在将所有片段替换到 ID 为:
R.id.container
. 的视图中
假设您正在推送一个 Fragment
A
,其顶级布局分配了一个 id,例如<LinearLayout android:id="@+id/rootLayout">
现在,您推送到
R.id.container
的任何其他片段都将与片段A
重叠。
所以只要确保被推送的片段的根布局没有分配给它的 id。
只需为每个片段的父布局设置背景颜色