ViewPager with previous and next page boundaries

103,925

Solution 1

Quoting myself from a blog post on this subject:

The third approach comes from Dave Smith, co-author of the well-regarded book Android Recipes. He went in a very different direction, using a custom container that disabled children clipping to show more than one page at a time.

His published sample code shows the whole thing in action. His container (com.example.pagercontainer.PagerContainer) wraps the ViewPager and calls setClipChildren(false); on itself, so even though the ViewPager is focused on one selected page, other pages that have coordinates beyond the ViewPager bounds are still visible, so long as they fit within the PagerContainer. By sizing the ViewPager to be smaller than the PagerContainer, the ViewPager can size its pages to that size, leaving room for other pages to be seen. PagerContainer, though, needs to help out a bit with touch events, as ViewPager will only handle swipe events on its own visible bounds, ignoring any pages visible to the sides.

enter image description here

Solution 2

I have a similar solution:

On the viewpager set left and right padding, e.g. 20dp. Do also set the page margin on the viewpager, e.g. half of the pager padding. And do not forget to disable clip padding.

tilePager.setPadding(defaultGap, 0, defaultGap, 0);
tilePager.setClipToPadding(false);
tilePager.setPageMargin(halfGap);

Solution 3

  1. Set left and right padding for whole item view. Example xml (page_item.xml):

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:paddingLeft="20dp"
    android:paddingRight="20dp"/>
    
    <TextView
        android:id="@+id/text1"
        android:text="Large Text"
        android:textAppearance="?android:attr/textAppearanceLarge" />
    
    </LinearLayout>
    
  2. Then set negative page margin for PageView equal to 2*(previous view padding)

    int margin = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 20*2,     getResources().getDisplayMetrics());
    mViewPager.setPageMargin(-margin);
    
  3. Optional. Set zero left padding for first item and zero right padding to last item to hide empty edges. You may do this in the PageAdapter or Page fragment class.

Solution 4

To show preview of left and right pages set the following two values

viewpager.setClipToPadding(false)
viewpager.setPadding(left,0,right,0)

If you need space between two pages in the viewpager then add viewpager.setPageMargin(int)

Android ViewPager - Show preview of page on left and right

Solution 5

if someone still looking for solution, I had customized the ViewPage to achieve it without using negative margin, find a sample project here https://github.com/44kksharma/Android-ViewPager-Carousel-UI it should work in most cases but you can still define page margin with mPager.setPageMargin(margin in pixel);

Share:
103,925

Related videos on Youtube

Gaurav Arora
Author by

Gaurav Arora

Speaks Android &amp; React Native. LinkedIn: https://www.linkedin.com/in/gauravsapiens Medium: https://medium.com/@gauravsapiens

Updated on July 08, 2022

Comments

  • Gaurav Arora
    Gaurav Arora almost 2 years

    I'm designing a view with multiple pages. I want edges of previous and next pages to be show like below and implement a 2 finger swipe to switch between pages.

    enter image description here

    I tried using ViewPager with negative page margin as suggested here but that only shows one of the edges on the screen, not both simultaneously.

    Alternatively, is there any way i can position part of my view outside screen and then animate it giving it a ViewPager type effect.

    How should I go about it ? Thanks !

    • logray
      logray over 11 years
      "only shows one of the edges on the screen, not both simultaneously." Are you on page 0 and you only see part of page 1? Perhaps you need to use a circular pager, example and then set your page always to the "middle" position. See this post and the comment : stackoverflow.com/a/8304474/1851478
  • Shruti
    Shruti about 11 years
    by using this,I am able to show part of previous and next page as shown in image above,but now I don't want to show sharp edges on images.I want them to blur towards edges..please guide me on how can i use z-index for achieving the same
  • Marckaraujo
    Marckaraujo almost 11 years
    @Sergey, I can't make this work with your solution, could you post a example? thx
  • Daniel L.
    Daniel L. over 10 years
    @Shruti - just add an overlay image with the effect you want
  • José Barbosa
    José Barbosa over 10 years
    just adding a note: with this solution when you slide from page 1 to page 2, the page 3 isn't in memory, so it will appear with a delay. to fix this just add - yourViewPager.setOffscreenPageLimit(2);
  • Yugesh
    Yugesh about 10 years
    am try this example it works perfectly in emulator but not work in Samsung real device.it overlaps the images.
  • Swayam
    Swayam about 10 years
    I do the same but it disables the over-scroll effect for the last item. Any leads on that ?
  • Swayam
    Swayam about 10 years
    I do the same but it disables the over-scroll effect for the last item. Any leads on that ?
  • CommonsWare
    CommonsWare about 10 years
    @Swayam: I actually haven't used Dave's technique much. I tend to go with the getPageWidth() solution (see option #1), which still supports overscroll.
  • Swayam
    Swayam about 10 years
    Thanks for your prompt reply sir! I am yet to try the solution out! But until now, what I have been experiencing is that as soon as give padding to the Pager, the last page doesn't have the overscroll effect. Funnily though, the first one still has overscroll. Would you have any idea?
  • CommonsWare
    CommonsWare about 10 years
    @Swayam: As I noted, I haven't used Dave's technique much, and so I have no idea how it behaves with respect to overscroll.
  • Swayam
    Swayam about 10 years
    Alright sir! I will try your solution then! Thanks much! :)
  • Swayam
    Swayam about 10 years
    @CommonsWare : Sir, I tried your solution! It worked pretty well. The overscroll is there. Only problem now is that the next card shows, but not the previous card. That is, if I am on page 2, I can see page 3 peeking out, but not page 1. Where could I have been going wrong?
  • CommonsWare
    CommonsWare about 10 years
    @Swayam: You aren't "going wrong". That is how the first technique works.
  • Swayam
    Swayam about 10 years
    So, what do I have to do to preserve the overscroll and also show both the previous and next page ?
  • CommonsWare
    CommonsWare about 10 years
    @Swayam: I have no idea.
  • Swayam
    Swayam about 10 years
    No problem sir. I will figure something from your blogpost. Thanks for all the help. :)
  • kenyee
    kenyee about 10 years
    I can't seem to get this to work either...the margins seem to display randomly if I use images w/ scale set to center crop. Anyone have a working code example they can share?
  • CoDe
    CoDe over 9 years
    @CommonsWare your solution work pretty well..is there way to make left/right side view semi transparent and then gradually start visibility as it start to come in centre. Please suggest.
  • Greg Ennis
    Greg Ennis over 9 years
    Beware that this solution calls setOnPageChangeListener(...). There can only be one page change listener for a viewpager. Therefore you need to add code to relay the listener through the container otherwise you get weird artifiacts due to redraw problems.
  • Greg Ennis
    Greg Ennis over 9 years
    This should be correct answer. I think maybe this didnt work in prior versions of viewpager but it works now.
  • Umesh Aawte
    Umesh Aawte about 9 years
    Its adding same margin on left side of first and right side of last page as well. Any fix
  • akash89
    akash89 over 8 years
    Good solution provided.
  • Nick
    Nick over 8 years
    This doesn't work for first time when using custom page transformers. After a bit of scrolling, it works. Any suggestions please?
  • Imran Ahmed
    Imran Ahmed over 8 years
    Short and more Clear answer.
  • Mr T
    Mr T almost 8 years
    Is there a way to make the next item and the preview item blurred, then when on focus remove the blur ?
  • CommonsWare
    CommonsWare almost 8 years
    @MrG: You could overlay the ViewPager with something that applies the blur on the sides. There are probably better solutions; you may want to ask a separate Stack Overflow question on this.
  • Aditya Vyas-Lakhan
    Aditya Vyas-Lakhan over 7 years
    @CommonsWare i tried that demo..but the issue is that i am not able to get my last item position.
  • HannahCarney
    HannahCarney over 7 years
    easiest and best way
  • hardik9850
    hardik9850 almost 7 years
    How to touch first and last item? By checking page index in OnPageListener?
  • silentsudo
    silentsudo almost 6 years
    This is the beast yes beast answer for consider naming values xd
  • voytez
    voytez over 5 years
    side note: this wont work with a custom view pager transformer
  • Anooj Krishnan G
    Anooj Krishnan G over 5 years
    When I try to zoom the center layout, its zooming to top and bottom. The left and right is not visible due to the padding. Please see the question stackoverflow.com/questions/52710076/…
  • Alex
    Alex over 5 years
    @voytez any solution for transformer ?
  • Chirag Joshi
    Chirag Joshi over 5 years
    This code is not working properly, its showing left side page bit bigger than right side
  • Phong Nguyen
    Phong Nguyen about 5 years
    @CommonsWare it works as expected but it remove corner radius of CardView? any help to fix this please?
  • CommonsWare
    CommonsWare about 5 years
    @ThinkTwiceCodeOnce: This question does not appear to have anything to do with CardView. You should be able to call setRadius() on a CardView to change its radius. If you have further concerns in this area, and you are not finding any existing questions that cover it, ask a fresh question.
  • Saeid Z
    Saeid Z over 3 years
    Thanks. How to increase space between pages?
  • 44kksharma
    44kksharma over 3 years
    mPager.setPageMargin(marging in pixels);
  • oziomajnr
    oziomajnr almost 3 years
    How can we make the off screen items respond to click events.
  • CommonsWare
    CommonsWare almost 3 years
    @oziomajnr: You would do it the same way as you would anything else in a ViewPager: add click listeners to the widgets. However, for items that are fully off-screen, the user has no visible pixels of those widgets to click.
  • oziomajnr
    oziomajnr almost 3 years
    I have tried setting on click listeners to the off screen elements but because they are drawn outside the parent, they do not respond to click events.
  • CommonsWare
    CommonsWare almost 3 years
    @oziomajnr: You might try switching to ViewPager2, as ViewPager itself largely is deprecated. Beyond that, consider asking a separate Stack Overflow question with a minimal reproducible example demonstrating what you are trying and explaining in detail what you are seeing.