Android动画仅显示最后一个ArrayList元素

时间:2014-02-18 20:26:11

标签: java android arraylist android-asynctask android-animation

我有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(),那么一切都可以正常运行。

非常感谢提前!

2 个答案:

答案 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();
}