Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package one.xcorp.widget
- import android.animation.ValueAnimator
- import android.content.Context
- import android.util.AttributeSet
- import android.view.View
- import android.view.ViewGroup.LayoutParams.MATCH_PARENT
- import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
- import one.xcorp.widget.R
- import kotlin.properties.Delegates.observable
- class ViewPager : android.support.v4.view.ViewPager {
- var enableAnimation by observable(false) { _, _, enable ->
- if (enable) {
- addOnPageChangeListener(onPageChangeListener)
- } else {
- removeOnPageChangeListener(onPageChangeListener)
- }
- }
- private var animationDuration = 0L
- private var animator: ValueAnimator? = null
- constructor (context: Context) : super(context) {
- init(context, null)
- }
- constructor (context: Context, attrs: AttributeSet?) : super(context, attrs) {
- init(context, attrs)
- }
- private fun init(context: Context, attrs: AttributeSet?) {
- context.theme.obtainStyledAttributes(
- attrs,
- R.styleable.ViewPager,
- 0,
- 0
- ).apply {
- try {
- enableAnimation = getBoolean(
- R.styleable.ViewPager_enableAnimation,
- enableAnimation
- )
- animationDuration = getInteger(
- R.styleable.ViewPager_animationDuration,
- resources.getInteger(android.R.integer.config_shortAnimTime)
- ).toLong()
- } finally {
- recycle()
- }
- }
- }
- override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
- val heightMode = MeasureSpec.getMode(heightMeasureSpec)
- val measuredHeight = if (heightMode == MeasureSpec.EXACTLY) {
- MeasureSpec.getSize(heightMeasureSpec)
- } else {
- val currentViewHeight = findViewByPosition(currentItem)?.also {
- measureView(it)
- }?.measuredHeight ?: 0
- if (heightMode != MeasureSpec.AT_MOST) {
- currentViewHeight
- } else {
- Math.min(
- currentViewHeight,
- MeasureSpec.getSize(heightMeasureSpec)
- )
- }
- }
- super.onMeasure(
- widthMeasureSpec,
- MeasureSpec.makeMeasureSpec(measuredHeight, MeasureSpec.EXACTLY)
- )
- }
- private fun measureView(view: View) = with(view) {
- val horizontalMode: Int
- val horizontalSize: Int
- when (layoutParams.width) {
- MATCH_PARENT -> {
- horizontalMode = MeasureSpec.EXACTLY
- horizontalSize = this@ViewPager.measuredWidth
- }
- WRAP_CONTENT -> {
- horizontalMode = MeasureSpec.UNSPECIFIED
- horizontalSize = 0
- }
- else -> {
- horizontalMode = MeasureSpec.EXACTLY
- horizontalSize = layoutParams.width
- }
- }
- val verticalMode: Int
- val verticalSize: Int
- when (layoutParams.height) {
- MATCH_PARENT -> {
- verticalMode = MeasureSpec.EXACTLY
- verticalSize = this@ViewPager.measuredHeight
- }
- WRAP_CONTENT -> {
- verticalMode = MeasureSpec.UNSPECIFIED
- verticalSize = 0
- }
- else -> {
- verticalMode = MeasureSpec.EXACTLY
- verticalSize = layoutParams.height
- }
- }
- val horizontalMeasureSpec = MeasureSpec.makeMeasureSpec(horizontalSize, horizontalMode)
- val verticalMeasureSpec = MeasureSpec.makeMeasureSpec(verticalSize, verticalMode)
- measure(horizontalMeasureSpec, verticalMeasureSpec)
- }
- private fun findViewByPosition(position: Int): View? {
- for (i in 0 until childCount) {
- val childView = getChildAt(i)
- val childLayoutParams = childView.layoutParams as LayoutParams
- val childPosition by lazy {
- val field = childLayoutParams.javaClass.getDeclaredField("position")
- field.isAccessible = true
- field.get(childLayoutParams) as Int
- }
- if (!childLayoutParams.isDecor && position == childPosition) {
- return childView
- }
- }
- return null
- }
- private fun animateContentHeight(childView: View, fromHeight: Int, toHeight: Int) {
- animator?.cancel()
- if (fromHeight == toHeight) {
- return
- }
- animator = ValueAnimator.ofInt(fromHeight, toHeight).apply {
- addUpdateListener {
- measureView(childView)
- if (childView.measuredHeight != toHeight) {
- animateContentHeight(childView, height, childView.measuredHeight)
- } else {
- layoutParams.height = animatedValue as Int
- requestLayout()
- }
- }
- duration = animationDuration
- start()
- }
- }
- private val onPageChangeListener = object : OnPageChangeListener {
- override fun onPageScrollStateChanged(state: Int) {
- /* do nothing */
- }
- override fun onPageScrolled(
- position: Int,
- positionOffset: Float,
- positionOffsetPixels: Int
- ) {
- /* do nothing */
- }
- override fun onPageSelected(position: Int) {
- if (!isAttachedToWindow) {
- return
- }
- findViewByPosition(position)?.let { childView ->
- measureView(childView)
- animateContentHeight(childView, height, childView.measuredHeight)
- }
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement