Skip to content

Instantly share code, notes, and snippets.

@mrmitew
Created September 5, 2018 14:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mrmitew/d579251997c4c258a4e87e000524f35c to your computer and use it in GitHub Desktop.
Save mrmitew/d579251997c4c258a4e87e000524f35c to your computer and use it in GitHub Desktop.
Helper class for automatically scrolling pages of a [ViewPager] which does not allow you to customize the speed at which it changes page when directly setting the current page.
/*
* Copyright 2018 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Helper class for automatically scrolling pages of a [ViewPager] which does not allow you to
* customize the speed at which it changes page when directly setting the current page.
*/
class ViewPagerPager(private val viewPager: ViewPager) {
private val fastOutSlowIn =
AnimationUtils.loadInterpolator(viewPager.context, android.R.interpolator.fast_out_slow_in)
fun advance() {
if (viewPager.width <= 0) return
val current = viewPager.currentItem
val next = ((current + 1) % requireNotNull(viewPager.adapter).count)
val pages = next - current
val dragDistance = pages * viewPager.width
ValueAnimator.ofInt(0, dragDistance).apply {
var dragProgress = 0
var draggedPages = 0
addListener(
onStart = { viewPager.beginFakeDrag() },
onEnd = { viewPager.endFakeDrag() }
)
addUpdateListener {
if (!viewPager.isFakeDragging) {
// Sometimes onAnimationUpdate is called with initial value before
// onAnimationStart is called.
return@addUpdateListener
}
val dragPoint = (animatedValue as Int)
val dragBy = dragPoint - dragProgress
viewPager.fakeDragBy(-dragBy.toFloat())
dragProgress = dragPoint
// Fake dragging doesn't let you drag more than one page width. If we want to do
// this then need to end and start a new fake drag.
val draggedPagesProgress = dragProgress / viewPager.width
if (draggedPagesProgress != draggedPages) {
viewPager.endFakeDrag()
viewPager.beginFakeDrag()
draggedPages = draggedPagesProgress
}
}
duration = if (pages == 1) PAGE_CHANGE_DURATION else MULTI_PAGE_CHANGE_DURATION
interpolator = fastOutSlowIn
}.start()
}
companion object {
private const val PAGE_CHANGE_DURATION = 400L
private const val MULTI_PAGE_CHANGE_DURATION = 600L
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment