Intereting Posts
Android / Java Regex для удаления дополнительных нулей из подстрок Android: как преобразовать массив байтов в Bitmap? Динамическое обновление адаптера AutoCompleteTextView Android Asyntask: используйте слабую ссылку для контекста, чтобы избежать поворота экрана устройства Ошибка при воспроизведении видео, загружаемого через PhoneGap FileTransfer Заполнение ListView w / AsyncTask Лучший способ изменить версии репозитория Android эффективно после загрузки с помощью repo / git Производительность разумная, что обычно лучше, используя образ или созданную xml-форму в качестве переносимого? USER_PRESENT Предназначение для GO Locker Лучший способ создать сегментированный индикатор прогресса? Приложение для дозвона Android Единый идентификатор рекламного блока Admob для разных приложений? Как ссылаться на строку в файле strings.xml библиотеки Android в коде? Произошло слияние Как показать диалог предупреждения только при первом запуске моего приложения?

Переключение между изображениями Android Navigation Drawer и Up caret при использовании фрагментов

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

Подробнее см. Здесь: http://youtu.be/F5COhlbpIbY

Я использую одно действие для управления несколькими уровнями фрагментов и может отображать изображение навигационного ящика для отображения и функционирования на всех уровнях.

При создании фрагментов более низкого уровня я могу вызвать ActionBarDrawerToggle setDrawerIndicatorEnabled(false) чтобы скрыть изображение навигационного ящика и отобразить Up-up

 LowerLevelFragment lowFrag = new LowerLevelFragment(); //disable the toggle menu and show up carat theDrawerToggle.setDrawerIndicatorEnabled(false); getSupportFragmentManager().beginTransaction().replace(R.id.frag_layout, lowFrag, "lowerFrag").addToBackStack(null).commit(); 

Проблема, с которой я столкнулась, – это вернуться к фрагментам верхнего уровня, которые по-прежнему показывает вверх карат, а не исходное изображение навигационного ящика. Любые предложения о том, как «обновить» ActionBar на фрагментах верхнего уровня, чтобы повторно отобразить изображение навигационного ящика?


Решение

Предложение Тома работало для меня. Вот что я сделал:

Основная деятельность

Это действие контролирует все фрагменты в приложении.

При создании новых фрагментов для замены других я устанавливаю DrawerToggle setDrawerIndicatorEnabled(false) следующим образом:

 LowerLevelFragment lowFrag = new LowerLevelFragment(); //disable the toggle menu and show up carat theDrawerToggle.setDrawerIndicatorEnabled(false); getSupportFragmentManager().beginTransaction().replace(R.id.frag_layout, lowFrag).addToBackStack(null).commit(); 

Затем, в переопределении onBackPressed , я вернул выше, установив DrawerToggle в setDrawerIndicatorEnabled(true) следующим образом:

 @Override public void onBackPressed() { super.onBackPressed(); // turn on the Navigation Drawer image; // this is called in the LowerLevelFragments setDrawerIndicatorEnabled(true) } 

В LowerLevelFragments

В фрагментах я изменил onCreate и onOptionsItemSelected следующим образом:

В onCreate добавлен setHasOptionsMenu(true) чтобы включить настройку меню опций. Также установите setDisplayHomeAsUpEnabled(true) чтобы включить < в панели действий:

 @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // needed to indicate that the fragment would // like to add items to the Options Menu setHasOptionsMenu(true); // update the actionbar to show the up carat/affordance getActivity().getActionBar().setDisplayHomeAsUpEnabled(true); } 

Затем в onOptionsItemSelected всякий раз, когда onOptionsItemSelected <, он вызывает onBackPressed() из действия, чтобы перейти на один уровень в иерархии и отобразить изображение навигационного ящика:

 @Override public boolean onOptionsItemSelected(MenuItem item) { // Get item selected and deal with it switch (item.getItemId()) { case android.R.id.home: //called when the up affordance/carat in actionbar is pressed getActivity().onBackPressed(); return true; … } 

Solutions Collecting From Web of "Переключение между изображениями Android Navigation Drawer и Up caret при использовании фрагментов"

Вы написали, что для реализации фрагментов нижнего уровня вы заменяете существующий фрагмент, в отличие от реализации фрагмента нижнего уровня в новом действии.

Я бы подумал, что тогда вам придется реализовать функциональность назад вручную: когда пользователь нажал назад, у вас есть код, который выталкивает стек (например, в Activity::onBackPressed override). Итак, где бы вы ни делали это, вы можете изменить setDrawerIndicatorEnabled .

Это легко, как 1-2-3.

Если вы хотите достичь:

1) Индикатор ящика – при отсутствии фрагментов в Back Stack или ящике

2) Стрелка – когда некоторые фрагменты находятся в Back Stack

 private FragmentManager.OnBackStackChangedListener mOnBackStackChangedListener = new FragmentManager.OnBackStackChangedListener() { @Override public void onBackStackChanged() { syncActionBarArrowState(); } }; @Override protected void onCreate(Bundle savedInstanceState) { getSupportActionBar().setDisplayShowHomeEnabled(true); getSupportActionBar().setDisplayHomeAsUpEnabled(true); mDrawerToggle = new ActionBarDrawerToggle( this, mDrawerLayout, R.drawable.ic_navigation_drawer, 0, 0 ) { public void onDrawerClosed(View view) { syncActionBarArrowState(); } public void onDrawerOpened(View drawerView) { mDrawerToggle.setDrawerIndicatorEnabled(true); } }; mDrawerLayout.setDrawerListener(mDrawerToggle); getSupportFragmentManager().addOnBackStackChangedListener(mOnBackStackChangedListener); } @Override protected void onDestroy() { getSupportFragmentManager().removeOnBackStackChangedListener(mOnBackStackChangedListener); super.onDestroy(); } private void syncActionBarArrowState() { int backStackEntryCount = getSupportFragmentManager().getBackStackEntryCount(); mDrawerToggle.setDrawerIndicatorEnabled(backStackEntryCount == 0); } 

3) Оба индикатора действуют в соответствии с их формой

 @Override public boolean onOptionsItemSelected(MenuItem item) { if (mDrawerToggle.isDrawerIndicatorEnabled() && mDrawerToggle.onOptionsItemSelected(item)) { return true; } else if (item.getItemId() == android.R.id.home && getSupportFragmentManager().popBackStackImmediate()) { return true; } else { return super.onOptionsItemSelected(item); } } 

PS См. Раздел Создание навигационного ящика на Android-разработчиках в других советах о поведении индикатора 3-х строк.

Я использовал следующее:

 getSupportFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() { @Override public void onBackStackChanged() { if(getSupportFragmentManager().getBackStackEntryCount() > 0){ mDrawerToggle.setDrawerIndicatorEnabled(false); getSupportActionBar().setDisplayHomeAsUpEnabled(true); } else { getSupportActionBar().setDisplayHomeAsUpEnabled(false); mDrawerToggle.setDrawerIndicatorEnabled(true); } } }); 

Если ваша кнопка на панели действий не работает, не забудьте добавить слушателя:

 // Navigation back icon listener mDrawerToggle.setToolbarNavigationClickListener(new View.OnClickListener() { @Override public void onClick(View v) { onBackPressed(); } }); 

У меня есть некоторые проблемы с реализацией навигации на ящике с помощью кнопки «домой», все работает, кроме действия.

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

 @Override public boolean onOptionsItemSelected(MenuItem item) { // Only handle with DrawerToggle if the drawer indicator is enabled. if (mDrawerToggle.isDrawerIndicatorEnabled() && mDrawerToggle.onOptionsItemSelected(item)) { return true; } // Handle action buttons switch (item.getItemId()) { // Handle home button in non-drawer mode case android.R.id.home: onBackPressed(); return true; default: return super.onOptionsItemSelected(item); } } 

СЛЕДОВАТЬ ЗА

Решение, данное @dzeikei, является опрятным, но при использовании фрагментов оно может быть расширено, чтобы автоматически обрабатывать настройку индикатора выдвижного ящика, когда стопка заднего фона пуста.

 @Override public boolean onOptionsItemSelected(MenuItem item) { // Only handle with DrawerToggle if the drawer indicator is enabled. if (mDrawerToggle.isDrawerIndicatorEnabled() && mDrawerToggle.onOptionsItemSelected(item)) { return true; } // Handle action buttons switch (item.getItemId()) { // Handle home button in non-drawer mode case android.R.id.home: // Use getSupportFragmentManager() to support older devices FragmentManager fragmentManager = getFragmentManager(); fragmentManager.popBackStack(); // Make sure transactions are finished before reading backstack count fragmentManager.executePendingTransactions(); if (fragmentManager.getBackStackEntryCount() < 1){ mDrawerToggle.setDrawerIndicatorEnabled(true); } return true; default: return super.onOptionsItemSelected(item); } } 

РЕДАКТИРОВАТЬ

По вопросу о @JJD.

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

В одном из моих приложений мне также нужно было обработать поведение курсора, когда была нажата кнопка «Назад». Это можно обрабатывать, переопределяя onBackPressed .

 @Override public void onBackPressed() { // Use getSupportFragmentManager() to support older devices FragmentManager fragmentManager = getFragmentManager(); fragmentManager.executePendingTransactions(); if (fragmentManager.getBackStackEntryCount() < 1){ super.onBackPressed(); } else { fragmentManager.executePendingTransactions(); fragmentManager.popBackStack(); fragmentManager.executePendingTransactions(); if (fragmentManager.getBackStackEntryCount() < 1){ mDrawerToggle.setDrawerIndicatorEnabled(true); } } }; 

Обратите внимание на дублирование кода между onOptionsItemSelected и onBackPressed чего можно избежать, создав метод и вызывая этот метод в обоих местах.

Также обратите внимание, что я добавляю еще два раза executePendingTransactions которые в моем случае были необходимы, или иногда я иногда executePendingTransactions странное поведение выше каретки.

Я создал интерфейс для хостинговой деятельности, чтобы обновить состояние представления меню гамбургера. Для фрагментов верхнего уровня я устанавливаю toggle в true и для фрагментов, для которых я хочу отобразить up <стрелка, я установил toggle в false .

 public class SomeFragment extends Fragment { public interface OnFragmentInteractionListener { public void showDrawerToggle(boolean showDrawerToggle); } private OnFragmentInteractionListener mListener; @Override public void onAttach(Activity activity) { super.onAttach(activity); try { this.mListener = (OnFragmentInteractionListener) activity; } catch (ClassCastException e) { throw new ClassCastException(activity.toString() + " must implement OnFragmentInteractionListener"); } } @Override public void onResume() { super.onResume(); mListener.showDrawerToggle(false); } } 

Тогда в моей деятельности …

 public class MainActivity extends Activity implements SomeFragment.OnFragmentInteractionListener { private ActionBarDrawerToggle mDrawerToggle; public void showDrawerToggle(boolean showDrawerIndicator) { mDrawerToggle.setDrawerIndicatorEnabled(showDrawerIndicator); } } 

Этот ответ работал, но с ним была небольшая проблема. Функция getSupportActionBar().setDisplayHomeAsUpEnabled(false) не вызывалась явно, и это вызывало скрытие значка ящика, даже если в нем не было элементов, поэтому изменение setActionBarArrowDependingOnFragmentsBackStack() сработало для меня.

 private void setActionBarArrowDependingOnFragmentsBackStack() { int backStackEntryCount = getSupportFragmentManager() .getBackStackEntryCount(); // If there are no items in the back stack if (backStackEntryCount == 0) { // Please make sure that UP CARAT is Hidden otherwise Drawer icon // wont display getSupportActionBar().setDisplayHomeAsUpEnabled(false); // Display the Drawer Icon mDrawerToggle.setDrawerIndicatorEnabled(true); } else { // Show the Up carat getSupportActionBar().setDisplayHomeAsUpEnabled(true); // Hide the Drawer Icon mDrawerToggle.setDrawerIndicatorEnabled(false); } } 

Логика понятна. Показывать кнопку «Назад», если ядро ​​фрагмента обратно. Покажите анимацию анимации материала в гамбургере, если фрагмент фрагмента не ясен.

 getSupportFragmentManager().addOnBackStackChangedListener( new FragmentManager.OnBackStackChangedListener() { @Override public void onBackStackChanged() { syncActionBarArrowState(); } } ); private void syncActionBarArrowState() { int backStackEntryCount = getSupportFragmentManager().getBackStackEntryCount(); mNavigationDrawerFragment.setDrawerIndicatorEnabled(backStackEntryCount == 0); } //add these in Your NavigationDrawer fragment class public void setDrawerIndicatorEnabled(boolean flag){ ActionBar actionBar = getActionBar(); if (!flag) { mDrawerToggle.setDrawerIndicatorEnabled(false); actionBar.setDisplayHomeAsUpEnabled(true); mDrawerToggle.setHomeAsUpIndicator(getColoredArrow()); } else { mDrawerToggle.setDrawerIndicatorEnabled(true); } mDrawerToggle.syncState(); getActivity().supportInvalidateOptionsMenu(); } //download back button from this(https://www.google.com/design/icons/) website and add to your project private Drawable getColoredArrow() { Drawable arrowDrawable = ContextCompat.getDrawable(getActivity(), R.drawable.ic_arrow_back_black_24dp); Drawable wrapped = DrawableCompat.wrap(arrowDrawable); if (arrowDrawable != null && wrapped != null) { // This should avoid tinting all the arrows arrowDrawable.mutate(); DrawableCompat.setTint(wrapped, Color.GRAY); } return wrapped; } 

Если вы посмотрите на приложение GMAIL и придете сюда, чтобы найти значок carret / vacance.

Я бы попросил вас сделать это, ни один из приведенных выше ответов не был ясен. Я смог изменить принятый ответ.

  • NavigationDrawer -> Listview содержит подфрагменты.


  • Субфрагменты будут перечислены следующим образом:

  • FirstFragment == position 0 —> у этого будут субфрагменты -> фрагмент

  • secondFragment
  • Третий фрагмент и т. Д ….

В firstFragment у вас есть другой фрагмент.

Вызовите это на DrawerActivity

 getFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() { @Override public void onBackStackChanged() { if (getFragmentManager().getBackStackEntryCount() > 0) { mDrawerToggle.setDrawerIndicatorEnabled(false); } else { mDrawerToggle.setDrawerIndicatorEnabled(true); } } }); 

И в фрагменте

  setHasOptionsMenu(true); @Override public boolean onOptionsItemSelected(MenuItem item) { // Get item selected and deal with it switch (item.getItemId()) { case android.R.id.home: //called when the up affordance/carat in actionbar is pressed activity.onBackPressed(); return true; } return false; } 

В методе активности OnBackPressed Drawer установите для переключателя ящика значение true, чтобы снова включить значок списка навигации.

Спасибо, Pusp

ИМО, используя onNavigateUp () (как показано здесь ) в решении riwnodennyk или Tom's, является более чистым и, похоже, работает лучше. Просто замените код onOptionsItemSelected следующим:

 @Override public boolean onSupportNavigateUp() { if (getSupportFragmentManager().getBackStackEntryCount() > 0) { // handle up navigation return true; } else { return super.onSupportNavigateUp(); } } 

Вы можете посмотреть на этот маленький пример! https://github.com/oskarko/NavDrawerExample