6

I replace a FrameLayout with a fragment using fragmentTransaction.replace().

Layout:

<FrameLayout
        android:id="@+id/articlesAppender"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
</FrameLayout>

Replacing in Activity's onCreate:

FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
articlesFragment = (ArticlesFragment) fragmentManager.findFragmentByTag(ARTICLES_FRAGMENT_TAG);

if (articlesFragment == null) {
    articlesFragment = new ArticlesFragment();
}

fragmentTransaction.replace(R.id.articlesAppender, articlesFragment, ARTICLES_FRAGMENT_TAG);
fragmentTransaction.commit();

ArticleFragment's onCreate:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    view = inflater.inflate(R.layout.articles_fragment, container, false);
    view.setVisibility(View.GONE);
    return view;
}

But the view.setVisibility(View.GONE); is not working on support library 25.1.0. So the fragment will still be displayed on the screen. If I set the visibility of the articlesAppender to GONE. So it should look like this:

<FrameLayout
        android:id="@+id/articlesAppender"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:visibility="gone">
</FrameLayout>

Then the the fragment will not be visible on the screen, but when I try to call view.setVisibility(View.VISIBLE); later, it still not works. The fragment still not be visible.

That means the view which is returned by inflater.inflate(R.layout.articles_fragment, container, false); is not the real view of the fragment. But it works perfectly on support library 25.0.1.

So it's an Android's bug?

Ziem
  • 6,579
  • 8
  • 53
  • 86
Kimi Chiu
  • 2,103
  • 3
  • 22
  • 37
  • Do you want to replace frame layout with fragment? – Rishabh Mahatha Dec 15 '16 at 06:54
  • How did you come to the conclusion that the replace() method is not working ? If you try to setVisibility(View.GONE) on the main root element in that fragment layout instead on the inflated view, does it still not working ? – Gilad Eshkoli Dec 15 '16 at 08:11
  • @RishabhMahatha Yes, I want to replace it. @Gil Because it works on support library 25.0.1. And I've described the situation in my question. I have to set the articlesAppender's visibility directly. That means it's not replaced. The inflated view is the root element, that's why I return this view in `onCreateView()`. – Kimi Chiu Dec 15 '16 at 09:57

3 Answers3

7

issue is reported. more people seems to have this issue

https://code.google.com/p/android/issues/detail?id=230191

Gillis Haasnoot
  • 2,229
  • 1
  • 19
  • 23
  • 3
    And it is not the only one. They now fire onStop and onStart in a different succession when you swap 2 views. So, we should probably stick to 25.0.1 for now. – Dmitry Dec 18 '16 at 05:33
  • 1
    "Development team has fixed this issue" as their pm said https://code.google.com/p/android/issues/detail?id=230526&q=AppCompat%2025.1.0&colspec=ID%20Status%20Priority%20Owner%20Summary%20Stars%20Reporter%20Opened – Orcun Sevsay Jan 12 '17 at 10:33
  • @Dmitry, the fix for that issue is as follows, .setAllowOptimization(false). I learned this the hard way. – worked Jan 26 '17 at 01:07
  • @worked Yes, I know. It is mentioned in the issue I posted at code.google.com. Still, strange that they do not mention such important changes in release notes. – Dmitry Jan 26 '17 at 06:52
  • @worked In the [release notes](https://developer.android.com/topic/libraries/support-library/revisions.html) it says "This optimization is disabled by default." So it's not necessary to set it to false. – Orcun Sevsay Feb 01 '17 at 15:25
  • I still have the issue. My viewpager tabs are gone after replacing a fragment with another (viewpager is inside the fragments) – Gillis Haasnoot Feb 01 '17 at 23:33
  • @MiloRambaldi that's for 25.1.1 recently released, which reverses the previous default behavior of 25.1.0. – worked Feb 03 '17 at 18:10
  • I've tried 25.1.1. The problem persists. Reverting to 25.0.1 again. – Clo Knibbe Feb 03 '17 at 21:06
  • They have fixed this problem, but maybe it's not included in 25.1.1. – Kimi Chiu Feb 04 '17 at 10:14
  • I added another bug report at https://code.google.com/p/android/issues/detail?id=233324&sort=-opened&colspec=ID%20Status%20Priority%20Owner%20Summary%20Stars%20Reporter%20Opened – Gillis Haasnoot Feb 04 '17 at 22:30
2

It seems to be a reported bug, as noted in Gillis Haasnoot's post.

I noticed that if I split replace() into remove() and add(), and use commitNow() it seems to work as expected.

Original code (fails starting with 25.1.0):

fragMngr.beginTransation()
    .replace(R.id.detail_container, newFrag, fragTag)
    .commit();

Work-around:

// remove old fragment
Fragment oldFrag = fragMngr.findFragmentByTag(fragTag);
if (oldFrag != null {
    fragMngr.beginTransaction().remove(oldFrag).commitNow();
}

// add new fragment
fragMngr.beginTransaction()
    .add(R.id.detail_container, newFrag, fragTag)
    .commitNow();
Clo Knibbe
  • 369
  • 2
  • 10
  • OK; but think that you have a really big project that is used too many fragment transaction. It's not logical to change all commit() structures with commitNow() structures. It's really unnecessary work, isn' it? – Orcun Sevsay Dec 20 '16 at 11:56
  • 1
    Of course. This is just suggested as a work-around while waiting for the actual fix. Or you can revert to the previous version of the support library. – Clo Knibbe Dec 20 '16 at 15:17
  • Good suggestion... funny thing is I'm trying this work-around but it won't work... after doing `fragMngr.beginTransaction().remove(oldFrag).commitNow();` The fragment is still there, checking with `fragMngr.findFragmentByTag(fragTag);` it will not return null. Even if I do a while loop, it would create an infinite loop. Any idea why? – Hugo Allexis Cardona Jan 16 '18 at 21:18
  • @HugoAllexisCardona: no, I'm sorry, I don't know why. – Clo Knibbe Jan 18 '18 at 17:13
-1
    //replace fragment
    private void replaceFragment(final Fragment newFragment, final int containerId) {
        final FragmentManager fragmentManager = getFragmentManager();
         final FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
        fragmentTransaction.replace(containerId, newFragment, newFragment.getClass().getSimpleName());
       fragmentTransaction.commit();
   }

ArticleFragment's onCreate:

 @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        view = inflater.inflate(R.layout.articles_fragment, container, false);
                return view;
    }

    <FrameLayout
            android:id="@+id/articlesAppender"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
    </FrameLayout>

Just call this method in your MainActivity onCreate() Where

newFreagment = "Fragment you want to replace with" containerId = "Framelayout id"

Rishabh Mahatha
  • 1,251
  • 9
  • 19