自定义ImageView,是RecyclerView的一个item,滚动显示完整的图片,如下
其实思路也很简单了,展示图片的控件高度很小,而图片高度很大,我们只有滚动的时候才能看到完整图片的不同部分, 我是想到ImageView处理图片的时候也会裁剪啥的,而且也有一种scaleType是Matrix,我们动态修改Matrix不就可以动态处理图片的显示效果了?
如下就是自定义了一个ImageView
import android.content.Context
import android.graphics.Matrix
import android.util.AttributeSet
import androidx.appcompat.widget.AppCompatImageView
import androidx.recyclerview.widget.RecyclerView
class ScrollShowImageView : AppCompatImageView {
constructor(context: Context) : super(context)
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(
context,
attrs,
defStyleAttr
)
init {
scaleType = ScaleType.MATRIX
}
val location = IntArray(2)
val scrollListener = object : RecyclerView.OnScrollListener() {
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
calMatrix()
}
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
}
}
private fun calMatrix(){
drawable?.apply {
val recyclerView=rv?:return
//只关心上下滚动的情况,所以这里只处理y轴
recyclerView.getLocationInWindow(location)//get recyclerView location [left ,top]
val y1 = location[1]
getLocationInWindow(location)//get this ImageView location [left,top]
val y2 = location[1]
val imageViewTop = y2 - y1
val rvHeight = recyclerView.height
val factor = Math.max(imageViewTop * 1.0f / rvHeight, 0f)
val dwidth: Int = this.bounds.width()//原始图片宽
val dheight: Int = this.bounds.height()//原始图片高
val vwidth: Int = width - paddingStart - paddingEnd// 这个ImageView的宽
val scale: Float = vwidth.toFloat() / dwidth.toFloat()//我们要保证图片横向铺满,所以缩放以横向为准
val trans =
factor * dheight * scale //dheight*scale 这个是原始图片缩放后的实际高度, 乘以滚动因子,就是要平移的距离
val m = Matrix()
m.setScale(scale, scale)
m.postTranslate(0f, -trans)
imageMatrix = m
}
}
private var rv: RecyclerView? = null
fun bindRecyclerView(recyclerView: RecyclerView) {
if (rv == recyclerView) return
rv?.removeOnScrollListener(scrollListener)
rv = recyclerView
rv?.addOnScrollListener(scrollListener)
post { calMatrix() }
}
override fun onDetachedFromWindow() {
super.onDetachedFromWindow()
rv?.removeOnScrollListener(scrollListener)
rv=null
}
}
用的时候也很简单,设置完图片,然后调用bindRecyclerView()就ok拉!
简单说下原理,黑框RecyclerView高度,红框是ImageView高度,ImageView可见范围就是RecyclerView的高度,算出这个因子,就知道图片该偏移多少,反正ImageView到顶部的话显示图片的顶部视图,ImageView在底部的话显示图片的底部视图.
题外话
目前的效果是滚到顶部的时候图片就不滚动了,然后继续划出屏幕, 感觉不满意的可以自行处理,把分母加上ImageView的高度也行,随意.