简体   繁体   English

Android ViewPager2 setPageMargin 未解决

[英]Android ViewPager2 setPageMargin unresolved

I want to implement Carousel using View Pager2 with preview of left and right page like this:我想使用View Pager2实现 Carousel 和左右页面的预览,如下所示:

在此处输入图片说明

Initially I was using view pager1 which supported.最初我使用的是支持的视图 pager1。 Now I think it's removed现在我认为它被删除了

    viewPagerhost.setPageMargin(20);

Any idea how we can achieve this using View Pager 2知道我们如何使用 View Pager 2 实现这一点

MarginPageTransformer cannot help your need. MarginPageTransformer无法满足您的需求。

You must use custom setPageTrarnsformer .您必须使用自定义setPageTrarnsformer


Step 1第1步

Here is my Extension Method for this.这是我的扩展方法。

you can check detail in this article Medium article您可以在这篇文章查看详细信息中文章

fun ViewPager2.setShowSideItems(pageMarginPx : Int, offsetPx : Int) {

    clipToPadding = false
    clipChildren = false
    offscreenPageLimit = 3

    setPageTransformer { page, position ->

        val offset = position * -(2 * offsetPx + pageMarginPx)
        if (this.orientation == ViewPager2.ORIENTATION_HORIZONTAL) {
            if (ViewCompat.getLayoutDirection(this) == ViewCompat.LAYOUT_DIRECTION_RTL) {
                page.translationX = -offset
            } else {
                page.translationX = offset
            }
        } else {
            page.translationY = offset
        }
    }

}

Step 2第2步

set pageMarginPx and offsetPx with your use case.根据您的用例设置 pageMarginPx 和 offsetPx。

<resources>
    <dimen name="pageMargin">20dp</dimen>
    <dimen name="pagerOffset">30dp</dimen>
    <dimen name="pageMarginAndoffset">50dp</dimen>
</resources>

Step 3第 3 步

set your side margin of layout item in your xml.在 xml 中设置布局项的侧边距。

like this像这样

    <androidx.cardview.widget.CardView
            app:cardCornerRadius="12dp"

            android:layout_marginTop="16dp"
            android:layout_marginBottom="16dp"

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

            android:layout_width="match_parent"
            android:layout_height="match_parent">

Now we need to use setPageTransformer() in Version 1.0.0-alpha05现在我们需要在Version 1.0.0-alpha05使用setPageTransformer()

New features新功能

  • ItemDecorator introduced with a behaviour consistent with RecyclerView. ItemDecorator引入了与 RecyclerView 一致的行为。
  • MarginPageTransformer introduced to provide an ability to create space between pages (outside of page inset).引入MarginPageTransformer以提供在页面之间(页面插图之外)创建空间的能力。
  • CompositePageTransformer introduced to provide an ability to combine multiple PageTransformers.引入CompositePageTransformer以提供组合多个 PageTransformer 的能力。

SAMPLE CODE示例代码

myViewPager2.setPageTransformer(new MarginPageTransformer(1500));

Check out my previous answer if you want to implement Carousel using View Pager2如果您想使用 View Pager2 实现 Carousel,请查看我之前的回答

ViewPager2 doesn't have the method setPageMargin as of now (version 1.0.0). ViewPager2目前(版本1.0.0), ViewPager2还没有方法setPageMargin However you can create the carousel you want with a RecyclerView.ItemDecoration and a PageTransformer . 但是,您可以使用RecyclerView.ItemDecorationPageTransformer创建所需的轮播。

The result 结果

在此处输入图片说明

The code 代码

In your Activity/Fragment, setup the ViewPager2: 在您的活动/片段中,设置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 : 添加HorizontalMarginItemDecoration ,这是一个琐碎的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: 添加尺寸以控制可见的上一个/下一个项目以及当前项目的水平边距:

<dimen name="viewpager_next_item_visible">26dp</dimen>
<dimen name="viewpager_current_item_horizontal_margin">42dp</dimen>

在此处输入图片说明

ItemDecoration vs adding margins to the item's layout ItemDecoration与在项目布局中增加边距

If you look at other answers, you'll see that you can achieve the same result without the ItemDecoration , simply by adding left and right margins directly to your item's layout: 如果您查看其他答案,您会发现无需ItemDecoration就可以达到相同的结果,只需将左右边距直接添加到项目的布局即可:

<androidx.cardview.widget.CardView
    android:layout_marginLeft="@dimen/pageMarginAndOffset"
    android:layout_marginRight="@dimen/pageMarginAndOffset">

While the result is the same, using an ItemDecoration allows you to re-use the same layout in other places without having to deal with this margins that are needed only when using this layout on a ViewPager. 虽然结果相同,但使用ItemDecoration可以使您在其他地方重用相同的布局,而不必处理仅在ViewPager上使用此布局时所需的页边距。

PageTransformer examples PageTransformer示例

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 谷歌增加了对ViewPager2一个指南,有2个PageTransformer实现,你可以作为一个启发使用: https://developer.android.com/training/animation/screen-slide-2

ViewPager2 useful links ViewPager2有用的链接

I used MJ Studio's approach to create my custom PageTransformer that also changes the page margin as follows:我使用MJ Studio 的方法来创建我的自定义PageTransformer ,它也会按如下方式更改页边距:

class OffsetPageTransformer(
    @Px private val offsetPx: Int,
    @Px private val pageMarginPx: Int
) : ViewPager2.PageTransformer {

    override fun transformPage(page: View, position: Float) {
        val viewPager = requireViewPager(page)
        val offset = position * -(2 * offsetPx + pageMarginPx)
        val totalMargin = offsetPx + pageMarginPx

        if (viewPager.orientation == ViewPager2.ORIENTATION_HORIZONTAL) {
            page.updateLayoutParams<ViewGroup.MarginLayoutParams> {
                marginStart = totalMargin
                marginEnd = totalMargin
            }

            page.translationX = if (ViewCompat.getLayoutDirection(viewPager) == ViewCompat.LAYOUT_DIRECTION_RTL) {
                -offset
            } else {
                offset
            }
        } else {
            page.updateLayoutParams<ViewGroup.MarginLayoutParams> {
                topMargin = totalMargin
                bottomMargin = totalMargin
            }

            page.translationY = offset
        }
    }

    private fun requireViewPager(page: View): ViewPager2 {
        val parent = page.parent
        val parentParent = parent.parent
        if (parent is RecyclerView && parentParent is ViewPager2) {
            return parentParent
        }
        throw IllegalStateException(
            "Expected the page view to be managed by a ViewPager2 instance."
        )
    }
}

That way you can just call:这样你就可以调用:

viewPager.setPageTransformer(OffsetPageTransformer(offsetPx, pageMarginPx))

you can use this code你可以使用这个代码

   viewPager.setPageTransformer(new MarginPageTransformer(margin as PX));

but if you want to use DP you can use the below function for convert PX to DP但是如果你想使用 DP 你可以使用下面的函数将 PX 转换为 DP

 private  int pxToDp(int px) {
    return (int) (px / Resources.getSystem().getDisplayMetrics().density);
}

MarginPageTransformer helps to define spaces between pages. MarginPageTransformer有助于定义页面之间的空间。

offscreenPageLimit let you define how many pages should be rendered offscreen. offscreenPageLimit让您定义应在屏幕外呈现的页面数。

Sample of the code:代码示例:

viewPager2.offscreenPageLimit = 3
viewPager2.setPageTransformer(MarginPageTransformer({MARGIN AS PX}));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM