Skip to content

Commit 6c62f8c

Browse files
committed
...
1 parent 9b86744 commit 6c62f8c

File tree

12 files changed

+198
-13
lines changed

12 files changed

+198
-13
lines changed

app/src/main/AndroidManifest.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
android:theme="@style/AppTheme"
1010
android:hardwareAccelerated="true" >
1111
<activity
12-
android:name=".MainActivity"
12+
android:name=".SimpleActivity"
1313
android:label="@string/app_name" >
1414
<intent-filter>
1515
<action android:name="android.intent.action.MAIN" />

app/src/main/assets/angel.svga

-326 KB
Binary file not shown.

app/src/main/assets/angel2.svga

-277 KB
Binary file not shown.

app/src/main/assets/posche.svga

198 KB
Binary file not shown.

app/src/main/java/com/example/ponycui_home/svgaplayer/MainActivity.java

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import android.util.AttributeSet;
2121
import android.view.View;
2222

23+
import com.opensource.svgaplayer.SVGACallback;
2324
import com.opensource.svgaplayer.SVGACanvasDrawer;
2425
import com.opensource.svgaplayer.SVGADrawable;
2526
import com.opensource.svgaplayer.SVGADynamicEntity;
@@ -38,6 +39,12 @@
3839
import okhttp3.Request;
3940
import okhttp3.Response;
4041

42+
43+
/**
44+
* Created by cuiminghui on 2017/3/30.
45+
* 这是最复杂的一个 Sample, 演示了从网络加载动画,并播放动画。
46+
*/
47+
4148
public class MainActivity extends AppCompatActivity {
4249

4350
SVGAImageView testView = null;
@@ -48,6 +55,7 @@ protected void onCreate(@Nullable Bundle savedInstanceState) {
4855
super.onCreate(savedInstanceState);
4956
testView = new SVGAImageView(this);
5057
testView.setBackgroundColor(Color.GRAY);
58+
setupCallback();
5159
loadDynamicText();
5260
loadDynamicBitmap(new Runnable() {
5361
@Override
@@ -58,6 +66,31 @@ public void run() {
5866
setContentView(testView);
5967
}
6068

69+
private void setupCallback() {
70+
testView.setCallback(new SVGACallback() {
71+
@Override
72+
public void onPause() {
73+
74+
}
75+
76+
@Override
77+
public void onFinished() {
78+
79+
}
80+
81+
@Override
82+
public void onRepeat() {
83+
84+
}
85+
86+
@Override
87+
public void onStep(int frame, double percentage) {
88+
// System.out.println("当前帧:" + frame);
89+
// System.out.println("当前百分比:" + percentage);
90+
}
91+
});
92+
}
93+
6194
// 加载动态图像
6295
private void loadDynamicBitmap(final Runnable complete) {
6396
OkHttpClient client = new OkHttpClient();
@@ -115,7 +148,7 @@ private static Bitmap getRoundedCornerBitmap(Bitmap bitmap, int pixels) {
115148
private void loadAnimation() {
116149
SVGAParser parser = new SVGAParser(this);
117150
try {
118-
parser.parse(new URL("http://legox.yy.com/svga/svga-me/kingset_dyn.svga"), new SVGAParser.ParseCompletion() {
151+
parser.parse(new URL("http://legox.yy.com/svga/svga-me/angel.svga"), new SVGAParser.ParseCompletion() {
119152
@Override
120153
public void onComplete(@NotNull SVGAVideoEntity videoItem) {
121154
SVGADrawable drawable = new SVGADrawable(videoItem, dynamicItem);
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package com.example.ponycui_home.svgaplayer;
2+
3+
import android.app.Activity;
4+
import android.os.Bundle;
5+
6+
/**
7+
* Created by cuiminghui on 2017/3/30.
8+
* 将 svga 文件打包到 assets 文件夹中,然后使用 layout.xml 加载动画。
9+
*/
10+
11+
public class SimpleActivity extends Activity {
12+
13+
@Override
14+
protected void onCreate(Bundle savedInstanceState) {
15+
super.onCreate(savedInstanceState);
16+
setContentView(R.layout.activity_simple);
17+
}
18+
19+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
3+
xmlns:app="http://schemas.android.com/apk/res-auto"
4+
android:orientation="vertical"
5+
android:layout_width="match_parent"
6+
android:layout_height="match_parent">
7+
8+
<com.opensource.svgaplayer.SVGAImageView
9+
android:layout_height="match_parent"
10+
android:layout_width="match_parent"
11+
app:source="posche.svga"
12+
app:autoPlay="true"
13+
android:background="#000" />
14+
15+
</RelativeLayout>
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package com.opensource.svgaplayer
2+
3+
/**
4+
* Created by cuiminghui on 2017/3/30.
5+
*/
6+
interface SVGACallback {
7+
8+
fun onPause()
9+
fun onFinished()
10+
fun onRepeat()
11+
fun onStep(frame: Int, percentage: Double)
12+
13+
}

library/src/main/java/com/opensource/svgaplayer/SVGACanvasDrawer.kt

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,10 @@ class SVGACanvasDrawer(videoItem: SVGAVideoEntity, val dynamicItem: SVGADynamicE
1717

1818
override fun drawFrame(frameIndex: Int) {
1919
super.drawFrame(frameIndex)
20-
val t = System.currentTimeMillis()
2120
val sprites = requestFrameSprites(frameIndex)
2221
sprites.forEach {
2322
drawSprite(it)
2423
}
25-
val e = System.currentTimeMillis()
26-
val o = e - t
27-
System.out.println("帧渲染耗时" + o + "ms")
2824
}
2925

3026
private fun drawSprite(sprite: SVGADrawerSprite) {

library/src/main/java/com/opensource/svgaplayer/SVGAImageView.kt

Lines changed: 84 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -49,21 +49,63 @@ class SVGADrawable(val videoItem: SVGAVideoEntity, val dynamicItem: SVGADynamicE
4949

5050
}
5151

52-
class SVGAImageView : ImageView {
52+
open class SVGAImageView : ImageView {
53+
54+
enum class FillMode {
55+
Backward,
56+
Forward,
57+
}
5358

5459
var loops = 0
5560

5661
var clearsAfterStop = true
5762

63+
var fillMode: FillMode = FillMode.Forward
64+
65+
var callback: SVGACallback? = null
66+
5867
private var animator: ValueAnimator? = null
5968

6069
constructor(context: Context) : super(context) {}
6170

62-
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {}
71+
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
72+
loadAttrs(attrs)
73+
}
6374

64-
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {}
75+
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
76+
loadAttrs(attrs)
77+
}
6578

66-
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int, defStyleRes: Int) : super(context, attrs, defStyleAttr, defStyleRes) {}
79+
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int, defStyleRes: Int) : super(context, attrs, defStyleAttr, defStyleRes) {
80+
loadAttrs(attrs)
81+
}
82+
83+
fun loadAttrs(attrs: AttributeSet) {
84+
val typedArray = context.theme.obtainStyledAttributes(attrs, R.styleable.SVGAImageView, 0, 0)
85+
loops = typedArray.getInt(R.styleable.SVGAImageView_loopCount, 0)
86+
clearsAfterStop = typedArray.getBoolean(R.styleable.SVGAImageView_clearsAfterStop, true)
87+
typedArray.getString(R.styleable.SVGAImageView_source).let {
88+
val parser = SVGAParser(context)
89+
Thread({
90+
parser.parse(it)?.let {
91+
handler.post({
92+
setVideoItem(it)
93+
if (typedArray.getBoolean(R.styleable.SVGAImageView_autoPlay, true)) {
94+
startAnimation()
95+
}
96+
})
97+
}
98+
}).start()
99+
}
100+
typedArray.getString(R.styleable.SVGAImageView_fillMode)?.let {
101+
if (it.equals("0")) {
102+
fillMode = FillMode.Backward
103+
}
104+
else if (it.equals("1")) {
105+
fillMode = FillMode.Forward
106+
}
107+
}
108+
}
67109

68110
fun startAnimation() {
69111
val drawable = drawable as? SVGADrawable ?: return
@@ -85,11 +127,21 @@ class SVGAImageView : ImageView {
85127
animator.addUpdateListener {
86128
drawable.currentFrame = animator.animatedValue as Int
87129
drawable.invalidateSelf()
130+
callback?.onStep(drawable.currentFrame, ((drawable.currentFrame + 1).toDouble() / drawable.videoItem.frames.toDouble()))
88131
}
89132
animator.addListener(object : Animator.AnimatorListener {
90-
override fun onAnimationRepeat(animation: Animator?) {}
133+
override fun onAnimationRepeat(animation: Animator?) {
134+
callback?.onRepeat()
135+
}
91136
override fun onAnimationEnd(animation: Animator?) {
92137
stopAnimation()
138+
if (!clearsAfterStop) {
139+
if (fillMode == FillMode.Backward) {
140+
drawable.currentFrame = 0
141+
drawable.invalidateSelf()
142+
}
143+
}
144+
callback?.onFinished()
93145
}
94146
override fun onAnimationCancel(animation: Animator?) {}
95147
override fun onAnimationStart(animation: Animator?) {}
@@ -101,6 +153,7 @@ class SVGAImageView : ImageView {
101153

102154
fun pauseAnimation() {
103155
stopAnimation(false)
156+
callback?.onPause()
104157
}
105158

106159
fun stopAnimation() {
@@ -116,11 +169,35 @@ class SVGAImageView : ImageView {
116169
}
117170

118171
fun setVideoItem(videoItem: SVGAVideoEntity) {
119-
setImageDrawable(SVGADrawable(videoItem))
172+
setVideoItem(videoItem, SVGADynamicEntity())
120173
}
121174

122175
fun setVideoItem(videoItem: SVGAVideoEntity, dynamicItem: SVGADynamicEntity) {
123-
setImageDrawable(SVGADrawable(videoItem, dynamicItem))
176+
val drawable = SVGADrawable(videoItem, dynamicItem)
177+
drawable.cleared = clearsAfterStop
178+
setImageDrawable(drawable)
179+
}
180+
181+
fun stepToFrame(frame: Int, andPlay: Boolean) {
182+
pauseAnimation()
183+
val drawable = drawable as? SVGADrawable ?: return
184+
drawable.currentFrame = frame
185+
drawable.invalidateSelf()
186+
if (andPlay) {
187+
startAnimation()
188+
animator?.let {
189+
it.currentPlayTime = (Math.max(0.0f, Math.min(1.0f, (frame.toFloat() / drawable.videoItem.frames.toFloat()))) * it.duration).toLong()
190+
}
191+
}
192+
}
193+
194+
fun stepToPercentage(percentage: Double, andPlay: Boolean) {
195+
val drawable = drawable as? SVGADrawable ?: return
196+
var frame = (drawable.videoItem.frames * percentage).toInt()
197+
if (frame >= drawable.videoItem.frames && frame > 0) {
198+
frame = drawable.videoItem.frames - 1
199+
}
200+
stepToFrame(frame, andPlay)
124201
}
125202

126203
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package com.opensource.svgaplayer
2+
3+
import android.content.Context
4+
import android.util.AttributeSet
5+
6+
/**
7+
* Created by cuiminghui on 2017/3/30.
8+
*/
9+
class SVGAPlayer: SVGAImageView {
10+
11+
constructor(context: Context) : super(context) {}
12+
13+
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {}
14+
15+
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {}
16+
17+
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int, defStyleRes: Int) : super(context, attrs, defStyleAttr, defStyleRes) {}
18+
19+
}

library/src/main/res/values/attrs.xml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<resources>
3+
<declare-styleable name="SVGAImageView">
4+
<attr name="source" format="string" />
5+
<attr name="autoPlay" format="boolean" />
6+
<attr name="loopCount" format="integer" />
7+
<attr name="clearsAfterStop" format="boolean" />
8+
<attr name="fillMode" format="enum">
9+
<enum name="Backward" value="0" />
10+
<enum name="Forward" value="1" />
11+
</attr>
12+
</declare-styleable>
13+
</resources>

0 commit comments

Comments
 (0)