2014-02-18 75 views
0

我有5个TextView字段用于显示字符串并每10秒更改一次文本。 为了进行更改,我有一个AsyncTask抓取下面的5条消息(doInBackground),并将它们传递给onPostExecute以显示在UI中。Android动画只显示最后一个ArrayList元素

当我在没有动画的情况下显示消息时,一切正常,并且消息每次都通过新的AsyncTask每10秒旋转一次。 现在,当我尝试在TextView上使用简单的淡入/淡出动画时,我可以看到它们全部淡出,然后返回到占位符字符串,但是我想要显示的实际文本消息仅显示在最后一个TextView。

AsyncTask是我的MainActivity.java的内部类。 我在MainActivity.java实施了AnimationListener并且由于该在onPostExecute之下的物体((TextView的)mNextTextView & (字符串)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下使用setText()和相同的TextView和String对象,那么在没有动画的情况下,一切都很好。

非常感谢提前!

回答

0

我找到了解决方案!

我最终完全删除了FOR循环逻辑并使用递归,一旦它使用了所有5个可用的TextView,就会引发一个布尔标志。

即得到下一个的TextView和字符串消息并执行动画的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++; 
    } 
} 

调用上述方法可运行,而递归停止布尔值是假:

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(); 
} 
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的淡出动画,并且View5在140ms后开始相同的动画,View5将立即“跳转”到与View1相同的Alpha值。

+0

我已经试过你上面建议的东西,事情是,无论是我的下一个TextView的旁边消息显示引用是主要活动类的全局变量,即使我通过字符串值在我的TextView实现中的setTextAnimated()方法中,它不能将该String分配给我需要用于循环中setText()的字符串。你知道一种方法,我可以在我的动画期间让for循环暂停,并且在onAnimationEnd被调用时让代码继续吗? –

相关问题