自定義ImageView,是RecyclerView的一個(gè)item,滾動(dòng)顯示完整的圖片,如下

device-2020-11-26-114926 00_00_04-00_00_24.gif
其實(shí)思路也很簡(jiǎn)單了,展示圖片的控件高度很小,而圖片高度很大,我們只有滾動(dòng)的時(shí)候才能看到完整圖片的不同部分, 我是想到ImageView處理圖片的時(shí)候也會(huì)裁剪啥的,而且也有一種scaleType是Matrix,我們動(dòng)態(tài)修改Matrix不就可以動(dòng)態(tài)處理圖片的顯示效果了?

image.png

image.png
如下就是自定義了一個(gè)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
//只關(guān)心上下滾動(dòng)的情況,所以這里只處理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// 這個(gè)ImageView的寬
val scale: Float = vwidth.toFloat() / dwidth.toFloat()//我們要保證圖片橫向鋪滿,所以縮放以橫向?yàn)闇?zhǔn)
val trans =
factor * dheight * scale //dheight*scale 這個(gè)是原始圖片縮放后的實(shí)際高度, 乘以滾動(dòng)因子,就是要平移的距離
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
}
}
用的時(shí)候也很簡(jiǎn)單,設(shè)置完圖片,然后調(diào)用bindRecyclerView()就ok拉!
簡(jiǎn)單說下原理,黑框RecyclerView高度,紅框是ImageView高度,ImageView可見范圍就是RecyclerView的高度,算出這個(gè)因子,就知道圖片該偏移多少,反正ImageView到頂部的話顯示圖片的頂部視圖,ImageView在底部的話顯示圖片的底部視圖.

image.png
題外話
目前的效果是滾到頂部的時(shí)候圖片就不滾動(dòng)了,然后繼續(xù)劃出屏幕, 感覺不滿意的可以自行處理,把分母加上ImageView的高度也行,隨意.