プログラムでスライドするときにViewPager2のスクロール速度を変更する 質問する

プログラムでスライドするときにViewPager2のスクロール速度を変更する 質問する

ViewPagerプログラムスライドのアニメーション期間を変更する方法があることは知っています(ここ)。

しかし、それは機能していないViewPager2

私はこれを試しました:

try {
        final Field scrollerField = ViewPager2.class.getDeclaredField("mScroller");
        scrollerField.setAccessible(true);
        final ResizeViewPagerScroller scroller = new ResizeViewPagerScroller(getContext());
        scrollerField.set(mViewPager, scroller);
    } catch (Exception e) {
        e.printStackTrace();
    }

IDE は「mScroller」に関して警告を表示します:

フィールド 'mScroller' を解決できません

このコードを実行すると、動作せず、以下のエラーが発生します。

No field mScroller in class Landroidx/viewpager2/widget/ViewPager2; (declaration of 'androidx.viewpager2.widget.ViewPager2' appears in /data/app/{packagename}-RWJhF9Gydojax8zFyFwFXg==/base.apk)

では、この機能をどのように実現できるのでしょうか?

ベストアンサー1

に基づくこの問題のチケットAndroid チームは ViewPager2 でこのような動作をサポートする予定はありませんが、チケットからのアドバイスは を使用することですViewPager2.fakeDragBy()。この方法の欠点は、ページ幅をピクセル単位で指定する必要があることです。ただし、ページ幅が ViewPager の幅と同じ場合は、代わりにその値を使用できます。

実装例はこちら

fun ViewPager2.setCurrentItem(
    item: Int,
    duration: Long,
    interpolator: TimeInterpolator = AccelerateDecelerateInterpolator(),
    pagePxWidth: Int = width // Default value taken from getWidth() from ViewPager2 view
) {
    val pxToDrag: Int = pagePxWidth * (item - currentItem)
    val animator = ValueAnimator.ofInt(0, pxToDrag)
    var previousValue = 0
    animator.addUpdateListener { valueAnimator ->
        val currentValue = valueAnimator.animatedValue as Int
        val currentPxToDrag = (currentValue - previousValue).toFloat()
        fakeDragBy(-currentPxToDrag)
        previousValue = currentValue
    }
    animator.addListener(object : Animator.AnimatorListener {
        override fun onAnimationStart(animation: Animator?) { beginFakeDrag() }
        override fun onAnimationEnd(animation: Animator?) { endFakeDrag() }
        override fun onAnimationCancel(animation: Animator?) { /* Ignored */ }
        override fun onAnimationRepeat(animation: Animator?) { /* Ignored */ }
    })
    animator.interpolator = interpolator
    animator.duration = duration
    animator.start()
}

サポートするにはRTL、 に提供される値を反転する必要があります。そのため、上記の例では、 を使用するときViewPager2.fakeDragBy()に の代わりにfakeDragBy(-currentPxToDrag)を使用します。fakeDragBy(currentPxToDrag)RTL

これを使用する際に留意すべき点がいくつかあります。公式ドキュメント:

  • 負の値は前方にスクロールし、正の値は後方にスクロールします(RTL で反転)。

  • 通話前と通話終了後にfakeDragBy()使用してくださいbeginFakeDrag()endFakeDrag()

  • onPageScrollStateChangedこのAPIはから簡単に使用でき、メソッドViewPager2.OnPageChangeCallbackのおかげでプログラムによるドラッグとユーザーによるドラッグを区別できます。isFakeDragging()
  • 上記のサンプル実装では、指定された項目が正しいかどうかのセキュリティ チェックは行われません。また、UI のライフサイクルにキャンセル機能を追加することも検討してください。これは、RxJava で簡単に実現できます。

おすすめ記事