Intereting Posts
Необходимо инициализировать Firebase Analytics в каждом мероприятии? Какой из них использовать NavUtils.navigateUpFromSameTask () vs. onBackPressed () Профиль пользователя ProfilePictureView Циркулярное изображение Получение JSON из объекта RetrofitError с использованием Retrofit Фоновая частичная параллельная развертка метки GC Тень карты не появляется в устройствах с леденец? Android – поддерживает ли Lollipop Screen pinning несколько действий в одном приложении? Android: как отключить AsyncTask до того, как я вызову другой метод? Как нажать на галерею Android с эспрессо Android FragmentTransaction.addToBackStack путаница Менеджер Android Alarm работает, но задерживается Ошибка Android для `@android: style / Theme.Material.Light` Изображение aim.putExtra (Intent.EXTRA_SHORTCUT_ICON, bmp) выключено Как обнаружить несколько маяков с помощью библиотеки Android Android? Android: относительная компоновка Две кнопки занимают все доступные горизонтальные пространства

Обработка заголовка ActionBar с помощью стека фрагментов?

У меня есть Activity где я загружаюсь в ListFragment и, щелкнув, он сверлит уровень и ListFragment новый тип ListFragment , заменив исходный (используя метод showFragment ниже). Это помещается в задний стек.

В начале активность показывает заголовок по умолчанию в панели действий (т. Е. Автоматически устанавливается на основе android:label ).

При отображении списка для следующего уровня в иерархии имя элемента, на который нужно щелкнуть, должно стать заголовком панели действий.

Однако, при нажатии Назад , мне бы хотелось, чтобы исходный заголовок по умолчанию был восстановлен. Об этом не говорит FragmentTransaction , поэтому заголовок не восстанавливается.

Я смутно читал о FragmentBreadCrumbs , но для этого, похоже, требуется использование настраиваемого представления. Я использую ActionBarSherlock и предпочитаю, чтобы у меня не было собственного пользовательского названия.

Каков наилучший способ сделать это? Возможно ли без загрузки кода шаблона и отслеживать названия, показанные на этом пути?


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

В каждом фрагменте и каждом действии я меняю заголовок наподобие этого. Таким образом, активное название всегда будет правильным:

 @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); } } 

Поскольку первоначальный ответ довольно старый, это может также помочь. Как указано в документации, можно захотеть зарегистрировать listener для прослушивания изменений заднего стека в хостинговом Управлении:

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

Затем определите ситуацию в методе обратного вызова и установите правильное название без доступа к ActionBar из Fragment .

Это более элегантное решение, так как Fragment не должен знать о существовании ActionBar а Activity – это, как правило, место, которое управляет стоп-кадром, поэтому, если он обрабатывается, кажется, более уместно. Fragment должен во все времена рассматриваться только по своему содержанию, а не по окружению.

Подробнее о теме в документации .

Пусть контролирующая деятельность выполняет всю работу следующим образом:

Слушайте события 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); . . . } 

Варпзит прав. Это также решает проблему названия при изменении ориентации устройства. Также, если вы используете поддержку v7 для панели действий, вы можете получить панель действий из фрагмента следующим образом:

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

Лучше всего позволить ОС выполнять как можно большую часть работы. Предполагая, что каждый фрагмент правильно назван с использованием .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); } } 

Я использую аналогичное решение для подхода Ли , но вместо этого вместо него вместо метода onBackStackChanged() .

Сначала я устанавливаю имя фрагмента при добавлении транзакции в задний стек.

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

Затем я переопределяю метод onBackStackChanged() и я вызываю setTitle() с последним именем записи backstack.

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

Использовать метод фрагментов:

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

Он называется для каждого фрагмента, но onResume – нет.

Лучшим подходом является использование андроида, предоставляемого интерфейсом 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 в навигационном ящике. Я установил заголовок actionbar соответственно getSupportActionBar.setTitle (название), где заголовок хранит соответствующее название названия.

Всякий раз, когда мы нажимаем элемент из навигационного ящика, фрагмент отображается в зависимости от элемента, который был нажат на пользователя. Но на обратной стороне этот фрагмент добавляется в backstack, и метод onBackStachChanged () получает удар. То, что я сделал, это то, что я создал переменную mPreviousBackStackCount и инициализировал ее на 0. Я также создал дополнительный стек, который будет хранить имена названий панели действий. Всякий раз, когда я добавляю новый фрагмент в backstack, я добавляю соответствующее название названия в созданный стек. На противоположной стороне всякий раз, когда я нажимаю кнопку «назад», вызывается onBackStackChanged (), и я вывожу последнее имя заголовка из своего стека и устанавливаю заголовок на имя, полученное методом peek () стека.

Пример:

Допустим, наша андроидная задняя часть пуста:

Нажмите «Выбор 1» из навигационного ящика: вызывается onBackStachChanged (), а фрагмент 1 добавляется к андроидному backstack, backStackEntryCount устанавливается в 1, а Frag1 переносится в мой стек, а размер mFragPositionTitleDisplayed становится равным 1.

Нажмите «Выбор 2» из навигационного ящика: вызывается onBackStachChanged (), а фрагмент 2 добавляется к backstack андроида, backStackEntryCount установлен в 2, а Frag2 помещается в мой стек, а размер mFragPositionTitleDisplayed становится равным 2.

Теперь у нас есть 2 элемента как в стеке Android, так и в моем стеке. Когда вы нажимаете кнопку возврата, вызывается onBackStackChanged (), а значение backStackEntryCount равно 1. Код входит в часть if и выдает последнюю запись из моего стека. Таким образом, андроид backstack имеет только 1 фрагмент – «Фрагмент 1», и мой стек имеет только 1 заголовок – «Frag1». Теперь я просто заглядываю () в заголовок из своего стека и устанавливаю панель действий в этот заголовок.

Помните: для установки названия bat bat используйте peek (), а не pop (), иначе ваше приложение выйдет из строя, когда вы откроете более 2 фрагментов и попытаетесь вернуться назад, нажав кнопку «Назад».

Вы можете решить с помощью onKeyDown! У меня есть bool mainisopen = true <- MainFragment is Visible other Fragment 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); } } 

Чтобы обновить заголовок панели действий, нажмите Назад. Просто просто положите

getActivity.setTitle ( "название")

Внутри метод onCreateView.