我有一个recyclerView,它包含一个自定义视图列表。当我单击recyclerView项时,它会被展开,提供更多信息。另一次点击此视图(或另一个视图)将关闭当前视图。提供SimpleItemAnimator
的默认动画似乎不合适。所以,我试着像我一样自己实现animateChange
:
public class CustomItemAnimator extends CustomDefaultItemAnimator {
private static final int FADE_IN = 1;
private static final int FADE_OUT = 2;
private ItemHolderInfo getItemHolderInfo(RecyclerView.ViewHolder viewHolder, MoveInfo moveInfo) {
moveInfo.stuff.clear();
ViewGroup content_container = (ViewGroup) viewHolder.itemView.findViewById(R.id.item_content);
for (int i = 0; i < content_container.getChildCount(); i++) {
View view = content_container.getChildAt(i);
if (view.getVisibility() == View.VISIBLE) {
moveInfo.stuff.put(view.getId(), new Pair<>(view.getTop(), view.getBottom()));
}
}
moveInfo.stuff.put(viewHolder.itemView.getId(), new Pair<>(viewHolder.itemView.getTop(), viewHolder.itemView.getBottom()));
moveInfo.stuff.put(content_container.getId(), new Pair<>(content_container.getTop(), content_container.getBottom()));
return moveInfo;
}
@NonNull
@Override
public ItemHolderInfo recordPreLayoutInformation(@NonNull RecyclerView.State state, @NonNull RecyclerView.ViewHolder viewHolder, int changeFlags, @NonNull List<Object> payloads) {
ItemHolderInfo info = super.recordPreLayoutInformation(state, viewHolder, changeFlags, payloads);
return getItemHolderInfo(viewHolder, (MoveInfo) info);
}
@NonNull
@Override
public ItemHolderInfo recordPostLayoutInformation(@NonNull RecyclerView.State state, @NonNull RecyclerView.ViewHolder viewHolder) {
MoveInfo info = (MoveInfo) super.recordPostLayoutInformation(state, viewHolder);
return getItemHolderInfo(viewHolder, info);
}
@Override
public boolean animateChange(@NonNull final RecyclerView.ViewHolder oldHolder, @NonNull final RecyclerView.ViewHolder newHolder, @NonNull ItemHolderInfo preInfo, @NonNull ItemHolderInfo postInfo) {
Log.d("ANIMATOR", "animate change called 2");
MoveInfo pre = (MoveInfo) preInfo;
MoveInfo post = (MoveInfo) postInfo;
int fade_style;
final HashMap<Integer, Pair<Integer, Integer>> minMap;
HashMap<Integer, Pair<Integer, Integer>> maxMap;
if (pre.stuff.keySet().size() <= post.stuff.keySet().size()) {
minMap = pre.stuff;
maxMap = post.stuff;
fade_style = FADE_IN;
} else {
minMap = post.stuff;
maxMap = pre.stuff;
fade_style = FADE_OUT;
}
/*Getting the GoneViews*/
HashMap<Integer, Pair<Integer, Integer>> goneViews = new HashMap<>();
for (Integer i : maxMap.keySet()) {
if (minMap.get(i) == null) {
goneViews.put(i, maxMap.get(i));
}
}
List<Animator> animators = new ArrayList<>();
for (Integer i : minMap.keySet()) {
ViewPropertyAnimatorCompat animView = ViewCompat.animate(newHolder.itemView.findViewById(i));
ObjectAnimator viewDeltaTop = ObjectAnimator.ofInt(newHolder.itemView.findViewById(i), "top", pre.stuff.get(i).first, post.stuff.get(i).first);
ObjectAnimator viewDeltaBot = ObjectAnimator.ofInt(newHolder.itemView.findViewById(i), "bottom", pre.stuff.get(i).second, post.stuff.get(i).second);
animators.add(viewDeltaTop);
animators.add(viewDeltaBot);
}
for (Integer i : goneViews.keySet()) {
float from = fade_style == FADE_IN ? 0.0f : 1.0f;
float to = fade_style == FADE_IN ? 1.0f : 0.0f;
Animator viewAlpha = ObjectAnimator.ofFloat(newHolder.itemView.findViewById(i), "alpha", from, to);
animators.add(viewAlpha);
}
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.playTogether(animators);
animatorSet.setDuration(getChangeDuration());
animatorSet.start();
return true;
}
@Override
public boolean canReuseUpdatedViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, @NonNull List<Object> payloads) {
//to make viewholders reusable
return true;
}
//we store our infos here
private class MoveInfo extends ItemHolderInfo {
HashMap<Integer, Pair<Integer, Integer>> stuff = new HashMap<>();
}
//not implementing this cause cast error in my case
@Override
public ItemHolderInfo obtainHolderInfo() {
return new MoveInfo();
}
}
除了一件事,这就像魅力一样。如果我尝试滚动,在更改动画时,动画视图无法正确显示。看起来好像动画的底部/顶部值不会通过滚动接收任何输入。我喜欢这种方式,itemAnimator
有效,我想以这种方式使事情发挥作用。任何提示都表示赞赏。可能,我必须检查LinearLayoutManager?