Flutter Engine
The Flutter Engine
SkottieActivity.java
Go to the documentation of this file.
1/*
2 * Copyright 2018 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8package org.skia.skottie;
9
10import android.app.Activity;
11import android.content.Intent;
12import android.graphics.Color;
13import android.graphics.Point;
14import android.net.Uri;
15import android.os.Bundle;
16import android.view.View;
17import android.view.ViewGroup;
18import android.widget.Button;
19import android.widget.GridLayout;
20
21import java.io.FileNotFoundException;
22import java.util.ArrayList;
23import java.util.List;
24import java.util.concurrent.CountDownLatch;
25import java.util.concurrent.TimeUnit;
26import java.util.concurrent.TimeoutException;
27
28import static java.lang.Math.ceil;
29import static java.lang.Math.sqrt;
30
31public class SkottieActivity extends Activity implements View.OnClickListener {
32
33 private final static long TIME_OUT_MS = 10000;
34
35 private CountDownLatch mEnterAnimationFence = new CountDownLatch(1);
36
37 private GridLayout mGrid;
38 private int mRowCount = 0;
39 private int mColumnCount = 0;
40 private int mCellWidth = 0;
41 private int mCellHeight = 0;
42
43 private List<SkottieView> mAnimations;
44 static private List<Uri> mAnimationFiles = new ArrayList<Uri>();
45
46 private void populateGrid() {
47 mRowCount = 0;
48 mColumnCount = 0;
49 mAnimations = new ArrayList<SkottieView>();
50 mCellWidth = 0;
51 mCellHeight = 0;
52
53 int[] rawAssets = {
54 R.raw.star,
55 R.raw.movie_loading,
56 R.raw.uk,
57 R.raw.white_material_wave_loading
58 };
59
60 for (int resId : rawAssets) {
61 SkottieView view = new SkottieView(this);
62 view.setSource(resId);
63 mAnimations.add(view);
64 }
65
66 for (Uri uri : mAnimationFiles) {
67 try {
68 SkottieView view = new SkottieView(this);
69 view.setSource(this, uri);
70 mAnimations.add(view);
71 } catch (FileNotFoundException e) {
72 e.printStackTrace();
73 }
74 }
75
76 Point size = new Point();
77 getWindowManager().getDefaultDisplay().getSize(size);
78 int screenWidth = size.x;
79 int screenHeight = (int)(size.y / 1.3f);
80
81 double unit = sqrt(mAnimations.size() / 6.0f);
82 mRowCount = (int)ceil(3 * unit);
83 mColumnCount = (int)ceil(2 * unit);
84 mGrid.setColumnCount(mColumnCount);
85 mGrid.setRowCount(mRowCount);
86 mCellWidth = screenWidth / mColumnCount;
87 mCellHeight = screenHeight / mRowCount;
88
89 refreshGrid();
90
91 startAnimation();
92
93 for (SkottieView view : mAnimations) {
94 view.setOnClickListener(new View.OnClickListener(){
95 public void onClick(View view){
96 inflateView((SkottieView)view);
97 }
98 });
99 }
100
101 if (mInflatedIndex >= 0) {
102 SkottieView view = mAnimations.get(mInflatedIndex);
103 mInflatedIndex = -1;
104 inflateView(view);
105 }
106 }
107
108 static int mInflatedIndex = -1;
109
110 private void inflateView(SkottieView view) {
111 if (mInflatedIndex >= 0) {
112 //deflate active view
113 SkottieView oldView = mAnimations.get(mInflatedIndex);
114 if (oldView != null) {
115 int row = mInflatedIndex / mColumnCount;
116 int column = mInflatedIndex % mColumnCount;
117 addView(oldView, row, column, false);
118 }
119 mInflatedIndex = -1;
120 //start and show animations that were in the background
121 for (SkottieView anyView : mAnimations) {
122 if (anyView != oldView) {
123 anyView.start();
124 anyView.setVisibility(View.VISIBLE);
125 }
126 }
127 return;
128 }
129
130 //stop and hide animations in the background
131 for (SkottieView anyView : mAnimations) {
132 if (anyView != view) {
133 anyView.stop();
134 anyView.setVisibility(View.INVISIBLE);
135 }
136 }
137
138 mInflatedIndex = mAnimations.indexOf(view);
139
140 GridLayout.Spec rowSpec = GridLayout.spec(0, mRowCount, GridLayout.CENTER);
141 GridLayout.Spec colSpec = GridLayout.spec(0, mColumnCount, GridLayout.CENTER);
142 GridLayout.LayoutParams params = new GridLayout.LayoutParams(rowSpec, colSpec);
143 params.width = ViewGroup.LayoutParams.MATCH_PARENT;
144 params.height = ViewGroup.LayoutParams.MATCH_PARENT;
145
146 mGrid.updateViewLayout(view, params);
147 }
148
149 private void refreshGrid() {
150 mGrid.removeAllViews();
151 int currentRaw = 0;
152 int row = 0;
153 int column = 0;
154 for (SkottieView view : mAnimations) {
155 addView(view, row, column, true);
156 column++;
157 if (column >= mColumnCount) {
158 column = 0;
159 row++;
160 }
161 }
162 }
163
164 private void addView(SkottieView view, int row , int column, boolean addView) {
165 GridLayout.Spec rowSpec = GridLayout.spec(row, 1, GridLayout.CENTER);
166 GridLayout.Spec colSpec = GridLayout.spec(column, 1, GridLayout.CENTER);
167 GridLayout.LayoutParams params = new GridLayout.LayoutParams(rowSpec, colSpec);
168 params.width = mCellWidth;
169 params.height = mCellHeight;
170 if (addView) {
171 mGrid.addView(view, params);
172 } else {
173 mGrid.updateViewLayout(view, params);
174 }
175 }
176
177 private void startAnimation() {
178 for (SkottieView view : mAnimations) {
179 view.start();
180 }
181 }
182
183 private void stopAnimation() {
184 for (SkottieView view : mAnimations) {
185 view.stop();
186 }
187 }
188
189 private void addLottie(Uri uri) throws FileNotFoundException {
190 int animations = mAnimations.size();
191 if (animations < mRowCount * mColumnCount) {
192 SkottieView view = new SkottieView(this);
193 view.setSource(this, uri);
194 int row = animations / mColumnCount;
195 int column = animations % mColumnCount;
196 mAnimations.add(view);
197 mAnimationFiles.add(uri);
198 view.setOnClickListener(new View.OnClickListener(){
199 public void onClick(View view){
200 inflateView((SkottieView)view);
201 }
202 });
203 addView(view, row, column, true);
204 view.start();
205 } else {
206 stopAnimation();
207 mAnimationFiles.add(uri);
208 populateGrid();
209 startAnimation();
210 }
211 }
212
213
214 @Override
216 super.onEnterAnimationComplete();
217 mEnterAnimationFence.countDown();
218 }
219
220 public void waitForEnterAnimationComplete() throws TimeoutException, InterruptedException {
221 if (!mEnterAnimationFence.await(TIME_OUT_MS, TimeUnit.MILLISECONDS)) {
222 throw new TimeoutException();
223 }
224 }
225
226 private void createLayout() {
227 setContentView(R.layout.main_layout);
228 Button open = (Button)findViewById(R.id.open_lottie);
229 open.setOnClickListener(this);
230
231 Button play = (Button)findViewById(R.id.play);
232 play.setOnClickListener(this);
233 Button pause = (Button)findViewById(R.id.pause);
234 pause.setOnClickListener(this);
235 Button reset = (Button)findViewById(R.id.reset);
236 reset.setOnClickListener(this);
237
238 mGrid = (GridLayout)findViewById(R.id.grid_lotties);
239 mGrid.setBackgroundColor(Color.LTGRAY);
240
241 populateGrid();
242 }
243
244 @Override
245 protected void onCreate(Bundle savedInstanceState) {
246 super.onCreate(savedInstanceState);
247
248 createLayout();
249 }
250
251 @Override
252 protected void onDestroy() {
253 super.onDestroy();
254 }
255
256 static final int PICK_FILE_REQUEST = 2;
257
258 @Override
259 public void onClick(View view) {
260 switch(view.getId()) {
261 case R.id.open_lottie:
262 Intent intent = new Intent();
263 intent.setType("application/json");
264 Intent i = Intent.createChooser(intent, "View Default File Manager");
265 startActivityForResult(i, PICK_FILE_REQUEST);
266 break;
267 case R.id.play:
268 for (SkottieView anim : mAnimations) {
269 anim.play();
270 }
271 break;
272 case R.id.pause:
273 for (SkottieView anim : mAnimations) {
274 anim.pause();
275 }
276 break;
277 case R.id.reset:
278 for (SkottieView anim : mAnimations) {
279 anim.seek(0f);
280 }
281 break;
282 }
283
284 }
285
286 @Override
287 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
288 super.onActivityResult(requestCode, resultCode, data);
289 if (resultCode == Activity.RESULT_OK) {
290 if (requestCode == PICK_FILE_REQUEST && data != null) {
291 //no data present
292 Uri uri = data.getData();
293
294 try {
295 addLottie(uri);
296 } catch (FileNotFoundException e) {
297 e.printStackTrace();
298 }
299 }
300 }
301 }
302}
m reset()
void onCreate(Bundle savedInstanceState)
void onActivityResult(int requestCode, int resultCode, Intent data)
void setSource(InputStream inputStream)
const EmbeddedViewParams * params
#define R(r)
SK_API sk_sp< SkShader > Color(SkColor)
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
TPoint< Scalar > Point
Definition: point.h:322
SIN Vec< N, float > sqrt(const Vec< N, float > &x)
Definition: SkVx.h:706
SIN Vec< N, float > ceil(const Vec< N, float > &x)
Definition: SkVx.h:702
std::shared_ptr< const fml::Mapping > data
Definition: texture_gles.cc:63