偶然间看到知乎广告位的效果,做为一名好奇心爆棚的程序员,以为颇有趣,思考了下原理,决定造个轮子,国际惯例效果图以下(注意图中的章鱼):android
首先应该市有一张长图,随着滚动按区域加载长图的局部,就能够实现效果。首先自定义一个 IamgeView,能够随着 RecyclerView 的滚动动态加载长图的的取域,获取滚动距离代码以下:程序员
/**
* 获取到RecyclerView的滚动距离
*/
private fun setRecyclerView() {
post {
var par: ViewParent? = parent
while (true) {
if (par is RecyclerView) {
rv = par
break
} else {
par = par?.parent
}
}
rv!!.addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
super.onScrollStateChanged(recyclerView, newState)
}
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
super.onScrolled(recyclerView, dx, dy)
Log.d(TAG, "onScrolled$dy")
setShowH(dy)
}
})
}
}
复制代码
根据滚动距离动态加载图片,代码以下:bash
/**
* @param h 每次过分的距离,用于计算 RecyclerView 滚动的总距离
*/
fun setShowH(h: Int) {
if (dettach) {
return
}
scollHeight += h
//边界
scollHeight = min(bitmapRegionDecoder.height - mHeight, (max(scollHeight, 0)))
Log.d(TAG, "setShowH$scollHeight")
Log.d(TAG, "bitmapRegionDecoder.height${bitmapRegionDecoder.height}")
Log.d(TAG, "scollHeight + mHeig${scollHeight + mHeight}")
//按举行区域加载图片
var bitmap: Bitmap =
bitmapRegionDecoder.decodeRegion(
Rect(0, scollHeight, width, scollHeight + mHeight),
null
)
setImageBitmap(bitmap)
}
复制代码
完整代码以下:ide
package com.example.juejin
import android.content.Context
import android.graphics.Bitmap
import android.graphics.BitmapRegionDecoder
import android.graphics.Rect
import android.util.AttributeSet
import android.util.Log
import android.view.ViewParent
import android.widget.ImageView
import androidx.recyclerview.widget.RecyclerView
import kotlin.math.max
import kotlin.math.min
/**
* @author lishaojie on 2019/10/22
*/
class RegionImageView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0,
val TAG: String = "RegionImageView",
var dettach: Boolean = false
) : ImageView(context, attrs, defStyleAttr) {
var mHeight: Int = 0
var scollHeight: Int = 0
private var rv: RecyclerView? = null
//长图
var bitmapRegionDecoder: BitmapRegionDecoder = BitmapRegionDecoder.newInstance(
context.assets.open("octopus.jpg"),
false
)
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
super.onSizeChanged(w, h, oldw, oldh)
if (mHeight == 0) {
mHeight = h
setShowH(0)
setRecyclerView()
}
}
/**
* 获取到RecyclerView的滚动距离
*/
private fun setRecyclerView() {
post {
var par: ViewParent? = parent
while (true) {
if (par is RecyclerView) {
rv = par
break
} else {
par = par?.parent
}
}
rv!!.addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
super.onScrollStateChanged(recyclerView, newState)
}
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
super.onScrolled(recyclerView, dx, dy)
Log.d(TAG, "onScrolled$dy")
setShowH(dy)
}
})
}
}
override fun onAttachedToWindow() {
super.onAttachedToWindow()
dettach = false
}
override fun onDetachedFromWindow() {
super.onDetachedFromWindow()
Log.d(TAG, "onDetachedFromWindow")
dettach = true
}
/**
* @param h 每次过分的距离,用于计算 RecyclerView 滚动的总距离
*/
fun setShowH(h: Int) {
if (dettach) {
return
}
scollHeight += h
//边界
scollHeight = min(bitmapRegionDecoder.height - mHeight, (max(scollHeight, 0)))
Log.d(TAG, "setShowH$scollHeight")
Log.d(TAG, "bitmapRegionDecoder.height${bitmapRegionDecoder.height}")
Log.d(TAG, "scollHeight + mHeig${scollHeight + mHeight}")
//按举行区域加载图片
var bitmap: Bitmap =
bitmapRegionDecoder.decodeRegion(
Rect(0, scollHeight, width, scollHeight + mHeight),
null
)
setImageBitmap(bitmap)
}
}
复制代码
binggopost