верхней панели навигации с фрагментами
у меня есть вкладка Actionbar/viewpager макет с тремя вкладками сказать A,B и C. Во вкладке C tab (фрагмент), я добавляю еще один фрагмент сказать фрагмент D. с
DFragment f= new DFragment();
ft.add(android.R.id.content, f, "");
ft.remove(CFragment.this);
ft.addToBackStack(null);
ft.commit();
Я изменяю actionbar в onResume DFragment, чтобы добавить кнопку:
ActionBar ab = getActivity().getActionBar();
ab.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
ab.setDisplayHomeAsUpEnabled(true);
ab.setDisplayShowHomeEnabled(true);
теперь в DFragment, когда я нажимаю кнопку аппаратного обеспечения(телефон) назад, я возвращаюсь к исходному макету с вкладками (ABC) с выбранным CFragment. Как я могу достичь этой функциональности с помощью кнопки actionbar up?
9 ответов:
реализовать
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 canback = getSupportFragmentManager().getBackStackEntryCount()>0; getSupportActionBar().setDisplayHomeAsUpEnabled(canback); } @Override public boolean onSupportNavigateUp() { //This method is called when the up button is pressed. Just the pop back stack. getSupportFragmentManager().popBackStack(); return true; }
Я понял. просто переопределить 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; default: return super.onOptionsItemSelected(item);; } }
вызов
getActionBar().setDisplayHomeAsUpEnabled(boolean);
иgetActionBar().setHomeButtonEnabled(boolean);
наonBackStackChanged()
как объяснено в ответе ниже.
Если у вас есть одно родительское действие и вы хотите, чтобы эта кнопка вверх работала как кнопка назад, вы можете использовать этот код:
добавьте это в 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; .... }
Я обычно использую это все время и кажется довольно законным
вы можете вернуться с кнопки как кнопки "Назад";
@Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case android.R.id.home: super.onBackPressed(); return true; } return super.onOptionsItemSelected(item); }
я использовал комбинацию Роджер Гарсон Ньето!--5--> и sohailaziz это ответы. Мое приложение имеет один MainActivity, и фрагменты A, B, C, которые загружаются в него. Мой" домашний " фрагмент (A) реализует OnBackStackChangedListener и проверяет размер backStack; если он меньше одного, то он скрывает кнопку UP. Фрагменты B и C всегда загружают кнопку "Назад" (в моем дизайне B запускается из A, а C запускается из B). Сам MainActivity просто всплывает backstack on UP button нажмите и имеет методы для отображения / скрытия кнопки, которую фрагменты вызывают:
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(); } }
fragmentB, fragmentC:
public void onCreate(Bundle savedinstanceSate) { // show the UP button ((MainActivity)getActivity()).showUpButton(); // other fragment init stuff ... }
Я знаю, что этот вопрос старый, но может быть кто-то (как я) также нуждается в этом.
Если ваша активность расширяется AppCompatActivity, вы можете использовать более простой (двухэтапный) решение:
1-всякий раз, когда вы добавляете не домашний фрагмент, просто покажите кнопку вверх, сразу после фиксации транзакции фрагмента. Вот так:
// ... add a fragment // Commit the transaction transaction.commit(); getSupportActionBar().setDisplayHomeAsUpEnabled(true);
2-Затем, когда кнопка вверх нажата, вы скрываете его.
@Override public boolean onSupportNavigateUp() { getSupportActionBar().setDisplayHomeAsUpEnabled(false); return true; }
вот именно.
это работает для меня. Переопределить 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)
щелчок по нему возвращает вас к предыдущему действию.
Это очень хорошее и надежное решение: 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; } }
Котлин:
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 } ... }