碉堡的效果-仿知乎广告效果

前言

偶然间看到知乎广告位的效果,做为一名好奇心爆棚的程序员,以为颇有趣,思考了下原理,决定造个轮子,国际惯例效果图以下(注意图中的章鱼):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

相关文章
相关标签/搜索