Android 实现流光字体显示
实现方式一
借助Facebook开源的项目Shimmer,非常方便强大的一款开源项目。
实现方式二
开源项目Shimmer-android,方便使用,可去参考。
实现方式三
自定义view实现,参考方式二实现方式,代码如下,重写onSizeChanged设置一些基本参数,在onDraw方法中绘制图层,通过改变Shader实现,最后通过postInvalidateDelayed方法进行重绘图层。
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.LinearGradient;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Shader;
import android.util.AttributeSet;
import android.widget.TextView;
import java.util.logging.Logger;
public class Test extends TextView {
private Logger logger= Logger.getLogger("Test");
private LinearGradient mLinearGradient;
private Matrix mGradientMatrix;
private Paint mPaint;
private int mViewWidth = 0;
private int mTranslate = 0;
private boolean mAnimating = true;
public Test(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
logger.info("onSizeChanged");
if (mViewWidth == 0) {
mViewWidth = getMeasuredWidth();
if (mViewWidth > 0) {
mPaint = getPaint();
mLinearGradient = new LinearGradient(-mViewWidth, 0, 0, 0,
new int[]{0x33ffffff, 0xffffffff, 0x33ffffff},
new float[]{0.0f, 0.5f, 1.0f}, Shader.TileMode.CLAMP);
mPaint.setShader(mLinearGradient);
mGradientMatrix = new Matrix();
}
}
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
logger.info("onDraw");
if (mAnimating && mGradientMatrix != null) {
mTranslate += mViewWidth / 10;
if (mTranslate > 2 * mViewWidth) {
mTranslate = -mViewWidth;
}
mGradientMatrix.setTranslate(mTranslate, 0);
mLinearGradient.setLocalMatrix(mGradientMatrix);
postInvalidateDelayed(30);
}
}
}
2019-07-12 修改实现方式,将流光效果封装到对象中,使用只需要调用对象设置paint即可。
- 接口
import android.graphics.Color
import android.graphics.LinearGradient
import android.graphics.Matrix
import android.graphics.Shader
import com.xjlmh.classic.view.sticker.Sticker
interface ShimmerStyle{
fun setAnimating(boolean: Boolean=true)
fun setLinearGradient(linearGradient: LinearGradient?=null)
fun setGradientMatrix(matrix: Matrix?=null)
fun setDefaultTranslate(default: Int=0)
fun setLinearGradientColors(colors:IntArray?)
fun setLinearGradientPositions(position:FloatArray?)
fun initShimmerDefault(){
println("initShimmerDefault")
setAnimating()
setLinearGradient()
setGradientMatrix()
setDefaultTranslate()
}
}
- 实现类
import android.graphics.*
import com.xjlmh.classic.instrument.log.DebugLog
class Shimmer() : ShimmerStyle {
private var mLinearGradient: LinearGradient? = null
private var mGradientMatrix: Matrix? = null
var mPaint = Paint()
private var mViewWidth = 0
private var isAnimating = true
private var mTranslate = 0
var mWidthDivideBy = 5
private val DEFAULT_COLORS = intArrayOf(0xff00ffff.toInt(), 0xffffffff.toInt(), 0xff00ffff.toInt())
private val DEFAULT_POSITIONS = floatArrayOf(0.0f, 0.5f, 1.0f)
private val DEFAULT_SHADER_TILEMODE=Shader.TileMode.CLAMP
private var colors = DEFAULT_COLORS//intArrayOf(0xff00ffff.toInt(), 0xffffffff.toInt(), 0xff00ffff.toInt())
private var positions = DEFAULT_POSITIONS
private var content: String = ""
private var tileMode:Shader.TileMode= DEFAULT_SHADER_TILEMODE
/**
* 构建基础数据
*/
constructor(content: String) : this() {
this.content = content
// if (content.length>7)
// setLinearGradientColors(intArrayOf(0xFF4DDA11.toInt(), 0xffffffff.toInt(), 0xFF4DDA11.toInt()))
DebugLog.i("Shimmer", "shimmer create")
println("shimmer create")
val rect = Rect()
mPaint.textSize = 60f
mPaint.getTextBounds(content, 0, 1, rect)
mViewWidth = mPaint.measureText(content).toInt()
}
/**
* 初始化,所有配置设置好以后调用,调用以后设置关联, LinearGradient首次实例化之后不可修改,因此采用每次修改都需实例化
*/
fun init(){
initShimmerDefault().apply {
DebugLog.i("Shimmer", "initShimmerDefault")
}
mPaint.shader = mLinearGradient
}
override fun setShaderTileMode(tileMode: Shader.TileMode?) {
tileMode?.let {
this.tileMode=it
return
}
this.tileMode= DEFAULT_SHADER_TILEMODE
}
override fun setLinearGradientColors(colors: IntArray?) {
DebugLog.i("Shimmer", "setLinearGradientColors before:${this.colors.toList()} ")
colors?.let {
this.colors=it
DebugLog.i("Shimmer", "setLinearGradientColors after: ${this.colors.toList()}")
return
}
this.colors=DEFAULT_COLORS
}
override fun setLinearGradientPositions(position: FloatArray?) {
DebugLog.i("Shimmer", "setLinearGradientPositions before:${this.positions.toList()} ")
position?.let {
this.positions=it
DebugLog.i("Shimmer", "setLinearGradientPositions after: ${this.positions.toList()}")
return
}
this.positions=DEFAULT_POSITIONS
}
override fun setAnimating(b: Boolean) {
DebugLog.i("Shimmer", "setAnimating:$b")
isAnimating = b
}
override fun setLinearGradient(linearGradient: LinearGradient?) {
DebugLog.i("Shimmer", "setLinearGradient:$linearGradient")
mLinearGradient = linearGradient ?: LinearGradient((-mViewWidth).toFloat(), 0f, 0f, 0f,
colors,
positions,tileMode)
}
override fun setGradientMatrix(matrix: Matrix?) {
DebugLog.i("Shimmer", "setGradientMatrix:$matrix")
mGradientMatrix = matrix ?: Matrix()
}
override fun setDefaultTranslate(i: Int) {
DebugLog.i("Shimmer", "setDefaultTranslate:$i")
mTranslate = i
}
/**
* 绘制函数,调用画出阴影
*/
fun run() {
DebugLog.i("Shimmer", "run")
if (isAnimating && mGradientMatrix != null) {
mTranslate += mViewWidth / mWidthDivideBy
if (mTranslate > 2 * mViewWidth) {
mTranslate = 0
}
DebugLog.i("Shimmer", "mTranslate :$mTranslate")
mGradientMatrix!!.setTranslate(mTranslate.toFloat(), 0f)
this.mLinearGradient?.setLocalMatrix(mGradientMatrix)
}
log()
}
/**
* 关闭流光效果
*/
fun stop() {
isAnimating = false
}
fun log(){
DebugLog.i("Shimmer","content:$content mViewWidth:$mViewWidth isAnimating:$isAnimating :mTranslate:$mTranslate mWidthDivideBy:$mWidthDivideBy colors:${colors.toList()} positions:${positions.toList()}")
}
fun getContent()=content
}
- 使用
private val shimmerList = ArrayList<Shimmer>()
----------------------------------------------
shimmerList.add(new Shimmer("你好呀!")) ;
shimmerList.add(new Shimmer("欢迎你哈啊阿达!")) ;
shimmerList.get(0).setMWidthDivideBy(10);
shimmerList.get(1).setMWidthDivideBy(10);
shimmerList.get(1).setLinearGradientColors(new int[]{0xFF4DDA11, 0xffffffff, 0xFF4DDA11});
shimmerList.get(0).init();
shimmerList.get(1).init();
----------------------------------------------
canvas.drawText(shimmerList.get(0).getContent(), 200, 600, shimmerList.get(0).getMPaint());
扩展
- Shader知识点