RecyclerView 加动画的坑

2019-05-21 11:46:05


参考地址 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动画算是告一段落了。
周五提测,找不到解决方案那叫一个烦躁,以为解决不了了。休息了一个周末,倒是让我找到解决方案了,哈哈。

              


  • 2018-12-13 17:14:41

    Android安全开发之浅谈密钥硬编码

    在阿里聚安全的漏洞扫描器中和人工APP安全审计中,经常发现有开发者将密钥硬编码在Java代码、文件中,这样做会引起很大风险。信息安全的基础在于密码学,而常用的密码学算法都是公开的,加密内容的保密依靠的是密钥的保密,密钥如果泄露,对于对称密码算法,根据用到的密钥算法和加密后的密文,很容易得到加密前的明文;对于非对称密码算法或者签名算法,根据密钥和要加密的明文,很容易获得计算出签名值,从而伪造签名。

  • 2018-12-13 17:17:02

    轻松实现动态获取Android手机CPU架构类型

    .so文件是unix的动态连接库,是二进制文件,作用相当于windows下的.dll文件。 他使用了C/C++代码编写的可以操作硬件比java更高级的 底层代码,执行速度和效率比其他语言要高。 在Android中调用动态库文件(*.so)都是通过jni的方式。

  • 2018-12-13 22:48:48

    Android MultiDex实践:如何绕过那些坑?

    MultiDex, 顾名思义,是指多dex实现,大多数App,解压其apk后,一般只有一个classes.dex文件,采用MultiDex的App解压后可以看到有classes.dex,classes2.dex,… classes(N).dex,这样每个dex都可以最大承载65k个方法,很大限度地缓解了单dex方法数限制。

  • 2018-12-14 13:32:18

    解决chrome调试手机模式没有鼠标问题

    F12后,切换到手机模式,方向没有鼠标,这对于调试前端页面来说无疑是一大难题,看不见只能盲点, 以为是浏览器问题,清理缓存,升级浏览器,清除插件等都不好使。 后来查到资料说是显卡问题。果然还真是显卡问题。

  • 2018-12-14 17:12:51

    Android APP适配全面屏手机的技术要点

    全面屏是手机业界对于超高屏占比手机设计的一个宽泛的定义。从字面上解释就是,手机的正面全部都是屏幕,四个边框位置都是采用无边框设计,追求接近100%的屏占比。但受限于目前的技术,还不能做到手机正面屏占比100%的手机。现在业内所说的全面屏手机是指真实屏占比可以达到80%以上,拥有超窄边框设计的手机。

  • 2018-12-14 17:15:50

    Android适配刘海屏沉浸式状态栏的一些坑

    18年简直是刘海元年,所有手机都在跟风刘海屏,甚至每个厂商还有自己的一套适配规范。我的初始需求很简单,就是做一个全屏显示的页面,一般情况下只需要开启Android规范的全屏模式就好:

  • 2018-12-16 12:12:12

    android:windowSoftInputMode属性具体解释

    android:windowSoftInputMode属性一共同拥有9个取值。各自是: stateUnspecified,stateUnchanged。stateHidden,stateAlwaysHidden。stateVisible,stateAlwaysVisible,adjustUnspecified,adjustResize。adjustPan。