Compare commits
60 Commits
gh-pages
...
fix_github
Author | SHA1 | Date | |
---|---|---|---|
a6152cc14e | |||
2360f643b7 | |||
1146e1f01d | |||
ba0bfcd126 | |||
cb8006d362 | |||
bf7d0ebf05 | |||
57faea6f5e | |||
548c77dc45 | |||
45a4c0b981 | |||
32b1181dad | |||
fcfe54686d | |||
b9aba4dce2 | |||
2cb1aefb2a | |||
478bd27e89 | |||
ef06d63040 | |||
0715f6a402 | |||
7e81ec3f69 | |||
f9f093a8a2 | |||
7c137ee55f | |||
8f4952a23a | |||
8bad4f96c0 | |||
bb73626c46 | |||
47e47f5cb8 | |||
954ec05598 | |||
66e644d043 | |||
3dab382b76 | |||
078e661fd4 | |||
336890cafe | |||
35ca2dc972 | |||
78aeed452f | |||
af9b69326a | |||
511094262f | |||
62a60208b2 | |||
c0c3ecbf5e | |||
d525de877e | |||
2914caf220 | |||
e89c3c4914 | |||
4ae257eaab | |||
fc683482db | |||
0d642c52f1 | |||
fe748895d3 | |||
42833c6429 | |||
c9a6a6a187 | |||
6eb9210952 | |||
20405b1c5f | |||
c383dc6be1 | |||
98c2efe12d | |||
17618ad360 | |||
3f45f372e5 | |||
289db49ad7 | |||
2489c48a19 | |||
b017066bad | |||
55674366fd | |||
45e1e9de7a | |||
a63b752ccc | |||
be0a3bbdad | |||
7cc0bcf5b3 | |||
d42f6b4b68 | |||
7cf36414ca | |||
711087fd25 |
35
.github/workflows/analyze-and-test.yaml
vendored
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
name: Lottie Flutter
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
analyze_and_test:
|
||||||
|
name: Flutter analyze
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
flutter: ['beta']
|
||||||
|
runs-on: macos-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- uses: subosito/flutter-action@v1
|
||||||
|
with:
|
||||||
|
channel: ${{ matrix.flutter }}
|
||||||
|
- run: flutter doctor
|
||||||
|
- run: flutter --version
|
||||||
|
- run: flutter pub get
|
||||||
|
working-directory: example
|
||||||
|
- run: flutter analyze
|
||||||
|
- run: flutter test test # https://github.com/flutter/flutter/issues/20907
|
||||||
|
- run: flutter test test
|
||||||
|
working-directory: example
|
||||||
|
- run: flutter pub run tool/prepare_submit.dart
|
||||||
|
- name: "check for uncommitted changes"
|
||||||
|
run: |
|
||||||
|
git diff --exit-code --stat -- . ':(exclude)*pubspec.lock' \
|
||||||
|
|| (echo "##[error] found changed files after build. please run 'dart tool/prepare_submit.dart'" \
|
||||||
|
"and check in all changes" \
|
||||||
|
&& exit 1)
|
||||||
|
shell: bash
|
32
.github/workflows/publish-on-pub.yaml
vendored
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
name: Publish package to pub.dev
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
# tags:
|
||||||
|
# - v*
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- uses: subosito/flutter-action@v1
|
||||||
|
with:
|
||||||
|
channel: 'beta'
|
||||||
|
- run: flutter pub get
|
||||||
|
- run: flutter pub run tool/publish/comment_dependency_overrides.dart
|
||||||
|
- run: flutter pub get
|
||||||
|
- run: echo ${GITHUB_REF}
|
||||||
|
- run: flutter pub run tool/publish/check_version.dart ${GITHUB_REF}
|
||||||
|
# - name: Setup credentials
|
||||||
|
# run: |
|
||||||
|
# mkdir -p $FLUTTER_HOME/.pub-cache
|
||||||
|
# cat <<EOF > $FLUTTER_HOME/.pub-cache/credentials.json
|
||||||
|
# {
|
||||||
|
# "accessToken":"${{ secrets.OAUTH_ACCESS_TOKEN }}",
|
||||||
|
# "refreshToken":"${{ secrets.OAUTH_REFRESH_TOKEN }}",
|
||||||
|
# "tokenEndpoint":"https://accounts.google.com/o/oauth2/token",
|
||||||
|
# "scopes": [ "openid", "https://www.googleapis.com/auth/userinfo.email" ],
|
||||||
|
# "expiration": 1580681402856
|
||||||
|
# }
|
||||||
|
# EOF
|
||||||
|
# - name: Publish package
|
||||||
|
# run: flutter pub publish --force
|
11
.gitignore
vendored
@ -0,0 +1,11 @@
|
|||||||
|
.*
|
||||||
|
_*
|
||||||
|
|
||||||
|
!.gitignore
|
||||||
|
!.github
|
||||||
|
|
||||||
|
**/failures/*.png
|
||||||
|
|
||||||
|
*.iml
|
||||||
|
**/doc/api/
|
||||||
|
build/
|
||||||
|
10
.metadata
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
# This file tracks properties of this Flutter project.
|
||||||
|
# Used by Flutter tool to assess capabilities and perform upgrades etc.
|
||||||
|
#
|
||||||
|
# This file should be version controlled and should not be manually edited.
|
||||||
|
|
||||||
|
version:
|
||||||
|
revision: 27321ebbad34b0a3fafe99fac037102196d655ff
|
||||||
|
channel: stable
|
||||||
|
|
||||||
|
project_type: package
|
105
CHANGELOG.md
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
## [0.7.1]
|
||||||
|
- Fix a crash for some lottie file with empty paths.
|
||||||
|
|
||||||
|
## [0.7.0+1]
|
||||||
|
- Fix Flutter Web compilation error
|
||||||
|
|
||||||
|
## [0.7.0]
|
||||||
|
- Performance improvement for complex animations.
|
||||||
|
|
||||||
|
## [0.6.0]
|
||||||
|
- Runs the animation at the frame rate specified in the json file (ie. An animation encoded with a 20 FPS will only
|
||||||
|
be paint 20 times per seconds even though the AnimationController will invalidate the widget 60 times per seconds).
|
||||||
|
A new property `frameRate` allows to opt-out this behavior and have the widget to repaint at the device frame rate
|
||||||
|
(`FrameRate.max`).
|
||||||
|
- Automatically add a `RepaintBoundary` around the widget. Since `Lottie` animations are generally complex to paint, a
|
||||||
|
`RepaintBoundary` will separate the animation with the rest of the app and improve performance. A new property `addRepaintBoundary`
|
||||||
|
allows to opt-out this behavior.
|
||||||
|
- Fix a bug where we would call `markNeedPaint` when the animation was not changing. This removes unnecessary paints in
|
||||||
|
animations with static periods.
|
||||||
|
|
||||||
|
## [0.5.1]
|
||||||
|
- Remove direct dependencies on dart:io to support Flutter Web
|
||||||
|
|
||||||
|
## [0.5.0]
|
||||||
|
- Support loading animation from network in a web app
|
||||||
|
- Fix a couple of bugs with the web dev compiler
|
||||||
|
|
||||||
|
## [0.4.1]
|
||||||
|
- Support color value stored as RGB, not RGBA
|
||||||
|
|
||||||
|
## [0.4.0+1]
|
||||||
|
- Support latest version of the `characters` package
|
||||||
|
|
||||||
|
## [0.4.0]
|
||||||
|
- Disable "Merge paths" by default and provide an option to enable them.
|
||||||
|
This is the same behavior as in Lottie-android.
|
||||||
|
Merge paths currently don't work if the the operand shape is entirely contained within the
|
||||||
|
first shape. If you need to cut out one shape from another shape, use an even-odd fill type
|
||||||
|
instead of using merge paths.
|
||||||
|
|
||||||
|
Merge paths can be enabled with:
|
||||||
|
```dart
|
||||||
|
Lottie.asset('file.json', options: LottieOptions(enableMergePaths: true));
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## [0.3.6]
|
||||||
|
- Export the `Marker` class
|
||||||
|
|
||||||
|
## [0.3.5]
|
||||||
|
- Fix a bug with a wrongly clipped rectangle.
|
||||||
|
|
||||||
|
## [0.3.4]
|
||||||
|
- Fix a bug with dashed path
|
||||||
|
|
||||||
|
## [0.3.3]
|
||||||
|
- Fix a bug with rounded rectangle shape
|
||||||
|
|
||||||
|
## [0.3.2]
|
||||||
|
- Fix a bug with "repeater" content
|
||||||
|
|
||||||
|
## [0.3.1]
|
||||||
|
- Support dashed path
|
||||||
|
|
||||||
|
## [0.3.0+1]
|
||||||
|
- Specify a version range for the dependency on `characters`.
|
||||||
|
|
||||||
|
## [0.3.0]
|
||||||
|
- Add `LottieDelegates` a group of options to customize the lottie animation at runtime.
|
||||||
|
ie: Dynamically modify color, position, size, text... of every elements of the animation.
|
||||||
|
- Correctly display Linear and Radial Gradients
|
||||||
|
- Integrate latest changes from Lottie-android
|
||||||
|
|
||||||
|
## [0.2.2]
|
||||||
|
- Add a [repeat] parameter to specify if the automatic animation should loop.
|
||||||
|
- Add the [animate], [reverse], [repeat] properties on `LottieBuilder`
|
||||||
|
- Fix bug with `onLoaded` callback when the `LottieProvider` is changed
|
||||||
|
|
||||||
|
## [0.2.1]
|
||||||
|
- Fix a big bug in the path transformation code. A lot more animations look correct now.
|
||||||
|
|
||||||
|
## [0.2.0+1]
|
||||||
|
- Improve readme
|
||||||
|
- (internal) Add golden tests
|
||||||
|
|
||||||
|
## [0.2.0]
|
||||||
|
- Support loading the animation and its images from a zip file
|
||||||
|
- Breaking: `LottieComposition.fromBytes` and `fromByteData` are now asynchronous.
|
||||||
|
|
||||||
|
## [0.1.4]
|
||||||
|
- Support images in animation
|
||||||
|
- Basic support for text in animation (work in progress)
|
||||||
|
|
||||||
|
## [0.1.3]
|
||||||
|
- Support Polystar shape
|
||||||
|
- Reorganize examples.
|
||||||
|
|
||||||
|
## [0.1.2]
|
||||||
|
- Implement `Lottie.network`, `Lottie.file` and `Lottie.memory`
|
||||||
|
|
||||||
|
## [0.1.1]
|
||||||
|
- Fix analysis lints
|
||||||
|
|
||||||
|
## [0.1.0]
|
||||||
|
- Initial conversion of [lottie-android](https://github.com/airbnb/lottie-android) to Dart/Flutter
|
21
LICENSE
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) [year] [fullname]
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
258
README.md
Normal file
@ -0,0 +1,258 @@
|
|||||||
|
# Lottie for Flutter
|
||||||
|
|
||||||
|
[](https://github.com/xvrh/lottie-flutter)
|
||||||
|
[](https://pub.dev/packages/lottie)
|
||||||
|
|
||||||
|
Lottie is a mobile library for Android and iOS that parses [Adobe After Effects](https://www.adobe.com/products/aftereffects.html)
|
||||||
|
animations exported as json with [Bodymovin](https://github.com/airbnb/lottie-web) and renders them natively on mobile!
|
||||||
|
|
||||||
|
This repository is a unofficial conversion of the [Lottie-android](https://github.com/airbnb/lottie-android) library in pure Dart.
|
||||||
|
|
||||||
|
It works on Android, iOS, macOS, linux, windows and web.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Simple animation
|
||||||
|
This example shows how to display a Lottie animation in the simplest way.
|
||||||
|
The `Lottie` widget will load the json file and run the animation indefinitely.
|
||||||
|
|
||||||
|
```dart
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:lottie/lottie.dart';
|
||||||
|
|
||||||
|
void main() => runApp(MyApp());
|
||||||
|
|
||||||
|
class MyApp extends StatelessWidget {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return MaterialApp(
|
||||||
|
home: Scaffold(
|
||||||
|
body: ListView(
|
||||||
|
children: [
|
||||||
|
// Load a Lottie file from your assets
|
||||||
|
Lottie.asset('assets/LottieLogo1.json'),
|
||||||
|
|
||||||
|
// Load a Lottie file from a remote url
|
||||||
|
Lottie.network(
|
||||||
|
'https://raw.githubusercontent.com/xvrh/lottie-flutter/master/example/assets/Mobilo/A.json'),
|
||||||
|
|
||||||
|
// Load an animation and its images from a zip file
|
||||||
|
Lottie.asset('assets/lottiefiles/angel.zip'),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Specify a custom `AnimationController`
|
||||||
|
This example shows how to take full control over the animation by providing your own `AnimationController`.
|
||||||
|
|
||||||
|
With a custom `AnimationController` you have a rich API to play the animation in various ways: start and stop the animation when you want,
|
||||||
|
play forward or backward, loop between specifics points...
|
||||||
|
|
||||||
|
```dart
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:lottie/lottie.dart';
|
||||||
|
|
||||||
|
void main() => runApp(MyApp());
|
||||||
|
|
||||||
|
class MyApp extends StatefulWidget {
|
||||||
|
@override
|
||||||
|
_MyAppState createState() => _MyAppState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _MyAppState extends State<MyApp> with TickerProviderStateMixin {
|
||||||
|
late final AnimationController _controller;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
|
||||||
|
_controller = AnimationController(vsync: this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_controller.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return MaterialApp(
|
||||||
|
home: Scaffold(
|
||||||
|
body: ListView(
|
||||||
|
children: [
|
||||||
|
Lottie.asset(
|
||||||
|
'assets/LottieLogo1.json',
|
||||||
|
controller: _controller,
|
||||||
|
onLoaded: (composition) {
|
||||||
|
// Configure the AnimationController with the duration of the
|
||||||
|
// Lottie file and start the animation.
|
||||||
|
_controller
|
||||||
|
..duration = composition.duration
|
||||||
|
..forward();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
[See this file](https://github.com/xvrh/lottie-flutter/blob/master/example/lib/examples/animation_full_control.dart) for a more comprehensive example.
|
||||||
|
|
||||||
|
### Control the size of the Widget
|
||||||
|
The `Lottie` widget takes the same arguments and have the same behavior as the `Image` widget
|
||||||
|
in term of controlling its size.
|
||||||
|
```dart
|
||||||
|
Lottie.asset(
|
||||||
|
'assets/LottieLogo1.json',
|
||||||
|
width: 200,
|
||||||
|
height: 200,
|
||||||
|
fit: BoxFit.fill,
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
`width` and `height` are optionals and fallback on the size imposed by the parent or on the intrinsic size of the lottie
|
||||||
|
animation.
|
||||||
|
|
||||||
|
### Custom loading
|
||||||
|
The `Lottie` widget has several convenient constructors (`Lottie.asset`, `Lottie.network`, `Lottie.memory`) to load, parse and
|
||||||
|
cache automatically the json file.
|
||||||
|
|
||||||
|
Sometime you may prefer to have full control over the loading of the file. Use `LottieComposition.fromByteData` to
|
||||||
|
parse the file from a list of bytes.
|
||||||
|
|
||||||
|
This example shows how to load and parse a Lottie composition from a json file.
|
||||||
|
|
||||||
|
```dart
|
||||||
|
class MyWidget extends StatefulWidget {
|
||||||
|
@override
|
||||||
|
_MyWidgetState createState() => _MyWidgetState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _MyWidgetState extends State<MyWidget> {
|
||||||
|
late final Future<LottieComposition> _composition;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
|
||||||
|
_composition = _loadComposition();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<LottieComposition> _loadComposition() async {
|
||||||
|
var assetData = await rootBundle.load('assets/LottieLogo1.json');
|
||||||
|
return await LottieComposition.fromByteData(assetData);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return FutureBuilder<LottieComposition>(
|
||||||
|
future: _composition,
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
var composition = snapshot.data;
|
||||||
|
if (composition != null) {
|
||||||
|
return Lottie(composition: composition);
|
||||||
|
} else {
|
||||||
|
return Center(child: CircularProgressIndicator());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Custom drawing
|
||||||
|
This example goes low level and shows you how to draw a `LottieComposition` on a custom Canvas at a specific frame in
|
||||||
|
a specific position and size.
|
||||||
|
|
||||||
|
````dart
|
||||||
|
class CustomDrawer extends StatelessWidget {
|
||||||
|
final LottieComposition composition;
|
||||||
|
|
||||||
|
const CustomDrawer(this.composition, {Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return CustomPaint(
|
||||||
|
painter: _Painter(composition),
|
||||||
|
size: Size(400, 400),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _Painter extends CustomPainter {
|
||||||
|
final LottieDrawable drawable;
|
||||||
|
|
||||||
|
_Painter(LottieComposition composition)
|
||||||
|
: drawable = LottieDrawable(composition);
|
||||||
|
|
||||||
|
@override
|
||||||
|
void paint(Canvas canvas, Size size) {
|
||||||
|
var frameCount = 40;
|
||||||
|
var columns = 10;
|
||||||
|
for (var i = 0; i < frameCount; i++) {
|
||||||
|
var destRect = Offset(i % columns * 50.0, i ~/ 10 * 80.0) & (size / 5);
|
||||||
|
drawable
|
||||||
|
..setProgress(i / frameCount)
|
||||||
|
..draw(canvas, destRect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool shouldRepaint(CustomPainter oldDelegate) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
````
|
||||||
|
|
||||||
|
### Modify properties at runtime
|
||||||
|
This example shows how to modify some properties of the animation at runtime. Here we change the text,
|
||||||
|
the color, the opacity and the position of some layers.
|
||||||
|
For each `ValueDelegate` we can either provide a static `value` or a `callback` to compute a value for a each frame.
|
||||||
|
|
||||||
|
````dart
|
||||||
|
class _Animation extends StatelessWidget {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Lottie.asset(
|
||||||
|
'assets/Tests/Shapes.json',
|
||||||
|
delegates: LottieDelegates(
|
||||||
|
text: (initialText) => '**$initialText**',
|
||||||
|
values: [
|
||||||
|
ValueDelegate.color(
|
||||||
|
const ['Shape Layer 1', 'Rectangle', 'Fill 1'],
|
||||||
|
value: Colors.red,
|
||||||
|
),
|
||||||
|
ValueDelegate.opacity(
|
||||||
|
const ['Shape Layer 1', 'Rectangle'],
|
||||||
|
callback: (frameInfo) => (frameInfo.overallProgress * 100).round(),
|
||||||
|
),
|
||||||
|
ValueDelegate.position(
|
||||||
|
const ['Shape Layer 1', 'Rectangle', '**'],
|
||||||
|
relative: Offset(100, 200),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
````
|
||||||
|
|
||||||
|
## Limitations
|
||||||
|
Only the [supported features of Lottie Android](https://airbnb.io/lottie/#/supported-features)
|
||||||
|
are supported in this port.
|
||||||
|
|
||||||
|
## Flutter Web
|
||||||
|
Run the app with `flutter run -d Chrome --dart-define=FLUTTER_WEB_USE_SKIA=true --release`
|
||||||
|
|
||||||
|
See a preview here: https://xvrh.github.io/lottie-flutter/index.html
|
||||||
|
|
||||||
|
## More examples
|
||||||
|
See the `example` folder for more code samples of the various possibilities.
|
90
README.template.md
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
# Lottie for Flutter
|
||||||
|
|
||||||
|
[](https://github.com/xvrh/lottie-flutter)
|
||||||
|
[](https://pub.dev/packages/lottie)
|
||||||
|
|
||||||
|
Lottie is a mobile library for Android and iOS that parses [Adobe After Effects](https://www.adobe.com/products/aftereffects.html)
|
||||||
|
animations exported as json with [Bodymovin](https://github.com/airbnb/lottie-web) and renders them natively on mobile!
|
||||||
|
|
||||||
|
This repository is a unofficial conversion of the [Lottie-android](https://github.com/airbnb/lottie-android) library in pure Dart.
|
||||||
|
|
||||||
|
It works on Android, iOS, macOS, linux, windows and web.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Simple animation
|
||||||
|
This example shows how to display a Lottie animation in the simplest way.
|
||||||
|
The `Lottie` widget will load the json file and run the animation indefinitely.
|
||||||
|
|
||||||
|
```dart
|
||||||
|
import 'example/lib/main.dart';
|
||||||
|
```
|
||||||
|
|
||||||
|
### Specify a custom `AnimationController`
|
||||||
|
This example shows how to take full control over the animation by providing your own `AnimationController`.
|
||||||
|
|
||||||
|
With a custom `AnimationController` you have a rich API to play the animation in various ways: start and stop the animation when you want,
|
||||||
|
play forward or backward, loop between specifics points...
|
||||||
|
|
||||||
|
```dart
|
||||||
|
import 'example/lib/examples/animation_controller.dart';
|
||||||
|
```
|
||||||
|
|
||||||
|
[See this file](https://github.com/xvrh/lottie-flutter/blob/master/example/lib/examples/animation_full_control.dart) for a more comprehensive example.
|
||||||
|
|
||||||
|
### Control the size of the Widget
|
||||||
|
The `Lottie` widget takes the same arguments and have the same behavior as the `Image` widget
|
||||||
|
in term of controlling its size.
|
||||||
|
```dart
|
||||||
|
Lottie.asset(
|
||||||
|
'assets/LottieLogo1.json',
|
||||||
|
width: 200,
|
||||||
|
height: 200,
|
||||||
|
fit: BoxFit.fill,
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
`width` and `height` are optionals and fallback on the size imposed by the parent or on the intrinsic size of the lottie
|
||||||
|
animation.
|
||||||
|
|
||||||
|
### Custom loading
|
||||||
|
The `Lottie` widget has several convenient constructors (`Lottie.asset`, `Lottie.network`, `Lottie.memory`) to load, parse and
|
||||||
|
cache automatically the json file.
|
||||||
|
|
||||||
|
Sometime you may prefer to have full control over the loading of the file. Use `LottieComposition.fromByteData` to
|
||||||
|
parse the file from a list of bytes.
|
||||||
|
|
||||||
|
This example shows how to load and parse a Lottie composition from a json file.
|
||||||
|
|
||||||
|
```dart
|
||||||
|
import 'example/lib/examples/custom_load.dart#example';
|
||||||
|
```
|
||||||
|
|
||||||
|
### Custom drawing
|
||||||
|
This example goes low level and shows you how to draw a `LottieComposition` on a custom Canvas at a specific frame in
|
||||||
|
a specific position and size.
|
||||||
|
|
||||||
|
````dart
|
||||||
|
import 'example/lib/examples/custom_draw.dart#example';
|
||||||
|
````
|
||||||
|
|
||||||
|
### Modify properties at runtime
|
||||||
|
This example shows how to modify some properties of the animation at runtime. Here we change the text,
|
||||||
|
the color, the opacity and the position of some layers.
|
||||||
|
For each `ValueDelegate` we can either provide a static `value` or a `callback` to compute a value for a each frame.
|
||||||
|
|
||||||
|
````dart
|
||||||
|
import 'example/lib/examples/simple_dynamic_properties.dart#example';
|
||||||
|
````
|
||||||
|
|
||||||
|
## Limitations
|
||||||
|
Only the [supported features of Lottie Android](https://airbnb.io/lottie/#/supported-features)
|
||||||
|
are supported in this port.
|
||||||
|
|
||||||
|
## Flutter Web
|
||||||
|
Run the app with `flutter run -d Chrome --dart-define=FLUTTER_WEB_USE_SKIA=true --release`
|
||||||
|
|
||||||
|
See a preview here: https://xvrh.github.io/lottie-flutter/index.html
|
||||||
|
|
||||||
|
## More examples
|
||||||
|
See the `example` folder for more code samples of the various possibilities.
|
39
analysis_options.yaml
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
include: package:pedantic/analysis_options.yaml
|
||||||
|
analyzer:
|
||||||
|
errors:
|
||||||
|
strong-mode:
|
||||||
|
implicit-casts: false
|
||||||
|
implicit-dynamic: false
|
||||||
|
linter:
|
||||||
|
rules:
|
||||||
|
avoid_renaming_method_parameters: true
|
||||||
|
avoid_returning_null_for_future: true
|
||||||
|
avoid_returning_null_for_void: true
|
||||||
|
avoid_returning_this: true
|
||||||
|
avoid_setters_without_getters: true
|
||||||
|
await_only_futures: true
|
||||||
|
camel_case_types: true
|
||||||
|
cancel_subscriptions: true
|
||||||
|
close_sinks: true
|
||||||
|
constant_identifier_names: true
|
||||||
|
empty_statements: true
|
||||||
|
hash_and_equals: true
|
||||||
|
iterable_contains_unrelated_type: true
|
||||||
|
list_remove_unrelated_type: true
|
||||||
|
no_adjacent_strings_in_list: true
|
||||||
|
non_constant_identifier_names: true
|
||||||
|
only_throw_errors: true
|
||||||
|
overridden_fields: true
|
||||||
|
prefer_inlined_adds: true
|
||||||
|
prefer_interpolation_to_compose_strings: true
|
||||||
|
prefer_null_aware_operators: true
|
||||||
|
prefer_relative_imports: true
|
||||||
|
prefer_typing_uninitialized_variables: true
|
||||||
|
sort_pub_dependencies: true
|
||||||
|
test_types_in_equals: true
|
||||||
|
unnecessary_brace_in_string_interps: true
|
||||||
|
unnecessary_getters_setters: true
|
||||||
|
unnecessary_parenthesis: true
|
||||||
|
unnecessary_statements: true
|
||||||
|
use_function_type_syntax_for_parameters: true
|
||||||
|
void_checks: true
|
@ -1 +0,0 @@
|
|||||||
[{"family":"MaterialIcons","fonts":[{"asset":"fonts/MaterialIcons-Regular.ttf"}]}]
|
|
14409
assets/LICENSE
37
example/.gitignore
vendored
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
# Miscellaneous
|
||||||
|
*.class
|
||||||
|
*.log
|
||||||
|
*.pyc
|
||||||
|
*.swp
|
||||||
|
.DS_Store
|
||||||
|
.atom/
|
||||||
|
.buildlog/
|
||||||
|
.history
|
||||||
|
.svn/
|
||||||
|
|
||||||
|
# IntelliJ related
|
||||||
|
*.iml
|
||||||
|
*.ipr
|
||||||
|
*.iws
|
||||||
|
.idea/
|
||||||
|
|
||||||
|
# The .vscode folder contains launch configuration and tasks you configure in
|
||||||
|
# VS Code which you may wish to be included in version control, so this line
|
||||||
|
# is commented out by default.
|
||||||
|
#.vscode/
|
||||||
|
|
||||||
|
# Flutter/Dart/Pub related
|
||||||
|
**/doc/api/
|
||||||
|
.dart_tool/
|
||||||
|
.flutter-plugins
|
||||||
|
.flutter-plugins-dependencies
|
||||||
|
.packages
|
||||||
|
.pub-cache/
|
||||||
|
.pub/
|
||||||
|
/build/
|
||||||
|
|
||||||
|
# Web related
|
||||||
|
lib/generated_plugin_registrant.dart
|
||||||
|
|
||||||
|
# Exceptions to above rules.
|
||||||
|
!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
|
31
example/README.md
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
# Lottie Flutter examples
|
||||||
|
|
||||||
|
### Simple usage
|
||||||
|
|
||||||
|
```dart
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:lottie/lottie.dart';
|
||||||
|
|
||||||
|
void main() => runApp(MyApp());
|
||||||
|
|
||||||
|
class MyApp extends StatelessWidget {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return MaterialApp(
|
||||||
|
home: Scaffold(
|
||||||
|
body: ListView(
|
||||||
|
children: [
|
||||||
|
// Load a Lottie file from your assets
|
||||||
|
Lottie.asset('assets/LottieLogo1.json'),
|
||||||
|
|
||||||
|
// Load a Lottie file from a remote url
|
||||||
|
Lottie.network(
|
||||||
|
'https://raw.githubusercontent.com/xvrh/lottie-flutter/master/sample_app/assets/Mobilo/A.json'),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
8
example/README.template.md
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
# Lottie Flutter examples
|
||||||
|
|
||||||
|
### Simple usage
|
||||||
|
|
||||||
|
```dart
|
||||||
|
import 'lib/examples/examples.dart';
|
||||||
|
```
|
||||||
|
|
7
example/android/.gitignore
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
gradle-wrapper.jar
|
||||||
|
/.gradle
|
||||||
|
/captures/
|
||||||
|
/gradlew
|
||||||
|
/gradlew.bat
|
||||||
|
/local.properties
|
||||||
|
GeneratedPluginRegistrant.java
|
66
example/android/app/build.gradle
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
def localProperties = new Properties()
|
||||||
|
def localPropertiesFile = rootProject.file('local.properties')
|
||||||
|
if (localPropertiesFile.exists()) {
|
||||||
|
localPropertiesFile.withReader('UTF-8') { reader ->
|
||||||
|
localProperties.load(reader)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def flutterRoot = localProperties.getProperty('flutter.sdk')
|
||||||
|
if (flutterRoot == null) {
|
||||||
|
throw new Exception("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
|
||||||
|
}
|
||||||
|
|
||||||
|
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
|
||||||
|
if (flutterVersionCode == null) {
|
||||||
|
flutterVersionCode = '1'
|
||||||
|
}
|
||||||
|
|
||||||
|
def flutterVersionName = localProperties.getProperty('flutter.versionName')
|
||||||
|
if (flutterVersionName == null) {
|
||||||
|
flutterVersionName = '1.0'
|
||||||
|
}
|
||||||
|
|
||||||
|
apply plugin: 'com.android.application'
|
||||||
|
apply plugin: 'kotlin-android'
|
||||||
|
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
|
||||||
|
|
||||||
|
android {
|
||||||
|
compileSdkVersion 28
|
||||||
|
|
||||||
|
sourceSets {
|
||||||
|
main.java.srcDirs += 'src/main/kotlin'
|
||||||
|
}
|
||||||
|
|
||||||
|
lintOptions {
|
||||||
|
disable 'InvalidPackage'
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultConfig {
|
||||||
|
applicationId "com.github.xvrh.lottie.sample"
|
||||||
|
minSdkVersion 16
|
||||||
|
targetSdkVersion 28
|
||||||
|
versionCode flutterVersionCode.toInteger()
|
||||||
|
versionName flutterVersionName
|
||||||
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
|
}
|
||||||
|
|
||||||
|
buildTypes {
|
||||||
|
release {
|
||||||
|
// TODO: Add your own signing config for the release build.
|
||||||
|
// Signing with the debug keys for now, so `flutter run --release` works.
|
||||||
|
signingConfig signingConfigs.debug
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
flutter {
|
||||||
|
source '../..'
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||||
|
testImplementation 'junit:junit:4.12'
|
||||||
|
androidTestImplementation 'androidx.test:runner:1.1.1'
|
||||||
|
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
|
||||||
|
}
|
7
example/android/app/src/debug/AndroidManifest.xml
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
package="com.github.xvrh.lottie.sample">
|
||||||
|
<!-- Flutter needs it to communicate with the running application
|
||||||
|
to allow setting breakpoints, to provide hot reload, etc.
|
||||||
|
-->
|
||||||
|
<uses-permission android:name="android.permission.INTERNET"/>
|
||||||
|
</manifest>
|
30
example/android/app/src/main/AndroidManifest.xml
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
package="com.github.xvrh.lottie.sample">
|
||||||
|
<!-- io.flutter.app.FlutterApplication is an android.app.Application that
|
||||||
|
calls FlutterMain.startInitialization(this); in its onCreate method.
|
||||||
|
In most cases you can leave this as-is, but you if you want to provide
|
||||||
|
additional functionality it is fine to subclass or reimplement
|
||||||
|
FlutterApplication and put your custom class here. -->
|
||||||
|
<application
|
||||||
|
android:name="io.flutter.app.FlutterApplication"
|
||||||
|
android:label="example"
|
||||||
|
android:icon="@mipmap/ic_launcher">
|
||||||
|
<activity
|
||||||
|
android:name=".MainActivity"
|
||||||
|
android:launchMode="singleTop"
|
||||||
|
android:theme="@style/LaunchTheme"
|
||||||
|
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
|
||||||
|
android:hardwareAccelerated="true"
|
||||||
|
android:windowSoftInputMode="adjustResize">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN"/>
|
||||||
|
<category android:name="android.intent.category.LAUNCHER"/>
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
<!-- Don't delete the meta-data below.
|
||||||
|
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
|
||||||
|
<meta-data
|
||||||
|
android:name="flutterEmbedding"
|
||||||
|
android:value="2" />
|
||||||
|
</application>
|
||||||
|
</manifest>
|
@ -0,0 +1,12 @@
|
|||||||
|
package com.github.xvrh.lottie.sample
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import io.flutter.embedding.android.FlutterActivity
|
||||||
|
import io.flutter.embedding.engine.FlutterEngine
|
||||||
|
import io.flutter.plugins.GeneratedPluginRegistrant
|
||||||
|
|
||||||
|
class MainActivity: FlutterActivity() {
|
||||||
|
override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
|
||||||
|
GeneratedPluginRegistrant.registerWith(flutterEngine);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Modify this file to customize your launch splash screen -->
|
||||||
|
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item android:drawable="@android:color/white" />
|
||||||
|
|
||||||
|
<!-- You can insert your own image assets here -->
|
||||||
|
<!-- <item>
|
||||||
|
<bitmap
|
||||||
|
android:gravity="center"
|
||||||
|
android:src="@mipmap/launch_image" />
|
||||||
|
</item> -->
|
||||||
|
</layer-list>
|
BIN
example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 544 B |
BIN
example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 442 B |
BIN
example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 721 B |
BIN
example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 1.0 KiB |
BIN
example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
8
example/android/app/src/main/res/values/styles.xml
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
|
||||||
|
<!-- Show a splash screen on the activity. Automatically removed when
|
||||||
|
Flutter draws its first frame -->
|
||||||
|
<item name="android:windowBackground">@drawable/launch_background</item>
|
||||||
|
</style>
|
||||||
|
</resources>
|
7
example/android/app/src/profile/AndroidManifest.xml
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
package="com.github.xvrh.lottie.sample">
|
||||||
|
<!-- Flutter needs it to communicate with the running application
|
||||||
|
to allow setting breakpoints, to provide hot reload, etc.
|
||||||
|
-->
|
||||||
|
<uses-permission android:name="android.permission.INTERNET"/>
|
||||||
|
</manifest>
|
31
example/android/build.gradle
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
buildscript {
|
||||||
|
ext.kotlin_version = '1.3.50'
|
||||||
|
repositories {
|
||||||
|
google()
|
||||||
|
jcenter()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
classpath 'com.android.tools.build:gradle:3.5.0'
|
||||||
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
allprojects {
|
||||||
|
repositories {
|
||||||
|
google()
|
||||||
|
jcenter()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rootProject.buildDir = '../build'
|
||||||
|
subprojects {
|
||||||
|
project.buildDir = "${rootProject.buildDir}/${project.name}"
|
||||||
|
}
|
||||||
|
subprojects {
|
||||||
|
project.evaluationDependsOn(':app')
|
||||||
|
}
|
||||||
|
|
||||||
|
task clean(type: Delete) {
|
||||||
|
delete rootProject.buildDir
|
||||||
|
}
|
4
example/android/gradle.properties
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
org.gradle.jvmargs=-Xmx1536M
|
||||||
|
android.enableR8=true
|
||||||
|
android.useAndroidX=true
|
||||||
|
android.enableJetifier=true
|
6
example/android/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#Fri Jun 23 08:50:38 CEST 2017
|
||||||
|
distributionBase=GRADLE_USER_HOME
|
||||||
|
distributionPath=wrapper/dists
|
||||||
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
zipStorePath=wrapper/dists
|
||||||
|
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip
|
15
example/android/settings.gradle
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
include ':app'
|
||||||
|
|
||||||
|
def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()
|
||||||
|
|
||||||
|
def plugins = new Properties()
|
||||||
|
def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')
|
||||||
|
if (pluginsFile.exists()) {
|
||||||
|
pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) }
|
||||||
|
}
|
||||||
|
|
||||||
|
plugins.each { name, path ->
|
||||||
|
def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile()
|
||||||
|
include ":$name"
|
||||||
|
project(":$name").projectDir = pluginDirectory
|
||||||
|
}
|
1458
example/assets/17297-fireworks.json
Normal file
Before Width: | Height: | Size: 149 KiB After Width: | Height: | Size: 149 KiB |