Android ViewPager - Show preview of page on left and right

后端 未结 10 2602
旧巷少年郎
旧巷少年郎 2020-12-02 03:52

I\'m using Android\'s ViewPager. What I want to do is to show a preview of the page on both the left and the right. I\'ve seen where I can use a negative

10条回答
  •  醉酒成梦
    2020-12-02 04:34

    Solution with the new ViewPager2

    Nowadays you should consider using ViewPager2 which "replaces ViewPager, addressing most of its predecessor’s pain-points":

    • Based on RecyclerView
    • RTL (right-to-left) layout support
    • Vertical orientation support
    • Reliable Fragment support (including handling changes to the underlying Fragment collection)
    • Dataset change animations (including DiffUtil support)

    The result

    The code

    In your Activity/Fragment, setup the ViewPager2:

    // MyRecyclerViewAdapter is an standard RecyclerView.Adapter :)
    viewPager2.adapter = MyRecyclerViewAdapter() 
    
    // You need to retain one page on each side so that the next and previous items are visible
    viewPager2.offscreenPageLimit = 1
    
    // Add a PageTransformer that translates the next and previous items horizontally
    // towards the center of the screen, which makes them visible
    val nextItemVisiblePx = resources.getDimension(R.dimen.viewpager_next_item_visible)
    val currentItemHorizontalMarginPx = resources.getDimension(R.dimen.viewpager_current_item_horizontal_margin)
    val pageTranslationX = nextItemVisiblePx + currentItemHorizontalMarginPx
    val pageTransformer = ViewPager2.PageTransformer { page: View, position: Float ->
        page.translationX = -pageTranslationX * position
        // Next line scales the item's height. You can remove it if you don't want this effect
        page.scaleY = 1 - (0.25f * abs(position))
        // If you want a fading effect uncomment the next line:
        // page.alpha = 0.25f + (1 - abs(position))
    }
    viewPager2.setPageTransformer(pageTransformer)
    
    // The ItemDecoration gives the current (centered) item horizontal margin so that
    // it doesn't occupy the whole screen width. Without it the items overlap
    val itemDecoration = HorizontalMarginItemDecoration(
        context,
        R.dimen.viewpager_current_item_horizontal_margin
    )
    viewPager2.addItemDecoration(itemDecoration)
    

    Add the HorizontalMarginItemDecoration, which is a trivial ItemDecoration:

    /**
     * Adds margin to the left and right sides of the RecyclerView item.
     * Adapted from https://stackoverflow.com/a/27664023/4034572
     * @param horizontalMarginInDp the margin resource, in dp.
     */
    class HorizontalMarginItemDecoration(context: Context, @DimenRes horizontalMarginInDp: Int) :
        RecyclerView.ItemDecoration() {
    
        private val horizontalMarginInPx: Int =
            context.resources.getDimension(horizontalMarginInDp).toInt()
    
        override fun getItemOffsets(
            outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State
        ) {
            outRect.right = horizontalMarginInPx
            outRect.left = horizontalMarginInPx
        }
    
    }
    

    Add the dimensions that control how much of the previous/next item is visible, and current item horizontal margin:

    26dp
    42dp
    

    Finally add the ViewPager2 to your layout:

    
    

    One important thing: a ViewPager2 item must have layout_height="match_parent" (otherwise it throws an IllegalStateException), so you should do something like:

    
    
        
    
            
    
        
    
    
    

    PageTransformer examples

    Google has added a guide on ViewPager2 that has 2 PageTransformer implementations that you can use as an inspiration: https://developer.android.com/training/animation/screen-slide-2

    About the new ViewPager2

    • Announcement at Google I/O 2019
    • Documentation
    • Release notes
    • Code sample
    • Migrate from ViewPager to ViewPager2

提交回复
热议问题