blob: 7210436c8692809a49a9768f188ae689debe703b [file] [log] [blame]
/*
* Copyright 2018 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.skottie;
import android.animation.Animator;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.net.Uri;
import android.util.AttributeSet;
import android.util.Log;
import android.view.SurfaceView;
import android.view.TextureView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import java.io.FileNotFoundException;
import java.io.InputStream;
import org.skia.skottielib.R;
public class SkottieView extends FrameLayout {
private SkottieAnimation mAnimation;
private View mBackingView;
private int mBackgroundColor;
// Repeat follows Animator API, infinite is represented by -1 (see Animator.DURATION_INFINITE)
private int mRepeatCount;
private static final int BACKING_VIEW_TEXTURE = 0;
private static final int BACKING_VIEW_SURFACE = 1;
private final String LOG_TAG = "SkottieView";
/*
* Build function for SkottieViews backed with a texture view
* Is the same as calling for a default SkottieView
*/
public SkottieView buildAsTexture(Context context) {
return new SkottieView(context);
}
/*
* Build function for SkottieViews backed with a surface view
* Backs the animation surface with a SurfaceView instead, requires background color
*/
public SkottieView buildAsSurface(Context context, int backgroundColor) {
SkottieView s = new SkottieView(context);
s.mBackingView = new SurfaceView(context);
s.mBackgroundColor = backgroundColor;
return s;
}
// Basic SkottieView, backing view defaults to TextureView
public SkottieView(Context context) {
super(context);
mBackingView = new TextureView(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 mRepeatCount
mRepeatCount = a.getInteger(R.styleable.SkottieView_android_repeatCount, 0);
// set backing view and background color
switch (a.getInteger(R.styleable.SkottieView_backing_view, -1)) {
case BACKING_VIEW_TEXTURE:
mBackingView = new TextureView(context);
((TextureView) mBackingView).setOpaque(false);
mBackgroundColor = a.getColor(R.styleable.SkottieView_background_color, 0);
break;
case BACKING_VIEW_SURFACE:
mBackingView = new SurfaceView(context);
mBackgroundColor = a.getColor(R.styleable.SkottieView_background_color, -1);
if (mBackgroundColor == -1) {
throw new RuntimeException("background_color attribute "
+ "needed for SurfaceView");
}
if (Color.alpha(mBackgroundColor) != 255) {
throw new RuntimeException("background_color cannot be transparent");
}
break;
default:
throw new RuntimeException("backing_view attribute needed to "
+ "specify between texture_view or surface_view");
}
// set source
int src = a.getResourceId(R.styleable.SkottieView_src, -1);
if (src != -1) {
setSource(src);
}
} finally {
a.recycle();
}
initBackingView();
}
private void initBackingView() {
mBackingView.setLayoutParams(new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT));
addView(mBackingView);
}
public void setSource(InputStream inputStream) {
mAnimation = setSourceHelper(inputStream);
}
public void setSource(int resId) {
InputStream inputStream = mBackingView.getResources().openRawResource(resId);
mAnimation = setSourceHelper(inputStream);
}
public void setSource(Context context, Uri uri) throws FileNotFoundException {
InputStream inputStream = context.getContentResolver().openInputStream(uri);
mAnimation = setSourceHelper(inputStream);
}
private SkottieAnimation setSourceHelper(InputStream inputStream) {
SkottieAnimation.Config config = null;
SkottieAnimation animation;
// if there is already an animation, save config and finalize it so as to not confuse GL
if (mAnimation != null) {
config = mAnimation.getBackingViewConfig();
try {
mAnimation.finalize();
} catch (Throwable t) {
Log.e(LOG_TAG, "existing animation couldn't finalize before setting new src");
}
}
if (mBackingView instanceof TextureView) {
animation = SkottieRunner.getInstance()
.createAnimation(((TextureView) mBackingView), inputStream, mBackgroundColor, mRepeatCount);
} else {
animation = SkottieRunner.getInstance()
.createAnimation(((SurfaceView) mBackingView), inputStream, mBackgroundColor, mRepeatCount);
}
// restore config settings from previous animation if needed
if (config != null) {
animation.setBackingViewConfig(config);
animation.setProgress(0f);
}
return animation;
}
protected SkottieAnimation getSkottieAnimation() {
return mAnimation;
}
public void removeListener(Animator.AnimatorListener listener) {
mAnimation.removeListener(listener);
}
public void addListener(Animator.AnimatorListener listener) {
mAnimation.addListener(listener);
}
// progress: a float from 0 to 1 representing the percent into the animation
public void seek(float progress) {
if(mAnimation != null) {
mAnimation.setProgress(progress);
}
}
public void play() {
if(mAnimation != null) {
mAnimation.resume();
}
}
public void pause() {
if(mAnimation != null) {
mAnimation.pause();
}
}
public void start() {
if(mAnimation != null) {
mAnimation.start();
}
}
public void stop() {
if(mAnimation != null) {
mAnimation.end();
}
}
public float getProgress() {
if(mAnimation != null) {
return mAnimation.getProgress();
}
return -1;
}
public void setRepeatCount(int repeatCount) {
mRepeatCount = repeatCount;
}
public void setBackgroundColor(int colorRGB) {
mBackgroundColor = colorRGB;
}
}