android – FragmentPagerAdapter Swipe to show ListView 1/3 Screen Width-ThrowExceptions

Exception or error:

EDIT: See my answer below–>

I am wanting to have a view that when swiped to the right, the listView is shown. Very much similar to what is implemented in the new Google Play Store (Sample image below). I think its a ViewPager but I tried duplicating it without prevail. I was thinking it may just be that the ‘listView Page’ width attribute was set to a specific dp but that doesn’t work. I also tried modifying pakerfeldt’s viewFlow and cant figure out how Google does this

Am I on the right track? If someone has an idea how to duplicate this, I would greatly appreciate it. I think this may become a popular new way of showing a navigation view on tablets….? Code would be best of help. Thank you!!

enter image description here

Swipe right:

enter image description here

Finnished swipe; the layout shows the list and PART OF THE SECOND FRAGMENT (EXACTLY AS SHOWN) The list fragment does not fill the screen:

enter image description here

When the user swipes left, the main page is only shown and if the user swipes left again the viewPager continues to the next page.

How to solve:

The following code achieves the desired effect:

In PageAdapter :

@Override
public float getPageWidth(int position) {
if (position == 0) {
    return(0.5f);
} else {
    return (1.0f);       
}

###

Reading your question one last time… make sure you also set up specific layouts for each size device. In your screenshots it looks like your trying to run this on a tablet. Are you getting the same results on a phone?

Setting up your Layout

Make sure your layout is simular to this and has the ViewPager:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
          android:orientation="vertical"
          android:layout_width="fill_parent"
          android:layout_height="fill_parent"
          android:background="@color/body_background">

<include layout="@layout/pagerbar" />
<include layout="@layout/colorstrip" />

<android.support.v4.view.ViewPager
        android:id="@+id/example_pager"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_weight="1" />

</LinearLayout>

Setting up your Activity

Setup your PagerAdapter in your “FragmentActivity” and make sure you implement “OnPageChangeListener”. Then properly setup your PagerAdapter in your onCreate.

public class Activity extends FragmentActivity 
             implements ViewPager.OnPageChangeListener { 
   ...

    public void onCreate(Bundle savedInstanceState) {

       PagerAdapter adapter = new PagerAdapter(getSupportFragmentManager());
       pager = (ViewPager) findViewById(R.id.example_pager);

       pager.setAdapter(adapter);
       pager.setOnPageChangeListener(this);
       pager.setCurrentItem(MyFragment.PAGE_LEFT);

       ...
   }


   /* setup your PagerAdapter which extends FragmentPagerAdapter */

   static class PagerAdapter extends FragmentPagerAdapter {
       public static final int NUM_PAGES = 2;

       private MyFragment[] mFragments = new MyFragment[NUM_PAGES];

          public PagerAdapter(FragmentManager fragmentManager) {
           super(fragmentManager);
       }

       @Override
       public int getCount() {
           return NUM_PAGES;
       }

       @Override
       public Fragment getItem(int position) {
           if (mFragments[position] == null) {
               /* this calls the newInstance from when you setup the ListFragment */
               mFragments[position] = MyFragment.newInstance(position);
           }

           return mFragments[position];
       }
   }

 ...

Setting up your Fragment

When you setup your actual ListFragment (your listViews) you can create multiple instances with arguments like the following:

  public static final int PAGE_LEFT = 0;
  public static final int PAGE_RIGHT = 1;

  static MyFragment newInstance(int num) {
       MyFragment fragment = new MyFragment();

       Bundle args = new Bundle();
       args.putInt("num", num);

       fragment.setArguments(args);
       return fragment;
   }

When you reload the listViews (how ever you decide to implement this) you can figure out which fragment instance you are on using the arguments like so:

    mNum = getArguments() != null ? getArguments().getInt("num") : 1;

If you step through your code you will notice that it will step through each instance so the above code is only needed in your onCreate and a reload method may look like this:

private void reloadFromArguments() {
    /* mNum is a variable which was created for each instance in the onCreate */
    switch (mNum) {
        case PAGE_LEFT:
            /* maybe a query here would fit your needs? */
            break;

        case PAGE_RIGHT:
            /* maybe a query here would fit your needs? */
            break;
    }
}

Few Sources that may help you out with examples that you could build from rather then starting from scratch:

More explanation and example from playground.
http://blog.peterkuterna.net/2011/09/viewpager-meets-swipey-tabs.html
which is references to:
http://code.google.com/p/android-playground/

More info and some good linkage.
http://www.pushing-pixels.org/2012/03/16/responsive-mobile-design-on-android-from-view-pager-to-action-bar-tabs.html

If you have more specific questions post and I can always Edit (update) my answer to address your questions. Good Luck! 🙂

###

Sorry for the late update. I implemented this from walkingice on Gethub with very little modification. Just use a conditional statement for a GestureDetector to swipe it into view only when a ViewPager id of ‘0’ is in view. I also added a toggle whithin my ActionBar

###

ViewPager is a part of the Compatibly Package

If you’re using Fragments, then you can use ViewPager to swipe between them.

Here’s an example of combining Fragments and ViewPager

In your particular case, you would want to create a ListFragment and then implement ViewPager.

###

I think you are looking to implement a “side navigation” beside a standard ViewPager.

I’ve read 2 different articles on this pattern:

The first one on the pattern itself:

Android Ui Pattern Emerging UI Pattern – Side Navigation

The second on a more detailed way of who to build it:

Cyril Mottier Fly-in app menu #1 #2 #3

This second article is referenced in Android Ui Pattern blog.

###

With a little Trick, the behavior can be achieved with the ScrollView-Behavior inside the ViewPager. If you only want to restrict the area of the most left fragment, you can restrict the scroll limits of the ScrollView.

In your case:
in the onPageChangeListener of the ViewPager do something like that:

@Override
public void onPageScrollStateChanged(int arg0) {
    restrictLeftScroll();
}

@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
    restrictLeftScroll();
}

@Override
public void onPageSelected(int arg0) {

}

private void restrictLeftScroll() {

    if (display != null) {

        /* get display size */
        Point size = new Point();
        display.getSize(size);

        /* get desired Width of left fragment */
        int fragmentWidth = getResources().getDimensionPixelSize(R.dimen.category_fragment_width);

        if (mViewPager.getScrollX() < size.x - fragmentWidth) {
            mViewPager.scrollTo(size.x - fragmentWidth, mViewPager.getScrollY());
        }
    }
}

This piece of code worked for me without problems. 😉

Leave a Reply

Your email address will not be published. Required fields are marked *