ViewPager2
package com.autoviewpager.v2
import android.content.Context
import android.util.AttributeSet
import android.util.Log
import android.view.View
import android.widget.FrameLayout
import androidx.viewpager.widget.ViewPager
import androidx.viewpager2.adapter.FragmentStateAdapter
import androidx.viewpager2.widget.ViewPager2
import com.autoviewpager.AutoHeightPager
class AutoHeightV2Pager @JvmOverloads constructor(context: android.content.Context, attrs: android.util.AttributeSet? = null) :FrameLayout(context, attrs) {
var lastWidthMeasureSpec: Int = 0
var currentHeight: Int = 0
var lastPosition:Int = 0
var isScrolling:Boolean = false
var viewPager2: ViewPager2? = null
override fun onFinishInflate() {
super.onFinishInflate()
}
init {
initialize(context, attrs)
}
fun initialize(context: Context, attrs: AttributeSet?) {
viewPager2 = ViewPager2(context);
viewPager2?.layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)
viewPager2?.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback(){
override fun onPageSelected(position: Int) {
super.onPageSelected(position)
}
override fun onPageScrolled(
position: Int,
positionOffset: Float,
positionOffsetPixels: Int
) {
Log.e("vic_ddd","position = $position positionOffset = $positionOffset positionOffsetPixels=$positionOffsetPixels")
if (positionOffset == 0f){
isScrolling = false
requestLayout()
return
}
val srcPosition = if (position>=lastPosition) position else position+1
val destPosition = if (position>=lastPosition) position+1 else position
val srcHeight = getViewHeight(srcPosition)
val destHeight = getViewHeight(destPosition)
Log.e("vic_ddd_2","srcHeight = $srcHeight destHeight=$destHeight")
val p = if(position>=lastPosition) positionOffset else 1-positionOffset
Log.e("vic_ddd_2","p = $p")
Log.e("vic_ddd_2","destHeight - srcHeight = ${destHeight - srcHeight}")
currentHeight =(srcHeight + (destHeight - srcHeight)*p).toInt()
isScrolling = true
requestLayout()
}
override fun onPageScrollStateChanged(state: Int) {
if (state == ViewPager.SCROLL_STATE_IDLE){
isScrolling = false
}
}
})
attachViewToParent(this.viewPager2, 0, this.viewPager2?.getLayoutParams())
}
fun setAdapter(adapter: FragmentStateAdapter) {
viewPager2?.adapter = adapter
}
private fun getViewHeight(position: Int): Int {
val adapter = viewPager2?.adapter as? AutoHeightPager
val view = adapter?.getView(position)
view?.measure(lastWidthMeasureSpec, MeasureSpec.makeMeasureSpec(0,MeasureSpec.UNSPECIFIED))
// view?.measure(lastWidthMeasureSpec, MeasureSpec.makeMeasureSpec(1000, View.MeasureSpec.EXACTLY))
// view?.measure(lastWidthMeasureSpec, MeasureSpec.makeMeasureSpec(1000, View.MeasureSpec.AT_MOST))
Log.e("vic_ddd_2","view?.measuredHeight = ${view?.measuredHeight } view = ${view}")
return view?.measuredHeight ?: 0
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
lastWidthMeasureSpec = widthMeasureSpec
var heightSpec = heightMeasureSpec
if (isScrolling){
Log.e("vic_ddd_2","currentHeight = $currentHeight")
heightSpec = View.MeasureSpec.makeMeasureSpec(currentHeight, View.MeasureSpec.EXACTLY)
}else{
getViewHeight(viewPager2?.currentItem?:0).takeIf { it > 0 }?.let {
heightSpec = View.MeasureSpec.makeMeasureSpec(it, View.MeasureSpec.EXACTLY)
}
}
super.onMeasure(widthMeasureSpec, heightSpec)
}
}
ViewPager
package com.autoviewpager
import android.util.Log
import android.view.View
import androidx.viewpager.widget.PagerAdapter
import androidx.viewpager.widget.ViewPager
interface AutoHeightPager {
fun getView(position:Int):View?
}
class AutoHeightViewPager @JvmOverloads constructor(context: android.content.Context, attrs: android.util.AttributeSet? = null) : ViewPager(context, attrs) {
var lastWidthMeasureSpec: Int = 0
var currentHeight: Int = 0
var lastPosition:Int = 0
var isScrolling:Boolean = false
init {
addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
Log.e("vic_ddd","position = $position positionOffset = $positionOffset positionOffsetPixels=$positionOffsetPixels")
if (positionOffset == 0f){
isScrolling = false
requestLayout()
return
}
val srcPosition = if (position>=lastPosition) position else position+1
val destPosition = if (position>=lastPosition) position+1 else position
val srcHeight = getViewHeight(srcPosition)
val destHeight = getViewHeight(destPosition)
Log.e("vic_ddd_2","srcHeight = $srcHeight destHeight=$destHeight")
val p = if(position>=lastPosition) positionOffset else 1-positionOffset
Log.e("vic_ddd_2","p = $p")
Log.e("vic_ddd_2","destHeight - srcHeight = ${destHeight - srcHeight}")
currentHeight =(srcHeight + (destHeight - srcHeight)*p).toInt()
isScrolling = true
requestLayout()
}
override fun onPageSelected(p0: Int) {
}
override fun onPageScrollStateChanged(state: Int) {
if (state == ViewPager.SCROLL_STATE_IDLE){
isScrolling = false
}
}
})
}
private fun getViewHeight(position: Int): Int {
val adapter = adapter as? AutoHeightPager
val view = adapter?.getView(position)
view?.measure(lastWidthMeasureSpec, MeasureSpec.makeMeasureSpec(0,MeasureSpec.UNSPECIFIED))
// view?.measure(lastWidthMeasureSpec, MeasureSpec.makeMeasureSpec(1000, View.MeasureSpec.EXACTLY))
// view?.measure(lastWidthMeasureSpec, MeasureSpec.makeMeasureSpec(1000, View.MeasureSpec.AT_MOST))
Log.e("vic_ddd_2","view?.measuredHeight = ${view?.measuredHeight } view = ${view}")
return view?.measuredHeight ?: 0
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
lastWidthMeasureSpec = widthMeasureSpec
var heightSpec = heightMeasureSpec
if (isScrolling){
Log.e("vic_ddd_2","currentHeight = $currentHeight")
heightSpec = View.MeasureSpec.makeMeasureSpec(currentHeight, View.MeasureSpec.EXACTLY)
}else{
getViewHeight(currentItem).takeIf { it > 0 }?.let {
heightSpec = View.MeasureSpec.makeMeasureSpec(it, View.MeasureSpec.EXACTLY)
}
}
super.onMeasure(widthMeasureSpec, heightSpec)
}
override fun setAdapter(adapter: PagerAdapter?) {
super.setAdapter(adapter)
}
}