Creating a simple Vertical ViewPager in Android

Android ViewPager is a Layout Manger that allows the user to flip left and right through pages of data. But sometimes we may need to scroll vertically instead of horizontally. Here’s how I created a simple Vertical ViewPager using a ScrollView.

In the layout xml I added four TextViews into the ScrollView. Notice that the android:layout_height is set to 150dip for all childs. So only one child can be visible at once.

<ScrollView
android:id="@+id/scrollView1"
android:layout_width="175dip"
android:layout_height="150dip"
android:layout_gravity="center_vertical"
android:scrollbars="none" >

<LinearLayout
android:layout_width="match_parent"
android:layout_height="150dip"
android:layout_gravity="center_horizontal"
android:orientation="vertical" >

<TextView
android:layout_width="match_parent"
android:layout_height="150dip"
android:layout_gravity="center_horizontal"
android:background="@drawable/ic_launcher"
android:text="Item 1" />

<TextView
android:layout_width="match_parent"
android:layout_height="150dip"
android:layout_gravity="center_horizontal"
android:background="@drawable/ic_launcher"
android:text="Item 2" />

<TextView
android:layout_width="match_parent"
android:layout_height="150dip"
android:layout_gravity="center_horizontal"
android:background="@drawable/ic_launcher"
android:text="Item 3" />

<TextView
android:layout_width="match_parent"
android:layout_height="150dip"
android:layout_gravity="center_horizontal"
android:background="@drawable/ic_launcher"
android:text="Item 4" />
</LinearLayout>
</ScrollView>

In the Activity, I listen for the onFling event and scroll the ScrollView to the correct place using the smoothScrollTo method.

		final int density = (int)getResources().getDisplayMetrics().density;

		mGestureDetector = new GestureDetector(getApplicationContext(),new GestureDetector.SimpleOnGestureListener() {
			int selectedPage=0;
			@Override
			public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
				if(velocityY<0){
					selectedPage = Math.min(3, selectedPage+1);
				}else{
					selectedPage = Math.max(0, selectedPage-1);
				}
				mScrollView.smoothScrollTo(0, 150 * density * selectedPage);
				return super.onFling(e1, e2, velocityX, velocityY);
			}

		});

		mScrollView = (ScrollView) findViewById(R.id.scrollView1);
		mScrollView.setOnTouchListener(new OnTouchListener() {
			@Override
			public boolean onTouch(View v, MotionEvent event) {
				mGestureDetector.onTouchEvent(event);
				return true;
			}

		});

The output should look like this,
device-2013-06-26-113321

 

Full Android project can be found here http://www.sendspace.com/file/hz5jyn

Android ViewPager with Multiple Views

Recently I had to customize the standard ViewPager in order to make multiple Views visible at the same time. Here’s how I achieved this.

First let’s add a standard ViewPager to our Activity.

In the layout XML file,

<FrameLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:background="#FFFFFF">

<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="200dip"
android:layout_height="200dip"
android:layout_gravity="center_horizontal|center_vertical"/>
</FrameLayout>

In the Activity we need to set a PagerAdapter which will supply views to the ViewPager.

@Override
protected void onCreate(Bundle savedInstanceState) {
	super.onCreate(savedInstanceState);
	setContentView(R.layout.activity_main);
	ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager);
	viewPager.setAdapter(new ViewAdapter());
}

private class ViewAdapter extends PagerAdapter{

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

@Override
public boolean isViewFromObject(View view, Object object) {
	return (view == object);
}

@Override
public Object instantiateItem(ViewGroup container, int position) {
	TextView textView = new TextView(MainActivity.this);
	textView.setText(“Item “+position);
	textView.setBackgroundResource(R.drawable.ic_launcher);
	((ViewPager)container).addView(textView, 0);
	return textView;
}

@Override
public void destroyItem(ViewGroup container, int position, Object object) {
	((ViewPager) container).removeView((TextView)object);
}

}

When we Run the application the output looks like this.

viewpager1

We can swipe left and right to navigate through Views. But we can see only one View at a time! 

We can modify this code and make the hidden views visible all the time.

First we need to create a custom container for the ViewPager by extending FrameLayout. Let’s call it ViewPagerContainer. And call this init method in its constructor.

private void init() {
	setClipChildren(false);
	setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}

We have to use this as the container instead of the FrameLayout in the layout XML file.

<com.example.viewpagerexample.ViewPagerContainer

android:id=”@+id/container”
android:layout_width=”match_parent”
android:layout_height=”fill_parent”
android:background=”#FFFFFF”>

<android.support.v4.view.ViewPager
android:id=”@+id/viewpager”
android:layout_width=”200dip”
android:layout_height=”200dip”
android:layout_gravity=”center_horizontal|center_vertical”/>

</com.example.viewpagerexample.ViewPagerContainer>

Finally in the Activity add these lines.

ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager);
viewPager.setAdapter(new ViewAdapter());
viewPager.setOffscreenPageLimit(5);
viewPager.setPageMargin(15);
viewPager.setClipChildren(false);

Now when we run the application it should look like this. It will not clip the child views now.

viewpager2

But there’s a problem here. We can swipe only the middle view. This is because the touch events occur outside the ViewPagers bounds. We can override the onTouchEvent of the ViewPagerContainer and dispatch the events to the ViewPager to solve this.

private ViewPager mPager;

@Override
protected void onFinishInflate() {
	mPager = (ViewPager) getChildAt(0);
}

@Override
public boolean onTouchEvent(MotionEvent ev) {
	return mPager.dispatchTouchEvent(ev);
}