flutter error: The method 'CustomTimerPainter' isn't defined for the class '_CountDownTimerState - flutter

This is what it shows in terminal
59:48: Error: The method 'CustomTimerPainter' isn't defined for the
class '_CountDownTimerState'.
'_CountDownTimerState' is from 'package:braintrinig/pages/Countdown_timer.dart'
('lib/pages/Countdown_timer.dart'). Try correcting the name to the
name of an existing method, or defining a method named
'CustomTimerPainter'.
painter: CustomTimerPainter(
How to solve this issue?
This is my code:
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
class CountDownTimer extends StatefulWidget {
#override
_CountDownTimerState createState() => _CountDownTimerState();
}
class _CountDownTimerState extends State<CountDownTimer>
with TickerProviderStateMixin {
late AnimationController controller;
String get timerString {
Duration duration = controller.duration! * controller.value;
return '${duration.inMinutes}:${(duration.inSeconds % 60).toString().padLeft(2, '0')}';
}
#override
void initState() {
super.initState();
controller = AnimationController(
vsync: this,
duration: Duration(seconds: 5),
);
}
#override
Widget build(BuildContext context) {
ThemeData themeData = Theme.of(context);
return Scaffold(
backgroundColor: Colors.white10,
body:
Container(
color: Colors.amber,
height: controller.value * MediaQuery.of(context).size.height,
child: AnimatedBuilder(
animation: controller,
builder: (context, child) {
return Stack(
children: <Widget>[
Align(
alignment: Alignment.bottomCenter,
child: Container(
color: Colors.amber,
height:
controller.value * MediaQuery.of(context).size.height,
),
),
Padding(
padding: EdgeInsets.all(8.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Expanded(
child: Align(
alignment: FractionalOffset.center,
child: AspectRatio(
aspectRatio: 1.0,
child: Stack(
children: <Widget>[
Positioned.fill(
child: CustomPaint(
painter: CustomTimerPainter(
animation: controller,
backgroundColor: Colors.white,
color: themeData.indicatorColor,
)),
),
Align(
alignment: FractionalOffset.center,
child: Column(
mainAxisAlignment:
MainAxisAlignment.spaceEvenly,
crossAxisAlignment:
CrossAxisAlignment.center,
children: <Widget>[
Text(
"Count Down Timer",
style: TextStyle(
fontSize: 20.0,
color: Colors.white),
),
Text(
timerString,
style: TextStyle(
fontSize: 112.0,
color: Colors.white),
),
],
),
),
],
),
),
),
),
AnimatedBuilder(
animation: controller,
builder: (context, child) {
return FloatingActionButton.extended(
onPressed: () {
if (controller.isAnimating)
controller.stop();
else {
controller.reverse(
from: controller.value == 0.0
? 1.0
: controller.value);
}
},
icon: Icon(controller.isAnimating
? Icons.pause
: Icons.play_arrow),
label: Text(
controller.isAnimating ? "Pause" : "Play"));
}),
],
),
),
],
);
}),
),
);
}
}

It checked that "CustomTimerPainter" is from circular_countdown_timer library.
After you add this library, the problem you mentioned will be resolved.
I pasted your code to my project and install "circular_countdown_timer", I didn't see any error right now.
circular_countdown_timer pub.dev
Add circular_countdown_timer in your pubspec.yaml => get => update.
dependencies:
circular_countdown_timer: ^0.2.2
Import this library into your dart file
import 'package:circular_countdown_timer/custom_timer_painter.dart';

The CustomeTimerPainter is a custom widget that someone has already written in your taken example,
You may please check those examples, or you can use the sample below.
class CustomTimerPainter extends CustomPainter {
CustomTimerPainter({
this.animation,
this.backgroundColor,
this.color,
}) : super(repaint: animation);
final Animation<double> animation;
final Color backgroundColor, color;
#override
void paint(Canvas canvas, Size size) {
Paint paint = Paint()
..color = backgroundColor
..strokeWidth = 10.0
..strokeCap = StrokeCap.butt
..style = PaintingStyle.stroke;
canvas.drawCircle(size.center(Offset.zero), size.width / 2.0, paint);
paint.color = color;
double progress = (1.0 - animation.value) * 2 * math.pi;
canvas.drawArc(Offset.zero & size, math.pi * 1.5, -progress, false, paint);
}
#override
bool shouldRepaint(CustomTimerPainter old) {
return animation.value != old.animation.value ||
color != old.color ||
backgroundColor != old.backgroundColor;
}
}

Related

Audio composing dashboard with flutter

I m trying to create the following view on my app, other area are done but now comes to the core feature of the app, which allows people to record the audio and stack other audio on top of the one that has been recorded, before going on the hard parts of recording and margin or trim the audios, I am stuck on the view, plz anyone who can shade a light on this will be appreciated. spare the bottom navigation bar, that one has no issue, only the timeline board.
here the view that I just prototyped.
Here some code that I've tried to play with but failed.
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
class Studio extends StatefulWidget {
const Studio({Key? key}) : super(key: key);
#override
_Studio createState() => _Studio();
}
class _Studio extends State<Studio> with SingleTickerProviderStateMixin {
late AnimationController _controller;
double _time = 0.0, _scale = 1.0;
int _minutes = 0;
int _seconds = 0;
#override
void initState() {
super.initState();
_controller =
AnimationController(vsync: this, duration: Duration(seconds: 60));
_controller.addListener(() {
setState(() {
_time = _controller.value;
_minutes = (_time * 60).floor();
_seconds = ((_time * 60) % 1 * 60).floor();
});
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Timeline'),
),
body: Column(
children: <Widget>[
Expanded(
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: 12,
itemBuilder: (context, index) {
return Container(
width: 50,
height: 50,
margin: EdgeInsets.all(8),
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(8),
),
child: Center(
child: Text('$index'),
),
);
},
),
),
Container(
padding: EdgeInsets.all(8),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('$_minutes'),
Text(':'),
Text('$_seconds'),
],
),
),
ElevatedButton(
onPressed: () {
if (_controller.isAnimating) {
_controller.stop();
} else {
_controller.forward();
}
},
child: Text(_controller.isAnimating ? 'Stop' : 'Start'),
),
],
),
);
}
void _onScaleStart(ScaleStartDetails details) {
print(details);
setState(() {
//_scale = details.focalPoint;
});
}
void _onScaleUpdate(ScaleUpdateDetails details) {
setState(() {
_scale = details.scale;
});
}
Widget _buildTimeline() {
return Container(
height: 40,
child: Row(
children: <Widget>[
_buildTimelineMinute(0),
_buildTimelineMinute(5),
_buildTimelineMinute(10),
],
),
);
}
Widget _buildTimelineHour(int hour) {
return Container(
width: 10,
color: Colors.green,
child: Center(
child: Text(
"$hour:00",
style: TextStyle(color: Colors.black, fontSize: 12),
),
),
);
}
Widget _buildTimelineMinute(int minute) {
return Container(
width: 10,
color: Colors.green,
child: Center(
child: Text(
"$minute",
style: TextStyle(color: Colors.black, fontSize: 12),
),
),
);
}
}
Thank you

How to navigate to another page if time is over and select automatically a feature from new page?

I have this design:
If time is over, I want to navigate to this page automatically
This is my code:
home_page_timer.dart
import 'package:braintrinig/animation/LongBreak.dart';
import 'package:braintrinig/animation/ShortBreak.dart';
import 'package:braintrinig/animation/StartPomodoro.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
class HomePageTimerUI extends StatelessWidget {
bool PomoRed = false;
bool ShortYellow = false;
bool LongBlue = false;
#override
Widget build(BuildContext context) {
return Container(
height: 600,
width: double.infinity,
child: DefaultTabController(
length: 3,
child: Scaffold(
bottomNavigationBar: BottomBar(),
appBar: AppBar(
elevation: 1.0,
backgroundColor: Colors.transparent,
bottom: PreferredSize(
preferredSize: Size.fromHeight(55),
child: Container(
color: Colors.transparent,
child: SafeArea(
child: Column(
children: <Widget>[
TabBar(
indicator: UnderlineTabIndicator(
borderSide: BorderSide(
color: Color(0xff3B3B3B), width: 4.0),
insets: EdgeInsets.fromLTRB(
12.0, 12.0, 12.0, 11.0)),
indicatorWeight: 15,
indicatorSize: TabBarIndicatorSize.label,
labelColor: Color(0xff3B3B3B),
labelStyle: TextStyle(
fontSize: 12,
letterSpacing: 1.3,
fontWeight: FontWeight.w500),
unselectedLabelColor: Color(0xffD7D7D7),
tabs: [
Tab(
text: "POMODORO",
icon: Icon(Icons.work_history, size: 40),
),
Tab(
text: "SHORT BREAK",
icon: Icon(Icons.ramen_dining, size: 40),
),
Tab(
text: "LONG BREAK",
icon: Icon(Icons.battery_charging_full_rounded,
size: 40),
),
])
],
),
),
),
),
),
body: TabBarView(
children: <Widget>[
Center(
child: StartPomodoro(),
),
Center(
child: ShortBreak(),
),
Center(
child: LongBreak()
),
],
))));
}
}
class BottomBar extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.fromLTRB(20, 20, 20, 20),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
FloatingActionButton.extended(
backgroundColor: Color(0xffF2F2F2),
onPressed: () {},
icon: Icon(Icons.settings,
color: Color(0xff3B3B3B),),
label: Text("Settings",
style: TextStyle(color: Color(0xff3B3B3B),
),)),
FloatingActionButton.extended(
backgroundColor: Color(0xffF2F2F2),
onPressed: () {},
icon: Icon(Icons.show_chart,
color: Color(0xff3B3B3B),),
label: Text("Performance",
style: TextStyle(color: Color(0xff3B3B3B),
),))
],
),
);
}
}
startpomodoro.dart
import 'dart:async';
import 'package:braintrinig/animation/home_page_timer_ui.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'dart:core';
import 'dart:math' as math;
import 'package:flutter_ringtone_player/flutter_ringtone_player.dart';
import 'ShortBreak.dart';
class StartPomodoro extends StatefulWidget {
const StartPomodoro({Key? key}) : super(key: key);
#override
State<StartPomodoro> createState() => _StartPomodoroState ();
}
class _StartPomodoroState extends State<StartPomodoro>
with TickerProviderStateMixin {
List<bool> isSelected = [true, false];
late Timer timer;
late AnimationController controller;
String get countText {
Duration count = controller.duration! * controller.value;
return controller.isDismissed
? '${controller.duration!.inHours.toString().padLeft(2, '0')}:${(controller.duration!.inMinutes % 60).toString().padLeft(2, '0')}:${(controller.duration!.inSeconds % 60).toString().padLeft(2, '0')}'
: '${count.inHours.toString().padLeft(2, '0')}:${(count.inMinutes % 60).toString().padLeft(2, '0')}:${(count.inSeconds % 60).toString().padLeft(2, '0')}';
}
double progress = 1.0;
bool LongBreak = true;
void notify() {
if (countText == '00:00:00') {
FlutterRingtonePlayer.playNotification();
}
}
#override
void initState() {
super.initState();
controller = AnimationController(
vsync: this,
duration: Duration(seconds: 0),
);
controller.addListener(() {
notify();
if (controller.isAnimating) {
setState(() {
progress = controller.value;
});
} else {
setState(() {
progress = 1.0;
LongBreak = true;
});
}
});
}
#override
void dispose() {
controller.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
ThemeData themeData = Theme.of(context);
return Scaffold(
backgroundColor: LongBreak? Color(0xffD94530) : Color(0xff6351c5),
body: GestureDetector(
onTap: () {
if (controller.isDismissed) {
showModalBottomSheet(
context: context,
builder: (context) => Container(
height:300,
child: CupertinoTimerPicker(
initialTimerDuration: controller.duration!,
onTimerDurationChanged: (time) {
setState(() {
controller.duration = time;
});
},
),
),
);
}
},
child: AnimatedBuilder(
animation: controller,
builder: (context, child) {
return Stack(
children: <Widget>[
Align(
alignment: Alignment.bottomCenter,
child: Container(
color: Color(0xffD94530),
height:
controller.value * MediaQuery.of(context).size.height * 0.742,
),
),
Padding(
padding: EdgeInsets.all(8.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Expanded(
child: Align(
alignment: Alignment.bottomCenter,
child:
Align(
alignment: FractionalOffset.bottomCenter,
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Text(
countText,
style: TextStyle(
fontSize: 90.0,
color: Color(0xffF2F2F2),),
),
],
),
),
),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
AnimatedBuilder(
animation: controller,
builder: (context, child) {
return Padding(
padding: EdgeInsets.symmetric(vertical: 2.0, horizontal: 15.0),
);
}),
AnimatedBuilder(
animation: controller,
builder: (context, child) {
return Padding(
padding: EdgeInsets.symmetric(vertical: 2.0, horizontal: 15.0),
child: FloatingActionButton.extended(
backgroundColor: Color(0xffF2F2F2),
onPressed:() {
if (controller.isAnimating) {
controller.stop();
setState(() {
LongBreak = false;
});
} else {
controller.reverse(
from: controller.value == 0 ? 1.0 : controller.value);
setState(() {
LongBreak = false;
});
}
},
icon: Icon(
controller.isAnimating ?
Icons.pause : Icons.play_arrow,
color: Color(0xff3B3B3B),),
label: Text(
controller.isAnimating ? "PAUSE" : "PLAY",
style: TextStyle(color: Color(0xff3B3B3B)),)),
);
}),
SizedBox(width: 20,),
],
),
],
),
),
],
);
}),
),
);
}
}
class CustomTimerPainter extends CustomPainter {
CustomTimerPainter({
required this.animation,
required this.backgroundColor,
required this.color,
}) : super(repaint: animation);
final Animation<double> animation;
final Color backgroundColor, color;
#override
void paint(Canvas canvas, Size size) {
Paint paint = Paint()
..color = backgroundColor
..strokeWidth = 10.0
..strokeCap = StrokeCap.butt
..style = PaintingStyle.stroke;
canvas.drawCircle(size.center(Offset.zero), size.width / 2.0, paint);
paint.color = color;
double progress = (1.0 - animation.value) * 2 * math.pi;
canvas.drawArc(Offset.zero & size, math.pi * 1.5, -progress, false, paint);
}
#override
bool shouldRepaint( CustomTimerPainter old) {
return animation.value != old.animation.value ||
color != old.color ||
backgroundColor != old.backgroundColor;
}
}
shortbreak.dart
import 'dart:async';
import 'package:braintrinig/animation/StartPomodoro.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'dart:core';
import 'dart:math' as math;
import 'package:flutter_ringtone_player/flutter_ringtone_player.dart';
class ShortBreak extends StatefulWidget {
const ShortBreak({Key? key}) : super(key: key);
#override
State<ShortBreak> createState() => _ShortBreakState ();
}
class _ShortBreakState extends State<ShortBreak>
with TickerProviderStateMixin {
List<bool> isSelected = [true, false];
late Timer timer;
late AnimationController controller;
String get countText {
Duration count = controller.duration! * controller.value;
return controller.isDismissed
? '${controller.duration!.inHours.toString().padLeft(2, '0')}:${(controller.duration!.inMinutes % 60).toString().padLeft(2, '0')}:${(controller.duration!.inSeconds % 60).toString().padLeft(2, '0')}'
: '${count.inHours.toString().padLeft(2, '0')}:${(count.inMinutes % 60).toString().padLeft(2, '0')}:${(count.inSeconds % 60).toString().padLeft(2, '0')}';
}
double progress = 1.0;
bool LongBreak = true;
void notify() {
if (countText == '00:00:00') {
FlutterRingtonePlayer.playNotification();
}
}
#override
void initState() {
super.initState();
controller = AnimationController(
vsync: this,
duration: Duration(seconds: 0),
);
controller.addListener(() {
notify();
if (controller.isAnimating) {
setState(() {
progress = controller.value;
});
} else {
setState(() {
progress = 1.0;
LongBreak = true;
});
}
});
}
#override
void dispose() {
controller.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
ThemeData themeData = Theme.of(context);
return Scaffold(
backgroundColor: LongBreak? Color(0xff6351c5) : Color(0xffD94530),
body: GestureDetector(
onTap: () {
if (controller.isDismissed) {
showModalBottomSheet(
context: context,
builder: (context) => Container(
height:300,
child: CupertinoTimerPicker(
initialTimerDuration: controller.duration!,
onTimerDurationChanged: (time) {
setState(() {
controller.duration = time;
});
},
),
),
);
}
},
child: AnimatedBuilder(
animation: controller,
builder: (context, child) {
return Stack(
children: <Widget>[
Align(
alignment: Alignment.bottomCenter,
child: Container(
color: Color(0xff6351c5),
height:
controller.value * MediaQuery.of(context).size.height * 0.742,
),
),
Padding(
padding: EdgeInsets.all(8.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Expanded(
child: Align(
alignment: Alignment.bottomCenter,
child:
Align(
alignment: FractionalOffset.bottomCenter,
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Text(
countText,
style: TextStyle(
fontSize: 90.0,
color: Color(0xffF2F2F2),),
),
],
),
),
),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
AnimatedBuilder(
animation: controller,
builder: (context, child) {
return Padding(
padding: EdgeInsets.symmetric(vertical: 2.0, horizontal: 15.0),
);
}),
AnimatedBuilder(
animation: controller,
builder: (context, child) {
return Padding(
padding: EdgeInsets.symmetric(vertical: 2.0, horizontal: 15.0),
child: FloatingActionButton.extended(
backgroundColor: Color(0xffF2F2F2),
onPressed:() {
if (controller.isAnimating) {
controller.stop();
setState(() {
LongBreak = false;
});
} else {
controller.reverse(
from: controller.value == 0 ? 1.0 : controller.value);
setState(() {
LongBreak = false;
});
}
},
icon: Icon(
controller.isAnimating ?
Icons.pause : Icons.play_arrow,
color: Color(0xff3B3B3B),),
label: Text(
controller.isAnimating ? "PAUSE" : "PLAY",
style: TextStyle(color: Color(0xff3B3B3B)),)),
);
}),
SizedBox(width: 20,),
],
),
],
),
),
],
);
}),
),
);
}
}
class CustomTimerPainter extends CustomPainter {
CustomTimerPainter({
required this.animation,
required this.backgroundColor,
required this.color,
}) : super(repaint: animation);
final Animation<double> animation;
final Color backgroundColor, color;
#override
void paint(Canvas canvas, Size size) {
Paint paint = Paint()
..color = backgroundColor
..strokeWidth = 10.0
..strokeCap = StrokeCap.butt
..style = PaintingStyle.stroke;
canvas.drawCircle(size.center(Offset.zero), size.width / 2.0, paint);
paint.color = color;
double progress = (1.0 - animation.value) * 2 * math.pi;
canvas.drawArc(Offset.zero & size, math.pi * 1.5, -progress, false, paint);
}
#override
bool shouldRepaint( CustomTimerPainter old) {
return animation.value != old.animation.value ||
color != old.color ||
backgroundColor != old.backgroundColor;
}
}
How to be able to navigate to shortbreak.dart without losing the design? I mean the appbar on top and bottom.
I tried this:
void notify() {
if (countText == '00:00:00') {
FlutterRingtonePlayer.playNotification();
Navigator.pushReplacement(context, MaterialPageRoute(builder: (context)=>
StartShortBreak()));
});
}
}
But, unfortunately, the appbars to the top and bottom don't show up.
How to solve this issue? Thank you in advance
you want to navigate between tab view , not between actual Navigator
first, change your homeui to stateful widget with SigleTickerMixin,
instead of using DefaultTabController, make one. :
late TabController _tabController;
#override
void initState() {
super.initState();
_tabController = TabController(length: 3, vsync: this);
}
#override
void dispose() {
_tabController.dispose();
super.dispose();
}
and assign that tabcontroller to tabview and tabbar :
TabBar(
controller: _tabController,
TabBarView(
controller: _tabController,
use this
void notify() {
if (countText == '00:00:00') {
FlutterRingtonePlayer.playNotification();
//REMOVE THIS NAVIGATOR
Navigator.pushReplacement(context, MaterialPageRoute(builder: (context)=>
StartShortBreak()));
});
//Change to this :
_tabController.animateTo(1, duration: const Duration(milliseconds: 300));
}
}
why index is 1, because you put ShortBreak in number 2 on your tabview childreen
In home page. Dart create a tab controller and assign it to the tab bar view. Then create a method to change index
void chageIndex(int index)
{
_tabController.animateTo(index);
}
Then pass this method to promo screen
class StartPomodoro extends StatefulWidget {
final Function (index) changeIndex;
const StartPomodoro({Key? key, required this.changeIndex}) : super(key: key);
#override
State<StartPomodoro> createState() => _StartPomodoroState ();
}
You have to pass it like this
body: TabBarView(
children: <Widget>[
Center(
child: StartPomodoro(changeIndex : changeIndex),
),
Center(
child: ShortBreak(),
),
Center(
child: LongBreak()
),
],
Then in startpromodoro in place of navigator. Push you can use
widget.changeIndex(1);
Inside your condition put this when start the timer or whatever you want to do:
Future.delayed(const Duration(milliseconds: 500), () {
Navigator.pop(context);
});

How to change opacity of text and angle of icon while using slider button in flutter

I want that as I move my slider button towards right, the opacity of text decreases and arrow icon rotates exactly oppposite, i.e. it strts rotating and at last last it should point backwards. I want to use opacity and Transform.rotate widgets, but how do I keep updating the value of dx ,so I can divide it with total width of container and use the fraction for calculation.
If there is another way, please do tell me.
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:passenger_flutter_app/utils/colors.dart';
import 'package:passenger_flutter_app/widgets/custom_sliding_button.dart';
class CommonSwipeButton extends StatelessWidget {
final String? buttonText1;
final String buttonText2;
final VoidCallback buttonCallBack2;
final bool isInfo;
final VoidCallback? buttonCallBack1;
final Widget itemWidget;
CommonSwipeButton(
{this.buttonCallBack1,
required this.buttonCallBack2,
this.isInfo = false,
this.buttonText1,
required this.buttonText2,
required this.itemWidget});
#override
Widget build(BuildContext context) {
return Container(
child: Column(
//crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Padding(padding: const EdgeInsets.only(left: 16.0, right: 16.0, bottom: 16.0, top: 16), child: itemWidget),
Padding(
padding:
const EdgeInsets.only(bottom: 16.0, left: 16.0, right: 16.0),
child: Align(
alignment: Alignment.center,
child: SizedBox(
width: MediaQuery.of(context).size.width,
height: 44,
child: CustomSlidingButton(
//text: buttonText2,
),
),
),
)
],
),
);
}
}
/*
class SwipeButton extends StatefulWidget {
final ValueChanged<double>? valueChanged;
final String? text;
final Function? callBack;
SwipeButton({this.valueChanged, this.text, this.callBack});
#override
SwipeButtonState createState() {
return new SwipeButtonState();
}
}
class SwipeButtonState extends State<SwipeButton> {
ValueNotifier<double> valueListener = ValueNotifier(.0);
GlobalKey swipeKey = GlobalKey();
ValueNotifier<double> x=ValueNotifier<double>(0);
ValueNotifier<bool> isVisible = ValueNotifier<bool>(true);
#override
void initState() {
valueListener.addListener(notifyParent);
super.initState();
}
void notifyParent() {
if (widget.valueChanged != null) {
widget.valueChanged!(valueListener.value);
}
}
void getPos(double totalSize) {
RenderBox box = swipeKey.currentContext?.findRenderObject() as RenderBox;
Offset position = box.localToGlobal(Offset.zero); //this is global position
x.value = position.dx;
print(x);
if(x.value>355) {
print("Reached");
isVisible.value=false;
}
}
#override
Widget build(BuildContext context) {
return Container(
color: colorPrimary,
height: 40.0,
padding: EdgeInsets.symmetric(horizontal: 10.0),
child: Stack(
children: [
Center(
child: Padding(
padding: const EdgeInsets.only(left: 10.0),
child: Text(
"${widget.text}",
style: TextStyle(
color: Colors.white,
fontSize: 17,
),
),
),
),
Builder(
builder: (context) {
final handle = GestureDetector(
onHorizontalDragUpdate: (details) {
valueListener.value = (valueListener.value +
details.delta.dx / context.size!.width)
.clamp(.0, 1.0);
getPos(context.size!.width-5);
print(context.size?.width);
},
child: ValueListenableBuilder(
valueListenable: isVisible,
builder: (BuildContext context, bool val, Widget? child) {
return Container(
key: swipeKey,
height: 25.0,
width: 25.0,
color: val ? Colors.white : colorPrimary,
child: Center(
child: ValueListenableBuilder(
valueListenable: x,
builder: (BuildContext context, double d, Widget? child) {
return Transform.rotate(
angle: -pi*(d/350),
child: Icon(
Icons.arrow_forward,
color: Colors.orange,
size: 12,
),
);
},
),
),
);
},
),
);
return AnimatedBuilder(
animation: valueListener,
builder: (context, child) {
return Align(
alignment: Alignment(valueListener.value * 2 - 1, 0),
child: child,
);
},
child: handle,
);
},
),
],
),
);
}
}*/
You can use Slider widget from Flutter framework and update a local variable in the onChange function:
Slider(
value: _currentSliderValue,
max: 100, //or any max value you need
onChanged: (double value) {
setState(() {
_value = value;
});
},
);
And the _value variable you will use in Opacity and Transform widgets.

Flutter resolve multiple heroes that share the same tag within a subtree

In my simple part of mobile application i used Hero without any problem and that works fine, now when i try to add a class as Widget which named AnimatedFab in part of this class i get this error:
There are multiple heroes that share the same tag within a subtree.
i don't use any Hero in this class and i'm wondering why i get the error
i used Hero in Stack and implementation code is:
Positioned(
top: 259.0,
left: 6.0,
child: SizedBox(
key: _imageKey,
width: 43.0,
height: 43.0,
child: InkWell(onTap: () {
//...
},child: MyHero(hiveFeed: widget.hiveFeeds)),
)),
and in parent of Stack which above code is one child of that, i have this code:
Positioned(top: 140.0, right: -40.0, child: const AnimatedFab().pl(8.0)),
full Stack children:
return Stack(
children: [
Card(
child: Stack(
children: [
Positioned(top: 140.0, right: -40.0, child: const AnimatedFab().pl(8.0)),
],
),
),
Positioned(
top: 259.0,
left: 6.0,
child: SizedBox(
key: _imageKey,
width: 43.0,
height: 43.0,
child: InkWell(onTap: () {
//...
},child: MyHero(hiveFeed: widget.hiveFeeds)),
)),
],
);
UPDATED
i consider heroTag as a value into below class:
AnimatedFab class which i have problem with that is below code:
Positioned(top: 140.0, right: -40.0, child: AnimatedFab(key:_imageKey).pl(8.0)),
class AnimatedFab extends StatefulWidget {
final VoidCallback onPressed;
final Key _key;
const AnimatedFab({Key key, this.onPressed}) : _key = key;
#override
_AnimatedFabState createState() => _AnimatedFabState();
}
class _AnimatedFabState extends State<AnimatedFab> with SingleTickerProviderStateMixin {
AnimationController _animationController;
Animation<Color> _colorAnimation;
final double expandedSize = 160.0;
final double hiddenSize = 50.0;
#override
void initState() {
super.initState();
_animationController = AnimationController(vsync: this, duration: const Duration(milliseconds: 200));
_colorAnimation = ColorTween(begin: Colors.transparent, end: Colors.pink[800]).animate(_animationController);
}
#override
void dispose() {
_animationController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return SizedBox(
width: expandedSize,
height: expandedSize,
child: AnimatedBuilder(
animation: _animationController,
builder: (BuildContext context, Widget child) {
return Stack(
alignment: Alignment.center,
children: <Widget>[
_buildFabCore(widget.key),
],
);
},
),
);
}
Widget _buildOption(IconData icon, double angle) {
if (_animationController.isDismissed) {
return Container();
}
double iconSize = 0.0;
if (_animationController.value > 0.8) {
iconSize = 26.0 * (_animationController.value - 0.8) * 5;
}
return Transform.rotate(
angle: angle,
child: Align(
alignment: Alignment.topCenter,
child: Padding(
padding: const EdgeInsets.only(top: 8.0),
child: IconButton(
onPressed: _onIconClick,
icon: Transform.rotate(
angle: -angle,
child: Icon(
icon,
color: Colors.black54,
),
),
iconSize: iconSize,
alignment: Alignment.center,
padding: const EdgeInsets.all(0.0),
),
),
),
);
}
Widget _buildExpandedBackground() {
final double size = hiddenSize + (expandedSize - hiddenSize) * _animationController.value;
return AnimatedOpacity(
opacity: _animationController.value,
duration: const Duration(milliseconds: 300),
child: Card(
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(100.0)),
elevation: 4.0,
child: Container(
height: size,
width: size,
),
),
);
}
Widget _buildFabCore(Key key) {
final double scaleFactor = 2 * (_animationController.value - 0.5).abs();
return FloatingActionButton(
key: key,
elevation: 0.0,
mini: true,
onPressed: _onFabTap,
backgroundColor: _colorAnimation.value,
child: Transform(
alignment: Alignment.center,
transform: Matrix4.identity()..scale(1.0, scaleFactor),
child: Icon(
_animationController.value > 0.5 ? Icons.close : Icons.filter_list,
color: _animationController.value > 0.5 ? Colors.white:Colors.black54,
size: 26.0,
),
),
);
}
void open() {
if (_animationController.isDismissed) {
_animationController.forward();
}
}
void close() {
if (_animationController.isCompleted) {
_animationController.reverse();
}
}
void _onFabTap() {
if (_animationController.isDismissed) {
open();
} else {
close();
}
}
void _onIconClick() {
widget.onPressed();
close();
}
}
how can i solve this issue? i think main problem is in _buildFabCore(),, method which i have this in this class.
thanks in advance
Consider passing a value to heroTag for the FloatingActionButton inside _buildFabCore or simply pass null.
This may happen if you have another FloatingActionButton is used within the app so if you didn't pass different heroTag for each one of them you will get this error.

Finish an animation before starting another - Flutter

I try to add a prestart to a countdown, both have different duration. So i maked two animation A and B,
when i press the start button the animation A start and when it's finished the animation B begin.
What happen to me now, is they starts at the same time, i tried Interval class and Tween class and it didn't works.
My code at this moment looks like this :
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class Timer2 extends StatefulWidget {
#override
_Timer2State createState() => _Timer2State();
}
class _Timer2State extends State<Timer2> with TickerProviderStateMixin {
AnimationController animationController;
#override
void initState() {
super.initState();
animationController = AnimationController(vsync: this,duration: Duration(seconds: 10));
}
#override
Widget build(BuildContext context) {
return Scaffold(backgroundColor: Colors.black,
body: Padding(
padding: EdgeInsets.all(8.0),
child: AnimatedBuilder(
animation: animationController,
builder: (context, child){
return Stack(
children: [
Align(
alignment: Alignment.bottomCenter,
child: Container(
color: Colors.red,
height:
animationController.value * MediaQuery.of(context).size.height,
),
),
Column(
children: <Widget>[
Expanded(
child: Align(
alignment: FractionalOffset.center,
child: AspectRatio(
aspectRatio: 1.0,
child: Stack(
children: <Widget>[
Positioned.fill(
child: AnimatedBuilder(
animation: animationController,
builder: (BuildContext context, Widget child) {
return CustomPaint(
painter: TimerPainter(
animation: animationController,
backgroundColor: Colors.white,
color: Colors.pink),
);
},
),
),
],
),
),
),
),
Container(
margin: EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
FloatingActionButton(
child: AnimatedBuilder(
animation: animationController,
builder: (_, Widget child) {
return Icon(
animationController.isAnimating
? Icons.pause
: Icons.play_arrow
);
}),
backgroundColor: Colors.pinkAccent,
onPressed: () {
if (animationController.isAnimating ) {
animationController.stop();
} else {
animationController.reverse(
from: animationController.value == 0.0
? 1.0
: animationController.value);
};
setState(() {
Icon(animationController.isAnimating
? Icons.play_arrow
: Icons.pause
);
});
},
)
],
),
)
],
),
],
);
},
),
),
);
}
}
class TimerPainter extends CustomPainter {
final Animation<double> animation;
final Color backgroundColor;
final Color color;
TimerPainter({this.animation, this.backgroundColor, this.color})
: super(repaint: animation);
#override
void paint(Canvas canvas, Size size) {
paint = Paint()
..color = backgroundColor
..strokeWidth = 5.0
..strokeCap = StrokeCap.round
..style = PaintingStyle.stroke;
canvas.drawCircle(size.center(Offset.zero), size.width / 2.0, paint);
paint.color = color;
double progress = (1.0 - animation.value) * 2 * 3.14;
canvas.drawArc(Offset.zero & size, 3.14 * 1.5, - progress, false, paint);
}
#override
bool shouldRepaint(TimerPainter old) {
return animation.value != old.animation.value ||
color != old.color ||
backgroundColor != old.backgroundColor;
}
}
Thank you