Home > Enterprise >  How can I center a container?
How can I center a container?

Time:01-01

This is my design for now:

enter image description here

I want to achive this design:

enter image description here

As you can see, the container starts at the top and want I want to do is center it like the second screenshot.

This is my code:

import 'dart:async';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:pomodoro/5.hourglass_animation/countdown_timer/responsive.dart';

class StartPomodoro extends StatefulWidget {
  const StartPomodoro({super.key, });

  //final DateTime end;

  @override
  State<StartPomodoro> createState() => _StartPomodoroState();
}

class _StartPomodoroState extends State<StartPomodoro>
    with TickerProviderStateMixin {
  final now = DateTime.now();

  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') {}
  }

  @override
  void initState() {
    super.initState();
    controller = AnimationController(
      vsync: this,
      duration: const 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 SafeArea(
      child: Scaffold(
        backgroundColor:
            LongBreak ? const Color(0xffD94530) : const 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: const Color(0xffD94530),
                        height: controller.value *
                            MediaQuery.of(context).size.height *
                            0.722,
                      ),
                    ),
                   Spacer(),
                    Padding(
                      padding: const EdgeInsets.all(8.0),
                      
                      child: Responsive(
                        
                        child: Column(
                          mainAxisAlignment: MainAxisAlignment.center,
                          crossAxisAlignment: CrossAxisAlignment.center,
                          children: <Widget>[
                            Align(
                              alignment: Alignment.bottomCenter,
                              child: Align(
                                alignment: FractionalOffset.bottomCenter,
                                child: Padding(
                                  padding: const EdgeInsets.symmetric(
                                      vertical: 2.0, horizontal: 15.0),
                                  child: Container(
                                    width: MediaQuery.of(context).size.width,
                                    height: 210,
                                    decoration:  BoxDecoration(
                                      borderRadius: BorderRadius.circular(20),
                                      color:
                                          const Color(0xffFAFAFA)
                                    ),
                                    child: Container(
                                      padding: const EdgeInsets.all(20.0),
                                      child: SingleChildScrollView(
                                        child: Column(
                                          mainAxisAlignment: MainAxisAlignment.center,
                                          crossAxisAlignment:
                                              CrossAxisAlignment.start,
                                          children: [
                                            const Text(
                                              "Hyper-focused on... ( add task)",
                                              style: TextStyle(
                                                fontSize: 22.0,
                                                fontWeight: FontWeight.w500,
                                              ),
                                            ),
                                            const SizedBox(height: 16),
                                            Center(
                                              child: SingleChildScrollView(
                                                child: Column(
                                                  mainAxisAlignment:
                                                      MainAxisAlignment.center,
                                                  children: [
                                                    Row(
                                                      mainAxisAlignment:
                                                          MainAxisAlignment
                                                              .center,
                                                      children: [
                                                        Text(
                                                          countText,
                                                          style: const TextStyle(
                                                            fontWeight:
                                                                FontWeight.w600,
                                                            letterSpacing: 4,
                                                            fontSize: 65.0,
                                                            color:
                                                                Color(0xff3B3B3B),
                                                          ),
                                                        ),
                                                      ],
                                                    ),
                                                    Row(
                                                      mainAxisAlignment:
                                                          MainAxisAlignment
                                                              .center,
                                                      children: const [
                                                        Text(
                                                          '    Hours      Minutes     Seconds    ',
                                                          style: TextStyle(
                                                            fontWeight:
                                                                FontWeight.w500,
                                                            letterSpacing: 2,
                                                            fontSize: 20.0,
                                                            color:
                                                                Color(0xff3B3B3B),
                                                          ),
                                                        ),
                                                      ],
                                                    ),
                                                  ],
                                                ),
                                              ),
                                            ),
                                          ],
                                        ),
                                      ),
                                    ),
                                  ),
                                ),
                              ),
                            ),
                            Spacer(),
                            Responsive( 
                              child: Column(
                                mainAxisAlignment: MainAxisAlignment.center,
                                crossAxisAlignment:
                                    CrossAxisAlignment.stretch,
                                children: [
                                  AnimatedBuilder(
                                      animation: controller,
                                      builder: (context, child) {
                                        return Padding(
                                          padding:
                                              const EdgeInsets.symmetric(
                                                  vertical: 2.0,
                                                  horizontal: 15.0),
                                          child:
                                              FloatingActionButton.extended(
                                                  backgroundColor:
                                                      const Color(
                                                          0xffFAFAFA),
                                                  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: const Color(
                                                        0xff3B3B3B),
                                                  ),
                                                  label: Text(
                                                    controller.isAnimating
                                                        ? "Pause"
                                                        : "Start",
                                                    style: const TextStyle(
                                                        color: Color(
                                                            0xff3B3B3B)),
                                                  )),
                                        );
                                      }),
                                 ],
                              ),
                            ),
                            SizedBox(height: 10,),
                          ],
                        ),
                      ),
                    ),
                  ],
                );
              }),
        ),
      ),
    );
  }

  AnimationController _buildClockAnimation(TickerProvider tickerProvider) {
    return AnimationController(
      vsync: tickerProvider,
      duration: const Duration(milliseconds: 750),
    );
  }

  void _animateLeftDigit(
    int prev,
    int current,
    AnimationController controller,
  ) {
    final prevFirstDigit = (prev / 10).floor();
    final currentFirstDigit = (current / 10).floor();
    if (prevFirstDigit != currentFirstDigit) {
      controller.forward();
    }
  }
}

For some reason, I'm unable to center the container, wrapped with the widget

center 

and no luck, how can I center the timer container?

Thank you for any help you can offer

CodePudding user response:

Its difficult to figure out the complete code because of lots of code and incorrect indentation. But as far as I can see, you are facing this problem because of using Spacer,

Spacer is pushing your floating button and the timer Container to its ends.

Try removing the Spacer and wrap the timer Container with Center and wrap it with Flexible this should solve your problem.

Your present code is roughly:

Column
|_ Timer Container
|_ Spacer
|_ Floating Button

Change it to:

Column
|_ Flexible
  |_ Center
    |_ Timer Container
|_ Floating Button

CodePudding user response:

If you like to use Stack widget, use positional widget like Aling, Positioned on Stack. Based on your UI, using stack widget structure will be

return Stack(
  children: <Widget>[
    background(context),
    Align(
      child: Padding(
        padding: const EdgeInsets.all(8.0),
        child: buildCounter(context),
      ),
    ),
    Align(
      alignment: Alignment.bottomCenter,
      child: startPauseButtonBuild(),
    ),
  ],
);

Here is the full snippet, I've removed some part for minimal and padding widget to handle some space

void main() => runApp(MaterialApp(home: const StartPomodoro()));

class StartPomodoro extends StatefulWidget {
  const StartPomodoro({
    super.key,
  });

  @override
  State<StartPomodoro> createState() => _StartPomodoroState();
}

class _StartPomodoroState extends State<StartPomodoro>
    with TickerProviderStateMixin {
  final now = DateTime.now();

  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') {}
  }

  @override
  void initState() {
    super.initState();
    controller = AnimationController(
      vsync: this,
      duration: const 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 SafeArea(
      child: Scaffold(
        backgroundColor:
            LongBreak ? const Color(0xffD94530) : const Color(0xff6351c5),
        body: GestureDetector(
          onTap: () {},
          child: AnimatedBuilder(
              animation: controller,
              builder: (context, child) {
                return Stack(
                  children: <Widget>[
                    background(context),
                    Align(
                      child: Padding(
                        padding: const EdgeInsets.all(8.0),
                        child: buildCounter(context),
                      ),
                    ),
                    Align(
                      alignment: Alignment.bottomCenter,
                      child: startPauseButtonBuild(),
                    ),
                  ],
                );
              }),
        ),
      ),
    );
  }

  Widget startPauseButtonBuild() {
    return LayoutBuilder(
      builder: (_, constraints) => Padding(
        padding: const EdgeInsets.all(8.0),
        child: AnimatedBuilder(
            animation: controller,
            builder: (context, child) {
              return Padding(
                padding:
                    const EdgeInsets.symmetric(vertical: 2.0, horizontal: 15.0),
                child: SizedBox(
                  width: constraints.maxWidth,
                  child: FloatingActionButton.extended(
                    backgroundColor: const Color(0xffFAFAFA),
                    onPressed: () {},
                    icon: Icon(
                      controller.isAnimating ? Icons.pause : Icons.play_arrow,
                      color: const Color(0xff3B3B3B),
                    ),
                    label: Text(
                      controller.isAnimating ? "Pause" : "Start",
                      style: const TextStyle(color: Color(0xff3B3B3B)),
                    ),
                  ),
                ),
              );
            }),
      ),
    );
  }

  Column buildCounter(BuildContext context) {
    return Column(
      mainAxisSize: MainAxisSize.min,
      children: <Widget>[
        Align(
          alignment: Alignment.bottomCenter,
          child: Container(
            width: MediaQuery.of(context).size.width,
            height: 210,
            decoration: BoxDecoration(
                borderRadius: BorderRadius.circular(20),
                color: const Color(0xffFAFAFA)),
            child: Container(
              padding: const EdgeInsets.all(20.0),
              child: SingleChildScrollView(
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    const Text(
                      "Hyper-focused on... ( add task)",
                      style: TextStyle(
                        fontSize: 22.0,
                        fontWeight: FontWeight.w500,
                      ),
                    ),
                    const SizedBox(height: 16),
                    Center(
                      child: SingleChildScrollView(
                        child: Column(
                          mainAxisAlignment: MainAxisAlignment.center,
                          children: [
                            Row(
                              mainAxisAlignment: MainAxisAlignment.center,
                              children: [
                                Text(
                                  countText,
                                  style: const TextStyle(
                                    fontWeight: FontWeight.w600,
                                    letterSpacing: 4,
                                    fontSize: 65.0,
                                    color: Color(0xff3B3B3B),
                                  ),
                                ),
                              ],
                            ),
                            Row(
                              mainAxisAlignment: MainAxisAlignment.center,
                              children: const [
                                Text(
                                  '    Hours      Minutes     Seconds    ',
                                  style: TextStyle(
                                    fontWeight: FontWeight.w500,
                                    letterSpacing: 2,
                                    fontSize: 20.0,
                                    color: Color(0xff3B3B3B),
                                  ),
                                ),
                              ],
                            ),
                          ],
                        ),
                      ),
                    ),
                  ],
                ),
              ),
            ),
          ),
        ),
      ],
    );
  }

  Align background(BuildContext context) {
    return Align(
      alignment: Alignment.bottomCenter,
      child: Container(
        color: const Color(0xffD94530),
        height: controller.value * MediaQuery.of(context).size.height * 0.722,
      ),
    );
  }

  AnimationController _buildClockAnimation(TickerProvider tickerProvider) {
    return AnimationController(
      vsync: tickerProvider,
      duration: const Duration(milliseconds: 750),
    );
  }

  void _animateLeftDigit(
    int prev,
    int current,
    AnimationController controller,
  ) {
    final prevFirstDigit = (prev / 10).floor();
    final currentFirstDigit = (current / 10).floor();
    if (prevFirstDigit != currentFirstDigit) {
      controller.forward();
    }
  }
}
  • Related