滚动显示完整图片

自定义ImageView,是RecyclerView的一个item,滚动显示完整的图片,如下

device-2020-11-26-114926 00_00_04-00_00_24.gif

其实思路也很简单了,展示图片的控件高度很小,而图片高度很大,我们只有滚动的时候才能看到完整图片的不同部分, 我是想到ImageView处理图片的时候也会裁剪啥的,而且也有一种scaleType是Matrix,我们动态修改Matrix不就可以动态处理图片的显示效果了?


image.png
image.png

如下就是自定义了一个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在底部的话显示图片的底部视图.

image.png

题外话

目前的效果是滚到顶部的时候图片就不滚动了,然后继续划出屏幕, 感觉不满意的可以自行处理,把分母加上ImageView的高度也行,随意.

你可能感兴趣的:(滚动显示完整图片)