我要做的是点击时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;
}
}
有什么不对吗?
答案 0 :(得分:2)
其他观点动摇的原因是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语句 - 其中convertView!= null - 表示您收到了回收的视图,而不是给新的视图充气。在这里,你应该防止再循环的观点继续震动。
编辑:我更仔细地查看了您的代码,我认为您实际上是在考虑我之前提到的内容(但是没有成功),但我会留下它帮助别人。在你的情况下,我认为问题是你没有阻止你的ObjectAnimator。
if (animators.get(p.getId()) == null)
animators.put(p.getId(), ObjectAnimator.ofFloat(convertView, "rotation", 0, -2, 0, 2, 0));
这里,如果当前Person的动画制作者为空。你创建一个新的。假设你点击了person1。 ObjectAnimator1开始为person1设置动画。向下滚动,此视图将重复用于person13。创建ObjectAnimator13,然后告诉它结束并取消。无论ObjectAnimator13说什么,ObjectAnimator1仍然可以激活重复使用的视图。
要解决此问题,您可能需要在ViewHolder中存储Person的当前ID,以便您可以做的第一件事是结束以前的任何现有动画。可能更好的方法是将ObjectAnimator存储在ViewHolder中,然后不需要在HashMap中搜索它。
答案 1 :(得分:1)
您可以使用标记比使用哈希映射更容易地执行此操作...在每个getView调用中,验证是否选择了此人 - 如果没有,则取消动画。并且因为convertviews被回收,你必须重置他们的状态每个 getView调用(在需要的地方开始动画,在不需要的地方取消)。
public void getView(final int position, View convertView, ViewGroup parent) {
// inflate convertviews if necessary
Person person = people.get(position);
ObjectAnimator anim = (ObjectAnimator) convertView.getTag(R.id.tag_row_animation);
if (person.isSelected()) {
if (anim == null) {
anim = getAnimator(convertView);
anim.setTarget(convertView);
anim.start();
convertView.setTag(R.id.tag_row_animation, anim);
}
} else {
if (anim != null) anim.cancel();
convertView.setTag(R.id.tag_row_animation, null);
}
convertView.setTag(R.id.tag_list_person, person);
convertView.setOnClickListener(new View.OnClickListener() {
@Override public void onClick(View v) {
Person person = (Person) v.getTag(R.id.tag_list_person);
person.toggleSelected();
notifyDataSetChanged();
}
});
return convertView;
}
public ObjectAnimator getAnimator(View v) {
ObjectAnimator a = ObjectAnimator.ofFloat(v, "rotation", 0, -2, 0, 2, 0);
a.setDuration(300);
a.setRepeatCount(ObjectAnimator.INFINITE);
return a;
}
至于你的解决方案不起作用的原因:因为你的hashmap正在保存对转换视图的引用,并且转换视图每n个位置被回收(n =屏幕上的位置数,给予或取1或2),他们将为每个位置摇动%n == 0,因为你设置为震动的前一个转换视图现在将为转换视图被回收的n个位置的网格单元摇动。