对 Android 片段交易发疯
Going mad with Android Fragment Transaction
我无法理解我的片段交易的这种行为。在我发疯之前有人可以干预吗?在我的 MainActivity 中,我正确设置了它:
private final GuideFragment guideFragment = new GuideFragment();
private final MapFragment mapFragment = new MapFragment();
private final MoreFragment moreFragment = new MoreFragment();
Fragment active;
private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
= new BottomNavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
FragmentTransaction transaction = getFragmentManager().beginTransaction();
switch (item.getItemId()) {
case R.id.navigation_guide:
if (!guideFragment.isAdded()) {
transaction.add(R.id.content,guideFragment).commit();
active = guideFragment;
Log.d(TAG, "add Fragment1");
break;
} else {
transaction.hide(active).show(guideFragment).commit();
active = guideFragment;
Log.d(TAG, "show Fragment1");
break;
}
case R.id.navigation_map:
if (!mapFragment.isAdded()) {
transaction.add(R.id.content, mapFragment).commit();
active = mapFragment;
Log.d(TAG,"add Fragment2");
break;
} else {
transaction.hide(active).show(mapFragment).commit();
active = mapFragment;
Log.d(TAG,"show Fragment2");
break;
}
case R.id.navigation_more:
if (!moreFragment.isAdded()) {
transaction.add(R.id.content,moreFragment).commit();
active = moreFragment;
Log.d(TAG,"add Fragment3");
break;
} else {
transaction.hide(active).show(moreFragment).commit();
active = moreFragment;
Log.d(TAG,"show Fragment3");
break;
}
}
return true;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_start);
//start with guide view/fragment
switchTabView(R.id.navigation_guide);
}
//method to start or switch a tab
private void switchTabView(int itemId) {
navigation = (BottomNavigationView) findViewById(R.id.navigation);
navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
navigation.setSelectedItemId(itemId);
}
我的应用有 3 个选项卡,如上所示:Tab1(指南)Tab2(地图)Tab3(更多)。
当应用程序启动时,第一个选项卡(指南)被添加并正确显示。
然后我点击地图(下一个片段),它被添加并正确显示。
终于在“更多”选项卡(我的第 3 个选项卡)上一切正常。
但是当 activity 启动并且我点击 1-3(地图指南)到目前为止是正确的 -
然后 3-2(更多选项卡到地图选项卡)都很好 - 但是 然后从 2-1(地图到指南)返回 突然出现第 3 个选项卡片段(更多)显示指南片段应该是。
有人知道哪里出了问题吗?
希望得到一些帮助。
感谢 Mateus 的解决方案
transaction.hide(fragment3).hide(fragment2).show(fragment1).commit();
我不确定调用两次隐藏片段是否干净,但我认为使用 3 个选项卡仍然可以。对于更多选项卡,我会考虑以不同的方式处理这个问题,例如 remove() 或 replace() 片段。
更新 - 解决方案如预期的那样更棘手:
switch (item.getItemId()) {
case R.id.navigation_guide:
if (!guideFragment.isAdded()) {
transaction.add(R.id.content,guideFragment).commit();
Log.d(TAG, "add Fragment1");
break;
} else {
if (!moreFragment.isAdded() && mapFragment.isAdded()) {
transaction.hide(mapFragment).show(guideFragment).commit();
}
if (moreFragment.isAdded() && !mapFragment.isAdded()) {
transaction.hide(moreFragment).show(guideFragment).commit();
}
if (moreFragment.isAdded() && mapFragment.isAdded()) {
transaction.hide(moreFragment).hide(mapFragment).show(guideFragment).commit();
}
Log.d(TAG, "show Fragment1");
break;
}
case R.id.navigation_map:
if (!mapFragment.isAdded()) {
transaction.add(R.id.content, mapFragment).commit();
Log.d(TAG,"add Fragment2");
break;
} else {
if (!moreFragment.isAdded()) {
transaction.hide(guideFragment).show(mapFragment).commit();
} else {
transaction.hide(guideFragment).hide(moreFragment).show(mapFragment).commit();
}
Log.d(TAG,"show Fragment2");
break;
}
case R.id.navigation_more:
if (!moreFragment.isAdded()) {
transaction.add(R.id.content,moreFragment).commit();
Log.d(TAG,"add Fragment3");
break;
} else {
if (!mapFragment.isAdded()) {
transaction.hide(guideFragment).show(moreFragment).commit();
} else {
transaction.hide(guideFragment).hide(mapFragment).show(moreFragment).commit();
}
Log.d(TAG,"show Fragment3");
break;
}
}
终于没有bug了,还得看看有没有添加其他片段!
在你从 2 返回到 1 的那一点,这一行将被称为:
transaction.hide(active).show(guideFragment).commit();
问题是,当您隐藏活动(片段 2)并显示片段 1 时,片段 3(添加在片段 1 之后,因此是片段 1 的 "on top")仍在显示。您也必须在 Fragment 3 上调用 hide 才能看到 Fragment 1。
换句话说,每次要显示特定片段时,您都需要调整代码以隐藏所有其他片段。
另请检查 this discussion 关于在 show/hide 和 add/remove/replace 之间进行选择的内容,以确认第一种策略更适合您的需要。
当我想转到同一 activity 中的另一个片段时,我使用这个:
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.container,yourFragment);
transaction.commit();
容器是您 activity 中的布局。用它来显示你的片段。
此外,您还必须在 bottomNavigationView
的每种情况下初始化 FragmentTransaction
对象!
我相信这就是您要找的!
我无法理解我的片段交易的这种行为。在我发疯之前有人可以干预吗?在我的 MainActivity 中,我正确设置了它:
private final GuideFragment guideFragment = new GuideFragment();
private final MapFragment mapFragment = new MapFragment();
private final MoreFragment moreFragment = new MoreFragment();
Fragment active;
private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
= new BottomNavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
FragmentTransaction transaction = getFragmentManager().beginTransaction();
switch (item.getItemId()) {
case R.id.navigation_guide:
if (!guideFragment.isAdded()) {
transaction.add(R.id.content,guideFragment).commit();
active = guideFragment;
Log.d(TAG, "add Fragment1");
break;
} else {
transaction.hide(active).show(guideFragment).commit();
active = guideFragment;
Log.d(TAG, "show Fragment1");
break;
}
case R.id.navigation_map:
if (!mapFragment.isAdded()) {
transaction.add(R.id.content, mapFragment).commit();
active = mapFragment;
Log.d(TAG,"add Fragment2");
break;
} else {
transaction.hide(active).show(mapFragment).commit();
active = mapFragment;
Log.d(TAG,"show Fragment2");
break;
}
case R.id.navigation_more:
if (!moreFragment.isAdded()) {
transaction.add(R.id.content,moreFragment).commit();
active = moreFragment;
Log.d(TAG,"add Fragment3");
break;
} else {
transaction.hide(active).show(moreFragment).commit();
active = moreFragment;
Log.d(TAG,"show Fragment3");
break;
}
}
return true;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_start);
//start with guide view/fragment
switchTabView(R.id.navigation_guide);
}
//method to start or switch a tab
private void switchTabView(int itemId) {
navigation = (BottomNavigationView) findViewById(R.id.navigation);
navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
navigation.setSelectedItemId(itemId);
}
我的应用有 3 个选项卡,如上所示:Tab1(指南)Tab2(地图)Tab3(更多)。
当应用程序启动时,第一个选项卡(指南)被添加并正确显示。 然后我点击地图(下一个片段),它被添加并正确显示。 终于在“更多”选项卡(我的第 3 个选项卡)上一切正常。
但是当 activity 启动并且我点击 1-3(地图指南)到目前为止是正确的 - 然后 3-2(更多选项卡到地图选项卡)都很好 - 但是 然后从 2-1(地图到指南)返回 突然出现第 3 个选项卡片段(更多)显示指南片段应该是。
有人知道哪里出了问题吗? 希望得到一些帮助。
感谢 Mateus 的解决方案
transaction.hide(fragment3).hide(fragment2).show(fragment1).commit();
我不确定调用两次隐藏片段是否干净,但我认为使用 3 个选项卡仍然可以。对于更多选项卡,我会考虑以不同的方式处理这个问题,例如 remove() 或 replace() 片段。
更新 - 解决方案如预期的那样更棘手:
switch (item.getItemId()) {
case R.id.navigation_guide:
if (!guideFragment.isAdded()) {
transaction.add(R.id.content,guideFragment).commit();
Log.d(TAG, "add Fragment1");
break;
} else {
if (!moreFragment.isAdded() && mapFragment.isAdded()) {
transaction.hide(mapFragment).show(guideFragment).commit();
}
if (moreFragment.isAdded() && !mapFragment.isAdded()) {
transaction.hide(moreFragment).show(guideFragment).commit();
}
if (moreFragment.isAdded() && mapFragment.isAdded()) {
transaction.hide(moreFragment).hide(mapFragment).show(guideFragment).commit();
}
Log.d(TAG, "show Fragment1");
break;
}
case R.id.navigation_map:
if (!mapFragment.isAdded()) {
transaction.add(R.id.content, mapFragment).commit();
Log.d(TAG,"add Fragment2");
break;
} else {
if (!moreFragment.isAdded()) {
transaction.hide(guideFragment).show(mapFragment).commit();
} else {
transaction.hide(guideFragment).hide(moreFragment).show(mapFragment).commit();
}
Log.d(TAG,"show Fragment2");
break;
}
case R.id.navigation_more:
if (!moreFragment.isAdded()) {
transaction.add(R.id.content,moreFragment).commit();
Log.d(TAG,"add Fragment3");
break;
} else {
if (!mapFragment.isAdded()) {
transaction.hide(guideFragment).show(moreFragment).commit();
} else {
transaction.hide(guideFragment).hide(mapFragment).show(moreFragment).commit();
}
Log.d(TAG,"show Fragment3");
break;
}
}
终于没有bug了,还得看看有没有添加其他片段!
在你从 2 返回到 1 的那一点,这一行将被称为:
transaction.hide(active).show(guideFragment).commit();
问题是,当您隐藏活动(片段 2)并显示片段 1 时,片段 3(添加在片段 1 之后,因此是片段 1 的 "on top")仍在显示。您也必须在 Fragment 3 上调用 hide 才能看到 Fragment 1。
换句话说,每次要显示特定片段时,您都需要调整代码以隐藏所有其他片段。
另请检查 this discussion 关于在 show/hide 和 add/remove/replace 之间进行选择的内容,以确认第一种策略更适合您的需要。
当我想转到同一 activity 中的另一个片段时,我使用这个:
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.container,yourFragment);
transaction.commit();
容器是您 activity 中的布局。用它来显示你的片段。
此外,您还必须在 bottomNavigationView
的每种情况下初始化 FragmentTransaction
对象!
我相信这就是您要找的!