我有一个Activity
我加载ListFragment
,点击后,它向下钻取一个级别,显示一个新类型的ListFragment
,替换原来的showFragment
(使用下面的android:label
方法。这是放在后面的堆栈上。
开头,活动会在操作栏中显示默认标题(即根据应用程序的FragmentTransaction
自动设置)。
当显示层次结构中下一个级别的列表时,单击的项目名称应该成为操作栏的标题。
然而,当按 Back 时,我希望恢复原始默认标题。这不是FragmentBreadCrumbs
所知道的,因此标题不会被恢复。
我模糊地阅读了protected void showFragment(Fragment f) {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.fragment_container, f);
ft.addToBackStack(null);
ft.commit();
}
,但这似乎需要使用自定义视图。我正在使用ActionBarSherlock,并且更愿意没有我自己的自定义标题视图。
这样做的最佳方式是什么?是否有可能没有大量的样板代码并且必须跟踪沿途显示的标题?
{{1}}
答案 0 :(得分:119)
在每个片段和每个活动中,我都会像这样更改标题。这样,活动标题将始终是正确的:
@Override
public void onResume() {
super.onResume();
// Set title
getActivity().getActionBar()
.setTitle(R.string.thetitle);
}
在某些情况下,onResume不会在片段内部调用。在某些情况下,我们可以使用:
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if(isVisibleToUser) {
// Set title
getActivity().getActionBar()
.setTitle(R.string.thetitle);
}
}
答案 1 :(得分:26)
由于最初的答案很老,这也可能有所帮助。正如文档所述,人们可能希望注册listener
来监听托管Activity
中的后台堆栈更改:
getSupportFragmentManager().addOnBackStackChangedListener(
new FragmentManager.OnBackStackChangedListener() {
public void onBackStackChanged() {
// Update your UI here.
}
});
然后,识别回调方法中的情况并设置正确的标题,而无需访问ActionBar
中的Fragment
。
这是一个更优雅的解决方案,因为Fragment
不必了解ActionBar
存在,Activity
通常是管理后台堆栈的地方,因此需要处理它似乎更合适。 Fragment
在任何时候都应该只考虑自己的内容,而不是周围环境。
答案 2 :(得分:10)
让控制活动按如下方式完成所有工作:
监听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);
}
});
从容器中获取当前片段:
/**
* Returns the currently displayed fragment.
* @return
* Fragment or null.
*/
private Fragment getFragment() {
Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.container);
return fragment;
}
在内容视图中设置片段:
private void setFragment(Fragment fragment, boolean addToBackStack) {
// Set the activity title
setTitleFromFragment(fragment);
.
.
.
}
答案 3 :(得分:7)
Warpzit是对的。这也解决了设备方向改变时的标题问题。此外,如果您使用支持v7操作栏,您可以从片段获取操作栏,如下所示:
@Override
public void onResume() {
super.onResume();
((ActionBarActivity)getActivity()).getSupportActionBar().setTitle("Home");
}
答案 4 :(得分:6)
最好让操作系统尽可能多地完成工作。 假设每个片段都使用.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);
}
}
答案 5 :(得分:5)
我使用Lee approach的类似解决方案,但改为替换onBackStackChanged()
方法。
首先,我在将事务添加到后台堆栈时设置片段名称。
getSupportFragmentManager().beginTransaction()
.replace(R.id.frame_content, fragment)
.addToBackStack(fragmentTitle)
.commit();
然后我覆盖onBackStackChanged()
方法,并使用最后一个backstack条目名称调用setTitle()
。
@Override
public void onBackStackChanged() {
int lastBackStackEntryCount = getSupportFragmentManager().getBackStackEntryCount() - 1;
FragmentManager.BackStackEntry lastBackStackEntry =
getSupportFragmentManager().getBackStackEntryAt(lastBackStackEntryCount);
setTitle(lastBackStackEntry.getName());
}
答案 6 :(得分:4)
使用碎片方法:
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater)
在每个Fragment外观上调用它,但onResume不是。
答案 7 :(得分:1)
最好的方法是使用android提供的接口OnBackStackChangedListener方法onBackStackChanged()。
假设我们有一个导航抽屉,其中有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++;
}
}
在显示的代码中,我们有displayFragment()方法。在这里,我根据从导航抽屉中选择的选项显示片段。变量位置对应于从导航抽屉中的ListView或RecyclerView单击的项目的位置。我使用getSupportActionBar.setTitle(title)相应地设置了操作栏标题,其中标题存储了相应的标题名称。
每当我们从导航抽屉中单击该项目时,将显示一个片段,具体取决于单击该用户的项目。但是在后端,这个片段被添加到backstack,而onBackStachChanged()方法被命中。我所做的是我创建了一个变量mPreviousBackStackCount并将其初始化为0.我还创建了一个额外的堆栈,它将存储操作栏标题名称。每当我向backstack添加一个新片段时,我都会将相应的标题名称添加到我创建的堆栈中。在对面,每当我按下后退按钮onBackStackChanged()被调用,我从我的堆栈中弹出最后一个标题名称,并将标题设置为堆栈的peek()方法派生的名称。
示例:
让我们说我们的android backstack是空的:
按导航抽屉中的选择1: 调用onBackStachChanged()并将Fragment 1添加到android backstack,将backStackEntryCount设置为1并将Frag1推送到我的堆栈,mFragPositionTitleDisplayed的大小变为1。
按导航抽屉中的选择2: 调用onBackStachChanged()并将Fragment 2添加到android backstack中,backStackEntryCount设置为2,Frag2被推送到我的堆栈,mFragPositionTitleDisplayed的大小变为2。
现在我们在android堆栈和堆栈中都有2个元素。按下后退按钮onBackStackChanged()被调用,backStackEntryCount的值为1.代码进入if部分并从我的堆栈中弹出最后一个条目。因此,android backstack只有1个片段 - “Fragment 1”,我的堆栈只有1个标题 - “Frag1”。现在我只是从我的堆栈中偷看()标题并将操作栏设置为该标题。
请记住:要设置动作蝙蝠标题,请使用peek()而不是pop()否则当您打开2个以上的碎片并尝试通过按后退按钮返回时,您的应用程序将崩溃。
答案 8 :(得分:1)
你用onKeyDown解决了问题! 我有一个布尔 mainisopen = true&lt; - MainFragment是可见的 其他片段mainisopen = false
这是我的代码:
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);
}
}
答案 9 :(得分:0)
如here所述,我的解决方案是将此代码添加到MainActivity onCreate method():并更改操作栏标题
FragmentManager fragmentManager=getSupportFragmentManager();
fragmentManager.addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
@Override
public void onBackStackChanged() {
Fragment currentFragment = fragmentManager.findFragmentById(R.id.My_Container_1_ID);
currentFragment.onResume();
}
});
并在片段的onResume()方法中更改操作栏标题
@Override
public void onResume() {
super.onResume();
AppCompatActivity activity = (AppCompatActivity) getActivity();
ActionBar actionBar = activity.getSupportActionBar();
if(actionBar!=null) {
actionBar.setTitle("Fragment Title");
actionBar.setSubtitle("Subtitle");
}
}
答案 10 :(得分:-3)
要在背面更新操作栏标题。只需简单地把
<强> getActivity.setTitle( “标题”)强>
在onCreateView方法中。