blob: 8dfc62c296440baab60ff2cf322ad0b2c233f9e9 [file] [log] [blame]
/*
* Copyright 2021 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
package org.skia.androidkit.util;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.SurfaceView;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import java.io.InputStream;
import org.skia.androidkit.Canvas;
import org.skia.androidkit.Color;
import org.skia.androidkit.Matrix;
import org.skia.androidkit.SkottieAnimation;
import org.skia.androidkit.Surface;
import org.skia.androidkit.R;
class SkottieRenderer extends SurfaceRenderer {
private float mSurfaceWidth,
mSurfaceHeight;
private Color mBackground;
private SkottieAnimation mAnimation;
private boolean mPlaying;
SkottieRenderer(SkottieAnimation mAnimation, Color mBackground) {
this.mAnimation = mAnimation;
this.mBackground = mBackground;
}
@Override
protected void onSurfaceInitialized(Surface surface) {
mSurfaceWidth = surface.getWidth();
mSurfaceHeight = surface.getHeight();
mPlaying = true;
}
@Override
protected void onRenderFrame(Canvas canvas, long ms) {
if(mPlaying) {
canvas.drawColor(mBackground);
double t = (double)ms / 1000 % mAnimation.getDuration();
mAnimation.seekTime(t);
float s = Math.min(mSurfaceWidth / mAnimation.getWidth(),
mSurfaceHeight / mAnimation.getHeight());
canvas.save();
canvas.concat(new Matrix().translate((mSurfaceWidth - s*mAnimation.getWidth())/2,
(mSurfaceHeight - s*mAnimation.getHeight())/2)
.scale(s, s));
mAnimation.render(canvas);
canvas.restore();
}
}
void play() {
if (!mPlaying) {
mPlaying = true;
}
}
void pause() {
if (mPlaying) {
mPlaying = false;
}
}
SkottieAnimation getAnimation() {
return mAnimation;
}
@Override
public void release() {
mAnimation.release();
super.release();
}
@Override
protected void finalize() throws Throwable {
this.release();
}
}
public class SkottieView extends FrameLayout {
private SurfaceView mBackingView;
private SkottieRenderer mRenderer;
private final String LOG_TAG = "SkottieView";
public SkottieView(Context context, int resID, Color background) {
super(context);
mBackingView = new SurfaceView(context);
initBackingView();
InputStream inputStream = context.getResources().openRawResource(resID);
mRenderer = new SkottieRenderer(makeAnimation(inputStream), background);
mBackingView.getHolder().addCallback(mRenderer);
}
public SkottieView(Context context) {
super(context);
mBackingView = new SurfaceView(context);
initBackingView();
}
public SkottieView(Context context, AttributeSet attrs) {
this(context, attrs, 0, 0);
}
public SkottieView(Context context, AttributeSet attrs, int defStyleAttr) {
this(context, attrs, defStyleAttr, 0);
}
// SkottieView constructor when initialized in XML layout
public SkottieView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs);
TypedArray a = context.getTheme()
.obtainStyledAttributes(attrs, R.styleable.SkottieView, defStyleAttr, defStyleRes);
try {
// set backing view and background color
mBackingView = new SurfaceView(context);
initBackingView();
int backgroundColor = a.getColor(R.styleable.SkottieView_background_color, -1);
if (backgroundColor == -1) {
throw new RuntimeException("background_color attribute "
+ "needed for SurfaceView");
}
if (android.graphics.Color.alpha(backgroundColor) != 255) {
throw new RuntimeException("background_color cannot be transparent");
}
// set source
int src = a.getResourceId(R.styleable.SkottieView_src, -1);
Color c = new Color(backgroundColor);
setSource(src, context, new Color(backgroundColor));
} finally {
a.recycle();
}
}
private void initBackingView() {
mBackingView.setLayoutParams(new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT));
addView(mBackingView);
}
static private SkottieAnimation makeAnimation(InputStream is) {
String json = "";
try {
byte[] data = new byte[is.available()];
is.read(data);
json = new String(data);
} catch (Exception e) {}
return new SkottieAnimation(json);
}
public void setSource(int resID, Context context, Color background) {
InputStream inputStream = context.getResources().openRawResource(resID);
mRenderer = new SkottieRenderer(makeAnimation(inputStream), background);
mBackingView.getHolder().addCallback(mRenderer);
}
public void play() {
mRenderer.play();
}
public void pause() {
mRenderer.pause();
}
public void seekTime(double t) {
mRenderer.setBaseTime(java.lang.System.currentTimeMillis() - ((long)t * 1000));
}
public void seekFrame(double f) {
double totalFrames = mRenderer.getAnimation().getFrameCount();
double totalTime = mRenderer.getAnimation().getDuration();
double targetTime = (f % totalFrames) / totalFrames * totalTime;
seekTime(targetTime);
}
}