无法投射到牛轧糖中的 AnimatedVectorDrawableCompat
Cannot cast to AnimatedVectorDrawableCompat in Nougat
这是我的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"/>
和 class 演员:
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 时,为什么 return 在 sdk 级别 21 上根本没有 AnimatedVectorDrawableCompat。尽管指定了 vectorDrawables.useSupportLibrary = true
.
,但为什么 return Nougat 中的 AnimatedVectorDrawable
我是这样处理的:
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();
}
}
});
}
}
您可以转换为 Animatable
而不是使用 API<21
进行检查,因为 AnimatedVectorDrawable
和 AnimatedVectorDrawableCompat
都实现了它
var anim = mImageView.drawable as Animatable
anim.start()
有点晚了,但我刚遇到类似的问题,我按如下方式解决了。也许它会帮助某人。
当我们使用vectorDrawables做动画时,我们需要做以下三件事:
- 从矢量可绘制资源创建一个 AnimatedVectorDrawableCompat:
val drawable: AnimatedVectorDrawableCompat? =
AnimatedVectorDrawableCompat.create(context, R.drawable.animated_vector)
- 将此可绘制对象转换为 Animatable2Compat:
val animatable: Animatable2Compat = drawable as Animatable2Compat
- 现在注册支持人员提供的回调
animatable.registerAnimationCallback(object : Animatable2Compat.AnimationCallback() {
override fun onAnimationEnd(drawable: Drawable?) {
// Put code to execute after the animation is done
}
})
这就是我所做的。如果有更好的方法,请随时发表评论。
简答:
使用 AnimatedVectorDrawableCompat.registerAnimationCallback
静态方法,它将为您完成这项工作。
(drawable as Animatable).start()
AnimatedVectorDrawableCompat.registerAnimationCallback(
drawable,
object : Animatable2Compat.AnimationCallback() {
override fun onAnimationEnd(drawable: Drawable?) {
postOnAnimation {
(drawable as Animatable).start()
}
}
})
长答案:
我在尝试循环动画矢量可绘制对象时遇到了同样的问题。直到我发现支持库 returns 不同 类(AnimatedVectorDrawable
和 AnimatedVectorDrawableCompat
)在不同的 SDK 级别。
除了 Nick Butcher post 的精彩博客 post 外,其他任何地方都没有记录:
https://medium.com/androiddevelopers/re-animation-7869722af206
他说:
Interestingly the support library currently uses the native version on API 24+ and the compat version prior despite the class being introduced in API 21. This enables it to supply bug fixes to APIs 21–23.
在博客 post 中,作者还建议使用其他方法来解决此问题,例如使用 AnimatedVectorDrawableCompat#create
方法并在运行时设置可绘制对象。
我建议您阅读整篇文章。
希望对您有所帮助。
感谢 SafaOrhan 提供的工作示例。
我将 post Java 导入的版本。
我使用了一个 class 成员变量来从另一个方法停止动画。
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();
}
}
这是我的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"/>
和 class 演员:
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 时,为什么 return 在 sdk 级别 21 上根本没有 AnimatedVectorDrawableCompat。尽管指定了 vectorDrawables.useSupportLibrary = true
.
我是这样处理的:
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();
}
}
});
}
}
您可以转换为 Animatable
而不是使用 API<21
进行检查,因为 AnimatedVectorDrawable
和 AnimatedVectorDrawableCompat
都实现了它
var anim = mImageView.drawable as Animatable
anim.start()
有点晚了,但我刚遇到类似的问题,我按如下方式解决了。也许它会帮助某人。
当我们使用vectorDrawables做动画时,我们需要做以下三件事:
- 从矢量可绘制资源创建一个 AnimatedVectorDrawableCompat:
val drawable: AnimatedVectorDrawableCompat? =
AnimatedVectorDrawableCompat.create(context, R.drawable.animated_vector)
- 将此可绘制对象转换为 Animatable2Compat:
val animatable: Animatable2Compat = drawable as Animatable2Compat
- 现在注册支持人员提供的回调
animatable.registerAnimationCallback(object : Animatable2Compat.AnimationCallback() {
override fun onAnimationEnd(drawable: Drawable?) {
// Put code to execute after the animation is done
}
})
这就是我所做的。如果有更好的方法,请随时发表评论。
简答:
使用 AnimatedVectorDrawableCompat.registerAnimationCallback
静态方法,它将为您完成这项工作。
(drawable as Animatable).start()
AnimatedVectorDrawableCompat.registerAnimationCallback(
drawable,
object : Animatable2Compat.AnimationCallback() {
override fun onAnimationEnd(drawable: Drawable?) {
postOnAnimation {
(drawable as Animatable).start()
}
}
})
长答案:
我在尝试循环动画矢量可绘制对象时遇到了同样的问题。直到我发现支持库 returns 不同 类(AnimatedVectorDrawable
和 AnimatedVectorDrawableCompat
)在不同的 SDK 级别。
除了 Nick Butcher post 的精彩博客 post 外,其他任何地方都没有记录:
https://medium.com/androiddevelopers/re-animation-7869722af206
他说:
Interestingly the support library currently uses the native version on API 24+ and the compat version prior despite the class being introduced in API 21. This enables it to supply bug fixes to APIs 21–23.
在博客 post 中,作者还建议使用其他方法来解决此问题,例如使用 AnimatedVectorDrawableCompat#create
方法并在运行时设置可绘制对象。
我建议您阅读整篇文章。
希望对您有所帮助。
感谢 SafaOrhan 提供的工作示例。
我将 post Java 导入的版本。
我使用了一个 class 成员变量来从另一个方法停止动画。
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();
}
}