欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

利用Android中的TextView实现逐字显示动画

程序员文章站 2024-03-06 14:12:14
前言 android的textview只能设置整个textview的动画,而不能设置每个文字的动画。即使是使用textswitcher,也很难实现我想要的效果。 &nb...

前言

android的textview只能设置整个textview的动画,而不能设置每个文字的动画。即使是使用textswitcher,也很难实现我想要的效果。
 

所以选择自定义一个。大体思路是:继承viewgroup,设置text的时候,每个文字为一个textview,每隔一个固定时间,启动每个textview的动画。

 定义一个ctextview,继承viewgroup:

实现主要代码:

public class ctextview extends viewgroup { 
} 

向外提供一个方法settext(string text, final animation animation, int duration),text为要显示的字符串,animation为每个字符的动画,duration为字符动画的播放间隔。

该方法实现如下:

public void settext(string text, final animation animation, int duration) { 
  int time = 0; 
  if(text != null && !text.isempty()) { 
    char[] characters = text.tochararray(); 
    for(char c : characters) { 
      final textview t = new textview(context); 
      //遍历传入的字符串的每个字符,生成一个textview,并设置它的动画 
      t.settext(string.valueof(c)); 
      t.settextsize(28); 
      handler h = new handler(); 
      //每隔duration时间,播放下一个textview的动画 
      h.postdelayed(new runnable() { 
        @override 
        public void run() { 
          addview(t); 
          t.setanimation(animation); 
        } 
      }, time); 
 
      time += duration; 
 
    } 
  } 
} 

ctextview完整实现如下:

import android.content.context; 
import android.os.handler; 
import android.util.attributeset; 
import android.view.view; 
import android.view.viewgroup; 
import android.view.animation.animation; 
import android.widget.textview; 
 
/** 
 * created by cchen on 2014/9/2. 
 */ 
public class ctextview extends viewgroup { 
  private context context; 
 
  public ctextview(context context) { 
    super(context); 
    this.context = context; 
  } 
 
  public ctextview(context context, attributeset attrs) { 
    super(context, attrs); 
    this.context = context; 
  } 
 
  public ctextview(context context, attributeset attrs, int defstyle) { 
    super(context, attrs, defstyle); 
    this.context = context; 
  } 
 
  public void settext(string text, final animation animation, int duration) { 
    int time = 0; 
    if(text != null && !text.isempty()) { 
      char[] characters = text.tochararray(); 
      for(char c : characters) { 
        final textview t = new textview(context); 
        //遍历传入的字符串的每个字符,生成一个textview,并设置它的动画 
        t.settext(string.valueof(c)); 
        t.settextsize(28); 
        handler h = new handler(); 
        //每隔duration时间,播放下一个textview的动画 
        h.postdelayed(new runnable() { 
          @override 
          public void run() { 
            addview(t); 
            t.setanimation(animation); 
          } 
        }, time); 
 
        time += duration; 
 
      } 
    } 
  } 
 
  @override 
  protected void onmeasure(int widthmeasurespec, int heightmeasurespec) { 
    int measurewidth = measurewidth(widthmeasurespec); 
    int measureheight = measureheight(heightmeasurespec); 
    // 计算自定义的viewgroup中所有子控件的大小 
    measurechildren(widthmeasurespec, heightmeasurespec); 
    // 设置自定义的控件myviewgroup的大小 
    setmeasureddimension(measurewidth, measureheight); 
  } 
 
  @override 
  protected void onlayout(boolean changed, int l, int t, int r, int b) { 
    int childleft = 0; 
    // 遍历所有子视图 
    int childcount = getchildcount(); 
    for (int i = 0; i < childcount; i++) { 
      view childview = getchildat(i); 
 
      // 获取在onmeasure中计算的视图尺寸 
      int measureheight = childview.getmeasuredheight(); 
      int measuredwidth = childview.getmeasuredwidth(); 
 
      //将他们横向排列 
      childview.layout(childleft, 0, childleft + measuredwidth, measureheight); 
 
      childleft += measuredwidth; 
    } 
  } 
 
  private int measurewidth(int pwidthmeasurespec) { 
    int result = 0; 
    int widthmode = measurespec.getmode(pwidthmeasurespec);// 得到模式 
    int widthsize = measurespec.getsize(pwidthmeasurespec);// 得到尺寸 
 
    switch (widthmode) { 
      /** 
       * mode共有三种情况,取值分别为measurespec.unspecified, measurespec.exactly, 
       * measurespec.at_most。 
       * 
       * 
       * measurespec.exactly是精确尺寸, 
       * 当我们将控件的layout_width或layout_height指定为具体数值时如andorid 
       * :layout_width="50dip",或者为fill_parent是,都是控件大小已经确定的情况,都是精确尺寸。 
       * 
       * 
       * measurespec.at_most是最大尺寸, 
       * 当控件的layout_width或layout_height指定为wrap_content时 
       * ,控件大小一般随着控件的子空间或内容进行变化,此时控件尺寸只要不超过父控件允许的最大尺寸即可 
       * 。因此,此时的mode是at_most,size给出了父控件允许的最大尺寸。 
       * 
       * 
       * measurespec.unspecified是未指定尺寸,这种情况不多,一般都是父控件是adapterview, 
       * 通过measure方法传入的模式。 
       */ 
      case measurespec.at_most: 
      case measurespec.exactly: 
        result = widthsize; 
        break; 
    } 
    return result; 
  } 
 
  private int measureheight(int pheightmeasurespec) { 
    int result = 0; 
 
    int heightmode = measurespec.getmode(pheightmeasurespec); 
    int heightsize = measurespec.getsize(pheightmeasurespec); 
 
    switch (heightmode) { 
      case measurespec.at_most: 
      case measurespec.exactly: 
        result = heightsize; 
        break; 
    } 
    return result; 
  } 
} 

然后在布局文件中使用该自定义组件:

<linearlayout xmlns:android="http://schemas.android.com/apk/res/android" 
  xmlns:tools="http://schemas.android.com/tools" 
  android:layout_width="match_parent" 
  android:layout_height="match_parent" 
  android:orientation="vertical" 
  tools:context=".networktestactivity"> 
 
  <com.network.cchen.network.ctextview 
    android:id="@+id/ctextview" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent"> 
  </com.network.cchen.network.ctextview> 
 
</linearlayout> 

在activity中,调用ctextview的settext方法,传入相关参数即可:

import android.app.activity; 
import android.os.bundle; 
import android.view.animation.animationutils; 
 
public class testactivity extends activity { 
 
  @override 
  public void oncreate(bundle savedinstancestate) { 
    super.oncreate(savedinstancestate); 
 
    setcontentview(r.layout.activity_network_test); 
 
    ctextview ctextview = (ctextview) findviewbyid(r.id.ctextview); 
    ctextview.settext("hello world", animationutils.loadanimation(this, r.anim.myanim), 300); 
  } 
} 

其中的第二个参数为动画,我想要的效果是从透明到不透明,myanim.xml:

<?xml version="1.0" encoding="utf-8"?> 
<set xmlns:android="http://schemas.android.com/apk/res/android"> 
  <alpha 
    android:duration="1000" 
    android:fromalpha="0.0" 
    android:toalpha="1.0" /> 
</set>  

如果想实现文字逐个从右侧飞入:

<?xml version="1.0" encoding="utf-8"?> 
<set xmlns:android="http://schemas.android.com/apk/res/android"> 
  <translate 
    android:duration="1000" 
    android:fillafter="true" 
    android:fromxdelta="50%p" 
    android:interpolator="@android:anim/anticipate_interpolator" 
    android:toxdelta="0" /> 
</set> 

总结

以上就是利用android中的textview实现逐字动画的全部内容,实现后效果还是很赞的,感兴趣的小伙伴们自己动手实践起来吧。如果有疑问可以留言讨论。