Android – [SelfView] 多动画效果图片播放器
效果(录制的有点卡)
1. 引用:
<com.nepalese.virgolib.widget.image.BaseImageView
android:id="@+id/base_image"
android:layout_width="match_parent"
android:layout_height="match_parent" />
2. 接口:
private BaseImageView baseImageView;
//绑定
baseImageView = findViewById(R.id.base_image);
//设置动画类型
baseImageView.setAnimType(type);
//设置图片资源
baseImageView.setImageResource(path);
3. BaseImageView.java
package com.nepalese.virgolib.widget.image;
import android.animation.Animator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Movie;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.animation.LinearInterpolator;
import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
/**
* Created by Administrator on 2024/10/10.
* Usage:自带动画的图片播放器: 两张图之间
*/
public class BaseImageView extends View {
private static final String TAG = "BaseImageView";
private static final long COM_INTERVAL = 500L;//通用动画时长
private static final int ANIM_NUM = 10;//动画效果数(除随机)
private static final int LENTH = 40;//像素跨值|cube 边长//按最大1920*1080容器,45时,差不多拆分1000个
private static final int MAX_CACHE = 10;//最大缓存数量
private static final int MAX_ALPHA = 255;//最大透明度
private static final int MAX_GRADE = 180;//最大旋转角度
public static final int ANIM_NONE = 0;//无动画
public static final int ANIM_FADE = 1;//淡入淡出 默认
public static final int ANIM_RIGHT = 2;//右进左出
public static final int ANIM_SCALE = 3;//中心缩放
public static final int ANIM_SCALE2 = 4;//中心缩放, 上一张不变
public static final int ANIM_JUMP = 5;//弹跳退出
public static final int ANIM_UP = 6;//底部上推
public static final int ANIM_BOTTOM_UP = 7;//底部上浮
public static final int ANIN_ROTATE = 8;//顺时针旋转
public static final int ANIM_ROLL = 9;//左下角顺时针旋转 + 右移
public static final int ANIM_CRASH = 10;//破碎效果
public static final int ANIM_RANDOM = 99;//随机
private final Context context;
private Drawable[] drawables;//操作的两张图
private ValueAnimator animator;//动画
private Paint paint;//画笔
private Movie movie;//用于承载gif文件
private Rect rectLast, rectCur, rectJump;//上一张、当前图片位置
private List<CubeBean> pixelList;
private HashMap<String, Drawable> cacheMap;//图片缓存
private int width, height;//控件宽高
private int animType;//动画类型
private int curIndex;//0|1
private int CV;//线性变化的基础值
private int JUMP_THRESHOLD;//跳动偏移阈值 px
private int rotate, cX, cY;//当前旋转角度
private int alphaLast, alphaCur;//上一张、当前图片透明值[0-255]
private int leftLast, leftCur;//上一张、当前图片左上点x[0-width]
private int topLast, topCur;//上一张、当前图片左上点xy[0-height]
private float time;//动画运行时间
private float whRate;//宽高比
private long INTERVAL_ANIMATION;//动画时长,按动画类型分配
private long gifPlayTime;//当前gif已播放时长
private boolean isSecond;//第二部分
private boolean isOver;//动画结束
private boolean isRandom;//随机动画效果
private boolean isGif;//当前为gif 文件?
private String lastPath;//记录上一张图片路径:相同的文件则不切换
public BaseImageView(Context context) {
this(context, null);
}
public BaseImageView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public BaseImageView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.context = context;
init();
}
private void init() {
time = 0;
curIndex = -1;
gifPlayTime = 0;
isSecond = false;
isOver = false;
isRandom = false;
isGif = false;
animType = ANIM_NONE;
}
/**
* 设置|更改布局时调用
*
* @param width 容器宽
* @param height 容器高
*/
public void initLayout(int width, int height) {
this.width = width;
this.height = height;
this.whRate = width * 1f / height;
initAnimator();
}
private void initAnimator() {
cancelAnim();
resetAnimator();
}
private void resetAnimator() {
switch (animType) {
case ANIM_NONE:
CV = 0;
break;
case ANIM_FADE:
CV = MAX_ALPHA; //透明值
INTERVAL_ANIMATION = COM_INTERVAL;
break;
case ANIN_ROTATE:
CV = MAX_GRADE;
cX = width / 2;//旋转中心
cY = height / 2;
INTERVAL_ANIMATION = COM_INTERVAL;
break;
case ANIM_ROLL:
CV = MAX_GRADE;
cX = 0;//旋转中心
cY = height;
INTERVAL_ANIMATION = COM_INTERVAL;
break;
case ANIM_RIGHT:
CV = width;
INTERVAL_ANIMATION = COM_INTERVAL;
break;
case ANIM_UP:
CV = height;
INTERVAL_ANIMATION = COM_INTERVAL;
break;
case ANIM_BOTTOM_UP:
CV = height;
INTERVAL_ANIMATION = COM_INTERVAL;
break;
case ANIM_SCALE:
rectLast = new Rect();
rectCur = new Rect();
CV = width / 2;
INTERVAL_ANIMATION = COM_INTERVAL;
break;
case ANIM_SCALE2:
rectCur = new Rect();
CV = width / 2;
INTERVAL_ANIMATION = COM_INTERVAL;
break;
case ANIM_CRASH:
if (paint == null) {
paint = new Paint();
paint.setAntiAlias(true);
paint.setStyle(Paint.Style.FILL);
}
if (pixelList == null) {
pixelList = new ArrayList<>();
}
CV = 128;
INTERVAL_ANIMATION = 1280L;
break;
case ANIM_JUMP:
rectJump = new Rect();
JUMP_THRESHOLD = Math.max(width / 8, 30);
CV = width + JUMP_THRESHOLD;
INTERVAL_ANIMATION = 800L;
break;
}
if (CV > 0) {
animator = ValueAnimator.ofInt(0, CV);
animator.setDuration(INTERVAL_ANIMATION);
animator.setInterpolator(new LinearInterpolator());//插值器设为线性
} else {
animator = null;
}
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
if (w > 0 && h > 0) {
initLayout(w, h);
}
}
@Override
protected void onDraw(Canvas canvas) {
if (drawables == null) {
return;
}
if (isGif && this.getVisibility() == VISIBLE) {
drawGif(canvas);
return;
}
switch (animType) {
case ANIM_NONE:
drawNone(canvas);
break;
case ANIM_FADE:
drawFade(canvas);
break;
case ANIN_ROTATE:
drawRotate(canvas);
break;
case ANIM_ROLL:
drawRoll(canvas);
break;
case ANIM_RIGHT:
drawRight(canvas);
break;
case ANIM_UP:
drawUp(canvas);
break;
case ANIM_BOTTOM_UP:
drawBottomUp(canvas);
break;
case ANIM_SCALE:
drawScal(canvas);
break;
case ANIM_SCALE2:
drawScal2(canvas);
break;
case ANIM_CRASH:
drawCrash(canvas);
break;
case ANIM_JUMP:
drawJump(canvas);
break;
}
}
/**
* 播放gif: 直接用movie绘制闪退?
* 使用读帧方式,绘制每帧
*/
private void drawGif(Canvas canvas) {
if (movie != null) {
long now = System.currentTimeMillis();
if (gifPlayTime == 0) {
gifPlayTime = now;
}
int dur = movie.duration();
if (dur <= 0) {
gifPlayTime = 0;
Log.w(TAG, "Gif 读取失败|文件有问题,仅画一次");
drawNone(canvas);
return;
}
int relTime = (int) ((now - gifPlayTime) % dur);
Drawable drawable = getMovieFirstFrame(movie, relTime);
if (drawable != null) {
drawable.setBounds(0, 0, width, height);
drawable.draw(canvas);
} else {
canvas.drawColor(Color.WHITE);
}
invalidate();
}
}
//无动画
private void drawNone(Canvas canvas) {
if (curIndex < 0) {
Log.e(TAG, "drawNone: error -- " + curIndex);
return;
}
if (drawables[curIndex] != null) {
drawables[curIndex].setBounds(0, 0, width, height);
drawables[curIndex].draw(canvas);
}
}
private void drawFade(Canvas canvas) {
if (curIndex < 0) {
Log.e(TAG, "drawFade: error -- " + curIndex);
return;
}
//如果有上一张,先消失,再加载当前的
if (curIndex == 0) {
if (drawables[1] == null) {
//第一张图
drawables[curIndex].setBounds(0, 0, width, height);
drawables[curIndex].setAlpha(alphaCur);
drawables[curIndex].draw(canvas);
} else {
if (isSecond) {
if (drawables[curIndex] != null) {
drawables[curIndex].setBounds(0, 0, width, height);
drawables[curIndex].setAlpha(alphaCur);
drawables[curIndex].draw(canvas);
}
} else {
//上一张,先消失
drawables[1].setBounds(0, 0, width, height);
drawables[1].setAlpha(alphaLast);
drawables[1].draw(canvas);
}
}
} else {
if (isSecond) {
if (drawables[curIndex] != null) {
drawables[curIndex].setBounds(0, 0, width, height);
drawables[curIndex].setAlpha(alphaCur);
drawables[curIndex].draw(canvas);
}
} else {
//上一张,先消失
if (drawables[0] != null) {
drawables[0].setBounds(0, 0, width, height);
drawables[0].setAlpha(alphaLast);
drawables[0].draw(canvas);
}
}
}
}
/**
* 顺时针旋转 180°
* 仅顶部,底下不变
*/
private void drawRotate(Canvas canvas) {
if (curIndex < 0) {
Log.e(TAG, "drawFade: error -- " + curIndex);
return;
}
if (isOver) {
//动画结束
if (drawables[curIndex] != null) {
drawables[curIndex].setBounds(0, 0, width, height);
drawables[curIndex].draw(canvas);
}
} else {
if (curIndex == 0) {
if (drawables[1] != null) {
//上一张
drawables[1].setBounds(0, 0, width, height);
drawables[1].draw(canvas);
}
} else {
//上一张
if (drawables[0] != null) {
drawables[0].setBounds(0, 0, width, height);
drawables[0].draw(canvas);
}
}
if (drawables[curIndex] != null) {
drawables[curIndex].setBounds(0, 0, width, height);
}
if (drawables[curIndex] != null) {
canvas.save();
canvas.rotate(rotate, cX, cY);
drawables[curIndex].draw(canvas);
canvas.restore();
}
}
}
/**
* 顺时针旋转90°
* 仅顶部,底下不变
*/
private void drawRoll(Canvas canvas) {
if (curIndex < 0) {
Log.e(TAG, "drawFade: error -- " + curIndex);
return;
}
if (isOver) {
//动画结束
if (drawables[curIndex] != null) {
drawables[curIndex].setBounds(0, 0, width, height);
drawables[curIndex].draw(canvas);
}
} else {
if (curIndex == 0) {
if (drawables[1] != null) {
//上一张
drawables[1].setBounds(0, 0, width, height);
drawables[1].draw(canvas);
}
} else {
//上一张
if (drawables[0] != null) {
drawables[0].setBounds(0, 0, width, height);
drawables[0].draw(canvas);
}
}
if (drawables[curIndex] != null) {
drawables[curIndex].setBounds(0, 0, width, height);
}
if (drawables[curIndex] != null) {
canvas.save();
canvas.rotate(rotate, cX, cY);
drawables[curIndex].draw(canvas);
canvas.restore();
}
}
}
/**
* 右进左出:进入时由变不变(宽度慢慢变大),出去时保持宽度不变
*/
private void drawRight(Canvas canvas) {
if (curIndex < 0) {
Log.e(TAG, "drawRight: error -- " + curIndex);
return;
}
//如果有上一张,先消失,再加载当前的
if (isOver) {
//动画结束
if (drawables[curIndex] != null) {
drawables[curIndex].setBounds(0, 0, width, height);
}
} else {
if (curIndex == 0) {
if (drawables[1] != null) {
//上一张
drawables[1].setBounds(leftLast, 0, width + leftLast, height);
drawables[1].draw(canvas);
}
} else {
//上一张
if (drawables[0] != null) {
drawables[0].setBounds(leftLast, 0, width + leftLast, height);
drawables[0].draw(canvas);
}
}
if (drawables[curIndex] != null) {
drawables[curIndex].setBounds(leftCur, 0, width, height);
}
}
if (drawables[curIndex] != null) {
drawables[curIndex].draw(canvas);
}
}
/**
* 从下面上浮:进入时由变不变(高度慢慢变大),出去时保持高度不变
*/
private void drawUp(Canvas canvas) {
if (curIndex < 0) {
Log.e(TAG, "drawRight: error -- " + curIndex);
return;
}
//如果有上一张,先消失,再加载当前的
if (isOver) {
//动画结束
if (drawables[curIndex] != null) {
drawables[curIndex].setBounds(0, 0, width, height);
}
} else {
if (curIndex == 0) {
if (drawables[1] != null) {
//上一张
drawables[1].setBounds(0, topLast, width, height - topLast);
drawables[1].draw(canvas);
}
} else {
//上一张
if (drawables[0] != null) {
drawables[0].setBounds(0, topLast, width, height - topLast);
drawables[0].draw(canvas);
}
}
if (drawables[curIndex] != null) {
drawables[curIndex].setBounds(0, topCur, width, height);
}
}
if (drawables[curIndex] != null) {
drawables[curIndex].draw(canvas);
}
}
/**
* 底部往上走,上一张不动
* 图片大小不变
*/
private void drawBottomUp(Canvas canvas) {
if (curIndex < 0) {
Log.e(TAG, "drawRight: error -- " + curIndex);
return;
}
//如果有上一张,先消失,再加载当前的
if (isOver) {
//动画结束
if (drawables[curIndex] != null) {
drawables[curIndex].setBounds(0, 0, width, height);
}
} else {
if (curIndex == 0) {
if (drawables[1] != null) {
//上一张
drawables[1].setBounds(0, 0, width, height);
drawables[1].draw(canvas);
}
} else {
//上一张
if (drawables[0] != null) {
drawables[0].setBounds(0, 0, width, height);
drawables[0].draw(canvas);
}
}
if (drawables[curIndex] != null) {
drawables[curIndex].setBounds(0, 0, width, height);
}
}
if (drawables[curIndex] != null) {
canvas.save();
canvas.translate(0, topCur);
drawables[curIndex].draw(canvas);
canvas.restore();
}
}
private void drawScal(Canvas canvas) {
if (curIndex < 0) {
Log.e(TAG, "drawScal: error -- " + curIndex);
return;
}
if (isOver) {
//动画结束
if (drawables[curIndex] != null) {
drawables[curIndex].setBounds(0, 0, width, height);
}
} else {
if (curIndex == 0) {
if (drawables[1] != null) {
//上一张
drawables[1].setBounds(rectLast);
drawables[1].draw(canvas);
}
} else {
//上一张
if (drawables[0] != null) {
drawables[0].setBounds(rectLast);
drawables[0].draw(canvas);
}
}
if (drawables[curIndex] != null) {
drawables[curIndex].setBounds(rectCur);
}
}
if (drawables[curIndex] != null) {
drawables[curIndex].draw(canvas);
}
}
/**
* 仅当前图片慢慢变大, 上一张不变
*/
private void drawScal2(Canvas canvas) {
if (curIndex < 0) {
Log.e(TAG, "drawScal: error -- " + curIndex);
return;
}
if (isOver) {
//动画结束
if (drawables[curIndex] != null) {
drawables[curIndex].setBounds(0, 0, width, height);
}
} else {
if (curIndex == 0) {
if (drawables[1] != null) {
//上一张
drawables[1].setBounds(0, 0, width, height);
drawables[1].draw(canvas);
}
} else {
//上一张
if (drawables[0] != null) {
drawables[0].setBounds(0, 0, width, height);
drawables[0].draw(canvas);
}
}
if (drawables[curIndex] != null) {
drawables[curIndex].setBounds(rectCur);
}
}
if (drawables[curIndex] != null) {
drawables[curIndex].draw(canvas);
}
}
private void drawCrash(Canvas canvas) {
if (curIndex < 0) {
Log.e(TAG, "drawCrash: error -- " + curIndex);
return;
}
if (isOver) {
//动画结束
if (drawables[curIndex] != null) {
drawables[curIndex].setBounds(0, 0, width, height);
drawables[curIndex].draw(canvas);
}
} else {
for (CubeBean item : pixelList) {
if (item.sY > height) {
//超出容器不用画
continue;
}
paint.setColor(item.color);
canvas.drawRect(item.sX, item.sY, item.sX + item.cL, item.sY + item.cL, paint);
//变化 s = v0t + at^2
item.sY += (float) (item.vY * time + item.aY * Math.pow(time, 2));
}
}
}
private void drawJump(Canvas canvas) {
if (curIndex < 0) {
Log.e(TAG, "drawJump: error -- " + curIndex);
return;
}
//当前图片一直存在
if (drawables[curIndex] != null) {
drawables[curIndex].setBounds(0, 0, width, height);
drawables[curIndex].draw(canvas);
}
if (isOver) {
return;
}
//上一张图
if (curIndex == 0) {
if (drawables[1] != null) {
//上一张
drawables[1].setBounds(rectJump);
drawables[1].draw(canvas);
}
} else {
//上一张
if (drawables[0] != null) {
drawables[0].setBounds(rectJump);
drawables[0].draw(canvas);
}
}
}
@Override
protected void onDetachedFromWindow() {
releaseBase();
super.onDetachedFromWindow();
}
@Override
protected void onVisibilityChanged(@NonNull View changedView, int visibility) {
super.onVisibilityChanged(changedView, visibility);
if (isGif) {
if (visibility == VISIBLE) {
invalidate();
}
}
}
/**
* 获取Gif图片帧
*/
private Drawable getMovieFirstFrame(Movie movie, int time) {
if (movie == null) {
return null;
}
Bitmap bitmap = Bitmap.createBitmap(movie.width(), movie.height(),
Bitmap.Config.RGB_565);
Canvas canvas = new Canvas(bitmap);
movie.setTime(time);
movie.draw(canvas, 0, 0);
canvas.save();
return new BitmapDrawable(getResources(), bitmap);
}
/**
* 大于控件分辨率的图片会自动压缩
*
* @param filePath 图片路径
* @return Drawable
*/
private Drawable getDrawableFromFile(String filePath) {
//启用缓存
if (cacheMap == null) {
cacheMap = new HashMap<>();
} else {
if (cacheMap.containsKey(filePath)) {
return cacheMap.get(filePath);
}
}
Drawable drawable = null;
try {
BitmapFactory.Options options = new BitmapFactory.Options();
//设置为true,仅解析图片的原始宽高信息,并不会加载图片
options.inJustDecodeBounds = true;
options.inPreferredConfig = Bitmap.Config.RGB_565;
BitmapFactory.decodeFile(filePath, options);
//按控件宽高压缩
options.inSampleSize = calculateInSampleSize(options, width, height);
options.inJustDecodeBounds = false;
if (options.inSampleSize > 0) {
drawable = new BitmapDrawable(getResources(), BitmapFactory.decodeFile(filePath, options));
if (cacheMap.size() < MAX_CACHE) {
cacheMap.put(filePath, drawable);
}//超出不处理
}
} catch (Exception e) {
e.printStackTrace();
}
return drawable;
}
/**
* 计算出合适的图片倍率
*
* @param options: 图片bitmapFactory选项
* @param reqWidth: 需要的图片宽
* @param reqHeight: 需要的图片长
* @return int 成功返回倍率, 异常-1
*/
private int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
int inSampleSize;
try {
// reqWidth/width, reqHeight/height两者中最大值作为压缩比
inSampleSize = Math.max(options.outWidth / reqWidth, options.outHeight / reqHeight);
inSampleSize = Math.max(inSampleSize, 1);//小图不变
} catch (Exception ignored) {
return -1;
}
return inSampleSize;
}
protected void cancelAnim() {
if (animator != null) {
animator.removeAllListeners();
animator.end();
animator = null;
}
}
private void doAnimation() {
if (animator != null) {
animator.removeAllListeners();
}
if (isRandom) {
animType = (int) (Math.random() * 1000) % ANIM_NUM;
resetAnimator();
}
if (animType == ANIM_NONE || animator == null) {
//无动画
invalidate();
return;
} else if (animType == ANIM_CRASH) {
pixelList.clear();
//获取上一张图片的像素
BitmapDrawable bitmapDrawable = null;
if (curIndex == 0) {
bitmapDrawable = (BitmapDrawable) drawables[1];
} else if (curIndex == 1) {
bitmapDrawable = (BitmapDrawable) drawables[0];
}
if (bitmapDrawable == null) {
isOver = true;
invalidate();
return;
}
Bitmap bitmap = bitmapDrawable.getBitmap();
if (bitmap != null) {
//该参数控制原来每一个像素点在屏幕上的缩放比例,此时为放大两倍
//基于控件宽高, 获取等比缩放下对应的像素点
float rW = bitmap.getWidth() * 1f / width;
float rH = bitmap.getHeight() * 1f / height;
CubeBean item;
for (int i = 0; i < width; i += LENTH) {//像素跨值
for (int j = 0; j < height; j += LENTH) {
item = new CubeBean();
item.color = bitmap.getPixel((int) (i * rW), (int) (j * rH));//取样点
item.sX = i;
item.sY = j;
item.cL = LENTH;
//初始速度
item.vY = getRandom(3, 20);
//加速度
item.aY = 15f;//9.8f;
pixelList.add(item);
}
}
}
}
animator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
time = 0;
isSecond = false;
isOver = false;
}
@Override
public void onAnimationEnd(Animator animation) {
time = 0;
isOver = true;
invalidate();
}
@Override
public void onAnimationCancel(Animator animation) {
//
}
@Override
public void onAnimationRepeat(Animator animation) {
//
}
});
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
int av = (int) animation.getAnimatedValue();
switch (animType) {
case ANIM_FADE:
if (av > CV / 2) {//一半
isSecond = true;
}
alphaCur = av;
alphaLast = CV - av;
break;
case ANIN_ROTATE:
rotate = MAX_GRADE + av;
break;
case ANIM_ROLL:
rotate = MAX_GRADE + av;
break;
case ANIM_RIGHT:
leftLast = -av - 10;//增加两图之间间隔
leftCur = CV - av;
break;
case ANIM_UP:
topLast = -av - 10;//增加两图之间间隔
topCur = CV - av;
break;
case ANIM_BOTTOM_UP:
topCur = CV - av;
break;
case ANIM_SCALE:
if (av > CV / 2) {//一半
isSecond = true;
}
if (!isSecond) {
//后面不用变化上一张 变小
rectLast.left = av;
rectLast.top = (int) (av / whRate);
rectLast.right = width - av;
rectLast.bottom = height - rectLast.top;
}
//当前:变大
rectCur.left = CV - av;
rectCur.top = (int) (rectCur.left / whRate);
rectCur.right = CV + av;
rectCur.bottom = height - rectCur.top;
break;
case ANIM_SCALE2:
//当前:变大
rectCur.left = CV - av;
rectCur.top = (int) (rectCur.left / whRate);
rectCur.right = CV + av;
rectCur.bottom = height - rectCur.top;
break;
case ANIM_CRASH:
time = animation.getCurrentPlayTime() / 1000f;//ms
break;
case ANIM_JUMP:
if (curIndex == 0) {
//右出
if (av < JUMP_THRESHOLD) {
//先向左移动
rectJump.left = -av;
} else {
//向右跳出
rectJump.left = av - JUMP_THRESHOLD;
}
} else {
//左出
if (av < JUMP_THRESHOLD) {
//先向左移动
rectJump.left = av;
} else {
//向右跳出
rectJump.left = JUMP_THRESHOLD - av;
}
}
rectJump.right = width + rectJump.left;
rectJump.top = 0;
rectJump.bottom = height;
break;
}
invalidate();
}
});
animator.start();
}
private float getRandom(int a, int b) {
return (float) (Math.random() * (b - a) + a);
}
/**
* 设置动画类型
*/
public void setAnimType(int animType) {
if (animType >= ANIM_NUM) {
//随机
this.isRandom = true;
return;
}
this.animType = animType;
resetAnimator();
}
/**
* 设置图片路径,默认路径存在(外部校验)
*
* @param path 图片路径
*/
public boolean setImageResource(String path) {
if (TextUtils.isEmpty(path)) {
return false;
}
if (path.equals(lastPath)) {
Log.d(TAG, "相同图片, 不切换!");
return true;
} else {
lastPath = path;
}
if (path.endsWith(".gif")) {
isGif = true;
movie = Movie.decodeFile(path);
return setImageResource(getMovieFirstFrame(movie, 500), path);
} else {
isGif = false;
return setImageResource(getDrawableFromFile(path), path);
}
}
/**
* 设置图片
*/
public boolean setImageResource(@DrawableRes int resId) {
Drawable d;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
d = context.getDrawable(resId);
} else {
d = context.getResources().getDrawable(resId);
}
return setImageResource(d, String.valueOf(resId));
}
/**
* 设置图片
*
* @return 是否成功播放
*/
public boolean setImageResource(Drawable drawable, String msg) {
if (drawable == null) {
Log.e(TAG, "图片资源为空!" + msg);
return false;
}
//重置透明度
drawable.setAlpha(MAX_ALPHA);
if (drawables == null) {
drawables = new Drawable[2];
}
curIndex++;//def -1
if (curIndex > 1) {
curIndex = 0;
}
if (drawables[curIndex] != null) {
drawables[curIndex] = null;//回收
}
drawables[curIndex] = drawable;
//Animators may only be run on Looper threads
if (isGif) {
//gif 文件直接播放,不用动画
invalidate();
} else {
doAnimation();
}
return true;
}
public void releaseBase() {
cancelAnim();
isGif = false;
movie = null;
lastPath = null;
drawables = null;
curIndex = -1;
gifPlayTime = 0;
if (cacheMap != null) {
cacheMap.clear();
cacheMap = null;
}
if (pixelList != null) {
pixelList.clear();
pixelList = null;
}
}
}