title: FragmentTransaction.replace() fade-in transition shows "ghost" fragment
body: <p>You can download my entire project to try and debug. Here is a repo of my entire code: <a href="https://bitbucket.org/lexic92/studio48/">https://bitbucket.org/lexic92/studio48/</a></p>
  
  <hr>
  
  <p><strong>I have a "ghost fragment" appearing in the transition when I try to replace a blank fragment with a blank fragment.</strong></p>
  
  <p><strong>How to recreate the problem:</strong>
  I have a navigation drawer and when I click on an item, it opens a fragment that fills the whole screen. </p>
  
  <p>Navigation Drawer:</p>
  
  <ul>
  <li>Button 1 - Fragment with text</li>
  <li><p>Button 2 - Fragment that is empty</p>
  
  <ol>
  <li><p>When I open the app, it starts out with the fragment with text.  Then, I open the Navigation Drawer and click Button 2. <strong>Transition is bad</strong>, and turns into a blank screen for a split second, then switches back to the fading text, until it becomes a blank screen.</p></li>
  <li><p>If I open the Navigation Drawer and click on Button 2 <em>again</em>, it fades from the full text to the blank screen.  So, <strong>for one split-second, it shows the fragment with text when it is not supposed to.</strong> I ran through my app on debug mode, step by step, to slow it down and verify that this behavior actually happened.</p></li>
  <li><p>If I open the Navigation Drawer and click on Button 2 <em>again</em> for the third time, it <strong>correctly does not show any animations because it is fading to the same screen.</strong></p></li>
  </ol></li>
  </ul>
  
  <p>Does anyone know why this happens? Do you think it has anything to do with the navigation drawer? </p>
  
  <p><strong>Here is a repo of my entire code:</strong> <a href="https://bitbucket.org/lexic92/studio48/">https://bitbucket.org/lexic92/studio48/</a></p>
  
  <p>Here are some code excerpts:</p>
  
  <p><strong>SongDetailActivity.java:</strong></p>
  
  <pre><code>      @Override
        public void onNavigationDrawerItemSelected(int position) {
          // update the main content by replacing fragments
          FragmentManager fragmentManager = getSupportFragmentManager();
  
          //OPEN THE BLANK SCREEN
          if(position == 1) {
              fragmentManager.beginTransaction()
                      //.setCustomAnimations(R.anim.fade_in, R.anim.fade_out)
                      .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE)
                      .replace(R.id.songlist_detail_container, PlaceholderFragment.newInstance(position + 1, mSongId))
                      .commit();
          }
          //OPEN THE SCREEN WITH TEXT
          else {
              SongDetailFragment sdf = new SongDetailFragment();
              Bundle args = new Bundle();
              args.putString(SongDetailFragment.ARG_ITEM_ID, mSongId);
              sdf.setArguments(args);
              fragmentManager.beginTransaction()
                      //.setCustomAnimations(R.anim.fade_in, R.anim.fade_out)
                      .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE)
                      .replace(R.id.songlist_detail_container, sdf)
                      .commit();
          }
      }
  </code></pre>
  
  <p>The same problem happens when I comment out the 2 lines that say ".setTransition" and un-comment the 2 lines that say ".setCustomAnimations". Here are the custom animations:</p>
  
  <p><strong>res/anim/fade_out.xml:</strong></p>
  
  <pre><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;
  &lt;set xmlns:android="http://schemas.android.com/apk/res/android"&gt;
      &lt;alpha android:fromAlpha="1.0" android:toAlpha="0.0"
             android:duration="@android:integer/config_mediumAnimTime" /&gt;
  &lt;/set&gt;
  </code></pre>
  
  <p><strong>res/anim/fade_in.xml</strong></p>
  
  <pre><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;
  &lt;set xmlns:android="http://schemas.android.com/apk/res/android"&gt;
      &lt;alpha android:fromAlpha="0.0" android:toAlpha="1.0"
             android:duration="@android:integer/config_mediumAnimTime" /&gt;
  &lt;/set&gt;
  </code></pre>
  
  <p>How can I get it to transition smoothly without the "ghost" fragment showing up?</p>
  
  <p><strong>Specs:</strong> I am running with android.support.v7.app.ActionBarActivity, minSdkVersion == 15, and targetSdkVersion == 21, on a Google Nexus 5 physical device (not an emulator).</p>
  
  <p><strong>My guesses of the answer:</strong></p>
  
  <p>This website seems to give me a hint: <a href="http://gotoanswer.com/?q=Android+Animation+within+a+Fragment+not+working">http://gotoanswer.com/?q=Android+Animation+within+a+Fragment+not+working</a></p>
  
  <blockquote>
    <p>Personally for me this is a bug with the zPosition for Fragment
    animations.</p>
    
    <p>What you see is the new fragment "appearing" this is because the new
    fragment is attached underneath the current one.</p>
    
    <p>So when trying to animate a fragment 'Over the top' of an existing
    fragment, it appears like nothing is happening then the new one just
    'appears'.</p>
    
    <p>I have tried many work arounds, playing with zPosition (only affects
    windows not layouts, so no effect to fragments), onAnimationCreate()
    bringing the root layout to front or even on animation start and
    stop... seems to do nothing.</p>
    
    <p>So at this point in time without writing a complete custom animation
    for fragment transitions, they are a bit buggy at the moment.</p>
    
    <p>You may have to play with. .add(Fragment) wait for it to be added,
    then call .remove(Fragment) removing the old fragment, that way the
    new fragment is physically placed on top of the existing fragment.</p>
  </blockquote>
  
  <p>I did notice that <strong>this code</strong> was being called upon instantiation of SongDetailActivity.java, even without me clicking on the navigation drawer:</p>
  
  <pre><code>//OPEN THE SCREEN WITH TEXT
              else {
                  SongDetailFragment sdf = new SongDetailFragment();
                  Bundle args = new Bundle();
                  args.putString(SongDetailFragment.ARG_ITEM_ID, mSongId);
                  sdf.setArguments(args);
                  fragmentManager.beginTransaction()
                          //.setCustomAnimations(R.anim.fade_in, R.anim.fade_out)
                          .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE)
                          .replace(R.id.songlist_detail_container, sdf)
                          .commit();
              }
  </code></pre>
  
  <p>Maybe the current fragment is fading out to this "underlying" fragment, as the quotation suggests, before fading in to the new fragment?</p>
  
  <h2>What I ended up doing</h2>
  
  <p><em>Note: I am not putting this as an answer because it does not technically answer my question, but it's the best back-up-plan solution I can come up with.</em></p>
  
  <p>I tried seeing if the problem was solved when there was <em>no</em> animation. The "ghost fragment" didn't show up, but I <em>did</em> notice that it took a split second to load the fragment, which looked jarring and ugly. I wanted a silky smooth app, and if it isn't smooth when there was <em>no</em> animation, then it will probably be hopeless even if I <em>did</em> fix the ghost fragment bug. I learned that fragments are just buggy (see <a href="http://www.techrepublic.com/article/the-good-the-bad-and-the-ugly-working-with-androids-child-fragment-manager-and-custom-transitions/">here</a>).  </p>
  
  <p>I decided to hide and show views instead. Here is my new code:</p>
  
  <p><strong>SongDetailActivity.java</strong></p>
  
  <pre><code>//---------- NAVIGATION DRAWER -------------
      @Override
      public void onNavigationDrawerItemSelected(int position) {
  
          //HOME
          if (position == 0) {
  
          }
          //LYRICS
          else if(position == 1) {
              findViewById(R.id.lyrics).setVisibility(View.VISIBLE);
              findViewById(R.id.info).setVisibility(View.INVISIBLE);
  
          }
          //INFO
          else if(position == 2) {
              findViewById(R.id.info).setVisibility(View.VISIBLE);
              findViewById(R.id.lyrics).setVisibility(View.INVISIBLE);
          }
      }
  </code></pre>
  
  <p>I also copied and pasted the layouts for the 2 fragments (the empty one and the one with lots of text) into the same layout, as children of a FrameLayout parent:</p>
  
  <p><strong>fragment_songlist_detail.xml:</strong></p>
  
  <pre><code>&lt;FrameLayout
      xmlns:android="http://schemas.android.com/apk/res/android"
      android:layout_height="match_parent"
      android:background="#f8bbd0"
      android:layout_width="match_parent"
      &gt;
      &lt;LinearLayout
          android:id="@+id/lyrics"
          android:orientation="horizontal"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          xmlns:android="http://schemas.android.com/apk/res/android"&gt;
      ...
      &lt;/LinearLayout&gt;
      &lt;LinearLayout
          android:id="@+id/info"
          android:orientation="horizontal"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          xmlns:android="http://schemas.android.com/apk/res/android"&gt;
      ...
      &lt;/LinearLayout&gt;
  &lt;/FrameLayout&gt;
  </code></pre>
  
  <p>It works fine, but I just don't know how to make it fade in and fade out. But that is a question for a separate stack overflow question. If anyone solves the ghost fragment mystery, I'm very interested to know the answer. But I decided I'm not going to waste my time trying to figure it out right now, especially when fragments' transitions have proven to be buggy in the past (like in that <a href="http://www.techrepublic.com/article/the-good-the-bad-and-the-ugly-working-with-androids-child-fragment-manager-and-custom-transitions/">article</a>).</p>