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

前言

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实现逐字动画的全部内容,实现后效果还是很赞的,感兴趣的小伙伴们自己动手实践起来吧。如果有疑问可以留言讨论。

(0)

相关推荐

  • 基于Android中的 AutoCompleteTextView实现自动填充

    现在我们上网会用百度或者谷歌搜索信息,当我们在输入框里输入一两个字后,就会自动提示我们想要的信息,这种效果在Android 是通过Android 的AutoCompleteTextView Widget 搭配ArrayAdapter 设计同类似Google 搜索提示的效果. 先在Layout 当中布局一个AutoCompleteTextView Widget ,然后通过预先设置好的字符串数组,将此字符串数组放入ArrayAdapter ,最后利用AutoCompleteTextView.setA

  • Android TextView实现垂直滚动效果的方法

    本文实例讲述了Android TextView实现垂直滚动效果的方法.分享给大家供大家参考,具体如下: 在TextView中,如果文本很长,可能需要实现垂直滚动显示文本的效果.这里需要在XML布局文件中为TextView设置如下几个属性. Android:scrollbars="vertical" android:scrollbarStyle="X" 其中X为outsideOverlay或insideOverlay. android:scrollbarFadeDur

  • Android编程实现TextView垂直自动滚动功能【附demo源码下载】

    本文实例讲述了Android编程实现TextView垂直自动滚动功能.分享给大家供大家参考,具体如下: 在做android 应用的开发的时候,横向滚动或者要做出跑马灯的效果很简单,textview本身的属性就支持,只要设置准确就会滚动,开发起来比较简单,但是textview 不支持垂直滚动,那么垂直滚动就需要自己来实现了,很多网友提供的垂直滚 动方案都是千篇一律,使用ScrollView来进行滚动,但是都不完美,做起来有些别扭.有一位网友给出的歌词的滚动思路明确,能从根本上解决问题,因此我实现的

  • Android AutoCompleteTextView连接数据库自动提示的方法(附demo源码下载)

    本文实例讲述了Android AutoCompleteTextView连接数据库自动提示的方法.分享给大家供大家参考,具体如下: 这个简单例子也体现MVC的思想.AutoCompleteTextView 就是View,而SimpleCursorAdapter就是Controller,SQLiteOpenHelper就相当于Model. 1.首先定义MVC中的Model,自定义DBHelper类继承SQLiteOpenHelper用于访问数据库 import android.content.Con

  • Android实现在TextView文字过长时省略部分或滚动显示的方法

    本文实例讲述了Android实现在TextView文字过长时省略部分或滚动显示的方法.分享给大家供大家参考,具体如下: TextView中有个ellipsize属性,作用是当文字过长时,该控件该如何显示,解释如下: 1.android:ellipsize="start"-–省略号显示在开头 2.android:ellipsize="end"--省略号显示在结尾 3.android:ellipsize="middle"--省略号显示在中间 4.an

  • android动态布局之动态加入TextView和ListView的方法

    本文实例讲述了android动态布局之动态加入TextView和ListView的方法.分享给大家供大家参考.具体实现方法如下: package org.guoshi; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.guoshi.adapter.ImageAndTextAdapter; import android.app.

  • Android开发技巧之在a标签或TextView控件中单击链接弹出Activity(自定义动作)

    在5.2.1节和5.2.2节介绍了<a>标签以及TextView自动识别的特殊文本(网址.电话号.Email等),这些都可以通过单击来触发不同的动作.虽然这些单击动作已经可以满足大多数需要了,但如果读者想在单击链接时执行任意自定义的动作,那么本节的内容非看不可. 现在让我们使用5.2.1节介绍的方法重新查看Html.java文件的内容,随便找一个处理Html标签的方法,例 如,endA方法.该方法用于处理</a>标签.我们会发现在该方法中如下的语句. text.setSpan(ne

  • android实现上下滚动的TextView

    一 说明    这里重要应用类 AutoTextView,这是一个自定义的类,继承至TextSwitcher,下面临 AutoTextView类做简要说明: 1. 该类应用的重点,在于设置两个动画, setInAnimation(...)  和 setOutAnimation(...),分离是文字进入的动画和文字退出的动画: 2. 类中定义了一个外部类-Rotate3dAnimation,重要靠该类实现文字进出动画,该外部类继承至Animation.说来偶合,这个恰好是在apiDemo中看到了,

  • Android开发:TextView加入滚动条示例

    利用scrollview来实现,效果会好很多 复制代码 代码如下: <ScrollView android:id="@+id/scrollView1" android:layout_width="match_parent" android:layout_height="150dp" android:fadingEdge="vertical" android:scrollbars="vertical"

  • android TextView不用ScrollViewe也可以滚动的方法

    代码 复制代码 代码如下: TextView textview = (TextView) findViewById(R.id.text);            /**             *              * 只有调用了该方法,TextView才能不依赖于ScrollView而实现滚动的效果.             * 要在XML中设置TextView的textcolor,否则,当TextView被触摸时,会灰掉.             */ textview.setMov

  • Android编程实现自动调整TextView字体大小以适应文字长度的方法

    本文实例讲述了Android编程实现自动调整TextView字体大小以适应文字长度的方法.分享给大家供大家参考,具体如下: package com.test.android.textview; import android.content.Context; import android.graphics.Paint; import android.util.AttributeSet; import android.widget.TextView; public class CustomTextV

随机推荐