我要做的是在单击时进行一次View震动,在再次单击时停止震动,我做到了,但是当我滚动gridview时,一切都变得一团糟,另一个View上的震动动画没有单击。
这里有一个更清楚的解释:http://i.imgur.com/IDv7vJ6.gif
我不知道为什么其他人的观点在动摇。
这是我的代码:

public class PeopleFragmentGridAdapter extends BaseAdapter {

private List<Person> people = new ArrayList<>();
private Context context;
private Map<Integer, Boolean> animating;
private Map<Integer, ObjectAnimator> animators;

public PeopleFragmentGridAdapter(Context context, List<Person> people) {
    this.context = context;
    this.people.addAll(people);
    this.animating = new HashMap<>();
    this.animators = new HashMap<>();
}

@Override
public int getCount() {
    return people.size();
}

@Override
public Person getItem(int position) {
    return people.get(position);
}

@Override
public long getItemId(int position) {
    return position;
}

@Override
public View getView(final int position, View convertView, ViewGroup parent) {
    ViewHolder ViewHolder;
    final Person p = people.get(position);

    if (convertView == null) {
        convertView = ((LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE))
            .inflate(R.layout.fragment_people_grid_peoples_item, null);
        ViewHolder = new ViewHolder();
        ViewHolder.peopleGridItem = (PeopleGridItem) convertView.findViewById(R.id.fragment_people_grid_peoples_item_item);
        convertView.setTag(ViewHolder);
    } else {
        ViewHolder = (ViewHolder) convertView.getTag();
    }


    convertView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            p.setSelected(!p.isSelected());
            notifyDataSetChanged();
        }
    });

    if (animators.get(p.getId()) == null)
        animators.put(p.getId(), ObjectAnimator.ofFloat(convertView, "rotation", 0, -2, 0, 2, 0));
    if (animating.get(p.getId()) == null)
        animating.put(p.getId(), false);

    if (p.isSelected()) {
        if (!animating.get(p.getId())) {
            animating.put(p.getId(), true);
            animators.get(p.getId()).setTarget(convertView);
            animators.get(p.getId()).setRepeatCount(ObjectAnimator.INFINITE);
            animators.get(p.getId()).setDuration(300);
            animators.get(p.getId()).start();
        }
    } else {
        animators.get(p.getId()).setTarget(convertView);
        animating.put(p.getId(), false);
        animators.get(p.getId()).end();
        animators.get(p.getId()).cancel();
    }

    return convertView;
}
}

出什么事了吗?

最佳答案

其他视图都在震动的原因是android实现gridview的方式。为了保留内存,它会循环使用视图,以便只有屏幕上显示的(或即将显示的)视图保存在内存中。任何被回收的视图都被放入一个未使用的视图池中,这些视图可以在将来重用。这是参数“convertView”获取其视图的位置。
这意味着你的工作是在物体离开屏幕时保持它的状态。

if (convertView == null) {
    convertView = ((LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE))
        .inflate(R.layout.fragment_people_grid_peoples_item, null);
    ViewHolder = new ViewHolder();
    ViewHolder.peopleGridItem = (PeopleGridItem) convertView.findViewById(R.id.fragment_people_grid_peoples_item_item);
    convertView.setTag(ViewHolder);
} else {
    ViewHolder = (ViewHolder) convertView.getTag();
}

输入else语句——where convertview!=null——表示您收到了一个回收视图,而不是膨胀一个新视图。在这里,您应该防止回收视图继续抖动。
编辑:我更仔细地看了看你的代码,我认为你实际上是在考虑我之前提到的(尽管没有成功),但我会留下它,以防它帮助其他人。在您的情况下,我认为问题在于您未能停止objectanimator。
if (animators.get(p.getId()) == null)
    animators.put(p.getId(), ObjectAnimator.ofFloat(convertView, "rotation", 0, -2, 0, 2, 0));

如果当前人的动画师为空。你创建一个新的。假设你点击了person1。objectanimator1开始设置person1的动画。您向下滚动,这个视图将被重新用于person13。创建objectanimator13,然后告诉它结束并取消。无论objectanimator13说什么,objectanimator1仍然处于活动状态,为重用的视图设置动画。
要解决这个问题,您可能需要将此人的当前id存储在viewholder中,以便您可以做的第一件事是结束以前的任何现有动画。可能更好的方法是将objectanimator存储在viewholder中,然后不需要在hashmap中搜索它。

07-24 09:45
查看更多