我正在尝试将 textView 中的 3 个“爆炸”文本动画链接在一起,以依次显示 3 个单词:“Ready”、“Set”和“Go!”。通过“爆炸”,我的意思是文本大小从默认的 0.25f 到默认的 1.00f,而 alpha=0 到 alpha=1。
问题:我能够按预期将第一个单词“Ready”变为“explode”,但下一个单词“Set”没有“explode”,即根本不改变文本大小(只有动画的 alpha 部分有效)。
我的 MainActivity.java 如下。我没有进行第三次“爆炸”,因为如果我能让第二次爆炸,那就是复制和粘贴的问题。
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.util.TypedValue;
import android.view.View;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
public void actionExplode(View view) {
// .setTextSize() defaults to sp but .getTextSize() defaults to px http://stackoverflow.com/a/3687385/1827488
String textReady = "Ready";
final String textSet = "Set";
final String textGo = "Go!";
final TextView questionDisplay = (TextView) findViewById(R.id.textView);
final float textSizePx = questionDisplay.getTextSize();
Log.i("actionExplode", "textSizePx=" + textSizePx);
final float scaleSmall = 0.25f;
float scaleFull = 1.0f;
final float fadeOut = 0f;
float fadeIn = 1f;
questionDisplay.setAlpha(fadeOut);
questionDisplay.setText(textReady);
questionDisplay.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSizePx * scaleSmall);
Log.i("actionExplode", ".getTextSize()=" + questionDisplay.getTextSize());
int animateDurationReadySetGo = 1000;
int animateDurationFudge = 100;
ObjectAnimator animateReadyFadeIn = ObjectAnimator.ofFloat(questionDisplay, "alpha", fadeOut, fadeIn);
animateReadyFadeIn.setDuration(animateDurationReadySetGo);
ObjectAnimator animateReadyX = ObjectAnimator.ofFloat(questionDisplay, "scaleX", scaleFull/scaleSmall);
animateReadyX.setDuration(animateDurationReadySetGo);
ObjectAnimator animateReadyY = ObjectAnimator.ofFloat(questionDisplay, "scaleY", scaleFull/scaleSmall);
animateReadyY.setDuration(animateDurationReadySetGo /* + animateDurationFudge */ );
animateReadyY.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
Log.i("onAnimationEnd", "before .getTextSize()=" + questionDisplay.getTextSize());
//questionDisplay.setAlpha(fadeOut);
questionDisplay.setText(textSet);
questionDisplay.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSizePx * scaleSmall);
Log.i("onAnimationEnd", "after .getTextSize()=" + questionDisplay.getTextSize());
}
});
ObjectAnimator animateSetFadeIn = ObjectAnimator.ofFloat(questionDisplay, "alpha", fadeOut, fadeIn);
animateSetFadeIn.setDuration(animateDurationReadySetGo);
ObjectAnimator animateSetX = ObjectAnimator.ofFloat(questionDisplay, "scaleX", scaleFull/scaleSmall);
animateSetX.setDuration(animateDurationReadySetGo);
ObjectAnimator animateSetY = ObjectAnimator.ofFloat(questionDisplay, "scaleY", scaleFull/scaleSmall);
animateSetY.setDuration(animateDurationReadySetGo /* + animateDurationFudge */ );
animateSetY.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
Log.i("onAnimationEnd", "before .getTextSize()=" + questionDisplay.getTextSize());
//questionDisplay.setAlpha(fadeOut);
questionDisplay.setText(textGo);
questionDisplay.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSizePx * scaleSmall);
Log.i("onAnimationEnd", "after .getTextSize()=" + questionDisplay.getTextSize());
}
});
AnimatorSet animateReadySetGo = new AnimatorSet();
animateReadySetGo.playTogether(animateReadyX, animateReadyY, animateReadyFadeIn);
animateReadySetGo.playTogether(animateSetX, animateSetY, animateSetFadeIn);
animateReadySetGo.playSequentially(animateReadyY, animateSetY);
animateReadySetGo.start();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
这就是日志显示的内容。没有意义的是:1)为什么“之前”行显示 43.75 而应该显示 175.0?和 2)为什么“之后”行显示 43.75 但文本大小不缩小?
I/actionExplode: textSizePx=175.0
I/actionExplode: .getTextSize()=43.75
I/onAnimationEnd: before .getTextSize()=43.75
I/onAnimationEnd: after .getTextSize()=43.75
I/onAnimationEnd: before .getTextSize()=43.75
I/onAnimationEnd: after .getTextSize()=43.75
我的activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.plaudev.explodingtext.MainActivity">
<TextView
android:layout_width="match_parent"
android:layout_height="100dp"
android:text="@string/textView"
android:id="@+id/textView"
android:fontFamily="casual"
android:textSize="50sp"
android:textStyle="normal|bold"
android:textAlignment="center"
android:gravity="center" />
<Button
android:text="@string/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/textView"
android:layout_centerHorizontal="true"
android:layout_marginTop="50dp"
android:id="@+id/button"
android:background="@color/colourTransparent"
android:textAllCaps="false"
android:textSize="25sp"
android:textStyle="normal|bold"
android:fontFamily="casual"
android:onClick="actionExplode"
android:textColor="@android:color/holo_green_dark" />
</RelativeLayout>
更新 1:仍未找到解决方案,但想注意此行为。如果我重写actionExplode()
为递归运行并使用其他东西作为 onClick 来启动,所以我的 MainActivity 类如下,那么我可以获得 3 个“爆炸”链,但每个都从一个连续较小的文本大小开始,如图所示下面的附加日志。似乎通过制作插座questionDisplay
final
以便听众或计时器可以使用它来链接动画以某种方式导致插座保留文本大小,即使我仍然可以更改其文本(即仅选择性地final
)。因此,我也尝试了一些变体(如代码注释中所述),但没有一个比变体 A 更接近预期的行为。
public class MainActivity extends AppCompatActivity {
String[] explosionChain = {"Ready", "Set", "Go!"};
int explosionIndex = 0;
int animateDurationExplosion = 1000;
int animateDurationFudge = 100;
public void actionExplode(final float textSizeFullPx, final int explosionIndex) {
final TextView questionDisplay = (TextView) findViewById(R.id.textView);
float textSizePx = questionDisplay.getTextSize();
Log.i("actionExplode", "textSizeFullPx=" + textSizeFullPx + ", explosionIndex=" + explosionIndex + ", textSizePx=" + textSizePx);
float scaleSmall = 0.25f;
float scaleFull = 1.0f;
float fadeOut = 0f;
float fadeIn = 1f;
questionDisplay.setAlpha(fadeOut);
questionDisplay.setText(explosionChain[explosionIndex]);
// variation A
//questionDisplay.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSizeFullPx * scaleSmall);
// variation B
questionDisplay.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSizePx * scaleSmall);
Log.i("actionExplode", ".getTextSize()=" + questionDisplay.getTextSize());
ObjectAnimator animateFadeIn = ObjectAnimator.ofFloat(questionDisplay, "alpha", fadeOut, fadeIn);
animateFadeIn.setDuration(animateDurationExplosion);
ObjectAnimator animateScaleX = ObjectAnimator.ofFloat(questionDisplay, "scaleX", scaleFull/scaleSmall);
animateScaleX.setDuration(animateDurationExplosion);
ObjectAnimator animateScaleY = ObjectAnimator.ofFloat(questionDisplay, "scaleY", scaleFull/scaleSmall);
animateScaleY.setDuration(animateDurationExplosion /* + animateDurationFudge */ );
AnimatorSet animateExplosion = new AnimatorSet();
animateExplosion.playTogether(animateScaleX, animateScaleY, animateFadeIn);
animateExplosion.start();
CountDownTimer explodeNext = new CountDownTimer(animateDurationExplosion, animateDurationExplosion) {
@Override
public void onTick(long millisUntilFinished) {
}
@Override
public void onFinish() {
// variation C
Log.i("onFinish", ".getTextSize()=" + questionDisplay.getTextSize());
// variation D
//Log.i("onFinish", "before .getTextSize()=" + questionDisplay.getTextSize());
//questionDisplay.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSizeFullPx);
//Log.i("onFinish", "after .getTextSize()=" + questionDisplay.getTextSize());
if ((explosionIndex + 1) < explosionChain.length) {
actionExplode(textSizeFullPx, explosionIndex + 1);
}
}
};
explodeNext.start();
}
public void startChainExplosion(View view) {
final TextView questionDisplay = (TextView) findViewById(R.id.textView);
final float textSizeFullPx = questionDisplay.getTextSize();
Log.i("startChainExplosion", "explosionIndex=" + explosionIndex + ", textSizeFullPx=" + textSizeFullPx);
actionExplode(textSizeFullPx, explosionIndex);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
上面更新的代码产生了这个日志:
I/startChainExplosion: explosionIndex=0, textSizeFullPx=175.0
I/actionExplode: textSizeFullPx=175.0, explosionIndex=0, textSizePx=175.0
I/actionExplode: .getTextSize()=43.75
I/onFinish: .getTextSize()=43.75
I/actionExplode: textSizeFullPx=175.0, explosionIndex=1, textSizePx=43.75
I/actionExplode: .getTextSize()=10.9375
I/onFinish: .getTextSize()=10.9375
I/actionExplode: textSizeFullPx=175.0, explosionIndex=2, textSizePx=10.9375
I/actionExplode: .getTextSize()=2.734375
I/onFinish: .getTextSize()=2.734375
更新 2:按照@Xaver 的建议,尝试将其用作 onClick。但结果与我最初的尝试相同,即“Ready”爆炸但“Set”和“Go!” 不。此外,在所有动画完成后,文本大小变得非常大(我猜是 175px * 4)。更新代码和日志如下。我有一种感觉,我需要每个单词都有自己的 textView 以避免这个文本大小保留问题。
public void explodeSequentially(View view) {
String textReady = "Ready";
final String textSet = "Set";
final String textGo = "Go!";
final TextView questionDisplay = (TextView) findViewById(R.id.textView);
float textSizePx = questionDisplay.getTextSize();
Log.i("explodeSequentially", "textSizePx=" + textSizePx);
float scaleSmall = 0.25f;
float scaleFull = 1.0f;
float fadeOut = 0f;
float fadeIn = 1f;
questionDisplay.setAlpha(fadeOut);
questionDisplay.setText(textReady);
questionDisplay.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSizePx * scaleSmall);
Log.i("explodeSequentially", ".getTextSize()=" + questionDisplay.getTextSize());
ObjectAnimator animateReadyFadeIn = ObjectAnimator.ofFloat(questionDisplay, "alpha", fadeOut, fadeIn);
animateReadyFadeIn.setDuration(animateDurationExplosion);
ObjectAnimator animateReadyX = ObjectAnimator.ofFloat(questionDisplay, "scaleX", scaleFull/scaleSmall);
animateReadyX.setDuration(animateDurationExplosion);
ObjectAnimator animateReadyY = ObjectAnimator.ofFloat(questionDisplay, "scaleY", scaleFull/scaleSmall);
animateReadyY.setDuration(animateDurationExplosion /* + animateDurationFudge */ );
animateReadyY.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
Log.i("onAnimationEnd", "before .getTextSize()=" + questionDisplay.getTextSize());
//questionDisplay.setAlpha(fadeOut);
questionDisplay.setText(textSet);
//questionDisplay.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSizePx * scaleSmall);
//Log.i("onAnimationEnd", "after .getTextSize()=" + questionDisplay.getTextSize());
}
});
AnimatorSet animateReady = new AnimatorSet();
animateReady.playTogether(animateReadyX, animateReadyY, animateReadyFadeIn);
ObjectAnimator animateSetFadeIn = ObjectAnimator.ofFloat(questionDisplay, "alpha", fadeOut, fadeIn);
animateSetFadeIn.setDuration(animateDurationExplosion);
ObjectAnimator animateSetX = ObjectAnimator.ofFloat(questionDisplay, "scaleX", scaleFull/scaleSmall);
animateSetX.setDuration(animateDurationExplosion);
ObjectAnimator animateSetY = ObjectAnimator.ofFloat(questionDisplay, "scaleY", scaleFull/scaleSmall);
animateSetY.setDuration(animateDurationExplosion /* + animateDurationFudge */ );
animateSetY.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
Log.i("onAnimationEnd", "before .getTextSize()=" + questionDisplay.getTextSize());
//questionDisplay.setAlpha(fadeOut);
questionDisplay.setText(textGo);
//questionDisplay.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSizePx * scaleSmall);
//Log.i("onAnimationEnd", "after .getTextSize()=" + questionDisplay.getTextSize());
}
});
AnimatorSet animateSet = new AnimatorSet();
animateSet.playTogether(animateSetX, animateSetY, animateSetFadeIn);
ObjectAnimator animateGoFadeIn = ObjectAnimator.ofFloat(questionDisplay, "alpha", fadeOut, fadeIn);
animateGoFadeIn.setDuration(animateDurationExplosion);
ObjectAnimator animateGoX = ObjectAnimator.ofFloat(questionDisplay, "scaleX", scaleFull/scaleSmall);
animateGoX.setDuration(animateDurationExplosion);
ObjectAnimator animateGoY = ObjectAnimator.ofFloat(questionDisplay, "scaleY", scaleFull/scaleSmall);
animateGoY.setDuration(animateDurationExplosion /* + animateDurationFudge */ );
animateGoY.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
Log.i("onAnimationEnd", "before .getTextSize()=" + questionDisplay.getTextSize());
//questionDisplay.setAlpha(fadeOut);
questionDisplay.setText("Here is the question!");
//questionDisplay.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSizePx * scaleSmall);
//Log.i("onAnimationEnd", "after .getTextSize()=" + questionDisplay.getTextSize());
}
});
AnimatorSet animateGo = new AnimatorSet();
animateGo.playTogether(animateGoX, animateGoY, animateGoFadeIn);
AnimatorSet animateReadySetGo = new AnimatorSet();
animateReadySetGo.playSequentially(animateReady, animateSet, animateGo);
animateReadySetGo.start();
}
和日志
I/explodeSequentially: textSizePx=175.0
I/explodeSequentially: .getTextSize()=43.75
I/onAnimationEnd: before .getTextSize()=43.75
I/onAnimationEnd: before .getTextSize()=43.75
I/onAnimationEnd: before .getTextSize()=43.75