title: Master-Detail View using ViewPager
body: <p>I'd like to change the master-detail implementation of my Android phone app. Currently, users can select items from a <code>ListView</code>, opening a new activity. To select a different activity, the user must return to the list. Instead of this pogo-sticking, I'd like the user to swipe left and right to page through the documents using a <code>ViewPager</code>. There can be many documents, so I'd like to load at most 3 pages at a time - the current page, the previous, and the next. Paging back and forth should then add and remove pages left and right. I've created an adapter implementing <code>FragmentStatePagerAdapter</code> that handles static content (e.g. TextViews) nicely. Also deleting pages seems to work OK (not included here). But when I add e.g. an <code>EditText</code> content is copied over from one page to the next when paging.</p>
  
  <p>Below is the code for the adapter and for the activity. There are two questions I have:</p>
  
  <ol>
  <li>What is wrong with my adapter that causes the undesired copying of <code>EditText</code> from one fragment to the next?</li>
  <li>This is my first shot at this, and it's probably far from an optimal implementation. But I find this to be such a common use case that I almost feel like there would be a ready made framework for it. Could this be achieved much easier?</li>
  </ol>
  
  <p><strong>Pager Adapter:</strong></p>
  
  <pre><code>public class DetailPagerAdapter extends FragmentStatePagerAdapter {
  
      private final List&lt;Fragment&gt; mFragments;
      private final static String TAG = "DetailPagerAdapter";
  
      public DetailPagerAdapter(FragmentManager fm, List&lt;Fragment&gt; fragments) {
          super(fm);
          mFragments = fragments;
      }
  
      @Override
      public int getCount() {
          return mFragments.size();
      }
  
      @Override
      public int getItemPosition(Object object) {
          return PagerAdapter.POSITION_NONE;
      }
  
      @Override
      public Fragment getItem(int position) {
          return mFragments.get(position);
      }
  
      public void addItem(Fragment fragment) {
          mFragments.add(fragment);
          notifyDataSetChanged();
      }
  
      public void removeItem(int position) {
          mFragments.remove(position);
          notifyDataSetChanged();
      }
  
      public void insertItem(int position, Fragment fragment) {
          mFragments.add(position, fragment);
          notifyDataSetChanged();
      }
  }
  </code></pre>
  
  <p><strong>PagingActivity Base Class:</strong></p>
  
  <pre><code>public abstract class PagingActivity 
          extends AppCompatActivity
          implements ViewPager.OnPageChangeListener {
  
      protected ViewPager mViewPager;
      DetailPagerAdapter mViewPagerAdapter;
      protected ArrayList&lt;String&gt; mAllItemIds;
      private String mPreviousItemId;
      private String mCurrentItemId;
      private String mNextItemId;
  
      private boolean mMuteOnPageSelected = false;
  
  
      protected abstract Fragment getNewPageFragment(String id);
  
      @Override
      protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
  
          List&lt;Fragment&gt; initialFragments = new ArrayList&lt;&gt;();
  
          int currentItemIndex = mAllItemIds.indexOf(mCurrentItemId);
          int pageSelection = 1;
          // Add previous view.
          if (currentItemIndex &gt; 0) {
              mPreviousItemId = mAllItemIds.get(mAllItemIds.indexOf(mCurrentItemId) - 1);
              initialFragments.add(getNewPageFragment(mPreviousItemId));
          } else {
              pageSelection = 0;
              mPreviousItemId = null;
          }
          // Add current view.
          initialFragments.add(getNewPageFragment(mCurrentItemId));
          // Add next view.
          if (currentItemIndex &lt; mAllItemIds.size() - 1) {
              mNextItemId = mAllItemIds.get(mAllItemIds.indexOf(mCurrentItemId) + 1);
              initialFragments.add(getNewPageFragment(mNextItemId));
          } else {
              mNextItemId = null;
          }
  
          mViewPagerAdapter = new DetailPagerAdapter(getSupportFragmentManager(), initialFragments);
          mViewPager.setAdapter(mViewPagerAdapter);
          mViewPager.setCurrentItem(pageSelection);
  
          mViewPager.addOnPageChangeListener(this);
      }
  
      @Override
      public void onPageSelected(int position) {
  
          if (!mMuteOnPageSelected) {
              mCurrentItemId = ((PagingFragment) (mViewPagerAdapter.getItem(mViewPager.getCurrentItem()))).getItemId();
              int currentItemIndex = mAllItemIds.indexOf(mCurrentItemId);
  
              // Navigated to the right.
              if (position == mViewPagerAdapter.getCount() - 1) {
                  // Add next if not already pointing at the last available item.
                  if (currentItemIndex &lt; mAllItemIds.size() - 1) {
                      mNextItemId = mAllItemIds.get(mAllItemIds.indexOf(mCurrentItemId) + 1);
                      mViewPagerAdapter.addItem(getNewPageFragment(mNextItemId));
                  } else {
                      mNextItemId = null;
                  }
                  // If it succeeds remove first item.
                  int itemCount = mViewPagerAdapter.getCount();
                  if ((itemCount &gt; 3) || ((itemCount == 3) &amp;&amp; (currentItemIndex == mAllItemIds.size() - 1))) {
                      mMuteOnPageSelected = true;
                      mViewPagerAdapter.removeItem(0);
                      mViewPager.setCurrentItem(1);
                      mMuteOnPageSelected = false;
                  }
              }
  
              // Navigated to the left.
              else if (position == 0) {
                  // Add item on the left if not already pointing at the first available item.
                  if (currentItemIndex &gt; 0) {
                      mPreviousItemId = mAllItemIds.get(mAllItemIds.indexOf(mCurrentItemId) - 1);
                      mViewPagerAdapter.insertItem(0, getNewPageFragment(mPreviousItemId));
                  } else {
                      mPreviousItemId = null;
                  }
                  // Check if last item needs to be removed and selection updated.
                  int itemCount = mViewPagerAdapter.getCount();
                  if (itemCount == 3) {
                      if (currentItemIndex == 0) {
                          // Points to the first of two items.
                          // -&gt; do not change selection
                          // -&gt; remove rightmost item.
                          mViewPagerAdapter.removeItem(itemCount - 1);
                      } else if (currentItemIndex == mAllItemIds.size() - 2) {
                          // Will point to the middle of 3 items.
                          // -&gt; nothing to remove
                          // -&gt; select middle page.
                          mMuteOnPageSelected = true;
                          mViewPager.setCurrentItem(1);
                          mMuteOnPageSelected = false;
                      }
                  } else if (itemCount &gt; 3) {
                      // Pager contains 4 items, first item selected.
                      // -&gt; remove rightmost item
                      // -&gt; select middle page.
                      mMuteOnPageSelected = true;
                      mViewPagerAdapter.removeItem(itemCount - 1);
                      mViewPager.setCurrentItem(1);
                      mMuteOnPageSelected = false;
                  }
              }
  
              mViewPagerAdapter.notifyDataSetChanged();
          }
      }
  }
  </code></pre>