我有5个TextView字段,用于显示字符串并每10秒更改一次文本。 为了进行更改,我有一个AsyncTask,它抓取接下来的5条消息(doInBackground)并将它们传递给onPostExecute以显示在UI中。
当我在没有动画的情况下显示消息时,一切都运行得很好,消息每隔10秒就会通过一个新的AsyncTask旋转。 现在,当我尝试在TextViews上使用简单的淡入/淡出动画时,我可以看到所有这些都淡出然后用占位符字符串返回,但是我要显示的实际文本消息只显示在最后一个TextView的。
AsyncTask是我的MainActivity.java的内部类。 我在MainActivity.java中实现了一个AnimationListener,由于onPostExecute((TextView)mNextTextView & (String)mNextMessageToDisplay )中的对象也被声明为全局变量在主要班级。
这是AsyncTask的onPostExecute:
protected void onPostExecute(List<String> mFiveMessagesToDisplay) {
super.onPostExecute(mFiveMessagesToDisplay);
for (int mTextViewCounter = 0; mTextViewCounter < 5; mTextViewCounter++) {
// Prepare the next TextView and message to use
mNextTextViewToUse = mTextViewArrayList.get(mTextViewCounter);
mNextMessageToDisplay = mFiveMessagesToDisplay.get(mTextViewCounter);
// Post and animate the message changes in the TextView
mNextTextViewToUse.startAnimation(mFadeOutAnimation);
}
}
我的AnimationListener:
private AnimationListener mFadeOutAnimListener = new AnimationListener() {
public void onAnimationStart(Animation animation) {}
public void onAnimationRepeat(Animation animation) {}
public void onAnimationEnd(Animation animation) {
mNextTextViewToUse.setVisibility(View.INVISIBLE);
mNextTextViewToUse.setText(mNextMessageToDisplay);
mNextTextViewToUse.setVisibility(View.VISIBLE);
mNextTextViewToUse.startAnimation(mFadeInAnimation);
}
}
正如您所看到的,我的setText()方法应用于mNextTextViewToUse对象,其内容为mNextMessageToDisplay,如同主类中的两个全局变量之前所述。
ArrayLists,包含消息的那个,另一个包含正确的,我已经迭代了两个并打印了内容 - 一切都在它的位置。 再次提醒我,如果我在onPostExecute下使用相同的TextView和String对象的setText(),那么一切都可以正常运行。
非常感谢提前!
答案 0 :(得分:0)
您的问题是,在动画结束时循环结束,这就是您只看到最后一条消息的原因。 让我们说mNextTextViewToUse指向TextView1。您为此TextView启动淡出动画。当动画结束时,mNextTextViewToUse指向不同的textView对象(因为循环动画正在播放时循环继续运行)所以当调用onAnimationEnd时(通过TextView1的淡出动画)mNextTextView指向TextView5,并且基本上你只是将文本设置为此文本视图。
有几种方法可以解决这个/实现你需要的东西,我个人可能会创建自己的TextView类(当然是扩展TextView),我将添加一个名为setTextAnimated(String newText)的公共方法。它看起来像:
public void setTextAnimated (String newText) {
mNextText = newText;
startAnimation(mFadeOutAnim);
}
你的onAnimationEnd回调将简单地调用setText(mNextText),然后启动淡入动画。
使用这个你将避免另一个问题 - 如果你在不同的视图上使用相同的动画对象 - 它们将共享相同的时间轴和插值器。结果是,如果View1启动一个应该需要200ms的淡出动画,而View 5在140ms后启动相同的动画,View5将立即“跳转”到与View1相同的alpha值。
答案 1 :(得分:0)
我找到了解决方案!
我最终完全删除了FOR循环逻辑并使用递归,一旦它使用了所有5个可用的TextView,就会引发一个布尔标志。
获取下一个TextView和String消息并执行动画setText()的方法:
public void updateTextView(List<String> mMessages) {
mNextTextViewToUse = mTextViewArrayList.get(mCurrentMessageIndex);
mNextMessageToDisplay = mMessages.get(mCurrentMessageIndex);
mNextTextViewToUse.startAnimation(mFadeOutAnimation);
if (mCurrentMessageIndex == 4) {
mStopMessageDisplayRepeat = true;
} else {
mCurrentMessageIndex++;
}
}
调用上述方法的Runnable,而递归停止布尔值为false:
public Runnable mUpdateTextViewRunnable = new Runnable() {
final static int POSTDELAY_INTERVAL = 600;
@Override
public void run() {
updateTextView(mFiveMessages);
if (! mStopMessageDisplayRepeat) {
mMessageDisplayRepeatHandler.postDelayed(mUpdateTextViewRunnable, POSTDELAY_INTERVAL);
}
}
};
执行Runnable:
public void startTextViewRunnableRepeat() {
mUpdateTextViewRunnable.run();
}
这就是我的AsyncTask的onPostExecute()的样子:
@Override
protected void onPostExecute(List<String> mFiveMessagesToDisplay) {
super.onPostExecute(mFiveMessagesToDisplay);
mFiveMessages = mFiveMessagesToDisplay;
startTextViewRunnableRepeat();
}