class Animation extends State<ConnectToFriend> {
late RiveAnimationController riveAnimationController;
#override
void initState() {
super.initState();
riveAnimationController = SimpleAnimation('idle');
setState(() {});
}
#override
Widget build(BuildContext context) {
return LoaderOverlay(
useDefaultLoading: false,
overlayOpacity: 0.6,
overlayWidget: Center(child: CircularProgressIndicator()),
child: Scaffold(
body: Positioned(
child: Container(
child: RiveAnimation.asset(
'assets/animations/4054-8407-polito (2).riv',
controllers: [riveAnimationController],
animations: const ['idle'],
fit: BoxFit.cover,
onInit: (p0) => setState(() {}))))),
);
}
}
enter image description here
enter image description here
enter image description here
i can't play the polito animation in rive flutter, it's static
can anyone help me?I am new to Rive and because there is close to no good documentation for Rive 2 I wanted to ask here.
here is link https://rive.app/community/4054-8407-polito/
Related
I am using android studio and flutter. I want to build the screen as shown below in the image:screen Image
let's say I have 4 screens. on the first screen, the bar will load up to 25%. the user will move to next screen by clicking on continue, the linearbar will load up to 50% and so on. the user will get back to previous screens by clicking on the back button in the appbar.
I tried stepper but it doesn't serve my purpose.
You can use the widget LinearProgressIndicator(value: 0.25,) for the first screen and with value: 0.5 for the second screen etc.
If you want to change the bar value within a screen, just use StatefullWidget's setState(), or any state management approaches will do.
import 'package:flutter/material.dart';
class ProgressPage extends StatefulWidget {
const ProgressPage({super.key});
#override
State<ProgressPage> createState() => _ProgressPageState();
}
class _ProgressPageState extends State<ProgressPage> {
final _pageController = PageController();
final _pageCount = 3;
int? _currentPage;
double? _screenWidth;
double? _unit;
double? _progress;
#override
void initState() {
super.initState();
_pageController.addListener(() {
_currentPage = _pageController.page?.round();
setState(() {
_progress = (_currentPage! + 1) * _unit!;
});
});
}
#override
void didChangeDependencies() {
super.didChangeDependencies();
_screenWidth = MediaQuery.of(context).size.width;
_unit = _screenWidth! / _pageCount;
_progress ??= _unit;
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('HOZEROGOLD')),
body: Column(
children: [
Align(
alignment: Alignment.topLeft,
child: Container(
color: Colors.yellow,
height: 10,
width: _progress,
),
),
Expanded(
child: PageView(
controller: _pageController,
children: _createPage(),
),
),
],
),
);
}
List<Widget> _createPage() {
return List<Widget>.generate(
_pageCount,
(index) => Container(
color: Colors.white,
child: Center(
child: ElevatedButton(
onPressed: () => _moveNextPage(),
child: Text('NEXT $index'),
),
),
),
);
}
void _moveNextPage() {
if (_pageController.page!.round() == _pageCount-1) {
_pageController.jumpToPage(0);
} else {
_pageController.nextPage(
curve: Curves.bounceIn,
duration: const Duration(milliseconds: 100));
}
}
}
HAPPY CODING! I hope it will be of help.
I am a beginner to rive and flutter. I am building a favorite items page in flutter. If there are not anything added to favorites I need to show a riveAnimation on screen. I already implemented almost everything to show the animation on screen. But I need to toggle a jumping animation when user tap on the animation which is really cool. for now I have the animation on 'Idle' mode
You may want to refer to the rive file => Go to Rive. And I renamed Rive stateMachine name to Bird. Everything else is the same.
summary => I want bird to jump when user tap on him :)
The code and the image may be little bit bigger. Sorry about that
class Favourites extends StatefulWidget {
Favourites({Key? key}) : super(key: key);
#override
State<Favourites> createState() => _FavouritesState();
}
class _FavouritesState extends State<Favourites> {
String animation = 'idle';
SMIInput<String>? _birdInput;
Artboard? _birdArtboard;
void jump() {
setState(() {
_birdInput?.value = 'Pressed';
});
}
#override
void initState() {
super.initState();
rootBundle.load('assets/rive/bird.riv').then(
(data) {
final file = RiveFile.import(data);
final artboard = file.mainArtboard;
var controller = StateMachineController.fromArtboard(
artboard,
'Bird',
);
if (controller != null) {
artboard.addController(controller);
_birdInput = controller.findInput('Pressed');
}
setState(() => _birdArtboard = artboard);
},
);
}
#override
Widget build(BuildContext context) {
final favourite = Provider.of<Favourite>(context);
return Scaffold(
backgroundColor: Colors.grey[300],
appBar: const CustomAppBar(title: 'Favourites'),
body: favourite.items.isEmpty
? Center(
child: Column(
children: [
SizedBox(
width: 300,
height: 500,
child: _birdArtboard == null
? const SizedBox()
: Center(
child: GestureDetector(
onTap: () {},
child: Rive(artboard: _birdArtboard!),
),
),
),
NeumorphicButton(),
],
),
)
: CustomGrid(),
);
}
}
If you open/run rive file on rive site, you can find that it is using Trigger variable for jumping and it is using State Machine 1 state machine.
Next thing comes about declaring variable. You need to use SMITrigger data type for this and use StateMachineController to control the animation.
Use .findSMI(..) instead of .findInput() for SMITrigger.
To start animation on trigger, use
trigger?.fire();
I will encourage you to take a look on editor and check input variable type while performing rive animation.
So the full widget that will provide animation is
class Favourites extends StatefulWidget {
const Favourites({Key? key}) : super(key: key);
#override
State<Favourites> createState() => _FavouritesState();
}
class _FavouritesState extends State<Favourites> {
String animation = 'idle';
Artboard? _birdArtboard;
SMITrigger? trigger;
StateMachineController? stateMachineController;
#override
void initState() {
super.initState();
rootBundle.load('assets/rive/bird.riv').then(
(data) {
final file = RiveFile.import(data);
final artboard = file.mainArtboard;
stateMachineController =
StateMachineController.fromArtboard(artboard, "State Machine 1");
if (stateMachineController != null) {
artboard.addController(stateMachineController!);
trigger = stateMachineController!.findSMI('Pressed');
stateMachineController!.inputs.forEach((e) {
debugPrint(e.runtimeType.toString());
debugPrint("name${e.name}End");
});
trigger = stateMachineController!.inputs.first as SMITrigger;
}
setState(() => _birdArtboard = artboard);
},
);
}
void jump() {
trigger?.fire();
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.grey[300],
body: Center(
child: Column(
children: [
SizedBox(
width: 300,
height: 400,
child: _birdArtboard == null
? const SizedBox()
: Center(
child: GestureDetector(
onTap: () {
jump();
},
child: Rive(artboard: _birdArtboard!),
),
),
),
],
),
));
}
}
I'm trying to show a video inside a container, videos could exceed container's aspect ratio, so the they need to be cropped.
With images it is simple as that:
Image.network(someUrl, fit: BoxFit.cover)
but how to do it with VideoPlayer?
my current code looks like this:
Stack(
children: [
Container(
width: double.infinity,
height: double.infinity,
child: ShowcaseVideoPlayer(someUrl)
),
Material(
color: Colors.transparent,
child: InkWell(
onTap: () {},
),
),
],);
class ShowcaseVideoPlayer extends StatefulWidget {
final String url;
ShowcaseVideoPlayer(this.url);
#override
_ShowcaseVideoPlayerState createState() => _ShowcaseVideoPlayerState();
}
class _ShowcaseVideoPlayerState extends State<ShowcaseVideoPlayer> {
VideoPlayerController _controller;
Future<void> _initializeVideoPlayerFuture;
#override
void initState() {
_controller = VideoPlayerController.network(widget.url);
_initializeVideoPlayerFuture = _controller.initialize();
_controller.setVolume(0);
super.initState();
}
#override
Widget build(BuildContext context) {
return FutureBuilder(
future: _initializeVideoPlayerFuture,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
_controller.play();
// If the VideoPlayerController has finished initialization, use
// the data it provides to limit the aspect ratio of the VideoPlayer.
return AspectRatio(
aspectRatio: _controller.value.aspectRatio,
// Use the VideoPlayer widget to display the video.
child: VideoPlayer(_controller),
);
} else {
// If the VideoPlayerController is still initializing, show a
// loading spinner.
return Center(),
);
}
},
);
}
#override
void dispose() {
_controller.dispose();
super.dispose();
}
}
I need a stack as I will have to show other things over the video. I tried without the stack and the player maintains the aspect ratio of the video, basically letter-boxing it. With the stack, the video stratches, losing the original aspect ratio:
to be clear, what I want is this:
EDIT: I tried random things on it and managed to achieve something, I removed the Container and wrapped the VideoPlayer like this:
Stack(
children: [
OverflowBox(
child: Wrap(
children: [
ShowcaseVideoPlayer(someUrl)
],
),
)]);
now the the video is actually cropped, but not centered (I see the upper part of the video instead of the central one). Wrapping Wrap in a Center and setting alignment: Alignment.center on OverfowBox have no effect. Any idea?
I am trying to create a background video splash screen for my app.
Currently, I am achieving a blank screen by running this code.
void main() => runApp(WalkThrough());
class WalkThrough extends StatefulWidget {
#override
_WalkThroughState createState() => _WalkThroughState();
}
class _WalkThroughState extends State<WalkThrough> {
VideoPlayerController _controller;
#override
void initState() {
super.initState();
// Pointing the video controller to our local asset.
_controller = VideoPlayerController.asset('assets/video.mp4')
..initialize().then((_) {
// Once the video has been loaded we play the video and set looping to true.
_controller.play();
_controller.setLooping(true);
_controller.setVolume(0.0);
_controller.play();
// Ensure the first frame is shown after the video is initialized.
setState(() {});
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: <Widget>[
I suspect the problem may be here and have based my research off this Full screen video background in Flutter on Login as I am trying to achieve a similar result.
SizedBox.expand(
child: FittedBox(
// If your background video doesn't look right, try changing the BoxFit property.
// BoxFit.fill created the look I was going for.
fit: BoxFit.fill,
child: SizedBox(
width: _controller.value.size?.width ?? 0,
height: _controller.value.size?.height ?? 0,
child: VideoPlayer(_controller),
),
),
),
I think the video player package has an issue to show video in the Ios simulator. I had the same issue and search for it and find out this issue in Github. until now this issue is open. I tested the video player on a real device and there were no problems.
Use this video player video_player plugin
& Save your mp4 file in assets/videos location
Try the below code
import 'dart:async';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:video_player/video_player.dart';
import 'HomePage.dart';
class SplashPage extends StatefulWidget {
SplashPage({Key key}) : super(key: key);
#override
State<StatefulWidget> createState() => _SplashPageState();
}
class _SplashPageState extends State<SplashPage> {
VideoPlayerController _controller;
bool _visible = false;
#override
void initState() {
super.initState();
SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitUp,
]);
_controller = VideoPlayerController.asset("assets/video/splash_video.mp4");
_controller.initialize().then((_) {
_controller.setLooping(true);
Timer(Duration(milliseconds: 100), () {
setState(() {
_controller.play();
_visible = true;
});
});
});
Future.delayed(Duration(seconds: 4), () {
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(
builder: (context) => HomePage(param_homepage: 'Welcome Home')),
(e) => false);
});
}
#override
void dispose() {
super.dispose();
if (_controller != null) {
_controller.dispose();
_controller = null;
}
}
_getVideoBackground() {
return AnimatedOpacity(
opacity: _visible ? 1.0 : 0.0,
duration: Duration(milliseconds: 1000),
child: VideoPlayer(_controller),
);
}
_getBackgroundColor() {
return Container(color: Colors.transparent //.withAlpha(120),
);
}
_getContent() {
return Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.start,
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Stack(
children: <Widget>[
_getVideoBackground(),
],
),
),
);
}
}
I'm trying to position some text over a video.
The video is currently taking as much space as possible while retaining it's original aspect ratio. Ideally I'd like it to keep doing this as I want the video to resize to fit the browser window.
I'm assuming I need to get get the height/width of the video dynamically..
If anyone knows how to make a video play automatically that would be great as well - I'm using the video_player package.
class HomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.black,
drawer: ResponsiveLayout.isSmallScreen(context) ? NavDrawer() : null,
body: Container(
child: SingleChildScrollView(
child: Column(
children: <Widget>[
NavBar(),
Body(),
Footer(),
],
),
),
),
);
}
}
class Body extends StatelessWidget {
#override
Widget build(BuildContext context) {
return ResponsiveLayout(
largeScreen: LargeScreen(),
mediumScreen: LargeScreen(),
smallScreen: LargeScreen(),
);
}
}
class LargeScreen extends StatefulWidget {
#override
_LargeScreenState createState() => _LargeScreenState();
}
class _LargeScreenState extends State<LargeScreen> {
VideoPlayerController _videoPlayerController;
Future<void> _initializeVideoPlayerFuture;
#override
void initState() {
_videoPlayerController = VideoPlayerController.asset(
'assets/videos/video.mp4',
);
_initializeVideoPlayerFuture = _videoPlayerController.initialize();
super.initState();
}
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 40),
child: Column(
children: <Widget>[
FutureBuilder(
future: _initializeVideoPlayerFuture,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
// If the VideoPlayerController has finished initialization, use
// the data it provides to limit the aspect ratio of the VideoPlayer.
return AspectRatio(
aspectRatio: _videoPlayerController.value.aspectRatio,
// Use the VideoPlayer widget to display the video.
child: VideoPlayer(_videoPlayerController),
);
} else {
// If the VideoPlayerController is still initializing, show a
// loading spinner.
return Center(child: CircularProgressIndicator());
}
},
),
],
),
);
}
#override
void dispose() {
super.dispose();
_videoPlayerController.dispose();
}
}
you can wrap your Widgets in stack widget and use positioning to position your text
AspectRatio(
aspectRatio: _videoPlayerController.value.aspectRatio,
// Use the VideoPlayer widget to display the video.
child: Stack(children:<Widget>[
VideoPlayer(_videoPlayerController),
Positioned(bottom:10,left:10,
child:Text("my text here))
])
)
update
If anyone knows how to make a video play automatically that would be great as well - I'm using the video_player package.
you can set the state of your video using your controller
_videoPlayerController.value.isPlaying
I want the video to resize to fit the browser window.
you can wrap your video in a SizedBox.expand which Creates a box that will become as large as its parent allows.
sized box constructors