使用片段后端堆栈处理ActionBar标题?

时间:2022-12-05 00:26:37

I have an Activity where I load in a ListFragment and, upon clicking, it drills down a level and a new type of ListFragment is shown, replacing the original one (using the showFragment method below). This is placed on the back stack.

我有一个Activity,我在ListFragment中加载,点击后,它向下钻取一个级别,显示一个新类型的ListFragment,替换原来的一个(使用下面的showFragment方法)。这是放在后面的堆栈上。

At the beginning, the activity shows the default title in the action bar (i.e. it's set automatically based on the application's android:label).

开始时,活动会在操作栏中显示默认标题(即根据应用程序的android:标签自动设置)。

When showing the list for the next level in the hierarchy, the name of the item clicked on should become the action bar's title.

显示层次结构中下一级别的列表时,单击的项目名称应成为操作栏的标题。

However, when pressing Back, I would like the original default title to be restored. This isn't something FragmentTransaction knows about, so the title isn't restored.

但是,当按Back时,我希望恢复原始默认标题。这不是FragmentTransaction所知道的,因此标题不会被恢复。

I've vaguely read about FragmentBreadCrumbs, but this seems to require using a custom view. I'm using ActionBarSherlock and would prefer to not have my own custom title view.

我模糊地阅读了FragmentBreadCrumbs,但这似乎需要使用自定义视图。我正在使用ActionBarSherlock,并且更愿意没有我自己的自定义标题视图。

What is the best way of doing this? Is it possible without a load of boilerplate code and having to keep track of the titles shown along the way?

这样做的最佳方式是什么?是否有可能没有大量的样板代码并且必须跟踪沿途显示的标题?


protected void showFragment(Fragment f) {
  FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
  ft.replace(R.id.fragment_container, f);
  ft.addToBackStack(null);
  ft.commit();
}

10 个解决方案

#1


114  

In every fragment and every activity I change the title like this. This way the active title will always be correct:

在每个片段和每个活动中,我都会像这样更改标题。这样,活动标题将始终是正确的:

@Override
public void onResume() {
    super.onResume();
    // Set title
    getActivity().getActionBar()
        .setTitle(R.string.thetitle);
}

There is some cases where onResume isn't called inside fragments. In some of these cases we can use:

在某些情况下,onResume不会在片段内部调用。在某些情况下,我们可以使用:

public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);
    if(isVisibleToUser) {
        // Set title
        getActivity().getActionBar()
            .setTitle(R.string.thetitle);
    }
}

#2


26  

As the original answer is quite old, this might come of help as well. As the documentation states, one might want to register a listener to listen on the back stack changes in the hosting Activity:

由于最初的答案很老,这也可能有所帮助。正如文档所述,人们可能希望注册一个监听器来监听托管活动中的后台堆栈更改:

getSupportFragmentManager().addOnBackStackChangedListener(
        new FragmentManager.OnBackStackChangedListener() {
            public void onBackStackChanged() {
                // Update your UI here.
            }
        });

Then, identify the situation in the callback method and set a proper title, without accessing the ActionBar from the Fragment.

然后,在回调方法中识别情况并设置正确的标题,而无需从Fragment访问ActionBar。

This is a more elegant solution as the Fragment doesn't have to know about the ActionBar existence and Activity is usually the place that is managing the backstack so having it handled over there seems to be more appropriate. Fragment should at all time be considered only by its own content, not the surroundings.

这是一个更优雅的解决方案,因为Fragment不必了解ActionBar的存在,而Activity通常是管理backstack的地方,因此在那里处理它似乎更合适。片段应始终只考虑其自身内容,而不是周围环境。

More on the topic in the documentation.

有关该文档主题的更多信息。

#3


9  

Let the controlling activity do all the work as follows:

让控制活动完成所有工作如下:

Listen for backstack events (in onCreate() of activity):

监听backstack事件(在活动的onCreate()中):

// Change the title back when the fragment is changed
    getSupportFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
        @Override
        public void onBackStackChanged() {
            Fragment fragment = getFragment();
            setTitleFromFragment(fragment);
        }
    });

Get the current fragment from the container:

从容器中获取当前片段:

/**
 * Returns the currently displayed fragment.
 * @return
 *      Fragment or null.
 */
private Fragment getFragment() {
    Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.container);
    return fragment;
}

Set the fragment inside the content view:

在内容视图中设置片段:

private void setFragment(Fragment fragment, boolean addToBackStack) {
    // Set the activity title
    setTitleFromFragment(fragment);
    .
    .
    .
}

#4


7  

Warpzit is right. This also solves title problem when orientation of device is changed. Also if you use support v7 for action bar, you can get action bar from fragment like this :

Warpzit是对的。这也解决了设备方向改变时的标题问题。此外,如果您使用支持v7操作栏,您可以从片段获取操作栏,如下所示:

@Override
public void onResume() {
    super.onResume();
    ((ActionBarActivity)getActivity()).getSupportActionBar().setTitle("Home");
}

#5


6  

It is best to let the OS do as much of the work as possible. Assuming each fragment is properly named using .addToBackStack("title") then you can override onBackPressed something like this to achieve desired behavior:

最好让操作系统尽可能多地完成工作。假设每个片段都使用.addToBackStack(“title”)正确命名,那么你可以覆盖onBackPressed这样的东西来实现所需的行为:

// this example uses the AppCompat support library
// and works for dynamic fragment titles
@Override
public void onBackPressed() {
    FragmentManager fragmentManager = getSupportFragmentManager();
    int count = fragmentManager.getBackStackEntryCount();
    if (count <= 1) {
        finish();
    }
    else {
        String title = fragmentManager.getBackStackEntryAt(count-2).getName();
        if (count == 2) {
            // here I am using a NavigationDrawer and open it when transitioning to the initial fragment
            // a second back-press will result in finish() being called above.
            mDrawerLayout.openDrawer(mNavigationDrawerFragment.getView());
        }
        super.onBackPressed();
        Log.v(TAG, "onBackPressed - title="+title);
        getSupportActionBar().setTitle(title);
    }
}

#6


4  

I use a similar solution to Lee approach, but replacing onBackStackChanged() method instead.

我使用类似于Lee方法的解决方案,但是替换onBackStackChanged()方法。

First I set the fragment name when adding the transaction to the back stack.

首先,我在将事务添加到后台堆栈时设置片段名称。

getSupportFragmentManager().beginTransaction()
                .replace(R.id.frame_content, fragment)
                .addToBackStack(fragmentTitle)
                .commit();

Then I override the onBackStackChanged() method and I call setTitle() with the last backstack entry name.

然后我重写onBackStackChanged()方法,并使用最后一个backstack条目名称调用setTitle()。

@Override
public void onBackStackChanged() {
    int lastBackStackEntryCount = getSupportFragmentManager().getBackStackEntryCount() - 1;
    FragmentManager.BackStackEntry lastBackStackEntry =
            getSupportFragmentManager().getBackStackEntryAt(lastBackStackEntryCount);

    setTitle(lastBackStackEntry.getName());
}

#7


2  

Use Fragments method:

使用片段方法:

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater)

It is called on every Fragment appearance, but onResume is not.

它在每个Fragment外观上调用,但onResume不是。

#8


0  

The best approach is to make use of the android provided Interface OnBackStackChangedListener method onBackStackChanged().

最好的方法是使用android提供的接口OnBackStackChangedListener方法onBackStackChanged()。

Lets say we have a navigation drawer with 4 options to which the user can navigate to. In that case we will have 4 fragments. Lets see the code first and then I will explain the working.

假设我们有一个导航抽屉,有4个选项,用户可以导航到这些选项。在那种情况下,我们将有4个片段。让我们先看看代码,然后我将解释它的工作原理。

    private int mPreviousBackStackCount = 0;
    private String[] title_name = {"Frag1","Frag2","Frag3","Frag4"};
    Stack<String> mFragPositionTitleDisplayed;

    public class MainActivity extends ActionBarActivity implements FragmentManager.OnBackStackChangedListener
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    ....
    ....
    ....
    getSupportFragmentManager().addOnBackStackChangedListener(this);
    mFragPositionTitleDisplayed = new Stack<>();
}

public void displayFragment() {
    Fragment fragment = null;
    String title = getResources().getString(R.string.app_name);
    switch (position) {
        case 0:
            fragment = new Fragment1();
            title = title_name[position];
            break;
        case 1:
            fragment = new Fragment2();
            title = title_name[position];
            break;
        case 2:
            fragment = new Fragment3();
            title = title_name[position];
            break;
        case 3:
            fragment = new Fragment4();
            title = title_name[position];
            break;
        default:
            break;
    }
    if (fragment != null) {
        FragmentManager fragmentManager = getSupportFragmentManager();
        fragmentManager.beginTransaction()
                .replace(R.id.container_body, fragment)
                .addToBackStack(null)
                .commit();
        getSupportActionBar().setTitle(title);
    }
}

@Override
public void onBackStackChanged() {
    int backStackEntryCount = getSupportFragmentManager().getBackStackEntryCount();
    if(mPreviousBackStackCount >= backStackEntryCount) {
        mFragPositionTitleDisplayed.pop();
        if (backStackEntryCount == 0)
            getSupportActionBar().setTitle(R.string.app_name);
        else if (backStackEntryCount > 0) {
            getSupportActionBar().setTitle(mFragPositionTitleDisplayed.peek());
        }
        mPreviousBackStackCount--;
    }
    else{
        mFragPositionTitleDisplayed.push(title_name[position]);
        mPreviousBackStackCount++;
    }

}   

In the code shown we have the displayFragment() method. Here I display the fragment on the basis of option chosen from the navigation drawer.The variable position corresponds to the position of the item clicked from the ListView or RecyclerView in the navigation drawer. I set the actionbar title accordingly with getSupportActionBar.setTitle(title), where the title stores the appropriate title name.

在显示的代码中,我们有displayFragment()方法。在这里,我根据从导航抽屉中选择的选项显示片段。变量位置对应于从导航抽屉中的ListView或RecyclerView单击的项目的位置。我使用getSupportActionBar.setTitle(title)相应地设置了操作栏标题,其中标题存储了相应的标题名称。

Whenever we click the item from nav drawer a fragment is displayed depending on the item clicked to the user. But on the back end side this fragment is added to the backstack and the method onBackStachChanged(), gets hit. What I have done is that I have created a variable mPreviousBackStackCount and initialized it to 0. I have also created an additional stack which will store the action bar title names. Whenever I add a new fragment to the backstack, I add the corresponding title name to my created stack. On the opposite side whenever I press the back button onBackStackChanged() is called and I pop the last title name from my stack and set the title to the name derived by the peek() method of the stack.

每当我们从导航抽屉单击该项目时,将显示一个片段,具体取决于单击该用户的项目。但是在后端,这个片段被添加到backstack并且onBackStachChanged()方法被命中。我所做的是我创建了一个变量mPreviousBackStackCount并将其初始化为0.我还创建了一个额外的堆栈,它将存储操作栏标题名称。每当我向backstack添加一个新片段时,我都会将相应的标题名称添加到我创建的堆栈中。在对面,每当我按下后退按钮onBackStackChanged()被调用,我从我的堆栈中弹出最后一个标题名称,并将标题设置为堆栈的peek()方法派生的名称。

Example:

例:

Lets say our android backstack is empty:

让我们说我们的android backstack是空的:

Press Choice 1 from nav drawer: onBackStachChanged() is called and the Fragment 1 is added to android backstack, backStackEntryCount is set to 1 and Frag1 is pushed to my stack and size of mFragPositionTitleDisplayed becomes 1.

按导航抽屉中的选择1:调用onBackStachChanged()并将片段1添加到android backstack,将backStackEntryCount设置为1并将Frag1推送到我的堆栈,mFragPositionTitleDisplayed的大小变为1。

Press Choice 2 from nav drawer: onBackStachChanged() is called and the Fragment 2 is added to android backstack, backStackEntryCount is set to 2 and Frag2 is pushed to my stack and size of mFragPositionTitleDisplayed becomes 2.

按导航抽屉中的选择2:调用onBackStachChanged()并将片段2添加到android backstack,将backStackEntryCount设置为2并将Frag2推送到我的堆栈,mFragPositionTitleDisplayed的大小变为2。

Now we have 2 elements both in the android stack and my stack. When you press back button onBackStackChanged() is called and the value of backStackEntryCount is 1. The code enters the if part and pops out the last entry from my stack. So, the android backstack has only 1 fragment - "Fragment 1" and my stack has only 1 title - "Frag1". Now I just peek() the title from my stack and set the action bar to that title.

现在我们在android堆栈和堆栈中都有2个元素。当您按下后退按钮onBackStackChanged()被调用并且backStackEntryCount的值为1.代码进入if部分并从我的堆栈中弹出最后一个条目。因此,android backstack只有1个片段 - “Fragment 1”,我的堆栈只有1个标题 - “Frag1”。现在我只是从我的堆栈中偷看()标题并将操作栏设置为该标题。

Remember: To set the action bat title use peek() and not pop() else your application will crash when you open more than 2 fragments and try to go back by pressing back button.

记住:要设置动作蝙蝠标题使用peek()而不是pop(),否则当您打开2个以上的碎片并尝试通过按后退按钮返回时,您的应用程序将崩溃。

#9


0  

You cane Solve with onKeyDown! I have a bool mainisopen=true <-- MainFragment is Visible other Fragment mainisopen=false

你用onKeyDown解决了Solve!我有一个bool mainisopen = true < - MainFragment是Visible其他Fragment mainisopen = false

and here is My Code:

这是我的代码:

public boolean onKeyDown(int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_BACK && mainisopen == false) {
        mainisopen = true;
        HomeFrag fragment = new HomeFrag();
        FragmentTransaction fragmentTransaction =
                getSupportFragmentManager().beginTransaction();
        fragmentTransaction.replace(R.id.fragmet_cont, fragment);
        fragmentTransaction.commit();
        navigationView = (NavigationView) findViewById(R.id.nav_view);
        navigationView.getMenu().findItem(R.id.nav_home).setChecked(true);
        navigationView.setNavigationItemSelectedListener(this);
        this.setTitle("Digi - Home"); //Here set the Title back
        return true;
    } else {
        if (keyCode == KeyEvent.KEYCODE_BACK && mainisopen == true) {
            AlertDialog.Builder builder = new AlertDialog.Builder(this);
            builder.setMessage("Wollen sie die App schliessen!");
            builder.setCancelable(true);

            builder.setPositiveButton("Ja!", new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int which) {
                    System.exit(1);
                }
            });

            builder.setNegativeButton("Nein!", new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int which) {
                    Toast.makeText(getApplicationContext(), "Applikation wird fortgesetzt", Toast.LENGTH_SHORT).show();
                }
            });

            AlertDialog dialog = builder.create();
            dialog.show();

            return true;
        }
        return super.onKeyDown(keyCode, event);
    }

}

#10


-3  

To update the actionbar title on back press. Just simply put

要在背面更新操作栏标题。只是简单地说

getActivity.setTitle("title")

getActivity.setTitle( “标题”)

inside onCreateView method.

在onCreateView方法中。

#1


114  

In every fragment and every activity I change the title like this. This way the active title will always be correct:

在每个片段和每个活动中,我都会像这样更改标题。这样,活动标题将始终是正确的:

@Override
public void onResume() {
    super.onResume();
    // Set title
    getActivity().getActionBar()
        .setTitle(R.string.thetitle);
}

There is some cases where onResume isn't called inside fragments. In some of these cases we can use:

在某些情况下,onResume不会在片段内部调用。在某些情况下,我们可以使用:

public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);
    if(isVisibleToUser) {
        // Set title
        getActivity().getActionBar()
            .setTitle(R.string.thetitle);
    }
}

#2


26  

As the original answer is quite old, this might come of help as well. As the documentation states, one might want to register a listener to listen on the back stack changes in the hosting Activity:

由于最初的答案很老,这也可能有所帮助。正如文档所述,人们可能希望注册一个监听器来监听托管活动中的后台堆栈更改:

getSupportFragmentManager().addOnBackStackChangedListener(
        new FragmentManager.OnBackStackChangedListener() {
            public void onBackStackChanged() {
                // Update your UI here.
            }
        });

Then, identify the situation in the callback method and set a proper title, without accessing the ActionBar from the Fragment.

然后,在回调方法中识别情况并设置正确的标题,而无需从Fragment访问ActionBar。

This is a more elegant solution as the Fragment doesn't have to know about the ActionBar existence and Activity is usually the place that is managing the backstack so having it handled over there seems to be more appropriate. Fragment should at all time be considered only by its own content, not the surroundings.

这是一个更优雅的解决方案,因为Fragment不必了解ActionBar的存在,而Activity通常是管理backstack的地方,因此在那里处理它似乎更合适。片段应始终只考虑其自身内容,而不是周围环境。

More on the topic in the documentation.

有关该文档主题的更多信息。

#3


9  

Let the controlling activity do all the work as follows:

让控制活动完成所有工作如下:

Listen for backstack events (in onCreate() of activity):

监听backstack事件(在活动的onCreate()中):

// Change the title back when the fragment is changed
    getSupportFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
        @Override
        public void onBackStackChanged() {
            Fragment fragment = getFragment();
            setTitleFromFragment(fragment);
        }
    });

Get the current fragment from the container:

从容器中获取当前片段:

/**
 * Returns the currently displayed fragment.
 * @return
 *      Fragment or null.
 */
private Fragment getFragment() {
    Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.container);
    return fragment;
}

Set the fragment inside the content view:

在内容视图中设置片段:

private void setFragment(Fragment fragment, boolean addToBackStack) {
    // Set the activity title
    setTitleFromFragment(fragment);
    .
    .
    .
}

#4


7  

Warpzit is right. This also solves title problem when orientation of device is changed. Also if you use support v7 for action bar, you can get action bar from fragment like this :

Warpzit是对的。这也解决了设备方向改变时的标题问题。此外,如果您使用支持v7操作栏,您可以从片段获取操作栏,如下所示:

@Override
public void onResume() {
    super.onResume();
    ((ActionBarActivity)getActivity()).getSupportActionBar().setTitle("Home");
}

#5


6  

It is best to let the OS do as much of the work as possible. Assuming each fragment is properly named using .addToBackStack("title") then you can override onBackPressed something like this to achieve desired behavior:

最好让操作系统尽可能多地完成工作。假设每个片段都使用.addToBackStack(“title”)正确命名,那么你可以覆盖onBackPressed这样的东西来实现所需的行为:

// this example uses the AppCompat support library
// and works for dynamic fragment titles
@Override
public void onBackPressed() {
    FragmentManager fragmentManager = getSupportFragmentManager();
    int count = fragmentManager.getBackStackEntryCount();
    if (count <= 1) {
        finish();
    }
    else {
        String title = fragmentManager.getBackStackEntryAt(count-2).getName();
        if (count == 2) {
            // here I am using a NavigationDrawer and open it when transitioning to the initial fragment
            // a second back-press will result in finish() being called above.
            mDrawerLayout.openDrawer(mNavigationDrawerFragment.getView());
        }
        super.onBackPressed();
        Log.v(TAG, "onBackPressed - title="+title);
        getSupportActionBar().setTitle(title);
    }
}

#6


4  

I use a similar solution to Lee approach, but replacing onBackStackChanged() method instead.

我使用类似于Lee方法的解决方案,但是替换onBackStackChanged()方法。

First I set the fragment name when adding the transaction to the back stack.

首先,我在将事务添加到后台堆栈时设置片段名称。

getSupportFragmentManager().beginTransaction()
                .replace(R.id.frame_content, fragment)
                .addToBackStack(fragmentTitle)
                .commit();

Then I override the onBackStackChanged() method and I call setTitle() with the last backstack entry name.

然后我重写onBackStackChanged()方法,并使用最后一个backstack条目名称调用setTitle()。

@Override
public void onBackStackChanged() {
    int lastBackStackEntryCount = getSupportFragmentManager().getBackStackEntryCount() - 1;
    FragmentManager.BackStackEntry lastBackStackEntry =
            getSupportFragmentManager().getBackStackEntryAt(lastBackStackEntryCount);

    setTitle(lastBackStackEntry.getName());
}

#7


2  

Use Fragments method:

使用片段方法:

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater)

It is called on every Fragment appearance, but onResume is not.

它在每个Fragment外观上调用,但onResume不是。

#8


0  

The best approach is to make use of the android provided Interface OnBackStackChangedListener method onBackStackChanged().

最好的方法是使用android提供的接口OnBackStackChangedListener方法onBackStackChanged()。

Lets say we have a navigation drawer with 4 options to which the user can navigate to. In that case we will have 4 fragments. Lets see the code first and then I will explain the working.

假设我们有一个导航抽屉,有4个选项,用户可以导航到这些选项。在那种情况下,我们将有4个片段。让我们先看看代码,然后我将解释它的工作原理。

    private int mPreviousBackStackCount = 0;
    private String[] title_name = {"Frag1","Frag2","Frag3","Frag4"};
    Stack<String> mFragPositionTitleDisplayed;

    public class MainActivity extends ActionBarActivity implements FragmentManager.OnBackStackChangedListener
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    ....
    ....
    ....
    getSupportFragmentManager().addOnBackStackChangedListener(this);
    mFragPositionTitleDisplayed = new Stack<>();
}

public void displayFragment() {
    Fragment fragment = null;
    String title = getResources().getString(R.string.app_name);
    switch (position) {
        case 0:
            fragment = new Fragment1();
            title = title_name[position];
            break;
        case 1:
            fragment = new Fragment2();
            title = title_name[position];
            break;
        case 2:
            fragment = new Fragment3();
            title = title_name[position];
            break;
        case 3:
            fragment = new Fragment4();
            title = title_name[position];
            break;
        default:
            break;
    }
    if (fragment != null) {
        FragmentManager fragmentManager = getSupportFragmentManager();
        fragmentManager.beginTransaction()
                .replace(R.id.container_body, fragment)
                .addToBackStack(null)
                .commit();
        getSupportActionBar().setTitle(title);
    }
}

@Override
public void onBackStackChanged() {
    int backStackEntryCount = getSupportFragmentManager().getBackStackEntryCount();
    if(mPreviousBackStackCount >= backStackEntryCount) {
        mFragPositionTitleDisplayed.pop();
        if (backStackEntryCount == 0)
            getSupportActionBar().setTitle(R.string.app_name);
        else if (backStackEntryCount > 0) {
            getSupportActionBar().setTitle(mFragPositionTitleDisplayed.peek());
        }
        mPreviousBackStackCount--;
    }
    else{
        mFragPositionTitleDisplayed.push(title_name[position]);
        mPreviousBackStackCount++;
    }

}   

In the code shown we have the displayFragment() method. Here I display the fragment on the basis of option chosen from the navigation drawer.The variable position corresponds to the position of the item clicked from the ListView or RecyclerView in the navigation drawer. I set the actionbar title accordingly with getSupportActionBar.setTitle(title), where the title stores the appropriate title name.

在显示的代码中,我们有displayFragment()方法。在这里,我根据从导航抽屉中选择的选项显示片段。变量位置对应于从导航抽屉中的ListView或RecyclerView单击的项目的位置。我使用getSupportActionBar.setTitle(title)相应地设置了操作栏标题,其中标题存储了相应的标题名称。

Whenever we click the item from nav drawer a fragment is displayed depending on the item clicked to the user. But on the back end side this fragment is added to the backstack and the method onBackStachChanged(), gets hit. What I have done is that I have created a variable mPreviousBackStackCount and initialized it to 0. I have also created an additional stack which will store the action bar title names. Whenever I add a new fragment to the backstack, I add the corresponding title name to my created stack. On the opposite side whenever I press the back button onBackStackChanged() is called and I pop the last title name from my stack and set the title to the name derived by the peek() method of the stack.

每当我们从导航抽屉单击该项目时,将显示一个片段,具体取决于单击该用户的项目。但是在后端,这个片段被添加到backstack并且onBackStachChanged()方法被命中。我所做的是我创建了一个变量mPreviousBackStackCount并将其初始化为0.我还创建了一个额外的堆栈,它将存储操作栏标题名称。每当我向backstack添加一个新片段时,我都会将相应的标题名称添加到我创建的堆栈中。在对面,每当我按下后退按钮onBackStackChanged()被调用,我从我的堆栈中弹出最后一个标题名称,并将标题设置为堆栈的peek()方法派生的名称。

Example:

例:

Lets say our android backstack is empty:

让我们说我们的android backstack是空的:

Press Choice 1 from nav drawer: onBackStachChanged() is called and the Fragment 1 is added to android backstack, backStackEntryCount is set to 1 and Frag1 is pushed to my stack and size of mFragPositionTitleDisplayed becomes 1.

按导航抽屉中的选择1:调用onBackStachChanged()并将片段1添加到android backstack,将backStackEntryCount设置为1并将Frag1推送到我的堆栈,mFragPositionTitleDisplayed的大小变为1。

Press Choice 2 from nav drawer: onBackStachChanged() is called and the Fragment 2 is added to android backstack, backStackEntryCount is set to 2 and Frag2 is pushed to my stack and size of mFragPositionTitleDisplayed becomes 2.

按导航抽屉中的选择2:调用onBackStachChanged()并将片段2添加到android backstack,将backStackEntryCount设置为2并将Frag2推送到我的堆栈,mFragPositionTitleDisplayed的大小变为2。

Now we have 2 elements both in the android stack and my stack. When you press back button onBackStackChanged() is called and the value of backStackEntryCount is 1. The code enters the if part and pops out the last entry from my stack. So, the android backstack has only 1 fragment - "Fragment 1" and my stack has only 1 title - "Frag1". Now I just peek() the title from my stack and set the action bar to that title.

现在我们在android堆栈和堆栈中都有2个元素。当您按下后退按钮onBackStackChanged()被调用并且backStackEntryCount的值为1.代码进入if部分并从我的堆栈中弹出最后一个条目。因此,android backstack只有1个片段 - “Fragment 1”,我的堆栈只有1个标题 - “Frag1”。现在我只是从我的堆栈中偷看()标题并将操作栏设置为该标题。

Remember: To set the action bat title use peek() and not pop() else your application will crash when you open more than 2 fragments and try to go back by pressing back button.

记住:要设置动作蝙蝠标题使用peek()而不是pop(),否则当您打开2个以上的碎片并尝试通过按后退按钮返回时,您的应用程序将崩溃。

#9


0  

You cane Solve with onKeyDown! I have a bool mainisopen=true <-- MainFragment is Visible other Fragment mainisopen=false

你用onKeyDown解决了Solve!我有一个bool mainisopen = true < - MainFragment是Visible其他Fragment mainisopen = false

and here is My Code:

这是我的代码:

public boolean onKeyDown(int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_BACK && mainisopen == false) {
        mainisopen = true;
        HomeFrag fragment = new HomeFrag();
        FragmentTransaction fragmentTransaction =
                getSupportFragmentManager().beginTransaction();
        fragmentTransaction.replace(R.id.fragmet_cont, fragment);
        fragmentTransaction.commit();
        navigationView = (NavigationView) findViewById(R.id.nav_view);
        navigationView.getMenu().findItem(R.id.nav_home).setChecked(true);
        navigationView.setNavigationItemSelectedListener(this);
        this.setTitle("Digi - Home"); //Here set the Title back
        return true;
    } else {
        if (keyCode == KeyEvent.KEYCODE_BACK && mainisopen == true) {
            AlertDialog.Builder builder = new AlertDialog.Builder(this);
            builder.setMessage("Wollen sie die App schliessen!");
            builder.setCancelable(true);

            builder.setPositiveButton("Ja!", new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int which) {
                    System.exit(1);
                }
            });

            builder.setNegativeButton("Nein!", new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int which) {
                    Toast.makeText(getApplicationContext(), "Applikation wird fortgesetzt", Toast.LENGTH_SHORT).show();
                }
            });

            AlertDialog dialog = builder.create();
            dialog.show();

            return true;
        }
        return super.onKeyDown(keyCode, event);
    }

}

#10


-3  

To update the actionbar title on back press. Just simply put

要在背面更新操作栏标题。只是简单地说

getActivity.setTitle("title")

getActivity.setTitle( “标题”)

inside onCreateView method.

在onCreateView方法中。