skip to Main Content

This is my problem:

as you can see, the widgets are stacked

I want to achieve this design:

The app bar and timer are separated there, not stacked

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?

enter image description here

Thank you for any help you can offer

2

Answers


  1. 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.

    Login or Signup to reply.
  2. 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.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search