This is my problem:
I want to achieve this design:
How can I separate one to each other, first the homePageTimerUI and below the countDownTimer ?
This is my code: homePageTimerUI.dart
class HomePageTimerUI extends StatefulWidget {
const HomePageTimerUI({Key? key}) : super(key: key);
@override
State<HomePageTimerUI> createState() => _HomePageTimerUIState();
}
class _HomePageTimerUIState extends State<HomePageTimerUI> {
@override
Widget build(BuildContext context) {
return SizedBox(
height: double.maxFinite,
width: double.infinity,
child: DefaultTabController(
length: 3,
child: Scaffold(
appBar: AppBar(
elevation: 0,
backgroundColor: Colors.transparent,
bottom: PreferredSize(
preferredSize: const Size.fromHeight(40),
child: Container(
color: Colors.transparent,
child: SafeArea(
child: Column(
children: <Widget>[
TabBar(
indicator: const 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: const Color(0xff3B3B3B),
labelStyle: const TextStyle(
fontSize: 12,
letterSpacing: 1.3,
fontWeight: FontWeight.w500),
unselectedLabelColor: const Color(0xffD7D7D7),
tabs: const [
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: const <Widget>[
// Center(
// child: StartPomodoro(),
// ),
// Center(
// child: ShortBreak(),
// ),
// Center(child: LongBreak()),
],
),
),
),
);
}
}
countDownTimer.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: 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: Stack(
children: <Widget>[
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(
timerString,
style: TextStyle(
fontSize: 112.0,
color: Colors.white),
),
],
),
),
],
),
),
),
Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
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"));
}),
],
),
],
),
),
],
);
}),
);
}
}
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;
}
}
This is my own attempt to solve the issue, but didn't work
class StackedPages extends StatelessWidget {
const StackedPages({super.key});
@override
Widget build(BuildContext context) {
return Column(
children: [
HomePageTimerUI(),
CountDownTimer(),
],
);
}
}
How can achieve this design?
Thank you for any help you can offer
CodePudding user response:
Try wrap CountDownTimer
with Expanded
widget like this:
Column(
children: [
HomePageTimerUI(),
Expanded(child: CountDownTimer()),
],
)
CodePudding user response:
Are you asking for Stack() widget? You want to replace one for another? You could use AnimatedSwitcher().
AnimatedSwitcher(
duration: const Duration(seconds: 1), child: MyWidget());
Where MyWidget() is asigned to the widget you want to show via SetState(). The widgets are switched with a nice animation.
If you need to have one Widget placed one above the other in the vertical axis, you should try to remove the scaffold and the SizedBox with infity values.
CodePudding user response:
if this class can't stack.
Just using static
type.
add these codes at the same file with CountDownTimer
.
static const Widget countDownTimer = CountDownTimer();
...
// class CountDownTimer
Then, you must import this file and call this widget by this parameter. example
@override
Widget build(BuildContext context) {
return Column(
children: [
HomePageTimerUI(),
countDownTimer,
],
);
}
but you don't need to use StackPages
just put countDownTimer
in your pages.