ViewPager2具有不同的项目高度和WRAP_CONTENT [英] ViewPager2 with differing item heights and WRAP_CONTENT

查看:775
本文介绍了ViewPager2具有不同的项目高度和WRAP_CONTENT的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

关于使ViewPager与不同高度的项目一起使用的一些文章,围绕扩展 ViewPager 本身以修改其 onMeasure 来支持这一点.

There are a few posts on getting ViewPager to work with varying height items that center around extending ViewPager itself to modify its onMeasure to support this.

但是,鉴于 ViewPager2 被标记为最终课程,所以扩展它不是我们可以做的.

However, given that ViewPager2 is marked as a final class, extending it isn't something that we can do.

有人知道是否有办法解决这个问题吗?

Does anyone know if there's a way to make this work out?

View1 = 200dp

View1 = 200dp

View2 = 300dp

View2 = 300dp

加载ViewPager2( layout_height ="wrap_content" )时-查看View1,其高度将为200dp.

When the ViewPager2 (layout_height="wrap_content") loads -- looking at View1, its height will be 200dp.

但是当我滚动到View2时,高度仍然是200dp;View2的最后100dp被切断.

But when I scroll over to View2, the height is still 200dp; the last 100dp of View2 is cut off.

推荐答案

解决方案是注册一个 PageChangeCallback 并调整 ViewPager2的 LayoutParams 要求孩子重新测量自己之后.

The solution is to register a PageChangeCallback and adjust the LayoutParams of the ViewPager2 after asking the child to re-measure itself.

pager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
    override fun onPageSelected(position: Int) {
        super.onPageSelected(position)
        val view = // ... get the view
        view.post {
            val wMeasureSpec = MeasureSpec.makeMeasureSpec(view.width, MeasureSpec.EXACTLY)
            val hMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)
            view.measure(wMeasureSpec, hMeasureSpec)

            if (pager.layoutParams.height != view.measuredHeight) {
                // ParentViewGroup is, for example, LinearLayout
                // ... or whatever the parent of the ViewPager2 is
                pager.layoutParams = (pager.layoutParams as ParentViewGroup.LayoutParams)
                    .also { lp -> lp.height = view.measuredHeight }
            }
        }
    }
})

或者,如果您的视图的高度可能由于某些原因而在某些时候发生变化异步数据加载,然后改为使用全局布局侦听器:

Alternatively, if your view's height can change at some point due to e.g. asynchronous data load, then use a global layout listener instead:

pager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
    private val listener = ViewTreeObserver.OnGlobalLayoutListener {
        val view = // ... get the view
        updatePagerHeightForChild(view)
    }

    override fun onPageSelected(position: Int) {
        super.onPageSelected(position)
        val view = // ... get the view
        // ... IMPORTANT: remove the global layout listener from other views
        otherViews.forEach { it.viewTreeObserver.removeOnGlobalLayoutListener(layoutListener) }
        view.viewTreeObserver.addOnGlobalLayoutListener(layoutListener)
    }

    private fun updatePagerHeightForChild(view: View) {
        view.post {
            val wMeasureSpec = MeasureSpec.makeMeasureSpec(view.width, MeasureSpec.EXACTLY)
            val hMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)
            view.measure(wMeasureSpec, hMeasureSpec)

            if (pager.layoutParams.height != view.measuredHeight) {
                // ParentViewGroup is, for example, LinearLayout
                // ... or whatever the parent of the ViewPager2 is
                pager.layoutParams = (pager.layoutParams as ParentViewGroup.LayoutParams)
                    .also { lp -> lp.height = view.measuredHeight }
            }
        }
    }
}

查看此处的讨论:

https://issuetracker.google.com/u/0/issues/143095219

这篇关于ViewPager2具有不同的项目高度和WRAP_CONTENT的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆