Android UI | 控件占位加載的Drawable
本文未經(jīng)授權(quán),切勿轉(zhuǎn)載
嗨,各位路過的小伙伴大家好。由于工作原因,已經(jīng)快鴿了好長時(shí)間不更新文章了,這次就先介紹用于控件占位加載的動畫,基于自定義Drawable實(shí)現(xiàn)的。
Drawable是什么
1、一種可以在Canvas上進(jìn)行繪制的抽象的概念
2、顏色、圖片等都可以是一個(gè)Drawable
3、Drawable可以通過XML定義,或者通過代碼創(chuàng)建</font>**
4、Android中Drawable是一個(gè)抽象類,每個(gè)具體的Drawable都是其子類
自定義Drawable優(yōu)勢
1、使用簡單,比自定義View成本低
2、非圖片類的Drawable所占空間小,能減小apk大小
實(shí)現(xiàn)加載動畫的Drawable
按慣例我們先直接看效果:
<font face="STCAIYUN" color="#0099ff">代碼分析</font>
這次分析代碼我們從需要什么,到如何實(shí)現(xiàn)進(jìn)行一步步講解
1、我們需要什么
既然我們是需要實(shí)現(xiàn)自定義Drawable,那么第一步肯定是新建一個(gè)類并繼承Drawalbe,我這里繼承的是ShapeDrawable
class PlaceHolderDrawable: ShapeDrawable()
接下來就是畫圖,我們可以看到我們的自定義Drawable也是有Canvas這個(gè)方法,和自定義View很像。然后這個(gè)加載動畫中間白色部分從左到右滑動,然后有漸變效果,可以知道這個(gè)就是我們熟悉的漸變色的Drawable,這個(gè)是我們在xml上面自定義Drawable經(jīng)常使用到的。先看代碼:
private var mGradientCanvas: Canvas? = null //柱狀漸變色的Canvas
private var mGradientLayer: Bitmap? = null
private var mBackgroundCanvas: Canvas? = null //背景Canvas
private var mBackgroundLayer: Bitmap? = null
private val floatArray = floatArrayOf( 0f,0.4f,0.8f)
override fun draw(canvas: Canvas) {
super.draw(canvas)
shape.draw(mBackgroundCanvas, paint)
canvas.drawBitmap(mBackgroundLayer!!, 0f, 0f, paint)
xStartCoordinate = animatedValue
xEndCoordinate = xStartCoordinate + mCanvasWidth/2
paint.shader = LinearGradient(xStartCoordinate, 0f, xEndCoordinate, 0f, mColors, floatArray, Shader.TileMode.CLAMP)
shape.draw(mGradientCanvas, paint)
canvas.drawBitmap(mGradientLayer!!, 0f, 0f, paint)
}
其中LinearGradient的源碼是這樣解釋的:
/**
* Create a shader that draws a linear gradient along a line.
*
* @param x0 The x-coordinate for the start of the gradient line
* @param y0 The y-coordinate for the start of the gradient line
* @param x1 The x-coordinate for the end of the gradient line
* @param y1 The y-coordinate for the end of the gradient line
* @param colors The sRGB colors to be distributed along the gradient line
* @param positions May be null. The relative positions [0..1] of
* each corresponding color in the colors array. If this is null,
* the the colors are distributed evenly along the gradient line.
* @param tile The Shader tiling mode
*/
public LinearGradient(float x0, float y0, float x1, float y1, @NonNull @ColorInt int[] colors,
@Nullable float[] positions, @NonNull TileMode tile) {
this(x0, y0, x1, y1, convertColors(colors), positions, tile,
ColorSpace.get(ColorSpace.Named.SRGB));
}
第一個(gè)參數(shù)為線性起點(diǎn)的x坐標(biāo)
第二個(gè)參數(shù)為線性起點(diǎn)的y坐標(biāo)
第三個(gè)參數(shù)為線性終點(diǎn)的x坐標(biāo)
第四個(gè)參數(shù)為線性終點(diǎn)的y坐標(biāo)
第五個(gè)參數(shù)為實(shí)現(xiàn)漸變效果的顏色的組合
第六個(gè)參數(shù)為前面的顏色組合中的各顏色在漸變中占據(jù)的位置(比重)
第七個(gè)參數(shù)為渲染器平鋪的模式,一共有三種
詳細(xì)介紹各參數(shù)區(qū)別可以參考以下文章
http://www.itdecent.cn/p/a9d09cb7577f
然后再把移動的動畫加進(jìn)去,就可以做到效果了
private val interpolator = LinearInterpolator()
private var animatedValue = 0f
fun setupAnimator() {
xStartCoordinate = 0f //偏移量
valueAnimator = ValueAnimator.ofFloat(- mCanvasWidth.toFloat()/3, mCanvasWidth.toFloat())
valueAnimator?.duration = duration
valueAnimator?.interpolator = interpolator
valueAnimator?.repeatMode = ValueAnimator.RESTART
valueAnimator?.repeatCount = ValueAnimator.INFINITE
valueAnimator?.addUpdateListener { animation ->
animatedValue = animation.animatedValue as Float
invalidateSelf()
}
valueAnimator?.start()
}
原理十分簡單就是利用X軸的不斷偏移,然后一直繪制從而達(dá)到效果
其實(shí)是大致上已經(jīng)完成了這個(gè)功能了,剩下就是Drawable的長寬高獲取顏色,以及如何管理,詳細(xì)可以到我GitHub上看源碼,有問題可以在掘金或者Github上的Issue留言,如果有問題不清楚建議在Issue留言,因?yàn)槲掖贕ithub的時(shí)間多于掘金。
https://github.com/ShowMeThe/PlaceHolder。