У меня есть вкладки ActionBar / ViewPager макет с три вкладки говорит A , B и C . На вкладке C вкладке (фрагмент), я добавляю еще один фрагмент скажет фрагмент D . с участием
DFragment f= new DFragment();
ft.add(android.R.id.content, f, "");
ft.remove(CFragment.this);
ft.addToBackStack(null);
ft.commit();
Я изменяю панель действий в onResume DFragment, чтобы добавить кнопку:
ActionBar ab = getActivity().getActionBar();
ab.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
ab.setDisplayHomeAsUpEnabled(true);
ab.setDisplayShowHomeEnabled(true);
Теперь в DFragment, когда я нажимаю аппаратную кнопку (телефон) Назад, я возвращаюсь к исходному макету с вкладками (ABC) с выбранным CFragment. Как я могу достичь этой функции с помощью кнопки вверх на панели действий?
android
android-fragments
android-actionbar
СохаилАзиз
источник
источник
Ответы:
Реализуйте
OnBackStackChangedListener
и добавьте этот код в свою активность фрагментов.@Override public void onCreate(Bundle savedInstanceState) { //Listen for changes in the back stack getSupportFragmentManager().addOnBackStackChangedListener(this); //Handle when activity is recreated like on orientation Change shouldDisplayHomeUp(); } @Override public void onBackStackChanged() { shouldDisplayHomeUp(); } public void shouldDisplayHomeUp(){ //Enable Up button only if there are entries in the back stack boolean canGoBack = getSupportFragmentManager().getBackStackEntryCount()>0; getSupportActionBar().setDisplayHomeAsUpEnabled(canGoBack); } @Override public boolean onSupportNavigateUp() { //This method is called when the up button is pressed. Just the pop back stack. getSupportFragmentManager().popBackStack(); return true; }
источник
onSupportNavigateUp()
, «Метод не отменяет метод из своего суперкласса».onOptionsItemSelected
, можно также проверить itemIdandroid.R.id.home
вместо добавленияonSupportNavigateUp
.ActionBar
? Когда я реализую этот код, я его не вижу. Я могу только щелкнуть значок, но он ничего не делает. Android 4.0+.Я понял. просто переопределите onOptionsItemSelected в активности хостинга и откройте backstack, например
public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case android.R.id.home: { FragmentManager fm = getSupportFragmentManager(); if (fm.getBackStackEntryCount() > 0) { fm.popBackStack(); return true; } break; } } return super.onOptionsItemSelected(item); }
Звоните
getActionBar().setDisplayHomeAsUpEnabled(boolean);
иgetActionBar().setHomeButtonEnabled(boolean);
в ,onBackStackChanged()
как описано в ответ ниже.источник
switch
оператор с регистромandroid.R.id.home
.Если у вас есть одно родительское действие и вы хотите, чтобы эта кнопка вверх работала как кнопка возврата, вы можете использовать этот код:
добавьте это в onCreate в свой основной класс активности
getSupportFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() { @Override public void onBackStackChanged() { int stackHeight = getSupportFragmentManager().getBackStackEntryCount(); if (stackHeight > 0) { // if we have something on the stack (doesn't include the current shown fragment) getSupportActionBar().setHomeButtonEnabled(true); getSupportActionBar().setDisplayHomeAsUpEnabled(true); } else { getSupportActionBar().setDisplayHomeAsUpEnabled(false); getSupportActionBar().setHomeButtonEnabled(false); } } });
а затем добавьте onOptionsItemSelected вот так:
@Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case android.R.id.home: getSupportFragmentManager().popBackStack(); return true; .... }
Я обычно использую это все время и кажется вполне законным
источник
Activity
из своих, в надежде, что он вернется к фрагменту, с которого он начался. Когда я перехожу к своемуActivity
, рядом со значком приложения появляется кнопка «Назад» , но я нажимаю на значок, и ничего не происходит (он должен вернуться к фрагменту). Есть идеи, почему? Спасибо.вы можете вернуться с помощью кнопки «вверх», например кнопки «назад»;
@Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case android.R.id.home: super.onBackPressed(); return true; } return super.onOptionsItemSelected(item); }
источник
Я знаю, что это старый вопрос, но может быть, кому-то (вроде меня) он тоже нужен.
Если ваша Activity расширяет AppCompatActivity , вы можете использовать более простое (двухэтапное) решение:
1 - Всякий раз, когда вы добавляете фрагмент, отличный от домашнего, просто показывайте кнопку вверх сразу после совершения транзакции фрагмента. Как это:
// ... add a fragment // Commit the transaction transaction.commit(); getSupportActionBar().setDisplayHomeAsUpEnabled(true);
2 - Затем при нажатии кнопки ВВЕРХ вы ее скрываете.
@Override public boolean onSupportNavigateUp() { getSupportActionBar().setDisplayHomeAsUpEnabled(false); return true; }
Вот и все.
источник
Я использовал комбинацию ответов Роджера Гарсона Ньето и Сохайлазиза . В моем приложении есть одна MainActivity и загруженные в нее фрагменты A, B, C. Мой «домашний» фрагмент (A) реализует OnBackStackChangedListener и проверяет размер backStack; если меньше единицы, то кнопка ВВЕРХ скрывается. Фрагменты B и C всегда загружают кнопку возврата (в моем дизайне B запускается из A, а C запускается из B). Сама MainActivity просто выдвигает задний стек при нажатии кнопки ВВЕРХ и имеет методы для отображения / скрытия кнопки, которую вызывают фрагменты:
Основное занятие:
public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { // Respond to the action bar's Up/Home button case android.R.id.home: getSupportFragmentManager().popBackStack(); return true; } return super.onOptionsItemSelected(item); } public void showUpButton() { getSupportActionBar().setDisplayHomeAsUpEnabled(true); } public void hideUpButton() { getSupportActionBar().setDisplayHomeAsUpEnabled(false); }
fragmentA (реализует FragmentManager.OnBackStackChangedListener):
public void onCreate(Bundle savedinstanceSate) { // listen to backstack changes getActivity().getSupportFragmentManager().addOnBackStackChangedListener(this); // other fragment init stuff ... } public void onBackStackChanged() { // enable Up button only if there are entries on the backstack if(getActivity().getSupportFragmentManager().getBackStackEntryCount() < 1) { ((MainActivity)getActivity()).hideUpButton(); } }
фрагментB, фрагментC:
public void onCreate(Bundle savedinstanceSate) { // show the UP button ((MainActivity)getActivity()).showUpButton(); // other fragment init stuff ... }
источник
Это сработало для меня. Переопределите, например, onSupportNavigateUp и onBackPressed (код в Kotlin);
override fun onBackPressed() { val count = supportFragmentManager.backStackEntryCount if (count == 0) { super.onBackPressed() } else { supportFragmentManager.popBackStack() } } override fun onSupportNavigateUp(): Boolean { super.onSupportNavigateUp() onBackPressed() return true }
Теперь во фрагменте, если отобразить стрелку вверх
activity.supportActionBar?.setDisplayHomeAsUpEnabled(true)
Нажав на нее, вы вернетесь к предыдущему действию.
источник
Котлин:
class MyActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { ... supportFragmentManager.addOnBackStackChangedListener { setupHomeAsUp() } setupHomeAsUp() } private fun setupHomeAsUp() { val shouldShow = 0 < supportFragmentManager.backStackEntryCount supportActionBar?.setDisplayHomeAsUpEnabled(shouldShow) } override fun onSupportNavigateUp(): Boolean = supportFragmentManager.popBackStack().run { true } ... }
источник
Это очень хорошее и надежное решение: http://vinsol.com/blog/2014/10/01/handling-back-button-press-inside-fragments/
Этот парень сделал абстрактный фрагмент, который обрабатывает поведение backPress и переключается между активными фрагментами, используя шаблон стратегии.
Для некоторых из вас, возможно, есть небольшой недостаток в абстрактном классе ...
Вкратце решение по ссылке выглядит так:
// Abstract Fragment handling the back presses public abstract class BackHandledFragment extends Fragment { protected BackHandlerInterface backHandlerInterface; public abstract String getTagText(); public abstract boolean onBackPressed(); @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if(!(getActivity() instanceof BackHandlerInterface)) { throw new ClassCastException("Hosting activity must implement BackHandlerInterface"); } else { backHandlerInterface = (BackHandlerInterface) getActivity(); } } @Override public void onStart() { super.onStart(); // Mark this fragment as the selected Fragment. backHandlerInterface.setSelectedFragment(this); } public interface BackHandlerInterface { public void setSelectedFragment(BackHandledFragment backHandledFragment); } }
И использование в деятельности:
// BASIC ACTIVITY CODE THAT LETS ITS FRAGMENT UTILIZE onBackPress EVENTS // IN AN ADAPTIVE AND ORGANIZED PATTERN USING BackHandledFragment public class TheActivity extends FragmentActivity implements BackHandlerInterface { private BackHandledFragment selectedFragment; @Override public void onBackPressed() { if(selectedFragment == null || !selectedFragment.onBackPressed()) { // Selected fragment did not consume the back press event. super.onBackPressed(); } } @Override public void setSelectedFragment(BackHandledFragment selectedFragment) { this.selectedFragment = selectedFragment; } }
источник