碎片不断重复

时间:2014-11-25 09:10:14

标签: android android-fragments fragmenttransaction fragmentmanager

Hee Guys,

我目前正在使用片段而我正在尝试管理它,以便当您在同一菜单项上点击两次时,它不会将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()函数每次使用相同的硬编码标记从片段本身调用最终的String。因此,同一类的每个片段都具有相同的标记。 (这应该防止双重碎片,但它仍然没有)

解决方案:

tag()在时间上返回null。 (不知道为什么)所以我改变了showFragment(片段,标签,位置)并在主要活动中硬编码了标签。然后使用:

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

别忘了将它添加到后台堆栈!或者你的后退导航不起作用。 只需添加一行:trans.addToBackStack(tag);

1 个答案:

答案 0 :(得分:1)

您可以在添加/替换片段时设置标记,

所以你需要提到它:

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

将标签值传递给根据片段

的方法
showFragment(new EventsFragment(),tag, position);

希望它会帮助你ツ