Фрагменты продолжают дублировать

Привет, ребята,

В настоящее время я работаю с фрагментами и пытаюсь управлять ими, чтобы при двойном нажатии на один и тот же пункт меню он не помещал 2 одинаковых фрагмента поверх друг друга. Однако это все еще делает. Может кто-нибудь сказать мне, что я делаю не так?

/*
* Method to check which action is behind the selected Menu item. Then call ShowFragment()
* With the correct fragment parameter used with this Menu action value.
 */
public void getAction(int position, Cursor cursor) {
    // TODO Auto-generated method stub
    mCursor = cursor;
    cursor.moveToPosition(position);
    String action = cursor.getString(cursor.getColumnIndex(AppMenu.ACTION));
    if (action != null) {
        if (action.equalsIgnoreCase("home")) {
            trans = manager.beginTransaction();
            BaseFragment newFragment = new HomeFragment();
            if (manager.findFragmentByTag(newFragment.getTag()) != null) {
                mCursor.moveToPosition(position);

                // Set the current fragment
                mCurrentFragment = newFragment;
                Bundle bundle = new Bundle();
                int fragId = mCursor.getInt(mCursor.getColumnIndex(AppMenu._ID));
                Log.i(TAG, fragId + " ");
                bundle.putInt("fragmentID", fragId);
                newFragment.setArguments(bundle);

                trans.replace(R.id.fragmentContainer, newFragment).addToBackStack(
                        newFragment.tag());
                trans.commit();
            } else {
                trans.show(newFragment);
            }

        } else if (action.equalsIgnoreCase("event")) {
            showFragment(new EventsFragment(), position);
        } else if (action.equalsIgnoreCase("location")) {
            showFragment(new LocationsFragment(), position);
        } else if (action.equalsIgnoreCase("news")) {
            showFragment(new NewsFragment(), position);
        } else if (action.equalsIgnoreCase("bars")) {
            showFragment(new BarsFragment(), position);
        } else if (action.equalsIgnoreCase("currency")) {
            showFragment(new CurrencyFragment(), position);
        } else if (action.equalsIgnoreCase("map")) {
            showFragment(new MapFragment(), position);
        }
    } else {
        Log.i(TAG, "You've got a nullpointerexception on getAction().");
    }
}
/*
* Method that's called when changing from fragment through Menu or HomeMenu.
 */
public void showFragment(BaseFragment newFragment, int position) {
    trans = manager.beginTransaction();
    if (manager.findFragmentByTag(newFragment.tag()) == null) {
        mCursor.moveToPosition(position);

        // Set the current fragment
        mCurrentFragment = newFragment;

        // Go on and set the bundle values and pass it on the fragment.
        Bundle bundle = new Bundle();
        int fragId = mCursor.getInt(mCursor.getColumnIndex(AppMenu._ID));
        Log.i(TAG, fragId + " ");
        bundle.putInt("fragmentID", fragId);
        newFragment.setArguments(bundle);

        trans.replace(R.id.fragmentContainer, newFragment).addToBackStack(
                newFragment.tag());
        trans.commit();
    } else {
        trans.show(newFragment);
    }
}

И вот 2 обратных вызова для того, когда что-то изменяется или когда нажата спина.

 /*
* Interface method called whenever a new fragment is created.
 */
@Override
public void onNewFragment(BaseFragment newFragment) {
    // TODO Auto-generated method stub

    FragmentManager fm = getSupportFragmentManager();
    Class<? extends Fragment> newFragmentClass = newFragment.getClass();
    if (newFragmentClass == EventsFragment.class
            || newFragmentClass == LocationsFragment.class
            || newFragmentClass == MapFragment.class
            || newFragmentClass == NewsFragment.class
            || newFragmentClass == CurrencyFragment.class
            || newFragmentClass == BarsFragment.class) {
        for (Fragment fragment : fm.getFragments()) {
            if (fragment != null && ((Object) fragment).getClass() == newFragmentClass) {
                while (((Object) mCurrentFragment).getClass() != newFragmentClass) {
                    popFragment();
                }
                popFragment();
                break;
            }
        }
    }
}
/*
* Interface method called when you navigate back from a fragment.
* Checks which fragment is active, calls upon this fragments back function to clear any data,
* then pops the first fragment on the backstack.
 */
@Override
public void onBackNavigated() {
    // TODO Auto-generated method stub
    if ((mCurrentFragment instanceof HomeFragment)
            && !((HomeFragment) mCurrentFragment)
            .isStackEmpty()) {
       System.exit(0);
        // break;
    }
    if ((mCurrentFragment instanceof LocationsFragment)
            && !((LocationsFragment) mCurrentFragment)
            .isStackEmpty()) {
        ((LocationsFragment) mCurrentFragment).goBack();
        // return;
    }
    if ((mCurrentFragment instanceof EventsFragment)
            && !((EventsFragment) mCurrentFragment)
            .isStackEmpty()) {
        ((EventsFragment) mCurrentFragment).goBack();
        // return;
    }
    if ((mCurrentFragment instanceof MapFragment)
            && !((MapFragment) mCurrentFragment).isStackEmpty()) {
        ((MapFragment) mCurrentFragment).goBack();
        // break;
    }
    if ((mCurrentFragment instanceof BarsFragment)
            && !((BarsFragment) mCurrentFragment).isStackEmpty()) {
        ((BarsFragment) mCurrentFragment).goBack();
        // break;
    }
    if ((mCurrentFragment instanceof CurrencyFragment)
            && !((CurrencyFragment) mCurrentFragment).isStackEmpty()) {
        ((CurrencyFragment) mCurrentFragment).goBack();
        // break;
    }
    popFragment();
}
/*
* Pops the first fragment in the backstack. Then sets this as the new current fragment.
* If no fragment is in the backstack then finish() is called. Which will destroy the only fragment.
* Which in this case exits the application.
 */
public void popFragment() {
    if (manager.getBackStackEntryCount() > 1) {
        manager.popBackStack();
        manager.executePendingTransactions();
        ArrayList<Fragment> reversedFragments = new ArrayList<Fragment>(
                manager.getFragments());
        Collections.reverse(reversedFragments);
        for (Fragment fragment : reversedFragments)
            if (fragment != null) {
                mCurrentFragment = (BaseFragment) fragment;
                break;
            }
    } else {
        finish();
    }
}

** ПРИМЕЧАНИЕ: ** Функции tag() каждый раз вызывают финальную строку из самого фрагмента с одним и тем же жестко закодированным тегом. Таким образом, каждый фрагмент одного и того же класса имеет один и тот же тег. (Который должен предотвращать двойные фрагменты, но это все еще не делает)

Решение:

Тег () возвращал ноль все время. (Не знаю почему). Так что я изменил showFragment(фрагмент, тег, положение) и жестко закодировал тег в основной деятельности. Затем использовали:

trans.replace(R.id.fragmentContainer, newFragment, tag); 
//instead of
trans.replace(R.id.fragmentContainer, newFragment).addToStackBack(tag);

Не забудьте добавить его в бэкстек! Или ваша задняя навигация не будет работать. Просто добавьте дополнительную строку: trans.addToBackStack(tag);

1 ответ

Решение

Вы можете установить тег при добавлении / замене фрагмента,

Так что вам нужно упомянуть это как:

trans.replace(R.id.fragmentContainer, newFragment,tag);

Передайте значение тега методу в соответствии с фрагментом

showFragment(new EventsFragment(),tag, position);

Надеюсь, это поможет вам ツ

Другие вопросы по тегам