文档章节

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

IamOkay
 IamOkay
发布于 2016/01/15 15:57
字数 649
阅读 6301
收藏 44

先来看效果

第一种效果的代码如下,主要是结合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. 自己去试试吧,我这些代码不够完善。

© 著作权归作者所有

IamOkay

IamOkay

粉丝 198
博文 483
码字总数 403041
作品 0
海淀
程序员
私信 提问
加载中

评论(2)

l
linsea
facebook shimmer
johnchain_li
johnchain_li
QQQ
ShimmerTextView

本文来自网易云社区 作者:孙有军 产品中有一个需求,要求TextView的文字有一个高亮的效果,高亮的同时有跑马灯效果! 本来想在网上找一个现成的用用,比如Facebook出的Shimmer,还有很多,但...

网易云
2018/09/27
0
0
玩转Android 之 TextView常用特效

暑期大学生博客分享大赛 - 2011 Android 成长篇 本文参加第二届Google大学生暑期博客分享大赛 TextView是最常用的Android控件之一,显示文字时的首选,然而很多人都不满足于,TextView默认的...

cokey
2011/08/06
0
3
android实例源码,渐变图像图片浏览高仿美团!

渐变颜色渐变文字渐变图像GradualshowcolorAndResourse 根据图片高度动态变化的ViewPager android Kotlin开发的一款超简单的图片浏览源码 android多种reveal动画效果 栗子——高仿美团首页分...

莫非有道
2017/11/08
0
0
Android学习之Textview的一些属性解释

delia 动态改变控件的方法 1.声明控件参数获取的对象 LinearLayout.LayoutParams linear = (LayoutParams) view.getLayoutParams(); 2.设置控件参数,如宽度: linear.width = 10; 3.使得设...

程序袁_绪龙
2014/09/25
0
0
Android TextView文字横向自动滚动(跑马灯)

转自: http://blog.csdn.net/muyu114/article/details/6400563 TextView实现文字滚动需要以下几个要点: 1.文字长度长于可显示范围:android:singleLine="true" 2.设置可滚到,或显示样式:...

长平狐
2012/08/28
989
1

没有更多内容

加载失败,请刷新页面

加载更多

老也有错?35岁程序员是一道坎,横亘在每个技术职场人的心中

随着互联网的高速发展变革,大龄恐惧症越来越多地在技术圈被人讨论。很多程序员在工作5-10年以后,都会开始思考5年、10年甚至更久以后的自己,会是怎样一种生活工作状态,以及是否会被时代抛...

我最喜欢三大框架
35分钟前
2
0
今日头条算法原理详解全集,值得收藏!

今天,算法分发已经是信息平台、搜索引擎、浏览器、社交软件等几乎所有软件的标配,但同时,算法也开始面临质疑、挑战和误解。今日头条的推荐算法,从 2012 年 9月第一版开发运行至今,已经经...

骚年锦时
47分钟前
4
0
零拷贝:用户态视角

在Linux系统越来越多的人听说过所谓的零拷贝技术,但是我经常遇到很多对这个名词没有完全理解的人。因此,我决定写一些文章,深挖这个问题,希望能揭开这个有用的特性。在这篇文章,我们从用...

凌渡
59分钟前
1
0
以太坊中文文档翻译-区块

本文原文链接 点击这里获取Etherscan API 中文文档(完整版) 完整内容排版更好,推荐读者前往阅读。 区块(Blocks) 区块相关的 API,接口的参数说明请参考Etherscan API 约定, 文档中不单独...

Tiny熊
今天
2
0
Linux 内核的一个问题

是virtio 驱动,但是没有启动 virtio-mmio virtio-mmio.0: Failed to enable 64-bit or 32-bit DMA. Trying to continue, but this might not work.....[ 1.047924] md: ... autorun......

MtrS
今天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部