zl程序教程

您现在的位置是:首页 >  移动开发

当前栏目

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

Android动画 实现 自定义 文字 渐变 textview
2023-09-27 14:27:46 时间

先来看效果

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