web-dev-qa-db-ja.com

異なるアイテムの高さとwrap_contentを持つViewPager2

ViewPager自身を延ばすためにonMeasureを変更するために概要されるさまざまな高さ項目で動作するようにviewPagerを取得するにはいくつかの投稿があります。

しかし、それを与えて ViewPager2最終クラスとしてマークされ、それができることはそれほど伸びていません。

誰かがこれを作る方法があるかどうかを知っていますか?


例えば。 2つのビューがあるとしましょう。

View1 = 200dp.

View2 = 300dp.

ViewPager2(layout_height="wrap_content")負荷 - View1を見て、その高さは200dpになります。

しかし、私がView2にスクロールすると、高さはまだ200dpです。 View2の最後の100dpが遮断されます。

12
Mephoros

この解決策は、PageChangeCallbackを登録し、子に再度再測定するように求められた後、_ViewPager2LayoutParamsを調整することです。

_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 }
            }
        }
    }
}
_

あるいは、あなたの見方の高さがe.のためにある時点で変わることがある場合非同期データのロード、代わりにグローバルレイアウトリスナーを使用します。

_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

4
Mephoros

私のためにこれは完全に働いた:


    viewPager2.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
            override fun onPageScrolled(
                position: Int,
                positionOffset: Float,
                positionOffsetPixels: Int
            ) {
                super.onPageScrolled(position,positionOffset,positionOffsetPixels)
                if (position>0 && positionOffset==0.0f && positionOffsetPixels==0){
                    viewPager2.layoutParams.height =
                        viewPager2.getChildAt(0).height
                }
            }
        })
 _
2
Bikash Das

マイケースでは、adapter.notifyDataSetChanged()onPageSelectedに追加しました。

1
Almir Burnashev

この場合、この場合は断片でつまずいた。承認された答えとしてビューをサイズ変更する代わりに、私は制約の範囲内でビューを折り返すことにしました。これには、ViewPager2のサイズを指定し、wrap_contentを使用しないことが必要です。

したがって、ViewPagerのサイズを変更する代わりに、それが処理する最大のビューの最小サイズである必要があります。

Androidの少し新しいので、これが良い解決策であるかどうかわからないが、それは私のための仕事をします。

言い換えると:

_<androidx.constraintlayout.widget.ConstraintLayout
  xmlns:Android="http://schemas.Android.com/apk/res/Android"
  xmlns:app="http://schemas.Android.com/apk/res-auto"
  xmlns:tools="http://schemas.Android.com/tools"
  Android:layout_width="match_parent"
  Android:layout_height="match_parent"
  >
    <!-- Adding transparency above your view due to wrap_content -->
    <androidx.constraintlayout.widget.ConstraintLayout
      Android:layout_width="match_parent"
      Android:layout_height="wrap_content"
      app:layout_constraintBottom_toBottomOf="parent"
      app:layout_constraintStart_toStartOf="parent"
      app:layout_constraintEnd_toEndOf="parent"
      >

      <!-- Your view here -->

    </androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
_
0
Miniskurken