Old iron remember to forward, Brother Cat will present more Flutter good articles ~~~~

Wechat Flutter research group Ducafecat

The original

Evandrmb.medium.com/flutter-mod…

code

Github.com/evandrmb/bo…

reference

  • Material. IO/components /…

The body of the

According to the material design guide, the bottom table is a small tool for displaying additional content anchored at the bottom of the screen. While it would be nice to know the design rules for using this, that is not the goal of this article. For more detailed information on the principles of floor Design, see “Sheets: Bottom — Material Design”.

Now that you know BottomSheet, you might ask yourself: what is a ModalBottomSheet? How do we use them in Flutter?

Ok, first question, there are two types of underlying tables: modal and persistent. Persistence remains visible when the user interacts with the screen. Google Maps is one example.

On the other hand, stereotyped actions prevent users from doing other things in the application. You can use them to confirm certain actions, or to request additional data, such as asking the user how much interchange is required when ordering in an e-commerce application, and so on.

In this article, we’ll show how to use it by creating a simple weight tracking application where we can submit our weight and view our previous weight. Instead of entering the details of the application, we go directly to the ModalBottomSheet implementation.

To display it, you need to call showModalBottomSheet from the context with the Scaffold, otherwise you will get an error. In other words, let’s start building our table.

The first thing to know is that ModalBottomSheets defaults to half the height of the screen. In order to change this, you must pass true to the isScrollControlled parameter and return a widget that matches the size we expect, so let’s do that.

void addWeight() {
    showModalBottomSheet(
      isScrollControlled: true,
      context: context,
      builder: (context) {
        var date = DateTime.now();

		    return Container(
          height: 302,
          padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ ], ), ); }); }Copy the code

Now, we need to add something so that our users can enter their weights let’s add a TextInput and give it a TextEditingController (this way its value remains even if our worksheet is accidentally closed and the user opens it again).

void addWeight() {
    showModalBottomSheet(
      isScrollControlled: true,
      context: context,
      builder: (context) {
        var date = DateTime.now();

		    return Container(
          height: 302,
          padding: const EdgeInsets.all(16.0),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
				      padding: EdgeInsets.only(bottom: 24.0),
                child: Text(
                  'Register Weight',
                  style: Styles.titleStyle,
                ),
              ),
              TextField(
                controller: weightInputController,
                keyboardType: TextInputType.number,
                decoration: InputDecoration(
                  labelText: 'Weight (KG)', border: OutlineInputBorder( borderRadius: Styles.borderRadius, ), ), ), ], ), ); }); }Copy the code

It looks good, but now we have a problem. When the user clicks our TextField keyboard on it, why? Our worksheet doesn’t adjust its position when the keyboard is on, and we can make the worksheet bigger, but that doesn’t solve our problem because we still need to add a field where the user can enter the date they recorded the weight. So what’s the solution? This is simple, if we open the keyboard and let our worksheet on top of it, we can implement this, giving our container an edge margin. In viewinset.bottom, we get the following result:

It looks nice at first, but don’t you think it would be smoother if we added some radii to the paper? Let’s do this by adding shapeProperty as shown below.

showModalBottomSheet(
      isScrollControlled: true,
      context: context,
      shape: const RoundedRectangleBorder(
          borderRadius: BorderRadius.only(
            topLeft: Radius.circular(8),
            topRight: Radius.circular(8))),Copy the code

Cool, now let’s make our gadget to choose a date. Normally, you would create a widget to handle this logic and expose the selected values using the ValueChanged function, but to illustrate the problems you might face in the future, let’s create all the logic inside the worksheet itself.

void addWeight() {
    showModalBottomSheet(
      isScrollControlled: true,
      context: context,
      shape: const RoundedRectangleBorder(
          borderRadius: BorderRadius.only(
        topLeft: Radius.circular(8),
        topRight: Radius.circular(8),
      )),
      builder: (context) {
        return Container(
          height: 360,
          width: MediaQuery.of(context).size.width,
          margin:
              EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
          padding: const EdgeInsets.all(16.0),
          decoration: BoxDecoration(
            borderRadius: BorderRadius.circular(20),
          ),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              const Padding(
                padding: EdgeInsets.only(bottom: 24.0),
                child: Text(
                  'Register Weight',
                  style: Styles.titleStyle,
                ),
              ),
              TextField(
                controller: weightInputController,
                keyboardType: TextInputType.number,
                decoration: InputDecoration(
                  labelText: 'Weight (KG)',
                  border: OutlineInputBorder(
                    borderRadius: Styles.borderRadius,
                  ),
                ),
              ),
              Padding(
                padding: const EdgeInsets.symmetric(vertical: 8.0),
                child: Row(
                  children: [
                    Expanded(
                      child: Text(
                        'Select a date',
                        style: TextStyle(
                          fontSize: 14,
                          fontWeight: FontWeight.w500,
                        ),
                      ),
                    ),
                    Container(
                      padding: const EdgeInsets.symmetric(horizontal: 4),
                      margin: const EdgeInsets.symmetric(vertical: 8.0),
                      height: 36,
                      decoration: BoxDecoration(
                        borderRadius: Styles.borderRadius,
                      ),
                      child: OutlinedButton(
                        onPressed: () async {
                          final now = DateTime.now();

                          final result = await showDatePicker(
                              context: context,
                              initialDate: now,
                              firstDate: now.subtract(
                                const Duration(
                                  days: 90,
                                ),
                              ),
                              lastDate: now);

                          if(result ! =null) {
                            setState(() {
                              selectedDate = result;
                            });
                          }
                        },
                        child: Row(
                          mainAxisAlignment: MainAxisAlignment.spaceBetween,
                          children: [
                            Padding(
                              padding: const EdgeInsets.only(right: 16.0),
                              child:
                                  Text('${formatDateToString(selectedDate)}'), ), Icon(Icons.calendar_today_outlined), ], ), ), ), ], ), ) ], ), ); }); }Copy the code

Note that I have added selectedDatevariable to our home page, which you can see in the repository link I provided at the end. But now we have a problem, even though we are using setStateOutlineButton to update the value of selectedDate, the old value is still displayed before reopening the worksheet, as shown below.

To solve this problem, we need to pass the OutlinedButton to the StatefulBuilder (or you can create a new widget and expose the changes using callbacks, as I said earlier, which is the right way, by the way).

void addWeight() {
    showModalBottomSheet(
      isScrollControlled: true,
      context: context,
      shape: const RoundedRectangleBorder(
          borderRadius: BorderRadius.only(
        topLeft: Radius.circular(8),
        topRight: Radius.circular(8),
      )),
      builder: (context) {
        return Container(
          height: 360,
          width: MediaQuery.of(context).size.width,
          margin:
              EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
          padding: const EdgeInsets.all(16.0),
          decoration: BoxDecoration(
            borderRadius: BorderRadius.circular(20),
          ),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              const Padding(
                padding: EdgeInsets.only(bottom: 24.0),
                child: Text(
                  'Register Weight',
                  style: Styles.titleStyle,
                ),
              ),
              TextField(
                controller: weightInputController,
                keyboardType: TextInputType.number,
                decoration: InputDecoration(
                  labelText: 'Weight (KG)',
                  border: OutlineInputBorder(
                    borderRadius: Styles.borderRadius,
                  ),
                ),
              ),
              Padding(
                padding: const EdgeInsets.symmetric(vertical: 8.0),
                child: Row(
                  children: [
                    Expanded(
                      child: Text(
                        'Select a date',
                        style: TextStyle(
                          fontSize: 14,
                          fontWeight: FontWeight.w500,
                        ),
                      ),
                    ),
                    Container(
                        padding: const EdgeInsets.symmetric(horizontal: 4),
                        margin: const EdgeInsets.symmetric(vertical: 8.0),
                        height: 36,
                        decoration: BoxDecoration(
                          borderRadius: Styles.borderRadius,
                        ),
                        child: StatefulBuilder(
                          builder: (context, setState) {
                            return OutlinedButton(
                              onPressed: () async {
                                final now = DateTime.now();

                                final result = await showDatePicker(
                                    context: context,
                                    initialDate: now,
                                    firstDate: now.subtract(
                                      const Duration(
                                        days: 90,
                                      ),
                                    ),
                                    lastDate: now);

                                if(result ! =null) {
                                  setState(() {
                                    selectedDate = result;
                                  });
                                }
                              },
                              child: Row(
                                mainAxisAlignment:
                                    MainAxisAlignment.spaceBetween,
                                children: [
                                  Padding(
                                    padding: const EdgeInsets.only(right: 16.0),
                                    child: Text(
                                        '${formatDateToString(selectedDate)}'),
                                  ),
                                  Icon(Icons.calendar_today_outlined),
                                ],
                              ),
                            );
                          },
                        )),
                  ],
                ),
              ),
              Expanded(child: Container()),
              ButtonBar(
                children: [
                  ElevatedButton(
                    onPressed: () => Navigator.pop(context),
                    child: Text('Cancel',
                        style: TextStyle(
                          color: Theme.of(context).primaryColor,
                        )),
                    style: ElevatedButton.styleFrom(
                      primary: Colors.white,
                      // minimumSize: Size(96, 48),
                    ),
                  ),
                  ElevatedButton(
                      onPressed: () {
                        setState(() {
                          weights.insert(
                              0,
                              WeightModel(
                                value: double.parse(weightInputController.text),
                                date: selectedDate,
                              ));
                        });
                        Navigator.pop(context);
                      },
                      child: const Text('Register'(() [[() [() [() [() }); }Copy the code

This is the final version of our ModalBottomSheet!

Github.com/evandrmb/bo…


The elder brother of the © cat

ducafecat.tech/

github.com/ducafecat

The issue of

Open source

GetX Quick Start

Github.com/ducafecat/g…

News client

Github.com/ducafecat/f…

Strapi manual translation

getstrapi.cn

Wechat discussion group Ducafecat

A series of collections

The translation

Ducafecat. Tech/categories /…

The open source project

Ducafecat. Tech/categories /…

Dart programming language basics

Space.bilibili.com/404904528/c…

Start Flutter with zero basics

Space.bilibili.com/404904528/c…

Flutter combat news client from scratch

Space.bilibili.com/404904528/c…

Flutter component development

Space.bilibili.com/404904528/c…

Flutter Bloc

Space.bilibili.com/404904528/c…

Flutter Getx4

Space.bilibili.com/404904528/c…

Docker Yapi

Space.bilibili.com/404904528/c…