【问题标题】:onBackPressed to Home Fragment from another Fragment in Navigation DraweronBackPressed 从导航抽屉中的另一个片段到主页片段
【发布时间】:2017-07-04 18:17:02
【问题描述】:

在我的应用程序中,我创建了一个包含六个片段的导航抽屉。 MainOption 片段不包含在导航项菜单列表中。现在我想激活移动设备上的后退按钮以重定向到主片段。例如,如果我有片段 A、B、C、D、E、F,现在如果我单击 B,那么如果我按下返回按钮,它将返回到 A。以同样的方式,如果我在片段 E 上按下返回按钮它将重定向到片段 A。现在我怎样才能在我的代码中实现这个逻辑。因此,我从网站上尝试了很多代码,但根本没有工作。这是我的导航抽屉代码片段

private NavigationView navigationView;
private DrawerLayout drawerLayout;
private Toolbar toolbar ;
private View navigationHeader;
private ImageView imgProfile;
private TextView txtName, txtWebsite;

// flag to load home fragment when user presses back key
private boolean shouldLoadHomeFragOnBackPress = true;
private Handler mHandler;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);

    mHandler = new Handler();

    drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
    navigationView = (NavigationView) findViewById(R.id.nav_view);

    // Navigation view header
    navigationHeader= navigationView.getHeaderView(0);
    txtName = navigationHeader.findViewById(R.id.username);
    txtWebsite = navigationHeader.findViewById(R.id.email);
    imgProfile = navigationHeader.findViewById(R.id.profile_image);

    // load nav menu header data
    loadNavHeader();

    //Set the Home Fragment initially
    OptionMenuFragment fragment = new OptionMenuFragment();
    android.support.v4.app.FragmentTransaction fragmentTransaction =
            getSupportFragmentManager().beginTransaction();
    fragmentTransaction.replace(R.id.fragment_container, fragment, "OptionMenuFragment");
    fragmentTransaction.commit();

    ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
            this, drawerLayout, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
    drawerLayout.setDrawerListener(toggle);
    toggle.syncState();

    navigationView.setNavigationItemSelectedListener(this);
 }

 private void loadNavHeader() {
    // name, website
    txtName.setText("Hallo");
    txtWebsite.setText("mail.com");
    imgProfile.setImageResource(R.drawable.profile_image);

    //ToDo: Image should be uploaded from web
}

 String lastFragmentTag;
 boolean showingFirstFragment = true;

 public void addNewFragment(Fragment fragment, String fragmentTag) {
    FragmentManager fragmentManager = getSupportFragmentManager();
    FragmentTransaction transaction = fragmentManager.beginTransaction();

    if (lastFragmentTag != null) {
        Fragment currentFragment = fragmentManager.findFragmentByTag(lastFragmentTag);
        transaction.remove(currentFragment);
    } else {
        Fragment currentFragment = fragmentManager.findFragmentById(R.id.fragment_container);
        transaction.hide(currentFragment);
    }

    transaction.add(R.id.fragment_container, fragment, fragmentTag);
    transaction.commit();

    lastFragmentTag = fragmentTag;
    showingFirstFragment = false;

 }
 @Override
 public void onBackPressed() {
    //Here we're gonna remove the last fragment added, and show OptionMenuFragment again
    if (!showingFirstFragment)
    {
        FragmentManager fragmentManager = getSupportFragmentManager();
        FragmentTransaction transaction = fragmentManager.beginTransaction();

        Fragment firstFragment = fragmentManager.findFragmentByTag("OptionMenuFragment");
        Fragment currentFragment = fragmentManager.findFragmentByTag(lastFragmentTag);

        transaction.remove(currentFragment);
        transaction.show(firstFragment);

        transaction.commit();

        showingFirstFragment = true;
    } else {
        super.onBackPressed();
    }
 }


 @Override
 public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.menu_main, menu);
    return true;
 }

 @Override
 public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();

    //noinspection SimplifiableIfStatement
    if (id == R.id.blu_home) {
        Intent intent = new Intent(this, MainOptionPage.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        startActivity(intent);
        return true;
    }
    return super.onOptionsItemSelected(item);
  }


 @SuppressWarnings("StatementWithEmptyBody")
 @Override
 public boolean onNavigationItemSelected(MenuItem item) {

    String fragmentTag=null;
    // Handle navigation view item clicks here.
    Fragment fragment = null;
    FragmentManager fragmentManager = getSupportFragmentManager();
    switch (item.getItemId()) {
        case R.id.view_profile:
            fragment = new ViewProfileFragment();
            fragmentTag = "ViewProfileFragment";
            break;
        case R.id.todo_list:
            fragment =new ToDoListFragment();
            fragmentTag="ToDoListFragment";
            break;
        case R.id.logout:
            showAlertDialogLogOut();
            break;
        case R.id.settings:
            fragment = new SettingsFragment();
            fragmentTag="SettingFragment";
            break;
        case R.id.about:
            fragment = new AboutFragment();
            fragmentTag="AboutFragment";
            break;
        case R.id.info:
            fragment=new InfoFragment();
            fragmentTag="InfoFragment";
            break;
    }
    if(fragment!=null){
        fragmentManager.beginTransaction().replace(R.id.fragment_container, fragment).commit();
    }
    drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
    drawerLayout.closeDrawer(GravityCompat.START);
    return true;
 }

 private void showAlertDialogLogOut() {

    AlertDialog.Builder builder = new AlertDialog.Builder(this);

    builder.setTitle("Logout");
    builder.setMessage("Are you sure you want to log out?");

    builder.setPositiveButton("YES", new DialogInterface.OnClickListener() {

        public void onClick(DialogInterface dialog, int which) {
            // close the dialog, go to login page
            dialog.dismiss();
            startActivity(new Intent(MainOptionPage.this, LoginPage.class));
        }
    });

    builder.setNegativeButton("NO", new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
            // Do nothing
            dialog.dismiss();
        }
    });

    AlertDialog alert = builder.create();
    alert.show();
  }
}

【问题讨论】:

    标签: android android-fragments navigation-drawer onbackpressed


    【解决方案1】:

    对于这种方法,您将希望使用 add(containerViewId, fragment, tag) 方法而不是 replace(containerViewId, fragment),因为在添加之前,replace 将对之前添加到容器中的所有片段调用 remove(Fragment)新片段。此外,您还需要使用 addToBackStack(name)。

    这是我为一个项目创建的方法,并为您稍作修改:

    String lastFragmentTag;
    boolean showingFirstFragment = true;
    
    public void addNewFragment(Fragment fragment, String fragmentTag) {
        FragmentManager fragmentManager = getSupportFragmentManager();
        FragmentTransaction transaction = fragmentManager.beginTransaction();
    
        if (lastFragmentTag != null) {
            Fragment currentFragment = fragmentManager.findFragmentByTag(lastFragmentTag);
            transaction.remove(currentFragment);
        } else {
            Fragment currentFragment = fragmentManager.findFragmentById(R.id.fragment_container);
            transaction.hide(currentFragment);
        }
    
        transaction.add(R.id.fragment_container, fragment, fragmentTag);
        transaction.commit();
    
        lastFragmentTag = fragmentTag;
        showingFirstFragment = false;
    }
    

    然后你只需要在 onNavigationItemSelected 内部进行这个更改:

    Fragment fragment = null;
    FragmentManager fragmentManager = getSupportFragmentManager();
    
    String fragmentTag;
    
    switch (item.getItemId()) {
        case R.id.view_profile:
            fragment = new ViewProfileFragment();
            fragmentTag = "ViewProfileFragment";
    
            break;
        ...
    }
    
    if(fragment!=null){
            addNewFragment(fragment, fragmentTag);
    }
    

    其中“fragmentTag”将是一个字符串变量,您可以根据实例化的片段进行更改。

    编辑:由于代码未按预期工作,因此进行了一些更改:

    @Override
    public void onBackPressed() {
        //Here we're gonna remove the last fragment added, and show OptionMenuFragment again
        if (!showingFirstFragment)
        {
            FragmentManager fragmentManager = getSupportFragmentManager();
            FragmentTransaction transaction = fragmentManager.beginTransaction();
    
            Fragment firstFragment = fragmentManager.findFragmentByTag("OptionMenuFragment");
            Fragment currentFragment = fragmentManager.findFragmentByTag(lastFragmentTag);
    
            transaction.remove(currentFragment);
            transaction.show(firstFragment);
    
            transaction.commit();
    
            showingFirstFragment = true;
        } else {
            super.onBackPressed();
        }
    }
    

    当添加 OptionMenuFragment 时,改为这样做:

    fragmentTransaction.replace(R.id.fragment_container, fragment, "OptionMenuFragment");
    

    【讨论】:

    • 片段标签我不清楚。是 homeFragment 还是请您多解释一下。此代码无效
    • 片段标签将唯一标识您的每个片段,因此您可以稍后使用 fragmentManager.findFragmentByTag(tag) 再次获取它们。我编辑了答案,希望现在更清楚了。
    • @Tharius 谢谢。这可能是题外话。但我需要知道这一点。我是否必须首先声明每个片段。例如字符串 ViewProfileTag、字符串 ToDoList 等...
    • 这段代码的问题是,这样所有其他的片段都加载在MainOptionMenu页面上。它就像用片段重载了主页。但我想在加载其他片段时替换 mainOptionMenu 页面。
    • 我应该只修改我的 onBackPressed() 方法,然后在 oncreate 方法中修改 Optionmenu 片段事务。我还有另一个问题,我怎样才能在 onBackpress 方法中获取显示FirstFragment 变量。我的意思是我应该像这个布尔值一样初始化 ShowFirstFragment=true;因此我修改了我的代码。但它仍然无法正常工作
    猜你喜欢
    • 1970-01-01
    • 2022-01-02
    • 2018-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-16
    • 2016-01-03
    • 1970-01-01
    相关资源
    最近更新 更多