需要
最近研究在底部菜单中加入gif播放。这样显得高级一些。研究了一些技术方案,现在写篇博客,沉淀一下。
效果
实现
通过Glide实现。虽然android官方有AnimatedImageDrawable 但是只支持API28以上,也就是android9.0以上的手机。兼容性太差。
写了一个工具类,可以根据传入的两个drawable的id值。自动生成一个StateListDrawable 。在view被选中的时候,显示相关图片。如果相关图片是gif就播放一次。
难点在于怎么播放一次。
我的方法是先stop,再调用startFromFirstFrame。
还有就是怎么监听状态的改变,在onStateChange添加记录即可。
关于StateListDrawable 手动调用addState时要注意。空的状态数组表示默认状态。一定要最后一个添加。如果第一个添加。其他状态都无法匹配,将始终显示默认状态。
这个工具类依赖glide,需要引入依赖
implementation 'com.github.bumptech.glide:glide:4.15.1'
工具
/**
* <pre>
* Created by zhuguohui
* Date: 2023/7/7
* Time: 14:54
* Desc:
* </pre>
*/
public class GifUtil {
public static void setDrawable(ImageView imageView,int normalId, int selectedId) {
GIfStateListDrawable listDrawable = new GIfStateListDrawable();
addState(imageView, new int[]{android.R.attr.state_selected}, selectedId, listDrawable, () -> {
addState(imageView, new int[]{}, normalId, listDrawable, () -> {
imageView.setImageDrawable(listDrawable);
});
});
}
private interface CallBack {
void call();
}
private static void addState(ImageView imageView, int[] states, int resId, StateListDrawable listDrawable, CallBack callBack) {
Glide.with(imageView)
.asDrawable()
.load(resId)
.into(new CustomTarget<Drawable>() {
@Override
public void onResourceReady(@NonNull Drawable resource, @Nullable Transition<? super Drawable> transition) {
listDrawable.addState(states, resource);
callBack.call();
}
@Override
public void onLoadCleared(@Nullable Drawable placeholder) {
}
});
}
public static class GIfStateListDrawable extends StateListDrawable {
private boolean stateChange=false;
@Override
protected boolean onStateChange(int[] stateSet) {
boolean change=super.onStateChange(stateSet);
if(change){
stateChange=true;
}
return change;
}
@Override
public void draw(Canvas canvas) {
super.draw(canvas);
if(stateChange) {
//确保只播放一次gif
stateChange=false;
Drawable current = getCurrent();
if (current instanceof GifDrawable) {
GifDrawable gifDrawable = (GifDrawable) current;
gifDrawable.setLoopCount(1);
gifDrawable.stop();
gifDrawable.startFromFirstFrame();
}
}
}
}
}
使用
demo
使用很简单,传入两个drawable就行了。更过修改view的selected状态来自动播放gif
public class MainActivity extends AppCompatActivity {
ImageView iv1,iv2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
iv1=findViewById(R.id.iv_1);
iv2=findViewById(R.id.iv_2);
GifUtil.setDrawable(iv1,R.drawable.city_normal,R.drawable.city_selected);
GifUtil.setDrawable(iv2,R.drawable.home_normal,R.drawable.home_selected);
iv1.setOnClickListener(v->{
iv1.setSelected(true);
iv2.setSelected(false);
});
iv2.setOnClickListener(v->{
iv2.setSelected(true);
iv1.setSelected(false);
});
}
}