Is there any solution to make my Flare Button work properly? Flutter - flutter

Basically, I have a button that I made in Flare and it should make an animation then I tap it! It works well but the animation starts everytime I tap anywhere within my app and not only the button.
Is there any way I can make animation only when I click in the Button Area? I`m using GestureDetector to handle tapping.
https://i.stack.imgur.com/ZBjmz.jpg
My code:
import 'package:flutter/material.dart';
import 'package:flare_flutter/flare_actor.dart';
import 'package:vibrate/vibrate.dart';
void main() => runApp(MaterialApp(
home: InvalidButton(),
));
class InvalidButton extends StatefulWidget {
#override
_InvalidButtonState createState() => _InvalidButtonState();
}
class _InvalidButtonState extends State<InvalidButton> {
var _type = FeedbackType.heavy;
final FlareControls controls = FlareControls();
void _playAnimation(){
controls.play('invalid');
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.pink[50],
body: Container(
child: GestureDetector(
onTap: () {
setState(() {
_playAnimation();
Vibrate.feedback(_type);
});
},
child: FlareActor(
'assets/invalid_button.flr',
animation: 'invalid',
alignment: Alignment.center,
fit: BoxFit.contain,
controller: controls,
),
),
),
);
}
}
I`m a newbie so will be glad to any help!

Do you have space around the button in the Rive editor ? If so, go in design mode, click Artboard and then "fit contents". That should remove the extra space. Then, wrap your FlareActor with a SizedBox and set its size, like so :
SizedBox(
width: 100,
height: 100,
child: FlareActor(),
)
That should do it.

Related

Flutter open popup menu above list item

I am making a chat app in Flutter with Firestore but I am stumped with one of the requirement: Making a reaction menu appear above a chat dialog. I need that when the user long press on a chat text the reaction menu would appear above the current chat position. Something like Facebook Messenger app:
I have look around and found https://medium.com/#duytq94/facebook-reactions-with-flutter-9019ce8b95b8 but it seems it is too much for just a simple function (making a popup menu appear above a list tile and don't need the animation). I also found this package: https://pub.dev/packages/flutter_reaction_button, but it does not allow to wrap the widget around another to open up the reacton menu. Is there a simple way that I can archive this? I have looked into PopupMenuButton but it only allows onPressed and not long press.
You can use Overlay widget. I make a simple example for you.
import 'package:flutter/material.dart';
class Temp extends StatefulWidget {
#override
_TempState createState() => _TempState();
}
class _TempState extends State<Temp> {
GlobalKey floatingKey = LabeledGlobalKey("Floating");
bool isFloatingOpen = false;
OverlayEntry floating;
OverlayEntry createFloating() {
RenderBox renderBox = floatingKey.currentContext.findRenderObject();
Offset offset = renderBox.localToGlobal(Offset.zero);
return OverlayEntry(
builder: (context) {
return Positioned(
left: offset.dx,
width: renderBox.size.width,
top: offset.dy - 50,
child: Material(
elevation: 20,
child: Container(
height: 50,
color: Colors.blue,
child: Text("I'm floating overlay")
)
)
);
}
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: RaisedButton(
key: floatingKey,
color: Colors.red,
onPressed: (){
setState(() {
if(isFloatingOpen) floating.remove();
else {
floating = createFloating();
Overlay.of(context).insert(floating);
}
isFloatingOpen = !isFloatingOpen;
});
},
)
),
);
}
}

Flutter overlay page, details account page

I'm trying to make an app and I need the help of the community for something: I'm trying to make an overlay (which would be a new page) coming on top of an other page. Look at these screenshots found on dribbble and I'll try to explain better then.
So, imaging you're on the page as shown on the first screenshot. What I want to do is, when you click, for exemple on the "contact page" button, a windows comes up from the bottom of the screen with a linear animation, and show the view, as on the screenshot on the right of the screen. But I don't want it to be a "real new page" because as you can see on the second screenshot, we can see in transparency the first page behind...
And of course, when you click the cross button, the window pop...
Ask me any question if I'm not clear enough.
Any help is welcome !
Thanks a lot, stackoverflow is an extraordinary community !
Here a min example how you can achieve this using AnimatedPositioned widget hoping it will help you get started.
class ExampleApp extends StatefulWidget {
#override
_ExampleAppState createState() => _ExampleAppState();
}
class _ExampleAppState extends State<ExampleApp> {
final double containerHeight = 200.0;
bool _showProfile;
#override
void initState() {
_showProfile = false;
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
color: Colors.teal,
child: Stack(
children: <Widget>[
Container(
color: Colors.redAccent,
child: Center(
child: FlatButton(
child: Text("Animate"),
onPressed: () {
setState(() {
_showProfile = true;
});
},
),
),
),
AnimatedPositioned(
bottom: _showProfile ? 0 : -containerHeight,
right: 0,
left: 0,
duration: Duration(milliseconds: 300),
child: Container(
color: Colors.white,
height: containerHeight,
))
],
),
),
);
}
}
you can achieve the same with Bottomsheet too.
Check out
https://api.flutter.dev/flutter/material/BottomSheet-class.html

How to align widget to another widget in Flutter?

I have a RaisedButton widget inside of a Center widget as one of the widgets in a Column of widgets. I want to add a CircularProgressIndicator to the right side of this button and show it when the button is pressed. Yet I want to leave the button centred when the progress bar is shown. In other words I want the button always be in the center and the progress bar aligned to this button.
I tried to use a Row here but this pushes the button and it becomes not centred any more.
EDIT1: Looking at the result of the solution provided by #Anil Chauhan (thanks for the answer):
Like I said before that I tried to use Row like he did, the problem is that in this case the button is not in the centred in the screen and is pushed by the progress bar. And I need it to stay in the middle of it's row.
EDIT2: #Anil Chauhan edited answer now works for a specific case in which the button is predetermined size. But if the size of the button is changed based on the language of the text (in apps that have several languages) this solution will not work.
This is the reason the question I asked is: "How to align widget to another widget". Because if I could that I don't have to worry about the button text size any more.
What would be the right way to handle this in Flutter?
class MyPage extends StatefulWidget {
#override
_MyPageState createState() => _MyPageState();
}
class _MyPageState extends State<MyPage> {
bool _showIndicator = false;
void _onButtonClicked() {
setState(() {
_showIndicator = !_showIndicator;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Row(
children: <Widget>[
const Expanded(child: SizedBox()),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 10.0),
child: RaisedButton(
child: Text("I am Too Big"),
onPressed: _onButtonClicked,
),
),
Expanded(
child: _showIndicator
? const Align(
alignment: Alignment.centerLeft,
child: CircularProgressIndicator(),
)
: const SizedBox(),
),
],
),
),
);
}
}
Here is my explanation:
The RaisedButton size is depends on its child. If you add it to Row it will automatically align to left(or start).
Expanded widget will fill the remaining space in Flex widget(Row & Column are child classes of Flex). If you add more than one Expanded widgets, it will split equally. So I added two Expanded to both the side of button to make it center.
Now We should give child for Expanded Widget.
For the first one(left) we don't have anything to display so I added SizedBox.
For the second one(right) we need CircularProgressIndicator. so I added it.
The Expanded widget will try to make its child to fill the space inside of it. So the CircularProgressIndicator will become Ellipse shaped. We can avoid this by using Align Widget.
Try this:
Updated:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: MyAppOne(),
);
}
}
class MyAppOne extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyAppOne>{
bool show = false;
#override
Widget build(BuildContext context){
return Scaffold(
body: Stack(
alignment: Alignment.center,
children: <Widget>[
Container(
alignment: Alignment.center,
child: RaisedButton(
onPressed: () {
setState(() {
show =!show;
});
},
child: Text('Show'),
),
),
Positioned(
right: MediaQuery.of(context).size.width * .20,
child: Container(
alignment: Alignment.center,
padding: EdgeInsets.all(10.0),
child: show ? CircularProgressIndicator() : Container(),
),
)
],
)
);
}
}
Flutter's Column and Row widgets have two convenient properties called mainAxisAlignment and crossAxisAlignment. I assume since you're using a Column and want the CircularProgressIndicator to the right of the button, you might be want to use crossAxisAlignment since the cross-axis of a Column is along the horizontal.
If possible, please share your code for better understanding and support of the issue.

How to stop GIF loop in flutter?

How to stop gif loop after 1 time? It is animating forever.
Image(
color: Colors.red,
image: new AssetImage(Icn.splash),
width: 150.0,
),
Solution
- Go to https://ezgif.com/loop-count
- Upload gif
- Set loop count 1 (0 - infinity)
- Change loop count and download gif
I hope this flutter package will help;
A flutter plugin to control gif animation: https://pub.dev/packages/gif_ani
Two steps:
Edit the gif loop count from 0(infinite) to 1 using any online gif editing tool like https://onlinegiftools.com/change-gif-loop-count and/or https://ezgif.com/loop-count and download the edited gif. This would ensure that the gif is played only once.
Manually evict the image cache to ensure the gif is played again when the user navigates away and/or uses the back button and revisits the page assuming the goal is to play the gif every time the user visits the page but just once.
Sample code:
import 'package:flutter/material.dart';
class OneTimeGifLoader extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return _OneTimeGifLoaderState();
}
}
class _OneTimeGifLoaderState extends State<OneTimeGifLoader> {
late AssetImage myAssetImage;
#override
void initState() {
super.initState();
myAssetImage = const AssetImage("assets/path/to/my/image.gif");
}
#override
void dispose() {
super.dispose();
myAssetImage.evict(); //Evict image cache
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text("One time gif loader"),
),
body: Container(
width: double.infinity,
height: double.infinity,
decoration: BoxDecoration(
image: DecorationImage(
image: myAssetImage,
fit: BoxFit.contain,
),
color: Colors.white,
),
),
),
);
}
}
this code:
Image.asset("assets/tasky_logo.gif",
gaplessPlayback: false, fit: BoxFit.fill)

Refresh widget or page in Flutter without ListView et al

I want refresh my page without having a scrollable content, i.e. without having a ListView et al.
When I want use RefreshIndicator, the documentation says it needs a scrollable widget like ListView.
But if I want to refresh and want to use the refresh animation of RefreshIndicator without using a ListView, GridView or any other scorllable widget, how can i do that?
You can simply wrap your content in a SingleChildScrollView, which will allow you to use a RefreshIndicator. In order to make the pull down to refresh interaction work, you will have to use AlwaysScrollableScrollPhysics as your content will most likely not cover more space than available without a scroll view:
RefreshIndicator(
onRefresh: () async {
// Handle refresh.
},
child: SingleChildScrollView(
physics: const AlwaysScrollableScrollPhysics(),
child: /* your content */,
),
);
You can just use GestureDetector, I have created a sample for you, but it's not perfect, you can customize it to your own needs, it just detects when you swipe from the top.
class Test extends StatefulWidget {
#override
_TestState createState() => _TestState();
}
class _TestState extends State<Test> {
var refresh=false;
void refreshData(){
if(!refresh){
refresh=true;
print("Refreshing");
Future.delayed(Duration(seconds: 4),(){
refresh =false;
print("Refreshed");
});
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
title: Text("Test"),
centerTitle: true,
),
body: GestureDetector(
child: Container(
color: Colors.yellow,
height: double.infinity,
width: double.infinity,
child: Center(child: Text('TURN LIGHTS ON')),
),
onVerticalDragUpdate: (DragUpdateDetails details){
print("direction ${details.globalPosition.direction}");
print("distance ${details.globalPosition.distance}");
print("dy ${details.globalPosition.dy}");
if(details.globalPosition.direction < 1 && (details.globalPosition.dy >200 && details.globalPosition.dy < 250)){
refreshData();
}
},
));
}
}