前言
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;
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) {
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实现逐字动画的全部内容,实现后效果还是很赞的,感兴趣的小伙伴们自己动手实践起来吧。如果有疑问可以留言讨论。
您可能感兴趣的文章:android实现上下滚动的TextViewandroid TextView不用ScrollViewe也可以滚动的方法Android编程实现自动调整TextView字体大小以适应文字长度的方法Android开发技巧之在a标签或TextView控件中单击链接弹出Activity(自定义动作)Android开发:TextView加入滚动条示例android动态布局之动态加入TextView和ListView的方法基于Android中的 AutoCompleteTextView实现自动填充Android AutoCompleteTextView连接数据库自动提示的方法(附demo源码下载)Android编程实现TextView部分颜色变动的方法Android实现在TextView文字过长时省略部分或滚动显示的方法Android TextView实现垂直滚动效果的方法Android编程实现TextView垂直自动滚动功能【附demo源码下载】