参考地址 RecyclerView 加动画的坑
有个需求是在recyclerView上的第一个item加呼吸动画,作为一个动画小白,写个呼吸动画就已经很不容易了,呼吸和心跳很像吧,上来我就咔写了个心跳,哈哈哈,才改成了呼吸。
然后加到recyclerView上,我是在adapter上加的。Adapter的holder复用相信大家也都很熟悉了,这个在绘制效率的提高上很重要,也很容易发现一个问题,就是内容混乱的复用。所以常见的处理就是对view加上tag来多次判断,对于visibility之类的设置一定是if...else的写法,光有if是不可以的。
比方说
if (course.isReview()) { setVideoBtn(holder, true, stateRes[1], false); } else { setVideoBtn(holder, true, stateResOver, false); }
然后对于动画,你会发现if else还是不行,因为
holder.getRootView().clearAnimation();
似乎根本不会把我的动画给去掉。
比方说:先定义一个
mBreathAnimator = makeBreathAnimator();
if (pos == 0) { holder.getContainerView().setBackgroundResource(R.drawable.bg_ips_detail_item_breath_shadow); holder.getContentBg().setBackgroundColor(mContext.getResources().getColor(android.R.color.transparent));// final View holderCopy = holder.getRootView(); if (ips.isShouldBreath()) {// mBreathAnimator.setTarget(holderCopy); mBreathAnimator.setTarget(holder.getRootView()); mBreathAnimator.start(); isBreathAnimating = true; } } else { Drawable up = ContextCompat.getDrawable(mContext, R.drawable.bg_ips_detail_item); Drawable drawableUp= DrawableCompat.wrap(up); DrawableCompat.setTint(drawableUp, colors[pos%colors.length]); holder.getContentBg().setImageDrawable(drawableUp); holder.getRootView().clearAnimation();// if (mBreathAnimator!=null) {// mBreathAnimator.setTarget(holder.getRootView());// LogUtils.d("IPS","pos:"+pos+"-----set end");// mBreathAnimator.cancel();// mBreathAnimator.end();// } }
其中那些注释掉的都是我尝试的解决方法,各种不好使。为什么呢,因为这个问题的根本是holder的复用,只要holder pos等于0的动画没有被停止掉,那么它就不会停止。最直观的方法是打log看一眼。
@Overridepublic void onBindViewHolder(ViewHolder holder, int pos) { LogUtils.d("onBindViewHolder: 验证是否重用了"); LogUtils.d( "onBindViewHolder: 重用了"+holder.getRootView().getTag()); LogUtils.d("onBindViewHolder: 放到了"+mDataSet.get(pos)); IPSDetailBean.QuestionsBean ips = mDataSet.get(pos); ...
没有重用的pos0,tag是null。
08-08 15:27:19.269 D/DeatilAdapter: onBindViewHolder: 验证是否重用了
08-08 15:27:19.270 D/DeatilAdapter: onBindViewHolder: 重用了null
08-08 15:27:19.270 D/DeatilAdapter: onBindViewHolder: 放到了QuestionsBean{id=74, gain_star=0}
重用的pos0,tag是0。
08-08 15:23:06.635 D/DeatilAdapter: onBindViewHolder: 验证是否重用了
08-08 15:23:06.635 D/DeatilAdapter: onBindViewHolder: 重用了0
08-08 15:23:06.639 D/DeatilAdapter: onBindViewHolder: 放到了QuestionsBean{id=57, gain_star=0}
这就是原因,所以我能想到的就是从原因复用上解决了。解决方案如下👇:
@Override public void onViewRecycled(ViewHolder holder) { super.onViewRecycled(holder); int pos = (int) holder.getRootView().getTag(); LogUtils.d("onViewRecycled:"+holder.getRootView().getTag()); if(isBreathAnimating && pos == 0) { mBreathAnimator.end(); LogUtils.d("clearAnimation:"); holder.getRootView().clearAnimation(); } }
至此,这个recyclerview动画算是告一段落了。
周五提测,找不到解决方案那叫一个烦躁,以为解决不了了。休息了一个周末,倒是让我找到解决方案了,哈哈。