单活动多片段导航问题

时间:2018-08-08 12:47:46

标签: android android-fragments

我的主要活动是主持多个片段。我有一个基本片段类,所有其他片段都继承了该片段。

我有一个主屏幕片段,其中有一些按钮可以显示子片段。现在,在子片段中,我有一些按钮显示其子片段。现在,当我单击“后退”按钮时,我应该返回上一个片段,从该片段我已经打开了当前片段,但是它始终将我带到主屏幕片段。

这就是我编写主要活动代码的方式

public class MainActivity extends AppCompatActivity implements 
FragmentDrawer.FragmentDrawerListener, View.OnClickListener {


private Context context;
public HashMap<String, Stack<BaseFragment>> mStacks;

private static String TAG = MainActivity.class.getSimpleName();

private Toolbar mToolbar;
private FragmentDrawer drawerFragment;

private TextView toolbarTitle,toolbar_signout;
public String mCurrentTab;

private ActionBar actionBar;
public BaseFragment fragment = null;
public String title;

private DrawerLayout drawer_layout;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    context = this;

    mToolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(mToolbar);
    actionBar = getSupportActionBar();

    actionBar.setDisplayShowHomeEnabled(true);
    actionBar.setDisplayShowTitleEnabled(false);

    toolbarTitle = (TextView) findViewById(R.id.toolbar_title);
    toolbar_signout = (TextView) findViewById(R.id.toolbar_signout);
    toolbar_signout.setOnClickListener(this);
  //  toolbarSettings = (ImageView) findViewById(R.id.toolbar_settings);

    mStacks = new HashMap<String, Stack<BaseFragment>>();
    mStacks.put(MyConstants.TAB_HOME, new Stack<BaseFragment>());
    mStacks.put(MyConstants.TAB_INCIDENTS, new Stack<BaseFragment>());
    mStacks.put(MyConstants.TAB_LICENSE, new Stack<BaseFragment>());
    mStacks.put(MyConstants.TAB_SCHEDULE, new Stack<BaseFragment>());
    mStacks.put(MyConstants.TAB_CREATE, new Stack<BaseFragment>());
    mStacks.put(MyConstants.TAB_SCHEDULE_DETAILS, new Stack<BaseFragment>());
    mStacks.put(MyConstants.TAB_CHECKLIST_WAREHOUSE, new Stack<BaseFragment>());
    mStacks.put(MyConstants.TAB_UPLOAD_FILES, new Stack<BaseFragment>());

    drawerFragment = (FragmentDrawer)
            getSupportFragmentManager().findFragmentById(R.id.fragment_navigation_drawer);
    drawerFragment.setUp(R.id.fragment_navigation_drawer, (DrawerLayout) findViewById(R.id.drawer_layout), mToolbar);
    drawerFragment.setDrawerListener(this);

enter code here
    displayView(0);
}


@Override
public void onDrawerItemSelected(View view, int position) {
    displayView(position);
}

private void displayView(int position) {

    title = getString(R.string.app_name);
    switch (position) {
        case 0:
            mCurrentTab = MyConstants.TAB_HOME;
            mStacks.get(mCurrentTab).clear();
            fragment = new HomeFragment();
            pushFragments(mCurrentTab, fragment, false, true);
            title = getString(R.string.Incidents);
            break;
        case 1:
            mCurrentTab = MyConstants.TAB_INCIDENTS;
            mStacks.get(mCurrentTab).clear();
            fragment = new IncidentFragment();
            pushFragments(mCurrentTab, fragment, false, true);
            title = getString(R.string.Incidents);
            break;

        case 2:
            mCurrentTab = MyConstants.TAB_LICENSE;
            mStacks.get(mCurrentTab).clear();
            fragment = new LicensesFragment();
            pushFragments(mCurrentTab, fragment, false, true);
            title = getString(R.string.Licences);
            break;
        case 3:
            mCurrentTab = MyConstants.TAB_SCHEDULE;
            mStacks.get(mCurrentTab).clear();
            fragment = new ScheduleFragment();
            pushFragments(mCurrentTab, fragment, false, true);
            title = getString(R.string.ScheduleVisits);
            break;
        case 4:
            mCurrentTab = MyConstants.TAB_CREATE;
            mStacks.get(mCurrentTab).clear();
            fragment = new CreateScheduleFragment();
            pushFragments(mCurrentTab, fragment, false, true);
            title = getString(R.string.SchedulenewVisits);
            break;
        default:
            break;
    }


}


public void pushFragments(String tag, BaseFragment fragment, boolean shouldAnimate, boolean shouldAdd) {
    if (shouldAdd)
        mStacks.get(tag).push(fragment);
    FragmentManager manager = getSupportFragmentManager();
    FragmentTransaction ft = manager.beginTransaction();
    /*
     * if(shouldAnimate) ft.setCustomAnimations(R.anim.slide_in_right,
     * R.anim.slide_out_left);
     */
    ft.replace(R.id.container_body, fragment);

    ft.commit();

}

@Override
public void onBackPressed() {
    boolean temp = true;
    if (temp) {
        temp = false;

        if (mStacks.get(mCurrentTab).size() == 1) {
            if (mCurrentTab.equals(MyConstants.TAB_HOME)) {
            } else {
                displayView(0);
            }

        } else {
            int stackSize = mStacks.get(mCurrentTab).size();
            BaseFragment fragment = mStacks.get(mCurrentTab).get(stackSize - 1);
            //popFragments();
            if (fragment.onBackPressed())
                popFragments();
        }
    } else {
        // do nothing.. fragment already handled back button press.
    }
    temp = true;
}



public void popFragments() {
    /*
     * Select the second last fragment in current tab's stack.. which will
     * be shown after the fragment transaction given below
     */
    Fragment fragment = mStacks.get(mCurrentTab).elementAt(
            mStacks.get(mCurrentTab).size() - 1);

    /* pop current fragment from stack.. */
    mStacks.get(mCurrentTab).pop();
    FragmentManager manager = getSupportFragmentManager();
    FragmentTransaction ft = manager.beginTransaction();
    // ft.setCustomAnimations(R.anim.slide_in_left, R.anim.slide_out_right);
    ft.replace(R.id.container_body, fragment);
    ft.commit();
}
}

现在在我的主屏幕按钮中单击,我以这种方式调用片段

 layout_schedule.setOnClickListener(new View.OnClickListener() {
                                           @Override
                                           public void onClick(View view) {
                                               mActivity.mCurrentTab = MyConstants.TAB_SCHEDULE;
                                               mActivity.mStacks.get(mActivity.mCurrentTab).clear();
                                               mActivity.fragment = new ScheduleFragment();
                                               mActivity.pushFragments(mActivity.mCurrentTab, mActivity.fragment, false, true);
                                               mActivity.title = getString(R.string.ScheduleVisits);
                                           }
                                       }
    );

    layout_newincident.setOnClickListener(new View.OnClickListener() {
                                              @Override
                                              public void onClick(View view) {

                                                  mActivity.mCurrentTab = MyConstants.TAB_CREATE;
                                                  mActivity.mStacks.get(mActivity.mCurrentTab).clear();
                                                  mActivity.fragment = new CreateScheduleFragment();
                                                  mActivity.pushFragments(mActivity.mCurrentTab, mActivity.fragment, false, true);
                                                  mActivity.title = getString(R.string.create_schedule);
                                              }
                                          }

    );

现在从ScheduleFragment()片段内部,我有一个打开新片段的按钮

 activity.mCurrentTab = MyConstants.TAB_SCHEDULE_DETAILS;
    activity.fragment = new FragmentScheduleDetails();
    activity.pushFragments(activity.mCurrentTab, activity.fragment, false, true);
    activity.title = activity.getString(R.string.schedule_details);


 public boolean onBackPressed(){

    return true;
}

如果我从FragmentScheduleDetails()片段中单击“后退”按钮,它将带我回到主屏幕,但我正尝试转到ScheduleFragment()。

请纠正我。我肯定走错了路。

谢谢

3 个答案:

答案 0 :(得分:0)

如果要以A-> B-> c->的形式流动 然后按下A-> B

所以你应该写

  

ft.addToBackStack(null);

之前的pushFragment()方法中
  

ft.commit();

答案 1 :(得分:0)

这与您编写的完全一样。您可以通过简单的步骤拆分导航逻辑。

步骤1。单击layout_schedule,将打开ScheduleFragment。此操作后的状态是什么? mCurrentTab = MyConstants.TAB_SCHEDULEmStack.get(MyConstants.TAB_SCHEDULE).size() == 1

步骤2。单击并打开FragmentScheduleDetails。此操作后的状态是什么? mCurrentTab = MyConstants.TAB_SCHEDULE_DETAILSmStack.get(MyConstants.TAB_SCHEDULE).size() == 1

第3步。单击“后退”按钮。此时,您进入分支mStacks.get(mCurrentTab).size() == 1,因为mCurrentTab = MyConstants.TAB_SCHEDULE_DETAILS。在此分支中,您调用displayView(0),它会有效显示主屏幕。

我想您想实现Instagram-like导航。在这种情况下,您应仅将根视图的标记用作mStacks的键,并在称为mCurrentRoot的某个字段上进行操作。或者最好像这样https://github.com/ncapdevi/FragNav

使用lib

答案 2 :(得分:-1)

您可以将片段与ft.addToBackStack("fragment-name")添加到堆栈中以处理后退按钮。 https://developer.android.com/training/implementing-navigation/temporal