CodeFlys
1/3/2020 - 6:59 AM

ViewExtend

class ViewExtend {
    companion object {
        /**
         * 将 layout 文件转换成 Bitmap
         */
        fun layoutResDrawToBitmap(
            layoutInflater: LayoutInflater, @LayoutRes layoutRes: Int,
            width: Int,
            height: Int
        ): Bitmap {
            val view: View = layoutInflater.inflate(layoutRes, null, false)
            val measuredWidth = View.MeasureSpec.makeMeasureSpec(
                width,
                View.MeasureSpec.EXACTLY
            )
            val measuredHeight = View.MeasureSpec.makeMeasureSpec(
                height,
                View.MeasureSpec.EXACTLY
            )
            view.measure(measuredWidth, measuredHeight)
            view.layout(0, 0, view.measuredWidth, view.measuredHeight)
            return view.draw2Bitmap {
                drawColor(Color.WHITE)
            }
        }
    }
}

///////////////////////////////////////////////////////////////////////////
// View2Bitmap View 转换成 Bitmap
///////////////////////////////////////////////////////////////////////////
/**
 * 将 view 转换成 Bitmap
 */
fun View.draw2Bitmap(
    config: Bitmap.Config = Bitmap.Config.ARGB_8888,
    block: (Canvas.() -> Unit)? = null
): Bitmap {
    if (!ViewCompat.isLaidOut(this)) {
        throw IllegalStateException("View needs to be laid out before calling drawToBitmap()")
    }
    val bitmap = Bitmap.createBitmap(width, height, config)
    Canvas(bitmap).apply {
        block?.invoke(this)
        translate(-scrollX.toFloat(), -scrollY.toFloat())
        draw(this)
    }
    return bitmap
}

/**
 * 将 NestedScrollView 转换成 Bitmap
 */
fun NestedScrollView.draw2Bitmap(
    config: Bitmap.Config = Bitmap.Config.ARGB_8888,
    block: (Canvas.() -> Unit)? = null
): Bitmap {
    if (!ViewCompat.isLaidOut(this)) {
        throw IllegalStateException("View needs to be laid out before calling drawToBitmap()")
    }
    var h = 0
    var bitmap: Bitmap? = null
    for (i in 0 until this.childCount) {
        h += this.getChildAt(i).height
    }
    bitmap = Bitmap.createBitmap(this.width, h, config)
    val canvas = Canvas(bitmap)
    block?.invoke(canvas)
    this.draw(canvas)
    return bitmap
}

///////////////////////////////////////////////////////////////////////////
// ViewFastClick 快速点击
///////////////////////////////////////////////////////////////////////////
/**
 * 拦截 View 快速点击
 * @param fastLimitTime 快速点击的时间限制
 * @param blockAction 拦截到快速点击后执行的操作
 */
fun View.blockFastClick(fastLimitTime: Long = 2000, blockAction: (View) -> Unit) {
    if (fastClicked(fastLimitTime)) blockAction(this)
}

/**
 * 拦截 View 快速点击
 * @param fastLimitTime 快速点击的时间限制
 * @param blockAction 拦截到快速点击后执行的操作
 */
fun View.setFastClickListener(
    acrossAction: View.OnClickListener,
    fastLimitTime: Long = 800,
    blockAction: (View) -> Unit = {}
) {
    setOnClickListener {
        if (fastClicked(fastLimitTime)) {
            //不允许
            blockAction(it)
        } else {
            //允许
            acrossAction.onClick(it)
        }
    }
}

/**
 * 拦截 View 快速点击
 * @param fastLimitTime 快速点击的时间限制
 * @param blockAction 拦截到快速点击后执行的操作
 */
fun View.setFastClickListener(
    acrossAction: (View) -> Unit = {}, blockAction: (View) -> Unit = {},
    fastLimitTime: Long = 2000
) {
    setOnClickListener {
        if (fastClicked(fastLimitTime)) {
            blockAction(it)
        } else {
            acrossAction(it)
        }
    }
}

/**
 * 判断 View 是否是快速点击
 * @param fastClickLimitTime 快速点击的时间限制
 * @return true -> 快速点击 false -> 非快速点击
 */
fun View.fastClicked(fastClickLimitTime: Long = 800): Boolean {
    val preClickTimeTag: Any? = getTag(R.id.tag_fast_click_limit_time)
    if (preClickTimeTag == null) {
        setTag(R.id.tag_fast_click_limit_time, SystemClock.elapsedRealtime())
        return false
    }
    val preClickTime = preClickTimeTag as Long
    val currClickTime = SystemClock.elapsedRealtime()
    return if (currClickTime - preClickTime <= fastClickLimitTime) {
        true
    } else {
        setTag(R.id.tag_fast_click_limit_time, currClickTime)
        false
    }
}