OnBackPressed不跟随后退;直接回家碎片 [英] OnBackPressed not following backstack; goes directly to home Fragment

查看:89
本文介绍了OnBackPressed不跟随后退;直接回家碎片的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在泡菜中,无法理解发生了什么.我的应用程序使用带有关闭窗口和主屏幕检查的OnBackPressed,总之如果要回家,请使用退出菜单"

I'm in a pickle and can't understand what's going on. I have my app using an OnBackPressed with a closing window and a home screen check, in short "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();
    }
}

我不想发生的事情是,后退使我直接回到我的大怪物"片段.我想让它跟在栈后.

What's happening that I don't want happening is that pressing back takes me straight back to my "Large Monsters" fragment. I'm wanting this to follow the backstack.

我在大型怪物"页面上有大约30个按钮,可带您进入怪物的信息,但是立即按回去会弹出您确定要退出"菜单,而不是返回到大型怪物片段:

I have about 30 buttons on the Large Monsters page that takes you into a Monster's information, but pressing back immediately brings up the "Are you sure you want to quit" menu, instead of going back to the Large Monster Fragment:

大型怪物

从怪物片段中按后退"按钮

很显然,它并没有跟进栈.与其他任何屏幕一样,如果我执行其他任何片段,它将直接将我带回到Nav_Large_Monsters,而不是跟随后退堆栈.

Clearly it's not following the backstack. Same with any other screen, if I go any other fragment, it'll take me straight back to Nav_Large_Monsters instead of following the backstack.

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

I'm assuming my issue is this:

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

但是,如果我将其删除,则该应用将希望立即要求退出,而不是返回家乡,仍然不追随退堆.

But if I remove it, the app will want to immediately ask for exit, not return home, still not following the backstack.

如果我将onBackPressed返回其默认代码,它将遵循Backstack,但不会加载主片段并以空白片段开头.

If I return the onBackPressed back to its default code, it'll follow backstack, but it won't load a home fragment and start with a blank fragment.

  • 我试图删除onBackPressed中的"else if(!viewIsAtHome)"部分,并在我的onNavigationItemSelected方法中实现了默认"

  • I've attempted to remove the " else if (!viewIsAtHome)" section in onBackPressed, and implemented "default" in my onNavigationItemSelected method

default:
fragment = new Large_Monsters();
break;

这也行不通.不加载主片段.

This too did not work. Does not load a home fragment.

  • 以前,我有一个showHome()方法,该DID可以使用backStack并使用home片段,但是将Fragments更改为v4.support.app.Fragment之后,我不得不进行更改我的家庭活动如何处理onNavigationItemSelected.它不喜欢我的showHome方法,并不断指出我使用的是旧的FragmentManager而不是v4.support.app.FragmentManager(此方法导致我的应用程序在更改为v4后立即崩溃):

  • Previously I had a showHome() method, and this DID work for being able to use the backStack and use a home fragment, but after changing my Fragments to v4.support.app.Fragment, I had to change up how my Home Activity handled my onNavigationItemSelected. It did not like my showHome method and kept calling out that I was using the old FragmentManager and not v4.support.app.FragmentManager(this method caused my app to crash immediately after changing to v4):

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

}

我还尝试添加有关弹出backStack的If语句,但这似乎没有任何效果:

I also attempted adding an If statement about popping backStack, and this did not seem to do anything productive:

if (!fragment.getFragmentManager().popBackStackImmediate()) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        finishAfterTransition();
    }
}

  • 我还尝试添加一个If语句来检查Backstack是否> 0,但这也无济于事,尽管我删除了该字符串并不确定在哪里找到它.也许我构建的字符串不正确.

  • I also attempted adding an If statement checking if Backstack was > 0 but that also did not help, although I deleted that string and unsure where I found it. Maybe I built that string incorrectly.

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

    Any assistance would be great! Thanks!

    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 的作用:

    If you're going to override onBackPressed, you have to handle the undoing of the backstrack yourself. This is what a FragmentActivity does:

    /**
     * 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 使其包含片段管理器的弹出窗口-如果成功,则您可以提早返回,因为系统已根据需要执行了弹出片段的操作.

    If you skip that, you don't get the fragment popping behavior. So just update your onBackPressed to include a pop of the fragment manager - if it succeeds, you can return early because the system did its thing popping the fragment as desired.

    @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"片段实际上将是堆栈上的第一件事,并且会弹出并显示空白屏幕.因此,如果要显示主"片段,请不要在片段管理器上调用 addToBackStack .

    You also need to update your displayView method, because right now it's always pushing something on the stack. So your "home" fragment will actually be the first thing on the stack and will pop leaving you with a blank screen. So if you're showing the "home" fragment, do not call addToBackStack on the fragment manager.

    此外,您不需要在按下时显式设置"home"片段,因为弹出backstack应该可以正确处理(请参见上面的更新示例).

    Further, you should not need to explicitly set the "home" fragment on pressing back as popping the backstack should do the right thing (see updated example above).

    希望有帮助!

    这篇关于OnBackPressed不跟随后退;直接回家碎片的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆