Android ограничивает фрагменты только один раз, чтобы вернуться в стек
Привет, ребята, я использую BottomNavigationView
, Каждый предмет BottomNavigationView
откроет фрагмент, который будет храниться в обратном стеке, но если элемент, выбранный несколько раз в обратном стеке, сохранит последний экземпляр этого фрагмента. Я имею в виду при нажатии кнопки назад фрагмент будет открываться только один раз.
Например, есть 3 фрагмента. А, В, С
Образец фрагмента: ABCBACAC
На выходе пресса должно быть: CAB-выход
Но я получу этот паттерн - CACABCBA-выход
Вот код, который я использую
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()){
case R.id.nav_home:
mFragment = getSupportFragmentManager().findFragmentByTag("Fragment_Home");
if(!(mFragment!=null && mFragment.isVisible())){
mFragmentManager.popBackStackImmediate("Fragment_Home", FragmentManager.POP_BACK_STACK_INCLUSIVE);
mFragmentTransaction = mFragmentManager.beginTransaction();
mFragmentTransaction.replace(R.id.container, new HomeFragment(), "Fragment_Home").addToBackStack("Fragment_Home").commit();
}
return true;
case R.id.nav_account:
mFragment = getSupportFragmentManager().findFragmentByTag("Fragment_Account");
if(!(mFragment != null && mFragment.isVisible())){
mFragmentManager.popBackStackImmediate("Fragment_Account", FragmentManager.POP_BACK_STACK_INCLUSIVE);
mFragmentTransaction = mFragmentManager.beginTransaction();
mFragmentTransaction.replace(R.id.container, new AccountFragment(), "Fragment_Account").addToBackStack("Fragment_Account").commit();
}
return true;
case R.id.nav_category:
mFragment = getSupportFragmentManager().findFragmentByTag("Fragment_Category");
if(!(mFragment != null && mFragment.isVisible())){
mFragmentManager.popBackStackImmediate("Fragment_Category", FragmentManager.POP_BACK_STACK_INCLUSIVE);
mFragmentTransaction = mFragmentManager.beginTransaction();
mFragmentTransaction.replace(R.id.container, new CategoryFragment(), "Fragment_Category").addToBackStack("Fragment_Category").commit();
}
return true;
}
return false;
}
@Override
public void onBackPressed() {
if (mDrawerLayout.isDrawerOpen(GravityCompat.START)) {
mDrawerLayout.closeDrawer(GravityCompat.START);
}
else if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
getSupportFragmentManager().popBackStack();
}
else if (doubleBackToExitPressedOnce) {
finishAffinity();
}
else {
this.doubleBackToExitPressedOnce = true;
Toast.makeText(this, "Please BACK again to exit", Toast.LENGTH_SHORT).show();
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
doubleBackToExitPressedOnce = false;
}
}, 2000);
}
}
Дайте мне понять, что не так с моим кодом. Любая помощь будет оценена.
2 ответа
Для этой проблемы я рекомендую использовать Viewpager вместо Back-stack фрагмента. Во-первых, я скажу вам, почему вы не должны использовать Backstack Fragment. Я полагаю, в вашем коде, когда ваша деятельность создается. Вы немедленно перейдете к своему Первому фрагменту. Например: A - B - C - C - C - C - C или A - B - C - A -B -C - A -C -B. Это удалит фрагмент backstack, как то, что вы сказали, каждый раз, когда вы щелкаете фрагмент снова, вы создаете новый. Вот еще один способ использовать Viewpager, сделать UX намного лучше. Во-первых, я настроил свой собственный FragmentStatePagerAdapter
для лучшей производительности
public abstract class SmartFragmentStatePagerAdapter extends FragmentStatePagerAdapter {
// Sparse array to keep track of registered fragments in memory
private SparseArray<Fragment> registeredFragments = new SparseArray<Fragment>();
public SmartFragmentStatePagerAdapter(FragmentManager fragmentManager) {
super(fragmentManager);
}
// Register the fragment when the item is instantiated
@Override
public Object instantiateItem(ViewGroup container, int position) {
Fragment fragment = (Fragment) super.instantiateItem(container, position);
registeredFragments.put(position, fragment);
return fragment;
}
// Unregister when the item is inactive
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
registeredFragments.remove(position);
super.destroyItem(container, position, object);
}
// Returns the fragment for the position (if instantiated)
public Fragment getRegisteredFragment(int position) {
return registeredFragments.get(position);
}
}
Давай создадим CustomViewPager
public class CustomViewPager extends ViewPager {
public CustomViewPager(Context context) {
super(context);
setMyScroller();
}
public CustomViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
setMyScroller();
}
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
// Never allow swiping to switch between pages
return false;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
// Never allow swiping to switch between pages
return false;
}
//down one is added for smooth scrolling
private void setMyScroller() {
try {
Class<?> viewpager = ViewPager.class;
Field scroller = viewpager.getDeclaredField("mScroller");
scroller.setAccessible(true);
scroller.set(this, new MyScroller(getContext()));
} catch (Exception e) {
e.printStackTrace();
}
}
public class MyScroller extends Scroller {
public MyScroller(Context context) {
super(context, new DecelerateInterpolator());
}
@Override
public void startScroll(int startX, int startY, int dx, int dy, int duration) {
super.startScroll(startX, startY, dx, dy, 350 /*1 secs*/);
}
}
}
положить его в свой XML
файл как это:
<YOUR_PACKAGE_NAME.CustomViewPager
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
Это адаптер ViewPager:
public class ViewPagerAdapter extends SmartFragmentStatePagerAdapter {
private static int NUM_ITEMS = 3;
private BaseFragment mFragment1, mFragment2, mFragment3;
public ViewPagerAdapter(FragmentManager fragmentManager) {
super(fragmentManager);
mFragment1= Fragment1.newInstance(0, FRAGMENT_TAG_1);
mFragment2= Fragment2.newInstance(1, FRAGMENT_TAG_2);
mFragment3= Fragment3.newInstance(2, FRAGMENT_TAG_3);
}
@Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return mFragment1;
case 1:
return mFragment2;
case 2:
return mFragment3;
default:
return null;
}
}
@Override
public int getCount() {
return NUM_ITEMS;
}
@Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
@Override
public Parcelable saveState() {
return null;
}
}
В вашей деятельности пусть init это в onCreateView()
mViewPager = (CustomViewPager) findViewById(R.id.viewPager);
mViewPagerAdapter = new ViewPagerAdapter(mFragmentManager);
mViewPager.setAdapter(mViewPagerAdapter);
mFrameLayout.setVisibility(View.GONE);
mViewPager.setVisibility(View.VISIBLE);
mViewPager.setSaveEnabled(true);
Когда вы нажимаете на вкладку, вам просто нужно использовать
mViewPager.setCurrentItem(NUMBER_OF_TIME);
Что вы должны сделать, так это объявить действия A,B и C как "singleTop"
Если экземпляр действия уже существует в верхней части текущей задачи, система направляет намерение этому экземпляру посредством вызова его метода onNewIntent(), а не создает новый экземпляр действия. Действие может быть создано несколько раз, каждый экземпляр может принадлежать разным задачам, и у одной задачи может быть несколько экземпляров (но только если операция в верхней части заднего стека не является существующим экземпляром действия). Например, предположим, что задний стек задачи состоит из корневого действия A с действиями B, C и D сверху (стек ABCD; D сверху). Намерение приходит для действия типа D. Если D имеет стандартный стандартный режим запуска, запускается новый экземпляр класса, и стек становится ABCDD. Однако, если режим запуска D - "singleTop", существующий экземпляр D получает намерение через onNewIntent(), потому что он находится на вершине стека - стек остается ABCD. Однако, если для действия типа B прибывает намерение, то в стек добавляется новый экземпляр B, даже если его режим запуска "singleTop".
Примечание. Когда создается новый экземпляр действия, пользователь может нажать кнопку "Назад", чтобы вернуться к предыдущему действию. Но когда существующий экземпляр действия обрабатывает новое намерение, пользователь не может нажать кнопку "Назад", чтобы вернуться в состояние действия, пока новое намерение не поступило в onNewIntent().
Вы должны прочитать документацию здесь для получения дополнительной информации по теме