style: updated example and readme

Diffs=
a259b57b2 style: clean up example app
483978f10 docs: update readme
This commit is contained in:
HayesGordon
2023-01-11 21:04:30 +00:00
parent 82e5dc984c
commit 0767844a56
19 changed files with 305 additions and 287 deletions

View File

@ -1 +1 @@
9af05d04450219713d6f8135f393a8d68231ffa0
a259b57b29e25b763c484370cefa6560073800ab

View File

@ -3,25 +3,58 @@
![Discord badge](https://img.shields.io/discord/532365473602600965)
![Twitter handle](https://img.shields.io/twitter/follow/rive_app.svg?style=social&label=Follow)
# Rive
# Rive Flutter
Runtime docs are available in [Rive's help center](https://help.rive.app/runtimes/quick-start).
![Rive hero image](https://rive-app.notion.site/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2Fff44ed5f-1eea-4154-81ef-84547e61c3fd%2Frive_notion.png?table=block&id=f198cab2-c0bc-4ce8-970c-42220379bcf3&spaceId=9c949665-9ad9-445f-b9c4-5ee204f8b60c&width=2000&userId=&cache=v2)
[Rive](https://rive.app/) is a real-time interactive design and animation tool. Use our collaborative editor to create motion graphics that respond to different states and user inputs. Then load your animations into apps, games, and websites with our lightweight open-source runtimes.
Rive Flutter is a runtime library for [Rive](https://rive.app), a real-time interactive design and animation tool.
## Add dependency to pubspec.yaml
This library allows you to fully control Rive files with a high-level API for simple interactions and animations, as well as a low-level API for creating custom render loops for multiple artboards, animations, and state machines in a single canvas.
```yaml
dependencies:
rive: ^0.9.0
```
## Table of contents
## Platform Considerations
Read some [platform specific considerations](platform_considerations.md) with regards to the Rive Flutter package.
- :star: [Rive Overview](#rive-overview)
- 🚀 [Getting Started & API docs](#getting-started)
- :mag: [Supported Platforms](#supported-platforms)
- :books: [Examples](#examples)
- 👨‍💻 [Contributing](#contributing)
- :question: [Issues](#issues)
## Quick Start
## Overview of Rive
Play an animation from a Rive file over HTTP:
[Rive](https://rive.app) is a powerful tool that helps teams create and run interactive animations for apps, games, and websites. Designers and developers can use the collaborative editor to create motion graphics that respond to different states and user inputs, and then use the lightweight open-source runtime libraries, like Rive Flutter, to load their animations into their projects.
For more information, check out the following resources:
:house_with_garden: [Homepage](https://rive.app/)
:blue_book: [General help docs](https://help.rive.app/)
🛠 [Learning Rive](https://rive.app/learn-rive)
## Getting Started
To get started with Rive Flutter, check out the following resources:
- [Getting Started with Rive in Flutter](https://help.rive.app/runtimes/overview/flutter)
- [Alternative Widget Setup](https://help.rive.app/runtimes/overview/flutter/alternative-widget-setup)
For additional help, see the Runtime sections of the Rive help documentation, such as:
- [Animation Playback](https://help.rive.app/runtimes/playback)
- [State Machines](https://help.rive.app/runtimes/state-machines)
## Supported Platforms
Be sure to read the [platform specific considerations](platform_considerations.md) for the Rive Flutter package.
## Examples
To see some examples of what you can do with Rive Flutter, check out the following projects:
- [Demo app](https://github.com/rive-app/rive-flutter/tree/master/example)
- [Find the Dog (game)](https://github.com/rive-app/find-the-dog)
Here is an example of how to play an animation from a Rive file retrieved over HTTP:
```dart
import 'package:flutter/material.dart';
@ -171,11 +204,10 @@ class _PlayOneShotAnimationState extends State<PlayOneShotAnimation> {
}
```
## Antialiasing
## Contributing
If you want to disable antialiasing (usually for performance reasons), you can set `antialiasing` to `false` on the `Rive` and `RiveAnimation` widgets.
We love contributions and all are welcome! 💙
## API Documentation
## Issues
Check out our more extensive API documentation on pub.dev:
https://pub.dev/documentation/rive/latest/
Have an issue with using the runtime, or want to suggest a feature/API to help make your development life better? Log an issue in our [issues](https://github.com/rive-app/flutter/issues) tab! You can also browse older issues and discussion threads there to see solutions that may have worked for common problems.

View File

@ -1,16 +1,21 @@
# rive_example
# Rive Flutter Example
A new Flutter project.
A demo application showcasing Rive Flutter.
## Getting Started
This project is a starting point for a Flutter application.
Clone this repository:
```bash
git clone https://github.com/rive-app/rive-flutter
```
A few resources to get you started if this is your first Flutter project:
Run the example:
- [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab)
- [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook)
```bash
cd rive-flutter/example
flutter pub get
flutter run
```
For help getting started with Flutter, view our
[online documentation](https://flutter.dev/docs), which offers tutorials,
samples, guidance on mobile development, and a full API reference.
### Flutter Installation Instructions
If you're new to [Flutter](https://flutter.dev), see the official [installation instructions](https://docs.flutter.dev/get-started/install).

View File

@ -0,0 +1,4 @@
include: package:flutter_lints/flutter.yaml
linter:
rules:

BIN
example/assets/vehicles.riv Normal file

Binary file not shown.

View File

@ -6,7 +6,7 @@ class AnimationCarousel extends StatefulWidget {
const AnimationCarousel({Key? key}) : super(key: key);
@override
_AnimationCarouselState createState() => _AnimationCarouselState();
State<AnimationCarousel> createState() => _AnimationCarouselState();
}
class _AnimationCarouselState extends State<AnimationCarousel> {
@ -55,9 +55,8 @@ class _AnimationCarouselState extends State<AnimationCarousel> {
@override
Widget build(BuildContext context) {
final _indexToShow = _index % riveAnimations.length;
final indexToShow = _index % riveAnimations.length;
return Scaffold(
backgroundColor: Colors.grey,
appBar: AppBar(
title: const Text('Animation Carousel'),
),
@ -70,9 +69,9 @@ class _AnimationCarouselState extends State<AnimationCarousel> {
),
Expanded(
child: RiveAnimation.asset(
riveAnimations[_indexToShow].name,
animations: riveAnimations[_indexToShow].animations,
stateMachines: riveAnimations[_indexToShow].stateMachines,
riveAnimations[indexToShow].name,
animations: riveAnimations[indexToShow].animations,
stateMachines: riveAnimations[indexToShow].stateMachines,
),
),
GestureDetector(

View File

@ -14,8 +14,8 @@ class SpeedyAnimation extends StatelessWidget {
title: const Text('Custom Controller'),
),
body: Center(
child: RiveAnimation.network(
'https://cdn.rive.app/animations/vehicles.riv',
child: RiveAnimation.asset(
'assets/vehicles.riv',
fit: BoxFit.cover,
animations: const ['idle'],
controllers: [SpeedController('curves', speedMultiplier: 3)],

View File

@ -7,7 +7,7 @@ class ExampleStateMachine extends StatefulWidget {
const ExampleStateMachine({Key? key}) : super(key: key);
@override
_ExampleStateMachineState createState() => _ExampleStateMachineState();
State<ExampleStateMachine> createState() => _ExampleStateMachineState();
}
class _ExampleStateMachineState extends State<ExampleStateMachine> {
@ -48,30 +48,40 @@ class _ExampleStateMachineState extends State<ExampleStateMachine> {
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.grey,
appBar: AppBar(
title: const Text('Button State Machine'),
),
body: Center(
child: _riveArtboard == null
? const SizedBox()
: MouseRegion(
onEnter: (_) => _hoverInput?.value = true,
onExit: (_) => _hoverInput?.value = false,
child: GestureDetector(
onTapDown: (_) => _pressInput?.value = true,
onTapCancel: () => _pressInput?.value = false,
onTapUp: (_) => _pressInput?.value = false,
child: SizedBox(
width: 250,
height: 250,
child: Rive(
appBar: AppBar(title: const Text('Button State Machine')),
body: _riveArtboard == null
? const SizedBox()
: MouseRegion(
onEnter: (_) => _hoverInput?.value = true,
onExit: (_) => _hoverInput?.value = false,
child: GestureDetector(
onTapDown: (_) => _pressInput?.value = true,
onTapCancel: () => _pressInput?.value = false,
onTapUp: (_) => _pressInput?.value = false,
child: Stack(
children: [
Rive(
fit: BoxFit.cover,
artboard: _riveArtboard!,
),
),
Align(
alignment: Alignment.bottomCenter,
child: Padding(
padding: const EdgeInsets.all(18.0),
child: Text(
'Try pressing the button...',
style: TextStyle(
fontSize: 22,
fontWeight: FontWeight.bold,
color: Colors.grey[800],
),
),
),
)
],
),
),
),
),
);
}
}

View File

@ -8,7 +8,7 @@ class LiquidDownload extends StatefulWidget {
const LiquidDownload({Key? key}) : super(key: key);
@override
_LiquidDownloadState createState() => _LiquidDownloadState();
State<LiquidDownload> createState() => _LiquidDownloadState();
}
class _LiquidDownloadState extends State<LiquidDownload> {
@ -49,7 +49,6 @@ class _LiquidDownloadState extends State<LiquidDownload> {
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.grey,
appBar: AppBar(
title: const Text('Liquid Download'),
),
@ -72,11 +71,9 @@ class _LiquidDownloadState extends State<LiquidDownload> {
min: 0,
max: 100,
label: _progress!.value.round().toString(),
onChanged: (double value) {
setState(() {
_progress!.value = value;
});
},
onChanged: (double value) => setState(() {
_progress!.value = value;
}),
),
const SizedBox(height: 10),
Expanded(

View File

@ -7,7 +7,7 @@ class LittleMachine extends StatefulWidget {
const LittleMachine({Key? key}) : super(key: key);
@override
_LittleMachineState createState() => _LittleMachineState();
State<LittleMachine> createState() => _LittleMachineState();
}
class _LittleMachineState extends State<LittleMachine> {
@ -58,36 +58,40 @@ class _LittleMachineState extends State<LittleMachine> {
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.grey,
appBar: AppBar(
title: const Text('Little Machine'),
),
body: Center(
child: _riveArtboard == null
? const SizedBox()
: GestureDetector(
onTapDown: (_) => _trigger?.value = true,
child: Column(
children: [
const SizedBox(height: 10),
const Text(
'Press to activate!',
style: TextStyle(
fontSize: 18,
),
),
const SizedBox(height: 10),
Expanded(
child: Rive(
artboard: _riveArtboard!,
),
),
const SizedBox(height: 10),
Text('$stateChangeMessage'),
const SizedBox(height: 10),
],
appBar: AppBar(title: const Text('Little Machine')),
body: Stack(
children: [
_riveArtboard == null
? const SizedBox()
: GestureDetector(
onTapDown: (_) => _trigger?.value = true,
child: Rive(
artboard: _riveArtboard!,
fit: BoxFit.cover,
),
),
const Align(
alignment: Alignment.topCenter,
child: Padding(
padding: EdgeInsets.all(16.0),
child: Text(
'Press to activate!',
style: TextStyle(fontSize: 18, color: Colors.black),
),
),
),
Align(
alignment: Alignment.bottomCenter,
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Text(
stateChangeMessage,
style: const TextStyle(
color: Colors.black, fontWeight: FontWeight.bold),
),
),
)
],
),
);
}

View File

@ -7,180 +7,106 @@ import 'package:rive_example/little_machine.dart';
import 'package:rive_example/play_one_shot_animation.dart';
import 'package:rive_example/play_pause_animation.dart';
import 'package:rive_example/simple_animation.dart';
import 'package:rive_example/simple_animation_network.dart';
import 'package:rive_example/simple_machine_listener.dart';
import 'package:rive_example/simple_state_machine.dart';
import 'package:rive_example/state_machine_skills.dart';
void main() => runApp(MaterialApp(
title: 'Navigation Basics',
home: Home(),
));
void main() => runApp(
MaterialApp(
title: 'Rive Example',
home: const RiveExampleApp(),
darkTheme: ThemeData.dark().copyWith(
scaffoldBackgroundColor: _backgroundColor,
appBarTheme: const AppBarTheme(backgroundColor: _appBarColor),
colorScheme:
ColorScheme.fromSwatch().copyWith(primary: _primaryColor),
),
themeMode: ThemeMode.dark,
),
);
/// An example application demoing Rive.
class RiveExampleApp extends StatefulWidget {
const RiveExampleApp({Key? key}) : super(key: key);
@override
State<RiveExampleApp> createState() => _RiveExampleAppState();
}
class _RiveExampleAppState extends State<RiveExampleApp> {
// Example animations
final _pages = [
const _Page('Simple Animation - Asset', SimpleAssetAnimation()),
const _Page('Simple Animation - Network', SimpleNetworkAnimation()),
const _Page('Play/Pause Animation', PlayPauseAnimation()),
const _Page('Play One-Shot Animation', PlayOneShotAnimation()),
const _Page('Button State Machine', ExampleStateMachine()),
const _Page('Skills Machine', StateMachineSkills()),
const _Page('Little Machine', LittleMachine()),
const _Page('Liquid Download', LiquidDownload()),
const _Page('Custom Controller - Speed', SpeedyAnimation()),
const _Page('Simple State Machine', SimpleStateMachine()),
const _Page('State Machine with Listener', StateMachineListener()),
const _Page('Animation Carousel', AnimationCarousel()),
];
class Home extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Rive Examples'),
),
appBar: AppBar(title: const Text('Rive Examples')),
body: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
ElevatedButton(
child: const Text('Simple Animation'),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute<void>(
builder: (context) => const SimpleAnimation(),
),
);
},
),
const SizedBox(
height: 10,
),
ElevatedButton(
child: const Text('Play/Pause Animation'),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute<void>(
builder: (context) => const PlayPauseAnimation(),
),
);
},
),
const SizedBox(
height: 10,
),
ElevatedButton(
child: const Text('Play One-Shot Animation'),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute<void>(
builder: (context) => const PlayOneShotAnimation(),
),
);
},
),
const SizedBox(
height: 10,
),
ElevatedButton(
child: const Text('Button State Machine'),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute<void>(
builder: (context) => const ExampleStateMachine(),
),
);
},
),
const SizedBox(
height: 10,
),
ElevatedButton(
child: const Text('Skills Machine'),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute<void>(
builder: (context) => const StateMachineSkills(),
),
);
},
),
const SizedBox(
height: 10,
),
ElevatedButton(
child: const Text('Little Machine'),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute<void>(
builder: (context) => const LittleMachine(),
),
);
},
),
const SizedBox(
height: 10,
),
ElevatedButton(
child: const Text('Liquid Download'),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute<void>(
builder: (context) => const LiquidDownload(),
),
);
},
),
const SizedBox(
height: 10,
),
ElevatedButton(
child: const Text('Custom Controller - Speed'),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute<void>(
builder: (context) => const SpeedyAnimation(),
),
);
},
),
const SizedBox(
height: 10,
),
ElevatedButton(
child: const Text('Simple State Machine'),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute<void>(
builder: (context) => const SimpleStateMachine(),
),
);
},
),
const SizedBox(
height: 10,
),
ElevatedButton(
child: const Text('State Machine with Listener'),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute<void>(
builder: (context) => const StateMachineListener(),
),
);
},
),
const SizedBox(
height: 10,
),
ElevatedButton(
child: const Text('Animation Carousel'),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute<void>(
builder: (context) => const AnimationCarousel(),
),
);
},
),
],
child: ListView.separated(
shrinkWrap: true,
itemBuilder: (context, index) => _NavButton(page: _pages[index]),
separatorBuilder: (context, index) => const SizedBox(height: 16),
itemCount: _pages.length,
),
),
);
}
}
/// Class used to organize demo pages.
class _Page {
final String name;
final Widget page;
const _Page(this.name, this.page);
}
/// Button to navigate to demo pages.
class _NavButton extends StatelessWidget {
const _NavButton({required this.page});
final _Page page;
@override
Widget build(BuildContext context) {
return Center(
child: ElevatedButton(
child: SizedBox(
width: 250,
child: Center(
child: Text(
page.name,
style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
),
),
),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute<void>(
builder: (context) => page.page,
),
);
},
),
);
}
}
const _appBarColor = Color(0xFF323232);
const _backgroundColor = Color(0xFF1D1D1D);
const _primaryColor = Color(0xFF57A5E0);

View File

@ -1,13 +1,12 @@
/// Demonstrates playing a one-shot animation on demand
import 'package:flutter/material.dart';
import 'package:rive/rive.dart';
/// Demonstrates playing a one-shot animation on demand
class PlayOneShotAnimation extends StatefulWidget {
const PlayOneShotAnimation({Key? key}) : super(key: key);
@override
_PlayOneShotAnimationState createState() => _PlayOneShotAnimationState();
State<PlayOneShotAnimation> createState() => _PlayOneShotAnimationState();
}
class _PlayOneShotAnimationState extends State<PlayOneShotAnimation> {
@ -35,9 +34,10 @@ class _PlayOneShotAnimationState extends State<PlayOneShotAnimation> {
title: const Text('One-Shot Example'),
),
body: Center(
child: RiveAnimation.network(
'https://cdn.rive.app/animations/vehicles.riv',
child: RiveAnimation.asset(
'assets/vehicles.riv',
animations: const ['idle', 'curves'],
fit: BoxFit.cover,
controllers: [_controller],
),
),

View File

@ -7,7 +7,7 @@ class PlayPauseAnimation extends StatefulWidget {
const PlayPauseAnimation({Key? key}) : super(key: key);
@override
_PlayPauseAnimationState createState() => _PlayPauseAnimationState();
State<PlayPauseAnimation> createState() => _PlayPauseAnimationState();
}
class _PlayPauseAnimationState extends State<PlayPauseAnimation> {
@ -33,13 +33,12 @@ class _PlayPauseAnimationState extends State<PlayPauseAnimation> {
appBar: AppBar(
title: const Text('Animation Example'),
),
body: Center(
child: RiveAnimation.network(
'https://cdn.rive.app/animations/vehicles.riv',
controllers: [_controller],
// Update the play state when the widget's initialized
onInit: (_) => setState(() {}),
),
body: RiveAnimation.asset(
'assets/off_road_car.riv',
fit: BoxFit.cover,
controllers: [_controller],
// Update the play state when the widget's initialized
onInit: (_) => setState(() {}),
),
floatingActionButton: FloatingActionButton(
onPressed: _togglePlay,

View File

@ -1,8 +1,9 @@
import 'package:flutter/material.dart';
import 'package:rive/rive.dart';
class SimpleAnimation extends StatelessWidget {
const SimpleAnimation({Key? key}) : super(key: key);
/// Basic example playing a Rive animation from a packaged asset.
class SimpleAssetAnimation extends StatelessWidget {
const SimpleAssetAnimation({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
@ -11,8 +12,8 @@ class SimpleAnimation extends StatelessWidget {
title: const Text('Simple Animation'),
),
body: const Center(
child: RiveAnimation.network(
'https://cdn.rive.app/animations/vehicles.riv',
child: RiveAnimation.asset(
'assets/off_road_car.riv',
fit: BoxFit.cover,
),
),

View File

@ -0,0 +1,23 @@
import 'package:flutter/material.dart';
import 'package:rive/rive.dart';
/// Basic example playing a Rive animation from a network asset.
class SimpleNetworkAnimation extends StatelessWidget {
const SimpleNetworkAnimation({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Simple Animation'),
),
body: const Center(
child: RiveAnimation.network(
'https://cdn.rive.app/animations/vehicles.riv',
fit: BoxFit.cover,
placeHolder: Center(child: CircularProgressIndicator()),
),
),
);
}
}

View File

@ -5,7 +5,7 @@ class StateMachineListener extends StatefulWidget {
const StateMachineListener({Key? key}) : super(key: key);
@override
_StateMachineListenerState createState() => _StateMachineListenerState();
State<StateMachineListener> createState() => _StateMachineListenerState();
}
class _StateMachineListenerState extends State<StateMachineListener> {

View File

@ -1,11 +1,14 @@
import 'package:flutter/material.dart';
import 'package:rive/rive.dart';
/// An example demonstrating a simple state machine.
///
/// The "bumpy" state machine will be activated on tap of the vehicle.
class SimpleStateMachine extends StatefulWidget {
const SimpleStateMachine({Key? key}) : super(key: key);
@override
_SimpleStateMachineState createState() => _SimpleStateMachineState();
State<SimpleStateMachine> createState() => _SimpleStateMachineState();
}
class _SimpleStateMachineState extends State<SimpleStateMachine> {
@ -23,17 +26,31 @@ class _SimpleStateMachineState extends State<SimpleStateMachine> {
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Simple Animation'),
title: const Text('Simple State Machine'),
),
body: Center(
child: GestureDetector(
child: RiveAnimation.network(
'https://cdn.rive.app/animations/vehicles.riv',
fit: BoxFit.cover,
onInit: _onRiveInit,
body: Stack(
children: [
Center(
child: GestureDetector(
onTap: _hitBump,
child: RiveAnimation.asset(
'assets/vehicles.riv',
fit: BoxFit.cover,
onInit: _onRiveInit,
),
),
),
onTap: _hitBump,
),
const Align(
alignment: Alignment.topCenter,
child: Padding(
padding: EdgeInsets.all(16.0),
child: Text(
'Bump the van!',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
),
),
],
),
);
}

View File

@ -7,7 +7,7 @@ class StateMachineSkills extends StatefulWidget {
const StateMachineSkills({Key? key}) : super(key: key);
@override
_StateMachineSkillsState createState() => _StateMachineSkillsState();
State<StateMachineSkills> createState() => _StateMachineSkillsState();
}
class _StateMachineSkillsState extends State<StateMachineSkills> {
@ -46,7 +46,6 @@ class _StateMachineSkillsState extends State<StateMachineSkills> {
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.grey,
appBar: AppBar(
title: const Text('Skills Machine'),
),
@ -58,10 +57,11 @@ class _StateMachineSkillsState extends State<StateMachineSkills> {
Positioned.fill(
child: Rive(
artboard: _riveArtboard!,
fit: BoxFit.cover,
),
),
Positioned.fill(
bottom: 100,
bottom: 32,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.end,

View File

@ -6,7 +6,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev
version: 1.0.0+1
environment:
sdk: ">=2.12.0 <3.0.0"
sdk: ">=2.17.0 <3.0.0"
dependencies:
flutter:
@ -17,6 +17,7 @@ dependencies:
dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^2.0.0
flutter:
uses-material-design: true