SVGA JAVA库在源码AOSP Android.mk中引用及应用

SVGA 纯Java库做成

我用Android studio kotlin插件自带的转化工具,这个百度都有就不说了。不过不能百分百转化,有些问题就要自己手动改了。还要有些系统不支持的也要换,比如lambda表达式Java7不支持,就改掉了。依赖的kotlin库也要换成Java的。
然后我把SVGA在mk中配置成静态jar包:svga

SVGA库引用

在Android.mk中配置:

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)

LOCAL_SRC_FILES := $(call all-java-files-under, src) 

LOCAL_PACKAGE_NAME := svgademo

LOCAL_PRIVILEGED_MODULE := true

LOCAL_DEX_PREOPT:=false

LOCAL_CERTIFICATE := platform

LOCAL_MODULE_TAGS := optional

LOCAL_PROGUARD_ENABLED := disabled
LOCAL_PROGUARD_FLAG_FILES := proguard-rules.pro

LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res \
    frameworks/support/v7/appcompat/res \
    vendor/nextev/frameworks/support/3rdparty/svga/res

LOCAL_ASSET_DIR :=  $(LOCAL_PATH)/assets

LOCAL_STATIC_JAVA_LIBRARIES += \
    svga \

LOCAL_AAPT_FLAGS := --auto-add-overlay \
                --extra-packages android.support.v7.appcompat \
                --extra-packages com.opensource.svgaplayer \
                

include $(BUILD_PACKAGE)

include $(call all-makefiles-under,$(LOCAL_PATH))


SVGA使用

layout XML配置

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".SimpleActivity">

    <com.opensource.svgaplayer.SVGAImageView
        android:id="@+id/svgaImage"
        android:layout_width="match_parent"
        android:layout_height="658dp"
        android:layout_alignParentTop="true"
        app:autoPlay="true"
        app:loopCount="1"
        app:clearsAfterStop = "false"/>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:orientation="horizontal">
        
       ...
       我的Button控件
       ...
       
    </LinearLayout>

</RelativeLayout>

在 XML 中,允许定义以下这些标签:

用于表示 svga 文件的路径,提供一个在 assets 目录下的文件名,或者提供一个 http url 地址。

source: String

默认为 true,当动画加载完成后,自动播放。

autoPlay: Boolean

默认为 0,设置动画的循环次数,0 表示无限循环。

loopCount: Int

默认为 true,当动画播放完成后,是否清空画布。

clearsAfterStop: Boolean

默认为 true,当 SVGAImageView 触发 onDetachedFromWindow 方法时,是否清空画布。

clearsAfterStop: Boolean

默认为 Forward,可以是 Forward、 Backward。

fillMode: Forward/Backward
Forward 表示动画结束后,将停留在最后一帧。
Backward 表示动画结束后,将停留在第一帧。

资源文件

把.svga文件放到assets文件下,Android.mk中LOCAL_ASSET_DIR配置好路径。

ActivityMain

package com.tecinno.svgaplayer;

import android.app.Activity;
import android.net.http.HttpResponseCache;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import java.io.File;
import java.io.IOException;
import com.opensource.svgaplayer.SVGAImageView;

public class SimpleActivity extends Activity {

    private Button button1, button2, button3, button4;
    private SVGAImageView svgaImage;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_simple);
        //播放网络动画时需要配置的缓存
        try {
            File cacheDir  = new  File(getApplicationContext().getCacheDir(),"http");
            HttpResponseCache.install(cacheDir, 1024 * 1024 * 128);
        } catch (IOException e) {
            e.printStackTrace();
        }
        initView();
    }

    private void initView(){
        button1 = findViewById(R.id.button1);
        button2 = findViewById(R.id.button2);
        button3 = findViewById(R.id.button3);
        button4 = findViewById(R.id.button4);
        svgaImage = findViewById(R.id.svgaImage);

        final SvgaUtils svgaUtils = new SvgaUtils(SimpleActivity.this, svgaImage);
        //startAnimator前需要先initAnimator,完成一些监听注册
        svgaUtils.initAnimator();

        //button监听
        button1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                svgaUtils.startAnimator("alarm", true);
            }
        });
        button2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                svgaUtils.startAnimator("angel", false);
            }
        });
        button3.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                svgaUtils.startAnimator("posche", false);
            }
        });
        button4.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                svgaUtils.startAnimator("rose_1.5.0", false);
            }
        });
    }
}

SVGAUtils

showSVGAStep()可以监听手指左右滑动来正反播放动画。

package com.tecinno.svgaplayer;

import android.content.Context;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import com.opensource.svgaplayer.SVGACallback;
import com.opensource.svgaplayer.SVGADrawable;
import com.opensource.svgaplayer.SVGADynamicEntity;
import com.opensource.svgaplayer.SVGAImageView;
import com.opensource.svgaplayer.SVGAParser;
import com.opensource.svgaplayer.SVGARange;
import com.opensource.svgaplayer.SVGAVideoEntity;
import java.net.URL;

/**
 * author: jieqin.liu
 * date: on 2021/02/23.
 * describe:SVGA工具类
 * 使用时首先调用初始化数据方法,
 * 然后再调用开始动画的方法
 */

public class SvgaUtils {
    private Context context;
    private SVGAImageView svgaImage;
    private SVGAParser parser;
    private final static String TAG = "SvgaUtils";
    private String needLoop;
    private SVGARange ran;
    private FrameEntry frameEntry;

    public SvgaUtils(Context context, SVGAImageView svgaImage) {
        this.context = context;
        this.svgaImage = svgaImage;
        //播放的帧顺序,第一个参数是开始位置,第二个参数是帧数
        ran = new SVGARange(9,20);
    }

    /**
     * 初始化数据
     */
    public void initAnimator() {
        //左右滑动播放动画的灵敏度
        final int slideSpeed = 10;
        parser = new SVGAParser(context);
        //监听大动画的控件周期
        svgaImage.setCallback(new SVGACallback() {
            @Override
            public void onPause() {
                Log.e(TAG, "onPause");
            }

            @Override
            public void onFinished() {
                Log.e(TAG, "onFinished"+ (needLoop.equals("yes")? ", loop play":" "));
                if(needLoop.equals("no")){
                    stopSVGA();
                } else {
                	//从第几帧开始播放,正序播放
                    svgaImage.stepToFrame(0, false);

                    //以给定的顺序播放,倒序播放
//                    svgaImage.startAnimation(ran,true);

                    //以给定的顺序播放,正序播放
//                    svgaImage.startAnimation(ran,false);
                }
            }

            @Override
            public void onRepeat() {
                Log.e(TAG, "onRepeat");
                stopSVGA();
            }

            @Override
            public void onStep(int i, double v) {
                Log.e(TAG, "onStep i :"+i+", maxFrame : " + frameEntry.maxFrame);
                //保存当前是第几帧
                frameEntry.currentFrame = i;
            }
        });
        //滑动监听
        svgaImage.setOnTouchListener(new View.OnTouchListener() {

            @Override
            public boolean onTouch(View v, MotionEvent event) {

                switch (event.getAction()) {
                    // 按下
                    case MotionEvent.ACTION_DOWN:
                        Log.e(TAG,"ACTION_DOWN X "+ event.getX()+ " Y "+event.getY());
                        break;
                    // 移动
                    case MotionEvent.ACTION_MOVE:
                        Log.e(TAG,"ACTION_MOVE X "+ event.getX()+ " Y "+event.getY());
                        float currentPosX = event.getX();
                        if(currentPosX - frameEntry.mPosX > slideSpeed){
                            frameEntry.mPosX = currentPosX;
                            showSVGAStep(false);
                        } else if(frameEntry.mPosX - currentPosX > slideSpeed){
                            frameEntry.mPosX = currentPosX;
                            showSVGAStep(true);
                        }
                        break;
                    // 拿起
                    case MotionEvent.ACTION_UP:
                        Log.e(TAG,"ACTION_UP X "+ event.getX()+ " Y "+event.getY());
                        break;
                    default:
                        break;
                }
                return true;
            }
        });
    }

    /**
     * 显示动画
     */
    public void startAnimator(String svgaName, boolean isLoop) {
        Log.e(TAG,"startAnimator");
        if (svgaName != null) {
            needLoop = isLoop ? "yes" : "no";
            //播放本地动画
            showSVGA(svgaName);
            //播放网络动画
//            showNetSVGA("https://github.com/yyued/SVGA-Samples/blob/master/posche.svga?raw=true");
            //播放网络动画并插入图片
//            showdynamicSVGA("https://github.com/yyued/SVGA-Samples/blob/master/kingset.svga?raw=true");

        } else {
            Log.e(TAG,"startAnimator svgaName is null");
            return;
        }
    }

    /**
     * 停止动画
     */
    private void stopSVGA() {
        if (svgaImage.isAnimating()) {
            svgaImage.stopAnimation();
        }
    }
    /**
     * 滑动播放动画,向右滑动顺序播放,向左滑动倒序播放
     * reserse:播放顺序,顺序播放或者倒放
     */
    public void showSVGAStep(boolean reverse){
        if(svgaImage == null && frameEntry == null){
            Log.e(TAG, svgaImage == null ? "svgaImage is null" : "frameEntry is null");
            return;
        }
        int nextFrame;
        SVGARange range;
        if(reverse){ //倒序播放
            //下一帧
            nextFrame = frameEntry.currentFrame - 1;
            //配置播放的帧和帧数
            range = new SVGARange(nextFrame < 0 ? frameEntry.maxFrame : nextFrame,1);
        } else{//顺序播放
            //下一帧
            nextFrame = frameEntry.currentFrame + 1;
            //配置播放的帧和帧数
            range = new SVGARange(nextFrame >= frameEntry.maxFrame ? 0:nextFrame, 1);
        }
        //开始播放
        svgaImage.startAnimation(range, reverse);
    }
    /**
     * 播放动画
     */
    private void showSVGA(String svagName) {
        try {
            parser.parse(svagName+".svga", new SVGAParser.ParseCompletion() {
                @Override
                public void onComplete(SVGAVideoEntity svgaVideoEntity) {
                    //保存当前动画最大帧数,方便后面随机播放
                    frameEntry = new FrameEntry(svgaVideoEntity.getFrames());
                    //解析动画成功,到这里才真正的显示动画
                    SVGADrawable drawable = new SVGADrawable(svgaVideoEntity);
                    svgaImage.setImageDrawable(drawable);
                    svgaImage.startAnimation();
                }
                @Override
                public void onError() {
                    //停止播放
                    stopSVGA();
                }
            });
        } catch (Exception e) {
            Log.e(TAG,"show svga error : "+e);
        }
    }

    /**
     * 播放网络动画
     */
    private void showNetSVGA(String svagURL) {
        try {
            parser.parse(new URL(svagURL), new SVGAParser.ParseCompletion() {
                @Override
                public void onComplete(SVGAVideoEntity svgaVideoEntity) {
                    //保存当前动画最大帧数,方便后面随机播放
                    frameEntry = new FrameEntry(svgaVideoEntity.getFrames());
                    //解析动画成功,到这里才真正的显示动画
                    svgaImage.setVideoItem(svgaVideoEntity);
                    svgaImage.startAnimation();
                }
                @Override
                public void onError() {
                    //停止播放
                    stopSVGA();
                }
            });
        } catch (Exception e) {
            Log.e(TAG,"show svga error : "+e);
        }
    }
    /**
     * 播放动态动画,动画中插入自定义图片
     */
    private void showdynamicSVGA(String svagURL) {
        try {
            parser.parse(new URL(svagURL), new SVGAParser.ParseCompletion() {
                @Override
                public void onComplete(SVGAVideoEntity svgaVideoEntity) {
                    //保存当前动画最大帧数,方便后面随机播放
                    frameEntry = new FrameEntry(svgaVideoEntity.getFrames());
                    //解析动画成功,到这里才真正的显示动画
                    SVGADynamicEntity dynamicEntity = new SVGADynamicEntity();
                    dynamicEntity.setDynamicImage("https://github.com/PonyCui/resources/blob/master/svga_replace_avatar.png?raw=true", "99"); // Here is the KEY implementation.
                    SVGADrawable drawable = new SVGADrawable(svgaVideoEntity, dynamicEntity);
                    svgaImage.setImageDrawable(drawable);
                    svgaImage.startAnimation();
                }
                @Override
                public void onError() {
                    //停止播放
                    stopSVGA();
                }
            });
        } catch (Exception e) {
            Log.e(TAG,"show svga error : "+e);
        }
    }
    /*
    * 随机播放动画时保存的动画和touch位置信息,需要在parser完成时初始化。
    *
    * mPosX:当前touch X轴位置
    * currentFrame:当前播放的是第几帧
    * maxFrame:该动画有多少帧
    *
    * */
    public class FrameEntry{
        //当前触点X轴位置
        public float mPosX;
        //当前播放是第几帧
        public int currentFrame;
        //最大帧数
        public int maxFrame;

        public FrameEntry(int maxFrame){
            mPosX = 0;
            currentFrame = 0;
            this.maxFrame = maxFrame;
        }
    }

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值