【问题标题】:Animate list items in ListViewListView 中的动画列表项
【发布时间】:2011-08-14 06:47:54
【问题描述】:

我尝试在我的 ListView 中为新项目设置动画。我有稳定的 id-s,所以我确切地知道要为哪个元素设置动画。问题来自ListView的回收机制。当我知道我有一个最近插入的元素时,我在视图上调用 startAnimation。但随后,视图被回收,填充了不同的数据。 它会导致 UI 动画错误的行。在某些时候,视图持有正确的数据,但随后被回收。我通过 logcat 确认了这一点。 有没有办法解决这个问题?

编辑:

public ExpensCursorAdapter(Context context, Cursor c, boolean autoRequery,
        CopyOnWriteArraySet<String> fadeAnimateTags) {
    super(context, c, autoRequery);
    this.mFadeAnimTags = fadeAnimateTags;
}

@Override
public boolean hasStableIds() {
    return true;
}

@Override
public void bindView(View view, Context context, Cursor cursor) {
    setup(view, context, cursor);
}

private void setup(View view, Context context, Cursor cursor) {
    final String id = cursor.getString(4);
    if (LOCAL_LOGV) Log.v(TAG, String.format("Create item for %s. Received view: %s", id, view.toString()));
    view.setTag(id);
    final TextView dateText = (TextView) view.findViewById(R.id.date);
    final TextView timeText = (TextView) view.findViewById(R.id.time);
    final TextView title = (TextView) view.findViewById(R.id.title);
    final TextView amount = (TextView) view.findViewById(R.id.amount);
    final Date date = new Date(cursor.getLong(0));
    title.setText(cursor.getString(1));
    dateText.setText(dFormat.format(date));
    timeText.setText(tFormat.format(date));
    amount.setText(String.format("%d Ft", cursor.getInt(2)));
    if (cursor.getInt(3) == 1) {
        timeText.setTextColor(Color.LTGRAY);
        title.setTextColor(Color.LTGRAY);
        dateText.setTextColor(Color.LTGRAY);
        amount.setTextColor(Color.LTGRAY);
    } else {
        timeText.setTextColor(Color.BLACK);
        title.setTextColor(Color.BLACK);
        dateText.setTextColor(Color.BLACK);
        amount.setTextColor(Color.BLACK);
    }
    if (mFadeAnimTags.contains(id)) {
     view.setAnimation(AnimationUtils.loadAnimation(context, R.anim.fade));
     mFadeAnimTags.remove(id);
    }

}

@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
    final LayoutInflater inflater = LayoutInflater.from(context);
    View view = inflater.inflate(R.layout.expense_list_item, parent, false);
    setup(view, context, cursor);
    return view;
}

【问题讨论】:

  • 你从哪里开始动画?我觉得应该在Adapter的getView()方法上。
  • 我确实从那里开始。添加到问题中的代码。
  • 您是否尝试在每次“设置”行时创建新的动画对象?可能是因为您使用的是静态方法,它总是引用相同的动画,并且从一行更改为另一行。
  • 我每次都创建一个新动画。在第一个之后我不会看到任何东西,如果它一直是一样的。它不是。问题是由于视图回收,我设置动画的视图持有不同的数据。
  • 问题解决了吗?我有与 bindView 和 newView 相同的代码,以及由视图回收引起的相同问题,每行都有一个倒计时 textView 而不是你的动画:(请帮助!

标签: android listview adapter


【解决方案1】:

如果你在这里使用 getView() 简单的代码, (无需自定义库)

private int lastPosition = -1;

@Override
public View getView(int position, View convertView, ViewGroup parent) {
//Load your view, populate it, etc...
View view = ...;

Animation animation = AnimationUtils.loadAnimation(getContext(), (position > lastPosition) ? R.anim.up_from_bottom : R.anim.down_from_top);
view.startAnimation(animation);
lastPosition = position;

return view;
}

up_from_bottom.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
 android:shareInterpolator="@android:anim/decelerate_interpolator">
<translate
    android:fromXDelta="0%" android:toXDelta="0%"
    android:fromYDelta="100%" android:toYDelta="0%"
    android:duration="400" />
</set>

down_from_bottom.xml

 <?xml version="1.0" encoding="utf-8"?>
 <set xmlns:android="http://schemas.android.com/apk/res/android"
 android:shareInterpolator="@android:anim/decelerate_interpolator">
<translate
    android:fromXDelta="0%" android:toXDelta="0%"
    android:fromYDelta="-100%" android:toYDelta="0%"
    android:duration="400" />
 </set>

来自本站的参考:http://kylewbanks.com/blog/Implementing-Google-Plus-Style-ListView-Animations-on-Android

【讨论】:

    【解决方案2】:

    在自定义适配器的 getView 方法中为每个添加的元素设置动画。

    public View getView(int position, View convertView, ViewGroup parent) {
    
        View v = convertView;
    
        if (v == null) {
            LayoutInflater vi = (LayoutInflater) getActivity()
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            v = vi.inflate(R.layout.simple_list_item_1, null);
        }
    
        ListData o = list.get(position);
        TextView tt = (TextView) v.findViewById(R.id.toptext);
    
        tt.setText(o.content);
    
        Log.d("ListTest", "Position : "+position);
    
        if(flag == false) {
            Animation animation = AnimationUtils.loadAnimation(getActivity(), R.anim.slide_top_to_bottom);
            v.startAnimation(animation);
        }
        return v;
    }
    

    从而实现动画效果。

    【讨论】:

    • 永远不要在适配器中制作动画
    • @KorniltsevAnatoly 那么在哪里以及如何?
    【解决方案3】:

    查看ListViewAnimations 库,为您的 ListView 项设置动画。

    基本上,您只需再添加两行即可为您的项目设置动画:

    之前:

    MyListAdapter mAdapter = new MyListAdapter(this, getItems());
    getListView().setAdapter(mAdapter);
    

    之后:

    MyListAdapter mAdapter = new MyListAdapter(this, getItems());
    AlphaInAnimationAdapter alphaInAnimationAdapter = new AlphaInAnimationAdapter(mAdapter);
    alphaInAnimationAdapter.setAbsListView(getListView());
    getListView().setAdapter(alphaInAnimationAdapter);
    

    【讨论】:

    • +1 非常好的图书馆。小问题,一旦加载了列表视图,我需要向列表视图添加其他项目,添加其他项目时,我需要对这些项目进行动画处理(添加时仅对新添加的项目进行动画处理),这个库是否支持?
    【解决方案4】:

    我遇到了类似的问题。我不能 100% 确定这是否是正确的方法,但您可以尝试在开始新的视图之前清除视图上的动画,以取消回收视图中的任何剩余动画。这对我有帮助。

    if(flag == false) {
        v.clearAnimation();
        Animation animation = AnimationUtils.loadAnimation(getActivity(), R.anim.slide_top_to_bottom);
        v.startAnimation(animation);
    }
    

    【讨论】:

      猜你喜欢
      • 2023-03-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-24
      • 2012-09-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多