我要做的是在单击时进行一次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中搜索它。