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

前言

偶然間看到知乎廣告位的效果,做爲一名好奇心爆棚的程序員,以爲頗有趣,思考了下原理,決定造個輪子,國際慣例效果圖以下(注意圖中的章魚):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

相關文章
相關標籤/搜索