无法在Nougat中强制转换为AnimatedVectorDrawableCompat

时间:2017-09-17 06:26:54

标签: android android-vectordrawable

这是我的build.gradle

    defaultConfig {
    ...
    minSdkVersion 21
    targetSdkVersion 26
    vectorDrawables.useSupportLibrary = true
}

和布局的一部分

<ImageView
    android:id="@+id/recents"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="?attr/selectableItemBackground"
    android:clickable="true"
    android:scaleType="fitCenter"
    app:srcCompat="@drawable/anim_test"/>

和班级演员:

val np = convertView.findViewById<ImageView>(R.id.recents)
val anim = np.drawable as AnimatedVectorDrawableCompat

这在Lolipop(sdk 21)上按预期工作,但在Nougat上失败说:

android.graphics.drawable.AnimatedVectorDrawable cannot be cast to android.support.graphics.drawable.AnimatedVectorDrawableCompat

我没有得到的是,为什么当系统已经支持AnimatedVectorDrawable时,它在sdk级别21上返回AnimatedVectorDrawableCompat。为什么它会在Nougat中返回AnimatedVectorDrawable而不是指定vectorDrawables.useSupportLibrary = true

5 个答案:

答案 0 :(得分:6)

由于API<21Animatable都实现了AnimatedVectorDrawable,因此您可以转发AnimatedVectorDrawableCompat,而不是使用var anim = mImageView.drawable as Animatable anim.start() 进行检查

{{1}}

答案 1 :(得分:6)

简短答案:

使用AnimatedVectorDrawableCompat.registerAnimationCallback静态方法,它将为您完成工作。

(drawable as Animatable).start()

AnimatedVectorDrawableCompat.registerAnimationCallback(
        drawable,
        object : Animatable2Compat.AnimationCallback() {
            override fun onAnimationEnd(drawable: Drawable?) {
                postOnAnimation {
                    (drawable as Animatable).start()
                }
            }
        })

长答案:

当我尝试循环绘制可绘制动画矢量时,我遇到了同样的问题。直到我发现支持库在不同的SDK级别上返回不同的类(AnimatedVectorDrawableAnimatedVectorDrawableCompat)。

除了Nick Butcher的精彩博客文章,其他任何地方都没有记录:

https://medium.com/androiddevelopers/re-animation-7869722af206

他说:

  

有趣的是,尽管在API 21中引入了该类,但该支持库当前仍使用API​​ 24+上的本机版本和compat版本。这使它能够为API 21–23提供错误修复。

在博客文章中,作者还建议了其他方法来解决此问题,例如使用AnimatedVectorDrawableCompat#create方法并在运行时设置可绘制对象。

我建议您阅读全文。

希望这会有所帮助。

答案 2 :(得分:4)

我这样处理:

public class MainActivity extends AppCompatActivity {

    ImageView img;
    Button show,play,stop;
    AnimatedVectorDrawableCompat anim_show,anim_play,anim_stop;
    Object canim_show,canim_play,canim_stop;



    static {
        AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        img = findViewById(R.id.img);

        show = findViewById(R.id.show);
        play = findViewById(R.id.play);
        stop = findViewById(R.id.stop);


        if(Build.VERSION.SDK_INT<21){
            anim_show = (AnimatedVectorDrawableCompat) getResources().getDrawable(R.drawable.xunfei_show_animated_vector);
            anim_play = (AnimatedVectorDrawableCompat) getResources().getDrawable(R.drawable.xunfei_play_animated_vector);
            anim_stop = (AnimatedVectorDrawableCompat) getResources().getDrawable(R.drawable.xunfei_stop_animated_vector);

        }else{
            canim_show = (AnimatedVectorDrawable) getResources().getDrawable(R.drawable.xunfei_show_animated_vector);
            canim_play = (AnimatedVectorDrawable) getResources().getDrawable(R.drawable.xunfei_play_animated_vector);
            canim_stop = (AnimatedVectorDrawable) getResources().getDrawable(R.drawable.xunfei_stop_animated_vector);

        }


        show.setOnClickListener(new View.OnClickListener() {
            @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
            @Override
            public void onClick(View view) {
                if(Build.VERSION.SDK_INT<21){
                    img.setImageDrawable(anim_show);
                    anim_show.start();
                }else{
                    img.setImageDrawable((AnimatedVectorDrawable) canim_show);
                    ((AnimatedVectorDrawable)canim_show).start();
                }

            }
        });





    }
}

答案 3 :(得分:1)

有点晚了,但我遇到了类似的问题,我解决了如下问题。也许它会帮助别人。

当我们使用 vectorDrawables 制作动画时,我们需要做以下三件事:

  1. 从矢量可绘制资源创建AnimatedVectorDrawableCompat:
  2. val drawable: AnimatedVectorDrawableCompat? =
              AnimatedVectorDrawableCompat.create(context, R.drawable.animated_vector)
    
    1. 将此drawable投射到Animatable2Compat:
    2. val animatable: Animatable2Compat = drawable as Animatable2Compat
      
      1. 现在注册支持
      2. 提供的回调
        animatable.registerAnimationCallback(object : Animatable2Compat.AnimationCallback() {
            override fun onAnimationEnd(drawable: Drawable?) {
              // Put code to execute after the animation is done
            }
          })
        

        这就是我所做的。如果有更好的方法,请随时评论。

答案 4 :(得分:0)

感谢 SafaOrhan 作为工作示例。
我将在导入中发布 Java 版本。
我使用了一个类成员变量,以便能够从其他方法停止动画。

import android.graphics.drawable.Drawable;
import android.graphics.drawable.Animatable;
import android.support.graphics.drawable.Animatable2Compat.AnimationCallback;
import android.support.graphics.drawable.AnimatedVectorDrawableCompat;
import android.os.Handler;

public class MainActivity {
  private Animatable vectorAnimation;

  public void stopAnimation() {
    if (vectorAnimation != null) vectorAnimation.stop();
  }

  public void startAnimation() {
    Drawable vectorDrawable = imageView.getDrawable();
    vectorAnimation = (Animatable) vectorDrawable;
    AnimatedVectorDrawableCompat.registerAnimationCallback(vectorDrawable, new AnimationCallback() {
      public void onAnimationEnd(Drawable drawable) {
        new Handler().postDelayed(() -> vectorAnimation.start(), 1000);
      }
    });
    vectorAnimation.start();
  }
}
相关问题