IlegalStateException when trying to replace the Fragment - android

I want to display another Fragment when the phone isn't connected to a WiFi network. Normally I'm displaying MainFragment, when no connection is available ErrorFragment.
I'm using mWifi.isConnected() to check if there is a connection.
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
if (mWifi.isConnected()) {
new PostTask(1).execute();
} else {
MainFragment.firstPageListener.onSwitchToNextFragment();
}
}
This is my code (inside MainFragment) to switch to the ErrorFragment, but it's giving me
11-23 20:57:29.588: E/AndroidRuntime(4025): java.lang.IllegalStateException: Recursive entry to executePendingTransactions
This is in my MainActivity (I'm using a ViewPager):
public class SectionsPagerAdapter extends FragmentPagerAdapter {
private final class FirstPageListener implements FirstPageFragmentListener {
public void onSwitchToNextFragment() {
mFragmentManager.beginTransaction().remove(mFragmentAtPos0).commit();
if (mFragmentAtPos0 instanceof MainFragment) {
mFragmentAtPos0 = new ErrorFragment(listener);
} else { // Instance of NextFragment
mFragmentAtPos0 = new MainFragment(listener);
}
notifyDataSetChanged();
}
}
private String[] titles = { "SEARCH", "LIST" };
private final FragmentManager mFragmentManager;
public Fragment mFragmentAtPos0;
private Context context;
FirstPageListener listener = new FirstPageListener();
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
mFragmentManager = fm;
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0: // Fragment # 0
if (mFragmentAtPos0 == null) {
mFragmentAtPos0 = new MainFragment(listener);
}
return mFragmentAtPos0;
case 1: // Fragment # 1
return new ListFragment();
}
return null;
}
#Override
public int getCount() {
return titles.length;
}
#Override
public int getItemPosition(Object object) {
if (object instanceof MainFragment && mFragmentAtPos0 instanceof ErrorFragment) {
return POSITION_NONE;
}
if (object instanceof MainFragment && mFragmentAtPos0 instanceof MainFragment) {
return POSITION_NONE;
}
return POSITION_UNCHANGED;
}
#Override
public CharSequence getPageTitle(int position) {
return titles[position];
}
}
public interface MainFragmentListener {
void onSwitchToNextFragment();
}
I tried to change Fragments with:
FragmentManager fragmentManager2 = getFragmentManager();
FragmentTransaction fragmentTransaction2 = fragmentManager2.beginTransaction();
ErrorFragment fragment2 = new ErrorFragment();
fragmentTransaction2.addToBackStack("xyz");
fragmentTransaction2.hide(MainFragment.this);
fragmentTransaction2.add(android.R.id.content, fragment2);
fragmentTransaction2.commit();
But when I swipe to the other Tab, the Fragments are overlapping... What should do? Thanks!
(The thumbs down is the ErrorFragment, the Button and On/Off Switch, is in ListFragment)

Try to remove
fragmentTransaction2.hide(MainFragment.this);
and change
fragmentTransaction2.add(android.R.id.content, fragment2);
to
fragmentTransaction2.replace(android.R.id.content, fragment2);

Related

Android Activity has been destroyed when called getChildFragmentManager...commit()

My application structure is like this:
ActivityMedia is main activity that has 2 tabs: Photo & Video, each tab is FragmentCategory.
In each tab, the 1st screen is list of Category, and when click on a category, will show FragmentMediaList, which is list of Media for the category, with this code:
((ActivityMedia) getActivity()).addFragment(FragmentMediaList.newInstance(mediaType, aSite, null));
When clicking back from FragmentMediaList of Photo, it will show FragmentCategory of Photo, same for Video tab
In FragmentMediaList, when click on an item, will show ActivityMediaPlayer with this code:
Intent it = new Intent(getActivity(),ActivityMediaPlayer.class);
getActivity().startActivity(it);
When clicking back from ActivityMediaPlayer, app will show FragmentMediaList , back again, will show FragmentCategory
Everything was fine when I tested on my device, but on some of user's devices, when starting ActivityMediaPlayer, the ActivityMedia seems to be destroyed. When click back from ActivityMediaPlayer, the FragmentMediaList is showed, click back again, FragmentCategory is showed, but when click on a category in FragmentCategory, crash happens in this line of code of HostFragment class:
getChildFragmentManager().beginTransaction().replace(R.id.hosted_fragment, fragment).addToBackStack(null).commit();
It said "Activity has been destroyed"
Here are my classes details:
ActivityMedia:
public class ActivityMedia extends BaseActivity
...
protected void onCreate(Bundle savedInstanceState) {
viewPager = (ViewPager) findViewById(R.id.viewpager);
tabLayout = (TabLayout) findViewById(R.id.tablayout);
customPagerAdapter = new CustomPagerAdapter(getSupportFragmentManager());
// increase this limit if you have more tabs!
viewPager.setOffscreenPageLimit(1);
viewPager.setAdapter(customPagerAdapter);
tabLayout.setupWithViewPager(viewPager);
...
#Override public void onBackPressed() {
if(!BackStackFragment.handleBackPressed(getSupportFragmentManager())){
super.onBackPressed();
}
}
CustomPagerAdapter:
public class CustomPagerAdapter extends FragmentStatePagerAdapter {
private final List<String> tabTitles = new ArrayList<String>() {{
add("VIDEO");
add("PHOTO");
}};
private List<Fragment> tabs = new ArrayList<>();
public CustomPagerAdapter(FragmentManager fragmentManager) {
super(fragmentManager);
initializeTabs();
}
public CustomPagerAdapter(FragmentManager fragmentManager, Fragment fragment1, Fragment fragment2) {
super(fragmentManager);
tabs.add(fragment1);
tabs.add(fragment2);
}
private void initializeTabs() {
tabs.add(HostFragment.newInstance(FragmentSite.newInstance(MediaType.Movie)));
tabs.add(HostFragment.newInstance(FragmentSite.newInstance(MediaType.Photo)));
}
#Override
public Fragment getItem(int position) {
return tabs.get(position);
}
#Override
public int getCount() {
return tabs.size();
}
#Override
public CharSequence getPageTitle(int position) {
return tabTitles.get(position);
}
}
HostFragment:
public class HostFragment extends BackStackFragment {
private Fragment fragment;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
View view = inflater.inflate(R.layout.host_fragment, container, false);
if (fragment != null) {
replaceFragment(fragment, false);
}
return view;
}
public void replaceFragment(Fragment fragment, boolean addToBackstack) {
try{
if (addToBackstack) {
getChildFragmentManager().beginTransaction().replace(R.id.hosted_fragment, fragment).addToBackStack(null).commit();
} else {
getChildFragmentManager().beginTransaction().replace(R.id.hosted_fragment, fragment).commit();
}
}catch (Exception e){
getChildFragmentManager().beginTransaction().remove(this);
K.log("Error when commit fragment: " + e.getLocalizedMessage());
}
}
public static HostFragment newInstance(Fragment fragment) {
HostFragment hostFragment = new HostFragment();
hostFragment.fragment = fragment;
return hostFragment;
}
}
BackStackFragment:
public abstract class BackStackFragment extends BaseFragment {
public static boolean handleBackPressed(FragmentManager fm)
{
if(fm.getFragments() != null){
for(Fragment frag : fm.getFragments()){
if(frag != null && frag.isVisible() && frag instanceof BackStackFragment){
if(((BackStackFragment)frag).onBackPressed()){
return true;
}
}
}
}
return false;
}
protected boolean onBackPressed()
{
FragmentManager fm = getChildFragmentManager();
if(handleBackPressed(fm)){
return true;
} else if(getUserVisibleHint() && fm.getBackStackEntryCount() > 0){
fm.popBackStack();
return true;
}
return false;
}
}

Refresh a fragment inside a viewpager which is inside a fragment

I have an activity which consists of three fragments. In one of these fragments I have a viewpager that consists of three other fragments. I call getChildFragmentManager() inside fragment that has viewpager in it. I have searched SO and read almost every answer that are related to this topic for example: this and this and one that seemed most useful was this but could not solve my problem. I think if i can just return POSITION_NONE for getItemPosition(Object object) in FragmentStatePagerAdapter and call notifyDataSetChanged() will solve my problem but every time I do this my app crashes with this error:
java.lang.IllegalStateException: FragmentManager is already executing
transactions!!!
and I mentioned that I am using getChildFragmentManager() inside my fragment.
Anyone thinks of any solution to this problem?
this is the parent fragment:
public class WordDetailFragment extends Fragment {
#BindView(R.id.word_parts_tab_layout)
TabLayout mTabLayout;
#BindView(R.id.word_part_view_pager)
ViewPager mViewPager;
private WordPagerAdapter mPagerAdapter;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_word_detail, container, false);
ButterKnife.bind(this, view);
mPagerAdapter = new WordPagerAdapter(getChildFragmentManager(), getActivity());
mViewPager.setAdapter(mPagerAdapter);
mTabLayout.setupWithViewPager(mViewPager);
return view;
}
public void notifyTranslateChanged() {
mViewPager.getAdapter().notifyDataSetChanged();
}
}
this is the code for adapter
public class WordPagerAdapter extends FragmentStatePagerAdapter {
final int PAGE_COUNT = 3;
private String[] tabTitles = new String[]{"Definition", "Example", "Col & fam"};
private Context context;
public WordPagerAdapter(FragmentManager fm, Context context) {
super(fm);
this.context = context;
}
#Override
public int getCount() {
return PAGE_COUNT;
}
#Override
public Fragment getItem(int position) {
Fragment fragment;
switch (position) {
case 0:
fragment = new WordDefinitionFragment();
break;
case 1:
fragment = new WordExampleFragment();
break;
case 2:
fragment = new WordColFamFragment();
break;
default: fragment = new WordDefinitionFragment();
}
return fragment;
}
#Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
#Override
public CharSequence getPageTitle(int position) {
// Generate title based on item position
return tabTitles[position];
}
}
One of the fragments in viewpager
public class WordDefinitionFragment extends Fragment {
#BindView(R.id.show_translate_switch)
Switch mShowTranslateSwitch;
private List<WordInfo> mWordInfoList;
private List<Definition> mDefinitionList;
private boolean mShowTranslation;
private View mView;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
mView = inflater.inflate(R.layout.fragment_word_definition, container, false);
ButterKnife.bind(this, mView);
mShowTranslation = SharedPrefHelper.getBooleanInfo(getActivity(), getString(R.string.show_translate_key));
mShowTranslateSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
if (getActivity() != null)
((WordActivity) getActivity()).changeTranslateMode(b);
showTranslation(b);
}
});
return mView;
}
}
and my activity. U have just included the parts that i felt are needed here.
public class WordActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceSate) {
super.onCreate(savedInstanceSate);
setContentView(R.layout.activity_word);
}
public void changeTranslateMode(boolean show) {
SharedPrefHelper.setBooleanInfo(this, getString(R.string.show_translate_ke)y, show);
((WordDetailFragment)mWordDetailFragment).notifyTranslateChanged();
}
}
and my logcat error is
After many searches I could figure out a way which is not very smart but for the time being has solved my problem.
First of all I used the class FixedFragmentStatePagerAdapter from this post. I also had to remove the part in which the fragment bundle is restored because it caches fragment variables and views.
public abstract class FixedFragmentStatePagerAdapter extends PagerAdapter {
private static final String TAG = "PagerAdapter";
private static final boolean DEBUG = false;
private final FragmentManager mFragmentManager;
private FragmentTransaction mCurTransaction = null;
private ArrayList<Fragment.SavedState> mSavedState = new ArrayList<>();
private ArrayList<String> mSavedFragmentTags = new ArrayList<>();
private ArrayList<Fragment> mFragments = new ArrayList<>();
private Fragment mCurrentPrimaryItem = null;
public FixedFragmentStatePagerAdapter(FragmentManager fm) {
mFragmentManager = fm;
}
/**
* Return the Fragment associated with a specified position.
*/
public abstract Fragment getItem(int position);
public String getTag(int position) {
return null;
}
#Override
public void startUpdate(ViewGroup container) {
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
// If we already have this item instantiated, there is nothing
// to do. This can happen when we are restoring the entire pager
// from its saved state, where the fragment manager has already
// taken care of restoring the fragments we previously had instantiated.
if (mFragments.size() > position) {
Fragment f = mFragments.get(position);
if (f != null) {
return f;
}
}
if (mCurTransaction == null) {
mCurTransaction = mFragmentManager.beginTransaction();
}
Fragment fragment = getItem(position);
String fragmentTag = getTag(position);
if (DEBUG) Log.v(TAG, "Adding item #" + position + ": f=" + fragment + " t=" + fragmentTag);
/* if (mSavedState.size() > position) {
String savedTag = mSavedFragmentTags.get(position);
if (TextUtils.equals(fragmentTag, savedTag)) {
Fragment.SavedState fss = mSavedState.get(position);
if (fss != null) {
fragment.setInitialSavedState(fss);
}
}
}*/
while (mFragments.size() <= position) {
mFragments.add(null);
}
fragment.setMenuVisibility(false);
fragment.setUserVisibleHint(false);
mFragments.set(position, fragment);
mCurTransaction.add(container.getId(), fragment, fragmentTag);
return fragment;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
Fragment fragment = (Fragment)object;
if (mCurTransaction == null) {
mCurTransaction = mFragmentManager.beginTransaction();
}
if (DEBUG) Log.v(TAG, "Removing item #" + position + ": f=" + object
+ " v=" + ((Fragment)object).getView() + " t=" + fragment.getTag());
while (mSavedState.size() <= position) {
mSavedState.add(null);
mSavedFragmentTags.add(null);
}
mSavedState.set(position, mFragmentManager.saveFragmentInstanceState(fragment));
mSavedFragmentTags.set(position, fragment.getTag());
mFragments.set(position, null);
mCurTransaction.remove(fragment);
}
#Override
public void setPrimaryItem(ViewGroup container, int position, Object object) {
Fragment fragment = (Fragment)object;
if (fragment != mCurrentPrimaryItem) {
if (mCurrentPrimaryItem != null) {
mCurrentPrimaryItem.setMenuVisibility(false);
mCurrentPrimaryItem.setUserVisibleHint(false);
}
if (fragment != null) {
fragment.setMenuVisibility(true);
fragment.setUserVisibleHint(true);
}
mCurrentPrimaryItem = fragment;
}
}
#Override
public void finishUpdate(ViewGroup container) {
if (mCurTransaction != null) {
mCurTransaction.commitAllowingStateLoss();
mCurTransaction = null;
mFragmentManager.executePendingTransactions();
}
}
#Override
public boolean isViewFromObject(View view, Object object) {
return ((Fragment)object).getView() == view;
}
#Override
public Parcelable saveState() {
Bundle state = null;
if (mSavedState.size() > 0) {
state = new Bundle();
Fragment.SavedState[] fss = new Fragment.SavedState[mSavedState.size()];
mSavedState.toArray(fss);
state.putParcelableArray("states", fss);
state.putStringArrayList("tags", mSavedFragmentTags);
}
for (int i=0; i<mFragments.size(); i++) {
Fragment f = mFragments.get(i);
if (f != null) {
if (state == null) {
state = new Bundle();
}
String key = "f" + i;
mFragmentManager.putFragment(state, key, f);
}
}
return state;
}
#Override
public void restoreState(Parcelable state, ClassLoader loader) {
if (state != null) {
Bundle bundle = (Bundle)state;
bundle.setClassLoader(loader);
Parcelable[] fss = bundle.getParcelableArray("states");
mSavedState.clear();
mFragments.clear();
ArrayList<String> tags = bundle.getStringArrayList("tags");
if (tags != null) {
mSavedFragmentTags = tags;
} else {
mSavedFragmentTags.clear();
}
if (fss != null) {
for (int i=0; i<fss.length; i++) {
mSavedState.add((Fragment.SavedState)fss[i]);
}
}
Iterable<String> keys = bundle.keySet();
for (String key: keys) {
if (key.startsWith("f")) {
int index = Integer.parseInt(key.substring(1));
Fragment f = mFragmentManager.getFragment(bundle, key);
if (f != null) {
while (mFragments.size() <= index) {
mFragments.add(null);
}
f.setMenuVisibility(false);
mFragments.set(index, f);
} else {
Log.w(TAG, "Bad fragment at key " + key);
}
}
}
}
}
}
Then I implemented ViewPager.OnPageChangeListener in the fragment that contains the viewpager. And in the void onPageScrollStateChanged(int state) method I updated the view of my fragments in viewpager.
public class WordDetailFragment extends Fragment implements ViewPager.OnPageChangeListener {
#BindView(R.id.word_parts_tab_layout)
TabLayout mTabLayout;
#BindView(R.id.word_part_view_pager)
ViewPager mViewPager;
private WordPagerAdapter mPagerAdapter;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_word_detail, container, false);
ButterKnife.bind(this, view);
mPagerAdapter = new WordPagerAdapter(getChildFragmentManager(), getActivity());
mViewPager.setAdapter(mPagerAdapter);
mTabLayout.setupWithViewPager(mViewPager);
mViewPager.addOnPageChangeListener(this);
return view;
}
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
Fragment mFragment;
#Override
public void onPageSelected(int position) {
mFragment = mPagerAdapter.getItem(position);
}
#Override
public void onPageScrollStateChanged(int state) {
if (state == ViewPager.SCROLL_STATE_IDLE) {
if (mFragment instanceof WordDefinitionFragment) {
((WordDefinitionFragment) mFragment).showTranslation();
//Log.e("StateChanged", mFragment.getClass().getSimpleName());
}
if (mFragment instanceof WordExampleFragment) {
((WordExampleFragment) mFragment).showTranslation();
//Log.e("StateChanged", mFragment.getClass().getSimpleName());
}
if (mFragment instanceof WordColFamFragment) {
((WordColFamFragment) mFragment).showTranslation();
//Log.e("StateChanged", mFragment.getClass().getSimpleName());
}
}
}
}
And in my fragments, I had a callback interface which was implemented in the activity. And in void setUserVisibleHint(boolean isVisibleToUser) method I updated the UI again because neighbor fragments did not get updated.
public class WordExampleFragment extends Fragment {
#BindView(R.id.example_field_name_id)
TextView mExampleFieldNameTV;
#BindView(R.id.word_tv)
TextView mWordTv;
#BindView(R.id.play_sound_iv)
ImageView mPlaySoundIv;
#BindView(R.id.show_translate_switch)
Switch mShowTranslateSwitch;
private TextView mExample1ContentFaTV;
private List<WordInfo> mWordInfoList;
private List<Example> mExampleList;
private int mWordNumber;
//callback interface
private TranslateModeChangeListener mWordPartFragments;
#Override
public void onAttach(Context context) {
super.onAttach(context);
try {
mWordPartFragments = (TranslateModeChangeListener) context;
} catch (ClassCastException ex) {
throw new ClassCastException("Must implement WordPartFragments interface");
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_word_example, container, false);
ButterKnife.bind(this, view);
mWordInfoList = WordActivity.sWordInfoList;
mWordNumber = WordActivity.sWordNumber;
mExampleList = mWordInfoList.get(mWordNumber).getExamples();
showTranslation();
mShowTranslateSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
//this method is called from activity=> callback interface
mWordPartFragments.changeTranslateMode(b);
showTranslation();
}
});
return view;
}
//this method is called when viewpager shows this fragment and it is visible to user
#Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (isVisibleToUser) {
showTranslation();
}
}
//this methoud updates my UI: shows or hides the translation
public void showTranslation() {
if (isAdded()) {
boolean showTranslation = WordActivity.sTranslationShown;
//Log.e("Ex", "added & shown = " + showTranslation);
mShowTranslateSwitch.setChecked(showTranslation);
mExample1ContentFaTV.setVisibility((showTranslation) ? View.VISIBLE : View.INVISIBLE);
}
}
}

How to add fragment Tag in a FragmentPagerAdapter to reference the fragment later?

I tried the following but it didn't help . How can I set tags or acess tags of fragments from FragmentPagerAdapter ?
#Override
public Fragment getItem(int position) {
MainActivity activity = (MainActivity)mcontext;
if (position == 0) {
Fragment discoverFragment = new DiscoverFragment();
activity.getSupportFragmentManager().beginTransaction().add(discoverFragment, "discover").commit();
return discoverFragment;
} else if (position == 1){
Fragment myFeedFragment = new MyFeedFragment();
activity.getSupportFragmentManager().beginTransaction().add(myFeedFragment, "myfeed").commit();
return myFeedFragment;
} else {
Fragment filterFragment = new FilterFragment();
activity.getSupportFragmentManager().beginTransaction().add(filterFragment, "filter").commit();
return filterFragment;
}
}
It seems that you are setting the tags correctly. Anyway, this way should work.
Set tag:
MyFeedFragment myFeedFragment= new MyFeedFragment();
getSupportFragmentManager().beginTransaction().add(R.id.fragmentContainer, myFeedFragment, "myfeed");
fragmentTransaction.commit();
And then you can get it by searching tag:
List fragments = getSupportFragmentManager().getFragments();
Fragment discoverFrag = null;
Fragment myFeedFragment = null;
Fragment filterFragment = null;
for (int i = 0; i < fragments.size(); i++) {
if (((Fragment) fragments.get(i)).getTag() == "discover")
discoverFrag = (Fragment) fragments.get(i);
if (((Fragment) fragments.get(i)).getTag() == "myfeed")
myFeedFragment = (Fragment) fragments.get(i);
if (((Fragment) fragments.get(i)).getTag() == "filter")
filterFragment = (Fragment) fragments.get(i);
}
Use this this class as your adapter
class SwipeAdapter extends FragmentPagerAdapter {
private Map<Integer, String> mFragmentTags;
private FragmentManager mFragmentManager;
private String mPagetile[];
public SwipeAdapter(FragmentManager fm, Context context) {
super(fm);
mPagetile = context.getResources().getStringArray(R.array.pageTitle);
mFragmentManager = fm;
mFragmentTags = new HashMap<>();
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return new "Your_fragment";
default:
break;
}
return null;
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
Object obj = super.instantiateItem(container, position);
if (obj instanceof Fragment) {
Fragment f = (Fragment) obj;
String tag = f.getTag();
mFragmentTags.put(position, tag);
}
return obj;
}
public Fragment getFragment(int position) {
String tag = mFragmentTags.get(position);
if (tag == null)
return null;
return mFragmentManager.findFragmentByTag(tag);
}
#Override
public CharSequence getPageTitle(int position) {
return mPagetile[position];
}
#Override
public int getCount() {
return "Number of fragments";
}
}
Now with the instance of SwipeAdapter call getFrament(int "position of fragment");
Hope you get it.
To retrieve a fragment used in your FragmentPagerAdapter, you can do this anywhere (Kotlin) :
for (fragment in supportFragmentManager.fragments) {
if (fragment is YourFragment) {
val yourFragment = fragment as YourFragment
}
}

How to clear fragment backstack till a specified fragment?

I am working on an application that has tabs with viewpager. I am using fragmentstatepageradapter for handling the viewpager tabs. I am replacing the first fragment with nested fragments using the childFragmentmanager and adding the current fragment to the backstack. The control flow is as follows.
First tab fragment A -> Replaced with Fragment B -> Replaced with Fragment C ->Replaced with Fragment D.
Now when i click on a specific button in Fragment D, I need to go back to the fragment B, clearing the Fragments C,D from the backstack.
I tried
getSupportFragmentManager().popBackStack(
getSupportFragmentManager().getBackStac‌​kEntryAt(0).getId(), FragmentManager.POP_BACK_STACK_INCLUSIVE);
But unsuccessfull. Can someone tell me the correct method to clear the backstack and navigate to fragment B from fragment D.?
This is my fragmentstatepageradapter
public class HomeViewPagerAdapter extends FragmentStatePagerAdapter {
CharSequence Titles[]; // This will Store the Titles of the Tabs which are
Context mcontext; // Going to be passed when ViewPagerAdapter is
int[] images; // created
int NumbOfTabs;
private Fragment mFragmentAtPos0;
SparseArray<Fragment> registeredFragments = new SparseArray<Fragment>();
Fragment homefragment;
Context context;
FragmentManager fragmentmanager;
public HomeViewPagerAdapter(Context context, FragmentManager fm,
CharSequence mTitles[], int mNumbOfTabsumb) {
super(fm);
this.Titles = mTitles;
this.NumbOfTabs = mNumbOfTabsumb;
this.context = context;
this.fragmentmanager = fm;
}
#Override
public Fragment getItem(int position) {
// TODO Auto-generated method stub
if (position == 0)
{
SharedPreferences LoginPref = this.context.getSharedPreferences("login_credentials", Context.MODE_PRIVATE);
if (LoginPref.contains("login_pref") && LoginPref.getString("login_pref", "").equals("loggedin")) {
homefragment = new SearchHomeFragment();
} else {
homefragment = new HomeScreenFragment();
}
return homefragment;
} else if (position == 1)
{
HomeCategoriesFragment homecategoriesfragment = new HomeCategoriesFragment();
return homecategoriesfragment;
} else if (position == 2)
{
HomePriceComparisonFragment homepricecomparefragment = new HomePriceComparisonFragment();
return homepricecomparefragment;
} else if (position == 3)
{
HomeEnterFeedFragment homeenterfeedfragment = new HomeEnterFeedFragment();
return homeenterfeedfragment;
} else {
HomeMoreFragment homemorefragment = new HomeMoreFragment();
return homemorefragment;
}
}
#Override
public int getItemPosition(Object object) {
Log.e("getItemPosition", "getItemPosition");
if (object instanceof HomeScreenFragment)
return POSITION_NONE;
else
return POSITION_UNCHANGED;
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
Fragment fragment = (Fragment) super.instantiateItem(container, position);
registeredFragments.put(position, fragment);
return fragment;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
registeredFragments.remove(position);
if(MyTabFragment.shouldDestroy) {
super.destroyItem(container, position, object);
MyTabFragment.shouldDestroy=false;
}
}
public void resetScreendata() {
if (homefragment != null) {
homefragment.getChildFragmentManager().popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
}
}
public void resettoSearch() {
if (homefragment != null) {
homefragment.getChildFragmentManager().popBackStack("search", FragmentManager.POP_BACK_STACK_INCLUSIVE);
}
}
public Fragment getRegisteredFragment(int position) {
return registeredFragments.get(position);
}
#Override
public CharSequence getPageTitle(int position) {
// TODO Auto-generated method stub
return Titles[position];
}
#Override
public int getCount() {
// TODO Auto-generated method stub
return NumbOfTabs;
}
}
And this is how i am replacing the fragment.
final SearchHomeFragment newFragment = new SearchHomeFragment();
FragmentTransaction transaction =getChildFragmentManager().beginTransaction();
transaction.setCustomAnimations(R.anim.slide_in_right,R.anim.slide_out_left,R.anim.slide_in_left,R.anim.slide_out_right);
transaction.replace(R.id.fragment_mainLayout, newFragment);
transaction.addToBackStack("search");
transaction.commit();
While you are adding fragments to backstack give them a name.
fragmentTransaction.addToBackStack("fragmentA");
fragmentTransaction.addToBackStack("fragmentB");
fragmentTransaction.addToBackStack("fragmentC");
fragmentTransaction.addToBackStack("fragmentD");
Then add this code on button click:
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
FragmentManager fm = getActivity()
.getSupportFragmentManager();
fm.popBackStack ("fragmentB", FragmentManager.POP_BACK_STACK_INCLUSIVE);
}
});
It looks like your code is popping everything off the stack of fragments. Try using a specific name or id for fragment B instead of using the id for the the very first fragment in the stack.

Switch fragment Fail inside viewpager

My hierarchy is like this.A viewpager included 3 pages(all fragment),called
NewFragment,InvoledFragment and MeFragment,and outside the viewpager i set a Radiobutton to switch between Newfragment and another fragment named Hotfragment,for some reason i used hide(),show()to manage the switch,here is![enter image description here is my code
Page 1
Page 2
Page 3
RadioButton check listener
private class CheckedChangeListener implements RadioGroup.OnCheckedChangeListener {
#Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
switch (checkedId) {
case R.id.button_new:
mFragmentAtPos0 = newfrag;
fragTransaction = fragmentManager.beginTransaction();
if(!newfrag.isAdded()){
fragTransaction.hide(hotfrag).add(R.id.mainviewpager,newfrag).commit();
}
else{
fragTransaction.hide(hotfrag).show(newfrag).commit();
}
mFragmentAtPos0 = newfrag;
Toast.makeText(MainActivity.this, "NEW", Toast.LENGTH_SHORT).show();
break;
case R.id.button_hot:
fragTransaction = fragmentManager.beginTransaction();
if(!hotfrag.isAdded()){
fragTransaction.hide(newfrag).add(R.id.mainviewpager,hotfrag).commit();
}
else{
fragTransaction.hide(newfrag).show(hotfrag).commit();
}
mFragmentAtPos0 = hotfrag;
Toast.makeText(MainActivity.this, "HOT", Toast.LENGTH_SHORT).show();
break;
}
}
}
and the FragmentPagerAdapter
private class MyPagerAdapter extends FragmentPagerAdapter {
private final FragmentManager mFragmentManager;
public MyPagerAdapter(android.support.v4.app.FragmentManager fm) {
super(fm);
mFragmentManager = fm;
}
#Override
public Fragment getItem(int position) {
if(position == 0){
Log.d("check","111");
return mFragmentAtPos0;
}
else if(position == 1){
return(new InvolveFragment());
}
else {
return(new MeFragment());
}
}
#Override
public int getCount() {
return 3;
}
#Override
public int getItemPosition(Object object)
{
if (object instanceof NewFragment && mFragmentAtPos0 == hotfrag)
return POSITION_NONE;
return POSITION_UNCHANGED;
}
}
My problem is the HotFrag didn't show,but it worked (I put log code in hotfrag to check),and viewpager just works fine,I stucked here for several hours but still got no way to solve it.
There is a answer i found quite similar,it's here
Replace Fragment inside a ViewPager, but i worked with hide,show, not replace.
Anyone could help?Thanks a lot!

Categories

Resources