先来看效果
第一种效果的代码如下,主要是结合Shader实现的
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.util.Log;
import android.widget.TextView;
public class GradientShaderTextView extends TextView {
private LinearGradient mLinearGradient;
private Matrix mGradientMatrix;
private Paint mPaint;
private int mViewWidth = 0;
private int mTranslate = 0;
private boolean mAnimating = true;
private int delta = 15;
public GradientShaderTextView(Context ctx)
{
this(ctx,null);
}
public GradientShaderTextView(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);
if (mViewWidth == 0) {
mViewWidth = getMeasuredWidth();
if (mViewWidth > 0) {
mPaint = getPaint();
String text = getText().toString();
// float textWidth = mPaint.measureText(text);
int size;
if(text.length()>0)
{
size = mViewWidth*2/text.length();
}else{
size = mViewWidth;
}
mLinearGradient = new LinearGradient(-size, 0, 0, 0,
new int[] { 0x33ffffff, 0xffffffff, 0x33ffffff },
new float[] { 0, 0.5f, 1 }, Shader.TileMode.CLAMP); //边缘融合
mPaint.setShader(mLinearGradient);
mGradientMatrix = new Matrix();
}
}
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int length = Math.max(length(), 1);
if (mAnimating && mGradientMatrix != null) {
float mTextWidth = getPaint().measureText(getText().toString());
mTranslate += delta;
if (mTranslate > mTextWidth+1 || mTranslate<1) {
delta = -delta;
}
mGradientMatrix.setTranslate(mTranslate, 0);
mLinearGradient.setLocalMatrix(mGradientMatrix);
postInvalidateDelayed(30);
}
}
}
第二种效果
import android.animation.ObjectAnimator;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.drawable.BitmapDrawable;
import android.util.AttributeSet;
import android.view.ActionMode;
import android.view.View;
import android.widget.TextView;
public class KTVTextView extends View {
private Paint mPaint;
private int delta = 15;
private float mTextHeight;
private float mTextWidth;
private PorterDuffXfermode xformode;
private String mText = "你是我生命里的一首歌";
public KTVTextView(Context ctx)
{
this(ctx,null);
}
public KTVTextView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public KTVTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
xformode = new PorterDuffXfermode(PorterDuff.Mode.SRC_IN);
initViewAndDatas();
setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
postIndex = 0;
postInvalidate();
}
});
}
public void initViewAndDatas()
{
mPaint.setColor(Color.CYAN);
mPaint.setTextSize(40.0f);
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
mPaint.setXfermode(null);
mPaint.setTextAlign(Paint.Align.LEFT);
Paint.FontMetrics fontMetrics = mPaint.getFontMetrics();
mTextHeight = fontMetrics.bottom-fontMetrics.descent-fontMetrics.ascent;
mTextWidth = mPaint.measureText(mText);
//文字精确高度
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int mWidth;
int mHeight;
/**
* 设置宽度
*/
int specMode = MeasureSpec.getMode(widthMeasureSpec);
int specSize = MeasureSpec.getSize(widthMeasureSpec);
if (specMode == MeasureSpec.EXACTLY)// match_parent , accurate
{
mWidth = specSize;
}
else
{
// 由图片决定的宽
int desireByImg = getPaddingLeft() + getPaddingRight()
+ 380;
if (specMode == MeasureSpec.AT_MOST)// wrap_content
{
mWidth = Math.min(desireByImg, specSize);
} else
mWidth = desireByImg;
}
/***
* 设置高度
*/
specMode = MeasureSpec.getMode(heightMeasureSpec);
specSize = MeasureSpec.getSize(heightMeasureSpec);
if (specMode == MeasureSpec.EXACTLY)// match_parent , accurate
{
mHeight = specSize;
} else
{
int desire = getPaddingTop() + getPaddingBottom()
+ 80;
if (specMode == MeasureSpec.AT_MOST)// wrap_content
{
mHeight = Math.min(desire, specSize);
} else
{
mHeight = desire;
}
}
setMeasuredDimension((int) mWidth, (int) mHeight);
}
private int postIndex;
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int contentWidth = getWidth() - getPaddingLeft() - getPaddingRight();
int contentHeight = getHeight() - getPaddingTop() - getPaddingBottom();
Bitmap srcBitmap = Bitmap.createBitmap(getWidth(),getHeight(), Bitmap.Config.ARGB_8888);
Canvas srcCanvas = new Canvas(srcBitmap);
srcCanvas.drawText(mText, 0, getPaddingTop(), mPaint);
mPaint.setXfermode(xformode);
mPaint.setColor(Color.RED);
RectF rectF = new RectF(0,0,postIndex,mTextHeight);
srcCanvas.drawRect(rectF, mPaint);
canvas.drawBitmap(srcBitmap,getPaddingLeft(),getPaddingTop(), null);
initViewAndDatas();
if(postIndex<mTextWidth)
{
postIndex+=10;
postInvalidateDelayed(30);
}
}
}
注意:
- 文本绘制时必须和当前View保持同样的长宽尺寸,否则会出现文字变形问题
- 文本绘制的drawText(string,int x,int y,Paint paint);中的y值是基线位置
mTextHeight = fontMetrics.bottom-fontMetrics.descent-fontMetrics.ascent;//获得文本的高度
- 注意内容去的尺寸大小以及图片合成模式
- 注意LinearGradient的最后一个参数
- 自己去试试吧,我这些代码不够完善。