OnBackPressed 不跟随 backstack;直接转到主页片段

OnBackPressed not following backstack; goes directly to home Fragment

我很困惑,不明白发生了什么。我的应用程序使用带有关闭 window 和主屏幕检查的 OnBackPressed,简而言之 "if home, else, use exit menu"

@Override
public void onBackPressed() {
    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    if (drawer.isDrawerOpen(GravityCompat.START)) {
        drawer.closeDrawer(GravityCompat.START);
    } else if (!viewIsAtHome) {
        displayView(R.id.nav_large_monsters);
    } else {
        new AlertDialog.Builder(this)
                .setMessage("Are you sure you want to exit?")
                .setCancelable(false)
                .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int id) {
                        Home.this.finish();
                    }
                })
                .setNegativeButton("No", null)
                .show();
    }
}

正在发生但我不想发生的事情是 按下后退会直接将我带回我的 "Large Monsters" 片段。我想让它跟在后台。

我在大型怪物页面上有大约 30 个按钮可以带你进入怪物的信息,但是按下后退会立即弹出 "Are you sure you want to quit" 菜单,而不是返回到大型怪物碎片:

Large Monsters

Pressing Back button from a Monster fragment

很明显它没有跟随后退堆栈。与任何其他屏幕一样,如果我转到任何其他片段,它会直接带我回到 Nav_Large_Monsters 而不是跟随后退堆栈。

我假设我的问题是这样的:

    } else if (!viewIsAtHome) {
        displayView(R.id.nav_large_monsters);

但是如果我删除它,应用程序会立即要求退出,而不是return home,仍然没有跟随backstack。

如果我 return 将 onBackPressed 返回到其默认代码,它将跟随 backstack,但它不会加载主页片段并以空白片段开始。

已尝试:

这也行不通。不加载主页片段。

任何帮助都会很棒!谢谢!

代码:

Home.java(MainActivity,我只是在这个项目上将它命名为 Home)

public class Home extends AppCompatActivity
    implements NavigationView.OnNavigationItemSelectedListener {
private Fragment fragment = null;
private FragmentManager fragmentManager;


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_home);
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);
    DatabaseHelper myDbHelper = new DatabaseHelper(Home.this);


    try {
        myDbHelper.createDataBase();
    } catch (IOException ioe) {
        throw new Error("Unable to create database");
    }

    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
            this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
    drawer.addDrawerListener(toggle);
    toggle.syncState();

    NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
    navigationView.setNavigationItemSelectedListener(this);
    navigationView.setItemIconTintList(null);
//        showHome();

    displayView(R.id.nav_large_monsters);

}

private boolean viewIsAtHome;

@Override
public void onBackPressed() {
    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    if (drawer.isDrawerOpen(GravityCompat.START)) {
        drawer.closeDrawer(GravityCompat.START);
    } else if (!viewIsAtHome) {
        displayView(R.id.nav_large_monsters);
    } else {
        new AlertDialog.Builder(this)
                .setMessage("Are you sure you want to exit?")
                .setCancelable(false)
                .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int id) {
                        Home.this.finish();
                    }
                })
                .setNegativeButton("No", null)
                .show();
    }
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.search_menu, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    int id = item.getItemId();
    return super.onOptionsItemSelected(item);
}

//    private void showHome() {
//        fragment = new Large_Monsters();
//        if (fragment != null) {
//            android.app.FragmentManager fragMgmt = getFragmentManager();
//            fragmentManager.beginTransaction().replace(R.id.content_frame, fragment).commit();
//        }
//    }


@SuppressWarnings("StatementWithEmptyBody")
@Override
public boolean onNavigationItemSelected(MenuItem item) {
    // Handle navigation view item clicks here.
    displayView(item.getItemId());
    return true;

}

public void displayView(int viewId) {

    Fragment fragment = null;
    String title = getString(R.string.app_name);

    switch (viewId) {
        case R.id.nav_large_monsters:
            fragment = new Large_Monsters();
            title  = "Large Monsters";
            viewIsAtHome = true;
            break;

        case R.id.nav_small_monsters:
            fragment = new Small_Monsters();
            title = "Small Monsters";
            viewIsAtHome = false;
            break;

        case R.id.nav_weapons:
            fragment = new Weapons();
            title = "Weapons";
            viewIsAtHome = false;
            break;

        case R.id.nav_armors:
            fragment = new Armors_Low_High();
            title = "Armor Sets";
            viewIsAtHome = false;
            break;

        case R.id.nav_charms:
            fragment = new Charms();
            title = "Charms";
            viewIsAtHome = false;
            break;

        case R.id.nav_items:
            fragment = new Items();
            title = "Items";
            viewIsAtHome = false;
            break;

        case R.id.palico_armor:
            fragment = new Palico_Armor();
            title = "Palico Armor";
            viewIsAtHome = false;
            break;

        case R.id.palico_gadgets:
            fragment = new Palico_Gadgets();
            title = "Palico Gadgets";
            viewIsAtHome = false;
            break;

        case R.id.palico_weps:
            fragment = new Palico_Weapons();
            title = "Palico Weapons";
            viewIsAtHome = false;
            break;

        case R.id.palico_helms:
            fragment = new Palico_Helms();
            title = "Palico Helmets";
            viewIsAtHome = false;
            break;

        default:
            fragment = new Large_Monsters();
            break;

    }

    if (fragment != null) {
        FragmentTransaction ft = getSupportFragmentManager().beginTransaction()
                .replace(R.id.content_frame, fragment, fragment.getTag())
                .addToBackStack(null);
                ft.commit();
    }

    // set the toolbar title
    if (getSupportActionBar() != null) {
        getSupportActionBar().setTitle(title);
    }

    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    drawer.closeDrawer(GravityCompat.START);

}

}

如果您要覆盖 onBackPressed,您必须自己处理回溯的撤消。这是 FragmentActivity 的作用:

/**
 * Take care of popping the fragment back stack or finishing the activity
 * as appropriate.
 */
@Override
public void onBackPressed() {
    FragmentManager fragmentManager = mFragments.getSupportFragmentManager();
    final boolean isStateSaved = fragmentManager.isStateSaved();
    if (isStateSaved && Build.VERSION.SDK_INT <= Build.VERSION_CODES.N_MR1) {
        // Older versions will throw an exception from the framework
        // FragmentManager.popBackStackImmediate(), so we'll just
        // return here. The Activity is likely already on its way out
        // since the fragmentManager has already been saved.
        return;
    }
    if (isStateSaved || !fragmentManager.popBackStackImmediate()) {
        super.onBackPressed();
    }
}

如果您跳过它,您将不会出现片段弹出行为。因此,只需更新您的 onBackPressed 以包含片段管理器的弹出 - 如果成功,您可以提前 return 因为系统会根据需要弹出片段。

@Override
public void onBackPressed() {
    // Pressing back popped the back stack, nothing else to do
    FragmentManager fragmentManager = getSupportFragmentManager();

    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    if (drawer.isDrawerOpen(GravityCompat.START)) {
        drawer.closeDrawer(GravityCompat.START);
    } else if (!fragmentManager.isStateSaved() && fragmentManager.popBackStackImmediate()) {
        return;
    } else {
        new AlertDialog.Builder(this)
                .setMessage("Are you sure you want to exit?")
                .setCancelable(false)
                .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int id) {
                        Home.this.finish();
                    }
                })
                .setNegativeButton("No", null)
                .show();
    }
}

更新

您还需要更新您的 displayView 方法,因为现在它总是 将某些东西压入堆栈。因此,您的 "home" 片段实际上将成为堆栈中的第一件事,并且会弹出并留下一个空白屏幕。因此,如果您要显示 "home" 片段,不要 在片段管理器上调用 addToBackStack

此外,您不需要在按下时显式设置 "home" 片段,因为弹出 backstack 应该做正确的事情(参见上面更新的示例)。

希望对您有所帮助!