55

Is there a possibility to display two pages at the same time, when using a ViewPager? I'm not looking for an edge effect, but rather for two full pages at the same time.

Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
Kirill Rakhman
  • 42,195
  • 18
  • 124
  • 148

8 Answers8

69

Please have a look at the getPageWidth Method in the corresponding PagerAdapter. Override it and return e.g. 0.8f to have all child pages span only 80% of the ViewPager's width.

More info: http://developer.android.com/reference/android/support/v4/view/PagerAdapter.html#getPageWidth(int)

Markus Wörz
  • 736
  • 5
  • 4
  • the problem with that technique, is that an extra margin-bottom appears, adding weird blank space below the Viewpager – elgui Oct 22 '13 at 12:38
  • This adds some flickering effect on view pager, I can still swipe and can see views make weird flickering. – Piyush Agarwal Nov 02 '17 at 18:46
36

See my more up-to-date answer here: Can ViewPager have multiple views in per page?

I discovered that a perhaps even simpler solution through specifying a negative margin for the ViewPager. I've created the MultiViewPager project on GitHub, which you may want to take a look at:

https://github.com/Pixplicity/MultiViewPager

Although this question specifically asks for a solution without edge effect, some answers here propose the workaround by CommonsWare, such as the suggestion by kaw.

There are various problems with touch handling and hardware acceleration with that particular solution. A simpler and more elegant solution, in my opinion, is to specify a negative margin for the ViewPager:

ViewPager.setPageMargin(
    getResources().getDimensionPixelOffset(R.dimen.viewpager_margin));

I then specified this dimension in my dimens.xml:

<dimen name="viewpager_margin">-64dp</dimen>

To compensate for overlapping pages, each page's content view has the opposite margin:

android:layout_marginLeft="@dimen/viewpager_margin_fix"
android:layout_marginRight="@dimen/viewpager_margin_fix"

Again in dimens.xml:

<dimen name="viewpager_margin_fix">32dp</dimen>

(Note that the viewpager_margin_fix dimension is half that of the absolute viewpager_margin dimension.)

We implemented this in the Dutch newspaper app De Telegraaf Krant:

Phone example in De Telegraaf KrantTablet example

Community
  • 1
  • 1
Paul Lammertsma
  • 37,593
  • 16
  • 136
  • 187
  • 1
    I loved your solution. Simple and elegant... ! Thanks man. I was trying to achieve this using `PageTransformer`. – M-Wajeeh Feb 25 '14 at 08:38
  • 3
    worked for me. You also need to add setOffScreenPageLimit(2) to improve the caching to 2 to avoid lagging on the second next view. – Giorgio May 11 '14 at 14:52
  • 1
    In previous note: That's ViewPager.setOffscreenPageLimit(2) in case anyone gets thrown off. – fooser Jul 09 '14 at 18:44
13

You have to override the getPageWidth() method on the viewpager's Adapter. For Example:

@Override
public float getPageWidth(int position) {
    return 0.9f;
}

Try that code in your Adapter and then you'll understand.

bummi
  • 27,123
  • 14
  • 62
  • 101
flagg327
  • 967
  • 1
  • 10
  • 21
5

See that blog entry.
PagerContainer technique is solved my problem.

EDIT:
I found same answer.
How to migrate from Gallery to HorizontalScrollView & ViewPager?

Community
  • 1
  • 1
kaw
  • 51
  • 1
  • 5
3

You can solve this problem by using getPageWidth in PagerAdapter class.

Be sure about whether your JAR is up-to-date.Since previously ViewPager was not supporting multiple pages at the same time.

public float getPageWidth(){

return 0.4f;(You can choose it .For full screen per page you should give 1f) }

Sevil
  • 31
  • 6
3

create your layout file: my_layout.xml:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<FrameLayout
    android:id="@+id/pager_container"
    android:layout_width="match_parent"
    android:layout_height="240dp"
    android:clipChildren="false">

    <android.support.v4.view.ViewPager
        android:id="@+id/pager"
        android:layout_width="200dp"
        android:clipToPadding="false"
        android:layout_height="200dp"
        android:layout_marginLeft="70dp"
        android:layout_marginRight="70dp"
        android:layout_gravity="center" />
</FrameLayout>
</layout>

the viewpager is about as small as you want your pages to be. With android:clipToPadding="false" the pages outside the pager are visible as well. But now dragging outside the viewpager has no effect This can be remedied by picking touches from the pager-container and passing them on to the pager:

MyLayoutBinding binding = DataBindingUtil.<MyLayoutBinding>inflate(layoutInflater, R.layout.my_layout, parent, false)
binding.pager.setOffscreenPageLimit(3);
binding.pager.setPageMargin(15);
binding.pagerContainer.setOnTouchListener(new View.OnTouchListener() {
      @Override
      public boolean onTouch(View v, MotionEvent event) {
           return chatCollectionLayoutBinding.pager.onTouchEvent(event);
      }
 });
Hans
  • 1,886
  • 24
  • 18
-2

It can be don in the Item Layout of the Viewpager. Assume that, you want two pages at a time.

This is the Item Layout (photo_slider_item.xml):

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" style="@style/photosSliderItem">
        <ImageView android:id="@id/photoBox1" style="@style/photoBox"/>
        <ImageView android:id="@id/photoBox2" style="@style/photoBox"/>
    </LinearLayout>

And in your PagerAdapter:

@Override
public View instantiateItem(ViewGroup container, int position){
    View sliderItem = LayoutInflater.from(container.getContext()).inflate(photo_slider_item, container, false);
    ImageView photoBox1 = (ImageView) sliderItem.findViewById(R.id.photoBox1);
    ImageView photoBox2 = (ImageView) sliderItem.findViewById(R.id.photoBox2);
    photoBox1.setImageResource(photosIds[position]);
    if(position < photosIds.length-1){
        photoBox2.setImageResource(photosIds[position+1]);
    } else {photoBox2.setImageResource(photosIds[0]);}
    container.addView(sliderItem);
    return sliderItem;
}

Edited version for more than two items

if you want more than two items, first add your items to the LinearLayout then use following algorithm:

photoBox1.setImageResource(photosIds[position]);
if(position < photosIds.length-i-1){
   photoBox2.setImageResource(photosIds[position+1]);
   photoBox3.setImageResource(photosIds[position+2]);
   .
   .
   .
   photoBox(i).setImageResource(photosIds[position+i-1]);
} else if(position < photosIds.length-i-2){
   photoBox2.setImageResource(photosIds[position+1]);
   photoBox3.setImageResource(photosIds[position+2]);
   .
   .
   .
   photoBox(i-1).setImageResource(photosIds[position+i-2]);
   photoBox(i).setImageResource(photosIds[0]);
} . . . else if(position < photosIds.length-1){
   photoBox2.setImageResource(photosIds[position+1]);
   photoBox3.setImageResource(photosIds[0]);
   photoBox4.setImageResource(photosIds[1]);
   .
   .
   .
   photoBox(i-1).setImageResource(photosIds[i-2-2]);
   photoBox(i).setImageResource(photosIds[i-2-1]);
} else {
    photoBox2.setImageResource(photosIds[0]);
    photoBox3.setImageResource(photosIds[1]);
    .
    .
    .
    photoBox(i-1).setImageResource(photosIds[i-1-2]);
    photoBox(i).setImageResource(photosIds[i-1-1]);
}

i : number of your items

[i-2-2] : number 2 in the middle is number of items in the last page of the viewpager.

Arash
  • 696
  • 8
  • 24
-2

I don't think that's possible with the limitations of a View Pager. It only allows a user to view pages 1 at a time. You might be able to work something out with the use of fragments, and have 2 ViewPager fragments side by side and use buttons to work out the page flipping you want to implement, but the code may become very complex.

You can try something like a ViewFlipper - where you can do a lot more customizations (including animations).

Hope this helps.

aimango
  • 1,567
  • 2
  • 15
  • 29