2025-09-13 15:38:16 +08:00
|
|
|
|
package com.xscm.moduleutil.widget;
|
|
|
|
|
|
|
|
|
|
|
|
import android.content.Context;
|
|
|
|
|
|
import android.graphics.Color;
|
|
|
|
|
|
import android.util.AttributeSet;
|
|
|
|
|
|
import android.widget.FrameLayout;
|
|
|
|
|
|
import android.widget.ImageView;
|
|
|
|
|
|
|
|
|
|
|
|
import com.opensource.svgaplayer.SVGACallback;
|
|
|
|
|
|
import com.opensource.svgaplayer.SVGADrawable;
|
|
|
|
|
|
import com.opensource.svgaplayer.SVGAImageView;
|
|
|
|
|
|
import com.opensource.svgaplayer.SVGAParser;
|
|
|
|
|
|
import com.opensource.svgaplayer.SVGAVideoEntity;
|
|
|
|
|
|
|
|
|
|
|
|
import org.jetbrains.annotations.NotNull;
|
|
|
|
|
|
|
|
|
|
|
|
import java.io.File;
|
|
|
|
|
|
import java.io.FileInputStream;
|
|
|
|
|
|
import java.io.IOException;
|
|
|
|
|
|
import java.io.InputStream;
|
|
|
|
|
|
import java.net.URL;
|
|
|
|
|
|
|
|
|
|
|
|
public class GiftSvgaView extends FrameLayout implements SVGACallback {
|
|
|
|
|
|
private SVGAImageView player;
|
|
|
|
|
|
private SVGAParser parser;
|
|
|
|
|
|
private boolean isAutoPlay = true;
|
|
|
|
|
|
|
|
|
|
|
|
// 回调接口
|
|
|
|
|
|
public interface OnAnimationListener {
|
|
|
|
|
|
void onStartAnimation(GiftSvgaView view);
|
|
|
|
|
|
void onFinishedDisplay(GiftSvgaView view);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private OnAnimationListener didStartAnimation;
|
|
|
|
|
|
private OnAnimationListener didFinishedDisplay;
|
|
|
|
|
|
|
|
|
|
|
|
public GiftSvgaView(Context context) {
|
|
|
|
|
|
this(context, null);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public GiftSvgaView(Context context, AttributeSet attrs) {
|
|
|
|
|
|
this(context, attrs, 0);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public GiftSvgaView(Context context, AttributeSet attrs, int defStyleAttr) {
|
|
|
|
|
|
super(context, attrs, defStyleAttr);
|
|
|
|
|
|
initializeData(true);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public GiftSvgaView(Context context, boolean isAutoPlay) {
|
|
|
|
|
|
super(context);
|
|
|
|
|
|
initializeData(isAutoPlay);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void initializeData(boolean isAutoPlay) {
|
|
|
|
|
|
this.isAutoPlay = isAutoPlay;
|
|
|
|
|
|
setBackgroundColor(Color.TRANSPARENT); // clearColor
|
|
|
|
|
|
setClickable(false); // userInteractionEnabled = NO
|
|
|
|
|
|
initPlayer();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void initPlayer() {
|
|
|
|
|
|
player = new SVGAImageView(getContext());
|
|
|
|
|
|
player.setBackgroundColor(Color.TRANSPARENT);
|
|
|
|
|
|
player.setScaleType(ImageView.ScaleType.CENTER_CROP); // UIViewContentModeScaleAspectFill
|
|
|
|
|
|
// 如果需要 ScaleAspectFit,使用 ImageView.ScaleType.FIT_CENTER
|
|
|
|
|
|
|
|
|
|
|
|
// 设置布局参数 - 填满父视图
|
|
|
|
|
|
LayoutParams params = new LayoutParams(
|
|
|
|
|
|
LayoutParams.MATCH_PARENT,
|
|
|
|
|
|
LayoutParams.MATCH_PARENT
|
|
|
|
|
|
);
|
|
|
|
|
|
addView(player, params);
|
|
|
|
|
|
|
|
|
|
|
|
// 初始化解析器
|
|
|
|
|
|
parser = new SVGAParser(getContext());
|
|
|
|
|
|
player.setCallback(this);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void loadSVGAPlayerWith(String loadPath) {
|
|
|
|
|
|
loadSVGAPlayerWith(loadPath, false);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void loadSVGAPlayerWith(String loadPath, boolean inBundle) {
|
|
|
|
|
|
loadSVGAPlayerWith(loadPath, inBundle, 1);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void loadSVGAPlayerWith(String loadPath, boolean inBundle, int loop) {
|
|
|
|
|
|
if (loadPath == null || loadPath.isEmpty()) {
|
|
|
|
|
|
if (didFinishedDisplay != null) {
|
|
|
|
|
|
didFinishedDisplay.onFinishedDisplay(this);
|
|
|
|
|
|
}
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (player == null) {
|
|
|
|
|
|
initPlayer();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
stopEffectSvgaPlay();
|
|
|
|
|
|
player.setLoops(loop);
|
|
|
|
|
|
|
|
|
|
|
|
if (loadPath.startsWith("https:") || loadPath.startsWith("http:")) {
|
|
|
|
|
|
// URL加载
|
|
|
|
|
|
try {
|
|
|
|
|
|
parser.parse(new URL(loadPath), new SVGAParser.ParseCompletion() {
|
|
|
|
|
|
@Override
|
|
|
|
|
|
public void onComplete(@NotNull SVGAVideoEntity videoItem) {
|
|
|
|
|
|
SVGADrawable drawable = new SVGADrawable(videoItem);
|
|
|
|
|
|
player.setImageDrawable(drawable);
|
|
|
|
|
|
|
|
|
|
|
|
if (isAutoPlay) {
|
|
|
|
|
|
player.startAnimation();
|
|
|
|
|
|
if (didStartAnimation != null) {
|
|
|
|
|
|
didStartAnimation.onStartAnimation(GiftSvgaView.this);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
public void onError() {
|
|
|
|
|
|
if (didFinishedDisplay != null) {
|
|
|
|
|
|
didFinishedDisplay.onFinishedDisplay(GiftSvgaView.this);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
|
if (didFinishedDisplay != null) {
|
|
|
|
|
|
didFinishedDisplay.onFinishedDisplay(this);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
} else if (inBundle) {
|
|
|
|
|
|
// 从Assets加载
|
|
|
|
|
|
try {
|
|
|
|
|
|
parser.parse(loadPath, new SVGAParser.ParseCompletion() {
|
|
|
|
|
|
@Override
|
|
|
|
|
|
public void onComplete(@NotNull SVGAVideoEntity videoItem) {
|
|
|
|
|
|
SVGADrawable drawable = new SVGADrawable(videoItem);
|
|
|
|
|
|
player.setImageDrawable(drawable);
|
|
|
|
|
|
|
|
|
|
|
|
if (isAutoPlay) {
|
|
|
|
|
|
player.startAnimation();
|
|
|
|
|
|
if (didStartAnimation != null) {
|
|
|
|
|
|
didStartAnimation.onStartAnimation(GiftSvgaView.this);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
public void onError() {
|
|
|
|
|
|
if (didFinishedDisplay != null) {
|
|
|
|
|
|
didFinishedDisplay.onFinishedDisplay(GiftSvgaView.this);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
|
if (didFinishedDisplay != null) {
|
|
|
|
|
|
didFinishedDisplay.onFinishedDisplay(this);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// 从文件路径加载
|
|
|
|
|
|
try {
|
|
|
|
|
|
File file = new File(loadPath);
|
|
|
|
|
|
if (!file.exists() || file.length() < 4) {
|
|
|
|
|
|
if (didFinishedDisplay != null) {
|
|
|
|
|
|
didFinishedDisplay.onFinishedDisplay(this);
|
|
|
|
|
|
}
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
InputStream inputStream = new FileInputStream(file);
|
|
|
|
|
|
parser.parse(inputStream, loadPath, new SVGAParser.ParseCompletion() {
|
|
|
|
|
|
@Override
|
|
|
|
|
|
public void onComplete(@NotNull SVGAVideoEntity videoItem) {
|
|
|
|
|
|
SVGADrawable drawable = new SVGADrawable(videoItem);
|
|
|
|
|
|
player.setImageDrawable(drawable);
|
|
|
|
|
|
|
|
|
|
|
|
if (isAutoPlay) {
|
|
|
|
|
|
player.startAnimation();
|
|
|
|
|
|
if (didStartAnimation != null) {
|
|
|
|
|
|
didStartAnimation.onStartAnimation(GiftSvgaView.this);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
public void onError() {
|
|
|
|
|
|
if (didFinishedDisplay != null) {
|
|
|
|
|
|
didFinishedDisplay.onFinishedDisplay(GiftSvgaView.this);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}, true);
|
|
|
|
|
|
} catch (IOException e) {
|
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
|
if (didFinishedDisplay != null) {
|
|
|
|
|
|
didFinishedDisplay.onFinishedDisplay(this);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Public方法
|
|
|
|
|
|
public void startEffectSvgaPlay() {
|
|
|
|
|
|
if (player != null && player.getDrawable() != null) {
|
|
|
|
|
|
player.startAnimation();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void pauseEffectSvgaPlay() {
|
|
|
|
|
|
if (player != null) {
|
|
|
|
|
|
player.pauseAnimation();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void stopEffectSvgaPlay() {
|
|
|
|
|
|
if (player != null) {
|
|
|
|
|
|
player.stopAnimation();
|
2025-09-15 18:22:36 +08:00
|
|
|
|
player.clearAnimation();
|
|
|
|
|
|
player.setImageDrawable( null);
|
2025-09-13 15:38:16 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void destroySvga() {
|
|
|
|
|
|
stopEffectSvgaPlay();
|
|
|
|
|
|
if (player != null) {
|
|
|
|
|
|
removeView(player);
|
|
|
|
|
|
player = null;
|
|
|
|
|
|
}
|
|
|
|
|
|
parser = null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// SVGACallback接口实现
|
|
|
|
|
|
@Override
|
|
|
|
|
|
public void onPause() {
|
|
|
|
|
|
// 暂停回调
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
public void onFinished() {
|
|
|
|
|
|
if (didFinishedDisplay != null) {
|
|
|
|
|
|
didFinishedDisplay.onFinishedDisplay(this);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
public void onRepeat() {
|
|
|
|
|
|
// 重复回调
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
public void onStep(int frame, double percentage) {
|
|
|
|
|
|
// 步骤回调
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Getter和Setter方法
|
|
|
|
|
|
public void setDidStartAnimation(OnAnimationListener listener) {
|
|
|
|
|
|
this.didStartAnimation = listener;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void setDidFinishedDisplay(OnAnimationListener listener) {
|
|
|
|
|
|
this.didFinishedDisplay = listener;
|
|
|
|
|
|
if (player != null) {
|
|
|
|
|
|
player.setCallback(this);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public boolean isAutoPlay() {
|
|
|
|
|
|
return isAutoPlay;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void setAutoPlay(boolean autoPlay) {
|
|
|
|
|
|
isAutoPlay = autoPlay;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public SVGAImageView getPlayer() {
|
|
|
|
|
|
return player;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public SVGAParser getParser() {
|
|
|
|
|
|
return parser;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|