Android 自定义TextView实现文字渐变动画

来源:互联网 发布:c语言从入门到放弃图片 编辑:程序博客网 时间:2024/05/17 20:25

先来看效果

第一种效果的代码如下,主要是结合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);    }  }}


注意:

  1. 文本绘制时必须和当前View保持同样的长宽尺寸,否则会出现文字变形问题

  2. 文本绘制的drawText(string,int x,int y,Paint paint);中的y值是基线位置

  3. mTextHeight = fontMetrics.bottom-fontMetrics.descent-fontMetrics.ascent;//获得文本的高度
  4. 注意内容去的尺寸大小以及图片合成模式

  5. 注意LinearGradient的最后一个参数

  6. 自己去试试吧,我这些代码不够完善。

来自: http://my.oschina.net/ososchina/blog/603274

0 0