How do you achieve the smooth transition when the checkmark is added?
Clicking the element will setState update the pressAttention variable, and therefore add the checkmark widget to the list of children of the row.
For now it just instantly rebuilds the row, and adds the checkmark, but I would really like it to smoothly do as in the GIF.
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
widget.amount,
style: const TextStyle(
color: Colors.white, fontWeight: FontWeight.w700),
),
if (pressAttention)
Padding(
padding: const EdgeInsets.only(left: 10),
child: Container(
width: 23,
height: 23,
decoration: BoxDecoration(
color: Theme.of(context).highlightColor,
shape: BoxShape.circle,
),
child: Padding(
padding: const EdgeInsets.all(4),
child: SvgPicture.asset(
MyIcons.checkmarkThick,
),
),
),
)
],
),
try this:
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
late Animation<double> _animation;
late Animation<double> _opacityAnimation;
late Animation _colorAnimation;
late AnimationController _controller;
var pressAttention = false;
#override
void initState() {
super.initState();
_controller =
AnimationController(duration: Duration(milliseconds: 500), vsync: this)
..addListener(() => setState(() {}));
_animation = Tween(begin: 15.0, end: 0.0).animate(_controller);
_opacityAnimation = Tween(begin: 0.0, end: 1.0).animate(_controller);
_colorAnimation =
ColorTween(begin: Colors.grey, end: Colors.purple).animate(_controller);
}
#override
void dispose() {
_controller.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.black,
body: Center(
child: Center(
child: Container(
child: InkWell(
splashColor: Colors.transparent,
highlightColor: Colors.transparent,
onTap: () {
if (pressAttention) {
_controller.forward();
} else {
_controller.reverse();
}
setState(() {
pressAttention = !pressAttention;
});
},
child: AnimatedBuilder(
animation: _controller,
builder: (context, child) {
return Container(
width: 100,
decoration: BoxDecoration(
border: Border.all(color: _colorAnimation.value),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Transform.translate(
offset: Offset(_animation.value, 0),
child: Text(
'1000',
style: const TextStyle(
color: Colors.white,
fontWeight: FontWeight.w700),
),
),
Opacity(
opacity: _opacityAnimation.value,
child: Padding(
padding: EdgeInsets.only(left: 10),
child: Container(
decoration: BoxDecoration(
color: Theme.of(context).highlightColor,
shape: BoxShape.circle,
),
child: const Padding(
padding: EdgeInsets.all(4),
child: Icon(
Icons.check,
size: 13,
),
),
),
),
)
],
),
);
}),
),
),
),
),
);
}
}
You can achieve this with a combination of Animated Widgets. Set their behaviours and durations and you should be good to go.
Related
This is the Animation Class where MoviesListView Widget Calls When i apply Animation on listViewBuilder GestureDetector not get Call
import 'package:autoscroll/MoviesListView.dart';
import 'package:autoscroll/data.dart';
import 'package:flutter/material.dart';
class HomeScreen extends StatefulWidget {
#override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
ScrollController _scrollController1 = ScrollController();
ScrollController _scrollController2 = ScrollController();
ScrollController _scrollController3 = ScrollController();
#override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
double minScrollExtent1 = _scrollController1.position.minScrollExtent;
double maxScrollExtent1 = _scrollController1.position.maxScrollExtent;
double minScrollExtent2 = _scrollController2.position.minScrollExtent;
double maxScrollExtent2 = _scrollController2.position.maxScrollExtent;
double minScrollExtent3 = _scrollController3.position.minScrollExtent;
double maxScrollExtent3 = _scrollController3.position.maxScrollExtent;
//
animateToMaxMin(maxScrollExtent1, minScrollExtent1, maxScrollExtent1, 1,
_scrollController1);
animateToMaxMin(maxScrollExtent2, minScrollExtent2, maxScrollExtent2, 15,
_scrollController2);
animateToMaxMin(maxScrollExtent3, minScrollExtent3, maxScrollExtent3, 20,
_scrollController3);
});
}
animateToMaxMin(double max, double min, double direction, int seconds,
ScrollController scrollController) {
scrollController
.animateTo(direction,
duration: Duration(seconds: seconds), curve: Curves.linear)
.then((value) {
direction = direction == max ? min : max;
animateToMaxMin(max, min, direction, seconds, scrollController);
});
}
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
backgroundColor: Colors.white,
body: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Column(
children: [
MoviesListView(
scrollController: _scrollController1,
images: movies1,
),
MoviesListView(
scrollController: _scrollController2,
images: movies2,
),
MoviesListView(
scrollController: _scrollController3,
images: movies3,
),
],
),
Text(
'30 days for free',
style: TextStyle(
fontSize: 35,
fontWeight: FontWeight.bold,
),
),
Material(
elevation: 0,
color: Color(0xfff2c94c),
borderRadius: BorderRadius.circular(20),
child: MaterialButton(
onPressed: () {},
minWidth: 340,
height: 60,
child: Text(
'Continue',
style: TextStyle(
color: Colors.white,
fontSize: 25,
fontWeight: FontWeight.bold,
),
),
),
)
],
),
),
);
}
}
Gesture Detector is not working when i apply animation on List view Builder it didn't let the Gesture Detector work how can I resolve this issue
import 'package:flutter/material.dart';
class MoviesListView extends StatelessWidget {
final ScrollController scrollController;
final List images;
const MoviesListView({Key key, this.scrollController, this.images})
: super(key: key);
#override
Widget build(BuildContext context) {
return Container(
height: 120,
child: ListView.builder(
controller: scrollController,
scrollDirection: Axis.horizontal,
shrinkWrap: true,
itemCount: images.length,
itemBuilder: (context, index) {
return Container(
margin: EdgeInsets.all(10),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(25),
),
child: GestureDetector(
onTap: (){
print('Func Called');
},
child: ClipRRect(
borderRadius: BorderRadius.circular(25),
child: Image.asset(
'assets/${images[index]}',
width: 150,
fit: BoxFit.cover,
),
),
),
);
}),
);
}
}
Without Animation Gesture detector working perfectly
Try wrapping outer Container with GestureDetector()
return GestureDetector(
onTap: () {
print('Func Called');
},
child: Container(
margin: EdgeInsets.all(10),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(25),
),
child: ClipRRect(
borderRadius: BorderRadius.circular(25),
child: Image.asset(
'assets/${images[index]}',
width: 150,
fit: BoxFit.cover,
),
),
),
);
I am using AnimationController.animateTo method to jump my animation to specific points instantly.
When I pass parameter 'target' with a value of 0.0 to animateTo method, the resulting 'value' property of AnimationController is 0.0. If I pass a parameter 'target' to animateTo method with a value of 0.5, the resulting 'value' property of AnimationController still returns 0.0. I would expect the 'value' property to return 0.5.
void _onPlayButtonPressed() {
final cpm = ScopedModel.of<CpModel>(context);
if (cpm.started) {
cpm.stop();
_animController.stop();
var targetProgress = cpm.adjustedProgress;
_animController.animateTo(targetProgress , duration: Duration(seconds: 0));
} else {
_ranOnce = true;
cpm.start();
_animController.forward();
}
}
I got late to answer that but will be helpful for other developers.
Add your animation controller onto the Animation object and use that animation object.
Like this:
The following example shows how you can use AnimationController's toAnimate method:
class Example extends StatefulWidget {
const Example({Key? key}) : super(key: key);
#override[![demo][1]][1]
State<Example> createState() => _ExampleState();
}
class _ExampleState extends State<Example> with TickerProviderStateMixin {
late Animation<double> slideAnimation;
late AnimationController sliderAnimationController;
#override
void initState() {
sliderAnimationController = AnimationController(
vsync: this, duration: const Duration(milliseconds: 1000));
slideAnimation = Tween<double>(begin:0, end: 130).animate(CurvedAnimation(
parent: sliderAnimationController, curve: Curves.ease));
print( sliderAnimationController.value);
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(body: SizedBox(width: 130,height: 160,child: IntrinsicHeight(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 10),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
InkWell(
onTap: () {
sliderAnimationController.animateTo(0.0);
},
child: Padding(
padding: const EdgeInsets.all(6.0),
child: Text(
"Text1",
style: Theme.of(context)
.textTheme
.bodyText1!
.copyWith(
color: Colors.black,
fontWeight: FontWeight.w600),
),
),
),
12.verticalSpace,
InkWell(
onTap: () {
// sliderAnimationController.forward();
sliderAnimationController.animateTo(0.215);
},
child: Padding(
padding: const EdgeInsets.all(6.0),
child: Text(
"Text2",
style: Theme.of(context)
.textTheme
.subtitle1!
.copyWith(color: Colors.black),
),
),
),
12.verticalSpace,
InkWell(
onTap: () {
sliderAnimationController.animateTo(0.405);
}
,
child: Padding(
padding: const EdgeInsets.all(6.0),
child: Text(
"Text3",
style: Theme.of(context)
.textTheme
.subtitle1!
.copyWith(color: Colors.black),
),
),
),
12.verticalSpace,
InkWell(
onTap: () {
sliderAnimationController.animateTo(1.0);
},
child: Padding(
padding: const EdgeInsets.all(6.0),
child: Text(
"Text4",
style: Theme.of(context)
.textTheme
.subtitle1!
.copyWith(color: Colors.black),
),
),
)
],
),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 10),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
AnimatedBuilder(
animation: sliderAnimationController,
builder: (BuildContext context, Widget? child) {
return Transform.translate(offset: Offset(0, slideAnimation.value),
child: child);
},
child: Container(
width: 3,
height: 26,
color: Colors.blue,
),
),
Container(
width: 1,
color: Colors.black54,
)
],
),
),
],
),
),
),));
}
#override
void dispose() {
sliderAnimationController.dispose();
super.dispose();
}
}
How can I change my standard Switch
to this gradient switch
Also how to increase the size of switch?
Please help.
Code:-
Switch(
activeColor: Colors.lightBlueAccent,
inactiveThumbColor: Colors.grey,
value: _switchValueRead,
onChanged: (value) {
setState(() {
_switchValueRead = value;
});
},
),
You can do it by this from this thread
library custom_switch;
import 'package:flutter/material.dart';
class CustomSwitch extends StatefulWidget {
final bool value;
final ValueChanged<bool> onChanged;
final Color activeColor;
final Color inactiveColor;
final String activeText;
final String inactiveText;
final Color activeTextColor;
final Color inactiveTextColor;
const CustomSwitch(
{Key key,
this.value,
this.onChanged,
this.activeColor,
this.inactiveColor = Colors.grey,
this.activeText = '',
this.inactiveText = '',
this.activeTextColor = Colors.white70,
this.inactiveTextColor = Colors.white70})
: super(key: key);
#override
_CustomSwitchState createState() => _CustomSwitchState();
}
class _CustomSwitchState extends State<CustomSwitch>
with SingleTickerProviderStateMixin {
Animation _circleAnimation;
AnimationController _animationController;
#override
void initState() {
super.initState();
_animationController =
AnimationController(vsync: this, duration: Duration(milliseconds: 60));
_circleAnimation = AlignmentTween(
begin: widget.value ? Alignment.centerRight : Alignment.centerLeft,
end: widget.value ? Alignment.centerLeft : Alignment.centerRight)
.animate(CurvedAnimation(
parent: _animationController, curve: Curves.linear));
}
#override
Widget build(BuildContext context) {
return AnimatedBuilder(
animation: _animationController,
builder: (context, child) {
return GestureDetector(
onTap: () {
if (_animationController.isCompleted) {
_animationController.reverse();
} else {
_animationController.forward();
}
widget.value == false
? widget.onChanged(true)
: widget.onChanged(false);
},
child: Container(
width: 70.0,
height: 35.0,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20.0),
// I commented here.
// color: _circleAnimation.value == Alignment.centerLeft
// ? widget.inactiveColor
// : widget.activeColor,
gradient: LinearGradient(
begin: Alignment.topRight,
end: Alignment.bottomLeft,
// You can set your own colors in here!
colors: [
Colors.blue,
Colors.red,
],
),
),
child: Padding(
padding: const EdgeInsets.only(
top: 4.0, bottom: 4.0, right: 4.0, left: 4.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
_circleAnimation.value == Alignment.centerRight
? Padding(
padding: const EdgeInsets.only(left: 34.0, right: 0),
child: Text(
widget.activeText,
style: TextStyle(
color: widget.activeTextColor,
fontWeight: FontWeight.w900,
fontSize: 16.0),
),
)
: Container(),
Align(
alignment: _circleAnimation.value,
child: Container(
width: 25.0,
height: 25.0,
decoration: BoxDecoration(
shape: BoxShape.circle, color: Colors.white),
),
),
_circleAnimation.value == Alignment.centerLeft
? Padding(
padding: const EdgeInsets.only(left: 0, right: 34.0),
child: Text(
widget.inactiveText,
style: TextStyle(
color: widget.inactiveTextColor,
fontWeight: FontWeight.w900,
fontSize: 16.0),
),
)
: Container(),
],
),
),
),
);
},
);
}
}
Check this for gradient
For increasing the size - wrap your Switch into Container (or SizedBox) and set width and height to Container(SizedBox). It should help.
Is there any way to generate this switch with the Switch widget?
Thank you
You can use custom_switch package. I changed it for linearGradient.
library custom_switch;
import 'package:flutter/material.dart';
class CustomSwitch extends StatefulWidget {
final bool value;
final ValueChanged<bool> onChanged;
final Color activeColor;
final Color inactiveColor;
final String activeText;
final String inactiveText;
final Color activeTextColor;
final Color inactiveTextColor;
const CustomSwitch(
{Key key,
this.value,
this.onChanged,
this.activeColor,
this.inactiveColor = Colors.grey,
this.activeText = '',
this.inactiveText = '',
this.activeTextColor = Colors.white70,
this.inactiveTextColor = Colors.white70})
: super(key: key);
#override
_CustomSwitchState createState() => _CustomSwitchState();
}
class _CustomSwitchState extends State<CustomSwitch>
with SingleTickerProviderStateMixin {
Animation _circleAnimation;
AnimationController _animationController;
#override
void initState() {
super.initState();
_animationController =
AnimationController(vsync: this, duration: Duration(milliseconds: 60));
_circleAnimation = AlignmentTween(
begin: widget.value ? Alignment.centerRight : Alignment.centerLeft,
end: widget.value ? Alignment.centerLeft : Alignment.centerRight)
.animate(CurvedAnimation(
parent: _animationController, curve: Curves.linear));
}
#override
Widget build(BuildContext context) {
return AnimatedBuilder(
animation: _animationController,
builder: (context, child) {
return GestureDetector(
onTap: () {
if (_animationController.isCompleted) {
_animationController.reverse();
} else {
_animationController.forward();
}
widget.value == false
? widget.onChanged(true)
: widget.onChanged(false);
},
child: Container(
width: 70.0,
height: 35.0,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20.0),
// I commented here.
// color: _circleAnimation.value == Alignment.centerLeft
// ? widget.inactiveColor
// : widget.activeColor,
gradient: LinearGradient(
begin: Alignment.topRight,
end: Alignment.bottomLeft,
// You can set your own colors in here!
colors: [
Colors.blue,
Colors.red,
],
),
),
child: Padding(
padding: const EdgeInsets.only(
top: 4.0, bottom: 4.0, right: 4.0, left: 4.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
_circleAnimation.value == Alignment.centerRight
? Padding(
padding: const EdgeInsets.only(left: 34.0, right: 0),
child: Text(
widget.activeText,
style: TextStyle(
color: widget.activeTextColor,
fontWeight: FontWeight.w900,
fontSize: 16.0),
),
)
: Container(),
Align(
alignment: _circleAnimation.value,
child: Container(
width: 25.0,
height: 25.0,
decoration: BoxDecoration(
shape: BoxShape.circle, color: Colors.white),
),
),
_circleAnimation.value == Alignment.centerLeft
? Padding(
padding: const EdgeInsets.only(left: 0, right: 34.0),
child: Text(
widget.inactiveText,
style: TextStyle(
color: widget.inactiveTextColor,
fontWeight: FontWeight.w900,
fontSize: 16.0),
),
)
: Container(),
],
),
),
),
);
},
);
}
}
Here is main.dart:
import 'package:custom_switch/custom_switch.dart';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.deepOrange
),
home: HomeScreen(),
);
}
}
class HomeScreen extends StatefulWidget {
#override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
bool status = false;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Custom Switch Example'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
CustomSwitch(
activeColor: Colors.pinkAccent,
value: status,
onChanged: (value) {
print("VALUE : $value");
setState(() {
status = value;
});
},
),
SizedBox(height: 12.0,),
Text('Value : $status', style: TextStyle(
color: Colors.black,
fontSize: 20.0
),)
],
),
),
);
}
}
I'm beginner in flutter. trying to design login page. when user clicks on 'ok' button then 'ok' button gets invisible and 'approved' named button gets visible using some animation. problem is that 'ok' displayed in inverted form as shown in pic. how dI correct this issue?
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
// TODO: implement build
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Animation class',
home: HomePage(),
);
}
}
class HomePage extends StatefulWidget {
#override
State<StatefulWidget> createState() => stateClass();
}
class stateClass extends State<HomePage> with SingleTickerProviderStateMixin {
AnimationController animationController;
Animation<double> animation;
Animation<double> sizeAnimation;
int currentState = 0;
#override
void initState() {
super.initState();
animationController = AnimationController(
duration: Duration(milliseconds: 1000), vsync: this);
animation = Tween<double>(begin: 0, end: 60).animate(animationController)
..addListener(() {
setState(() {});
});
sizeAnimation = Tween<double>(begin: 0, end: 1).animate(CurvedAnimation(
parent: animationController, curve: Curves.fastOutSlowIn))
..addListener(() {
setState(() {});
});
}
#override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
appBar: AppBar(
title: Text('Animation login'),
),
body: Container(
child: SingleChildScrollView(
child: Column(
children: <Widget>[
Container(
height: 100,
//color: Colors.black,
child: Center(
child: Image.asset('assets/fluttericon.png'),
)),
Container(
margin: EdgeInsets.all(10),
padding: EdgeInsets.all(10),
child: TextFormField(
decoration: InputDecoration(
labelText: 'enter your email id',
),
),
),
Container(
margin: EdgeInsets.all(10),
padding: EdgeInsets.all(10),
child: TextFormField(
obscureText: true,
decoration: InputDecoration(
labelText: 'enter your password',
),
),
),
Container(
// color: Colors.teal,
// height: 0,
child: Center(
child: Transform.scale(
scale: sizeAnimation.value - 1,
child: FlatButton(
onPressed: animationController.forward,
color: Colors.redAccent[200],
child: Text(
'ok',
style: TextStyle(fontSize: 17, color: Colors.black),
),
),
)),
),
Container(
//color: Colors.teal,
height: 80,
child: Center(
child: Transform.scale(
scale: sizeAnimation.value,
child: FlatButton(
onPressed: animationController.reverse,
color: Colors.redAccent[200],
child: Text(
'approved',
style: TextStyle(fontSize: 17, color: Colors.black),
),
),
)),
),
],
),
)
)
);
}
}
Text container
Container(
// color: Colors.teal,
// height: 0,
child: Center(
child: Transform.scale(
scale: sizeAnimation.value-1 ,
child: FlatButton(
onPressed: animationController.forward,
color: Colors.redAccent[200],
child: Text(
'ok',
style: TextStyle(fontSize: 17, color: Colors.black),
),
),
)),
),
When I change sizeAnimation.value-1 to sizeAnimation. then 'ok' word is in erect form. but ok button is not invisible.
Screenshot preview
A possible solution for what you are trying to do is to use Fade and Rotate transitions with separate controllers for each Text widget. Here's an example of that:
class ButtonTextFadeRotation extends StatefulWidget {
#override
_ButtonTextFadeRotationState createState() => _ButtonTextFadeRotationState();
}
class _ButtonTextFadeRotationState extends State<ButtonTextFadeRotation> with TickerProviderStateMixin {
AnimationController _okAnimationController;
AnimationController _approvedAnimationController;
#override
void initState() {
_okAnimationController = AnimationController(
vsync: this,
duration: Duration(milliseconds: 200),
value: 1
);
_approvedAnimationController = AnimationController(
vsync: this,
duration: Duration(milliseconds: 200),
value: 0
);
super.initState();
}
#override
Widget build(BuildContext context) {
return Center(
child: ClipRect(
child: RaisedButton(
onPressed: () {
_okAnimationController.reverse();
_approvedAnimationController.forward();
},
child: Stack(
alignment: Alignment.center,
children: <Widget>[
FadeTransition(
opacity: _okAnimationController,
child: RotationTransition(
turns: _okAnimationController,
alignment: Alignment.center,
child: Text('Ok'),
),
),
FadeTransition(
opacity: _approvedAnimationController,
child: RotationTransition(
turns: _approvedAnimationController,
alignment: Alignment.center,
child: Text('Approved'),
),
),
],
),
),
),
);
}
}