Android 使用Fresco实现不同形状的加载图片

一 概述

Fresco是Facebook发布的一款开源框架,号称是目前最强的Android图片加载库,在内存方面的表现极为优秀,对于Fresco的一些介绍,就不多说了,如果你感兴趣肯定会到网上找一些相关的资料,建议你到中文官网查看:https://www.fresco-cn.org/docs/index.html。好了,话不多说,我这次带给大家的是对于同一个图片如何使用Fresco加载出不同的形状。比如这样的:

这里写图片描述

二、原理分析

实现的原理很简单,就是通过继承BasePostprocessor对图片做一些修改。不熟悉的同学可以去这里瞅瞅https://www.fresco-cn.org/docs/modifying-image.html

  1. 实现一个静态的父类Postprocessor。(由于本人最近在学习kotlin,所以源码均以kotlin语言的形式给出)
abstract class DrawablePostprocessor : BasePostprocessor() {
    var paint: Paint? = null
    var drawable: Drawable? = null

    init {
        paint = Paint()
        paint!!.xfermode = PorterDuffXfermode(PorterDuff.Mode.SRC_IN)
    }

    override fun process(destBitmap: Bitmap?, sourceBitmap: Bitmap?) {
        drawable = createDrawable(sourceBitmap!!.width.toFloat(), sourceBitmap!!.height.toFloat())
        var bitmap: Bitmap = Bitmap.createBitmap(sourceBitmap!!.width, sourceBitmap!!.height, Bitmap.Config.ARGB_8888)
        var canvas: Canvas = Canvas(bitmap)

        drawable!!.bounds.set(0, 0, sourceBitmap!!.width, sourceBitmap!!.height)
        drawable!!.draw(canvas)
        canvas.drawBitmap(sourceBitmap, 0f, 0f, paint)
        super.process(destBitmap, bitmap)
    }

    abstract fun createDrawable(width: Float, height: Float): Drawable
}
  1. 在activity中通过fresco加载网络图片。

    通过创建ImageRequest 的方式加载图片,在创建ImageRequest 的过程中设置它的Postprocessor,这时我们使用上面的写好的DrawablePostprocessor 创建一个匿名的Postprocessor,同时重写它的createDrawable方法。

class MainActivity : BaseActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        //图片地址
        var url: String = "https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy" +
                "/it/u=3276424759,4034967609&fm=26&gp=0.jpg"
        var imageRequest: ImageRequest = ImageRequestBuilder.newBuilderWithSource(Uri.parse(url!!))
                .setPostprocessor(object : DrawablePostprocessor() {
                    override fun createDrawable(width: Float, height: Float): Drawable {
                        //五角星
                        return FivePointedStarDrawable(width, height)
                        //菱形
                        //return DiamondDrawable(width, height)
                        //半圆
                        //return HalfCircleDrawable(width, height)
                        //平行四边形
                        //return ParallelogramDrawable(width, height)
                    }
                }).build()
        var controller: DraweeController = Fresco.newDraweeControllerBuilder().setImageRequest(imageRequest)
                .setOldController(iv_image.controller).build()
        iv_image.controller = controller
        iv_image_origin.setImageURI(Uri.parse(url))
    }
}
  1. 实现createDrawable所需要的Drawable。
    在此我们只需要继承Android的Drawable实现自己的Drawable就好了。我为了方便写了一抽象的ShapeDrawable 父类,具体的实现只需要继承这个父类就好。

ShapeDrawable 父类

abstract class ShapeDrawable constructor(width: Float, height: Float) : Drawable() {
    var paint: Paint? = null
    var width: Float = 0F
    var height: Float = 0F

    init {
        this.width = width
        this.height = height
        paint = Paint()
    }

    override fun setAlpha(alpha: Int) {
        paint?.alpha = alpha
    }

    override fun getOpacity(): Int {
        return PixelFormat.TRANSLUCENT
    }

    override fun setColorFilter(colorFilter: ColorFilter?) {
        paint?.colorFilter = colorFilter
    }

    override fun getIntrinsicWidth(): Int {
        return width.toInt()
    }

    override fun getIntrinsicHeight(): Int {
        return height.toInt()
    }
}

具体实现子类

class FivePointedStarDrawable constructor(width: Float, height: Float) : ShapeDrawable(width, height) {
    init {
        super.width = width
        super.height = height
    }

    //绘制五角星
    override fun draw(canvas: Canvas?) {
        val path = Path()
        var radius = Math.min(width, height) / 2
        val radian = degree2Radian(36)// 36为五角星的角度
        val radius_in = (radius * Math.sin((radian / 2).toDouble()) / Math
                .cos(radian.toDouble())).toFloat() // 中间五边形的半径

        path.moveTo((radius * Math.cos((radian / 2).toDouble())).toFloat(), 0F)// 此点为多边形的起点
        path.lineTo((radius * Math.cos((radian / 2).toDouble()) + radius_in * Math.sin(radian.toDouble())).toFloat(),
                (radius - radius * Math.sin((radian / 2).toDouble())).toFloat())
        path.lineTo((radius.toDouble() * Math.cos((radian / 2).toDouble()) * 2.0).toFloat(),
                (radius - radius * Math.sin((radian / 2).toDouble())).toFloat())
        path.lineTo((radius * Math.cos((radian / 2).toDouble()) + radius_in * Math.cos((radian / 2).toDouble())).toFloat(),
                (radius + radius_in * Math.sin((radian / 2).toDouble())).toFloat())
        path.lineTo(
                (radius * Math.cos((radian / 2).toDouble()) + radius * Math.sin(radian.toDouble())).toFloat(), (radius + radius * Math.cos(radian.toDouble())).toFloat())
        path.lineTo((radius * Math.cos((radian / 2).toDouble())).toFloat(),
                (radius + radius_in).toFloat())
        path.lineTo(
                (radius * Math.cos((radian / 2).toDouble()) - radius * Math.sin(radian.toDouble())).toFloat(), (radius + radius * Math.cos(radian.toDouble())).toFloat())
        path.lineTo((radius * Math.cos((radian / 2).toDouble()) - radius_in * Math.cos((radian / 2).toDouble())).toFloat(),
                (radius + radius_in * Math.sin((radian / 2).toDouble())).toFloat())
        path.lineTo(0F, (radius - radius * Math.sin((radian / 2).toDouble())).toFloat())
        path.lineTo((radius * Math.cos((radian / 2).toDouble()) - radius_in * Math.sin(radian.toDouble())).toFloat(),
                (radius - radius * Math.sin((radian / 2).toDouble())).toFloat())

        path.close()// 使这些点构成封闭的多边形
        canvas!!.drawPath(path, paint)
    }

    fun degree2Radian(degree: Int): Float {
        return (Math.PI * degree / 180).toFloat()
    }
}

最后在附几张其他形状的效果图片
这里写图片描述这里写图片描述

本篇博客的目的呢,就是为了简绍Fresco的BasePostprocessor,在此分享出来希望和大家共同学习,共同进步,如文中有什么问题,或者kotlin的使用有误的地方,希望提出,本人不胜感激。如有疑问可以联系我邮箱97287691@qq.com。

源码下载

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值