导航抽屉,处理后退按钮以转到以前的片段?
Posted
技术标签:
【中文标题】导航抽屉,处理后退按钮以转到以前的片段?【英文标题】:Navigation drawer, handling the back button to go to previous fragments? 【发布时间】:2014-02-01 07:36:12 【问题描述】:我正在使用内置的导航抽屉来运行我的应用程序。我不太清楚如何处理后退按钮。当它被按下时,我希望它再次加载第一个片段。片段1。
因此,当应用启动时,您会看到 Fragment1 启动。然后,他们可以单击片段 2-5 转到其他页面。在所有这些页面中,我希望后退按钮将用户带回 Fragment1。用户应该能够通过返回按钮退出应用程序的唯一位置是 Fragment1。
因为这一切都是由 FragmentActivity 处理的,所以我试着在那里弄乱后退按钮。但是,我不断收到强制关闭错误:
(01-11 14:09:33.114: E/androidRuntime(8292): android.view.InflateException: Binary XML file line #7: Error inflating class fragment)
这是我目前所拥有的:
我已确保将片段添加到后台堆栈,如下所示:
fm.beginTransaction().replace(R.id.main, newFragment).addToBackStack("fragBack").commit();
返回按钮:
@Override
public void onBackPressed()
if (getSupportFragmentManager().findFragmentByTag("fragBack") != null)
else
super.onBackPressed();
return;
if (getSupportFragmentManager().getBackStackEntryCount() != 0)
Toast.makeText(getApplicationContext(), "Test", Toast.LENGTH_LONG).show();
Fragment frag = getSupportFragmentManager().findFragmentByTag("fragBack");
FragmentTransaction transac = getSupportFragmentManager().beginTransaction().remove(frag);
transac.commit();
有人知道我需要做什么吗?我是否需要在每个片段(如果可能的话)中调用 onBackPressed 而不是控制抽屉的 FragmentActivity ?在我过去的应用程序中,无论用户在哪个 Fragment 上,我都可以使用后退按钮关闭应用程序,但我现在正在制作的那个我希望后退按钮返回到 Fragment1。
非常感谢您的帮助,谢谢。
onItemClick
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l)
Fragment newFragment = new MapsPage();
FragmentManager fm = getSupportFragmentManager();
switch(i)
case 0:
newFragment = new Fragment2();
break;
case 1:
newFragment = new Fragment3();
break;
case 2:
newFragment = new Fragment4();
break;
case 3:
newFragment = new Fragment5();
break;
fm.beginTransaction().add(R.id.main, newFragment).addToBackStack("fragback").commit();
drawerLayout.closeDrawer(rl);
【问题讨论】:
它应该可以在不向 onBackkeypressed 添加任何代码的情况下工作。您遇到的与布局相关的错误您也可以发布您的布局吗? 真的吗?在我所有的导航抽屉中,后退按钮总是退出应用程序。无论用户选择继续使用什么 Fragment。我的布局中有自定义插件,但它是标准布局,我不认为这是我的问题,但我会发布它。 在提交之前,您需要在FragmentTrasaction
中使用addToBackStack()
方法(您正在这样做)。你不需要做更多的事情,后退按钮就可以带你回到上一个片段
vipul也是对的,你得到的错误是你的布局文件有问题
是的,只需在提交之前将 Fragment1 添加到 backstack,无论用户在哪个 Fragment 上,按下后退按钮都会将他带到 Fragment1。还要确保不要将其他 Fragments 添加到 backstack
【参考方案1】:
代替:
fm.beginTransaction().replace(R.id.main, newFragment).addToBackStack("fragBack").commit();
呼叫:
fm.beginTransaction().add(R.id.main, newFragment).addToBackStack("fragBack").commit();
addToBackStack 适用于add
。
replace
函数删除前一个片段并放置新片段,因此在您的后台堆栈中始终只有一个片段。所以使用 add 函数将之前的片段保留在堆栈中。
要始终从任何片段 onBackPress 转到 fragemnt1,请尝试执行以下操作:
getFragmentManager().popBackStack();
fm.beginTransaction().add(R.id.main, newFragment).addToBackStack("fragBack").commit();
这将从 backstack 中删除最后一个事务并添加新事务。 试试这个。
【讨论】:
谢谢。这有助于让 backstack 工作。你知道我怎样才能让它总是回到 Fragment1 吗?所以他们可以转到片段 2,然后是 3,但按后退按钮会将他们带到片段 1。如果您需要,我可以发布完整的 onItemClick。 这只是一个猜测 - 但是如果您在任何其他片段之间进行更改时不调用addToBackStack()
方法(仅在离开您的片段1时调用它),那么可能会这样做它
这听起来很合乎逻辑。我已经发布了我的 onItemClick 以获得更好的想法。
只有从 fragment1 移动时才调用 addToBackStack
我认为这里的问题可能是 Fragment 1(MapsPage) 不是导航抽屉的一部分。 (或者这不是问题吗?)。在我的代码中,当您启动应用程序时会显示片段 1,但返回它的唯一方法是返回按钮。这对我正在构建的东西很有意义。它不在导航列表中。【参考方案2】:
只是想报告我的发现,尽管对于其他可能对已接受的答案有同样问题的人来说,这个问题有点老了。对我来说,按照接受的答案中建议的方法,使图层重叠,很快使它们变得不可读。下面的代码(改编自接受的答案)避免了覆盖,但仍将屏幕添加到后台堆栈。
fragmentManager.beginTransaction().replace(R.id.container, fragment).addToBackStack("fragBack").commit();
【讨论】:
【参考方案3】:在某些情况下,您必须使用替换,然后您无法使用 addtobackstack(),因此您可以在 MainActivity 中使用此代码。在这段代码中,当你按下返回键时,你总是会转到第一个片段(我称之为 HomeFragment),当你在 HomeFragment 中时,它会询问两次从应用程序中退出的时间。
private Boolean exit = false;
@Override
public void onBackPressed()
if (exit)
super.onBackPressed();
return;
try
FragmentManager fragmentManager = getSupportFragmentManager();
Fragment fragment = fragmentManager.findFragmentByTag("HOME");
if (fragment != null)
if (fragment.isVisible())
this.exit = true;
Toast.makeText(this, "Press Back again to Exit", Toast.LENGTH_SHORT).show();
else
fragment = HomeFragment.class.newInstance();
getFragmentManager().popBackStack();
fragmentManager.beginTransaction().replace(R.id.flContent, fragment, "HOME").commit();
catch (Exception e)
new Handler().postDelayed(new Runnable()
@Override
public void run()
exit = false;
, 2000);
【讨论】:
【参考方案4】: - @Override
public void onBackPressed()
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
int backstack = getSupportFragmentManager().getBackStackEntryCount();
if (drawer.isDrawerOpen(GravityCompat.START))
drawer.closeDrawer(GravityCompat.START);
else if (backstack > 0)
for (int i = 0; i < backstack; i++)
getSupportFragmentManager().popBackStackImmediate();
else
this.finish();
【讨论】:
为了改善您的答案,也许您可以添加一些关于您的解决方案的描述文本【参考方案5】:我有 4 个片段附加到底部导航活动 我最近遇到了这个问题并成功解决如下 我的活动代码
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentTransaction;
import androidx.navigation.NavController;
import androidx.navigation.Navigation;
import androidx.navigation.ui.NavigationUI;
import android.os.Bundle;
import android.view.MenuItem;
import com.google.android.material.bottomnavigation.BottomNavigationView;
public class BottomNavigationActivity extends AppCompatActivity
NavController navController;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bottom_navigation);
BottomNavigationView bottomNavigationView=findViewById(R.id.bottom_navigation);
bottomNavigationView.setOnNavigationItemSelectedListener(navListener);
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,new FragmentHome()).commit();
public boolean onSupportNavigateUp()
return navController.navigateUp();
private BottomNavigationView.OnNavigationItemSelectedListener navListener= new
BottomNavigationView.OnNavigationItemSelectedListener()
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item)
Fragment selectedFragment = null ;
switch (item.getItemId())
case R.id.nav_home:
selectedFragment = new FragmentHome();
break;
case R.id.nav_search:
BottomNavigationActivity.this.getSupportFragmentManager().beginTransaction()
.addToBackStack(null)
.commit();
selectedFragment=new FragmentSearch();
break;
case R.id.nav_cart:
BottomNavigationActivity.this.getSupportFragmentManager().beginTransaction()
.addToBackStack(null)
.commit();
selectedFragment=new FragmentCart();
break;
case R.id.nav_user:
BottomNavigationActivity.this.getSupportFragmentManager().beginTransaction()
.addToBackStack(null)
.commit();
selectedFragment= new FragmentAccount();
break;
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
selectedFragment).commit();
return true;
;
@Override
public void onBackPressed()
int backStackEntryCount = getSupportFragmentManager().getBackStackEntryCount();
if (backStackEntryCount == 0)
super.onBackPressed();
else
goHome();
public void goHome()
//Following code will set the icon of the bottom navigation to active
final BottomNavigationView mBottomNav = findViewById(R.id.bottom_navigation);
MenuItem homeItem = mBottomNav.getMenu().getItem(0);
mBottomNav.setSelectedItemId(homeItem.getItemId());
getSupportFragmentManager().popBackStackImmediate();
//To delete all entries from back stack immediately one by one.
int backStackEntry = getSupportFragmentManager().getBackStackEntryCount();
for (int i = 0; i < backStackEntry; i++)
getSupportFragmentManager().popBackStackImmediate();
//To navigate to the Home Fragment
final FragmentHome homeFragment = new FragmentHome();
FragmentTransaction myFragmentTransaction = getSupportFragmentManager().beginTransaction();
myFragmentTransaction.replace(R.id.fragment_container, homeFragment, "HomeFrag Tag");
myFragmentTransaction.commit();
【讨论】:
【参考方案6】:我建议首先通过正确管理您的交易来完全避免覆盖onBackPressed()
。这将有助于避免在未来实施疯狂的逻辑。
首先,我们需要设置一个私有类变量来启用初始化:
private boolean popNext = false;
以下代码允许我们通过将初始返回函数放入堆栈来设置它。此后每次,当 popNext
设置为 true 时,我们弹出初始事务并推送新事务。因此,我们将 1>X 交易替换为 1>Y 交易。
额外嵌入的 if
语句处理选择初始项目,因为我们不想从 1>1 开始。如果这是我们最初的案例,我们只需关闭抽屉。另一种情况需要像返回按钮一样,但我们需要记住将它设置为返回初始状态!
if(popNext)
if(i == INITIAL_POSITION)
onBackPressed();
mDrawerLayout.closeDrawer(mDrawerList);
popNext = false;
return;
getFragmentManager().popBackStackImmediate();
else
if(i == INITIAL_POSITION)
mDrawerLayout.closeDrawer(mDrawerList);
return;
popNext=true;
getFragmentManager()
.beginTransaction()
.replace(R.id.fragment_container, fragment)
.addToBackStack(null)
.commit();
注意:我的代码使用 getFragmentManager()
而不是 getSupportFragmentManager()
,这是一个本机函数,我相信是 Honeycomb。
【讨论】:
以上是关于导航抽屉,处理后退按钮以转到以前的片段?的主要内容,如果未能解决你的问题,请参考以下文章