i want to read some images that are in "myImages" folder in storage of my phone. i need to list only these images. how can i open myImages folder and list images in that by flutter?
you can use Image.file(File('FilePath')) like this:
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Image.file(File('FilePath')),
);
}
}
Related
My application has a stateful widget which is the profile area, I would like to display an animated icon indicating to the user that is possible to scroll the screen, I want to use the animated icon, how to auto animate an AnimatedIcon as soon the Profile screen loads, thanks.
Obs.: The play_pause is just a placeholder for an animated icon
import 'package:flutter/material.dart';
void main() {
runApp(Profile());
}
class Profile extends StatefulWidget {
#override
ProfileState createState() {
return ProfileState();
}
}
class ProfileState extends State<Profile> with TickerProviderStateMixin {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: AnimatedIcon(
progress: AnimationController(
vsync: this,
duration: Duration(milliseconds: 400),
reverseDuration: Duration(milliseconds: 400),
),
icon: AnimatedIcons.play_pause,
),
)
)
);
}
}
You have to create an instance of AnimationController and initialize it on the initState. Then you can start the animation by calling animateTo method.
import 'package:flutter/material.dart';
void main() {
runApp(Profile());
}
class Profile extends StatefulWidget {
#override
ProfileState createState() {
return ProfileState();
}
}
class ProfileState extends State<Profile> with TickerProviderStateMixin {
AnimationController _animationController;
#override
void initState() {
super.initState();
_animationController = AnimationController(
vsync: this,
duration: Duration(milliseconds: 400),
);
_animationController.animateTo(1.0);
}
#override
void dispose() {
_animationController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: AnimatedIcon(
progress: _animationController,
icon: AnimatedIcons.play_pause,
),
),
),
);
}
}
you could do that using the animationController
_animationController.forward(); /// to start the animation
You can start your animation after the build method executes by calling it like this.
#override
void initState(){
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_){
_animationController.forward();
});
}
In my Flutter app I have lots of pop up dialogs, but I need to dismiss any open dialog when app goes to background (user switches to another app).
I know about Lifecycle, but it's not easy to implement it for all dialogs.
Did you try Navigator.popUntil on the life cycle?.
Navigator.popUntil(context, (route) => !(route is PopupRoute));
Example:
import 'package:flutter/material.dart';
void main() => runApp(MaterialApp(home: HomePage()));
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> with WidgetsBindingObserver {
#override
void initState() {
WidgetsBinding.instance.addObserver(this);
super.initState();
}
void _showDialogs() {
showDialog(
context: context,
builder: (context) => AlertDialog(title: Text("Dialog 1")),
);
showDialog(
context: context,
builder: (context) => AlertDialog(title: Text("Dialog 2")),
);
showDialog(
context: context,
builder: (context) => AlertDialog(title: Text("Dialog 3")),
);
}
#override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: RaisedButton(
child: Text("show multiple dialogs"),
onPressed: _showDialogs,
),
),
);
}
#override
void didChangeAppLifecycleState(AppLifecycleState state) {
if (state == AppLifecycleState.paused)
Navigator.popUntil(context, (route) => !(route is PopupRoute));
}
}
Navigator.of(context,rootNavigator:true).pop();
I've been trying to make a Container move from the bottom of the screen to the middle when I click a button. However, I can't figure out how to properly execute the animation only when I press the button. Furthermore, it seems that when I call the _customWidget.startAnimation() method an error stating I called the function on void always happens. Here are my questions:
How do I access startAnimation() inside MyCustomWidget properly and how should I structure the code to only run the animation when I press the button?
Main.dart:
import 'package:flutter/material.dart';
import 'MyCustomWidget.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
MyCustomWidget _customWidget;
#override
void initState() {
super.initState();
_customWidget = MyCustomWidget();
}
#override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Center(
child: MyCustomWidget(),
),
FloatingActionButton(
onPressed: () => {} //_customWidget.startAnimation() gives an error,
)
],
);
}
}
MyCustomWidget.dart:
import 'package:flutter/material.dart';
class MyCustomWidget extends StatefulWidget {
#override
_MyCustomWidgetState createState() => _MyCustomWidgetState();
startAnimation() {
debugPrint('is this where the function should be?');
}
}
class _MyCustomWidgetState extends State<MyCustomWidget>
with SingleTickerProviderStateMixin {
AnimationController _animationController;
Animation<Offset> _offsetAnimation;
void startAnimation() {
debugPrint('or is it here?');
}
#override
void initState() {
super.initState();
//Following code should go in startAnimation() rather than letting it execute
//every time the object is created
_animationController = AnimationController(
vsync: this,
duration: const Duration(seconds: 2),
)..repeat(reverse: true);
_offsetAnimation = Tween<Offset>(
begin: Offset.zero,
end: const Offset(1.5, 0.0),
).animate(CurvedAnimation(
parent: _animationController,
curve: Curves.elasticIn,
));
}
#override
Widget build(BuildContext context) {
return SlideTransition(
position: _offsetAnimation,
child: Container(
color: Colors.white,
height: 50,
width: 50,
),
);
}
#override
void dispose() {
super.dispose();
_animationController.dispose();
}
}
In Flutter, you access the child widgets using key. You also have to make the state public (remove the underscore from _MyCustomWidgetState)
So in the child:
class MyCustomWidget extends StatelessWidget {
final Key key;
MyCustomWidget(this.key) : super(key: key);
[...]
in the parent:
GlobalKey<MyCustomWidgetState> key = GlobalKey<MyCustomWidgetState>();
[...]
Center(
child: MyCustomWidget(key)
)
and calling the child (from parent):
key.currentState.startAnimation();
Tien's answer got my widget working correctly, here's how the two files look after the modifications:
Main.dart
import 'package:flutter/material.dart';
import 'MyCustomWidget.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
GlobalKey<MyCustomWidgetState> _customWidgetKey =
GlobalKey<MyCustomWidgetState>();
#override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Center(
child: MyCustomWidget(_customWidgetKey),
),
FloatingActionButton(
onPressed: () => _customWidgetKey.currentState.show(),
)
],
);
}
}
MyCustomWidget.dart:
import 'package:flutter/material.dart';
class MyCustomWidget extends StatefulWidget {
final Key key;
MyCustomWidget(this.key) : super(key: key);
#override
MyCustomWidgetState createState() => MyCustomWidgetState();
}
class MyCustomWidgetState extends State<MyCustomWidget>
with SingleTickerProviderStateMixin {
AnimationController _animationController;
Animation<Offset> _offsetAnimation;
void show() {
setState(() {
_animationController.animateTo(1.0);
});
}
void hide() {
setState(() {
_animationController.animateTo(0.0);
});
}
#override
void initState() {
super.initState();
_animationController = AnimationController(
vsync: this,
duration: const Duration(seconds: 1),
);
_offsetAnimation = Tween<Offset>(
begin: Offset(0.0, 40),
end: Offset.zero,
).animate(CurvedAnimation(
parent: _animationController,
curve: Curves.easeInOutQuint,
));
}
#override
Widget build(BuildContext context) {
return SlideTransition(
position: _offsetAnimation,
child: Container(
child: FloatingActionButton(
backgroundColor: Colors.white,
onPressed: () => hide(),
),
),
);
}
#override
void dispose() {
super.dispose();
_animationController.dispose();
}
}
This gets you a button which brings up a button when pressed. Clicking the second button sends it down. This whole thing is going to be useful to make custom widgets pop up and down!
I need to start an animation of a child widget from a parent widget. How can I do this?
I've tried giving the parent the controller, but then how do you replace vsync: this?
This is the basic code (I haven't actually tested this code yet, but I shows what I mean):
import 'package:flutter/material.dart';
class ParentWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
ChildText(),
FlatButton(
child: Text('start the animation'),
onPressed: () {
// start the animation!!!????????
},
)
],
);
}
}
class ChildText extends StatefulWidget {
#override
_ChildTextState createState() => _ChildTextState();
}
class _ChildTextState extends State<ChildText> with TickerProviderStateMixin {
AnimationController _controller;
Animation _animation;
#override
void initState() {
super.initState();
// actual animation is much more complex, this is just a random demo
_controller =
AnimationController(vsync: this, duration: Duration(seconds: 2));
_animation = Tween(begin: -1.0, end: 100.0).animate(CurvedAnimation(
parent: _controller,
curve: Curves.fastOutSlowIn,
));
}
#override
Widget build(BuildContext context) {
return Transform.translate(
offset: Offset(0, _animation.value),
child: Text('Text with fancy animation'));
}
}
You can try this:
class ParentWidget extends StatefulWidget {
#override
_ParentWidget createState() => _ParentWidget();
}
class _ParentWidget extends State<ParentWidget> with TickerProviderStateMixin {
AnimationController _controller;
#override
void initState() {
super.initState();
_controller =
AnimationController(vsync: this, duration: Duration(seconds: 2));
}
#override
void dispose() {
_controller.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
ChildText(_controller),
FlatButton(
child: Text('start the animation'),
onPressed: () {
// start the animation!!!
_controller.forward();
},
)
],
);
}
}
class ChildText extends StatefulWidget {
ChildText(this._controller);
final AnimationController _controller;
#override
_ChildTextState createState() => _ChildTextState();
}
class _ChildTextState extends State<ChildText> with TickerProviderStateMixin {
Animation _animation;
#override
void initState() {
super.initState();
_animation = Tween(begin: -1.0, end: 100.0).animate(CurvedAnimation(
parent: widget._controller,
curve: Curves.fastOutSlowIn,
));
}
#override
Widget build(BuildContext context) {
return Transform.translate(
offset: Offset(0, _animation.value),
child: Text('Text with fancy animation'));
}
}
Passing state down to widgets is easy. I have a StatefulWidget that contains an animation with its controller. I need to be able to trigger the animation from another widget higher in my widget tree.
My MainApp should trigger the animation using a button.
As I understand AnimationController only has an imperative API. I can call controller.forward() or controller.reverse(). But to do this I need to expose the controller to my MainApp.
What I currently do is to keep a global variable of my state around.
class MainApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new Scaffold(
...
body: new LogoWidget(),
);
}
_startAnimation() {
_state.restartAnimation();
}
}
_LogoWidgetState _state; // yuk!
class LogoWidget extends StatefulWidget {
_LogoWidgetState createState() {
_state = _LogoWidgetState();
return _state;
}
}
class _LogoWidgetState extends State<LogoWidget>
with SingleTickerProviderStateMixin {
Animation<double> animation;
AnimationController controller;
restartAnimation() {
controller.value == 1.0 ? controller.reverse() : controller.forward();
}
...
}
(full sourcecode here)
What is a better way to deal with this?
You don't need _LogoWidgetState _state; // yuk! out in the middle of nowhere, but you can try:
create LogoWidget _myBody = LogoWidget(), and use that for your body:
similarily, apply with final _LogoWidgetState _state = _LogoWidgetState()
then call it as _myBody._state.restartAnimation()
Your sample, modified:
class MainApp extends StatelessWidget {
LogoWidget _myBody = LogoWidget(); //<---
#override
Widget build(BuildContext context) {
return new Scaffold(
...
body: _myBody, //<---
);
}
_startAnimation() {
_myBody._state.restartAnimation(); //<---
}
}
class LogoWidget extends StatefulWidget {
final _LogoWidgetState _state = _LogoWidgetState(); //<---
_LogoWidgetState createState() {
return _state;
}
}
But if you think _myBody._state.restartAnimation() is too long, you can shorten it with:
class LogoWidget extends StatefulWidget {
final _LogoWidgetState _state = _LogoWidgetState(); //<---
void restartAnimation() { //<---
_state.restartAnimation();
}
_LogoWidgetState createState() {
return _state;
}
}
Then just use _myBody.restartAnimation()
Here's some relevant posts:
call method in one stateful widget from another stateful widget - Flutter
Flutter: Call a function on a child widget's state