我有一个填充了自定义视图的RecyclerView,其中包含各种信息和imageButton。 此ImageButton应在单击时触发显示动画,显示前一个视图。
当RecyclerView只包含一个项目时,它确实有效,但一旦视图开始被回收,它就会开始变得奇怪。 在这种情况下,当单击imageButton时,例如项目#4时,动画将出现在项目#2中(但它是随机的)。这是一个非常奇怪的行为,因为在自定义视图中引用了两个视图(第一个和要显示的视图),而不是其他任何地方。
显示动画的所有逻辑都在Custom视图中,由onBindViewHolder()中注入的ViewModel触发(每个onBindViewHolder都会生成一个新的ViewModel。)
我考虑过使用RecyclerView.ItemAnimator,但是我需要从视图中调用notifyItemChanged(),这将是非常hacky。
感谢您的任何建议。
更新
我会添加一些代码。
这是我的自定义视图。
public class CustomView extends RelativeLayout {
@BindView(R.id.visible_view)
View view1;
@BindView(R.id.hidden_view)
View view2;
private ViewModel viewModel;
public CustomView(Context context) {
this(context, null);
}
public CustomView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CustomView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
private void init() {
ButterKnife.bind(this, inflate(getContext(), R.layout.custom_layout, this));
}
public void setViewModel(HomeworkCardVM viewModel) {
view1.setViewModel(viewModel.subViewModel1());
view2.setViewModel(viewModel.subViewModel2());
viewModel.observeRevealShow()
.observeOn(AndroidSchedulers.mainThread())
.subscribe(aBoolean -> {
if (aBoolean) {
circularRevealView(visibleView, insertGradeView);
}
},Throwable::printStackTrace,() -> {});
viewModel.observeRevealHide()
.observeOn(AndroidSchedulers.mainThread())
.subscribe(aBoolean -> {
circularHideView(insertGradeView, visibleView);
},Throwable::printStackTrace, () -> {});
}
private void circularHideView(View visibleView, View invsisibleView) {
// get the center for the clipping circle
int cx = visibleView.getWidth() / 2;
int cy = visibleView.getHeight() / 2;
// get the initial radius for the clipping circle
float initialRadius = (float) Math.hypot(cx, cy);
// create the animation (the final radius is zero)
Animator anim =
ViewAnimationUtils.createCircularReveal(visibleView, cx, cy, initialRadius, 0);
// make the view invisible when the animation is done
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
visibleView.setVisibility(View.INVISIBLE);
invsisibleView.setVisibility(VISIBLE);
}
});
// start the animation
anim.start();
}
private void circularRevealView(View visibleView, View invisibleView) {
// get the center for the clipping circle
int cx = visibleView.getWidth() /2;
int cy = visibleView.getHeight() /2;
// get the final radius for the clipping circle
float finalRadius = (float) Math.hypot(cx, cy);
// create the animator for this view (the start radius is zero)
Animator anim =
ViewAnimationUtils.createCircularReveal(invisibleView, cx, cy, 0, finalRadius);
visibleView.setVisibility(INVISIBLE);
invisibleView.setVisibility(View.VISIBLE);
// make the view visible and start the animation
anim.start();
}
}
这是最基本的适配器。
public class Adapter extends RecyclerView.Adapter<ViewHolder> {
private List<Item> items = new ArrayList<>();
private Context mContext;
public Adapter(Context mContext) {
this.mContext = mContext;
}
@Override
public HomeworkViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(mContext).inflate(R.layout.view_holder, parent, false);
return new ViewHolder(v);
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.bindItem(items.get(position));
}
@Override
public int getItemCount() {
return items.size();
}
}
更基本的观点持有人。
public class ViewHolder extends RecyclerView.ViewHolder {
@BindView(R.id.custom_view)
CustomView customView;
public ViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
public void bindItem(Item item){
ViewModel viewModel = new ViewModel(item);
customView.setViewModel(viewModel);
}
}
我的直觉告诉我,circularRevealView(visibleView, insertGradeView);
中引用的视图在回收时被分配给另一个RecyclerView项目,我将进行调查
答案 0 :(得分:0)
这不是你怎么做的。唯一的好方法是:
正如你所建议的那样制作像你这样的动画是一种失败的好方法,因为recycleview的工作原理。您应该使用itemanimator完成所有动画以保持所有内容同步。