Android Glide加载小gif和图片比较模糊
其实Glide加载还是可以将小图片加载的非常清晰的,
可以通过Glide转换为Bitmap
利用Drawable将setFilterBitmap为true
但是这玩意解决不了GIF。在没有找到库的情况下:我直接自定义view
通过
pl.droidsonroids.gif:android-gif-drawable
获取时间间隔并将gif解析成bitmap获取像素 再通过Choreographer进行页面刷新
/** * GIF支持类 兼容 图片 * @author xiaotie https://www.cnblogs.com/xiao-tie/ * @time 2023/7/11 15:14 * @param widthNum 像素宽 * @param heightNum 像素高 * @param seekGif 时间戳间隔 * @param pos 当前显示位置 * @param data 像素数据组 */ data class GifSupport(val widthNum:Int, val heightNum:Int, val seekGif:Long, var pos:Int = 0, val data: MutableList<IntArray>){ fun next(){ pos++ if(pos >= data.size){ pos = 0 } } } /** * 以像素点加载gif支持图片默认以宽度为标准(以高度为标准暂时不需要 未开发) * @author xiaotie https://www.cnblogs.com/xiao-tie/ * @time 2023/7/11 14:48 */ class GIFView : View, Choreographer.FrameCallback{ constructor(context: Context?):super(context) constructor(context: Context?, attrs: AttributeSet?):super(context, attrs) constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int):super(context, attrs, defStyleAttr) private var gifSupport: GifSupport? = null private var size = 0 private var margin = 0f private val paint = Paint() private val choreographer: Choreographer = Choreographer.getInstance() private var isRendering = false ///是否加网格 var isGrid = true set(value) { field = value invalidate() } var widthDigit = 16 set(value) { field = value requestLayout() } var heightDigit = 16 set(value) { field = value requestLayout() } var path = Path() override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { val measuredWidth = MeasureSpec.getSize(widthMeasureSpec) size = measuredWidth / (gifSupport?.widthNum?:widthDigit) margin = (MeasureSpec.getSize(widthMeasureSpec).toFloat() - size * (gifSupport?.widthNum?:widthDigit)) / 2 val measuredHeight = size * (gifSupport?.heightNum?:heightDigit) + margin*2 setMeasuredDimension(measuredWidth, measuredHeight.toInt()) } override fun onAttachedToWindow() { super.onAttachedToWindow() startRendering() } override fun onDetachedFromWindow() { super.onDetachedFromWindow() stopRendering() } @SuppressLint("DrawAllocation") override fun onDraw(canvas: Canvas?) { super.onDraw(canvas) gifSupport?.apply { paint.reset() for (y in 0 until heightNum){ for (x in 0 until widthNum){ paint.color = data[pos][x + widthNum*y] val left = margin + x * size val top = margin + y * size canvas?.drawRect(Rect(left.toInt(), top.toInt(), (left+size).toInt(), (top+size).toInt()),paint) } } if(isGrid){ path.reset() for (y in 0 until heightNum){ path.moveTo(margin,margin + y * size) path.lineTo(width-margin, margin + y * size) } for (x in 0 until widthNum){ path.moveTo(margin + x * size, margin) path.lineTo(margin + x * size, height-margin) } paint.color = Color.parseColor("#66000000") paint.strokeWidth = 1f paint.style = Paint.Style.STROKE canvas?.drawPath(path,paint) } } } override fun doFrame(frameTimeNanos: Long) { gifSupport?.next() gifSupport?.let { invalidate() // 强制重绘视图 }?: kotlin.run { stopRendering() } if (isRendering) { choreographer.postFrameCallbackDelayed(this, gifSupport?.seekGif?:100) // 每 200 毫秒刷新一次 } } private fun startRendering() { if (!isRendering) { isRendering = true choreographer.postFrameCallback(this) } } private fun stopRendering() { invalidate() if (isRendering) { isRendering = false choreographer.removeFrameCallback(this) } } private suspend fun getHttpToStream(url:String) = withContext(Dispatchers.IO) { val client = OkHttpClient() val request: Request = Request.Builder() .url(url) .build() try { val response = client.newCall(request).execute() response.body!!.byteStream() }catch (e:Exception){ e.printStackTrace() null } } private suspend fun getFileToStream(filePath:String) = withContext(Dispatchers.IO) { val file = File(filePath) try { val inputStream = FileInputStream(file) as InputStream inputStream }catch (e:Exception){ e.printStackTrace() null } } /** * 颜色填充 * @author xiaotie https://www.cnblogs.com/xiao-tie/ * @time 2023/7/12 15:06 */ fun setColorData(@ColorInt colorInt: Int) { val colors:IntArray = Array(widthDigit * heightDigit) { colorInt }.toIntArray() gifSupport = GifSupport(widthDigit,heightDigit,10,0, mutableListOf(colors)) invalidate() } /** * 资源链接 支持本地链接和图片链接 * @author xiaotie https://www.cnblogs.com/xiao-tie/ * @time 2023/7/12 15:06 */ fun setUrlOrFile(link :String?) { link?:return gifSupport = null GlobalScope.launch { if(link.contains("http")){ getHttpToStream(link) }else{ getFileToStream(link) }?.also { if(link.contains(".gif")){ val bis = BufferedInputStream(it) val resource = GifDrawable( bis ) val width = resource.intrinsicWidth val height = resource.intrinsicHeight val bitmapsData = mutableListOf<IntArray>() // 将 GIF 每帧的像素数据写入 ByteBuffer for (i in 0 until resource.numberOfFrames) { val frame = resource.seekToFrameAndGet(i) val framePixels = IntArray(width * height) frame.getPixels(framePixels, 0, width, 0, 0, width, height) bitmapsData.add(framePixels) } gifSupport = GifSupport(width,height,resource.duration.toLong()/resource.numberOfFrames, 0,bitmapsData) post { widthDigit = width heightDigit = height } startRendering() resource.recycle() }else if(link.contains(".png")){ val frame = BitmapFactory.decodeStream(it) setBitmap(frame) it.close() } } } } /** * 设置图片 * @author xiaotie https://www.cnblogs.com/xiao-tie/ * @time 2023/7/13 10:05 */ fun setBitmap(frame:Bitmap){ val width = frame.width val height = frame.height val framePixels = IntArray(width * height) frame.getPixels(framePixels, 0, width, 0, 0, width, height) gifSupport = GifSupport(width,height,10,0, mutableListOf(framePixels)) post { widthDigit = width heightDigit = height } invalidate() } /** * 设置gif数据 * @author xiaotie https://www.cnblogs.com/xiao-tie/ * @time 2023/7/13 10:06 * @param byte Byte数组 */ fun setRawGifBytes(byte: ByteArray){ val resource = GifDrawable( byte ) val width = resource.intrinsicWidth val height = resource.intrinsicHeight val bitmapsData = mutableListOf<IntArray>() // 将 GIF 每帧的像素数据写入 ByteBuffer for (i in 0 until resource.numberOfFrames) { val frame = resource.seekToFrameAndGet(i) val framePixels = IntArray(width * height) frame.getPixels(framePixels, 0, width, 0, 0, width, height) bitmapsData.add(framePixels) } gifSupport = GifSupport(width,height,resource.duration.toLong()/resource.numberOfFrames, 0,bitmapsData) widthDigit = width heightDigit = height startRendering() resource.recycle() } /** * 设置图片数据 * @author xiaotie https://www.cnblogs.com/xiao-tie/ * @time 2023/7/13 10:06 * @param byte Byte数组 */ fun setRawPictureBytes(byte: ByteArray) { val frame = BitmapFactory.decodeByteArray(byte,0,byte.size) setBitmap(frame) } }