Our Ready to use Custom Flutter Modules

Action Sheet

The action sheet displays a set of menus to confirm or cancel an action. An Action Sheet comes up from the bottom of the screen and displays actions a user can select. An action sheet can have a title, a message, and a list of actions.

Use the action sheet if:

  • You need an alternative which provides more than one action.
  • You only have a small number of actions and no need to scroll.

Do not use the action sheet if:

  • Requires only one option. In this case, recommended to using a button instead.

Mobile Screen View


Precautions

  • An action sheet styles’ title and message must to match with standard iOS action sheet title and message text style.
  • Cancel button should appear at the bottom of an action sheet.

# Usage

You need to create two dart files at very first time. One is main .dart file and second is for particular function. Next you just need to update function details in the same main .dart file only.

Create action_sheet_page.dart file and paste the below code and call this file in your main.dart file.
First .dart file > action_sheet_page.dart (New)

				
					import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:fullter_main_app/src/api_calling/api_constant.dart';
import 'package:fullter_main_app/src/widgets/android_ios_check_box.dart';
import 'package:fullter_main_app/src/widgets/bottom_sheet_modal.dart';

class ActionSheetPage extends StatefulWidget {
 ActionSheetPage({Key key}) : super(key: key);
 @override
 _ActionSheetPageState createState() => _ActionSheetPageState();
}

class _ActionSheetPageState extends State<ActionSheetPage> {
 @override
 Widget build(BuildContext context) {
   //Center View
   Widget _centerView() {
     return Container(
       margin: EdgeInsets.symmetric(horizontal: 10),
       child: Column(
         crossAxisAlignment: CrossAxisAlignment.center,
         mainAxisAlignment: MainAxisAlignment.start,
         mainAxisSize: MainAxisSize.min,
         children: <Widget>[
           AndroidIosCheckbox(
             onChanged: () {
               setState(() {});
             },
           ),
           ListView(
             shrinkWrap: true,
             children: [
               ElevatedButton(
                 child: const Text('show Modal Bottom Sheet'),
                 onPressed: () {
                   ActionBottomSheetModal(
                     //isAndroid: ConstantC.isAndroidPlatform,
                     alertTitle: "Share option",
                     itemList: [
                       ItemModel(
                           menuName: "Delete", itemTextColor: Colors.red),
                       ItemModel(menuName: "Share"),
                       ItemModel(menuName: "Pay"),
                       ItemModel(menuName: "Favorite")
                     ],
                     context: context,
                     selectedItemCallBack: (num) {},
                   );
                 },
               ),
             ],
           ),
         ],
       ),
     );
   }

   //Back Press
   _onBackPressed() {
     Navigator.pop(context);
   }

   return WillPopScope(
       onWillPop: _onBackPressed,
       child: Container(
           color: Colors.transparent,
           child: SafeArea(
               bottom: false,
               child: Scaffold(
                 //appBar:_appBar(),
                 body: Container(
                   // color: Colors.white,
                   child: Align(
                     alignment: Alignment.topCenter,
                     child: SingleChildScrollView(
                       physics: BouncingScrollPhysics(),
                       dragStartBehavior: DragStartBehavior.down,
                       child: _centerView(),
                     ),
                   ),
                 ),
               ))));
 }
}

				
			


Create action_bottom_sheet_modal.dart file and paste the below code

Second .dart file > action_bottom_sheet_modal.dart

				
					import 'dart:io';
import 'package:flutter/material.dart';

//Selected menu call back function type
typedef IntCallback = Function(int num);

class ItemModel {
 String menuName;
 Color itemTextColor;
 ItemModel({this.menuName = "", this.itemTextColor});
}

class ActionBottomSheetModal {
 IntCallback
     selectedItemCallBack; //Call back function it call when user click on any menu item button and return index
 VoidCallback
     cancelCallBack; //Call back function it call when user click on cancel button
 BuildContext context;
 String alertTitle = "";
 final List<ItemModel> itemList;
 EdgeInsets itemMarginAllSide;
 EdgeInsets itemPaddingAllSide;
 EdgeInsets sheetPaddingAllSide;
 TextStyle styleRowItemAndroid;
 TextStyle styleRowItemIos;
 TextStyle styleRowTitleAndroid;
 TextStyle styleRowTitleIos;
 bool isAndroid;

 ActionBottomSheetModal({
   @required this.context,
   @required this.cancelCallBack,
   @required this.selectedItemCallBack,
   this.itemList,
   this.alertTitle = "Albums",
   this.isAndroid = false,
   this.itemMarginAllSide =
       const EdgeInsets.symmetric(horizontal: 15, vertical: 0),
   this.itemPaddingAllSide =
       const EdgeInsets.symmetric(horizontal: 0, vertical: 5),
   this.sheetPaddingAllSide =
       const EdgeInsets.symmetric(horizontal: 5, vertical: 5),
   this.styleRowItemAndroid,
   this.styleRowItemIos,
   this.styleRowTitleAndroid,
   this.styleRowTitleIos,
 }) {
   //Check device platform
   if (Platform.isIOS) {
     this.isAndroid = false;
   } else if (Platform.isAndroid) {
     this.isAndroid = true;
   }
   _actionBottomSheetModal();
 }

 //Single row of items
 Widget singleItemView(
     {@required String menuName, @required int itemIndex, Color itemColor}) {
   TextStyle styleRowItemTemp =
       buildTextStyleMenuItem(textColorItem: itemColor);

   return Align(
     alignment: this.isAndroid ? Alignment.centerLeft : Alignment.center,
     child: Container(
       margin: itemMarginAllSide,
       child: ElevatedButton(
         style: ButtonStyle(
             backgroundColor: MaterialStateProperty.all(Colors.white),
             overlayColor: MaterialStateProperty.all(
                 this.isAndroid ? Colors.grey.withOpacity(0.1) : Colors.white),
             padding: MaterialStateProperty.all(itemPaddingAllSide),
             alignment:
                 this.isAndroid ? Alignment.centerLeft : Alignment.center,
             minimumSize:
                 MaterialStateProperty.all(Size(double.maxFinite, 45)),
             elevation: MaterialStateProperty.all(0.0)),
         child: Text('$menuName', style: styleRowItemTemp),
         onPressed: () {
           if (this.selectedItemCallBack != null) {
             this.selectedItemCallBack(itemIndex);
           }
           Navigator.pop(context, true);
         },
       ),
     ),
   );
 }

 //Cancel
 Widget cancelView({Color itemColor}) {
   TextStyle styleRowItemTemp =
       buildTextStyleCancelTitle(textColor: itemColor);
   return Align(
     alignment: this.isAndroid ? Alignment.centerLeft : Alignment.center,
     child: InkWell(
         onTap: () {
           if (this.cancelCallBack != null) {
             this.cancelCallBack();
           }
           Navigator.pop(context, true);
         },
         child: Container(
           margin: this.itemMarginAllSide,
           padding: this.isAndroid
               ? EdgeInsets.only(bottom: 10, top: 10)
               : EdgeInsets.only(bottom: 15, top: 15),
           child: Text('Cancel', style: styleRowItemTemp),
         )),
   );
 }

 //Title
 Widget titleView({Color itemColor}) {
   TextStyle styleRowItemTemp = buildTextStyleTitle(textColor: itemColor);
   return Align(
     alignment: this.isAndroid ? Alignment.centerLeft : Alignment.center,
     child: Container(
       margin: itemMarginAllSide,
       padding: EdgeInsets.only(bottom: 10, top: 10),
       child: Text(
         '${this.alertTitle}',
         style: styleRowItemTemp,
       ),
     ),
   );
 }

 //Item list view
 Widget titleListView() {
   return Align(
     alignment: Alignment.center,
     child: Container(
       child: ListView.builder(
         shrinkWrap: true,
         itemCount: itemList.length,
         itemBuilder: (context, index) {
           return singleItemView(
               menuName: itemList[index].menuName,
               itemColor: itemList[index].itemTextColor,
               itemIndex: index);
         },
       ),
     ),
   );
 }

 Future<void> _actionBottomSheetModal() {
   return showModalBottomSheet<void>(
     isScrollControlled: false,
     context: context,
     backgroundColor: Colors.transparent,
     builder: (BuildContext context) {
       return Container(
         //height: 600,
         color: Colors.transparent,
         child: Column(
           mainAxisAlignment: MainAxisAlignment.end,
           mainAxisSize: MainAxisSize.max,
           children: [
             Card(
               elevation: this.isAndroid ? 0 : 1,
               margin: this.isAndroid
                   ? EdgeInsets.all(0)
                   : EdgeInsets.symmetric(vertical: 0, horizontal: 10),
               shape: this.isAndroid
                   ? RoundedRectangleBorder(
                       borderRadius: BorderRadius.all(Radius.circular(0.0)),
                     )
                   : RoundedRectangleBorder(
                       borderRadius: BorderRadius.all(Radius.circular(10.0)),
                     ),
               child: Column(
                 mainAxisAlignment: MainAxisAlignment.start,
                 mainAxisSize: MainAxisSize.min,
                 children: [titleView(), titleListView()],
               ),
             ),
             Card(
                 elevation: this.isAndroid ? 0 : 1,
                 margin: this.isAndroid
                     ? EdgeInsets.all(0)
                     : EdgeInsets.symmetric(vertical: 10, horizontal: 10),
                 shape: this.isAndroid
                     ? RoundedRectangleBorder(
                         borderRadius: BorderRadius.all(Radius.circular(0.0)),
                       )
                     : RoundedRectangleBorder(
                         borderRadius: BorderRadius.all(Radius.circular(10.0)),
                       ),
                 child: cancelView())
           ],
         ),
       );
     },
   );
 }

 TextStyle buildTextStyleMenuItem({Color textColorItem}) {
   TextStyle styleRowItem;
   if (textColorItem == null) {
     textColorItem = isAndroid ? Colors.black : Colors.blue;
   }
   //Ios
   styleRowItem = this.styleRowItemIos != null
       ? this.styleRowItemIos
       : TextStyle(
           color: textColorItem, fontSize: 16, fontWeight: FontWeight.w500);
   //Android
   if (isAndroid) {
     styleRowItem = this.styleRowItemAndroid != null
         ? this.styleRowItemAndroid
         : TextStyle(
             color: textColorItem, fontSize: 16, fontWeight: FontWeight.w400);
   }
   return styleRowItem;
 }

 TextStyle buildTextStyleTitle({Color textColor}) {
   TextStyle styleText;
   if (textColor == null) {
     textColor = isAndroid ? Colors.grey : Colors.grey;
   }
   //ios
   styleText = this.styleRowItemIos != null
       ? this.styleRowItemIos
       : TextStyle(
           color: textColor, fontSize: 16, fontWeight: FontWeight.w500);
   //Android
   if (isAndroid) {
     styleText = this.styleRowItemAndroid != null
         ? this.styleRowItemAndroid
         : TextStyle(
             color: textColor, fontSize: 16, fontWeight: FontWeight.w400);
   }
   return styleText;
 }

 TextStyle buildTextStyleCancelTitle({Color textColor}) {
   TextStyle styleText;
   if (textColor == null) {
     textColor = isAndroid ? Colors.grey : Colors.grey;
   }
   //iOS
   styleText = this.styleRowTitleIos != null
       ? this.styleRowTitleIos
       : TextStyle(
           color: textColor, fontSize: 16, fontWeight: FontWeight.w500);
   //Android
   if (isAndroid) {
     styleText = this.styleRowTitleAndroid != null
         ? this.styleRowTitleAndroid
         : TextStyle(
             color: textColor, fontSize: 16, fontWeight: FontWeight.w400);
   }
   return styleText;
 }
}

				
			

Alert

Alert gives information or collects information from the user using inputs. An alert has a title, an optional message, one or more buttons, and optional text fields to get feedbacks.

An alert generally display on the top of the app’s content, and must be manually rejected by the app user.

Use the alert if:

  • You need to show text messages only.
  • If you requires immediate user action.

Do not use the alert if:

  • If requires multiple responses from App user.

Precautions

  • Do not add multiple actions under alert dialog box, generally it has only two actions. like: Ok (or) Cancel

# Usage

Info Alert
Use the below code in your main dart file.
First .dart file> Main.dart (Update)

Mobile Screen View


				
					ElevatedButton(
                 child: const Text('Info Alert'),
                 onPressed: () {
                   InfoAlert(                       context: context,
                       // message: "",
                       callBackConfirm: (alertContext) {
                         // Navigator.pop(alertContext);
                       });
                 },
               )
				
			

Create info_alert.dart file and paste the below code
Second .dart file > info_alert.dart

				
					import 'dart:io';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:fullter_main_app/src/all_file_import/app_values_files_link.dart';
import 'package:fullter_main_app/src/values/app_color.dart';

//Selected menu call back function type
typedef ContextCallback = Function(BuildContext alertContext);

class InfoAlert {
 BuildContext context;
 String alertTitle;
 String message;
 String confirmActionText;
 TextStyle textStyleConfirmActionIos;
 TextStyle textStyleConfirmActionAndroid;
 ContextCallback callBackConfirm;
 bool isAndroid;

 InfoAlert(
     {Key key,
     @required this.context,
     this.alertTitle = "Alert",
     this.confirmActionText = "Ok",
     this.message = "This is inform alert",
     this.textStyleConfirmActionIos,
     this.textStyleConfirmActionAndroid,
     this.callBackConfirm,
     this.isAndroid = false})
     : assert(message != null) {
   //Check device platform
   if (Platform.isIOS) {
     this.isAndroid = false;
   } else if (Platform.isAndroid) {
     this.isAndroid = true;
   }
   infoAlert();
 }
 Future<bool> infoAlert() {
   return showDialog(
       barrierColor: Colors.transparent,
       context: this.context,
       barrierDismissible: false,
       builder: (alertContext) {
         //mContext = context1;
         return this.isAndroid
             ? AlertDialog(
                 // backgroundColor: Colors.transparent,
                 title: new Text(this.alertTitle,
                     style: new TextStyle(
                         color: AppColors().lightBlack, fontSize: 20.0)),
                 content: new Text(this.message),
                 actions: <Widget>[
                   TextButton(
                     child: buildTextPositiveAction(),
                     onPressed: () {
                       this.callBackConfirm(alertContext);
                       Navigator.pop(alertContext);
                     },
                   )
                 ],
               )
             : CupertinoAlertDialog(
                 // backgroundColor: Colors.transparent,
                 title: new Text(this.alertTitle,
                     style: new TextStyle(
                         color: AppColors().lightBlack, fontSize: 20.0)),
                 content: new Text(message ?? ""),
                 actions: <Widget>[
                   TextButton(
                     child: buildTextPositiveAction(),
                     onPressed: () {
                       this.callBackConfirm(alertContext);
                       Navigator.pop(alertContext);
                     },
                   )
                 ],
               );
       });
 }

 Text buildTextPositiveAction({Color textColorItem}) {
   Text textView;
   //Ios
   textView = textStyleConfirmActionIos != null
       ? Text("$confirmActionText", style: textStyleConfirmActionIos)
       : Text("$confirmActionText");
   //Android
   if (isAndroid) {
     textView = textStyleConfirmActionAndroid != null
         ? Text("$confirmActionText", style: textStyleConfirmActionAndroid)
         : Text("$confirmActionText");
   }
   return textView;
 }
}

				
			

Confirmation Alert
Use the below code in your main dart file.

First .dart file> Main.dart (Update)

				
					ConfirmationAlert(
   context: context,
   noCallback: (alertContext) {
   },
   callBackYes: (alertContext) {
   });
				
			

Create confirmation_alert.dart file and paste the below code

Second .dart file > confirmation_alert.dart

Mobile Screen View


				
					import 'dart:io';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:fullter_main_app/src/all_file_import/app_values_files_link.dart';
import 'package:fullter_main_app/src/values/app_color.dart';

//Selected menu call back function type
typedef ContextCallback = Function(BuildContext alertContext);

class ConfirmationAlert {
 BuildContext context;
 String alertTitle;
 String message;
 String positiveActionText;
 String negativeActionText;
 TextStyle textStylePositiveActionIos;
 TextStyle textStyleNegativeActionIos;

 TextStyle textStyleNegativeActionAndroid;
 TextStyle textStylePositiveActionAndroid;

 ContextCallback callBackYes;
 ContextCallback noCallback;
 bool isAndroid;

 ConfirmationAlert(
     {Key key,
     @required this.context,
     this.alertTitle = "Alert",
     this.positiveActionText = "Yes",
     this.negativeActionText = "No",
     this.message = "This is confirmation alert",
     this.textStylePositiveActionIos,
     this.textStyleNegativeActionIos,
     this.callBackYes,
     this.isAndroid = false,
     this.noCallback})
     : assert(message != null) {
   //Check device platform
   if (Platform.isIOS) {
     this.isAndroid = false;
   } else if (Platform.isAndroid) {
     this.isAndroid = true;
   }
   confirmationAlert();
 }
 Future<bool> confirmationAlert() {
   return showDialog(
       barrierColor: Colors.transparent,
       context: this.context,
       barrierDismissible: false,
       builder: (alertContext) {
         //mContext = context1;
         return this.isAndroid
             ? AlertDialog(
                 // backgroundColor: Colors.transparent,
                 title: new Text(this.alertTitle,
                     style: new TextStyle(
                         color: AppColors().lightBlack, fontSize: 20.0)),
                 content: new Text(this.message),
                 actions: <Widget>[
                   TextButton(
                     child: buildTextNegativeAction(),
                     onPressed: () {
                       this.noCallback(alertContext);
                       Navigator.pop(alertContext);
                     },
                   ),
                   TextButton(
                     child: buildTextPositiveAction(),
                     onPressed: () {
                       this.callBackYes(alertContext);
                       Navigator.pop(alertContext);
                     },
                   )
                 ],
               )
             : CupertinoAlertDialog(
                 // backgroundColor: Colors.transparent,
                 title: new Text(this.alertTitle,
                     style: new TextStyle(
                         color: AppColors().lightBlack, fontSize: 20.0)),
                 content: new Text(message ?? ""),
                 actions: <Widget>[
                   TextButton(
                     child: buildTextNegativeAction(),
                     onPressed: () {
                       this.noCallback(alertContext);
                       Navigator.pop(alertContext);
                     },
                   ),
                   TextButton(
                     child: buildTextPositiveAction(),
                     onPressed: () {
                       this.callBackYes(alertContext);
                       Navigator.pop(alertContext);
                     },
                   )
                 ],
               );
       });
 }

 Text buildTextPositiveAction({Color textColorItem}) {
   Text textView;
   /* if (textColorItem == null) {
     textColorItem = isAndroid ? Colors.black : Colors.blue;
   }*/
   //Ios
   textView = textStylePositiveActionIos != null
       ? Text("$positiveActionText", style: textStylePositiveActionIos)
       : Text("$positiveActionText");
   //Android
   if (isAndroid) {
     textView = textStylePositiveActionAndroid != null
         ? Text("$positiveActionText", style: textStylePositiveActionAndroid)
         : Text("$positiveActionText");
   }
   return textView;
 }

 Text buildTextNegativeAction({Color textColorItem}) {
   Text textView;
   /* if (textColorItem == null) {
     textColorItem = isAndroid ? Colors.black : Colors.blue;
   }*/
   //Ios
   textView = textStyleNegativeActionIos != null
       ? Text("$negativeActionText", style: textStyleNegativeActionIos)
       : Text("$negativeActionText");
   //Android
   if (isAndroid) {
     textView = textStyleNegativeActionAndroid != null
         ? Text("$negativeActionText", style: textStylePositiveActionAndroid)
         : Text("$negativeActionText");
   }
   return textView;
 }
}

				
			

Checkbox

Checkboxes allow users to select multiple options from the available options. Generally, the checkbox appears as checked(Right Symbol) or solid filled when activated.

Use the Checkbox if:

  • We need to get multiple responses from App users.

Do not Use the Checkbox if:

  • If required input field type response from the app users.

Precautions:

  • By default tristate is false and the checkbox’s value must be true or false.

Mobile Screen View


Properties:
CheckFillColor: Set color for active checkbox.
Label: Set label for checkbox.
OnChanged: It is callback function that return true or false for checked status of checkbox.
For add Android and iOS platform specific style:

//Check device platform

if (Platform.isIOS) {

 isAndroid = false;

} else if (Platform.isAndroid) {

 isAndroid = true;

}

# Usage

Checkbox
Create check_box_page.dart file and paste below code and call this file in your main.dart file.
First .dart file > check_box_page.dart (New)

				
					import 'package:flutter/material.dart';
import 'package:fullter_main_app/src/api_calling/api_constant.dart';
import 'package:fullter_main_app/src/widgets/android_ios_check_box.dart';
import 'package:fullter_main_app/src/widgets/labeled_check_box.dart';

class CheckBoxPage extends StatefulWidget {
  CheckBoxPage({Key key}) : super(key: key);
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<CheckBoxPage> {
  bool _isSelected = false;
  bool _isSelected1 = false;
  bool _isSelected2 = true;
  bool _isSelected3 = false;
  @override
  void dispose() {
    // TODO: implement dispose
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    //Center View
    Widget _centerView() {
      return Container(
        margin: EdgeInsets.symmetric(horizontal: 10),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          mainAxisAlignment: MainAxisAlignment.start,
          mainAxisSize: MainAxisSize.min,
          children: <Widget>[
            AndroidIosCheckbox(
              onChanged: () {
                setState(() {});
              },
            ),
            ListView(
              shrinkWrap: true,
              children: [
                LabeledCheckbox(
                  isAndroid: ConstantC.isAndroidPlatform,
                  label: 'This is the label text ',
                  padding: const EdgeInsets.symmetric(horizontal: 20.0),
                  value: _isSelected1,
                  onChanged: (bool newValue) {
                    setState(() {
                      _isSelected1 = newValue;
                    });
                  },
                ),
                LabeledCheckbox(
                  isAndroid: ConstantC.isAndroidPlatform,
                  label: 'This is the label text ',
                  padding: const EdgeInsets.symmetric(horizontal: 20.0),
                  value: _isSelected,
                  disabled: true,
                  onChanged: (bool newValue) {
                    setState(() {
                      _isSelected = newValue;
                    });
                  },
                ),
                LabeledCheckbox(
                  checkFillColor: Colors.blue,
                  isAndroid: ConstantC.isAndroidPlatform,
                  label: 'This is the label text ',
                  padding: const EdgeInsets.symmetric(horizontal: 20.0),
                  value: _isSelected2,
                  disabled: false,
                  onChanged: (bool newValue) {
                    setState(() {
                      _isSelected2 = newValue;
                    });
                  },
                ),
                LabeledCheckbox(
                  checkFillColor: Colors.pink,
                  isAndroid: ConstantC.isAndroidPlatform,
                  label: 'This is the label text ',
                  padding: const EdgeInsets.symmetric(horizontal: 20.0),
                  value: _isSelected3,
                  disabled: false,
                  onChanged: (bool newValue) {
                    setState(() {
                      _isSelected3 = newValue;
                    });
                  },
                ),
              ],
            )
          ],
        ),
      );
    }

    //Back Press
    _onBackPressed() {
      print("ok");
      Navigator.pop(context);
      print("ok");
    }

    return WillPopScope(
        onWillPop: _onBackPressed,
        child: Container(
            color: Colors.transparent,
            child: SafeArea(
                bottom: false,
                child: Scaffold(
                  backgroundColor: Colors.white,
                  //appBar:_appBar(),
                  body: Container(
                    color: Colors.white,
                    child: _centerView(),
                  ),
                ))));
  }
}
				
			


Create labeled_check_box.dart file and paste below code
Second .dart file > labeled_check_box.dart

				
					import 'dart:io';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

class LabeledCheckbox extends StatelessWidget {
  LabeledCheckbox({
    Key key,
    @required this.label,
    @required this.padding,
    @required this.value,
    @required this.onChanged,
    this.checkBoxColor = Colors
        .grey, //Check box out side border color in case or non selected check box
    this.checkColor = Colors.white, // Check rite icon color
    this.checkTextColor = Colors.black, //Check box text color
    this.checkNonFillColor =
        Colors.white, //Non fill color in case of check box not selected
    this.disabled = false,
    this.isAndroid = false,
    this.checkFillColor = Colors.green, //Fill color
  }) : super(key: key);

  final String label;
  final EdgeInsets padding;
  final bool value;
  final Function onChanged;
  final Color checkColor;
  final Color checkTextColor;
  final bool disabled;
  final bool isAndroid;
  final Color checkBoxColor;
  final Color checkFillColor;
  final Color checkNonFillColor;

  @override
  Widget build(BuildContext context) {
    /*bool isAndroid = false;
    //Check device platform
    if(Platform.isIOS){
      isAndroid = false;
    }
    else if(Platform.isAndroid){
      isAndroid = true;
    }*/
    //Disabled color
    Color textDisabledColor = Color(0xFFefefef);
    Color checkBoxDisableColor = Color(0xFFefefef);
    Color checkFillDisableColor = isAndroid
        ? (disabled ? Color(0xFFefefef) : Color(0xFFffffff))
        : Color(0xFFffffff);
    Color checkDisableColor = Color(0xFFffffff);
    //Ios check box custome
    Widget iosCheckBox = Container(
      margin: EdgeInsets.symmetric(vertical: 5),
      padding: EdgeInsets.all(
          5.0), //I used some padding without fixed width and height
      decoration: BoxDecoration(
          // You can use like this way or like the below line
          border: Border.all(
              color: disabled
                  ? checkBoxDisableColor
                  : (value ? checkFillColor : checkBoxColor),
              width: 1.0,
              style: BorderStyle.solid), //Border.all
          borderRadius: BorderRadius.all(
            Radius.circular(50),
          ),
          color: (value && !disabled)
              ? checkFillColor
              : !disabled
                  ? checkNonFillColor
                  : checkFillDisableColor),
      child: (value && !disabled)
          ? Icon(
              CupertinoIcons.checkmark_alt,
              color: checkColor,
            )
          : Icon(
              CupertinoIcons.checkmark_alt,
              color: !disabled ? checkNonFillColor : checkDisableColor,
            ), // You can add a Icon instead of text also, like below.
      //child: new Icon(Icons.arrow_forward, size: 50.0, color: Colors.black38)),
    );
    return InkWell(
      onTap: () {
        if (!disabled) {
          onChanged(!value);
        }
      },
      child: Padding(
        padding: padding,
        child: Row(
          children: <Widget>[
            isAndroid
                ? Checkbox(
                    checkColor: checkColor,
                    fillColor: MaterialStateProperty.all(!disabled
                        ? (value ? checkFillColor : checkBoxColor)
                        : checkFillDisableColor),
                    value: !disabled ? value : false,
                    onChanged: (bool newValue) {
                      onChanged(newValue);
                    },
                  )
                : iosCheckBox,
            SizedBox(
              width: 30,
            ),
            Expanded(
                child: Text(
              label,
              style: TextStyle(
                  color: !disabled ? checkTextColor : textDisabledColor),
            )),
          ],
        ),
      ),
    );
  }
}
				
			

Badges

Badges are inline-block elements that generally appear near another element. Badges are indicators of Feedback, Recognition, Notifications, Actions, Accomplishments, Skills, Quality, or interest that can be earned.

Use the Badges if:

  • Need to show the results as an indicator.

Do not Use the Badges if:

  • Need to show the results in detail.

Precautions:

  • Badges need to appear by default in the app.

Mobile Screen View


# Usage

Badges
Create badges_page.dart file and paste the below code and call this file in your main.dart file.

First .dart file > badges_page.dart (New)

				
					import 'dart:io';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:fullter_main_app/src/api_calling/api_constant.dart';
import 'package:fullter_main_app/src/widgets/android_ios_check_box.dart';
import 'package:fullter_main_app/src/widgets/badge.dart';
import 'package:fullter_main_app/src/widgets/icon_right_with_text.dart';
import 'package:fullter_main_app/src/widgets/labeled_check_box.dart';
import 'package:fullter_main_app/src/widgets/listViewCustom.dart';

class BadgesPage extends StatefulWidget {
  BadgesPage({Key key}) : super(key: key);
  @override
  _BadgesPageState createState() => _BadgesPageState();
}

class _BadgesPageState extends State<BadgesPage> {
  List<String> listData = [];
  @override
  void dispose() {
    // TODO: implement dispose
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    listData = [
      "Followers",
      "Like",
      "Share",
      "Completed",
      "Warning",
      "Notification",
      "Unread"
          "Draft",
      "Deleted"
    ];
    //Center View
    Widget _centerView() {
      return Container(
        margin: EdgeInsets.symmetric(horizontal: 10),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          mainAxisAlignment: MainAxisAlignment.start,
          mainAxisSize: MainAxisSize.min,
          children: <Widget>[
            AndroidIosCheckbox(
              onChanged: () {
                setState(() {});
              },
            ),
            ListViewCustom(
              shrinkWrap: true,
              listData: listData,
              listViewType: ListViewType.LIST_CUSTOM_ROW_ITEMS,
              tileWidget: ({singleRowData, index}) {
                BadgeType badgeType = BadgeType.FOLLOWERS;
                if (index == 1) {
                  badgeType = BadgeType.LIKE;
                } else if (index == 2) {
                  badgeType = BadgeType.SHARE;
                } else if (index == 3) {
                  badgeType = BadgeType.COMPLETED;
                } else if (index == 4) {
                  badgeType = BadgeType.WARNINGS;
                } else if (index == 5) {
                  badgeType = BadgeType.NOTIFICATION;
                } else if (index == 6) {
                  badgeType = BadgeType.UNREAD;
                } else if (index == 7) {
                  badgeType = BadgeType.DRAFT;
                } else {
                  badgeType = BadgeType.DELETED;
                }
                return IconRightWithText(
                  index: index,
                  text: listData[index],
                  iconRightWidget: Badge( isAndroid: ConstantC.isAndroidPlatform,
                    badgeType: badgeType,
                    badgeValue: "70",
                  ),
                  iconViewSize: Size(70, 40),
                );
              },
            )
          ],
        ),
      );
    }

    //Back Press
    _onBackPressed() {
      print("ok");
      Navigator.pop(context);
      print("ok");
    }

    return WillPopScope(
        onWillPop: _onBackPressed,
        child: Container(
            color: Colors.transparent,
            child: SafeArea(
                bottom: false,
                child: Scaffold(
                  backgroundColor: Colors.white,
                  //appBar:_appBar(),
                  body: Container(
                    color: Colors.white,
                    child: _centerView(),
                  ),
                ))));
  }
}
				
			


Create badge.dart file and paste the below code
Second .dart file > badge.dart

				
					import 'dart:io';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

enum BadgeType {
  FOLLOWERS,
  LIKE,
  SHARE,
  COMPLETED,
  WARNINGS,
  NOTIFICATION,
  UNREAD,
  DRAFT,
  DELETED
}

class Badge extends StatelessWidget {
  Badge({
    Key key,
    this.padding = const EdgeInsets.symmetric(horizontal: 8, vertical: 3),
    this.margin = const EdgeInsets.symmetric(horizontal: 5, vertical: 3),
    this.badgeValue = "-1",
    this.badgeType = BadgeType.FOLLOWERS,
    this.onChanged, //Check box out side border color in case or non selected check box
    this.isAndroid = false,
    this.badgeBackgroundColor,
    this.badgeValueStyle, //Fill color
  }) : super(key: key);

  final EdgeInsets padding;
  final BadgeType badgeType;
  final EdgeInsets margin;
  final String badgeValue;
  final TextStyle badgeValueStyle;
  final Function onChanged;
  final Color badgeBackgroundColor;
  final bool isAndroid;

  @override
  Widget build(BuildContext context) {
    /*bool isAndroid = false;
    //Check device platform
    if (Platform.isIOS) {
      isAndroid = false;
    } else if (Platform.isAndroid) {
      isAndroid = false;
    }*/

    // Badge
    BoxDecoration badgeDecorationStyle(
        {double borderWith = 1, double borderRadius = 15}) {
      borderRadius = isAndroid ? 5 : 15;
      Color badgeBackgroundColorTemp = Color(0xff3880ff);
      switch (this.badgeType) {
        case BadgeType.LIKE:
          badgeBackgroundColorTemp = Color(0xff3dc2ff);
          break;
        case BadgeType.SHARE:
          badgeBackgroundColorTemp = Color(0xff5260ff);
          break;
        case BadgeType.COMPLETED:
          badgeBackgroundColorTemp = Color(0xff2dd36f);
          break;
        case BadgeType.WARNINGS:
          badgeBackgroundColorTemp = Color(0xffffc409);
          break;
        case BadgeType.NOTIFICATION:
          badgeBackgroundColorTemp = Color(0xffeb445a);
          break;
        case BadgeType.UNREAD:
          badgeBackgroundColorTemp = Color(0x00ffffff);
          break;
        case BadgeType.DRAFT:
          badgeBackgroundColorTemp = Color(0xff92949c);
          break;
        case BadgeType.DELETED:
          badgeBackgroundColorTemp = Color(0xff222428);
          break;
        default:
          badgeBackgroundColorTemp = Color(0xff3880ff);
          break;
      }

      badgeBackgroundColorTemp = badgeBackgroundColor != null
          ? badgeBackgroundColor
          : badgeBackgroundColorTemp;

      return BoxDecoration(
          // You can use like this way or like the below line
          border: Border.all(
              color: badgeBackgroundColorTemp,
              width: borderWith,
              style: BorderStyle.solid),
          borderRadius: BorderRadius.all(
            Radius.circular(borderRadius),
          ),
          color: badgeBackgroundColorTemp);
    }

    //Badge text style
    Text buildTextBadge({String badgeValue}) {
      Text textView;
      Color badgeValueColor = Colors.white;
      //Set badge text color according selected badge
      switch (this.badgeType) {
        case BadgeType.UNREAD:
          badgeValueColor = Colors.black;
          break;
        case BadgeType.WARNINGS:
          badgeValueColor = Colors.black;
          break;
        default:
          badgeValueColor = Colors.white;
          break;
      }

      TextStyle badgeValueStyle = this.badgeValueStyle != null
          ? this.badgeValueStyle
          : TextStyle(color: badgeValueColor, fontWeight: FontWeight.w600);

      textView = Text("$badgeValue", style: badgeValueStyle);
      return textView;
    }

    //Badge view for both android ios
    Widget badgeView = Row(
      mainAxisSize: MainAxisSize.min,
      children: [
        Container(
          margin: margin,
          padding: padding,
          decoration: badgeDecorationStyle(),
          child: Align(
            alignment: Alignment.center,
            child: buildTextBadge(badgeValue: this.badgeValue),
          ),
        )
      ],
    );
    return badgeValue == "-1"
        ? Container()
        : InkWell(
            onTap: () {
              if (onChanged != null) {
                onChanged();
              }
            },
            child: Padding(
              padding: padding,
              child: badgeView,
            ),
          );
  }
}
				
			

Buttons

Buttons are the graphical element that taking actions and many more. Buttons can be display text, icon, or both.

Use the Buttons if:

  • If taking simple actions through the graphical element.

Do not Use the Buttons if:

  • If required multiple actions from the user in the App

Precautions:

  • Keep always the size of the button and style according to the contents.

# Usage

Buttons
Create buttons_page.dart file and paste the below code and call this file in your main.dart file.

First .dart file > buttons_page.dart (New)

				
					import 'dart:io';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:fullter_main_app/src/api_calling/api_constant.dart';
import 'package:fullter_main_app/src/widgets/android_ios_check_box.dart';
import 'package:fullter_main_app/src/widgets/badge.dart';
import 'package:fullter_main_app/src/widgets/button_clear_with_outline.dart';
import 'package:fullter_main_app/src/widgets/button_solid.dart';
import 'package:fullter_main_app/src/widgets/button_solid_with_outline.dart';
import 'package:fullter_main_app/src/widgets/dividerListCustom.dart';

class ButtonsPage extends StatefulWidget {
  ButtonsPage({Key key}) : super(key: key);
  @override
  _ButtonsPageState createState() => _ButtonsPageState();
}

class _ButtonsPageState extends State<ButtonsPage> {
  Widget buttonView = Column(
    children: [
      ButtonSolid(
        isAndroid: ConstantC.isAndroidPlatform,
        title: "Default",
      ),
      ButtonSolid(
        isAndroid: ConstantC.isAndroidPlatform,
        buttonExpandedType: ButtonExpandedType.BLOCK_WIDTH,
        buttonSize: ButtonSize.LARGE_SIZE,
        title: "Large Size",
      ),
      ButtonSolid(
        isAndroid: ConstantC.isAndroidPlatform,
        buttonExpandedType: ButtonExpandedType.DEFAULT_WIDTH,
        buttonSize: ButtonSize.LARGE_SIZE,
        title: "Large Size Default width",
      ),
      ButtonSolid(
        isAndroid: ConstantC.isAndroidPlatform,
        buttonExpandedType: ButtonExpandedType.DEFAULT_WIDTH,
        buttonSize: ButtonSize.SMALL_SIZE,
        title: "Small",
      ),
      ButtonSolid(
        isAndroid: ConstantC.isAndroidPlatform,
        buttonExpandedType: ButtonExpandedType.FULL_WITH,
        buttonSize: ButtonSize.SMALL_SIZE,
        title: "Small",
      )
    ],
  );

  Widget buttonClearView = Column(
    children: [
      ButtonClearWithOutline(
        isAndroid: ConstantC.isAndroidPlatform,
        title: "Default",
      ),
      ButtonClearWithOutline(
        isAndroid: ConstantC.isAndroidPlatform,
        buttonExpandedType: ButtonExpandedTypeClear.BLOCK_WIDTH,
        buttonSize: ButtonSizeClear.LARGE_SIZE,
        title: "Large Size",
      ),
      ButtonClearWithOutline(
        isAndroid: ConstantC.isAndroidPlatform,
        buttonExpandedType: ButtonExpandedTypeClear.DEFAULT_WIDTH,
        buttonSize: ButtonSizeClear.LARGE_SIZE,
        title: "Large Size Default width",
      ),
      ButtonClearWithOutline(
        isAndroid: ConstantC.isAndroidPlatform,
        buttonExpandedType: ButtonExpandedTypeClear.DEFAULT_WIDTH,
        buttonSize: ButtonSizeClear.SMALL_SIZE,
        title: "Small",
      ),
      ButtonClearWithOutline(
        isAndroid: ConstantC.isAndroidPlatform,
        buttonExpandedType: ButtonExpandedTypeClear.FULL_WITH,
        buttonSize: ButtonSizeClear.SMALL_SIZE,
        title: "Small",
      )
    ],
  );

  Widget buttonSolidWithBorderView = Column(
    children: [
      ButtonSolidWithOutLine(
        Colors.grey,
        title: "Default",
      ),
      ButtonSolidWithOutLine(
        Colors.red,
        borderWidth: 2,
        buttonExpandedType: ButtonExpandedTypeSolidOutline.BLOCK_WIDTH,
        buttonSizeType: ButtonSizeTypeSolidOutline.LARGE_SIZE,
        title: "Large Size",
      ),
      ButtonSolidWithOutLine(
        Colors.grey,
        buttonExpandedType: ButtonExpandedTypeSolidOutline.DEFAULT_WIDTH,
        buttonSizeType: ButtonSizeTypeSolidOutline.LARGE_SIZE,
        title: "Large Size Default width",
      ),
      ButtonSolidWithOutLine(
        Colors.orange,
        borderWidth: 2,
        buttonExpandedType: ButtonExpandedTypeSolidOutline.DEFAULT_WIDTH,
        buttonSizeType: ButtonSizeTypeSolidOutline.SMALL_SIZE,
        title: "Small",
      ),
      ButtonSolidWithOutLine(
        Colors.green,
        borderWidth: 4,
        buttonExpandedType: ButtonExpandedTypeSolidOutline.FULL_WITH,
        buttonSizeType: ButtonSizeTypeSolidOutline.LARGE_SIZE,
        title: "Full With",
      )
    ],
  );
  List<HeaderListModel> listData = [];
  @override
  void dispose() {
    // TODO: implement dispose
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    listData = [
      HeaderListModel(
          isHeaderRow: true, listRowData: {'title': "Solid button"}),
      HeaderListModel(
          isHeaderRow: false,
          listRowData: {'title': "Solid button", 'button_type': 'solid'}),
      HeaderListModel(
          isHeaderRow: false,
          listRowData: {'title': "Solid button", 'button_type': 'solid'}),
      HeaderListModel(
          isHeaderRow: false,
          listRowData: {'title': "Solid button", 'button_type': 'solid'}),
      HeaderListModel(
          isHeaderRow: false,
          listRowData: {'title': "Solid button", 'button_type': 'solid'}),
      HeaderListModel(
          isHeaderRow: true,
          listRowData: {'title': "Solid button with border"}),
      HeaderListModel(isHeaderRow: false, listRowData: {
        'title': "Solid button with border",
        'button_type': 'solid_with_boarder'
      }),
      HeaderListModel(isHeaderRow: false, listRowData: {
        'title': "Solid button with border",
        'button_type': 'solid_with_boarder'
      }),
      HeaderListModel(isHeaderRow: false, listRowData: {
        'title': "Solid button with border",
        'button_type': 'solid_with_boarder'
      }),
      HeaderListModel(isHeaderRow: false, listRowData: {
        'title': "Solid button with border",
        'button_type': 'solid_with_boarder'
      }),
      HeaderListModel(isHeaderRow: false, listRowData: {
        'title': "Solid button with border",
        'button_type': 'solid_with_boarder'
      }),
      HeaderListModel(
          isHeaderRow: true, listRowData: {'title': "Out border button"}),
      HeaderListModel(isHeaderRow: false, listRowData: {
        'title': "Out border button",
        'button_type': 'out_boarder'
      }),
      HeaderListModel(isHeaderRow: false, listRowData: {
        'title': "Out border button",
        'button_type': 'out_boarder'
      }),
      HeaderListModel(isHeaderRow: false, listRowData: {
        'title': "Out border button",
        'button_type': 'out_boarder'
      }),
      HeaderListModel(isHeaderRow: false, listRowData: {
        'title': "Out border button",
        'button_type': 'out_boarder'
      }),
      HeaderListModel(isHeaderRow: false, listRowData: {
        'title': "Out border button",
        'button_type': 'out_boarder'
      }),
    ];

    //List child head
    Widget listItemHead({String item, int index}) {
      Widget tempRowView = Container(
        color: Colors.blueGrey.withOpacity(0.2),
        height: 45,
        width: double.infinity,
        padding: EdgeInsets.symmetric(horizontal: 15, vertical: 5),
        child: Align(alignment: Alignment.centerLeft, child: Text("$item")),
      );
      return tempRowView;
    }

    //Center View
    Widget _centerView() {
      return Container(
        margin: EdgeInsets.symmetric(horizontal: 10),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          mainAxisAlignment: MainAxisAlignment.start,
          mainAxisSize: MainAxisSize.min,
          children: <Widget>[
            AndroidIosCheckbox(
              onChanged: () {
                setState(() {});
              },
            ),
            Column(
              children: [
                listItemHead(item: "Solid Button"),
                buttonView,
                SizedBox(
                  height: 10,
                ),
                listItemHead(item: "Solid Button With Out Line"),
                buttonSolidWithBorderView,
                SizedBox(
                  height: 10,
                ),
                listItemHead(item: "Button With Out Line"),
                buttonClearView
              ],
            )
          ],
        ),
      );
    }

    //Back Press
    _onBackPressed() {
      print("ok");
      Navigator.pop(context);
      print("ok");
    }

    return WillPopScope(
        onWillPop: _onBackPressed,
        child: Container(
            color: Colors.transparent,
            child: SafeArea(
                bottom: false,
                child: Scaffold(
                  backgroundColor: Colors.white,
                  //appBar:_appBar(),
                  body: Container(
                    color: Colors.white,
                    child: SingleChildScrollView(
                        physics: BouncingScrollPhysics(),
                        dragStartBehavior: DragStartBehavior.down,
                        child: _centerView()),
                  ),
                ))));
  }
}
				
			








Solid Button

Create button_solid.dart file and paste the below code
Second .dart file > button_solid.dart

Mobile Screen View


				
					import 'dart:io';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

enum ButtonSize { SMALL_SIZE, DEFAULT_SIZE, LARGE_SIZE }

enum ButtonExpandedType { DEFAULT_WIDTH, BLOCK_WIDTH, FULL_WITH }

enum ButtonColorType {
  PRIMARY,
  SECONDARY,
  TERTIARY,
  SUCCESS,
  WARNINGS,
  DANGER,
  LIGHT,
  MEDIUM,
  DARK
}

class ButtonSolid extends StatelessWidget {
  ButtonSolid({
    Key key,
    @required this.onPressed,
    this.title = 'DONE',
    this.width = 0.0,
    this.height = 0.0,
    this.borderWidth = 0.0,
    this.btnBgColor,
    this.textStyle,
    this.btnShape,
    this.elevation = 0.0,
    this.showEffect = true,
    this.btnPadding,
    this.isAndroid = true,
    this.buttonSize = ButtonSize.DEFAULT_SIZE,
    this.buttonExpandedType = ButtonExpandedType.DEFAULT_WIDTH,
    this.buttonColorType = ButtonColorType.PRIMARY,
  }) : super(key: key);

  final GestureTapCallback onPressed;
  final String title;
  final double width;
  final double height;
  final double borderWidth;
  final Color btnBgColor;
  final TextStyle textStyle;
  final bool showEffect;
  final ShapeBorder btnShape;
  final double elevation;
  final EdgeInsetsGeometry btnPadding;
  final bool isAndroid;
  final ButtonSize buttonSize;
  final ButtonExpandedType buttonExpandedType;
  final ButtonColorType buttonColorType;

  @override
  Widget build(BuildContext context) {
    /*bool isAndroid = false;
    //Check device platform
    if (Platform.isIOS) {
      isAndroid = false;
    } else if (Platform.isAndroid) {
      isAndroid = true;
    }*/

    Color fillColor() {
      Color badgeBackgroundColorTemp = Color(0xff3880ff);
      switch (this.buttonColorType) {
        case ButtonColorType.SECONDARY:
          badgeBackgroundColorTemp = Color(0xff3dc2ff);
          break;
        case ButtonColorType.TERTIARY:
          badgeBackgroundColorTemp = Color(0xff5260ff);
          break;
        case ButtonColorType.SUCCESS:
          badgeBackgroundColorTemp = Color(0xff2dd36f);
          break;
        case ButtonColorType.WARNINGS:
          badgeBackgroundColorTemp = Color(0xffffc409);
          break;
        case ButtonColorType.DANGER:
          badgeBackgroundColorTemp = Color(0xffeb445a);
          break;
        case ButtonColorType.LIGHT:
          badgeBackgroundColorTemp = Color(0xfff4f5f8);
          break;
        case ButtonColorType.MEDIUM:
          badgeBackgroundColorTemp = Color(0xff92949c);
          break;
        case ButtonColorType.DARK:
          badgeBackgroundColorTemp = Color(0xff222428);
          break;
        default:
          badgeBackgroundColorTemp = Color(0xff3880ff);
          break;
      }

      badgeBackgroundColorTemp =
          btnBgColor != null ? btnBgColor : badgeBackgroundColorTemp;
      return badgeBackgroundColorTemp;
    }

    //ButtonSolid text style
    Text buildTextBadge({String buttonValue}) {
      Text textView;
      double textSize = buttonSize == ButtonSize.LARGE_SIZE ? 18 : 16;
      Color badgeValueColor = Colors.white;
      //Set badge text color according selected badge
      TextStyle badgeValueStyle = this.textStyle != null
          ? this.textStyle
          : TextStyle(
              fontSize: textSize,
              color: badgeValueColor,
              fontWeight: FontWeight.w600);

      textView = Text("$buttonValue", style: badgeValueStyle);
      return textView;
    }

    // ButtonSolid width/height
    BoxConstraints constraints() {
      double widthTemp = double.maxFinite;
      double heightTemp = 47.0;
      if (buttonExpandedType == ButtonExpandedType.BLOCK_WIDTH) {
        widthTemp = double.maxFinite;
        switch (buttonSize) {
          case ButtonSize.SMALL_SIZE:
            heightTemp = 35;
            break;
          case ButtonSize.LARGE_SIZE:
            heightTemp = 57.0;
            break;
          default:
            heightTemp = 45.0;
        }
      } else if (buttonExpandedType == ButtonExpandedType.FULL_WITH) {
        widthTemp = double.maxFinite;
        heightTemp = 47.0;
      }
      //Set user specific custom height
      if (width > 0.0) {
        widthTemp = width;
      }
      if (height > 0.0) {
        heightTemp = height;
      }
      return (buttonExpandedType == ButtonExpandedType.DEFAULT_WIDTH)
          ? BoxConstraints()
          : BoxConstraints.expand(width: widthTemp, height: heightTemp);
    }

    // ButtonSolid Out Side Padding
    EdgeInsetsGeometry buttonOutSidePadding() {
      double paddingHorizontal = 0.0;
      double paddingVertical = 0.0;
      if (buttonExpandedType == ButtonExpandedType.DEFAULT_WIDTH) {
        switch (buttonSize) {
          case ButtonSize.SMALL_SIZE:
            paddingHorizontal = 8;
            paddingVertical = 5;
            break;
          case ButtonSize.LARGE_SIZE:
            paddingHorizontal = 8;
            paddingVertical = 15;
            break;
          default:
            paddingHorizontal = 8;
            paddingVertical = 8;
        }
      } else if (buttonExpandedType == ButtonExpandedType.BLOCK_WIDTH) {
        paddingHorizontal = 15.0;
      } else if (buttonExpandedType == ButtonExpandedType.FULL_WITH) {
        paddingHorizontal = 5.0;
      }
      return EdgeInsets.symmetric(
          horizontal: paddingHorizontal, vertical: paddingVertical);
    }

    EdgeInsetsGeometry buttonInSidePadding() {
      double paddingHorizontal = 0.0;
      double paddingVertical = 0.0;
      if (buttonExpandedType == ButtonExpandedType.DEFAULT_WIDTH) {
        switch (buttonSize) {
          case ButtonSize.SMALL_SIZE:
            paddingHorizontal = 8;
            paddingVertical = 5;
            break;
          case ButtonSize.LARGE_SIZE:
            paddingHorizontal = 8;
            paddingVertical = 15;
            break;
          default:
            paddingHorizontal = 8;
            paddingVertical = 8;
        }
      } else if (buttonExpandedType == ButtonExpandedType.BLOCK_WIDTH) {
        paddingHorizontal = 5.0;
      }
      return EdgeInsets.symmetric(
          horizontal: paddingHorizontal, vertical: paddingVertical);
    }

    ShapeBorder buttonShape() {
      double radius = 10.0;
      if (buttonExpandedType == ButtonExpandedType.FULL_WITH) {
        radius = 0;
      }
      return btnShape != null
          ? btnShape
          : RoundedRectangleBorder(borderRadius: BorderRadius.circular(radius));
    }

    double elevationGet() {
      double elevationTemp = 0;
      if (elevation > 0) {
        elevationTemp = elevation;
      } else {
        //Set elevation for android platform
        if (isAndroid) {
          elevationTemp = 4;
        }
      }
      return elevationTemp;
    }

    return Padding(
      padding: buttonOutSidePadding(),
      child: RawMaterialButton(
        elevation: elevationGet(),
        highlightColor: fillColor(),
        fillColor: fillColor(),
        splashColor: fillColor(),
        constraints: constraints(),
        shape: buttonShape(),
        child: Padding(
          padding: btnPadding == null ? buttonInSidePadding() : btnPadding,
          child: Row(
            mainAxisSize: MainAxisSize.min,
            children: [
              /*Icon(
    newicon!=null ? newicon : Icons.help,
    color: iconColor!=null ? iconColor: Colors.amber,
    ),SizedBox(
                width: 8,
              ),*/
              buildTextBadge(buttonValue: title),
            ],
          ),
        ),
        onPressed: () => onPressed,
      ),
    );
  }
}
				
			




Solid Button With-outline
Create button_solid_with_outline.dart file and paste the below code
Second .dart file > button_solid_with_outline.dart

Mobile Screen View


				
					import 'dart:io';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

enum ButtonSizeTypeSolidOutline { SMALL_SIZE, DEFAULT_SIZE, LARGE_SIZE }

enum ButtonExpandedTypeSolidOutline { DEFAULT_WIDTH, BLOCK_WIDTH, FULL_WITH }

enum ButtonColorTypeSolidOutline {
  PRIMARY,
  SECONDARY,
  TERTIARY,
  SUCCESS,
  WARNINGS,
  DANGER,
  LIGHT,
  MEDIUM,
  DARK
}

class ButtonSolidWithOutLine extends StatelessWidget {
  ButtonSolidWithOutLine(
    this.borderColor, {
    Key key,
    @required this.onPressed,
    this.title = 'DONE',
    this.width = 0.0,
    this.height = 0.0,
    this.borderWidth = 0.0,
    this.btnBgColor,
    this.textStyle,
    this.btnShape,
    this.elevation = 0.0,
    this.showEffect = true,
    this.btnPadding,
    this.isAndroid = true,
    this.buttonSizeType = ButtonSizeTypeSolidOutline.DEFAULT_SIZE,
    this.buttonExpandedType = ButtonExpandedTypeSolidOutline.DEFAULT_WIDTH,
    this.buttonColorType = ButtonColorTypeSolidOutline.PRIMARY,
  }) : super(key: key);

  final GestureTapCallback onPressed;

  final String title;
  final double width;
  final double height;
  final double borderWidth;
  final Color btnBgColor;
  final Color borderColor;
  final TextStyle textStyle;
  final bool showEffect;
  final ShapeBorder btnShape;
  final double elevation;
  final EdgeInsetsGeometry btnPadding;
  final bool isAndroid;
  final ButtonSizeTypeSolidOutline buttonSizeType;
  final ButtonExpandedTypeSolidOutline buttonExpandedType;
  final ButtonColorTypeSolidOutline buttonColorType;

  @override
  Widget build(BuildContext context) {
    bool isAndroid = false;
    //Check device platform
    if (Platform.isIOS) {
      isAndroid = false;
    } else if (Platform.isAndroid) {
      isAndroid = true;
    }

    Color fillColor() {
      Color badgeBackgroundColorTemp = Color(0xff3880ff);
      switch (this.buttonColorType) {
        case ButtonColorTypeSolidOutline.SECONDARY:
          badgeBackgroundColorTemp = Color(0xff3dc2ff);
          break;
        case ButtonColorTypeSolidOutline.TERTIARY:
          badgeBackgroundColorTemp = Color(0xff5260ff);
          break;
        case ButtonColorTypeSolidOutline.SUCCESS:
          badgeBackgroundColorTemp = Color(0xff2dd36f);
          break;
        case ButtonColorTypeSolidOutline.WARNINGS:
          badgeBackgroundColorTemp = Color(0xffffc409);
          break;
        case ButtonColorTypeSolidOutline.DANGER:
          badgeBackgroundColorTemp = Color(0xffeb445a);
          break;
        case ButtonColorTypeSolidOutline.LIGHT:
          badgeBackgroundColorTemp = Color(0xfff4f5f8);
          break;
        case ButtonColorTypeSolidOutline.MEDIUM:
          badgeBackgroundColorTemp = Color(0xff92949c);
          break;
        case ButtonColorTypeSolidOutline.DARK:
          badgeBackgroundColorTemp = Color(0xff222428);
          break;
        default:
          badgeBackgroundColorTemp = Color(0xff3880ff);
          break;
      }

      badgeBackgroundColorTemp =
          btnBgColor != null ? btnBgColor : badgeBackgroundColorTemp;
      return badgeBackgroundColorTemp;
    }

    //buttonSolidWithOutLine text style
    Text buildTextBadge({String buttonValue}) {
      Text textView;
      double textSize =
          buttonSizeType == ButtonSizeTypeSolidOutline.LARGE_SIZE ? 18 : 16;
      Color badgeValueColor = Colors.white;
      //Set badge text color according selected badge
      TextStyle badgeValueStyle = this.textStyle != null
          ? this.textStyle
          : TextStyle(
              fontSize: textSize,
              color: badgeValueColor,
              fontWeight: FontWeight.w600);

      textView = Text("$buttonValue", style: badgeValueStyle);
      return textView;
    }

    // buttonSolidWithOutLine width/height
    BoxConstraints constraints() {
      double widthTemp = 120.0;
      double heightTemp = 47.0;
      /*if (buttonExpandedType == ButtonExpandedTypeSolidOutline.DEFAULT_WIDTH) {
        switch (buttonSizeType) {
          case ButtonSizeTypeSolidOutline.SMALL_SIZE:
            widthTemp = double.minPositive;
            heightTemp = 35;
            break;
          case ButtonSizeTypeSolidOutline.LARGE_SIZE:
            widthTemp = double.maxFinite;
            heightTemp = 57.0;
            break;
          default:
            widthTemp = 120;
            heightTemp = 45.0;
        }
      }*/
      if (buttonExpandedType == ButtonExpandedTypeSolidOutline.BLOCK_WIDTH) {
        widthTemp = double.maxFinite;
        switch (buttonSizeType) {
          case ButtonSizeTypeSolidOutline.SMALL_SIZE:
            heightTemp = 35;
            break;
          case ButtonSizeTypeSolidOutline.LARGE_SIZE:
            heightTemp = 57.0;
            break;
          default:
            heightTemp = 45.0;
        }
      } else if (buttonExpandedType ==
          ButtonExpandedTypeSolidOutline.FULL_WITH) {
        widthTemp = double.maxFinite;
        heightTemp = 47.0;
      }
      //Set user specific custom height
      if (width > 0.0) {
        widthTemp = width;
      }
      if (height > 0.0) {
        heightTemp = height;
      }
      return (buttonExpandedType ==
              ButtonExpandedTypeSolidOutline.DEFAULT_WIDTH)
          ? BoxConstraints()
          : BoxConstraints.expand(width: widthTemp, height: heightTemp);
    }

    // buttonSolidWithOutLine Out Side Padding
    EdgeInsetsGeometry buttonOutSidePadding() {
      double paddingHorizontal = 0.0;
      double paddingVertical = 0.0;
      if (buttonExpandedType == ButtonExpandedTypeSolidOutline.DEFAULT_WIDTH) {
        switch (buttonSizeType) {
          case ButtonSizeTypeSolidOutline.SMALL_SIZE:
            paddingHorizontal = 8;
            paddingVertical = 5;
            break;
          case ButtonSizeTypeSolidOutline.LARGE_SIZE:
            paddingHorizontal = 8;
            paddingVertical = 15;
            break;
          default:
            paddingHorizontal = 8;
            paddingVertical = 8;
        }
      } else if (buttonExpandedType ==
          ButtonExpandedTypeSolidOutline.BLOCK_WIDTH) {
        paddingHorizontal = 15.0;
      } else if (buttonExpandedType ==
          ButtonExpandedTypeSolidOutline.FULL_WITH) {
        paddingHorizontal = 5.0;
      }
      return EdgeInsets.symmetric(
          horizontal: paddingHorizontal, vertical: paddingVertical);
    }

    EdgeInsetsGeometry buttonInSidePadding() {
      double paddingHorizontal = 0.0;
      double paddingVertical = 0.0;
      if (buttonExpandedType == ButtonExpandedTypeSolidOutline.DEFAULT_WIDTH) {
        switch (buttonSizeType) {
          case ButtonSizeTypeSolidOutline.SMALL_SIZE:
            paddingHorizontal = 8;
            paddingVertical = 5;
            break;
          case ButtonSizeTypeSolidOutline.LARGE_SIZE:
            paddingHorizontal = 8;
            paddingVertical = 15;
            break;
          default:
            paddingHorizontal = 8;
            paddingVertical = 8;
        }
      } else if (buttonExpandedType ==
          ButtonExpandedTypeSolidOutline.BLOCK_WIDTH) {
        paddingHorizontal = 5.0;
      }
      return EdgeInsets.symmetric(
          horizontal: paddingHorizontal, vertical: paddingVertical);
    }

    ShapeBorder buttonShape() {
      double radius = 10.0;
      double borderWidthTemp =
          borderColor != null ? (borderWidth > 0 ? borderWidth : 1.0) : 0.0;
      Color borderColorTemp =
          borderColor != null ? borderColor : Colors.transparent;
      if (buttonExpandedType == ButtonExpandedTypeSolidOutline.FULL_WITH) {
        radius = 0;
      }
      return btnShape != null
          ? btnShape
          : RoundedRectangleBorder(
              borderRadius: BorderRadius.circular(radius),
              side: BorderSide(width: borderWidthTemp, color: borderColorTemp));
    }

    double elevationGet() {
      double elevationTemp = 0;
      if (elevation > 0) {
        elevationTemp = elevation;
      } else {
        //Set elevation for android platform
        if (isAndroid) {
          elevationTemp = 4;
        }
      }
      return elevationTemp;
    }

    return Padding(
      padding: buttonOutSidePadding(),
      child: RawMaterialButton(
        elevation: elevationGet(),
        highlightColor: fillColor(),
        fillColor: fillColor(),
        splashColor: fillColor(),
        constraints: constraints(),
        shape: buttonShape(),
        child: Padding(
          padding: btnPadding == null ? buttonInSidePadding() : btnPadding,
          child: Row(
            mainAxisSize: MainAxisSize.min,
            children: [
              buildTextBadge(buttonValue: title),
            ],
          ),
        ),
        onPressed: () => onPressed,
      ),
    );
  }
}
				
			

 

Clear Button With-outline
Create button_clear_with_outline.dart file and paste the below code
Second .dart file > button_clear_with_outline.dart

Mobile Screen View


				
					import 'dart:io';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

enum ButtonSizeClear { SMALL_SIZE, DEFAULT_SIZE, LARGE_SIZE }

enum ButtonExpandedTypeClear { DEFAULT_WIDTH, BLOCK_WIDTH, FULL_WITH }

enum ButtonColorTypeClear {
  PRIMARY,
  SECONDARY,
  TERTIARY,
  SUCCESS,
  WARNINGS,
  DANGER,
  LIGHT,
  MEDIUM,
  DARK
}

class ButtonClearWithOutline extends StatelessWidget {
  ButtonClearWithOutline({
    Key key,
    @required this.onPressed,
    this.borderColor,
    this.title = 'DONE',
    this.width = 0.0,
    this.height = 0.0,
    this.borderWidth = 0.0,
    this.textStyle,
    this.btnShape,
    this.btnPadding,
    this.isAndroid = true,
    this.buttonSize = ButtonSizeClear.DEFAULT_SIZE,
    this.buttonExpandedType = ButtonExpandedTypeClear.DEFAULT_WIDTH,
    this.buttonColorType = ButtonColorTypeClear.PRIMARY,
  }) : super(key: key);

  final GestureTapCallback onPressed;

  final String title;
  final double width;
  final double height;
  final double borderWidth;
  final Color borderColor;
  final TextStyle textStyle;
  final ShapeBorder btnShape;
  final EdgeInsetsGeometry btnPadding;
  final bool isAndroid;
  final ButtonSizeClear buttonSize;
  final ButtonExpandedTypeClear buttonExpandedType;
  final ButtonColorTypeClear buttonColorType;

  @override
  Widget build(BuildContext context) {
    /* bool isAndroid = false;
    //Check device platform
    if (Platform.isIOS) {
      isAndroid = false;
    } else if (Platform.isAndroid) {
      isAndroid = true;
    }*/

    Color borderColorGet() {
      Color borderColorTemp = Color(0xff3880ff);
      switch (this.buttonColorType) {
        case ButtonColorTypeClear.SECONDARY:
          borderColorTemp = Color(0xff3dc2ff);
          break;
        case ButtonColorTypeClear.TERTIARY:
          borderColorTemp = Color(0xff5260ff);
          break;
        case ButtonColorTypeClear.SUCCESS:
          borderColorTemp = Color(0xff2dd36f);
          break;
        case ButtonColorTypeClear.WARNINGS:
          borderColorTemp = Color(0xffffc409);
          break;
        case ButtonColorTypeClear.DANGER:
          borderColorTemp = Color(0xffeb445a);
          break;
        case ButtonColorTypeClear.LIGHT:
          borderColorTemp = Color(0xfff4f5f8);
          break;
        case ButtonColorTypeClear.MEDIUM:
          borderColorTemp = Color(0xff92949c);
          break;
        case ButtonColorTypeClear.DARK:
          borderColorTemp = Color(0xff222428);
          break;
        default:
          borderColorTemp = Color(0xff3880ff);
          break;
      }

      borderColorTemp = borderColor != null ? borderColor : borderColorTemp;
      return borderColorTemp;
    }

    //ButtonClearWithOutline text style
    Text buildTextBadge({String buttonValue}) {
      Text textView;
      double textSize = buttonSize == ButtonSizeClear.LARGE_SIZE ? 18 : 16;
      Color badgeValueColor = Colors.black;
      //Set badge text color according selected badge
      TextStyle badgeValueStyle = this.textStyle != null
          ? this.textStyle
          : TextStyle(
              fontSize: textSize,
              color: badgeValueColor,
              fontWeight: FontWeight.w600);

      textView = Text("$buttonValue", style: badgeValueStyle);
      return textView;
    }

    // ButtonClearWithOutline width/height
    BoxConstraints constraints() {
      double widthTemp = 120.0;
      double heightTemp = 47.0;
      if (buttonExpandedType == ButtonExpandedTypeClear.BLOCK_WIDTH) {
        widthTemp = double.maxFinite;
        switch (buttonSize) {
          case ButtonSizeClear.SMALL_SIZE:
            heightTemp = 35;
            break;
          case ButtonSizeClear.LARGE_SIZE:
            heightTemp = 57.0;
            break;
          default:
            heightTemp = 45.0;
        }
      } else if (buttonExpandedType == ButtonExpandedTypeClear.FULL_WITH) {
        widthTemp = double.maxFinite;
        heightTemp = 47.0;
      }
      //Set user specific custom height
      if (width > 0.0) {
        widthTemp = width;
      }
      if (height > 0.0) {
        heightTemp = height;
      }
      return (buttonExpandedType == ButtonExpandedTypeClear.DEFAULT_WIDTH)
          ? BoxConstraints()
          : BoxConstraints.expand(width: widthTemp, height: heightTemp);
    }

    // ButtonClearWithOutline Out Side Padding
    EdgeInsetsGeometry buttonOutSidePadding() {
      double paddingHorizontal = 0.0;
      double paddingVertical = 0.0;
      if (buttonExpandedType == ButtonExpandedTypeClear.DEFAULT_WIDTH) {
        switch (buttonSize) {
          case ButtonSizeClear.SMALL_SIZE:
            paddingHorizontal = 8;
            paddingVertical = 5;
            break;
          case ButtonSizeClear.LARGE_SIZE:
            paddingHorizontal = 8;
            paddingVertical = 15;
            break;
          default:
            paddingHorizontal = 8;
            paddingVertical = 8;
        }
      } else if (buttonExpandedType == ButtonExpandedTypeClear.BLOCK_WIDTH) {
        paddingHorizontal = 15.0;
      } else if (buttonExpandedType == ButtonExpandedTypeClear.FULL_WITH) {
        paddingHorizontal = 5.0;
      }
      return EdgeInsets.symmetric(
          horizontal: paddingHorizontal, vertical: paddingVertical);
    }

    EdgeInsetsGeometry buttonInSidePadding() {
      double paddingHorizontal = 0.0;
      double paddingVertical = 0.0;
      if (buttonExpandedType == ButtonExpandedTypeClear.DEFAULT_WIDTH) {
        switch (buttonSize) {
          case ButtonSizeClear.SMALL_SIZE:
            paddingHorizontal = 8;
            paddingVertical = 5;
            break;
          case ButtonSizeClear.LARGE_SIZE:
            paddingHorizontal = 8;
            paddingVertical = 15;
            break;
          default:
            paddingHorizontal = 8;
            paddingVertical = 8;
        }
      } else if (buttonExpandedType == ButtonExpandedTypeClear.BLOCK_WIDTH) {
        paddingHorizontal = 5.0;
      }
      return EdgeInsets.symmetric(
          horizontal: paddingHorizontal, vertical: paddingVertical);
    }

    ShapeBorder buttonShape() {
      double radius = 10.0;

      double borderWidthTemp =
          borderColor != null ? (borderWidth > 0 ? borderWidth : 1.0) : 0.0;
      Color borderColorTemp = borderColorGet();
      if (buttonExpandedType == ButtonExpandedTypeClear.FULL_WITH) {
        radius = 0;
      }
      return btnShape != null
          ? btnShape
          : RoundedRectangleBorder(
              borderRadius: BorderRadius.circular(radius),
              side: BorderSide(width: borderWidthTemp, color: borderColorTemp));
    }

    return Padding(
      padding: buttonOutSidePadding(),
      child: RawMaterialButton(
        elevation: 0,
        highlightColor: Colors.grey,
        fillColor: Colors.transparent,
        splashColor: Colors.transparent,
        focusColor: Colors.transparent,
        hoverColor: Colors.transparent,
        constraints: constraints(),
        shape: buttonShape(),
        child: Padding(
          padding: btnPadding == null ? buttonInSidePadding() : btnPadding,
          child: Row(
            mainAxisSize: MainAxisSize.min,
            children: [
              buildTextBadge(buttonValue: title),
            ],
          ),
        ),
        onPressed: () => onPressed,
      ),
    );
  }
}
				
			

Floating Buttons

floating button generally a circular shape with an icon in its center. Basically, it appears in front of all the contents. It performs the primary or most common actions.

Use the Floating Buttons if:

  • It’s a cool and stylish way to get user’s attention to it.

Do not Use the Floating Buttons if:

  • If you required to display multiple buttons on different locations.

Precautions:

  • Only when Adopt the Floating Button if it is the most suitable way to present a screen’s primary action.

Mobile Screen View


# Usage

Floating Buttons
Create floating_button_page.dart file and paste the below code and call this file in your main.dart file.

First .dart file > floating_button_page.dart (New)

				
					import 'dart:io';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:fullter_main_app/src/api_calling/api_constant.dart';
import 'package:fullter_main_app/src/widgets/DraggableFloatingActionButton.dart';
import 'package:fullter_main_app/src/widgets/android_ios_check_box.dart';
import 'package:fullter_main_app/src/widgets/action_bottom_sheet_modal.dart';
import 'package:fullter_main_app/src/widgets/unicorndial.dart';
import 'package:fullter_main_app/src/widgets/unicorndial_new.dart';

class FloatingButtonsPage extends StatefulWidget {
  FloatingButtonsPage({Key key}) : super(key: key);
  @override
  _FloatingButtonsPageState createState() => _FloatingButtonsPageState();
}

class _FloatingButtonsPageState extends State<FloatingButtonsPage> {
  @override
  Widget build(BuildContext context) {
    var childButtons = List<UnicornButton>();
    childButtons.add(UnicornButton(
        hasLabel: true,
        labelText: "Choo choo",
        currentButton: FloatingActionButton(
          heroTag: "train",
          backgroundColor: Colors.redAccent,
          mini: true,
          child: Icon(Icons.train),
          onPressed: () {},
        )));
    childButtons.add(UnicornButton(
        currentButton: FloatingActionButton(
            heroTag: "airplane",
            backgroundColor: Colors.greenAccent,
            mini: true,
            child: Icon(Icons.airplanemode_active))));
    childButtons.add(UnicornButton(
        currentButton: FloatingActionButton(
            heroTag: "directions",
            backgroundColor: Colors.orange,
            mini: true,
            child: Icon(Icons.directions_walk))));
    childButtons.add(UnicornButton(
        currentButton: FloatingActionButton(
            heroTag: "directions",
            backgroundColor: Colors.blueAccent,
            mini: true,
            child: Icon(Icons.directions_car))));

    var childButtons1 = List<UnicornButtonNew>();
    childButtons1.add(UnicornButtonNew(
        hasLabel: true,
        labelText: "Choo choo",
        currentButton: FloatingActionButton(
          heroTag: "train",
          backgroundColor: Colors.redAccent,
          mini: true,
          child: Icon(Icons.train),
          onPressed: () {},
        )));
    childButtons1.add(UnicornButtonNew(
        currentButton: FloatingActionButton(
            heroTag: "airplane",
            backgroundColor: Colors.greenAccent,
            mini: true,
            child: Icon(Icons.airplanemode_active))));
    childButtons1.add(UnicornButtonNew(
        currentButton: FloatingActionButton(
            heroTag: "directions",
            backgroundColor: Colors.orange,
            mini: true,
            child: Icon(Icons.directions_walk))));
    childButtons1.add(UnicornButtonNew(
        currentButton: FloatingActionButton(
            heroTag: "directions",
            backgroundColor: Colors.blueAccent,
            mini: true,
            child: Icon(Icons.directions_car))));
    //Center View
    Widget _centerView() {
      return Container(
        margin: EdgeInsets.symmetric(horizontal: 10),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          mainAxisAlignment: MainAxisAlignment.start,
          mainAxisSize: MainAxisSize.min,
          children: <Widget>[
            AndroidIosCheckbox(
              onChanged: () {
                setState(() {});
              },
            ),
            /*UnicornDialer(
                backgroundColor: Color.fromRGBO(255, 255, 255, 0.6),
                parentButtonBackground: Colors.redAccent,
                orientation: UnicornOrientation.VERTICAL,
                parentButton: Icon(Icons.add),
                childButtons: childButtons),*/
            Container(
              height: 500,
              //width: 60,
              child: Stack(
                children: [
                  //R to L
                  Align(
                    alignment: Alignment.bottomRight,
                    child: UnicornDialer(
                        backgroundColor: Colors.transparent,
                        parentButtonBackground: Colors.redAccent,
                        orientation: UnicornOrientation.HORIZONTAL,
                        parentButton: Icon(Icons.chevron_left),
                        childButtons: childButtons),
                  ),
                  //B to T
                  Align(
                    alignment: Alignment.bottomLeft,
                    child: Container(
                      child: UnicornDialer(
                          backgroundColor: Colors.transparent,
                          parentButtonBackground: Colors.redAccent,
                          orientation: UnicornOrientation.VERTICAL,
                          parentButton: Icon(Icons.keyboard_arrow_up),
                          childButtons: childButtons),
                    ),
                  ),
                  //L to R
                  Align(
                    alignment: Alignment.topLeft,
                    child: UnicornDialerNew(
                      backgroundColor: Colors.transparent,
                      parentButtonBackground: Colors.blue,
                      orientation: UnicornOrientationNew.HORIZONTAL,
                      parentButton: Icon(Icons.keyboard_arrow_down),
                      childButtons: childButtons1,
                      isAlignBottomOrLeftSide: true,
                    ),
                  ),
                  //T to B
                  Align(
                    alignment: Alignment.topRight,
                    child: UnicornDialerNew(
                      backgroundColor: Colors.transparent,
                      parentButtonBackground: Colors.blue,
                      orientation: UnicornOrientationNew.VERTICAL,
                      parentButton: Icon(Icons.keyboard_arrow_down),
                      childButtons: childButtons1,
                      isAlignBottomOrLeftSide: false,
                    ),
                  ),
                  DraggableFloatingActionButton(
                      appContext: context,
                      data: 'Demo',
                      offset: new Offset(100, 100),
                      // backgroundColor: Theme.of(context).accentColor,
                      child: new Icon(
                        Icons.wb_incandescent,
                        color: Colors.yellow,
                      ))
                ],
              ),
            ),
          ],
        ),
      );
    }

    //Back Press
    _onBackPressed() {
      Navigator.pop(context);
    }

    return WillPopScope(
        onWillPop: _onBackPressed,
        child: Container(
            color: Colors.transparent,
            child: SafeArea(
                bottom: false,
                child: Scaffold(
                  //appBar:_appBar(),
                  body: Container(
                    // color: Colors.white,
                    child: Align(
                      alignment: Alignment.topCenter,
                      child: SingleChildScrollView(
                        physics: BouncingScrollPhysics(),
                        dragStartBehavior: DragStartBehavior.down,
                        child: _centerView(),
                      ),
                    ),
                  ),
                ))));
  }
}
				
			

Floating Buttons
Create floating_action_bubble.dart file and paste the below code
Second .dart file > floating_action_bubble.dart

				
					import 'package:flutter/material.dart';

class Bubble {
  const Bubble(
      {@required this.title,
      @required this.titleStyle,
      @required this.iconColor,
      @required this.bubbleColor,
      @required this.icon,
      @required this.onPress});

  final IconData icon;
  final Color iconColor;
  final Color bubbleColor;
  final Function onPress;
  final String title;
  final TextStyle titleStyle;
}

class BubbleMenu extends StatelessWidget {
  const BubbleMenu(this.item, {Key key}) : super(key: key);

  final Bubble item;

  @override
  Widget build(BuildContext context) {
    return MaterialButton(
      shape: StadiumBorder(),
      padding: EdgeInsets.only(top: 11, bottom: 13, left: 32, right: 32),
      color: item.bubbleColor,
      splashColor: Colors.grey.withOpacity(0.1),
      highlightColor: Colors.grey.withOpacity(0.1),
      elevation: 2,
      highlightElevation: 2,
      disabledColor: item.bubbleColor,
      onPressed: item.onPress,
      child: Row(
        mainAxisSize: MainAxisSize.min,
        children: <Widget>[
          item.icon != null
              ? Icon(
                  item.icon,
                  color: item.iconColor,
                )
              : Container(),
          SizedBox(
            width: 10.0,
          ),
          Text(
            item.title,
            style: item.titleStyle,
          ),
        ],
      ),
    );
  }
}

class _DefaultHeroTag {
  const _DefaultHeroTag();
  @override
  String toString() => '<default FloatingActionBubble tag>';
}

class FloatingActionBubble extends AnimatedWidget {
  const FloatingActionBubble({
    @required this.items,
    @required this.onPress,
    @required this.iconColor,
    @required this.backGroundColor,
    @required Animation animation,
    this.herotag,
    this.iconData,
    this.animatedIconData,
  })  : assert((iconData == null && animatedIconData != null) ||
            (iconData != null && animatedIconData == null)),
        super(listenable: animation);

  final List<Bubble> items;
  final Function onPress;
  final AnimatedIconData animatedIconData;
  final Object herotag;
  final IconData iconData;
  final Color iconColor;
  final Color backGroundColor;

  get _animation => listenable;

  Widget buildItem(BuildContext context, int index) {
    final screenWidth = MediaQuery.of(context).size.width;
    final screenHeight = MediaQuery.of(context).size.height;

    TextDirection textDirection =
        Directionality.of(context) ?? TextDirection.ltr;

    double animationDirection = textDirection == TextDirection.ltr ? 1 : 1;

    final transform = Matrix4.translationValues(
      0.0,
      animationDirection *
          (screenHeight - _animation.value * screenHeight) *
          ((items.length - index) / 4),
      0.0,
    );

    return Align(
      alignment: textDirection == TextDirection.ltr
          ? Alignment.centerRight
          : Alignment.centerLeft,
      child: Transform(
        transform: transform,
        child: Opacity(
          opacity: _animation.value,
          child: BubbleMenu(items[index]),
        ),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisSize: MainAxisSize.min,
      crossAxisAlignment: CrossAxisAlignment.end,
      children: [
        IgnorePointer(
          ignoring: _animation.value == 0,
          child: ListView.separated(
            shrinkWrap: true,
            physics: NeverScrollableScrollPhysics(),
            separatorBuilder: (_, __) => SizedBox(height: 12.0),
            padding: EdgeInsets.symmetric(vertical: 12),
            itemCount: items.length,
            itemBuilder: buildItem,
          ),
        ),
        FloatingActionButton(
          heroTag: herotag == null ? const _DefaultHeroTag() : herotag,
          backgroundColor: backGroundColor,
          // iconData is mutually exclusive with animatedIconData
          // only 1 can be null at the time
          child: iconData == null
              ? AnimatedIcon(
                  icon: animatedIconData,
                  progress: _animation,
                )
              : Icon(
                  iconData,
                  color: iconColor,
                ),
          onPressed: onPress,
        ),
      ],
    );
  }
}
				
			

Card View

Cards are a standard section of UI in the app that shows detailed information. A card can be a single component featured with header, title, subtitle, and content.

Use the Card View if:

  • If your content needs more style to display like an album, a geographical location, a meal, contact details, etc.

Do not use the Card View if:

  • No need to take cards if your content is too long.

Precautions:

  •  Need to use and design cards very carefully, cards can be one large touch target that shows a detailed screen when tapped.

Mobile Screen View


 

# Usage

Card View
Create card_page.dart file and paste the below code and call this file in your main.dart file.

First .dart file > card_page.dart (New)

				
					import 'dart:io';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:fullter_main_app/src/api_calling/api_constant.dart';
import 'package:fullter_main_app/src/widgets/android_ios_check_box.dart';
import 'package:fullter_main_app/src/widgets/badge.dart';
import 'package:fullter_main_app/src/widgets/button_clear_with_outline.dart';
import 'package:fullter_main_app/src/widgets/button_solid.dart';
import 'package:fullter_main_app/src/widgets/button_solid_with_outline.dart';
import 'package:fullter_main_app/src/widgets/card_view.dart';
import 'package:fullter_main_app/src/widgets/dividerListCustom.dart';

class CardPage extends StatefulWidget {
  CardPage({Key key}) : super(key: key);
  @override
  _CardPageState createState() => _CardPageState();
}

class _CardPageState extends State<CardPage> {
  @override
  void dispose() {
    // TODO: implement dispose
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    Widget cardView = CardView(
      isAndroid: ConstantC.isAndroidPlatform,
      cardType: CardType.DEFAULT,
      child: Column(
        //mainAxisSize: MainAxisSize.min,
        children: [
          Container(
            width: 300.0,
            height: 200.0,
            decoration: BoxDecoration(
              image: DecorationImage(
                  fit: BoxFit.cover,
                  image: NetworkImage(
                      'https://lh3.googleusercontent.com/RfaTa3bsm8zmVJYznMHpncW4HCNPmPf3fstlmU5hNNm-8j3Mz8nJjUj_avt1Qi0')),
              borderRadius: BorderRadius.only(
                  topLeft: Radius.circular(8.0),
                  topRight: Radius.circular(8.0)),
              color: Colors.redAccent,
            ),
          ),
          SizedBox(
            height: 20,
          ),
          Container(
            // color: Colors.green,
            child: Align(
                alignment: Alignment.centerLeft,
                child: Text('Destination'.toUpperCase(),
                    style: TextStyle(color: Colors.grey, fontSize: 14))),
          ),
          SizedBox(
            height: 0,
          ),
          Text(
            'Madison, WI',
            style: TextStyle(color: Colors.black, fontSize: 20),
            textAlign: TextAlign.start,
          ),
          SizedBox(
            height: 30,
          ),
          Text(
            'Founded in 1828 on an isthums',
            style: TextStyle(color: Colors.grey, fontSize: 15),
            textAlign: TextAlign.start,
          ),
          SizedBox(
            height: 10,
          ),
        ],
      ),
    );
    //List child head
    Widget listItemHead({String item, int index}) {
      Widget tempRowView = Container(
        color: Colors.blueGrey.withOpacity(0.2),
        height: 45,
        width: double.infinity,
        padding: EdgeInsets.symmetric(horizontal: 15, vertical: 5),
        child: Align(alignment: Alignment.centerLeft, child: Text("$item")),
      );
      return tempRowView;
    }

    //Center View
    Widget _centerView() {
      return Container(
        margin: EdgeInsets.symmetric(horizontal: 10),
        child: Column(
          //crossAxisAlignment: CrossAxisAlignment.center,
          mainAxisAlignment: MainAxisAlignment.start,
          mainAxisSize: MainAxisSize.min,
          children: <Widget>[
            AndroidIosCheckbox(
              onChanged: () {
                setState(() {});
              },
            ),
            Column(
              children: [cardView],
            )
          ],
        ),
      );
    }

    //Back Press
    _onBackPressed() {
      print("ok");
      Navigator.pop(context);
      print("ok");
    }

    return WillPopScope(
        onWillPop: _onBackPressed,
        child: Container(
            color: Colors.transparent,
            child: SafeArea(
                bottom: false,
                child: Scaffold(
                  backgroundColor: Colors.white,
                  //appBar:_appBar(),
                  body: Container(
                    color: Colors.white,
                    child: SingleChildScrollView(
                        physics: BouncingScrollPhysics(),
                        dragStartBehavior: DragStartBehavior.down,
                        child: _centerView()),
                  ),
                ))));
  }
}
				
			


Create card_view.dart file and paste the below code
Second .dart file > card_view.dart

				
					import 'dart:io';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

enum CardType {
  FULL_WIDTH, //Width always full screen with size not depends on child
  DEFAULT, //With and height accordingly child data
}

class CardView extends StatelessWidget {
  final child;
  final radius;
  final EdgeInsetsGeometry margin;
  final EdgeInsetsGeometry padding;
  final double elevation;
  final Color cardColor;
  final bool isAndroid;
  final CardType cardType;

  CardView(
      {Key key,
      @required this.child,
      this.margin,
      this.padding,
      this.radius = -1,
      this.elevation = 0.0,
      this.cardColor = Colors.white,
      this.cardType = CardType.DEFAULT,
      this.isAndroid = false})
      : super(key: key);
  @override
  Widget build(BuildContext context) {
    /*bool isAndroid = false;
    //Check device platform
    if (Platform.isIOS) {
      isAndroid = false;
    } else if (Platform.isAndroid) {
      isAndroid = true;
    }*/

    Color shadowColorTemp = Colors.white;
    //Card elevation
    double elevationGet() {
      double elevationTemp = 0;
      if (elevation > 0) {
        elevationTemp = elevation;
      } else {
        //Set elevation for android platform
        if (isAndroid) {
          elevationTemp = 2;
          shadowColorTemp = Colors.black;
        }
        //Set elevation for android platform
        else if (!isAndroid) {
          elevationTemp = 6;
          shadowColorTemp = Colors.white;
        }
      }
      return elevationTemp;
    }

    //Card shape
    ShapeBorder shape() {
      //iOS shape radius
      double radiusTemp = 8.0;
      //Android
      if (isAndroid) {
        radiusTemp = 5;
      }
      //User specific
      if (radius > -1) {
        radiusTemp = radius;
      }
      return RoundedRectangleBorder(
        borderRadius: BorderRadius.circular(radiusTemp),
      );
    }

    MainAxisSize cardWithType() {
      if (cardType == CardType.FULL_WIDTH) {
        return MainAxisSize.max;
      }
      return MainAxisSize.min;
    }

    return Card(
        color: cardColor,
        shadowColor: shadowColorTemp,
        elevation: elevationGet(),
        shape: shape(),
        margin: margin != null
            ? margin
            : EdgeInsets.symmetric(
                horizontal: isAndroid ? 16 : 16, vertical: isAndroid ? 4 : 8),
        child: Row(
          mainAxisSize: cardWithType(),
          /*crossAxisAlignment: CrossAxisAlignment.center,
          mainAxisAlignment: MainAxisAlignment.center,*/
          children: [
            Padding(
              padding: padding != null
                  ? padding
                  : EdgeInsets.symmetric(
                      horizontal: isAndroid ? 0 : 0,
                      vertical: isAndroid ? 0 : 0),
              child: child,
            ),
          ],
        ));
  }
}
				
			

Date & Time Picker

Date & Time Picker is a UI interface that makes it easy to select dates and times for Users. Generally, the picker displays scrollable columns that can be used to select years, months, days, hours, and minute values.

Use the Date & Time Picker if:

  • If you need to ask for date & time input fields from the user in a similar format.

Do not use the Date & Time Picker if:

  • If you have limited space on the screen you should avoid using the date and time picker because it occupies more space on the screen.

Precautions:

  • Need to carefully use of localization and CSS at the time of adding date & time picker on the app screen.

Mobile Screen View

Date Picker


Mobile Screen View

Time Picker


# Usage

Date & Time Picker
Create datepicker_page.dart file and paste the below code and call this file in your main.dart file.

First .dart file > datepicker_page.dart (New)

				
					import 'dart:io';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:fullter_main_app/src/api_calling/api_constant.dart';
import 'package:fullter_main_app/src/widgets/android_ios_check_box.dart';
import 'package:fullter_main_app/src/widgets/date_time_picker/date_picker_sheet.dart';

class DatePickerPage extends StatefulWidget {
  DatePickerPage({Key key}) : super(key: key);
  @override
  _DatePickerPageState createState() => _DatePickerPageState();
}

class _DatePickerPageState extends State<DatePickerPage> {
  @override
  void dispose() {
    // TODO: implement dispose
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    //List child head
    Widget listItemHead({String item, int index}) {
      Widget tempRowView = Container(
        color: Colors.blueGrey.withOpacity(0.2),
        height: 45,
        width: double.infinity,
        padding: EdgeInsets.symmetric(horizontal: 15, vertical: 5),
        child: Align(alignment: Alignment.centerLeft, child: Text("$item")),
      );
      return tempRowView;
    }

    Widget datePicker = ElevatedButton(
      child: Text('Date Picker'),
      onPressed: () {
        DatePickerBottomSheet(
          isAndroid: ConstantC.isAndroidPlatform,
          context: context,
          doneCallBack: (selectedDateTime) {
            print("$selectedDateTime");
          },
        );
      },
    );

    Widget timePicker = ElevatedButton(
      child: Text('Time Picker'),
      onPressed: () {
        DatePickerBottomSheet(
          isAndroid: ConstantC.isAndroidPlatform,
          mode: PickerType.time,
          context: context,
          doneCallBack: (selectedDateTime) {
            print("$selectedDateTime");
          },
        );
      },
    );
    //Center View
    Widget _centerView() {
      return Container(
        margin: EdgeInsets.symmetric(horizontal: 10),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          mainAxisAlignment: MainAxisAlignment.start,
          mainAxisSize: MainAxisSize.max,
          children: <Widget>[
            Center(
              child: AndroidIosCheckbox(
                onChanged: () {
                  setState(() {});
                },
              ),
            ),
            Column(
              crossAxisAlignment: CrossAxisAlignment.center,
              mainAxisAlignment: MainAxisAlignment.center,
              mainAxisSize: MainAxisSize.min,
              children: [
                SizedBox(
                  height: 10,
                ),
                datePicker,
                SizedBox(
                  height: 10,
                ),
                timePicker,
              ],
            )
          ],
        ),
      );
    }

    //Back Press
    _onBackPressed() {
      print("ok");
      Navigator.pop(context);
      print("ok");
    }

    return WillPopScope(
        onWillPop: _onBackPressed,
        child: Container(
            color: Colors.transparent,
            child: SafeArea(
                bottom: false,
                child: Scaffold(
                  backgroundColor: Colors.white,
                  //appBar:_appBar(),
                  body: Container(
                    color: Colors.white,
                    child: _centerView(),
                  ),
                ))));
  }
}
				
			


Create date_picker_custom.dart file and paste the below code
Second .dart file > date_picker_custom.dart

				
					import 'dart:math' as math;

import 'package:flutter/cupertino.dart';
import 'package:flutter/scheduler.dart';
import 'package:flutter/widgets.dart';
import 'package:fullter_main_app/src/widgets/date_time_picker/picker_custom.dart';

// Values derived from https://developer.apple.com/design/resources/ and on iOS
// simulators with "Debug View Hierarchy".
const double _kItemExtent = 32.0;
// From the picker's intrinsic content size constraint.
const double _kPickerWidth = 320.0;
const double _kPickerHeight = 216.0;
const bool _kUseMagnifier = true;
const double _kMagnification = 2.35 / 2.1;
const double _kDatePickerPadSize = 12.0;
// The density of a date picker is different from a generic picker.
// Eyeballed from iOS.
const double _kSqueeze = 1.25;

const TextStyle _kDefaultPickerTextStyle = TextStyle(
  letterSpacing: -0.83,
);

// The item height is 32 and the magnifier height is 34, from
// iOS simulators with "Debug View Hierarchy".
// And the magnified fontSize by [_kTimerPickerMagnification] conforms to the
// iOS 14 native style by eyeball test.
const double _kTimerPickerMagnification = 34 / 32;
// Minimum horizontal padding between [CupertinoTimerPicker]
//
// It shouldn't actually be hard-coded for direct use, and the perfect solution
// should be to calculate the values that match the magnified values by
// offAxisFraction and _kSqueeze.
// Such calculations are complex, so we'll hard-code them for now.
const double _kTimerPickerMinHorizontalPadding = 30;
// Half of the horizontal padding value between the timer picker's columns.
const double _kTimerPickerHalfColumnPadding = 4;
// The horizontal padding between the timer picker's number label and its
// corresponding unit label.
const double _kTimerPickerLabelPadSize = 6;
const double _kTimerPickerLabelFontSize = 17.0;

// The width of each column of the countdown time picker.
const double _kTimerPickerColumnIntrinsicWidth = 106;

TextStyle _themeTextStyle(BuildContext context, {bool isValid = true}) {
  final TextStyle style =
      CupertinoTheme.of(context).textTheme.dateTimePickerTextStyle;
  return isValid
      ? style
      : style.copyWith(
          color: CupertinoDynamicColor.resolve(
              CupertinoColors.inactiveGray, context));
}

void _animateColumnControllerToItem(
    FixedExtentScrollController controller, int targetItem) {
  controller.animateToItem(
    targetItem,
    curve: Curves.easeInOut,
    duration: const Duration(milliseconds: 200),
  );
}

Widget _leftSelectionOverlay({bool isAndroidG = false}) =>
    PickerDefaultSelectionOverlayCustom(
      capRightEdge: false,
      isAndroid: isAndroidG,
      background: isAndroidG
          ? CupertinoColors.tertiarySystemFill
          : CupertinoColors.inactiveGray,
    );
Widget _centerSelectionOverlay({bool isAndroidG = false}) =>
    PickerDefaultSelectionOverlayCustom(
      capLeftEdge: false,
      capRightEdge: false,
      isAndroid: isAndroidG,
      background: isAndroidG
          ? CupertinoColors.tertiarySystemFill
          : CupertinoColors.inactiveGray,
    );
Widget _rightSelectionOverlay({bool isAndroidG = false}) =>
    PickerDefaultSelectionOverlayCustom(
      capLeftEdge: false,
      isAndroid: isAndroidG,
      background: isAndroidG
          ? CupertinoColors.tertiarySystemFill
          : CupertinoColors.inactiveGray,
    );

// Lays out the date picker based on how much space each single column needs.
//
// Each column is a child of this delegate, indexed from 0 to number of columns - 1.
// Each column will be padded horizontally by 12.0 both left and right.
//
// The picker will be placed in the center, and the leftmost and rightmost
// column will be extended equally to the remaining width.
class _DatePickerLayoutDelegate extends MultiChildLayoutDelegate {
  _DatePickerLayoutDelegate({
    @required this.columnWidths,
    @required this.textDirectionFactor,
  })  : assert(columnWidths != null),
        assert(textDirectionFactor != null);

  // The list containing widths of all columns.
  final List<double> columnWidths;

  // textDirectionFactor is 1 if text is written left to right, and -1 if right to left.
  final int textDirectionFactor;

  @override
  void performLayout(Size size) {
    double remainingWidth = size.width;

    for (int i = 0; i < columnWidths.length; i++)
      remainingWidth -= columnWidths[i] + _kDatePickerPadSize * 2;

    double currentHorizontalOffset = 0.0;

    for (int i = 0; i < columnWidths.length; i++) {
      final int index =
          textDirectionFactor == 1 ? i : columnWidths.length - i - 1;

      double childWidth = columnWidths[index] + _kDatePickerPadSize * 2;
      if (index == 0 || index == columnWidths.length - 1)
        childWidth += remainingWidth / 2;

      // We can't actually assert here because it would break things badly for
      // semantics, which will expect that we laid things out here.
      assert(() {
        if (childWidth < 0) {
          FlutterError.reportError(
            FlutterErrorDetails(
              exception: FlutterError(
                'Insufficient horizontal space to render the '
                'DatePickerCustom because the parent is too narrow at '
                '${size.width}px.\n'
                'An additional ${-remainingWidth}px is needed to avoid '
                'overlapping columns.',
              ),
            ),
          );
        }
        return true;
      }());
      layoutChild(index,
          BoxConstraints.tight(Size(math.max(0.0, childWidth), size.height)));
      positionChild(index, Offset(currentHorizontalOffset, 0.0));

      currentHorizontalOffset += childWidth;
    }
  }

  @override
  bool shouldRelayout(_DatePickerLayoutDelegate oldDelegate) {
    return columnWidths != oldDelegate.columnWidths ||
        textDirectionFactor != oldDelegate.textDirectionFactor;
  }
}

/// Different display modes of [DatePickerCustom].
///
/// See also:
///
///  * [DatePickerCustom], the class that implements different display modes
///    of the iOS-style date picker.
///  * [CupertinoPicker], the class that implements a content agnostic spinner UI.
enum DatePickerCustomMode {
  /// Mode that shows the date in hour, minute, and (optional) an AM/PM designation.
  /// The AM/PM designation is shown only if [DatePickerCustom] does not use 24h format.
  /// Column order is subject to internationalization.
  ///
  /// Example: ` 4 | 14 | PM `.
  time,

  /// Mode that shows the date in month, day of month, and year.
  /// Name of month is spelled in full.
  /// Column order is subject to internationalization.
  ///
  /// Example: ` July | 13 | 2012 `.
  date,

  /// Mode that shows the date as day of the week, month, day of month and
  /// the time in hour, minute, and (optional) an AM/PM designation.
  /// The AM/PM designation is shown only if [DatePickerCustom] does not use 24h format.
  /// Column order is subject to internationalization.
  ///
  /// Example: ` Fri Jul 13 | 4 | 14 | PM `
  dateAndTime,
}

// Different types of column in DatePickerCustom.
enum _PickerColumnType {
  // Day of month column in date mode.
  dayOfMonth,
  // Month column in date mode.
  month,
  // Year column in date mode.
  year,
  // Medium date column in dateAndTime mode.
  date,
  // Hour column in time and dateAndTime mode.
  hour,
  // minute column in time and dateAndTime mode.
  minute,
  // AM/PM column in time and dateAndTime mode.
  dayPeriod,
}

/// A date picker widget in iOS style.
///
/// There are several modes of the date picker listed in [DatePickerCustomMode].
///
/// The class will display its children as consecutive columns. Its children
/// order is based on internationalization.
///
/// Example of the picker in date mode:
///
///  * US-English: `| July | 13 | 2012 |`
///  * Vietnamese: `| 13 | Tháng 7 | 2012 |`
///
/// Can be used with [showCupertinoModalPopup] to display the picker modally at
/// the bottom of the screen.
///
/// Sizes itself to its parent and may not render correctly if not given the
/// full screen width. Content texts are shown with
/// [CupertinoTextThemeData.dateTimePickerTextStyle].
///
/// See also:
///
///  * [CupertinoTimerPicker], the class that implements the iOS-style timer picker.
///  * [CupertinoPicker], the class that implements a content agnostic spinner UI.
class DatePickerCustom extends StatefulWidget {
  /// Constructs an iOS style date picker.
  ///
  /// [mode] is one of the mode listed in [DatePickerCustomMode] and defaults
  /// to [DatePickerCustomMode.dateAndTime].
  ///
  /// [onDateTimeChanged] is the callback called when the selected date or time
  /// changes and must not be null. When in [DatePickerCustomMode.time] mode,
  /// the year, month and day will be the same as [initialDateTime]. When in
  /// [DatePickerCustomMode.date] mode, this callback will always report the
  /// start time of the currently selected day.
  ///
  /// [initialDateTime] is the initial date time of the picker. Defaults to the
  /// present date and time and must not be null. The present must conform to
  /// the intervals set in [minimumDate], [maximumDate], [minimumYear], and
  /// [maximumYear].
  ///
  /// [minimumDate] is the minimum selectable [DateTime] of the picker. When set
  /// to null, the picker does not limit the minimum [DateTime] the user can pick.
  /// In [DatePickerCustomMode.time] mode, [minimumDate] should typically be
  /// on the same date as [initialDateTime], as the picker will not limit the
  /// minimum time the user can pick if it's set to a date earlier than that.
  ///
  /// [maximumDate] is the maximum selectable [DateTime] of the picker. When set
  /// to null, the picker does not limit the maximum [DateTime] the user can pick.
  /// In [DatePickerCustomMode.time] mode, [maximumDate] should typically be
  /// on the same date as [initialDateTime], as the picker will not limit the
  /// maximum time the user can pick if it's set to a date later than that.
  ///
  /// [minimumYear] is the minimum year that the picker can be scrolled to in
  /// [DatePickerCustomMode.date] mode. Defaults to 1 and must not be null.
  ///
  /// [maximumYear] is the maximum year that the picker can be scrolled to in
  /// [DatePickerCustomMode.date] mode. Null if there's no limit.
  ///
  /// [minuteInterval] is the granularity of the minute spinner. Must be a
  /// positive integer factor of 60.
  ///
  /// [use24hFormat] decides whether 24 hour format is used. Defaults to false.
  DatePickerCustom({
    Key key,
    this.mode = DatePickerCustomMode.dateAndTime,
    @required this.onDateTimeChanged,
    DateTime initialDateTime,
    this.minimumDate,
    this.maximumDate,
    this.minimumYear = 1,
    this.maximumYear,
    this.minuteInterval = 1,
    this.use24hFormat = false,
    this.backgroundColor,
    this.isAndroid = false,
  })  : initialDateTime = initialDateTime ?? DateTime.now(),
        assert(mode != null),
        assert(isAndroid != null),
        assert(onDateTimeChanged != null),
        assert(minimumYear != null),
        assert(
          minuteInterval > 0 && 60 % minuteInterval == 0,
          'minute interval is not a positive integer factor of 60',
        ),
        super(key: key) {
    assert(this.initialDateTime != null);
    assert(
      mode != DatePickerCustomMode.dateAndTime ||
          minimumDate == null ||
          !this.initialDateTime.isBefore(minimumDate),
      'initial date is before minimum date',
    );
    assert(
      mode != DatePickerCustomMode.dateAndTime ||
          maximumDate == null ||
          !this.initialDateTime.isAfter(maximumDate),
      'initial date is after maximum date',
    );
    assert(
      mode != DatePickerCustomMode.date ||
          (minimumYear >= 1 && this.initialDateTime.year >= minimumYear),
      'initial year is not greater than minimum year, or minimum year is not positive',
    );
    assert(
      mode != DatePickerCustomMode.date ||
          maximumYear == null ||
          this.initialDateTime.year <= maximumYear,
      'initial year is not smaller than maximum year',
    );
    assert(
      mode != DatePickerCustomMode.date ||
          minimumDate == null ||
          !minimumDate.isAfter(this.initialDateTime),
      'initial date ${this.initialDateTime} is not greater than or equal to minimumDate $minimumDate',
    );
    assert(
      mode != DatePickerCustomMode.date ||
          maximumDate == null ||
          !maximumDate.isBefore(this.initialDateTime),
      'initial date ${this.initialDateTime} is not less than or equal to maximumDate $maximumDate',
    );
    assert(
      this.initialDateTime.minute % minuteInterval == 0,
      'initial minute is not divisible by minute interval',
    );
  }

  /// The mode of the date picker as one of [DatePickerCustomMode].
  /// Defaults to [DatePickerCustomMode.dateAndTime]. Cannot be null and
  /// value cannot change after initial build.
  final DatePickerCustomMode mode;

  /// The initial date and/or time of the picker. Defaults to the present date
  /// and time and must not be null. The present must conform to the intervals
  /// set in [minimumDate], [maximumDate], [minimumYear], and [maximumYear].
  ///
  /// Changing this value after the initial build will not affect the currently
  /// selected date time.
  final DateTime initialDateTime;

  /// The minimum selectable date that the picker can settle on.
  ///
  /// When non-null, the user can still scroll the picker to [DateTime]s earlier
  /// than [minimumDate], but the [onDateTimeChanged] will not be called on
  /// these [DateTime]s. Once let go, the picker will scroll back to [minimumDate].
  ///
  /// In [DatePickerCustomMode.time] mode, a time becomes unselectable if the
  /// [DateTime] produced by combining that particular time and the date part of
  /// [initialDateTime] is earlier than [minimumDate]. So typically [minimumDate]
  /// needs to be set to a [DateTime] that is on the same date as [initialDateTime].
  ///
  /// Defaults to null. When set to null, the picker does not impose a limit on
  /// the earliest [DateTime] the user can select.
  final DateTime minimumDate;

  /// The maximum selectable date that the picker can settle on.
  ///
  /// When non-null, the user can still scroll the picker to [DateTime]s later
  /// than [maximumDate], but the [onDateTimeChanged] will not be called on
  /// these [DateTime]s. Once let go, the picker will scroll back to [maximumDate].
  ///
  /// In [DatePickerCustomMode.time] mode, a time becomes unselectable if the
  /// [DateTime] produced by combining that particular time and the date part of
  /// [initialDateTime] is later than [maximumDate]. So typically [maximumDate]
  /// needs to be set to a [DateTime] that is on the same date as [initialDateTime].
  ///
  /// Defaults to null. When set to null, the picker does not impose a limit on
  /// the latest [DateTime] the user can select.
  final DateTime maximumDate;

  /// Minimum year that the picker can be scrolled to in
  /// [DatePickerCustomMode.date] mode. Defaults to 1 and must not be null.
  final int minimumYear;

  /// Maximum year that the picker can be scrolled to in
  /// [DatePickerCustomMode.date] mode. Null if there's no limit.
  final int maximumYear;

  /// The granularity of the minutes spinner, if it is shown in the current mode.
  /// Must be an integer factor of 60.
  final int minuteInterval;

  /// Whether to use 24 hour format. Defaults to false.
  final bool use24hFormat;

  /// Callback called when the selected date and/or time changes. If the new
  /// selected [DateTime] is not valid, or is not in the [minimumDate] through
  /// [maximumDate] range, this callback will not be called.
  ///
  /// Must not be null.
  final ValueChanged<DateTime> onDateTimeChanged;

  /// Background color of date picker.
  ///
  /// Defaults to null, which disables background painting entirely.
  final Color backgroundColor;

  final bool isAndroid;

  @override
  State<StatefulWidget> createState() {
    // ignore: no_logic_in_create_state, https://github.com/flutter/flutter/issues/70499
    // The `time` mode and `dateAndTime` mode of the picker share the time
    // columns, so they are placed together to one state.
    // The `date` mode has different children and is implemented in a different
    // state.
    switch (mode) {
      case DatePickerCustomMode.time:
      case DatePickerCustomMode.dateAndTime:
        return _DatePickerCustomDateTimeState();
      case DatePickerCustomMode.date:
        return _DatePickerCustomDateState();
    }
  }

  // Estimate the minimum width that each column needs to layout its content.
  static double _getColumnWidth(
    _PickerColumnType columnType,
    CupertinoLocalizations localizations,
    BuildContext context,
  ) {
    String longestText = '';

    switch (columnType) {
      case _PickerColumnType.date:
        // Measuring the length of all possible date is impossible, so here
        // just some dates are measured.
        for (int i = 1; i <= 12; i++) {
          // An arbitrary date.
          final String date =
              localizations.datePickerMediumDate(DateTime(2018, i, 25));
          if (longestText.length < date.length) longestText = date;
        }
        break;
      case _PickerColumnType.hour:
        for (int i = 0; i < 24; i++) {
          final String hour = localizations.datePickerHour(i);
          if (longestText.length < hour.length) longestText = hour;
        }
        break;
      case _PickerColumnType.minute:
        for (int i = 0; i < 60; i++) {
          final String minute = localizations.datePickerMinute(i);
          if (longestText.length < minute.length) longestText = minute;
        }
        break;
      case _PickerColumnType.dayPeriod:
        longestText = localizations.anteMeridiemAbbreviation.length >
                localizations.postMeridiemAbbreviation.length
            ? localizations.anteMeridiemAbbreviation
            : localizations.postMeridiemAbbreviation;
        break;
      case _PickerColumnType.dayOfMonth:
        for (int i = 1; i <= 31; i++) {
          final String dayOfMonth = localizations.datePickerDayOfMonth(i);
          if (longestText.length < dayOfMonth.length) longestText = dayOfMonth;
        }
        break;
      case _PickerColumnType.month:
        for (int i = 1; i <= 12; i++) {
          final String month = localizations.datePickerMonth(i);
          if (longestText.length < month.length) longestText = month;
        }
        break;
      case _PickerColumnType.year:
        longestText = localizations.datePickerYear(2018);
        break;
    }

    assert(longestText != '', 'column type is not appropriate');

    final TextPainter painter = TextPainter(
      text: TextSpan(
        style: _themeTextStyle(context),
        text: longestText,
      ),
      textDirection: Directionality.of(context),
    );

    // This operation is expensive and should be avoided. It is called here only
    // because there's no other way to get the information we want without
    // laying out the text.
    painter.layout();

    return painter.maxIntrinsicWidth;
  }
}

typedef _ColumnBuilder = Widget Function(double offAxisFraction,
    TransitionBuilder itemPositioningBuilder, Widget selectionOverlay);

class _DatePickerCustomDateTimeState extends State<DatePickerCustom> {
  // Fraction of the farthest column's vanishing point vs its width. Eyeballed
  // vs iOS.
  static const double _kMaximumOffAxisFraction = 0.45;

  int textDirectionFactor;
  CupertinoLocalizations localizations;

  // Alignment based on text direction. The variable name is self descriptive,
  // however, when text direction is rtl, alignment is reversed.
  Alignment alignCenterLeft;
  Alignment alignCenterRight;

  // Read this out when the state is initially created. Changes in initialDateTime
  // in the widget after first build is ignored.
  DateTime initialDateTime;

  // The difference in days between the initial date and the currently selected date.
  // 0 if the current mode does not involve a date.
  int get selectedDayFromInitial {
    switch (widget.mode) {
      case DatePickerCustomMode.dateAndTime:
        return dateController.hasClients ? dateController.selectedItem : 0;
      case DatePickerCustomMode.time:
        return 0;
      case DatePickerCustomMode.date:
        break;
    }
    assert(
      false,
      '$runtimeType is only meant for dateAndTime mode or time mode',
    );
    return 0;
  }

  // The controller of the date column.
  FixedExtentScrollController dateController;

  // The current selection of the hour picker. Values range from 0 to 23.
  int get selectedHour => _selectedHour(selectedAmPm, _selectedHourIndex);
  int get _selectedHourIndex => hourController.hasClients
      ? hourController.selectedItem % 24
      : initialDateTime.hour;
  // Calculates the selected hour given the selected indices of the hour picker
  // and the meridiem picker.
  int _selectedHour(int selectedAmPm, int selectedHour) {
    return _isHourRegionFlipped(selectedAmPm)
        ? (selectedHour + 12) % 24
        : selectedHour;
  }

  // The controller of the hour column.
  FixedExtentScrollController hourController;

  // The current selection of the minute picker. Values range from 0 to 59.
  int get selectedMinute {
    return minuteController.hasClients
        ? minuteController.selectedItem * widget.minuteInterval % 60
        : initialDateTime.minute;
  }

  // The controller of the minute column.
  FixedExtentScrollController minuteController;

  // Whether the current meridiem selection is AM or PM.
  //
  // We can't use the selectedItem of meridiemController as the source of truth
  // because the meridiem picker can be scrolled **animatedly** by the hour picker
  // (e.g. if you scroll from 12 to 1 in 12h format), but the meridiem change
  // should take effect immediately, **before** the animation finishes.
  int selectedAmPm;
  // Whether the physical-region-to-meridiem mapping is flipped.
  bool get isHourRegionFlipped => _isHourRegionFlipped(selectedAmPm);
  bool _isHourRegionFlipped(int selectedAmPm) => selectedAmPm != meridiemRegion;
  // The index of the 12-hour region the hour picker is currently in.
  //
  // Used to determine whether the meridiemController should start animating.
  // Valid values are 0 and 1.
  //
  // The AM/PM correspondence of the two regions flips when the meridiem picker
  // scrolls. This variable is to keep track of the selected "physical"
  // (meridiem picker invariant) region of the hour picker. The "physical" region
  // of an item of index `i` is `i ~/ 12`.
  int meridiemRegion;
  // The current selection of the AM/PM picker.
  //
  // - 0 means AM
  // - 1 means PM
  FixedExtentScrollController meridiemController;

  bool isDatePickerScrolling = false;
  bool isHourPickerScrolling = false;
  bool isMinutePickerScrolling = false;
  bool isMeridiemPickerScrolling = false;

  bool get isScrolling {
    return isDatePickerScrolling ||
        isHourPickerScrolling ||
        isMinutePickerScrolling ||
        isMeridiemPickerScrolling;
  }

  // The estimated width of columns.
  final Map<int, double> estimatedColumnWidths = <int, double>{};

  @override
  void initState() {
    super.initState();
    initialDateTime = widget.initialDateTime;

    // Initially each of the "physical" regions is mapped to the meridiem region
    // with the same number, e.g., the first 12 items are mapped to the first 12
    // hours of a day. Such mapping is flipped when the meridiem picker is scrolled
    // by the user, the first 12 items are mapped to the last 12 hours of a day.
    selectedAmPm = initialDateTime.hour ~/ 12;
    meridiemRegion = selectedAmPm;

    meridiemController = FixedExtentScrollController(initialItem: selectedAmPm);
    hourController =
        FixedExtentScrollController(initialItem: initialDateTime.hour);
    minuteController = FixedExtentScrollController(
        initialItem: initialDateTime.minute ~/ widget.minuteInterval);
    dateController = FixedExtentScrollController(initialItem: 0);

    PaintingBinding.instance.systemFonts.addListener(_handleSystemFontsChange);
  }

  void _handleSystemFontsChange() {
    setState(() {
      // System fonts change might cause the text layout width to change.
      // Clears cached width to ensure that they get recalculated with the
      // new system fonts.
      estimatedColumnWidths.clear();
    });
  }

  @override
  void dispose() {
    dateController.dispose();
    hourController.dispose();
    minuteController.dispose();
    meridiemController.dispose();

    PaintingBinding.instance.systemFonts
        .removeListener(_handleSystemFontsChange);
    super.dispose();
  }

  @override
  void didUpdateWidget(DatePickerCustom oldWidget) {
    super.didUpdateWidget(oldWidget);

    assert(
      oldWidget.mode == widget.mode,
      "The $runtimeType's mode cannot change once it's built.",
    );

    if (!widget.use24hFormat && oldWidget.use24hFormat) {
      // Thanks to the physical and meridiem region mapping, the only thing we
      // need to update is the meridiem controller, if it's not previously attached.
      meridiemController.dispose();
      meridiemController =
          FixedExtentScrollController(initialItem: selectedAmPm);
    }
  }

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();

    textDirectionFactor =
        Directionality.of(context) == TextDirection.ltr ? 1 : -1;
    localizations = CupertinoLocalizations.of(context);

    alignCenterLeft =
        textDirectionFactor == 1 ? Alignment.centerLeft : Alignment.centerRight;
    alignCenterRight =
        textDirectionFactor == 1 ? Alignment.centerRight : Alignment.centerLeft;

    estimatedColumnWidths.clear();
  }

  // Lazily calculate the column width of the column being displayed only.
  double _getEstimatedColumnWidth(_PickerColumnType columnType) {
    if (estimatedColumnWidths[columnType.index] == null) {
      estimatedColumnWidths[columnType.index] =
          DatePickerCustom._getColumnWidth(columnType, localizations, context);
    }

    return estimatedColumnWidths[columnType.index];
  }

  // Gets the current date time of the picker.
  DateTime get selectedDateTime {
    return DateTime(
      initialDateTime.year,
      initialDateTime.month,
      initialDateTime.day + selectedDayFromInitial,
      selectedHour,
      selectedMinute,
    );
  }

  // Only reports datetime change when the date time is valid.
  void _onSelectedItemChange(int index) {
    final DateTime selected = selectedDateTime;

    final bool isDateInvalid = widget.minimumDate?.isAfter(selected) == true ||
        widget.maximumDate?.isBefore(selected) == true;

    if (isDateInvalid) return;

    widget.onDateTimeChanged(selected);
  }

  // Builds the date column. The date is displayed in medium date format (e.g. Fri Aug 31).
  Widget _buildMediumDatePicker(double offAxisFraction,
      TransitionBuilder itemPositioningBuilder, Widget selectionOverlay) {
    return NotificationListener<ScrollNotification>(
      onNotification: (ScrollNotification notification) {
        if (notification is ScrollStartNotification) {
          isDatePickerScrolling = true;
        } else if (notification is ScrollEndNotification) {
          isDatePickerScrolling = false;
          _pickerDidStopScrolling();
        }

        return false;
      },
      child: CupertinoPicker.builder(
        scrollController: dateController,
        offAxisFraction: offAxisFraction,
        itemExtent: _kItemExtent,
        useMagnifier: _kUseMagnifier,
        magnification: _kMagnification,
        backgroundColor: widget.backgroundColor,
        squeeze: _kSqueeze,
        onSelectedItemChanged: (int index) {
          _onSelectedItemChange(index);
        },
        itemBuilder: (BuildContext context, int index) {
          final DateTime rangeStart = DateTime(
            initialDateTime.year,
            initialDateTime.month,
            initialDateTime.day + index,
          );

          // Exclusive.
          final DateTime rangeEnd = DateTime(
            initialDateTime.year,
            initialDateTime.month,
            initialDateTime.day + index + 1,
          );

          final DateTime now = DateTime.now();

          if (widget.minimumDate?.isBefore(rangeEnd) == false) return null;
          if (widget.maximumDate?.isAfter(rangeStart) == false) return null;

          final String dateText =
              rangeStart == DateTime(now.year, now.month, now.day)
                  ? localizations.todayLabel
                  : localizations.datePickerMediumDate(rangeStart);

          return itemPositioningBuilder(
            context,
            Text(dateText, style: _themeTextStyle(context)),
          );
        },
        selectionOverlay: selectionOverlay,
      ),
    );
  }

  // With the meridiem picker set to `meridiemIndex`, and the hour picker set to
  // `hourIndex`, is it possible to change the value of the minute picker, so
  // that the resulting date stays in the valid range.
  bool _isValidHour(int meridiemIndex, int hourIndex) {
    final DateTime rangeStart = DateTime(
      initialDateTime.year,
      initialDateTime.month,
      initialDateTime.day + selectedDayFromInitial,
      _selectedHour(meridiemIndex, hourIndex),
      0,
    );

    // The end value of the range is exclusive, i.e. [rangeStart, rangeEnd).
    final DateTime rangeEnd = rangeStart.add(const Duration(hours: 1));

    return (widget.minimumDate?.isBefore(rangeEnd) ?? true) &&
        !(widget.maximumDate?.isBefore(rangeStart) ?? false);
  }

  Widget _buildHourPicker(double offAxisFraction,
      TransitionBuilder itemPositioningBuilder, Widget selectionOverlay) {
    return NotificationListener<ScrollNotification>(
        onNotification: (ScrollNotification notification) {
          if (notification is ScrollStartNotification) {
            isHourPickerScrolling = true;
          } else if (notification is ScrollEndNotification) {
            isHourPickerScrolling = false;
            _pickerDidStopScrolling();
          }

          return false;
        },
        child: CupertinoPicker(
          scrollController: hourController,
          offAxisFraction: offAxisFraction,
          itemExtent: _kItemExtent,
          useMagnifier: _kUseMagnifier,
          magnification: _kMagnification,
          backgroundColor: widget.backgroundColor,
          squeeze: _kSqueeze,
          onSelectedItemChanged: (int index) {
            final bool regionChanged = meridiemRegion != index ~/ 12;
            final bool debugIsFlipped = isHourRegionFlipped;

            if (regionChanged) {
              meridiemRegion = index ~/ 12;
              selectedAmPm = 1 - selectedAmPm;
            }

            if (!widget.use24hFormat && regionChanged) {
              // Scroll the meridiem column to adjust AM/PM.
              //
              // _onSelectedItemChanged will be called when the animation finishes.
              //
              // Animation values obtained by comparing with iOS version.
              meridiemController.animateToItem(
                selectedAmPm,
                duration: const Duration(milliseconds: 300),
                curve: Curves.easeOut,
              );
            } else {
              _onSelectedItemChange(index);
            }

            assert(debugIsFlipped == isHourRegionFlipped);
          },
          children: List<Widget>.generate(24, (int index) {
            final int hour = isHourRegionFlipped ? (index + 12) % 24 : index;
            final int displayHour =
                widget.use24hFormat ? hour : (hour + 11) % 12 + 1;

            return itemPositioningBuilder(
              context,
              Text(
                localizations.datePickerHour(displayHour),
                semanticsLabel:
                    localizations.datePickerHourSemanticsLabel(displayHour),
                style: _themeTextStyle(context,
                    isValid: _isValidHour(selectedAmPm, index)),
              ),
            );
          }),
          looping: true,
          selectionOverlay: selectionOverlay,
        ));
  }

  Widget _buildMinutePicker(double offAxisFraction,
      TransitionBuilder itemPositioningBuilder, Widget selectionOverlay) {
    return NotificationListener<ScrollNotification>(
      onNotification: (ScrollNotification notification) {
        if (notification is ScrollStartNotification) {
          isMinutePickerScrolling = true;
        } else if (notification is ScrollEndNotification) {
          isMinutePickerScrolling = false;
          _pickerDidStopScrolling();
        }

        return false;
      },
      child: CupertinoPicker(
        scrollController: minuteController,
        offAxisFraction: offAxisFraction,
        itemExtent: _kItemExtent,
        useMagnifier: _kUseMagnifier,
        magnification: _kMagnification,
        backgroundColor: widget.backgroundColor,
        squeeze: _kSqueeze,
        onSelectedItemChanged: _onSelectedItemChange,
        children:
            List<Widget>.generate(60 ~/ widget.minuteInterval, (int index) {
          final int minute = index * widget.minuteInterval;

          final DateTime date = DateTime(
            initialDateTime.year,
            initialDateTime.month,
            initialDateTime.day + selectedDayFromInitial,
            selectedHour,
            minute,
          );

          final bool isInvalidMinute =
              (widget.minimumDate?.isAfter(date) ?? false) ||
                  (widget.maximumDate?.isBefore(date) ?? false);

          return itemPositioningBuilder(
            context,
            Text(
              localizations.datePickerMinute(minute),
              semanticsLabel:
                  localizations.datePickerMinuteSemanticsLabel(minute),
              style: _themeTextStyle(context, isValid: !isInvalidMinute),
            ),
          );
        }),
        looping: true,
        selectionOverlay: selectionOverlay,
      ),
    );
  }

  Widget _buildAmPmPicker(double offAxisFraction,
      TransitionBuilder itemPositioningBuilder, Widget selectionOverlay) {
    return NotificationListener<ScrollNotification>(
      onNotification: (ScrollNotification notification) {
        if (notification is ScrollStartNotification) {
          isMeridiemPickerScrolling = true;
        } else if (notification is ScrollEndNotification) {
          isMeridiemPickerScrolling = false;
          _pickerDidStopScrolling();
        }

        return false;
      },
      child: CupertinoPicker(
        scrollController: meridiemController,
        offAxisFraction: offAxisFraction,
        itemExtent: _kItemExtent,
        useMagnifier: _kUseMagnifier,
        magnification: _kMagnification,
        backgroundColor: widget.backgroundColor,
        squeeze: _kSqueeze,
        onSelectedItemChanged: (int index) {
          selectedAmPm = index;
          assert(selectedAmPm == 0 || selectedAmPm == 1);
          _onSelectedItemChange(index);
        },
        children: List<Widget>.generate(2, (int index) {
          return itemPositioningBuilder(
            context,
            Text(
              index == 0
                  ? localizations.anteMeridiemAbbreviation
                  : localizations.postMeridiemAbbreviation,
              style: _themeTextStyle(context,
                  isValid: _isValidHour(index, _selectedHourIndex)),
            ),
          );
        }),
        selectionOverlay: selectionOverlay,
      ),
    );
  }

  // One or more pickers have just stopped scrolling.
  void _pickerDidStopScrolling() {
    // Call setState to update the greyed out date/hour/minute/meridiem.
    setState(() {});

    if (isScrolling) return;

    // Whenever scrolling lands on an invalid entry, the picker
    // automatically scrolls to a valid one.
    final DateTime selectedDate = selectedDateTime;

    final bool minCheck = widget.minimumDate?.isAfter(selectedDate) ?? false;
    final bool maxCheck = widget.maximumDate?.isBefore(selectedDate) ?? false;

    if (minCheck || maxCheck) {
      // We have minCheck === !maxCheck.
      final DateTime targetDate =
          minCheck ? widget.minimumDate : widget.maximumDate;
      _scrollToDate(targetDate, selectedDate);
    }
  }

  void _scrollToDate(DateTime newDate, DateTime fromDate) {
    assert(newDate != null);
    SchedulerBinding.instance.addPostFrameCallback((Duration timestamp) {
      if (fromDate.year != newDate.year ||
          fromDate.month != newDate.month ||
          fromDate.day != newDate.day) {
        _animateColumnControllerToItem(dateController, selectedDayFromInitial);
      }

      if (fromDate.hour != newDate.hour) {
        final bool needsMeridiemChange =
            !widget.use24hFormat && fromDate.hour ~/ 12 != newDate.hour ~/ 12;
        // In AM/PM mode, the pickers should not scroll all the way to the other hour region.
        if (needsMeridiemChange) {
          _animateColumnControllerToItem(
              meridiemController, 1 - meridiemController.selectedItem);

          // Keep the target item index in the current 12-h region.
          final int newItem = (hourController.selectedItem ~/ 12) * 12 +
              (hourController.selectedItem + newDate.hour - fromDate.hour) % 12;
          _animateColumnControllerToItem(hourController, newItem);
        } else {
          _animateColumnControllerToItem(
            hourController,
            hourController.selectedItem + newDate.hour - fromDate.hour,
          );
        }
      }

      if (fromDate.minute != newDate.minute) {
        _animateColumnControllerToItem(minuteController, newDate.minute);
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    // Widths of the columns in this picker, ordered from left to right.
    final List<double> columnWidths = <double>[
      _getEstimatedColumnWidth(_PickerColumnType.hour),
      _getEstimatedColumnWidth(_PickerColumnType.minute),
    ];

    // Swap the hours and minutes if RTL to ensure they are in the correct position.
    final List<_ColumnBuilder> pickerBuilders =
        Directionality.of(context) == TextDirection.rtl
            ? <_ColumnBuilder>[_buildMinutePicker, _buildHourPicker]
            : <_ColumnBuilder>[_buildHourPicker, _buildMinutePicker];

    // Adds am/pm column if the picker is not using 24h format.
    if (!widget.use24hFormat) {
      if (localizations.datePickerDateTimeOrder ==
              DatePickerDateTimeOrder.date_time_dayPeriod ||
          localizations.datePickerDateTimeOrder ==
              DatePickerDateTimeOrder.time_dayPeriod_date) {
        pickerBuilders.add(_buildAmPmPicker);
        columnWidths.add(_getEstimatedColumnWidth(_PickerColumnType.dayPeriod));
      } else {
        pickerBuilders.insert(0, _buildAmPmPicker);
        columnWidths.insert(
            0, _getEstimatedColumnWidth(_PickerColumnType.dayPeriod));
      }
    }

    // Adds medium date column if the picker's mode is date and time.
    if (widget.mode == DatePickerCustomMode.dateAndTime) {
      if (localizations.datePickerDateTimeOrder ==
              DatePickerDateTimeOrder.time_dayPeriod_date ||
          localizations.datePickerDateTimeOrder ==
              DatePickerDateTimeOrder.dayPeriod_time_date) {
        pickerBuilders.add(_buildMediumDatePicker);
        columnWidths.add(_getEstimatedColumnWidth(_PickerColumnType.date));
      } else {
        pickerBuilders.insert(0, _buildMediumDatePicker);
        columnWidths.insert(
            0, _getEstimatedColumnWidth(_PickerColumnType.date));
      }
    }

    final List<Widget> pickers = <Widget>[];

    for (int i = 0; i < columnWidths.length; i++) {
      double offAxisFraction = 0.0;
      Widget selectionOverlay =
          _centerSelectionOverlay(isAndroidG: widget.isAndroid);
      if (i == 0) {
        offAxisFraction = -_kMaximumOffAxisFraction * textDirectionFactor;
        selectionOverlay = _leftSelectionOverlay(isAndroidG: widget.isAndroid);
      } else if (i >= 2 || columnWidths.length == 2)
        offAxisFraction = _kMaximumOffAxisFraction * textDirectionFactor;

      EdgeInsets padding = const EdgeInsets.only(right: _kDatePickerPadSize);
      if (i == columnWidths.length - 1) {
        padding = padding.flipped;
        selectionOverlay = _rightSelectionOverlay(isAndroidG: widget.isAndroid);
      }
      if (textDirectionFactor == -1) padding = padding.flipped;

      pickers.add(LayoutId(
        id: i,
        child: pickerBuilders[i](
          offAxisFraction,
          (BuildContext context, Widget child) {
            return Container(
              alignment: i == columnWidths.length - 1
                  ? alignCenterLeft
                  : alignCenterRight,
              padding: padding,
              child: Container(
                alignment: i == columnWidths.length - 1
                    ? alignCenterLeft
                    : alignCenterRight,
                width: i == 0 || i == columnWidths.length - 1
                    ? null
                    : columnWidths[i] + _kDatePickerPadSize,
                child: child,
              ),
            );
          },
          selectionOverlay,
        ),
      ));
    }

    return MediaQuery(
      data: MediaQuery.of(context).copyWith(textScaleFactor: 1.0),
      child: DefaultTextStyle.merge(
        style: _kDefaultPickerTextStyle,
        child: CustomMultiChildLayout(
          delegate: _DatePickerLayoutDelegate(
            columnWidths: columnWidths,
            textDirectionFactor: textDirectionFactor,
          ),
          children: pickers,
        ),
      ),
    );
  }
}

class _DatePickerCustomDateState extends State<DatePickerCustom> {
  int textDirectionFactor;
  CupertinoLocalizations localizations;

  // Alignment based on text direction. The variable name is self descriptive,
  // however, when text direction is rtl, alignment is reversed.
  Alignment alignCenterLeft;
  Alignment alignCenterRight;

  // The currently selected values of the picker.
  int selectedDay;
  int selectedMonth;
  int selectedYear;

  // The controller of the day picker. There are cases where the selected value
  // of the picker is invalid (e.g. February 30th 2018), and this dayController
  // is responsible for jumping to a valid value.
  FixedExtentScrollController dayController;
  FixedExtentScrollController monthController;
  FixedExtentScrollController yearController;

  bool isDayPickerScrolling = false;
  bool isMonthPickerScrolling = false;
  bool isYearPickerScrolling = false;

  bool get isScrolling =>
      isDayPickerScrolling || isMonthPickerScrolling || isYearPickerScrolling;

  // Estimated width of columns.
  Map<int, double> estimatedColumnWidths = <int, double>{};

  @override
  void initState() {
    super.initState();
    selectedDay = widget.initialDateTime.day;
    selectedMonth = widget.initialDateTime.month;
    selectedYear = widget.initialDateTime.year;

    dayController = FixedExtentScrollController(initialItem: selectedDay - 1);
    monthController =
        FixedExtentScrollController(initialItem: selectedMonth - 1);
    yearController = FixedExtentScrollController(initialItem: selectedYear);

    PaintingBinding.instance.systemFonts.addListener(_handleSystemFontsChange);
  }

  void _handleSystemFontsChange() {
    setState(() {
      // System fonts change might cause the text layout width to change.
      _refreshEstimatedColumnWidths();
    });
  }

  @override
  void dispose() {
    dayController.dispose();
    monthController.dispose();
    yearController.dispose();

    PaintingBinding.instance.systemFonts
        .removeListener(_handleSystemFontsChange);
    super.dispose();
  }

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();

    textDirectionFactor =
        Directionality.of(context) == TextDirection.ltr ? 1 : -1;
    localizations = CupertinoLocalizations.of(context);

    alignCenterLeft =
        textDirectionFactor == 1 ? Alignment.centerLeft : Alignment.centerRight;
    alignCenterRight =
        textDirectionFactor == 1 ? Alignment.centerRight : Alignment.centerLeft;

    _refreshEstimatedColumnWidths();
  }

  void _refreshEstimatedColumnWidths() {
    estimatedColumnWidths[_PickerColumnType.dayOfMonth.index] =
        DatePickerCustom._getColumnWidth(
            _PickerColumnType.dayOfMonth, localizations, context);
    estimatedColumnWidths[_PickerColumnType.month.index] =
        DatePickerCustom._getColumnWidth(
            _PickerColumnType.month, localizations, context);
    estimatedColumnWidths[_PickerColumnType.year.index] =
        DatePickerCustom._getColumnWidth(
            _PickerColumnType.year, localizations, context);
  }

  // The DateTime of the last day of a given month in a given year.
  // Let `DateTime` handle the year/month overflow.
  DateTime _lastDayInMonth(int year, int month) => DateTime(year, month + 1, 0);

  Widget _buildDayPicker(double offAxisFraction,
      TransitionBuilder itemPositioningBuilder, Widget selectionOverlay) {
    final int daysInCurrentMonth =
        _lastDayInMonth(selectedYear, selectedMonth).day;
    return NotificationListener<ScrollNotification>(
      onNotification: (ScrollNotification notification) {
        if (notification is ScrollStartNotification) {
          isDayPickerScrolling = true;
        } else if (notification is ScrollEndNotification) {
          isDayPickerScrolling = false;
          _pickerDidStopScrolling();
        }

        return false;
      },
      child: CupertinoPicker(
        scrollController: dayController,
        offAxisFraction: offAxisFraction,
        itemExtent: _kItemExtent,
        useMagnifier: _kUseMagnifier,
        magnification: _kMagnification,
        backgroundColor: widget.backgroundColor,
        squeeze: _kSqueeze,
        onSelectedItemChanged: (int index) {
          selectedDay = index + 1;
          if (_isCurrentDateValid)
            widget.onDateTimeChanged(
                DateTime(selectedYear, selectedMonth, selectedDay));
        },
        children: List<Widget>.generate(31, (int index) {
          final int day = index + 1;
          return itemPositioningBuilder(
            context,
            Text(
              localizations.datePickerDayOfMonth(day),
              style:
                  _themeTextStyle(context, isValid: day <= daysInCurrentMonth),
            ),
          );
        }),
        looping: true,
        selectionOverlay: selectionOverlay,
      ),
    );
  }

  Widget _buildMonthPicker(double offAxisFraction,
      TransitionBuilder itemPositioningBuilder, Widget selectionOverlay) {
    return NotificationListener<ScrollNotification>(
      onNotification: (ScrollNotification notification) {
        if (notification is ScrollStartNotification) {
          isMonthPickerScrolling = true;
        } else if (notification is ScrollEndNotification) {
          isMonthPickerScrolling = false;
          _pickerDidStopScrolling();
        }

        return false;
      },
      child: CupertinoPicker(
        scrollController: monthController,
        offAxisFraction: offAxisFraction,
        itemExtent: _kItemExtent,
        useMagnifier: _kUseMagnifier,
        magnification: _kMagnification,
        backgroundColor: widget.backgroundColor,
        squeeze: _kSqueeze,
        onSelectedItemChanged: (int index) {
          selectedMonth = index + 1;
          if (_isCurrentDateValid)
            widget.onDateTimeChanged(
                DateTime(selectedYear, selectedMonth, selectedDay));
        },
        children: List<Widget>.generate(12, (int index) {
          final int month = index + 1;
          final bool isInvalidMonth =
              (widget.minimumDate?.year == selectedYear &&
                      widget.minimumDate.month > month) ||
                  (widget.maximumDate?.year == selectedYear &&
                      widget.maximumDate.month < month);

          return itemPositioningBuilder(
            context,
            Text(
              localizations.datePickerMonth(month),
              style: _themeTextStyle(context, isValid: !isInvalidMonth),
            ),
          );
        }),
        looping: true,
        selectionOverlay: selectionOverlay,
      ),
    );
  }

  Widget _buildYearPicker(double offAxisFraction,
      TransitionBuilder itemPositioningBuilder, Widget selectionOverlay) {
    return NotificationListener<ScrollNotification>(
      onNotification: (ScrollNotification notification) {
        if (notification is ScrollStartNotification) {
          isYearPickerScrolling = true;
        } else if (notification is ScrollEndNotification) {
          isYearPickerScrolling = false;
          _pickerDidStopScrolling();
        }

        return false;
      },
      child: CupertinoPicker.builder(
        scrollController: yearController,
        itemExtent: _kItemExtent,
        offAxisFraction: offAxisFraction,
        useMagnifier: _kUseMagnifier,
        magnification: _kMagnification,
        backgroundColor: widget.backgroundColor,
        onSelectedItemChanged: (int index) {
          selectedYear = index;
          if (_isCurrentDateValid)
            widget.onDateTimeChanged(
                DateTime(selectedYear, selectedMonth, selectedDay));
        },
        itemBuilder: (BuildContext context, int year) {
          if (year < widget.minimumYear) return null;

          if (widget.maximumYear != null && year > widget.maximumYear)
            return null;

          final bool isValidYear = (widget.minimumDate == null ||
                  widget.minimumDate.year <= year) &&
              (widget.maximumDate == null || widget.maximumDate.year >= year);

          return itemPositioningBuilder(
            context,
            Text(
              localizations.datePickerYear(year),
              style: _themeTextStyle(context, isValid: isValidYear),
            ),
          );
        },
        selectionOverlay: selectionOverlay,
      ),
    );
  }

  bool get _isCurrentDateValid {
    // The current date selection represents a range [minSelectedData, maxSelectDate].
    final DateTime minSelectedDate =
        DateTime(selectedYear, selectedMonth, selectedDay);
    final DateTime maxSelectedDate =
        DateTime(selectedYear, selectedMonth, selectedDay + 1);

    final bool minCheck = widget.minimumDate?.isBefore(maxSelectedDate) ?? true;
    final bool maxCheck =
        widget.maximumDate?.isBefore(minSelectedDate) ?? false;

    return minCheck && !maxCheck && minSelectedDate.day == selectedDay;
  }

  // One or more pickers have just stopped scrolling.
  void _pickerDidStopScrolling() {
    // Call setState to update the greyed out days/months/years, as the currently
    // selected year/month may have changed.
    setState(() {});

    if (isScrolling) {
      return;
    }

    // Whenever scrolling lands on an invalid entry, the picker
    // automatically scrolls to a valid one.
    final DateTime minSelectDate =
        DateTime(selectedYear, selectedMonth, selectedDay);
    final DateTime maxSelectDate =
        DateTime(selectedYear, selectedMonth, selectedDay + 1);

    final bool minCheck = widget.minimumDate?.isBefore(maxSelectDate) ?? true;
    final bool maxCheck = widget.maximumDate?.isBefore(minSelectDate) ?? false;

    if (!minCheck || maxCheck) {
      // We have minCheck === !maxCheck.
      final DateTime targetDate =
          minCheck ? widget.maximumDate : widget.minimumDate;
      _scrollToDate(targetDate);
      return;
    }

    // Some months have less days (e.g. February). Go to the last day of that month
    // if the selectedDay exceeds the maximum.
    if (minSelectDate.day != selectedDay) {
      final DateTime lastDay = _lastDayInMonth(selectedYear, selectedMonth);
      _scrollToDate(lastDay);
    }
  }

  void _scrollToDate(DateTime newDate) {
    assert(newDate != null);
    SchedulerBinding.instance.addPostFrameCallback((Duration timestamp) {
      if (selectedYear != newDate.year) {
        _animateColumnControllerToItem(yearController, newDate.year);
      }

      if (selectedMonth != newDate.month) {
        _animateColumnControllerToItem(monthController, newDate.month - 1);
      }

      if (selectedDay != newDate.day) {
        _animateColumnControllerToItem(dayController, newDate.day - 1);
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    List<_ColumnBuilder> pickerBuilders = <_ColumnBuilder>[];
    List<double> columnWidths = <double>[];

    switch (localizations.datePickerDateOrder) {
      case DatePickerDateOrder.mdy:
        pickerBuilders = <_ColumnBuilder>[
          _buildMonthPicker,
          _buildDayPicker,
          _buildYearPicker
        ];
        columnWidths = <double>[
          estimatedColumnWidths[_PickerColumnType.month.index],
          estimatedColumnWidths[_PickerColumnType.dayOfMonth.index],
          estimatedColumnWidths[_PickerColumnType.year.index],
        ];
        break;
      case DatePickerDateOrder.dmy:
        pickerBuilders = <_ColumnBuilder>[
          _buildDayPicker,
          _buildMonthPicker,
          _buildYearPicker
        ];
        columnWidths = <double>[
          estimatedColumnWidths[_PickerColumnType.dayOfMonth.index],
          estimatedColumnWidths[_PickerColumnType.month.index],
          estimatedColumnWidths[_PickerColumnType.year.index],
        ];
        break;
      case DatePickerDateOrder.ymd:
        pickerBuilders = <_ColumnBuilder>[
          _buildYearPicker,
          _buildMonthPicker,
          _buildDayPicker
        ];
        columnWidths = <double>[
          estimatedColumnWidths[_PickerColumnType.year.index],
          estimatedColumnWidths[_PickerColumnType.month.index],
          estimatedColumnWidths[_PickerColumnType.dayOfMonth.index],
        ];
        break;
      case DatePickerDateOrder.ydm:
        pickerBuilders = <_ColumnBuilder>[
          _buildYearPicker,
          _buildDayPicker,
          _buildMonthPicker
        ];
        columnWidths = <double>[
          estimatedColumnWidths[_PickerColumnType.year.index],
          estimatedColumnWidths[_PickerColumnType.dayOfMonth.index],
          estimatedColumnWidths[_PickerColumnType.month.index],
        ];
        break;
    }

    final List<Widget> pickers = <Widget>[];

    for (int i = 0; i < columnWidths.length; i++) {
      final double offAxisFraction = (i - 1) * 0.3 * textDirectionFactor;

      EdgeInsets padding = const EdgeInsets.only(right: _kDatePickerPadSize);
      if (textDirectionFactor == -1)
        padding = const EdgeInsets.only(left: _kDatePickerPadSize);

      Widget selectionOverlay =
          _centerSelectionOverlay(isAndroidG: widget.isAndroid);
      if (i == 0)
        selectionOverlay = _leftSelectionOverlay(isAndroidG: widget.isAndroid);
      else if (i == columnWidths.length - 1)
        selectionOverlay = _rightSelectionOverlay(isAndroidG: widget.isAndroid);

      pickers.add(LayoutId(
        id: i,
        child: pickerBuilders[i](
          offAxisFraction,
          (BuildContext context, Widget child) {
            return Container(
              alignment: i == columnWidths.length - 1
                  ? alignCenterLeft
                  : alignCenterRight,
              padding: i == 0 ? null : padding,
              child: Container(
                alignment: i == 0 ? alignCenterLeft : alignCenterRight,
                width: columnWidths[i] + _kDatePickerPadSize,
                child: child,
              ),
            );
          },
          selectionOverlay,
        ),
      ));
    }

    return MediaQuery(
      data: MediaQuery.of(context).copyWith(textScaleFactor: 1.0),
      child: DefaultTextStyle.merge(
        style: _kDefaultPickerTextStyle,
        child: CustomMultiChildLayout(
          delegate: _DatePickerLayoutDelegate(
            columnWidths: columnWidths,
            textDirectionFactor: textDirectionFactor,
          ),
          children: pickers,
        ),
      ),
    );
  }
}
				
			

Simple Item List

A simple Item List is a structured arrangement of elements in a listing format. Simple Item List is made up of rows of items, it can include text, buttons, toggles, icons, etc.

Use the Simple Item List if:

  • If you have large numbers of elements to add to the app.

Do not Use the Simple Item List if:

  • Not recommended to use an item list if you have a small number of elements to display in the App.

Precautions:

Mobile Screen View


  • Recommend to arrange the sequence of the item in a list according to a priority basis. Recommend to use short keywords.

# Usage

Simple Item List
Create item_list_page.dart file and paste the below code and call this file in your main.dart file.

First .dart file > item_list_page.dart (New)

				
					import 'dart:io';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:fullter_main_app/src/api_calling/api_constant.dart';
import 'package:fullter_main_app/src/widgets/android_ios_check_box.dart';
import 'package:fullter_main_app/src/widgets/badge.dart';
import 'package:fullter_main_app/src/widgets/icon_right_with_text.dart';
import 'package:fullter_main_app/src/widgets/labeled_check_box.dart';
import 'package:fullter_main_app/src/widgets/listViewCustom.dart';

class ItemListPage extends StatefulWidget {
  ItemListPage({Key key}) : super(key: key);
  @override
  _ItemListPageState createState() => _ItemListPageState();
}

class _ItemListPageState extends State<ItemListPage> {
  List<String> listData = [];
  @override
  void dispose() {
    // TODO: implement dispose
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    listData = [
      "Followers",
      "Like",
      "Share",
      "Completed",
      "Warning",
      "Notification",
      "Unread" "Draft",
      "Deleted"
    ];
    //Center View
    Widget _centerView() {
      return Container(
        margin: EdgeInsets.symmetric(horizontal: 0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          mainAxisAlignment: MainAxisAlignment.start,
          mainAxisSize: MainAxisSize.min,
          children: <Widget>[
            AndroidIosCheckbox(
              onChanged: () {
                setState(() {});
              },
            ),
            ListViewCustom(
              shrinkWrap: true,
              listData: listData,
              listViewType: ListViewType.LIST_ITEMS,
              tileWidget: ({singleRowData, index}) {
                BadgeType badgeType = BadgeType.FOLLOWERS;
                if (index == 1) {
                  badgeType = BadgeType.LIKE;
                } else if (index == 2) {
                  badgeType = BadgeType.SHARE;
                } else if (index == 3) {
                  badgeType = BadgeType.COMPLETED;
                } else if (index == 4) {
                  badgeType = BadgeType.WARNINGS;
                } else if (index == 5) {
                  badgeType = BadgeType.NOTIFICATION;
                } else if (index == 6) {
                  badgeType = BadgeType.UNREAD;
                } else if (index == 7) {
                  badgeType = BadgeType.DRAFT;
                } else {
                  badgeType = BadgeType.DELETED;
                }
                return IconRightWithText(
                  index: index,
                  text: listData[index],
                  iconRightWidget: Badge(
                    badgeType: badgeType,
                    badgeValue: "70",
                  ),
                  iconViewSize: Size(70, 40),
                );
              },
            )
          ],
        ),
      );
    }

    //Back Press
    _onBackPressed() {
      print("ok");
      Navigator.pop(context);
      print("ok");
    }

    return WillPopScope(
        onWillPop: _onBackPressed,
        child: Container(
            color: Colors.transparent,
            child: SafeArea(
                bottom: false,
                child: Scaffold(
                  backgroundColor: Colors.white,
                  //appBar:_appBar(),
                  body: Container(
                    color: Colors.white,
                    child: _centerView(),
                  ),
                ))));
  }
}
				
			


Create listViewCustom.dart file and paste the below code
Second .dart file > listViewCustom.dart

				
					import 'dart:io';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

//Selected menu call back function type
typedef RowViewCallback = Function({dynamic singleRowData, int index});

enum ListViewType {
  LIST_CUSTOM_ROW_ITEMS,
  LIST_ITEMS,
  LIST_DIVIDER,
  LIST_ICON,
  LIST_BUTTON,
  LIST_AVATAR,
  LIST_THUMBNAILS
}

class ListViewCustom extends StatelessWidget {
  ListViewCustom({
    Key key,
    this.padding = const EdgeInsets.fromLTRB(0.0, 0.0, 0.0, 0.0),
    this.value,
    this.onChanged,
    this.listViewType = ListViewType.LIST_ITEMS,
    this.isAndroid = false,
    this.dividerColor = Colors.grey,
    this.listData,
    this.tileWidget, // Widget to set the row in a list view
    this.listViewEdgeInsets = const EdgeInsets.fromLTRB(0.0, 8.0, 0.0, 8.0),
    this.listBgColor, // ListView background Color
    this.noDataFoundWidget, // No data found widget
    this.physics, // set data in the list view
    this.shrinkWrap =
        false, // get the call back when user reaches the end of the list view
    this.scrollDirection,
  }) : super(key: key);

  final EdgeInsets padding;
  final ListViewType listViewType;
  final bool value;
  final Function onChanged;
  final bool isAndroid;
  //Data to display to display in the list
  final List<dynamic> listData;
  //Properties to set the left, top, right and bottom margin using EdgeInsets
  final EdgeInsetsGeometry listViewEdgeInsets;
  //This color will set the list view background color
  final Color listBgColor;
  final Color dividerColor;
  //No data found widget that display when there no data found
  final Widget noDataFoundWidget;
  final physics;
  final bool shrinkWrap;
  final scrollDirection;
  //Tile widget to display the row in a list view
  final RowViewCallback tileWidget;
  final ScrollController scrollController = ScrollController();

  @override
  Widget build(BuildContext context) {
    bool isAndroid = false;
    //Check device platform
    if (Platform.isIOS) {
      isAndroid = false;
    } else if (Platform.isAndroid) {
      isAndroid = true;
    }
    //Ios check box custome
    Widget iosCheckBox = Container(
      margin: EdgeInsets.symmetric(vertical: 5),
      padding: EdgeInsets.all(
          5.0), //I used some padding without fixed width and height
      /* decoration: BoxDecoration(
          // You can use like this way or like the below line
          border: Border.all(
              color: disabled
                  ? checkBoxDisableColor
                  : (value ? checkFillColor : checkBoxColor),
              width: 1.0,
              style: BorderStyle.solid), //Border.all
          borderRadius: BorderRadius.all(
            Radius.circular(50),
          ),
          color: (value && !disabled)
              ? checkFillColor
              : !disabled
                  ? checkNonFillColor
                  : checkFillDisableColor),*/
      /*child: , */ // You can add a Icon instead of text also, like below.
      //child: new Icon(Icons.arrow_forward, size: 50.0, color: Colors.black38)),
    );

    //Create List row according list type
    Widget getTileWidgetType({dynamic singleRowData, int index}) {
      Widget tempRowView = Container();
      switch (this.listViewType) {
        case ListViewType.LIST_DIVIDER:
          break;
        case ListViewType.LIST_ICON:
          break;
        case ListViewType.LIST_BUTTON:
          break;
        case ListViewType.LIST_AVATAR:
          break;
        case ListViewType.LIST_THUMBNAILS:
          break;
        default: //ListViewType.LIST_ITEMS
          tempRowView = itemRowView(index: index, item: "$singleRowData");
      }
      return tempRowView;
    }

    //Main List view
    Widget getListContainer() {
      return Container(
        color: listBgColor == null ? Colors.white : listBgColor,
        child: ListView.separated(
            separatorBuilder: (context, index) => Divider(
                  color: dividerColor,
                  height: 1.0,
                  indent: 0.0,
                  endIndent: 0.0,
                ),
            //controller: scrollController,
            padding: listViewEdgeInsets,
            physics: physics ?? AlwaysScrollableScrollPhysics(),
            shrinkWrap: shrinkWrap,
            scrollDirection: scrollDirection ?? Axis.vertical,
            itemCount: getListData().length,
            itemBuilder: (context, i) {
              var textValue = getListData()[i];
              Widget tempRowView1 = Container();
              if (this.tileWidget != null &&
                  this.listViewType == ListViewType.LIST_CUSTOM_ROW_ITEMS) {
                tempRowView1 =
                    this.tileWidget(singleRowData: textValue, index: i);
                print("Hello");
              } else {
                tempRowView1 =
                    getTileWidgetType(singleRowData: textValue, index: i);
              }
              Widget tempRowView = tempRowView1;
              return tempRowView;
            }),
      );
    }

    return Padding(
      padding: padding,
      child: getListContainer(),
    );
  }

  //Get list according list type
  List<dynamic> getListData() {
    List<dynamic> listData = [];
    //If user set dynamic list type
    if (this.listData !=
            null /* &&
        this.listViewType == ListViewType.LIST_CUSTOM_ROW_ITEMS*/
        ) {
      listData.addAll(this.listData);
    } else {
      switch (this.listViewType) {
        case ListViewType.LIST_DIVIDER:
          break;
        case ListViewType.LIST_ICON:
          break;
        case ListViewType.LIST_BUTTON:
          break;
        case ListViewType.LIST_AVATAR:
          break;
        case ListViewType.LIST_THUMBNAILS:
          break;
        default: //ListViewType.LIST_ITEMS
          listData.addAll(["Mobile", "Laptop", "Keyboard"]);
      }
    }
    return listData;
  }

  //Single list row for item list type
  Widget itemRowView({String item, int index}) {
    Widget tempRowView = Container(
      color: Colors.white,
      height: 50,
      width: double.infinity,
      padding: EdgeInsets.symmetric(horizontal: 15, vertical: 5),
      child: Align(alignment: Alignment.centerLeft, child: Text("$item")),
    );
    return tempRowView;
  }
}
				
			

Divider List 

Divider List is block elements that can be used to separate items in a list. Under the divider list, elements are arranged in groups of items.

Use the Divider List if:

  • If you need to show items in a group.

Do not Use the Divider List if:

  • Do not use divider list type if your content type is Unique or completely different.

Precautions:

  • Carefully add the items according to the headings and group of the list.

Mobile Screen View


# Usage

Divider List
Create divider_list_page.dart file and paste the below code and call this file in your main.dart file.

First .dart file > divider_list_page.dart (New)

				
					import 'dart:io';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:fullter_main_app/src/api_calling/api_constant.dart';
import 'package:fullter_main_app/src/widgets/android_ios_check_box.dart';
import 'package:fullter_main_app/src/widgets/badge.dart';
import 'package:fullter_main_app/src/widgets/dividerListCustom.dart';
import 'package:fullter_main_app/src/widgets/icon_right_with_text.dart';
import 'package:fullter_main_app/src/widgets/labeled_check_box.dart';
import 'package:fullter_main_app/src/widgets/listViewCustom.dart';

class DividerListPage extends StatefulWidget {
  DividerListPage({Key key}) : super(key: key);
  @override
  _DividerListPageState createState() => _DividerListPageState();
}

class _DividerListPageState extends State<DividerListPage> {
  @override
  void dispose() {
    // TODO: implement dispose
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    //Center View
    Widget _centerView() {
      return Container(
        margin: EdgeInsets.symmetric(horizontal: 0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          mainAxisAlignment: MainAxisAlignment.start,
          mainAxisSize: MainAxisSize.min,
          children: <Widget>[
            AndroidIosCheckbox(
              onChanged: () {
                setState(() {});
              },
            ),
            DividerListCustom(
              shrinkWrap: true,
            ),
          ],
        ),
      );
    }

    //Back Press
    _onBackPressed() {
      print("ok");
      Navigator.pop(context);
      print("ok");
    }

    return WillPopScope(
        onWillPop: _onBackPressed,
        child: Container(
            color: Colors.transparent,
            child: SafeArea(
                bottom: false,
                child: Scaffold(
                  backgroundColor: Colors.white,
                  //appBar:_appBar(),
                  body: Container(
                    color: Colors.white,
                    child: _centerView(),
                  ),
                ))));
  }
}
				
			


Create dividerListCustom.dart file and paste the below code
Second .dart file > dividerListCustom.dart

				
					import 'dart:io';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:fullter_main_app/src/widgets/avatar_left_with_data.dart';
import 'package:fullter_main_app/src/widgets/badge.dart';
import 'package:fullter_main_app/src/widgets/icon_left_and_right.dart';
import 'package:fullter_main_app/src/widgets/icon_left_with_text.dart';
import 'package:fullter_main_app/src/widgets/thumbnail_left_with_data.dart';

import 'icon_left_and_right_text_with_text.dart';

typedef DividerRowViewCallback = Function({dynamic singleRowData, int index});
enum DividerListViewType {
  LIST_CUSTOM_ROW_ITEMS,
  LIST_ITEMS,
  LIST_ICON,
  LIST_BUTTON,
  LIST_AVATAR,
  LIST_THUMBNAILS
}

class DividerListCustom extends StatelessWidget {
  DividerListCustom({
    Key key,
    this.padding = const EdgeInsets.fromLTRB(0.0, 0.0, 0.0, 0.0),
    this.value,
    this.onChanged,
    this.dividerListViewType = DividerListViewType.LIST_ITEMS,
    this.isAndroid = false,
    this.dividerColor = Colors.grey,
    this.listData,
    this.dividerTileWidget, // Widget to set the row in a list view
    this.listViewEdgeInsets = const EdgeInsets.fromLTRB(0.0, 8.0, 0.0, 8.0),
    this.listBgColor, // ListView background Color
    this.noDataFoundWidget, // No data found widget
    this.physics, // set data in the list view
    this.shrinkWrap =
        false, // get the call back when user reaches the end of the list view
    this.scrollDirection,
  }) : super(key: key);

  final EdgeInsets padding;
  final DividerListViewType dividerListViewType;
  final bool value;
  final Function onChanged;
  final bool isAndroid;
  //Data to display to display in the list
  final List<HeaderListModel> listData;
  //Properties to set the left, top, right and bottom margin using EdgeInsets
  final EdgeInsetsGeometry listViewEdgeInsets;
  //This color will set the list view background color
  final Color listBgColor;
  final Color dividerColor;
  //No data found widget that display when there no data found
  final Widget noDataFoundWidget;
  final physics;
  final bool shrinkWrap;
  final scrollDirection;
  //Tile widget to display the row in a list view
  final DividerRowViewCallback dividerTileWidget;
  final ScrollController scrollController = ScrollController();

  @override
  Widget build(BuildContext context) {
    bool isAndroid = false;
    //Check device platform
    if (Platform.isIOS) {
      isAndroid = false;
    } else if (Platform.isAndroid) {
      isAndroid = true;
    }
    //Ios check box custom
    Widget iosCheckBox = Container(
      margin: EdgeInsets.symmetric(vertical: 5),
      padding: EdgeInsets.all(
          5.0), //I used some padding without fixed width and height
      /* decoration: BoxDecoration(
          // You can use like this way or like the below line
          border: Border.all(
              color: disabled
                  ? checkBoxDisableColor
                  : (value ? checkFillColor : checkBoxColor),
              width: 1.0,
              style: BorderStyle.solid), //Border.all
          borderRadius: BorderRadius.all(
            Radius.circular(50),
          ),
          color: (value && !disabled)
              ? checkFillColor
              : !disabled
                  ? checkNonFillColor
                  : checkFillDisableColor),*/
      /*child: , */ // You can add a Icon instead of text also, like below.
      //child: new Icon(Icons.arrow_forward, size: 50.0, color: Colors.black38)),
    );

    //Create List row according list type
    Widget getTileWidgetType({HeaderListModel singleRowData, int index}) {
      bool isHeaderRow = singleRowData.isHeaderRow;
      dynamic listRowData = singleRowData.listRowData;

      Widget tempRowView = Container();
      switch (this.dividerListViewType) {
        case DividerListViewType.LIST_ICON:
          if (isHeaderRow) {
            tempRowView = listItemHead(index: index, item: "$listRowData");
          } else {
            //Left and right both
            if (singleRowData.leftIcon != null &&
                singleRowData.rightIcon != null) {
              tempRowView = IconLeftAndRight(
                index: index,
                text: "$listRowData",
                iconLeftWidget: singleRowData.leftIcon,
                iconRightWidget: singleRowData.rightIcon,
                iconRightViewSize: Size(70, 40),
              );
            }

            //Only Right
            else if (singleRowData.rightIcon != null &&
                (singleRowData.rightText == null ||
                    singleRowData.rightText.length > 0)) {
              tempRowView = IconLeftAndRight(
                index: index,
                text: "$listRowData",
                iconRightWidget: singleRowData.rightIcon,
                iconLeftWidget: singleRowData.leftIcon,
              );
            }
            //Only Right text
            else if (singleRowData.rightIcon == null &&
                (singleRowData.rightText != null &&
                    singleRowData.rightText.length > 0)) {
              tempRowView = IconLeftAndRightTextWithText(
                index: index,
                text: "$listRowData",
                textRight: singleRowData.rightText,
                iconLeftWidget: singleRowData.leftIcon,
              );
            }
            //Only Left
            else if (singleRowData.leftIcon != null) {
              tempRowView = IconLeftWithText(
                index: index,
                text: "$listRowData",
                iconWidget: singleRowData.leftIcon,
              );
            } else
              tempRowView = IconLeftWithText(
                index: index,
                text: "$listRowData",
                iconWidget: singleRowData.leftIcon,
              );
          }
          break;
        case DividerListViewType.LIST_BUTTON:
          break;
        case DividerListViewType.LIST_AVATAR:
          tempRowView = AvatarLeftWithData(
            index: index,
            avatarPath: listRowData["image"],
            rightWidget: Column(
              mainAxisSize: MainAxisSize.min,
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Container(
                  // color: Colors.green,
                  child: Align(
                      alignment: Alignment.centerLeft,
                      child: Text(
                        'Name'.toUpperCase(),
                        style: TextStyle(color: Colors.black, fontSize: 12),
                        textAlign: TextAlign.start,
                      )),
                ),
                SizedBox(
                  height: 0,
                ),
                Text(
                  'Madison, WI',
                  style: TextStyle(color: Colors.grey, fontSize: 18),
                  textAlign: TextAlign.start,
                ),
              ],
            ), /*,
            rightWidget: ,: singleRowData.leftIcon,*/
          );

          break;
        case DividerListViewType.LIST_THUMBNAILS:
          tempRowView = ThumbnailLeftWithData(
            index: index,
            avatarPath: listRowData["image"],
            rightWidget: Padding(
              padding: const EdgeInsets.all(5.0),
              child: Column(
                mainAxisSize: MainAxisSize.max,
                crossAxisAlignment: CrossAxisAlignment.start,
                mainAxisAlignment: MainAxisAlignment.start,
                children: [
                  Container(
                    // color: Colors.green,
                    child: Align(
                        alignment: Alignment.centerLeft,
                        child: Text(
                          'Name'.toUpperCase(),
                          style: TextStyle(color: Colors.black, fontSize: 12),
                          textAlign: TextAlign.start,
                        )),
                  ),
                  SizedBox(
                    height: 0,
                  ),
                  Text(
                    'Madison, WI',
                    style: TextStyle(color: Colors.grey, fontSize: 18),
                    textAlign: TextAlign.start,
                  ),
                ],
              ),
            ), /*,
            rightWidget: ,: singleRowData.leftIcon,*/
          );
          break;
        default: //DividerListViewType.LIST_ITEMS
          tempRowView = isHeaderRow
              ? listItemHead(index: index, item: "$listRowData")
              : itemRowView(index: index, item: "$listRowData");
      }
      return tempRowView;
    }

    //Main List view
    Widget getListContainer() {
      return Container(
        color: listBgColor == null ? Colors.white : listBgColor,
        child: ListView.separated(
            separatorBuilder: (context, index) => Divider(
                  color: dividerColor,
                  height: 1.0,
                  indent: 0.0,
                  endIndent: 0.0,
                ),
            //controller: scrollController,
            padding: listViewEdgeInsets,
            physics: physics ?? AlwaysScrollableScrollPhysics(),
            shrinkWrap: shrinkWrap,
            scrollDirection: scrollDirection ?? Axis.vertical,
            itemCount: getListData().length,
            itemBuilder: (context, i) {
              HeaderListModel mHeaderListModel = getListData()[i];
              Widget tempRowView1 = Container();
              if (this.dividerTileWidget != null &&
                  this.dividerListViewType ==
                      DividerListViewType.LIST_CUSTOM_ROW_ITEMS) {
                tempRowView1 = this.dividerTileWidget(
                    singleRowData: mHeaderListModel, index: i);
              } else {
                tempRowView1 = getTileWidgetType(
                    singleRowData: mHeaderListModel, index: i);
              }
              Widget tempRowView = tempRowView1;
              return tempRowView;
            }),
      );
    }

    return Padding(
      padding: padding,
      child: getListContainer(),
    );
  }

  //Get list according list type
  List<HeaderListModel> getListData() {
    List<HeaderListModel> listData = [];
    //If user set dynamic list type
    if (this.listData !=
            null /* &&
        this.dividerListViewType == DividerListViewType.LIST_CUSTOM_ROW_ITEMS*/
        ) {
      listData.addAll(this.listData);
    } else {
      switch (this.dividerListViewType) {
        case DividerListViewType.LIST_ICON:
          listData.add(HeaderListModel(
              listRowData: "Check Email",
              leftIcon: const Icon(
                Icons.mail,
                color: Colors.black,
              )));
          listData.add(HeaderListModel(
              listRowData: "Call Me",
              leftIcon: const Icon(
                Icons.chat,
                color: Colors.black,
              )));
          listData.add(HeaderListModel(
              listRowData: "Record Album",
              leftIcon: const Icon(
                Icons.mic,
                color: Colors.black,
              ),
              rightText: "Grammy"));
          listData.add(HeaderListModel(
              listRowData: "Friend",
              leftIcon: const Icon(
                Icons.group,
                color: Colors.black,
              ),
              rightIcon: Badge(
                badgeType: BadgeType.WARNINGS,
                badgeValue: "70",
              )));

          listData.add(
              HeaderListModel(listRowData: "Activities", isHeaderRow: true));
          listData.add(HeaderListModel(
              listRowData: "Booking Bad",
              leftIcon: const Icon(
                Icons.mail,
                color: Colors.black,
              ),
              rightText: "Blue,Yellow,Pink"));
          /* listData.add(HeaderListModel(listRowData: "Mac Mini"));
          listData.add(HeaderListModel(listRowData: "CCTV Camera"));*/
          break;
        case DividerListViewType.LIST_BUTTON:
          break;
        case DividerListViewType.LIST_AVATAR:
          listData.add(HeaderListModel(listRowData: {
            'image': 'https://www.worldatlas.com/upload/ce/81/b5/artboard-1.png'
          }));
          listData.add(HeaderListModel(listRowData: {
            'image': 'https://www.worldatlas.com/upload/ce/81/b5/artboard-1.png'
          }));
          listData.add(HeaderListModel(listRowData: {
            'image': 'https://www.worldatlas.com/upload/ce/81/b5/artboard-1.png'
          }));
          break;
        case DividerListViewType.LIST_THUMBNAILS:
          listData.add(HeaderListModel(listRowData: {
            'image': 'https://www.worldatlas.com/upload/ce/81/b5/artboard-1.png'
          }));
          listData.add(HeaderListModel(listRowData: {
            'image': 'https://www.worldatlas.com/upload/ce/81/b5/artboard-1.png'
          }));
          listData.add(HeaderListModel(listRowData: {
            'image': 'https://www.worldatlas.com/upload/ce/81/b5/artboard-1.png'
          }));
          break;
        default: //DividerListViewType.LIST_ITEMS

          listData.add(HeaderListModel(
              listRowData: "Electronic Item", isHeaderRow: true));
          listData.add(HeaderListModel(listRowData: "Mobile"));
          listData.add(HeaderListModel(listRowData: "Laptop"));
          listData.add(HeaderListModel(listRowData: "Keyboard"));
          listData.add(HeaderListModel(
              listRowData: "Electronic Item 2", isHeaderRow: true));
          listData.add(HeaderListModel(listRowData: "Mouse"));
          listData.add(HeaderListModel(listRowData: "Mac Mini"));
          listData.add(HeaderListModel(listRowData: "CCTV Camera"));
      }
    }
    return listData;
  }

  //Single list row for item list type
  Widget itemRowView({String item, int index}) {
    Widget tempRowView = Container(
      color: Colors.white,
      height: 50,
      width: double.infinity,
      padding: EdgeInsets.symmetric(horizontal: 15, vertical: 5),
      child: Align(alignment: Alignment.centerLeft, child: Text("$item")),
    );
    return tempRowView;
  }

  //List child head
  Widget listItemHead({String item, int index}) {
    Widget tempRowView = Container(
      color: Colors.blueGrey.withOpacity(0.2),
      height: 45,
      width: double.infinity,
      padding: EdgeInsets.symmetric(horizontal: 15, vertical: 5),
      child: Align(alignment: Alignment.centerLeft, child: Text("$item")),
    );
    return tempRowView;
  }
}

class HeaderListModel {
  bool isHeaderRow;
  dynamic listRowData;
  Widget leftIcon;
  Widget rightIcon;
  String rightText;
  HeaderListModel(
      {this.isHeaderRow = false,
      @required this.listRowData,
      this.leftIcon,
      this.rightIcon,
      this.rightText = ""});
}
				
			

Icon List 

Icon Lists are made up of multiple rows of items with icons and text.

Use the Icon List if:

  • If you want to improve the visual interest and grab the user’s attention.

Do not Use the Icon List if:

  • Do not use if you have limited space and speed available.

Precautions:

  • Recommend to place the relevant icon before texts with proper alignments.

Mobile Screen View


# Usage

Icon List
Create divider_icon_list_page.dart file and paste the below code and call this file in your main.dart file.

First .dart file > divider_icon_list_page.dart (New)

				
					import 'dart:io';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:fullter_main_app/src/api_calling/api_constant.dart';
import 'package:fullter_main_app/src/widgets/android_ios_check_box.dart';
import 'package:fullter_main_app/src/widgets/badge.dart';
import 'package:fullter_main_app/src/widgets/dividerListCustom.dart';
import 'package:fullter_main_app/src/widgets/icon_right_with_text.dart';
import 'package:fullter_main_app/src/widgets/labeled_check_box.dart';
import 'package:fullter_main_app/src/widgets/listViewCustom.dart';

class DividerIconListPage extends StatefulWidget {
  DividerIconListPage({Key key}) : super(key: key);
  @override
  _DividerIconListPageState createState() => _DividerIconListPageState();
}

class _DividerIconListPageState extends State<DividerIconListPage> {
  @override
  void dispose() {
    // TODO: implement dispose
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    //Center View
    Widget _centerView() {
      return Container(
        margin: EdgeInsets.symmetric(horizontal: 0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          mainAxisAlignment: MainAxisAlignment.start,
          mainAxisSize: MainAxisSize.min,
          children: <Widget>[
            AndroidIosCheckbox(
              onChanged: () {
                setState(() {});
              },
            ),
            DividerListCustom(
              shrinkWrap: true,
              dividerListViewType: DividerListViewType.LIST_ICON,
            ),
          ],
        ),
      );
    }

    //Back Press
    _onBackPressed() {
      print("ok");
      Navigator.pop(context);
      print("ok");
    }

    return WillPopScope(
        onWillPop: _onBackPressed,
        child: Container(
            color: Colors.transparent,
            child: SafeArea(
                bottom: false,
                child: Scaffold(
                  backgroundColor: Colors.white,
                  //appBar:_appBar(),
                  body: Container(
                    color: Colors.white,
                    child: _centerView(),
                  ),
                ))));
  }
}
				
			


Create listViewCustom.dart file and paste the below code
Second .dart file > listViewCustom.dart

				
					import 'dart:io';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

//Selected menu call back function type
typedef RowViewCallback = Function({dynamic singleRowData, int index});

enum ListViewType {
  LIST_CUSTOM_ROW_ITEMS,
  LIST_ITEMS,
  LIST_DIVIDER,
  LIST_ICON,
  LIST_BUTTON,
  LIST_AVATAR,
  LIST_THUMBNAILS
}

class ListViewCustom extends StatelessWidget {
  ListViewCustom({
    Key key,
    this.padding = const EdgeInsets.fromLTRB(0.0, 0.0, 0.0, 0.0),
    this.value,
    this.onChanged,
    this.listViewType = ListViewType.LIST_ITEMS,
    this.isAndroid = false,
    this.dividerColor = Colors.grey,
    this.listData,
    this.tileWidget, // Widget to set the row in a list view
    this.listViewEdgeInsets = const EdgeInsets.fromLTRB(0.0, 8.0, 0.0, 8.0),
    this.listBgColor, // ListView background Color
    this.noDataFoundWidget, // No data found widget
    this.physics, // set data in the list view
    this.shrinkWrap =
        false, // get the call back when user reaches the end of the list view
    this.scrollDirection,
  }) : super(key: key);

  final EdgeInsets padding;
  final ListViewType listViewType;
  final bool value;
  final Function onChanged;
  final bool isAndroid;
  //Data to display to display in the list
  final List<dynamic> listData;
  //Properties to set the left, top, right and bottom margin using EdgeInsets
  final EdgeInsetsGeometry listViewEdgeInsets;
  //This color will set the list view background color
  final Color listBgColor;
  final Color dividerColor;
  //No data found widget that display when there no data found
  final Widget noDataFoundWidget;
  final physics;
  final bool shrinkWrap;
  final scrollDirection;
  //Tile widget to display the row in a list view
  final RowViewCallback tileWidget;
  final ScrollController scrollController = ScrollController();

  @override
  Widget build(BuildContext context) {
    bool isAndroid = false;
    //Check device platform
    if (Platform.isIOS) {
      isAndroid = false;
    } else if (Platform.isAndroid) {
      isAndroid = true;
    }
    //Ios check box custome
    Widget iosCheckBox = Container(
      margin: EdgeInsets.symmetric(vertical: 5),
      padding: EdgeInsets.all(
          5.0), //I used some padding without fixed width and height
      /* decoration: BoxDecoration(
          // You can use like this way or like the below line
          border: Border.all(
              color: disabled
                  ? checkBoxDisableColor
                  : (value ? checkFillColor : checkBoxColor),
              width: 1.0,
              style: BorderStyle.solid), //Border.all
          borderRadius: BorderRadius.all(
            Radius.circular(50),
          ),
          color: (value && !disabled)
              ? checkFillColor
              : !disabled
                  ? checkNonFillColor
                  : checkFillDisableColor),*/
      /*child: , */ // You can add a Icon instead of text also, like below.
      //child: new Icon(Icons.arrow_forward, size: 50.0, color: Colors.black38)),
    );

    //Create List row according list type
    Widget getTileWidgetType({dynamic singleRowData, int index}) {
      Widget tempRowView = Container();
      switch (this.listViewType) {
        case ListViewType.LIST_DIVIDER:
          break;
        case ListViewType.LIST_ICON:
          break;
        case ListViewType.LIST_BUTTON:
          break;
        case ListViewType.LIST_AVATAR:
          break;
        case ListViewType.LIST_THUMBNAILS:
          break;
        default: //ListViewType.LIST_ITEMS
          tempRowView = itemRowView(index: index, item: "$singleRowData");
      }
      return tempRowView;
    }

    //Main List view
    Widget getListContainer() {
      return Container(
        color: listBgColor == null ? Colors.white : listBgColor,
        child: ListView.separated(
            separatorBuilder: (context, index) => Divider(
                  color: dividerColor,
                  height: 1.0,
                  indent: 0.0,
                  endIndent: 0.0,
                ),
            //controller: scrollController,
            padding: listViewEdgeInsets,
            physics: physics ?? AlwaysScrollableScrollPhysics(),
            shrinkWrap: shrinkWrap,
            scrollDirection: scrollDirection ?? Axis.vertical,
            itemCount: getListData().length,
            itemBuilder: (context, i) {
              var textValue = getListData()[i];
              Widget tempRowView1 = Container();
              if (this.tileWidget != null &&
                  this.listViewType == ListViewType.LIST_CUSTOM_ROW_ITEMS) {
                tempRowView1 =
                    this.tileWidget(singleRowData: textValue, index: i);
                print("Hello");
              } else {
                tempRowView1 =
                    getTileWidgetType(singleRowData: textValue, index: i);
              }
              Widget tempRowView = tempRowView1;
              return tempRowView;
            }),
      );
    }

    return Padding(
      padding: padding,
      child: getListContainer(),
    );
  }

  //Get list according list type
  List<dynamic> getListData() {
    List<dynamic> listData = [];
    //If user set dynamic list type
    if (this.listData !=
            null /* &&
        this.listViewType == ListViewType.LIST_CUSTOM_ROW_ITEMS*/
        ) {
      listData.addAll(this.listData);
    } else {
      switch (this.listViewType) {
        case ListViewType.LIST_DIVIDER:
          break;
        case ListViewType.LIST_ICON:
          break;
        case ListViewType.LIST_BUTTON:
          break;
        case ListViewType.LIST_AVATAR:
          break;
        case ListViewType.LIST_THUMBNAILS:
          break;
        default: //ListViewType.LIST_ITEMS
          listData.addAll(["Mobile", "Laptop", "Keyboard"]);
      }
    }
    return listData;
  }

  //Single list row for item list type
  Widget itemRowView({String item, int index}) {
    Widget tempRowView = Container(
      color: Colors.white,
      height: 50,
      width: double.infinity,
      padding: EdgeInsets.symmetric(horizontal: 15, vertical: 5),
      child: Align(alignment: Alignment.centerLeft, child: Text("$item")),
    );
    return tempRowView;
  }
}
				
			

Avatar List 

Avatar lists are made up of multiple rows of items with circular components that usually wrap an image or icon. They can be used to represent a person or an object.

Use the Avatar List if:

  • If you need to show items related with persons or products

Do not Use the Avatar List if:

  • Do not use if you have limited space and speed available.
  • If you have feature items.

Precautions:

  • Recommend to align circular components properly and keep image size respectively.

Mobile Screen View


# Usage

Avatar List
Create divider_avatar_list_page.dart file and paste the below code and call this file in your main.dart file.

First .dart file > divider_avatar_list_page.dart (New)

				
					import 'dart:io';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:fullter_main_app/src/api_calling/api_constant.dart';
import 'package:fullter_main_app/src/widgets/android_ios_check_box.dart';
import 'package:fullter_main_app/src/widgets/badge.dart';
import 'package:fullter_main_app/src/widgets/dividerListCustom.dart';
import 'package:fullter_main_app/src/widgets/icon_right_with_text.dart';
import 'package:fullter_main_app/src/widgets/labeled_check_box.dart';
import 'package:fullter_main_app/src/widgets/listViewCustom.dart';

class DividerAvatarListPage extends StatefulWidget {
  DividerAvatarListPage({Key key}) : super(key: key);
  @override
  _DividerAvatarListPageState createState() => _DividerAvatarListPageState();
}

class _DividerAvatarListPageState extends State<DividerAvatarListPage> {
  @override
  void dispose() {
    // TODO: implement dispose
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    //Center View
    Widget _centerView() {
      return Container(
        margin: EdgeInsets.symmetric(horizontal: 0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          mainAxisAlignment: MainAxisAlignment.start,
          mainAxisSize: MainAxisSize.min,
          children: <Widget>[
            AndroidIosCheckbox(
              onChanged: () {
                setState(() {});
              },
            ),
            DividerListCustom(
              shrinkWrap: true,
              dividerListViewType: DividerListViewType.LIST_AVATAR,
            ),
          ],
        ),
      );
    }

    //Back Press
    _onBackPressed() {
      print("ok");
      Navigator.pop(context);
      print("ok");
    }

    return WillPopScope(
        onWillPop: _onBackPressed,
        child: Container(
            color: Colors.transparent,
            child: SafeArea(
                bottom: false,
                child: Scaffold(
                  backgroundColor: Colors.white,
                  //appBar:_appBar(),
                  body: Container(
                    color: Colors.white,
                    child: _centerView(),
                  ),
                ))));
  }
}
				
			

Create avatar_left_with_data.dart file and paste the below code
Second .dart file > avatar_left_with_data.dart

				
					import 'package:flutter/material.dart';
import 'package:fullter_main_app/src/widgets/avatar_image.dart';

class AvatarLeftWithData extends StatefulWidget {
  final String avatarPath;
  final int index;
  final Widget rightWidget;
  final double viewHeight;
  final Size avatarViewSize;
  final EdgeInsets padding;

  AvatarLeftWithData({
    @required this.avatarPath,
    @required this.index,
    this.rightWidget = const Text("data"),
    this.viewHeight = 100,
    this.avatarViewSize = const Size(60, 60),
    this.padding = const EdgeInsets.symmetric(vertical: 0, horizontal: 10),
  });

  @override
  _AvatarLeftWithDataState createState() => _AvatarLeftWithDataState();
}

class _AvatarLeftWithDataState extends State<AvatarLeftWithData> {
  @override
  Widget build(BuildContext context) {
    Widget _buildAvatarView() {
      return SizedBox(
        height: widget.avatarViewSize.height,
        width: widget.avatarViewSize.width,
        child: AvatarImage(
          height: widget.avatarViewSize.height,
          width: widget.avatarViewSize.width,
          image: widget.avatarPath != null
              ? widget.avatarPath
              : "https://upload.wikimedia.org/wikipedia/commons/4/44/Zonal_Councils.svg",
          name: "NA",
        ),
      );
    }

    Widget _buildText() {
      return widget.rightWidget;
    }

    return Container(
      height: widget.viewHeight,
      padding: widget.padding,
      child: Row(
        crossAxisAlignment: CrossAxisAlignment.center,
        mainAxisAlignment: MainAxisAlignment.start,
        children: [
          _buildAvatarView(),
          SizedBox(
            width: 10,
          ),
          _buildText()
        ],
      ),
    );
  }
}
				
			

Custom Switch (toggle) 

A custom switch is as same as checkbox input, except it looks different and is easier to use. It can be fully customized with desired icons, width, colors, text, corner radius, etc.

Use the Custom Switch:

  • If you need to replace two radio buttons or a single checkbox to allow users to choose between two opposing states

Do not Use the Custom Switch if:

  • Do not use it if you have multiple options to take an action.

Precautions:

  • Custom Switch generally adopted for “Activate” or “Deactivate” the function.

Mobile Screen View


# Usage

Custom Switch
Create custom_switch_page.dart file and paste the below code and call this file in your main.dart file.

First .dart file > custom_switch_page.dart (New)

				
					import 'dart:io';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:fullter_main_app/src/api_calling/api_constant.dart';
import 'package:fullter_main_app/src/widgets/DraggableFloatingActionButton.dart';
import 'package:fullter_main_app/src/widgets/android_ios_check_box.dart';
import 'package:fullter_main_app/src/widgets/badge.dart';
import 'package:fullter_main_app/src/widgets/custom_switch.dart';
import 'package:fullter_main_app/src/widgets/icon_right_with_text.dart';
import 'package:fullter_main_app/src/widgets/labeled_check_box.dart';
import 'package:fullter_main_app/src/widgets/listViewCustom.dart';

class CustomSwitchPage extends StatefulWidget {
  CustomSwitchPage({Key key}) : super(key: key);
  @override
  _CustomSwitchPageState createState() => _CustomSwitchPageState();
}

class _CustomSwitchPageState extends State<CustomSwitchPage> {
  bool status1 = false;
  bool status2 = true;
  bool status3 = false;
  bool status4 = false;
  bool status5 = false;
  bool status6 = false;
  bool status7 = false;
  bool status8 = false;
  bool isSwitchOn = false;

  Color _textColor = Colors.black;
  Color _appBarColor = Color.fromRGBO(36, 41, 46, 1);
  Color __scaffoldBgColor = Colors.white;

  DraggableFloatingActionButtonController
      mDraggableFloatingActionButtonController =
      DraggableFloatingActionButtonController();

  @override
  Widget build(BuildContext context) {
    return Theme(
      data: ThemeData(
        textTheme: TextTheme(
          bodyText1: TextStyle(color: _textColor),
          bodyText2: TextStyle(color: _textColor),
        ),
      ),
      child: Scaffold(
        backgroundColor: __scaffoldBgColor,
        appBar: AppBar(
          backgroundColor: _appBarColor,
          title: Text(
            "CustomSwitch Demo",
            style: TextStyle(color: Colors.white),
          ),
          actions: [
            CustomSwitch(
              value: isSwitchOn,
              onToggle: (value) {
                setState(() {
                  isSwitchOn = value;
                });
              },
            ),
          ],
        ),
        body: SingleChildScrollView(
          child: Padding(
            padding: EdgeInsets.all(10.0),
            child: Stack(
              children: [
                Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: <Widget>[
                    Text("Default"),
                    SizedBox(height: 10.0),
                    Row(
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      children: <Widget>[
                        CustomSwitch(
                          isAndroid: ConstantC.isAndroidPlatform,
                          value: status1,
                          onToggle: (val) {
                            setState(() {
                              status1 = val;
                            });
                          },
                        ),
                        Container(
                          alignment: Alignment.centerRight,
                          child: Text(
                            "Value: $status1",
                          ),
                        ),
                      ],
                    ),
                    Text("Default"),
                    SizedBox(height: 10.0),
                    Row(
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      children: <Widget>[
                        CustomSwitch(
                          isAndroid: ConstantC.isAndroidPlatform,
                          value: status1,
                          onToggle: (val) {
                            setState(() {
                              status1 = val;
                            });
                          },
                        ),
                        Container(
                          alignment: Alignment.centerRight,
                          child: Text(
                            "Value: $status1",
                          ),
                        ),
                      ],
                    ),
                    SizedBox(height: 20.0),
                    Text("Custom Colors and Borders"),
                    SizedBox(height: 10.0),
                    Row(
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      children: <Widget>[
                        CustomSwitch(
                          isAndroid: ConstantC.isAndroidPlatform,
                          width: 100.0,
                          height: 55.0,
                          toggleSize: 45.0,
                          value: status2,
                          borderRadius: 30.0,
                          padding: 2.0,
                          toggleColor: Color.fromRGBO(225, 225, 225, 1),
                          switchBorder: Border.all(
                            color: Color.fromRGBO(2, 107, 206, 1),
                            width: 6.0,
                          ),
                          toggleBorder: Border.all(
                            color: Color.fromRGBO(2, 107, 206, 1),
                            width: 5.0,
                          ),
                          activeColor: Color.fromRGBO(51, 226, 255, 1),
                          inactiveColor: Colors.black38,
                          onToggle: (val) {
                            setState(() {
                              status2 = val;
                            });
                          },
                        ),
                        Container(
                          alignment: Alignment.centerRight,
                          child: Text(
                            "Value: $status2",
                          ),
                        ),
                      ],
                    ),
                    SizedBox(height: 20.0),
                    Text("With 'On' and 'Off' text and custom text colors"),
                    SizedBox(height: 10.0),
                    Row(
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      children: <Widget>[
                        CustomSwitch(
                          isAndroid: ConstantC.isAndroidPlatform,
                          showOnOff: true,
                          activeTextColor: Colors.black,
                          inactiveTextColor: Colors.blue[50],
                          value: status3,
                          onToggle: (val) {
                            setState(() {
                              status3 = val;
                            });
                          },
                        ),
                        Container(
                          alignment: Alignment.centerRight,
                          child: Text(
                            "Value: $status3",
                          ),
                        ),
                      ],
                    ),
                    SizedBox(height: 20.0),
                    Text("Custom size"),
                    SizedBox(height: 10.0),
                    Row(
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      children: <Widget>[
                        CustomSwitch(
                          isAndroid: ConstantC.isAndroidPlatform,
                          width: 55.0,
                          height: 25.0,
                          valueFontSize: 12.0,
                          toggleSize: 18.0,
                          value: status4,
                          onToggle: (val) {
                            setState(() {
                              status4 = val;
                            });
                          },
                        ),
                        Container(
                          alignment: Alignment.centerRight,
                          child: Text(
                            "Value: $status4",
                          ),
                        ),
                      ],
                    ),
                    SizedBox(height: 20.0),
                    Text("Custom border radius and padding"),
                    SizedBox(height: 10.0),
                    Row(
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      children: <Widget>[
                        CustomSwitch(
                          isAndroid: ConstantC.isAndroidPlatform,
                          width: 125.0,
                          height: 55.0,
                          valueFontSize: 25.0,
                          toggleSize: 45.0,
                          value: status5,
                          borderRadius: 30.0,
                          padding: 8.0,
                          showOnOff: true,
                          onToggle: (val) {
                            setState(() {
                              status5 = val;
                            });
                          },
                        ),
                        Container(
                          alignment: Alignment.centerRight,
                          child: Text(
                            "Value: $status5",
                          ),
                        ),
                      ],
                    ),
                    SizedBox(height: 20.0),
                    Text("Custom text"),
                    SizedBox(height: 10.0),
                    Row(
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      children: <Widget>[
                        CustomSwitch(
                          isAndroid: ConstantC.isAndroidPlatform,
                          activeText: "All Good. Negative.",
                          inactiveText: "Under Quarantine.",
                          value: status6,
                          valueFontSize: 10.0,
                          width: 110,
                          borderRadius: 30.0,
                          showOnOff: true,
                          onToggle: (val) {
                            setState(() {
                              status6 = val;
                            });
                          },
                        ),
                        Container(
                          alignment: Alignment.centerRight,
                          child: Text(
                            "Value: $status6",
                          ),
                        ),
                      ],
                    ),
                    SizedBox(height: 20.0),
                    Text("Icon in toggle"),
                    Text(
                      "Inspired by the colors from Github Dark Mode switch",
                      style: TextStyle(
                        fontSize: 12.0,
                        fontStyle: FontStyle.italic,
                      ),
                    ),
                    SizedBox(height: 10.0),
                    Row(
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      children: <Widget>[
                        CustomSwitch(
                          isAndroid: ConstantC.isAndroidPlatform,
                          width: 100.0,
                          height: 55.0,
                          toggleSize: 45.0,
                          value: status7,
                          borderRadius: 30.0,
                          padding: 2.0,
                          activeToggleColor: Color(0xFF6E40C9),
                          inactiveToggleColor: Color(0xFF2F363D),
                          activeSwitchBorder: Border.all(
                            color: Color(0xFF3C1E70),
                            width: 6.0,
                          ),
                          inactiveSwitchBorder: Border.all(
                            color: Color(0xFFD1D5DA),
                            width: 6.0,
                          ),
                          activeColor: Color(0xFF271052),
                          inactiveColor: Colors.white,
                          activeIcon: Icon(
                            Icons.nightlight_round,
                            color: Color(0xFFF8E3A1),
                          ),
                          inactiveIcon: Icon(
                            Icons.wb_sunny,
                            color: Color(0xFFFFDF5D),
                          ),
                          onToggle: (val) {
                            setState(() {
                              status7 = val;

                              if (val) {
                                _textColor = Colors.white;
                                _appBarColor = Color.fromRGBO(22, 27, 34, 1);
                                __scaffoldBgColor = Color(0xFF0D1117);
                              } else {
                                _textColor = Colors.black;
                                _appBarColor = Color.fromRGBO(36, 41, 46, 1);
                                __scaffoldBgColor = Colors.white;
                              }
                            });
                          },
                        ),
                        Container(
                          alignment: Alignment.centerRight,
                          child: Text("Value: $status7"),
                        ),
                      ],
                    ),
                    SizedBox(height: 20.0),
                    Text("Image as toggle icon"),
                    SizedBox(height: 10.0),
                    Row(
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      children: <Widget>[
                        CustomSwitch(
                          isAndroid: ConstantC.isAndroidPlatform,
                          width: 100.0,
                          height: 55.0,
                          toggleSize: 45.0,
                          value: status8,
                          borderRadius: 30.0,
                          padding: 2.0,
                          activeToggleColor: Color(0xFF0082C8),
                          inactiveToggleColor: Color(0xFF01579B),
                          activeSwitchBorder: Border.all(
                            color: Color(0xFF00D2B8),
                            width: 6.0,
                          ),
                          inactiveSwitchBorder: Border.all(
                            color: Color(0xFF29B6F6),
                            width: 6.0,
                          ),
                          activeColor: Color(0xFF55DDCA),
                          inactiveColor: Color(0xFF54C5F8),
                          activeIcon: Image.network(
                            "https://img2.pngio.com/functional-bits-in-flutter-flutter-community-medium-flutter-png-1000_1000.png",
                          ),
                          inactiveIcon: Image.network(
                            "https://upload.wikimedia.org/wikipedia/commons/7/7e/Dart-logo.png",
                          ),
                          onToggle: (val) {
                            setState(() {
                              status8 = val;
                            });
                          },
                        ),
                        Container(
                          alignment: Alignment.centerRight,
                          child: Text("Value: $status8"),
                        ),
                      ],
                    ),
                  ],
                ),
                DraggableFloatingActionButton(
                    controller: mDraggableFloatingActionButtonController,
                    childViewSize: Size(250, 120),
                    childView: AndroidIosCheckbox(
                      onChanged: () {
                        mDraggableFloatingActionButtonController
                            .callToCollapse();
                        setState(() {});
                      },
                    ),
                    appContext: context,
                    data: 'Demo',
                    offset: new Offset(100, 100),
                    backgroundColor: Colors.white,
                    child: Icon(
                      Icons.wb_incandescent,
                      color: ConstantC.isAndroidPlatform
                          ? Colors.green
                          : Colors.yellow,
                    ) /*,
                            childSelected: new Icon(
                              Icons.wb_incandescent,
                              color: Colors.green,
                            )*/
                    ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}
				
			

Create custom_switch.dart file and paste the below code
Second .dart file > custom_switch.dart

 

				
					import 'dart:io';

import 'package:flutter/material.dart';

class CustomSwitch extends StatefulWidget {
  /// Creates a material design switch.
  ///
  /// The following arguments are required:
  ///
  /// * [value] determines whether this switch is on or off.
  /// * [onToggle] is called when the user toggles the switch on or off.
  ///
  const CustomSwitch({
    Key key,
    @required this.value,
    @required this.onToggle,
    this.activeColor = Colors.blue,
    this.inactiveColor = Colors.grey,
    this.activeTextColor = Colors.white70,
    this.inactiveTextColor = Colors.white70,
    this.toggleColor = Colors.white,
    this.activeToggleColor,
    this.inactiveToggleColor,
    this.width = 70.0,
    this.height = 35.0,
    this.toggleSize = 25.0,
    this.valueFontSize = 16.0,
    this.borderRadius = 20.0,
    this.padding = 4.0,
    this.showOnOff = false,
    this.activeText,
    this.inactiveText,
    this.activeTextFontWeight,
    this.inactiveTextFontWeight,
    this.switchBorder,
    this.activeSwitchBorder,
    this.inactiveSwitchBorder,
    this.toggleBorder,
    this.activeToggleBorder,
    this.inactiveToggleBorder,
    this.activeIcon,
    this.inactiveIcon,
    this.isAndroid = false,
    this.duration = const Duration(milliseconds: 200),
    this.disabled = false,
  })  : assert(
            (switchBorder == null || activeSwitchBorder == null) &&
                (switchBorder == null || inactiveSwitchBorder == null),
            'Cannot provide switchBorder when an activeSwitchBorder or inactiveSwitchBorder was given\n'
            'To give the switch a border, use "activeSwitchBorder: border" or "inactiveSwitchBorder: border".'),
        assert(
            (toggleBorder == null || activeToggleBorder == null) &&
                (toggleBorder == null || inactiveToggleBorder == null),
            'Cannot provide toggleBorder when an activeToggleBorder or inactiveToggleBorder was given\n'
            'To give the toggle a border, use "activeToggleBorder: color" or "inactiveToggleBorder: color".'),
        super(key: key);

  final bool isAndroid;

  /// Determines if the switch is on or off.
  ///
  /// This property is required.
  final bool value;

  /// Called when the user toggles the switch.
  ///
  /// This property is required.
  ///
  /// [onToggle] should update the state of the parent [StatefulWidget]
  /// using the [setState] method, so that the parent gets rebuilt; for example:
  ///
  /// ```dart
  /// CustomSwitch(
  ///   value: _status,
  ///   width: 110,
  ///   borderRadius: 30.0,
  ///   onToggle: (val) {
  ///     setState(() {
  ///        _status = val;
  ///     });
  ///   },
  /// ),
  /// ```
  final ValueChanged<bool> onToggle;

  /// Displays an on or off text.
  ///
  /// Text value can be override by the [activeText] and
  /// [inactiveText] properties.
  ///
  /// Defaults to 'false' if no value was given.
  final bool showOnOff;

  /// The text to display when the switch is on.
  /// This parameter is only necessary when [showOnOff] property is true.
  ///
  /// Defaults to 'On' if no value was given.
  ///
  /// To change value style, the following properties are available
  ///
  /// [activeTextColor] - The color to use on the text value when the switch is on.
  /// [activeTextFontWeight] - The font weight to use on the text value when the switch is on.
  final String activeText;

  /// The text to display when the switch is off.
  /// This parameter is only necessary when [showOnOff] property is true.
  ///
  /// Defaults to 'Off' if no value was given.
  ///
  /// To change value style, the following properties are available
  ///
  /// [inactiveTextColor] - The color to use on the text value when the switch is off.
  /// [inactiveTextFontWeight] - The font weight to use on the text value when the switch is off.
  final String inactiveText;

  /// The color to use on the switch when the switch is on.
  ///
  /// Defaults to [Colors.blue].
  final Color activeColor;

  /// The color to use on the switch when the switch is off.
  ///
  /// Defaults to [Colors.grey].
  final Color inactiveColor;

  /// The color to use on the text value when the switch is on.
  /// This parameter is only necessary when [showOnOff] property is true.
  ///
  /// Defaults to [Colors.white70].
  final Color activeTextColor;

  /// The color to use on the text value when the switch is off.
  /// This parameter is only necessary when [showOnOff] property is true.
  ///
  /// Defaults to [Colors.white70].
  final Color inactiveTextColor;

  /// The font weight to use on the text value when the switch is on.
  /// This parameter is only necessary when [showOnOff] property is true.
  ///
  /// Defaults to [FontWeight.w900].
  final FontWeight activeTextFontWeight;

  /// The font weight to use on the text value when the switch is off.
  /// This parameter is only necessary when [showOnOff] property is true.
  ///
  /// Defaults to [FontWeight.w900].
  final FontWeight inactiveTextFontWeight;

  /// The color to use on the toggle of the switch.
  ///
  /// Defaults to [Colors.white].
  ///
  /// If the [activeSwitchBorder] or [inactiveSwitchBorder] is used, this property must be null.
  final Color toggleColor;

  /// The color to use on the toggle of the switch when the given value is true.
  ///
  /// If [inactiveToggleColor] is used and this property is null. the value of
  /// [Colors.white] will be used.
  final Color activeToggleColor;

  /// The color to use on the toggle of the switch when the given value is false.
  ///
  /// If [activeToggleColor] is used and this property is null. the value of
  /// [Colors.white] will be used.
  final Color inactiveToggleColor;

  /// The given width of the switch.
  ///
  /// Defaults to a width of 70.0.
  final double width;

  /// The given height of the switch.
  ///
  /// Defaults to a height of 35.0.
  final double height;

  /// The size of the toggle of the switch.
  ///
  /// Defaults to a size of 25.0.
  final double toggleSize;

  /// The font size of the values of the switch.
  /// This parameter is only necessary when [showOnOff] property is true.
  ///
  /// Defaults to a size of 16.0.
  final double valueFontSize;

  /// The border radius of the switch.
  ///
  /// Defaults to the value of 20.0.
  final double borderRadius;

  /// The padding of the switch.
  ///
  /// Defaults to the value of 4.0.
  final double padding;

  /// The border of the switch.
  ///
  /// This property will give a uniform border to both states of the toggle
  ///
  /// If the [activeSwitchBorder] or [inactiveSwitchBorder] is used, this property must be null.
  final BoxBorder switchBorder;

  /// The border of the switch when the given value is true.
  ///
  /// This property is optional.
  final BoxBorder activeSwitchBorder;

  /// The border of the switch when the given value is false.
  ///
  /// This property is optional.
  final BoxBorder inactiveSwitchBorder;

  /// The border of the toggle.
  ///
  /// This property will give a uniform border to both states of the toggle
  ///
  /// If the [activeToggleBorder] or [inactiveToggleBorder] is used, this property must be null.
  final BoxBorder toggleBorder;

  /// The border of the toggle when the given value is true.
  ///
  /// This property is optional.
  final BoxBorder activeToggleBorder;

  /// The border of the toggle when the given value is false.
  ///
  /// This property is optional.
  final BoxBorder inactiveToggleBorder;

  /// The icon inside the toggle when the given value is true.
  /// activeIcon can be an Icon Widget, an Image or Fontawesome Icons.
  ///
  /// This property is optional.
  final Widget activeIcon;

  /// The icon inside the toggle when the given value is false.
  /// inactiveIcon can be an Icon Widget, an Image or Fontawesome Icons.
  ///
  /// This property is optional.
  final Widget inactiveIcon;

  /// The duration in milliseconds to change the state of the switch
  ///
  /// Defaults to the value of 200 milliseconds.
  final Duration duration;

  /// Determines whether the switch is disabled.
  ///
  /// Defaults to the value of false.
  final bool disabled;

  @override
  _CustomSwitchState createState() => _CustomSwitchState();
}

class _CustomSwitchState extends State<CustomSwitch>
    with SingleTickerProviderStateMixin {
  Animation _toggleAnimation;
  AnimationController _animationController;

  @override
  void initState() {
    super.initState();
    _animationController = AnimationController(
      vsync: this,
      value: widget.value ? 1.0 : 0.0,
      duration: widget.duration,
    );
    _toggleAnimation = AlignmentTween(
      begin: Alignment.centerLeft,
      end: Alignment.centerRight,
    ).animate(
      CurvedAnimation(
        parent: _animationController,
        curve: Curves.linear,
      ),
    );
  }

  @override
  void dispose() {
    _animationController.dispose();
    super.dispose();
  }

  @override
  void didUpdateWidget(CustomSwitch oldWidget) {
    super.didUpdateWidget(oldWidget);

    if (oldWidget.value == widget.value) return;

    if (widget.value)
      _animationController.forward();
    else
      _animationController.reverse();
  }

  @override
  Widget build(BuildContext context) {
    bool isAndroid = widget.isAndroid;
    //Check device platform
    /* if (Platform.isIOS) {
      isAndroid = false;
    } else if (Platform.isAndroid) {
      isAndroid = true;
    }*/
    Color _toggleColor = Colors.white;
    Color _switchColor = Colors.white;
    Border _switchBorder;
    Border _toggleBorder;

    if (widget.value) {
      _toggleColor = widget.activeToggleColor ?? widget.toggleColor;
      _switchColor = widget.activeColor;
      _switchBorder =
          widget.activeSwitchBorder as Border ?? widget.switchBorder as Border;
      _toggleBorder =
          widget.activeToggleBorder as Border ?? widget.toggleBorder as Border;
    } else {
      _toggleColor = widget.inactiveToggleColor ?? widget.toggleColor;
      _switchColor = widget.inactiveColor;
      _switchBorder = widget.inactiveSwitchBorder as Border ??
          widget.switchBorder as Border;
      _toggleBorder = widget.inactiveToggleBorder as Border ??
          widget.toggleBorder as Border;
    }

    double _textSpace = widget.width - widget.toggleSize;

    return AnimatedBuilder(
      animation: _animationController,
      builder: (context, child) {
        return Align(
          child: GestureDetector(
            onTap: () {
              if (!widget.disabled) {
                if (widget.value)
                  _animationController.forward();
                else
                  _animationController.reverse();

                widget.onToggle(!widget.value);
              }
            },
            child: Opacity(
              opacity: widget.disabled ? 0.6 : 1,
              child: isAndroid
                  ? Switch(
                      onChanged: (val) {
                        if (!widget.disabled) {
                          widget.onToggle(!widget.value);
                        }
                      },
                      value: widget.value,
                      activeColor: widget.activeToggleColor,
                      activeTrackColor: widget.activeColor,
                      inactiveThumbColor: widget.inactiveToggleColor,
                      inactiveTrackColor: widget.inactiveColor,
                    )
                  : Container(
                      width: widget.width,
                      height: widget.height,
                      padding: EdgeInsets.all(widget.padding),
                      decoration: BoxDecoration(
                        borderRadius:
                            BorderRadius.circular(widget.borderRadius),
                        color: _switchColor,
                        border: _switchBorder,
                      ),
                      child: Stack(
                        children: <Widget>[
                          AnimatedOpacity(
                            opacity: widget.value ? 1.0 : 0.0,
                            duration: widget.duration,
                            child: Container(
                              width: _textSpace,
                              padding: EdgeInsets.symmetric(horizontal: 4.0),
                              alignment: Alignment.centerLeft,
                              child: _activeText,
                            ),
                          ),
                          Align(
                            alignment: Alignment.centerRight,
                            child: AnimatedOpacity(
                              opacity: !widget.value ? 1.0 : 0.0,
                              duration: widget.duration,
                              child: Container(
                                width: _textSpace,
                                padding: EdgeInsets.symmetric(horizontal: 4.0),
                                alignment: Alignment.centerRight,
                                child: _inactiveText,
                              ),
                            ),
                          ),
                          Container(
                            child: Align(
                              alignment: _toggleAnimation.value,
                              child: Container(
                                width: widget.toggleSize,
                                height: widget.toggleSize,
                                padding: EdgeInsets.all(4.0),
                                decoration: BoxDecoration(
                                  shape: BoxShape.circle,
                                  color: _toggleColor,
                                  border: _toggleBorder,
                                ),
                                child: FittedBox(
                                  fit: BoxFit.contain,
                                  child: Container(
                                    child: Stack(
                                      children: [
                                        Center(
                                          child: AnimatedOpacity(
                                            opacity: widget.value ? 1.0 : 0.0,
                                            duration: widget.duration,
                                            child: widget.activeIcon,
                                          ),
                                        ),
                                        Center(
                                          child: AnimatedOpacity(
                                            opacity: !widget.value ? 1.0 : 0.0,
                                            duration: widget.duration,
                                            child: widget.inactiveIcon,
                                          ),
                                        ),
                                      ],
                                    ),
                                  ),
                                ),
                              ),
                            ),
                          ),
                        ],
                      ),
                    ),
            ),
          ),
        );
      },
    );
  }

  FontWeight get _activeTextFontWeight =>
      widget.activeTextFontWeight ?? FontWeight.w900;
  FontWeight get _inactiveTextFontWeight =>
      widget.inactiveTextFontWeight ?? FontWeight.w900;

  Widget get _activeText {
    if (widget.showOnOff) {
      return Text(
        widget.activeText ?? "On",
        style: TextStyle(
          color: widget.activeTextColor,
          fontWeight: _activeTextFontWeight,
          fontSize: widget.valueFontSize,
        ),
      );
    }

    return Text("");
  }

  Widget get _inactiveText {
    if (widget.showOnOff) {
      return Text(
        widget.inactiveText ?? "Off",
        style: TextStyle(
          color: widget.inactiveTextColor,
          fontWeight: _inactiveTextFontWeight,
          fontSize: widget.valueFontSize,
        ),
        textAlign: TextAlign.right,
      );
    }

    return Text("");
  }
}
				
			

Radio Button

Radio buttons allow the user to select one option in a set of options and sometimes allow for multiple selections.

Use the Radio Button:

  •  If you think that the user needs to see all available options side-by-side.

Do not use the Radio Button if:

  • Do not use it if you have only a single option to take an action.

Precautions:

  • User can see them at a glance and compare them easily.

Mobile Screen View


Properties:
radio color: For radio button color while button is active.
label: Label for Radio Button.
disabled: Assign true if you want to disable the radio button.
onChanged: It is callback function that return radio button status.
value: It is bool value for radio button initial state.

# Usage

Radio Button
Use below Code in your main dart file in body section.

First .dart file > main.dart

				
					RadioCustom(
 radioColor: Colors.pink,
 isAndroid: true, //ConstantC.isAndroidPlatform,,
 label: 'This is the label text ',
 padding: const EdgeInsets.symmetric(horizontal: 20.0),
 value: _isSelected3,
 disabled: false,
 onChanged: (bool newValue) {
   setState(() {
     _isSelected3 = newValue;
   });
 },
),

				
			


Second .dart file > For add Android and iOS platform specific style:

				
					
//Check device platform
if (Platform.isIOS) {
 isAndroid = false;
} else if (Platform.isAndroid) {
 isAndroid = true;
}

Add radio.dart file into your project:

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

enum SingingCharacter { lafayette, jefferson }

class RadioCustom extends StatelessWidget {
 RadioCustom({
   Key key,
   @required this.label,
   @required this.padding,
   @required this.value,
   @required this.onChanged,
   this.radioColor = Colors.grey, // Check rite icon color
   this.checkTextColor = Colors.black, //Check box text color
   this.disabled = false,
   this.isAndroid = false, //Fill color
 }) : super(key: key);

 final String label;
 final EdgeInsets padding;
 final bool value;
 final Function onChanged;
 final Color radioColor;
 final Color checkTextColor;
 final bool disabled;
 final bool isAndroid;

 @override
 Widget build(BuildContext context) {
   /*bool isAndroid = false;
   //Check device platform
   if(Platform.isIOS){
     isAndroid = false;
   }
   else if(Platform.isAndroid){
     isAndroid = true;
   }*/
   //Disabled color
   Color textDisabledColor = Color(0xFFefefef);
   SingingCharacter _character =
       value ? SingingCharacter.jefferson : SingingCharacter.lafayette;
   Widget androidRadio = Radio<SingingCharacter>(
     value: SingingCharacter.jefferson,
     activeColor: radioColor,
     groupValue: _character,
     onChanged: (SingingCharacter clickValue) {
       // bool  valueTemp = value;
       onChanged(!value);
       /* setState(() {
         _character = value;
       });*/
     },
   );

   //Ios check box custom
   Widget iosCheckBox = Container(
     margin: EdgeInsets.symmetric(vertical: 5),
     padding: EdgeInsets.all(
         5.0), //I used some padding without fixed width and height
     decoration: BoxDecoration(
         // You can use like this way or like the below line
         border: Border.all(
             color: Colors.transparent,
             width: 1.0,
             style: BorderStyle.solid), //Border.all
         borderRadius: BorderRadius.all(
           Radius.circular(50),
         ),
         color: Colors.transparent),
     child: (value && !disabled)
         ? Icon(
             CupertinoIcons.checkmark_alt,
             color: radioColor,
           )
         : Icon(
             CupertinoIcons.checkmark_alt,
             color: Colors.transparent,
           ), // You can add a Icon instead of text also, like below.
     //child: new Icon(Icons.arrow_forward, size: 50.0, color: Colors.black38)),
   );
   return InkWell(
     onTap: () {
       if (!disabled) {
         onChanged(!value);
       }
     },
     child: Padding(
       padding: padding,
       child: Row(
         children: <Widget>[
           isAndroid ? androidRadio : iosCheckBox,
           SizedBox(
             width: 30,
           ),
           Expanded(
               child: Text(
             label,
             style: TextStyle(
                 color: !disabled ? checkTextColor : textDisabledColor),
           )),
         ],
       ),
     ),
   );
 }
}

				
			

PopOver

A popover is a transient view that appears above other content onscreen when you tap a icon or in an area.

Use the PopOver:

  •  If you think that the user needs to see all available options side-by-side.

Do not use the PopOver  if:

  • Do not use for small screen devices.

Precautions:

  • Carefully use the CSS for it and make it responsive for different screen sizes.

Mobile Screen View


Properties:
MenuItem: MenuItem for add menus in a pop up
Title: For menu name.

# Usage

PopOver
Use below Code in your main dart file.

First .dart file > main.dart

				
					PopupMenu menu;
GlobalKey btnKey = GlobalKey();
GlobalKey btnKey2 = GlobalKey();
GlobalKey btnKey3 = GlobalKey();
GlobalKey btnKey4 = GlobalKey();
DraggableFloatingActionButtonController
mDraggableFloatingActionButtonController =
DraggableFloatingActionButtonController();
@override
void initState() {
 super.initState();

 menu = PopupMenu(items: [
    MenuItem(title: 'Mail'),
   MenuItem(title: 'Power'),
   MenuItem(title: 'Setting'),
   MenuItem(title: 'PopupMenu')
 ], onClickMenu: onClickMenu, onDismiss: onDismiss, maxColumn: 1);
}

 void stateChanged(bool isShow) {
   print('menu is ${isShow ? 'showing' : 'closed'}');
 }

 void onClickMenu(MenuItemProvider item) {
   print('Click menu -> ${item.menuTitle}');
 }

 void onDismiss() {
   print('Menu is dismiss');
 }

// This widget is the root of your application.
 @override
 Widget build(BuildContext context) {
   PopupMenu.context = context;

   return Scaffold(
     appBar: AppBar(
       title: Text("PopOver"),
       actions: <Widget>[
         // action button
         IconButton(
           key: btnKey,
           icon: Icon(Icons.access_time),
           onPressed: () {
             maxColumn();
           },
         ),
         IconButton(
           key: btnKey2,
           icon: Icon(Icons.memory),
           onPressed: () {
             maxColumn();
           },
         )
       ],
     ),
     body: Stack(
       children: [
         Container(
           child: Row(
             //mainAxisAlignment: MainAxisAlignment.start,
             children: <Widget>[
               Container(
                 width: 150,
                 child: MaterialButton(
                   height: 45.0,
                   //key: btnKey,
                   child: GestureDetector(
                       onTap: () {
                         maxColumn(btnKeyObj: btnKey3, maxColumn: 1);
                       },
                       child:
                       Container(key: btnKey3, child: Text('Show Menu'))),
                 ),
               ),
               Container(
                 width: 200,
                 child: Align(
                   alignment: Alignment.bottomRight,
                   child: GestureDetector(
                       onTap: () {
                         maxColumn(btnKeyObj: btnKey4, maxColumn: 2);
                       },
                       child: Container(key: btnKey4, child: Text('Me'))),
                 ),
               ),
             ],
           ),
         ),
        
       ],
     ),
   );
 }

 void onGesturesDemo() {
   /*Navigator.push(
   context,
   MaterialPageRoute(builder: (context) => GestureDemo()),
 );*/
 }

 void maxColumn({GlobalKey btnKeyObj, int maxColumn = 1}) {
   if (btnKeyObj == null) {
     btnKeyObj = btnKey;
   }
   PopupMenu menu = PopupMenu(
       isAndroid: true, //ConstantC.isAndroidPlatform,
       maxColumn: maxColumn,
       items: [
         MenuItem(title: 'Copy'),
         MenuItem(title: 'Power'),
         MenuItem(
    title: 'Setting',
       ),
         MenuItem(title: 'PopupMenu')
       ],
       onClickMenu: onClickMenu,
       stateChanged: stateChanged,
       onDismiss: onDismiss);
   menu.show(widgetKey: btnKeyObj);
 }

				
			

Second .dart file >Add popover_menu.dart file into your project:

				
					
import 'dart:core';
import 'dart:io';
import 'dart:math';
import 'dart:ui';
import 'package:flutter/material.dart';

abstract class MenuItemProvider {
 String get menuTitle;
 // Widget get menuImage;
 TextStyle get menuTextStyle;
 TextAlign get menuTextAlign;
}

class MenuItem extends MenuItemProvider {
 //Widget image;
 String title;
 var userInfo;
 TextStyle textStyle;
 TextAlign textAlign;

 MenuItem(
     {this.title,
     /* this.image,*/ this.userInfo,
     this.textStyle,
     this.textAlign});


 @override
 String get menuTitle => title;

 @override
 TextStyle get menuTextStyle =>
     textStyle ?? TextStyle(color: Colors.black, fontSize: 14.0);

 @override
 TextAlign get menuTextAlign => textAlign ?? TextAlign.left;
}

enum MenuType { big, oneLine }

typedef MenuClickCallback = Function(MenuItemProvider item);
typedef PopupMenuStateChanged = Function(bool isShow);

class PopupMenu {
 static double itemWidth = 150.0;
 static bool isAndroid = false;
 static double itemHeight = 65.0;
 static var arrowHeight = 10.0;
 OverlayEntry _entry;
 List<MenuItemProvider> items;

 /// row count
 int _row;

 /// col count
 int _col;

 /// The left top point of this menu.
 Offset _offset;

 /// Menu will show at above or under this rect
 Rect _showRect;

 /// if false menu is show above of the widget, otherwise menu is show under the widget
 bool _isDown = true;

 /// The max column count, default is 4.
 int _maxColumn;

 /// callback
 VoidCallback dismissCallback;
 MenuClickCallback onClickMenu;
 PopupMenuStateChanged stateChanged;

 Size _screenSize;

 /// Cannot be null
 static BuildContext context;

 /// style
 Color _backgroundColor;
 Color _highlightColor;
 Color _lineColor;

 /// It's showing or not.
 bool _isShow = false;
 bool get isShow => _isShow;

 PopupMenu(
     {MenuClickCallback onClickMenu,
     BuildContext context,
     VoidCallback onDismiss,
     int maxColumn,
     Color backgroundColor,
     Color highlightColor,
     Color lineColor,
     double itemWidth = 150.0,
     double itemHeight = 55.0,
     bool isAndroid = false,
     PopupMenuStateChanged stateChanged,
     List<MenuItemProvider> items}) {
   this.onClickMenu = onClickMenu;
   this.dismissCallback = onDismiss;
   this.stateChanged = stateChanged;
   this.items = items;
   this._maxColumn = maxColumn ?? 4;
   this._backgroundColor = backgroundColor ?? Colors.white54;
   this._lineColor = lineColor ?? Colors.grey;
   this._highlightColor = highlightColor ?? Colors.grey;

   PopupMenu.itemWidth = itemWidth;
   PopupMenu.itemHeight = itemHeight;

   //Check device platform
   if (Platform.isIOS) {
     PopupMenu.isAndroid = false;
   } else if (Platform.isAndroid) {
     PopupMenu.isAndroid = true;
   }

   //Set Platform accordingly menu selection it should commented for single module
   PopupMenu.isAndroid = isAndroid;

   if (context != null) {
     PopupMenu.context = context;
   }
 }

 void show({Rect rect, GlobalKey widgetKey, List<MenuItemProvider> items}) {
   if (rect == null && widgetKey == null) {
     print("'rect' and 'key' can't be both null");
     return;
   }

   this.items = items ?? this.items;
   this._showRect = rect ?? PopupMenu.getWidgetGlobalRect(widgetKey);
   this._screenSize = window.physicalSize / window.devicePixelRatio;
   this.dismissCallback = dismissCallback;

   _calculatePosition(PopupMenu.context);

   _entry = OverlayEntry(builder: (context) {
     return buildPopupMenuLayout(_offset);
   });

   Overlay.of(PopupMenu.context).insert(_entry);
   _isShow = true;
   if (this.stateChanged != null) {
     this.stateChanged(true);
   }
 }

 static Rect getWidgetGlobalRect(GlobalKey key) {
   RenderBox renderBox = key.currentContext.findRenderObject();
   var offset = renderBox.localToGlobal(Offset.zero);
   return Rect.fromLTWH(
       offset.dx, offset.dy, renderBox.size.width, renderBox.size.height);
 }

 void _calculatePosition(BuildContext context) {
   _col = _calculateColCount();
   _row = _calculateRowCount();
   _offset = _calculateOffset(PopupMenu.context);
 }

 Offset _calculateOffset(BuildContext context) {
   double dx = _showRect.left + _showRect.width / 2.0 - menuWidth() / 2.0;
   if (dx < 10.0) {
     dx = 10.0;
   }

   if (dx + menuWidth() > _screenSize.width && dx > 10.0) {
     double tempDx = _screenSize.width - menuWidth() - 10;
     if (tempDx > 10) dx = tempDx;
   }

   double dy = _showRect.top - menuHeight();
   if (dy <= MediaQuery.of(context).padding.top + 10) {
     // The have not enough space above, show menu under the widget.
     dy = arrowHeight + _showRect.height + _showRect.top;
     _isDown = false;
   } else {
     dy -= arrowHeight;
     _isDown = true;
   }

   return Offset(dx, dy);
 }

 double menuWidth() {
   return (itemWidth * _col) + 8;
 }

 // This height exclude the arrow
 double menuHeight() {
   return (itemHeight * _row);
 }

 LayoutBuilder buildPopupMenuLayout(Offset offset) {
   return LayoutBuilder(builder: (context, constraints) {
     return GestureDetector(
       behavior: HitTestBehavior.translucent,
       onTap: () {
         dismiss();
       },

       onVerticalDragStart: (DragStartDetails details) {
         dismiss();
       },
       onHorizontalDragStart: (DragStartDetails details) {
         dismiss();
       },
       child: Container(
         child: Stack(
           children: <Widget>[
             // triangle arrow
             PopupMenu.isAndroid
                 ? Container()
                 : Positioned(
                     left: _showRect.left + _showRect.width / 2.0 - 7.5,
                     top: _isDown
                         ? offset.dy + menuHeight()
                         : offset.dy - arrowHeight,
                     child: CustomPaint(
                       size: Size(15.0, arrowHeight),
                       painter: TrianglePainter(
                           isDown: _isDown, color: _backgroundColor),
                     ),
                   ),
             // menu content
             Positioned(
               left: offset.dx,
               top: offset.dy - 5,
               child: Container(
                 width: menuWidth(),
                 height: menuHeight() + 8,
                 child: Card(
                   color: _backgroundColor,
                   elevation: PopupMenu.isAndroid ? 4 : 0,
                   child: Column(
                     children: <Widget>[
                       ClipRRect(
                           borderRadius: BorderRadius.circular(10.0),
                           child: Container(
                             width: menuWidth(),
                             height: menuHeight(),
                             decoration: BoxDecoration(
                                 color: _backgroundColor,
                                 borderRadius: BorderRadius.circular(10.0)),
                             child: Column(
                               children: _createRows(),
                             ),
                           )),
                     ],
                   ),
                 ),
               ),
             )
           ],
         ),
       ),
     );
   });
 }

 List<Widget> _createRows() {
   List<Widget> rows = [];
   for (int i = 0; i < _row; i++) {
     Color color =
         (i < _row - 1 && _row != 1) ? _lineColor : Colors.transparent;
     Widget rowWidget = Container(
       /*decoration:
           BoxDecoration(border: Border(bottom: BorderSide(color: color))),*/
       height: itemHeight,
       child: Column(
         children: [
           Row(
             children: _createRowItems(i),
           ),
           Container(
             margin: EdgeInsets.only(left: 15),
             color: color,
             height: 1,
           )
         ],
       ),
     );

     rows.add(rowWidget);
   }

   return rows;
 }

 List<Widget> _createRowItems(int row) {
   List<MenuItemProvider> subItems =
       items.sublist(row * _col, min(row * _col + _col, items.length));
   List<Widget> itemWidgets = [];
   int i = 0;
   for (var item in subItems) {
     itemWidgets.add(_createMenuItem(
       item,
       i < (_col - 1),
     ));
     i++;
   }

   return itemWidgets;
 }

 // calculate row count
 int _calculateRowCount() {
   if (items == null || items.length == 0) {
     debugPrint('error menu items can not be null');
     return 0;
   }

   int itemCount = items.length;

   if (_calculateColCount() == 1) {
     return itemCount;
   }

   int row = (itemCount - 1) ~/ _calculateColCount() + 1;

   return row;
 }

 // calculate col count
 int _calculateColCount() {
   if (items == null || items.length == 0) {
     debugPrint('error menu items can not be null');
     return 0;
   }

   int itemCount = items.length;
   if (_maxColumn != 4 && _maxColumn > 0) {
     return _maxColumn;
   }

   if (itemCount == 4) {

     return 2;
   }

   if (itemCount <= _maxColumn) {
     return itemCount;
   }

   if (itemCount == 5) {
     return 3;
   }

   if (itemCount == 6) {
     return 3;
   }

   return _maxColumn;
 }

 double get screenWidth {
   double width = window.physicalSize.width;
   double ratio = window.devicePixelRatio;
   return width / ratio;
 }

 Widget _createMenuItem(MenuItemProvider item, bool showLine) {
   return _MenuItemWidget(
     item: item,
     showLine: showLine,
     clickCallback: itemClicked,
     lineColor: _lineColor,
     backgroundColor: _backgroundColor,
     highlightColor: _highlightColor,
   );
 }

 void itemClicked(MenuItemProvider item) {
   if (onClickMenu != null) {
     onClickMenu(item);
   }

   dismiss();
 }

 void dismiss() {
   if (!_isShow) {
     // Remove method should only be called once
     return;
   }

   _entry.remove();
   _isShow = false;
   if (dismissCallback != null) {
     dismissCallback();
   }

   if (this.stateChanged != null) {
     this.stateChanged(false);
   }
 }
}

class _MenuItemWidget extends StatefulWidget {
 final MenuItemProvider item;

 final bool showLine;
 final Color lineColor;
 final Color backgroundColor;
 final Color highlightColor;

 final Function(MenuItemProvider item) clickCallback;

 _MenuItemWidget(
     {this.item,
     this.showLine = false,
     this.clickCallback,
     this.lineColor,
     this.backgroundColor,
     this.highlightColor});

 @override
 State<StatefulWidget> createState() {
   return _MenuItemWidgetState();
 }
}

class _MenuItemWidgetState extends State<_MenuItemWidget> {
/*  var highlightColor = Color(0x55000000);
 var color = Color(0xff232323);*/

 var highlightColor = Color(0x55000000);
 var color = Color(0xff232323);

 @override
 void initState() {
   color = widget.backgroundColor;
   highlightColor = widget.highlightColor;
   super.initState();
 }

 @override
 Widget build(BuildContext context) {
   return GestureDetector(
     onTapDown: (details) {
       color = highlightColor;
       setState(() {});
     },
     onTapUp: (details) {
       color = widget.backgroundColor;
       setState(() {});
     },
     onLongPressEnd: (details) {
       color = widget.backgroundColor;
       setState(() {});
     },
     onTap: () {
       if (widget.clickCallback != null) {
         widget.clickCallback(widget.item);
       }
     },
     child: Container(
         width: PopupMenu.itemWidth,
         height: PopupMenu.itemHeight - 2,
         decoration: BoxDecoration(
             color: color,
             border: Border(
                 right: BorderSide(
                     color: widget.showLine
                         ? widget.lineColor
                         : Colors.transparent))),
         child: _createContent()),
   );
 }

 Widget _createContent() {
    // only text
   return Container(
     padding: EdgeInsets.symmetric(horizontal: 10),
     child: Align(
       alignment: Alignment.centerLeft,
       child: Material(
         color: Colors.transparent,
         child: Text(
           widget.item.menuTitle,
           style: widget.item.menuTextStyle,
           textAlign: widget.item.menuTextAlign,
         ),
       ),
     ),
   );
   //}
 }
}

class TrianglePainter extends CustomPainter {
 bool isDown;
 Color color;
 TrianglePainter({this.isDown = true, this.color});
 @override
 void paint(Canvas canvas, Size size) {
   Paint _paint = new Paint();
   _paint.strokeWidth = 2.0;
   _paint.color = color;
   _paint.style = PaintingStyle.fill;

   Path path = new Path();
   if (isDown) {
     path.moveTo(0.0, -1.0);
     path.lineTo(size.width, -1.0);
     path.lineTo(size.width / 2.0, size.height);
   } else {
     path.moveTo(size.width / 2.0, 0.0);
     path.lineTo(0.0, size.height + 1);
     path.lineTo(size.width, size.height + 1);
   }

   canvas.drawPath(path, _paint);
 }

 @override
 bool shouldRepaint(CustomPainter oldDelegate) {
   return true;
 }
}



				
			

Thumbnail  List 

Thumbnail lists are made up of multiple rows of items with square components that usually wrap an image or icon. They can be used to provide a preview of the full-size image.

Use the Thumbnail List if:

  • If you need to show previews of the contents.

Do not Use the Thumbnail List if:

  • Do not use if you have limited space and speed available.
  • If you have feature items.

Precautions:

  • Recommend to align square components properly and keep image size respectively.

Mobile Screen View


# Usage

Thumbnail List
Create divider_thumnail_list_page.dart file and paste the below code and call this file in your main.dart file.

First .dart file > divider_thumnail_list_page.dart (New)

				
					import 'dart:io';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:fullter_main_app/src/api_calling/api_constant.dart';
import 'package:fullter_main_app/src/widgets/android_ios_check_box.dart';
import 'package:fullter_main_app/src/widgets/badge.dart';
import 'package:fullter_main_app/src/widgets/dividerListCustom.dart';
import 'package:fullter_main_app/src/widgets/icon_right_with_text.dart';
import 'package:fullter_main_app/src/widgets/labeled_check_box.dart';
import 'package:fullter_main_app/src/widgets/listViewCustom.dart';

class DividerThumbnailListPage extends StatefulWidget {
  DividerThumbnailListPage({Key key}) : super(key: key);
  @override
  _DividerThumbnailListPageState createState() =>
      _DividerThumbnailListPageState();
}

class _DividerThumbnailListPageState extends State<DividerThumbnailListPage> {
  @override
  void dispose() {
    // TODO: implement dispose
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    //Center View
    Widget _centerView() {
      return Container(
        margin: EdgeInsets.symmetric(horizontal: 0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          mainAxisAlignment: MainAxisAlignment.start,
          mainAxisSize: MainAxisSize.min,
          children: <Widget>[
            AndroidIosCheckbox(
              onChanged: () {
                setState(() {});
              },
            ),
            DividerListCustom(
              shrinkWrap: true,
              dividerListViewType: DividerListViewType.LIST_THUMBNAILS,
            ),
          ],
        ),
      );
    }

    //Back Press
    _onBackPressed() {
      print("ok");
      Navigator.pop(context);
      print("ok");
    }

    return WillPopScope(
        onWillPop: _onBackPressed,
        child: Container(
            color: Colors.transparent,
            child: SafeArea(
                bottom: false,
                child: Scaffold(
                  backgroundColor: Colors.white,
                  //appBar:_appBar(),
                  body: Container(
                    color: Colors.white,
                    child: _centerView(),
                  ),
                ))));
  }
}
				
			


Create thumbnail_left_with_data.dart file and paste the below code
Second .dart file > thumbnail_left_with_data.dart

				
					import 'package:flutter/material.dart';
import 'package:fullter_main_app/src/widgets/thumbnail_image.dart';

class ThumbnailLeftWithData extends StatefulWidget {
  final String avatarPath;
  final int index;
  final Widget rightWidget;
  final double viewHeight;
  final Size avatarViewSize;
  final EdgeInsets padding;

  ThumbnailLeftWithData({
    @required this.avatarPath,
    @required this.index,
    this.rightWidget = const Text("data"),
    this.viewHeight = 100,
    this.avatarViewSize = const Size(95, 95),
    this.padding = const EdgeInsets.symmetric(vertical: 0, horizontal: 10),
  });

  @override
  _ThumbnailLeftWithDataState createState() => _ThumbnailLeftWithDataState();
}

class _ThumbnailLeftWithDataState extends State<ThumbnailLeftWithData> {
  @override
  Widget build(BuildContext context) {
    Widget _buildAvatarView() {
      return SizedBox(
        height: widget.avatarViewSize.height,
        width: widget.avatarViewSize.width,
        child: ThumbnailImage(
          height: widget.avatarViewSize.height,
          width: widget.avatarViewSize.width,
          image: widget.avatarPath != null
              ? widget.avatarPath
              : "https://upload.wikimedia.org/wikipedia/commons/4/44/Zonal_Councils.svg",
          name: "NA",
        ),
      );
    }

    Widget _buildText() {
      return widget.rightWidget;
    }

    return Container(
      height: widget.viewHeight,
      padding: widget.padding,
      child: Row(
        crossAxisAlignment: CrossAxisAlignment.center,
        mainAxisAlignment: MainAxisAlignment.start,
        children: [
          _buildAvatarView(),
          SizedBox(
            width: 10,
          ),
          _buildText()
        ],
      ),
    );
  }
}
				
			

Input field

The input field is used to create interactive controls for App & web-based forms in order to accept data from the user a wide variety of types of input data and control widgets are available, depending on the device and user agent.

Use the Input field if:

  • If you need to get information from User

Do not Use the Input field if:

  • Do not use it if taking simple actions through the graphical element.

Precautions:

  • Recommended using proper input types for fields like Name for characters & integer for numerical input type.

Mobile Screen View


# Usage

Input field
Use below Code in your main dart file in body section.

First .dart file > main.dart

				
					Column(
 crossAxisAlignment: CrossAxisAlignment.center,
 mainAxisAlignment: MainAxisAlignment.start,
 mainAxisSize: MainAxisSize.min,
 children: <Widget>[
   //_buildNameField(),
   _buildFloatingInputField(),
   _buildFixedLabelInputField(),
   _stackedLabelFiled(),
   SizedBox(
     height: 10,
   ),
   CommonTextField(
     //focusNode: focusNodes['email'],
     showError: true,
     errorText: errorMessages,
     controllerT: nameController,
     borderRadius: 8,
     capitalization: 2,
     inputHeight:
     (errorMessages != null && errorMessages != "") ? 65 : 50,
     inputKeyboardType: InputKeyboardType.email,
     hintText: "Name",
     placeHolderTextWidget: Text("Name"),
     onTextChange: (value) {},
     onEndEditing: (value) {},
   ),
 ],
),

				
			

Also add the following functions that return widget and variables into main dart file:

				
					TextEditingController nameController = new TextEditingController();
String errorMessages;

Widget _buildFloatingInputField() {
 return InputFieldWidget(
   keyboardType: KeyboardTypeInputFieldWidget.password,
   isFloatingLabel: true,
   labelText: "Floating Label",
 );
}

Widget _buildFixedLabelInputField() {
 return InputFieldWidget(
   keyboardType: KeyboardTypeInputFieldWidget.email,
   isFloatingLabel: false,
   labelText: "Fixed Label",
 );
}

Widget _stackedLabelFiled() {
 return InputFieldWidget(
   keyboardType: KeyboardTypeInputFieldWidget.email,
   isFloatingLabel: false,
   stackedLabelColor: true,
   labelText: "Stacked Label",
 );
}

				
			

InputKeyboardType:
inputKeyboardType is used for input field type like email, phone, text, password, number, multiLine

Add input_field.dart file into your project:

				
					
import 'package:flutter/material.dart';
import 'package:fluttercomponentuse/widget/common_text_field.dart';
import 'package:fluttercomponentuse/widget/input_field.dart';


class InputFiledPage extends StatefulWidget {
 InputFiledPage({Key key}) : super(key: key);
 @override
 _InputFiledPageState createState() => _InputFiledPageState();
}

class _InputFiledPageState extends State<InputFiledPage> {
 TextEditingController nameController = new TextEditingController();
 String errorMessages;
 @override
 void dispose() {
   // TODO: implement dispose
   super.dispose();
 }

 @override
 Widget build(BuildContext context) {
   //Password floating input field
   Widget _buildFloatingInputField() {
     return InputFieldWidget(
       keyboardType: KeyboardTypeInputFieldWidget.password,
       isFloatingLabel: true,
       labelText: "Floating Label",
     );
   }

   Widget _buildFixedLabelInputField() {
     return InputFieldWidget(
       keyboardType: KeyboardTypeInputFieldWidget.email,
       isFloatingLabel: false,
       labelText: "Fixed Label",
     );
   }

   Widget _stackedLabelFiled() {
     return InputFieldWidget(
       keyboardType: KeyboardTypeInputFieldWidget.email,
       isFloatingLabel: false,
       stackedLabelColor: true,
       labelText: "Stacked Label",
     );
   }

   //Center View
   Widget _centerView() {
     return Container(
       margin: EdgeInsets.symmetric(horizontal: 10),
       child: Column(
         crossAxisAlignment: CrossAxisAlignment.center,
         mainAxisAlignment: MainAxisAlignment.start,
         mainAxisSize: MainAxisSize.min,
         children: <Widget>[
         /*  AndroidIosCheckbox(
             onChanged: () {
               setState(() {});
             },
           ),*/
           //_buildNameField(),
           _buildFloatingInputField(),
           _buildFixedLabelInputField(),
           _stackedLabelFiled(),
           SizedBox(
             height: 10,
           ),
           CommonTextField(
             //focusNode: focusNodes['email'],
             showError: true,
             errorText: errorMessages,
             controllerT: nameController,
             borderRadius: 8,
             capitalization: 2,
             inputHeight:
                 (errorMessages != null && errorMessages != "") ? 65 : 50,
             inputKeyboardType: InputKeyboardType.email,
             hintText: "Name",
             placeHolderTextWidget: Text("Name"),
             onTextChange: (value) {},
             onEndEditing: (value) {},
           ),
           /*ListView(
             children: [

             ],
           )*/
         ],
       ),
     );
   }

   //Back Press
   _onBackPressed() {
     print("ok");
     Navigator.pop(context);
     print("ok");
   }

   return WillPopScope(
       onWillPop: _onBackPressed,
       child: Container(
           color: Colors.transparent,
           child: SafeArea(
               bottom: false,
               child: Scaffold(
                 backgroundColor: Colors.white,
                 appBar: AppBar(
                   backgroundColor: Color.fromRGBO(36, 41, 46, 1),
                   title: Text(
                     "Input Field",
                     style: TextStyle(color: Colors.white),
                   ),
                 ),
                 body: Container(
                   color: Colors.white,
                   child: _centerView(),
                 ),
               ))));
 }
}

				
			

Tab Bar

Tab Bar is a horizontal area of contain that allow for a consistent navigation experience between screens. It can contain any combination of text and icons, and is a popular method for enabling mobile navigation.

Use the Tab Bar if:

  • If you want to enabling navigation in your app.

Do not use the Tab Bar if:

  • If you have not required the navigation in your app.

Precautions:

  • Recommended to use proper icon, texts and sequence for better navigation offerings.

Mobile Screen View


# Usage

TabBar
Use the below Code in your main dart file.

First .dart file > main.dart

				
					SafeArea(
   bottom: false,
   child: Scaffold(
       backgroundColor: Colors.white.withOpacity(0.9),
       appBar: AppBar(
         backgroundColor: Color.fromRGBO(36, 41, 46, 1),
         title: Text(
           "$itemMenu",
           style: TextStyle(color: Colors.white),
         ),
       ),
       body: Container(
         //color: Colors.white,
         child: SingleChildScrollView(
           physics: BouncingScrollPhysics(),
           dragStartBehavior: DragStartBehavior.down,
           child: Container(
             margin: EdgeInsets.symmetric(horizontal: 10),
             child: Column(
               crossAxisAlignment: CrossAxisAlignment.center,
               mainAxisAlignment: MainAxisAlignment.start,
               mainAxisSize: MainAxisSize.min,
               children: <Widget>[],
             ),
           ),
         ),
       ),
       bottomNavigationBar: SafeArea(
         child: (MediaQuery.of(context).viewInsets.bottom == 0)
             ? Container(
           child: mTabBarView,
         )
             : Container(),
       )),
 )

				
			

Create the following variable in main.dart file:

				
					int selectedTabMenu = 0;
String itemMenu = "Music";
				
			

Create mTabBarView (Instance of TabBarWidget )  in main.dart file:

				
					TabBarWidget mTabBarView = TabBarWidget(
   menuClickedCallBack: onBottomIconPressed,
   enableItemColor: Colors.green,
   selectedTabMenu: selectedTabMenu,
   notificationCount: 0,
   showLabels: true,
   labelTextStyle: TextStyle(
     fontSize: 12,
   ),
   tabBarItems: [
     TabBarItemsDetails(
         menuName: "Music",
         iconData: Icon(
           Icons.music_note,
           color: Colors.green,
           size: 30.0,
         )),
     TabBarItemsDetails(
         menuName: "Movie",
         iconData: Icon(
           Icons.movie,
           color: Colors.green,
           size: 30.0,
         )),
     TabBarItemsDetails(
         menuName: "Video",
         iconData: Icon(
           Icons.video_call,
           color: Colors.green,
           size: 30.0,
         )),
     /*TabBarItemsDetails(
         menuName: "Home4",
         iconData: Icon(
           Icons.audiotrack,
           color: Colors.green,
           size: 30.0,
         )),
     TabBarItemsDetails(
         menuName: "Home5",
         iconData: Icon(
           Icons.audiotrack,
           color: Colors.green,
           size: 30.0,
         )),*/
   ]);
				
			

TabBarItems: It is an array of TabBarItemsDetails.
TabBarItemsDetails: Provide detail of tab bar menu. Please add name and icon.
SelectedTabMenu: For Initial Selected menu
showLabels: Set true for show menu name
menuClickedCallBack: Callback with taped menu index

Below is code of menuclicked callback:

				
					void onBottomIconPressed(int index) {
 setState(() {
   selectedTabMenu = index;
   if (index == 0) {
     itemMenu = "Music";
   } else if (index == 1) {
     itemMenu = "Movie";
   } else if (index == 2) {
     itemMenu = "Video";
   }
 });
}

				
			

Add tab_bar_widget.dart  file in your project:

				
					import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';


class TabBarWidget extends StatefulWidget {
 final menuClickedCallBack, selectedTabMenu;
 final int notificationCount;
 final centerBigMenu;
 final Color disableItemColor;
 final Color enableItemColor;
 final List<TabBarItemsDetails> tabBarItems;
 final bool showLabels;
 final TextStyle labelTextStyle;

 TabBarWidget(
     {this.menuClickedCallBack,
     this.selectedTabMenu,
     this.notificationCount,
     this.centerBigMenu,
     this.enableItemColor,
     this.disableItemColor,
     @required this.tabBarItems,
     this.showLabels,
     this.labelTextStyle});

 @override
 _TabBarWidgetState createState() {
   _TabBarWidgetState mBottomNavigationBarState =
       _TabBarWidgetState(this.selectedTabMenu);
   return mBottomNavigationBarState;
 }
}

class _TabBarWidgetState extends State<TabBarWidget> {
 var screenHeight, screenWidth;
 var menuClickedCallBack;
 int selectedTabMenu = 0;
 List<TabBarItemsDetails> tabBarItems = [];
 bool isBackground = true;

 _TabBarWidgetState(selectedTabMenu) {
   if (selectedTabMenu != null) {
     this.selectedTabMenu = selectedTabMenu;
   }
 }

 /*============add items for bottom bar===========*/
 addBottomBarItems() {
   if (widget.tabBarItems != null && widget.tabBarItems.length > 0) {
     if (widget.tabBarItems.length <= 5) {
       tabBarItems = [];
       tabBarItems.addAll(widget.tabBarItems);
     } else {}
   } else {}
 }

 @override
 void initState() {
   super.initState();
 }

 /*================on item tapped====================*/
 onItemTapped(int index) {
   /*setState(() {
     if (index != 4) {
       selectedTabMenu = index;
     }
   });*/
   menuClickedCallBack(index);
 }

 //Dynamic height
 double heightFullScreen() {
   try {
     MediaQueryData _mediaQueryData = MediaQuery.of(context);
     double value = _mediaQueryData.size.height;
     return value;
   } catch (e) {
     print(e);
     return 0.0;
   }
 }

//Dynamic width
 double widthFullScreen() {
   try {
     MediaQueryData _mediaQueryData = MediaQuery.of(context);
     double value = _mediaQueryData.size.width;
     return value;
   } catch (e) {
     print(e);
     return 0;
   }
 }

 @override
 Widget build(BuildContext context) {
   screenHeight = heightFullScreen();
   screenWidth = widthFullScreen();

   menuClickedCallBack = widget.menuClickedCallBack;

   if (mounted) {
     selectedTabMenu = widget.selectedTabMenu;
   }
   if (tabBarItems.length <= 0) {
     addBottomBarItems();
   }
   /*================on item tapped====================*/
   double _bottomBarHeightTemp = kBottomNavigationBarHeight + 12;
   Color _selectedItemColor = Color(0xFF4AA546);
   Color _unSelectedItemColor = Color(0xFFA3AEB5);
   Color _disabledItemColor = Color(0xFFA3AEB5);
   Color _bottomBarBgColor = Color(0xFFFFFFFF);

   double _bottomBarIconSize = _bottomBarHeightTemp / 2.5;
   double _bottomBarCenterIconSize = _bottomBarHeightTemp / 1.1;
   double _bottomBarHeight =
       _bottomBarHeightTemp; //Update app bar height according center button

   Widget menuIcon(String iconSelected, String icon, int itemIndex, int index,
       Icon iconData) {
     Widget iconTemp = Container();
     if (iconData != null) {
       Icon iconDataTemp = Icon(
         iconData.icon,
         color: (itemIndex == selectedTabMenu)
             ? widget.enableItemColor
             : (widget.disableItemColor != null
                 ? widget.disableItemColor
                 : _disabledItemColor),
         size: index == 3
             ? (widget.centerBigMenu != null
                 ? (_bottomBarCenterIconSize - 15)
                 : _bottomBarIconSize)
             : _bottomBarIconSize,
       );
       iconTemp = iconDataTemp;
     } else if (iconSelected != null) {
       if (iconSelected.contains(".svg")) {
         iconTemp = SvgPicture.asset(
             (itemIndex == selectedTabMenu) ? iconSelected : icon,
             width: index == 3
                 ? (widget.centerBigMenu != null
                     ? (_bottomBarCenterIconSize - 15)
                     : _bottomBarIconSize)
                 : _bottomBarIconSize,
             height: index == 3
                 ? (widget.centerBigMenu != null
                     ? (_bottomBarCenterIconSize - 15)
                     : _bottomBarIconSize)
                 : _bottomBarIconSize,
             color: (itemIndex == selectedTabMenu)
                 ? widget.enableItemColor
                 : (widget.disableItemColor != null
                     ? widget.disableItemColor
                     : _disabledItemColor),
             fit: BoxFit.scaleDown);
       } else {
         iconTemp = Image(
           image: AssetImage(
               (itemIndex == selectedTabMenu) ? iconSelected : icon),
           width: index == 3
               ? (widget.centerBigMenu != null
                   ? _bottomBarCenterIconSize
                   : _bottomBarIconSize)
               : _bottomBarIconSize,
           height: index == 3
               ? (widget.centerBigMenu != null
                   ? _bottomBarCenterIconSize
                   : _bottomBarIconSize)
               : _bottomBarIconSize,
           color: (itemIndex == selectedTabMenu)
               ? widget.enableItemColor
               : (widget.disableItemColor != null
                   ? widget.disableItemColor
                   : _disabledItemColor),
         );
       }
     }
     return iconTemp;
   }

   /*===========common function for bar item ===================*/
   barItems(String icon, int itemIndex, String iconSelected, int index,
       String menuName, Icon iconData) {
     return BottomNavigationBarItem(
       //backgroundColor: Colors.red,
       icon: Padding(
         padding: EdgeInsets.only(bottom: 0),
         child: menuIcon(iconSelected, icon, itemIndex, index, iconData),
       ),
       title: (widget.showLabels != null && widget.showLabels)
           ? (menuName != null
               ? Text(
                   menuName,
                   style: widget.labelTextStyle,
                 )
               : Text(""))
           : SizedBox.shrink(),
     );
   }

   /*=====================get bar items=================*/
   List<BottomNavigationBarItem> getItems() {
     if (tabBarItems != null) {
       List<BottomNavigationBarItem> items = [];
       for (int i = 0; i < tabBarItems.length; i++) {
         items.add(barItems(
             tabBarItems[i].icon,
             i,
             tabBarItems[i].iconSelected,
             (i + 1),
             tabBarItems[i].menuName,
             tabBarItems[i].iconData));
       }
       return items;
     } else {
       print('no item');
       return null;
     }
   }

   /*=====================return navigation bar view========================*/
   return SafeArea(
     child: Container(
       alignment: Alignment.topCenter,
       color: _bottomBarBgColor,
       height: (_bottomBarHeight),
       child: Stack(
         children: <Widget>[
           Positioned(
             child: Align(
               alignment: Alignment.center,
               child: SizedBox(
                 height: (_bottomBarHeight), //(_bottomBarHeight - 10)
                 child: BottomNavigationBar(
                   backgroundColor: _bottomBarBgColor,
                   type: BottomNavigationBarType.fixed,
                   elevation: 0,
                   currentIndex: selectedTabMenu,
                   selectedItemColor: _selectedItemColor,
                   unselectedItemColor: _unSelectedItemColor,
                   items: getItems(),
                   onTap: onItemTapped,
                   showSelectedLabels:
                       (widget.showLabels != null && widget.showLabels)
                           ? true
                           : false,
                   showUnselectedLabels:
                       (widget.showLabels != null && widget.showLabels)
                           ? true
                           : false,
                 ),
               ),
             ),
           ),
           Positioned(
               child: Align(
                   alignment: Alignment.center,
                   child: widget.centerBigMenu != null
                       ? Container(
                           height: widget.centerBigMenu != null
                               ? _bottomBarCenterIconSize
                               : 0,
                           width: widget.centerBigMenu != null
                               ? _bottomBarCenterIconSize
                               : 0,
                           child: widget.centerBigMenu)
                       : Container()))
         ],
       ),
     ),
   );
 }
}

class TabBarItemsDetails {
 Icon iconData;
 String icon;
 String iconSelected;
 String menuName;
 TabBarItemsDetails(
     {this.icon, this.iconSelected, this.menuName, this.iconData});
}

				
			

Select

A dropdown menu lets the user select from a number of items.

Use the select if:

  • If required only single input from the user.

Do not use the select if:

  • Do not use if required multiple inputs from the user.

Precautions:

  • Prepare a correct selection list and recommended keeping the list shorter in length.

Mobile Screen View


# Usage

Select
Use below Code in your main.dart file in body section.

First .dart file > main.dart

				
					ListViewCustom(
                   shrinkWrap: true,
                   listData: listData,
                   listViewType: ListViewType.LIST_CUSTOM_ROW_ITEMS,
                   tileWidget: ({singleRowData, index}) {
                     List<MenuItemModelAlertSelect> listOfData = [
                       MenuItemModelAlertSelect(itemName: "Playstation"),
                     MenuItemModelAlertSelect(itemName: "NAS"),
                     MenuItemModelAlertSelect(itemName: "Sega Saturn"),
                     MenuItemModelAlertSelect(itemName: "Cricket"),
                     ];
//                  if (index == 1) {
//                    listOfData = [
//                      MenuItemModelAlertSelect(itemName: "Playstation"),
//                      MenuItemModelAlertSelect(itemName: "NAS"),
//                      MenuItemModelAlertSelect(itemName: "Sega Saturn"),
//                      MenuItemModelAlertSelect(itemName: "Cricket"),
//                    ];
//                  }

                     return index == 1
                         ? SelectOptionBottomSheetView(
                       isAndroid: true, //ConstantC.isAndroidPlatform,
                       textLabel: "${listData[index]}",
                       itemList: [
                         MenuItemModelBottomSheet(itemName: "Enable"),
                         MenuItemModelBottomSheet(itemName: "Mute"),
                         MenuItemModelBottomSheet(itemName: "Mute for a week"),
                         MenuItemModelBottomSheet(itemName: "Mute for year")
                       ],
                     )
                         : SelectOptionAlertView(
                       isAndroid: true, //ConstantC.isAndroidPlatform,
                       textLabel: "${listData[index]}",
                       itemList: listOfData,
                     );
                   },
                 )

				
			

Also, initialize the list for list data or add data:

				
					listData = [
 "Gaming",
 "Notification",
];

				
			

Add select_option_alert_view.dart file into your project:

				
					import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

typedef SelectedAlertCallBack = Function({int index});

class SelectOptionAlertView extends StatefulWidget {
 final String text;
 final String textLabel;
 final TextStyle selectionOptionTextStyle;
 final Widget iconWidget;
 final List<MenuItemModelAlertSelect> itemList;
 final bool isAndroid;
 final SelectedAlertCallBack selectedCallBack;
 final int
     preSelectedIndex; //Pre selected index if we want show pre selected index from list it by default -1 means no menu selected
 SelectOptionAlertView({
   Key key,
   this.text,
   this.textLabel = "",
   this.isAndroid = false,
   this.selectedCallBack,
   this.iconWidget,
   this.preSelectedIndex = -1,
   @required this.itemList,
   this.selectionOptionTextStyle,
 }) : super(key: key);

 @override
 _SelectOptionAlertViewState createState() => _SelectOptionAlertViewState(
     selectionOptionTextStyle: selectionOptionTextStyle,
     itemList: itemList,
     isAndroid: isAndroid,
     iconWidget: iconWidget,
     preSelectedIndex: preSelectedIndex);
}

class _SelectOptionAlertViewState extends State<SelectOptionAlertView> {
 final TextStyle selectionOptionTextStyle;
 final Widget iconWidget;
 final List<MenuItemModelAlertSelect> itemList;
 final bool isAndroid;
 final int
     preSelectedIndex; //Pre selected index if we want show pre selected index from list it by default -1 means no menu selected
 String selectedItem = "";
 _SelectOptionAlertViewState({
   this.isAndroid = false,
   this.iconWidget,
   this.preSelectedIndex = -1,
   this.itemList,
   this.selectionOptionTextStyle,
 });
 @override
 Widget build(BuildContext context) {
   /*bool isAndroid = false;
   //Check device platform
   if (Platform.isIOS) {
     isAndroid = false;
   } else if (Platform.isAndroid) {
     isAndroid = true;
   }*/

   Widget selectorLabel() {
     TextStyle selectionOptionTextStyleTemp = selectionOptionTextStyle != null
         ? selectionOptionTextStyle
         : TextStyle(color: Colors.black, fontSize: 15);
     return Text(
       widget.textLabel,
       style: selectionOptionTextStyleTemp,
       textAlign: TextAlign.left,
     );
   }

   Widget selectedLabel() {
     TextStyle selectionOptionTextStyleTemp = selectionOptionTextStyle != null
         ? selectionOptionTextStyle
         : TextStyle(color: Colors.black, fontSize: 15);
     return Text(
       selectedItem,
       style: selectionOptionTextStyleTemp,
       textAlign: TextAlign.right,
     );
   }

   Widget icon() {
     return iconWidget != null
         ? iconWidget
         : Icon(
             Icons.arrow_drop_down,
             size: 25.0,
             color: CupertinoColors.black,
           );
   }

   return Material(
       child: Padding(
     padding: EdgeInsets.symmetric(vertical: 10),
     child: InkWell(
       onTap: () {
         ConfirmationAlert(
             itemList: itemList,
             alertTitle: widget.textLabel,
             isAndroid: isAndroid,
             context: context,
             noCallback: (alertContext) {},
             callBackYes: (int value) {
               if (widget.selectedCallBack != null) {
                 widget.selectedCallBack(index: value);
               }
               String itemSelected = itemList[value].itemName;
               setState(() {
                 selectedItem = itemSelected;
               });
             });
       },
       child: Row(
           mainAxisSize: MainAxisSize.max,
           mainAxisAlignment: MainAxisAlignment.spaceBetween,
           children: <Widget>[
             Container(
               child: selectorLabel(),
             ),
             Align(
                 alignment: Alignment.centerRight,
                 child: Row(
                   children: [selectedLabel(), icon()],
                 )),
           ]),
     ),
   ));
 }
}

//******************* Model ***** Start ********************
class MenuItemModelAlertSelect {
 String itemName;
 bool isSelected;
 String itemId;
 MenuItemModelAlertSelect(
     {@required this.itemName, this.isSelected = false, this.itemId = "0"});
}
//******************* Model ***** End ***********************

//****************** Menu List ****** Start ********************
typedef MenuItemListRowCallback = Function(
   {MenuItemModelAlertSelect singleRowData});

class MenuItemListView extends StatefulWidget {
 final List<MenuItemModelAlertSelect> itemList;
 final SelectedAlertCallBack selectedMenuCallBack;
 final double childRowHeight;
 final MenuItemListRowCallback rowView;

 MenuItemListView({
   Key key,
   this.itemList,
   this.selectedMenuCallBack,
   this.rowView,
   this.childRowHeight = 40.0,
 }) : super(key: key);
 @override
 _MenuItemListViewState createState() =>
     _MenuItemListViewState(itemListTemp: itemList);
}

class _MenuItemListViewState extends State<MenuItemListView> {
 List<MenuItemModelAlertSelect> itemList = [];
 int lastSelectedIndex = -1;
 _MenuItemListViewState(
     {List<MenuItemModelAlertSelect> itemListTemp = const []}) {
   itemList.addAll(itemListTemp);
   int i = 0;
   itemList.map((rowData) {
     if (rowData.isSelected) {
       MenuItemModelAlertSelect mMenuItemModel = itemList[i];
       // mMenuItemModel.isSelected = false;
       //itemList[i] = mMenuItemModel;
       lastSelectedIndex = i;
     }
     i++;
   }).toList();
 }
 //Item Tab
 void onItemTab(int index) {
   // if this item isn't selected yet, "isSelected": false -> true
   // If this item already is selected: "isSelected": true -> false
   setState(() {
     if (lastSelectedIndex == -1) {
       lastSelectedIndex = index;
     } else {
       if (lastSelectedIndex != index) {
         itemList[lastSelectedIndex].isSelected = false;
         lastSelectedIndex = index;
       } else if (lastSelectedIndex == index) {
         lastSelectedIndex = -1;
       }
     }
     itemList[index].isSelected = !itemList[index].isSelected;
   });
   //Return selected index
   if (widget.selectedMenuCallBack != null && itemList[index].isSelected) {
     widget.selectedMenuCallBack(index: index);
     //itemList[lastSelectedIndex].isSelected = false;
   } else {
     widget.selectedMenuCallBack(index: -1);
   }
 }

 @override
 Widget build(BuildContext context) {
   return ListView.builder(
     itemCount: itemList.length,
     itemBuilder: (BuildContext ctx, index) {
       return Container(
         height: widget.childRowHeight,
         child: Card(
             color: Colors.transparent,
             elevation: 0,
             shape: RoundedRectangleBorder(
                 borderRadius: BorderRadius.circular(0)),
             child: InkWell(
               onTap: () {
                 onItemTab(index);
               },
               child: widget.rowView != null
                   ? widget.rowView(singleRowData: itemList[index])
                   : Container(),
             )),
       );
     },
   );
 }
}
//****************** Menu List ****** End ********************

//***************************  Alert View *******************
typedef ContextCallback = Function(BuildContext alertContext);

class ConfirmationAlert {
 BuildContext context;
 String alertTitle;
 String positiveActionText;
 String negativeActionText;
 TextStyle textStylePositiveActionIos;
 TextStyle textStyleNegativeActionIos;

 TextStyle textStyleNegativeActionAndroid;
 TextStyle textStylePositiveActionAndroid;

 Function callBackYes;
 ContextCallback noCallback;
 bool isAndroid;
 List<MenuItemModelAlertSelect> itemList;
 double childRowHeight = 40.0;
 double popUpIdemHeight = 0.0;
 //Function onSelection;
 static int selectedIndex = -1;
 int selectedIndexLocal = -1;
 ConfirmationAlert(
     {Key key,
     @required this.context,
     this.alertTitle = "Alert",
     this.positiveActionText = "Yes",
     this.negativeActionText = "No",
     this.textStylePositiveActionIos,
     this.textStyleNegativeActionIos,
     this.itemList = const [],
     this.callBackYes,
     this.isAndroid = false,
     this.noCallback}) {
   if (selectedIndex != -1) {
     selectedIndexLocal = selectedIndex;
   }
   double height = MediaQuery.of(context).size.height;
   height = height - (height / 3);
   popUpIdemHeight = (childRowHeight * itemList.length).toDouble();
   if (popUpIdemHeight > height) {
     popUpIdemHeight = height;
   }
   confirmationAlert();
 }
 Future<bool> confirmationAlert() {
   Widget iOSView({String menuName, bool isSelected = false}) {
     TextStyle mTextStyle = TextStyle(
         color: isSelected ? CupertinoColors.activeBlue : Colors.black);
     return Row(
       mainAxisAlignment: MainAxisAlignment.spaceBetween,
       children: [
         Text(
           menuName,
           style: mTextStyle,
         ),
         !isSelected
             ? Container()
             : Icon(CupertinoIcons.checkmark_alt,
                 color: CupertinoColors.activeBlue)
       ],
     );
   }

   Widget androidView({String menuName, bool isSelected = false}) {
     TextStyle mTextStyle = TextStyle(
         color: /*isSelected ? CupertinoColors.activeBlue :*/ Colors.black);
     return Row(
       children: [
         isSelected
             ? Icon(Icons.radio_button_on, color: CupertinoColors.activeBlue)
             : Icon(Icons.radio_button_off,
                 color: CupertinoColors.inactiveGray),
         SizedBox(
           width: 15,
         ),
         Text(
           menuName,
           style: mTextStyle,
         )
       ],
     );
   }

   Widget customList = MenuItemListView(
     rowView: ({MenuItemModelAlertSelect singleRowData}) {
       return isAndroid
           ? androidView(
               menuName: singleRowData.itemName,
               isSelected: singleRowData.isSelected)
           : iOSView(
               menuName: singleRowData.itemName,
               isSelected: singleRowData.isSelected);
     },
     itemList: itemList,
     selectedMenuCallBack: ({index}) => selectedIndexLocal = index,
   );
   return showDialog(
       barrierColor: Colors.transparent,
       context: this.context,
       barrierDismissible: false,
       builder: (alertContext) {
         //mContext = context1;
         return this.isAndroid
             ? AlertDialog(
                 // backgroundColor: Colors.transparent,
                 title: new Text(this.alertTitle,
                     style:
                         new TextStyle(color: Colors.black54, fontSize: 20.0)),
                 content: Container(
                   child: customList,
                   height: popUpIdemHeight,
                 ),
                 actions: <Widget>[
                   TextButton(
                     child: buildTextNegativeAction(),
                     onPressed: () {
                       this.noCallback(alertContext);
                       Navigator.pop(alertContext);
                     },
                   ),
                   TextButton(
                     child: buildTextPositiveAction(),
                     onPressed: () {
                       selectedIndex = selectedIndexLocal;
                       if (selectedIndex != -1) {
                         this.callBackYes(selectedIndex);
                       }
                       Navigator.pop(alertContext);
                     },
                   )
                 ],
               )
             : CupertinoAlertDialog(
                 // backgroundColor: Colors.transparent,
                 title: new Text(this.alertTitle,
                     style:
                         new TextStyle(color: Colors.black54, fontSize: 20.0)),
                 content: Container(
                   child: customList,
                   height: popUpIdemHeight,
                 ),
                 actions: <Widget>[
                   TextButton(
                     child: buildTextNegativeAction(),
                     onPressed: () {
                       this.noCallback(alertContext);
                       Navigator.pop(alertContext);
                     },
                   ),
                   TextButton(
                     child: buildTextPositiveAction(),
                     onPressed: () {
                       selectedIndex = selectedIndexLocal;
                       if (selectedIndex != -1) {
                         this.callBackYes(selectedIndex);
                       }
                       Navigator.pop(alertContext);
                     },
                   )
                 ],
               );
       });
 }

 Text buildTextPositiveAction({Color textColorItem}) {
   Text textView;
   /* if (textColorItem == null) {
     textColorItem = isAndroid ? Colors.black : Colors.blue;
   }*/
   //Ios
   textView = textStylePositiveActionIos != null
       ? Text("$positiveActionText", style: textStylePositiveActionIos)
       : Text("$positiveActionText");
   //Android
   if (isAndroid) {
     textView = textStylePositiveActionAndroid != null
         ? Text("$positiveActionText", style: textStylePositiveActionAndroid)
         : Text("$positiveActionText");
   }
   return textView;
 }

 Text buildTextNegativeAction({Color textColorItem}) {
   Text textView;
   /* if (textColorItem == null) {
     textColorItem = isAndroid ? Colors.black : Colors.blue;
   }*/
   //Ios
   textView = textStyleNegativeActionIos != null
       ? Text("$negativeActionText", style: textStyleNegativeActionIos)
       : Text("$negativeActionText");
   //Android
   if (isAndroid) {
     textView = textStyleNegativeActionAndroid != null
         ? Text("$negativeActionText", style: textStylePositiveActionAndroid)
         : Text("$negativeActionText");
   }
   return textView;
 }
}
//*************** Alert View ***** End **************

				
			

Add select_option_bottom_sheet_view.dart file into your project:

				
					
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

typedef SelectedBottomSheetCallBack = Function({int index});

class SelectOptionBottomSheetView extends StatefulWidget {
 final String text;
 final String textLabel;
 final TextStyle selectionOptionTextStyle;
 final Widget iconWidget;
 final List<MenuItemModelBottomSheet> itemList;
 final bool isAndroid;
 final SelectedBottomSheetCallBack selectedCallBack;
 final int
     preSelectedIndex; //Pre selected index if we want show pre selected index from list it by default -1 means no menu selected
 SelectOptionBottomSheetView({
   Key key,
   this.text,
   this.textLabel = "",
   this.isAndroid = false,
   this.selectedCallBack,
   this.iconWidget,
   this.preSelectedIndex = -1,
   @required this.itemList,
   this.selectionOptionTextStyle,
 }) : super(key: key);

 @override
 _SelectOptionBottomSheetViewState createState() =>
     _SelectOptionBottomSheetViewState(
         selectionOptionTextStyle: selectionOptionTextStyle,
         itemList: itemList,
         isAndroid: isAndroid,
         iconWidget: iconWidget,
         preSelectedIndex: preSelectedIndex);
}

class _SelectOptionBottomSheetViewState
   extends State<SelectOptionBottomSheetView> {
 final TextStyle selectionOptionTextStyle;
 final Widget iconWidget;
 final List<MenuItemModelBottomSheet> itemList;
 final bool isAndroid;
 final int
     preSelectedIndex; //Pre selected index if we want show pre selected index from list it by default -1 means no menu selected
 String selectedItem = "";
 _SelectOptionBottomSheetViewState({
   this.isAndroid = false,
   this.iconWidget,
   this.preSelectedIndex = -1,
   this.itemList,
   this.selectionOptionTextStyle,
 });
 @override
 Widget build(BuildContext context) {
   Widget selectorLabel() {
     TextStyle selectionOptionTextStyleTemp = selectionOptionTextStyle != null
         ? selectionOptionTextStyle
         : TextStyle(color: Colors.black, fontSize: 15);
     return Text(
       widget.textLabel,
       style: selectionOptionTextStyleTemp,
       textAlign: TextAlign.left,
     );
   }

   Widget selectedLabel() {
     TextStyle selectionOptionTextStyleTemp = selectionOptionTextStyle != null
         ? selectionOptionTextStyle
         : TextStyle(color: Colors.black, fontSize: 15);
     return Text(
       selectedItem,
       style: selectionOptionTextStyleTemp,
       textAlign: TextAlign.right,
     );
   }

   Widget icon() {
     return iconWidget != null
         ? iconWidget
         : Icon(
             Icons.arrow_drop_down,
             size: 25.0,
             color: CupertinoColors.black,
           );
   }

   return Material(
       child: Padding(
     padding: EdgeInsets.symmetric(vertical: 10),
     child: InkWell(
       onTap: () {
         /*ConfirmationAlert(
             itemList: itemList,
             alertTitle: widget.textLabel,
             isAndroid: isAndroid,
             context: context,
             noCallback: (alertContext) {},
             callBackYes: (int value) {
               if (widget.selectedCallBack != null) {
                 widget.selectedCallBack(index: value);
               }
               String itemSelected = itemList[value].itemName;
               setState(() {
                 selectedItem = itemSelected;
               });
             });*/

         ActionBottomSheetModal(
           isAndroid: isAndroid,
           alertTitle: "Share option",
           itemList: itemList,
           context: context,
           selectedItemCallBack: (value) {
             if (widget.selectedCallBack != null) {
               widget.selectedCallBack(index: value);
             }
             String itemSelected = itemList[value].itemName;
             setState(() {
               selectedItem = itemSelected;
             });
           },
         );
       },
       child: Row(
           mainAxisSize: MainAxisSize.max,
           mainAxisAlignment: MainAxisAlignment.spaceBetween,
           children: <Widget>[
             Container(
               child: selectorLabel(),
             ),
             Align(
                 alignment: Alignment.centerRight,
                 child: Row(
                   children: [selectedLabel(), icon()],
                 )),
           ]),
     ),
   ));
 }
}

//******************* Model ***** Start ********************
class MenuItemModelBottomSheet {
 String itemName;
 bool isSelected;
 String itemId;
 MenuItemModelBottomSheet(
     {@required this.itemName, this.isSelected = false, this.itemId = "0"});
}
//******************* Model ***** End ***********************

//****************** Menu List ****** Start ********************
typedef MenuItemListRowCallback = Function(
   {MenuItemModelBottomSheet singleRowData});

class MenuItemListView extends StatefulWidget {
 final List<MenuItemModelBottomSheet> itemList;
 final SelectedBottomSheetCallBack selectedMenuCallBack;
 final double childRowHeight;
 final MenuItemListRowCallback rowView;

 MenuItemListView({
   Key key,
   this.itemList,
   this.selectedMenuCallBack,
   this.rowView,
   this.childRowHeight = 40.0,
 }) : super(key: key);
 @override
 _MenuItemListViewState createState() =>
     _MenuItemListViewState(itemListTemp: itemList);
}

class _MenuItemListViewState extends State<MenuItemListView> {
 List<MenuItemModelBottomSheet> itemList = [];
 int lastSelectedIndex = -1;
 _MenuItemListViewState(
     {List<MenuItemModelBottomSheet> itemListTemp = const []}) {
   itemList.addAll(itemListTemp);
   int i = 0;
   itemList.map((rowData) {
     if (rowData.isSelected) {
       MenuItemModelBottomSheet mMenuItemModel = itemList[i];
       // mMenuItemModel.isSelected = false;
       //itemList[i] = mMenuItemModel;
       lastSelectedIndex = i;
     }
     i++;
   }).toList();
 }
 //Item Tab
 void onItemTab(int index) {
   // if this item isn't selected yet, "isSelected": false -> true
   // If this item already is selected: "isSelected": true -> false
   setState(() {
     if (lastSelectedIndex == -1) {
       lastSelectedIndex = index;
     } else {
       if (lastSelectedIndex != index) {
         itemList[lastSelectedIndex].isSelected = false;
         lastSelectedIndex = index;
       } else if (lastSelectedIndex == index) {
         lastSelectedIndex = -1;
       }
     }
     itemList[index].isSelected = !itemList[index].isSelected;
   });
   //Return selected index
   if (widget.selectedMenuCallBack != null && itemList[index].isSelected) {
     widget.selectedMenuCallBack(index: index);
     //itemList[lastSelectedIndex].isSelected = false;
   } else {
     widget.selectedMenuCallBack(index: -1);
   }
 }

 @override
 Widget build(BuildContext context) {
   return ListView.builder(
     itemCount: itemList.length,
     itemBuilder: (BuildContext ctx, index) {
       return Container(
         height: widget.childRowHeight,
         child: Card(
             color: Colors.transparent,
             elevation: 0,
             shape: RoundedRectangleBorder(
                 borderRadius: BorderRadius.circular(0)),
             child: InkWell(
               onTap: () {
                 onItemTab(index);
               },
               child: widget.rowView != null
                   ? widget.rowView(singleRowData: itemList[index])
                   : Container(),
             )),
       );
     },
   );
 }
}
//****************** Menu List ****** End ********************

//Selected menu call back function type
typedef IntCallback = Function(int num);

class ItemModel {
 String menuName;
 Color itemTextColor;
 ItemModel({this.menuName = "", this.itemTextColor});
}

class ActionBottomSheetModal {
 IntCallback
     selectedItemCallBack; //Call back function it call when user click on any menu item button and return index
 VoidCallback
     cancelCallBack; //Call back function it call when user click on cancel button
 BuildContext context;
 String alertTitle = "";
 List<MenuItemModelBottomSheet> itemList;
 EdgeInsets itemMarginAllSide;
 EdgeInsets itemPaddingAllSide;
 EdgeInsets sheetPaddingAllSide;
 TextStyle styleRowItemAndroid;
 TextStyle styleRowItemIos;
 TextStyle styleRowTitleAndroid;
 TextStyle styleRowTitleIos;
 bool isAndroid;
 static int selectedIndex = -1;
 int selectedIndexLocal = -1;

 ActionBottomSheetModal({
   @required this.context,
   @required this.cancelCallBack,
   @required this.selectedItemCallBack,
   @required this.itemList,
   this.alertTitle = "Albums",
   this.isAndroid = false,
   this.itemMarginAllSide =
       const EdgeInsets.symmetric(horizontal: 15, vertical: 0),
   this.itemPaddingAllSide =
       const EdgeInsets.symmetric(horizontal: 0, vertical: 5),
   this.sheetPaddingAllSide =
       const EdgeInsets.symmetric(horizontal: 5, vertical: 5),
   this.styleRowItemAndroid,
   this.styleRowItemIos,
   this.styleRowTitleAndroid,
   this.styleRowTitleIos,
 }) {
   if (selectedIndex != -1) {
     selectedIndexLocal = selectedIndex;
   }
   //Check device platform
   /*if (Platform.isIOS) {
     this.isAndroid = false;
   } else if (Platform.isAndroid) {
     this.isAndroid = true;
   }*/
   _actionBottomSheetModal();
 }

 //Single row of items
 Widget singleItemView({@required String menuName, Color itemColor}) {
   TextStyle styleRowItemTemp =
       buildTextStyleMenuItem(textColorItem: itemColor);

   return Align(
     alignment: this.isAndroid ? Alignment.centerLeft : Alignment.center,
     child: Container(
       margin: itemMarginAllSide,
       child: ElevatedButton(
         style: ButtonStyle(
             backgroundColor: MaterialStateProperty.all(Colors.white),
             overlayColor: MaterialStateProperty.all(
                 this.isAndroid ? Colors.grey.withOpacity(0.1) : Colors.white),
             padding: MaterialStateProperty.all(itemPaddingAllSide),
             alignment:
                 this.isAndroid ? Alignment.centerLeft : Alignment.center,
             minimumSize:
                 MaterialStateProperty.all(Size(double.maxFinite, 45)),
             elevation: MaterialStateProperty.all(0.0)),
         child: Text('$menuName', style: styleRowItemTemp),
       ),
     ),
   );
 }

 //Cancel
 Widget cancelView({Color itemColor}) {
   TextStyle styleRowItemTemp =
       buildTextStyleCancelTitle(textColor: itemColor);
   return Align(
     alignment: this.isAndroid ? Alignment.centerLeft : Alignment.center,
     child: InkWell(
         onTap: () {
           if (this.cancelCallBack != null) {
             this.cancelCallBack();
           }
           Navigator.pop(context, true);
         },
         child: Container(
           margin: this.itemMarginAllSide,
           padding: this.isAndroid
               ? EdgeInsets.only(bottom: 10, top: 10)
               : EdgeInsets.only(bottom: 15, top: 15),
           child: Text('Cancel', style: styleRowItemTemp),
         )),
   );
 }

 //Title
 Widget titleView({Color itemColor}) {
   TextStyle styleRowItemTemp = buildTextStyleTitle(textColor: itemColor);
   return Align(
     alignment: this.isAndroid ? Alignment.centerLeft : Alignment.center,
     child: Container(
       margin: itemMarginAllSide,
       padding: EdgeInsets.only(bottom: 10, top: 10),
       child: Text(
         '${this.alertTitle}',
         style: styleRowItemTemp,
       ),
     ),
   );
 }

 Future<void> _actionBottomSheetModal() {
   //Item list view
   Widget titleListView() {
     return Align(
       alignment: Alignment.center,
       child: Container(
         height: 150,
         child: Expanded(
           child: MenuItemListView(
             rowView: ({MenuItemModelBottomSheet singleRowData}) {
               return singleItemView(
                   menuName: singleRowData.itemName); //singleItemView();
             },
             itemList: itemList,
             selectedMenuCallBack: ({index}) {
               selectedIndexLocal = index;
               selectedIndex = selectedIndexLocal;
               if (selectedIndex != -1) {
                 this.selectedItemCallBack(selectedIndex);
               }
               Navigator.pop(context, true);
             },
           ),
         ),
       ),
     );
   }

   return showModalBottomSheet<void>(
     isScrollControlled: false,
     context: context,
     backgroundColor: Colors.transparent,
     builder: (BuildContext context) {
       return Container(
         //height: 600,
         color: Colors.transparent,
         child: Column(
           mainAxisAlignment: MainAxisAlignment.end,
           mainAxisSize: MainAxisSize.max,
           children: [
             Card(
               elevation: this.isAndroid ? 0 : 1,
               margin: this.isAndroid
                   ? EdgeInsets.all(0)
                   : EdgeInsets.symmetric(vertical: 0, horizontal: 10),
               shape: this.isAndroid
                   ? RoundedRectangleBorder(
                       borderRadius: BorderRadius.all(Radius.circular(0.0)),
                     )
                   : RoundedRectangleBorder(
                       borderRadius: BorderRadius.all(Radius.circular(10.0)),
                     ),
               child: Column(
                 mainAxisAlignment: MainAxisAlignment.start,
                 mainAxisSize: MainAxisSize.min,
                 children: [/*titleView(),*/ titleListView()],
               ),
             ),
             Card(
                 elevation: this.isAndroid ? 0 : 1,
                 margin: this.isAndroid
                     ? EdgeInsets.all(0)
                     : EdgeInsets.symmetric(vertical: 10, horizontal: 10),
                 shape: this.isAndroid
                     ? RoundedRectangleBorder(
                         borderRadius: BorderRadius.all(Radius.circular(0.0)),
                       )
                     : RoundedRectangleBorder(
                         borderRadius: BorderRadius.all(Radius.circular(10.0)),
                       ),
                 child: cancelView())
           ],
         ),
       );
     },
   );
 }

 TextStyle buildTextStyleMenuItem({Color textColorItem}) {
   TextStyle styleRowItem;
   if (textColorItem == null) {
     textColorItem = isAndroid ? Colors.black12 : Colors.blue;
   }
   //Ios
   styleRowItem = this.styleRowItemIos != null
       ? this.styleRowItemIos
       : TextStyle(
           color: textColorItem, fontSize: 17, fontWeight: FontWeight.w600);
   //Android
   if (isAndroid) {
     styleRowItem = this.styleRowItemAndroid != null
         ? this.styleRowItemAndroid
         : TextStyle(
             color: textColorItem, fontSize: 17, fontWeight: FontWeight.w500);
   }
   return styleRowItem;
 }

 TextStyle buildTextStyleTitle({Color textColor}) {
   TextStyle styleText;
   if (textColor == null) {
     textColor = isAndroid ? Colors.black12 : Colors.blueAccent;
   }
   //ios
   styleText = this.styleRowItemIos != null
       ? this.styleRowItemIos
       : TextStyle(
           color: textColor, fontSize: 17, fontWeight: FontWeight.w600);
   //Android
   if (isAndroid) {
     styleText = this.styleRowItemAndroid != null
         ? this.styleRowItemAndroid
         : TextStyle(
             color: textColor, fontSize: 17, fontWeight: FontWeight.w500);
   }
   return styleText;
 }

 TextStyle buildTextStyleCancelTitle({Color textColor}) {
   TextStyle styleText;
   if (textColor == null) {
     textColor = isAndroid ? Colors.black12 : Colors.blueAccent;
   }
   //iOS
   styleText = this.styleRowTitleIos != null
       ? this.styleRowTitleIos
       : TextStyle(
           color: textColor, fontSize: 17, fontWeight: FontWeight.w600);
   //Android
   if (isAndroid) {
     styleText = this.styleRowTitleAndroid != null
         ? this.styleRowTitleAndroid
         : TextStyle(
             color: textColor, fontSize: 17, fontWeight: FontWeight.w500);
   }
   return styleText;
 }
}

				
			

ToolBar

Toolbars are positioned above or below content and actions related in the App. Fullscreen content will scroll behind a toolbar in a header or footer. It’s used for branding, screen titles, navigation, and actions.

Use the toolbar if:

  • If you need to display branding, screen titles, navigation, and actions on screen.

Do not use the toolbar if:

  • If you want to keep the screen clear and simple.

Precautions:

  • Use appropriate titles and actions on screen.

Mobile Screen View


# Usage

toolbar
Use the below Code in your main.dart file in body section:

First .dart file > main.dart

				
					Column(
 children: [
   ToolBarWidget(
     isAndroid: true,//ConstantC.isAndroidPlatform,
     appBarBgColor: Colors.red,
     titleStyle: TextStyle(color: Colors.white),
     context: context,
     title: "Danger",
     appBarLeftIcons: Icon(
       Icons.star,
       color: Colors.white,
     ),
     appBarRightIcons: [
       Container(
         margin: EdgeInsets.only(right: 10.0),
         child: Icon(
           Icons.menu_outlined,
           color: Colors.black,
         ),
       )
     ],
   ),
 ],
)

				
			

Properties:
isAndroid: Its bool value is set true for android default style and set false for iOS specific style.
appBarBgColor: Set background color of toolbar.
context: Pass context of current widget as a parameter.
title: Set title for toolbar.
appBarLeftIcons: It is an array of widgets that you want to show at left in the toolbar.
appBarRightIcons: It is an array of widgets that you want to show at right in the toolbar widget.

For add Android and iOS platform specific style:

				
					
//Check device platform
if (Platform.isIOS) {
 isAndroid = false;
} else if (Platform.isAndroid) {
 isAndroid = true;
}

				
			

Add tool_bar_widget.dart file into your project:

				
					
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';


class ToolBarWidget extends StatelessWidget implements PreferredSizeWidget {
 final String title;
 final TextStyle titleStyle;
 final double profileSize;
 final Widget appBarLeftIcons;
 final String notificationCount;
 final double leftIconSize;
 final double marginLeft;
 final double marginRight;
 final Color appBarBgColor;
 final Function() onPressed;
 final Function() onLeftIconPressed;
 final List<Widget> appBarRightIcons;
 final double statusBarHeight;
 final bool isAndroid;

 ToolBarWidget(
     {Key key,
     this.isAndroid = true,
     this.statusBarHeight,
     this.title = "",
     this.titleStyle,
     this.profileSize,
     this.appBarLeftIcons,
     this.notificationCount = "0",
     this.leftIconSize = 25,
     this.marginLeft = 0,
     this.marginRight = 0,
     this.appBarBgColor = const Color(0xFF00aeef),
     this.onPressed,
     this.onLeftIconPressed,
     this.appBarRightIcons,
     @required context})
     : super(key: key);

 @override
 Size get preferredSize =>
     Size.fromHeight(profileSize != null ? profileSize : 56.0);

 @override
 Widget build(BuildContext context) {
   /*bool isAndroid = false;
   //Check device platform
   if (Platform.isIOS) {
     isAndroid = false;
   } else if (Platform.isAndroid) {
     isAndroid = true;
   }*/

   TextStyle appBarT1Style(
           {Color texColor, double fontSize, fontFamily, fontWeight}) =>
       TextStyle(
         color: texColor != null ? texColor : Colors.white,
         fontSize: fontSize != null ? fontSize : 20,
         fontFamily: fontFamily,
         fontWeight: fontWeight != null ? fontWeight : FontWeight.w500,
       );

   Widget leftIcon() {
     return Center(
       child: Container(
         child: appBarLeftIcons,
       ),
     );
   }

   return AppBar(
       backgroundColor: appBarBgColor,
       elevation: 0.0,
       //For card view
       flexibleSpace: Container(
         // Add box decoration
         decoration: BoxDecoration(
           // Box decoration takes a gradient
           gradient: LinearGradient(
             // Where the linear gradient begins and ends
             begin: Alignment.centerLeft,
             end: Alignment.centerRight,
             // Add one stop for each color. Stops should increase from 0 to 1
             stops: [0.1, 0.6, 0.9],
             colors: [
               // Colors are easy thanks to Flutter's Colors class.
               Color(0xFFFFF),
               Color(0xFFFFF),
               Color(0xFFFFF),
             ],
           ),
         ),
       ),
       automaticallyImplyLeading: true,
       //`true` if you want Flutter to automatically add Back Button when needed,
       //or `false` if you want to force your own back button everywhere
       centerTitle: true,
       title: isAndroid
           ? Align(
               alignment: Alignment.centerLeft,
               child: Container(
                 padding: EdgeInsets.symmetric(horizontal: 0),
                 child: new Text(title != null ? title : "",
                     style: titleStyle != null ? titleStyle : appBarT1Style(),
                     textAlign: Text Align.center),
               ),
             )
           : Container(
               padding: EdgeInsets.symmetric(horizontal: 5),
               child: new Text(title != null ? title : "",
                   style: titleStyle != null ? titleStyle : appBarT1Style(),
                   textAlign: Text Align.center),
             ),
       leading: appBarLeftIcons == null
           ? Container()
           : Center(
               child: IconButton(
                 icon Size: leftIconSize,
                 icon: leftIcon(),
                 onPressed: () => onLeftIconPressed(),
               ),
             ),
       actions: appBarRightIcons);
 }
}

				
			

Search

A Search is an input text field. It is acting according to the search request and showing the result accordingly.

Use the search if:

  • Use it if you have huge content in the App and difficult to navigate.

Do not use the search if:

  • do not use it if you have low content in the app and want to keep the App lightweight and simple.

Precautions:

  • Make sure your code will show the right search result according to the user’s search request.

Mobile Screen View


# Usage

Search
Use the below code in your main dart file in the body section.

First .dart file > main.dart

				
					SearchView(
 isAndroid: true,//ConstantC.isAndroidPlatform,
 onCancel: _cancelSearch,
 onClear: _clearSearch,
 onUpdate: _onUpdate,
 onSubmit: _onSubmit,
)

				
			

Also add following functions into the main file:

				
					void _cancelSearch() {
 print("cancel Search");
}

void _clearSearch() {
 print("clear Search");
}

void _onUpdate(String value) {
 print("update  $value");
}

void _onSubmit(String value) {
 print("submit  $value");
}

				
			

cancelSearch: It is callback function that handles if user cancel the search.
clearSearch: It is callback function that handles if user clear the search field.
onUpdate: It is callback function that handles if user update the value in the search field.
onSubmit: It is a function called when the user submits the value for search.

For add Android and iOS platform specific style:

				
					//Check device platform
if (Platform.isIOS) {
 isAndroid = false;
} else if (Platform.isAndroid) {
 isAndroid = true;
}

				
			

Add search_view.dart file into your project:

				
					import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/cupertino.dart';

class SearchView extends StatefulWidget {
 /// The function to call when the "Cancel" button is pressed
 final Function onCancel;

 /// The function to call when the "Clear" button is pressed
 final Function onClear;

 /// The function to call when the text is updated
 final Function(String) onUpdate;

 /// The function to call when the text field is submitted
 final Function(String) onSubmit;
 final bool isAndroid;

 SearchView({
   Key key,
   this.onCancel,
   this.onClear,
   this.onSubmit,
   this.onUpdate,
   this.isAndroid = false,
 }) : super(key: key);
 @override
 _SearchViewState createState() => _SearchViewState(isAndroidTemp: isAndroid);
}

class _SearchViewState extends State<SearchView>
   with SingleTickerProviderStateMixin {
 TextEditingController _searchTextController = new TextEditingController();
 FocusNode _searchFocusNode = new FocusNode();
 Animation _animation;
 AnimationController _animationController;
 bool isAndroid = false;
 _SearchViewState({bool isAndroidTemp = false}) {
   //Check device platform
   if (Platform.isIOS) {
     isAndroid = false;
   } else if (Platform.isAndroid) {
     isAndroid = true;
   }
   /*if (isAndroidTemp != null) {
     isAndroid = isAndroidTemp;
   }*/
 }

 @override
 void dispose() {
   // TODO: implement dispose
   super.dispose();
 }

 @override
 void initState() {
   super.initState();
   _animationController = new AnimationController(
     duration: new Duration(milliseconds: 200),
     vsync: this,
   );
   _animation = new CurvedAnimation(
     parent: _animationController,
     curve: Curves.easeInOut,
     reverseCurve: Curves.easeInOut,
   );
   _searchFocusNode.addListener(() {
     if (!_animationController.isAnimating) {
       _animationController.forward();
     }
   });
 }

 @override
 Widget build(BuildContext context) {
   void _cancelSearch() {
     _searchTextController.clear();
     _searchFocusNode.unfocus();
     _animationController.reverse();
     if (widget.onCancel != null) {
       widget.onCancel();
     }
   }

   void _clearSearch() {
     _searchTextController.clear();
     if (widget.onClear != null) {
       widget.onClear();
     }
   }

   Widget _searchIos() {
     return IOSSearchBar(
       controller: this._searchTextController,
       focusNode: this._searchFocusNode,
       animation: this._animation,
       onCancel: _cancelSearch,
       onClear: _clearSearch,
       onSubmit: widget.onSubmit,
       onUpdate: widget.onUpdate,
     );
   }

   Widget _searchAndroid() {
     return AndroidSearchBar(
       controller: this._searchTextController,
       focusNode: this._searchFocusNode,
       animation: this._animation,
       onCancel: _cancelSearch,
       onClear: _clearSearch,
       onSubmit: widget.onSubmit,
       onUpdate: widget.onUpdate,
     );
   }

   return Container(
     child: isAndroid ? _searchAndroid() : _searchIos(),
   );
 }
}

/// Creates the Cupertino-style search bar. See the README for an example on how to use.
class IOSSearchBar extends AnimatedWidget {
 IOSSearchBar({
   Key key,
   @required Animation<double> animation,
   @required this.controller,
   @required this.focusNode,
   this.onCancel,
   this.onClear,
   this.onSubmit,
   this.onUpdate,
 })  : assert(controller != null),
       assert(focusNode != null),
       super(key: key, listenable: animation);

 /// The text editing controller to control the search field
 final TextEditingController controller;

 /// The focus node needed to manually unfocus on clear/cancel
 final FocusNode focusNode;

 /// The function to call when the "Cancel" button is pressed
 final Function onCancel;

 /// The function to call when the "Clear" button is pressed
 final Function onClear;

 /// The function to call when the text is updated
 final Function(String) onUpdate;

 /// The function to call when the text field is submitted
 final Function(String) onSubmit;
 static final _opacityTween = new Tween(begin: 1.0, end: 0.0);
 static final _paddingTween = new Tween(begin: 0.0, end: 60.0);
 static final _kFontSize = 13.0;
 @override
 Widget build(BuildContext context) {
   final Animation<double> animation = listenable;
   return Material(
       child: Container(
     margin: EdgeInsets.symmetric(horizontal: 5.0, vertical: 4.0),
     child: Row(children: <Widget>[
       Expanded(
           child: new Container(
               padding:
                   const EdgeInsets.symmetric(horizontal: 7.0, vertical: 0.0),
               decoration: new BoxDecoration(
                 color: /*CupertinoColors.white*/ Color(0Xffededed),
                 border: new Border.all(
                     width: 0.0,
                     color: /*CupertinoColors.white*/ Color(0Xffededed)),
                 borderRadius: new BorderRadius.circular(8.0),
               ),
               child:
                   Stack(alignment: Alignment.centerLeft, children: <Widget>[
                 Row(
                     mainAxisAlignment: MainAxisAlignment.start,
                     children: <Widget>[
                       Padding(
                           padding:
                               const EdgeInsets.fromLTRB(0.0, 0.0, 4.0, 1.0),
                           child: Icon(
                             CupertinoIcons.search,
                             color: Colors.black54,
                             size: _kFontSize + 13.0,
                           ))
                     ]),
                 Row(
                     mainAxisAlignment: MainAxisAlignment.end,
                     mainAxisSize: MainAxisSize.min,
                     children: <Widget>[
                       Expanded(
                         child: Padding(
                           padding: const EdgeInsets.only(left: 18.0),
                           child: TextField(
                             decoration: InputDecoration(
                                 contentPadding: const EdgeInsets.all(10.0),
                                 hintText: 'Search',
                                 enabledBorder: UnderlineInputBorder(
                                   borderSide:
                                       BorderSide(color: Colors.transparent),
                                 ),
                                 focusedBorder: UnderlineInputBorder(
                                     borderSide: BorderSide(
                                         color: Colors.transparent))),
                             controller: controller,
                             style: TextStyle(
                               color: Colors.black,
                               fontSize: 15.0,
                             ),
                             autocorrect: false,
                             focusNode: focusNode,
                             onChanged: onUpdate,
                             onSubmitted: onSubmit,
                             cursorColor: CupertinoColors.black,
                           ),
                         ),
                       ),
                       CupertinoButton(
                           minSize: 10.0,
                           padding: const EdgeInsets.all(1.0),
                           borderRadius: BorderRadius.circular(30.0),
                           color: CupertinoColors.inactiveGray.withOpacity(
                             1.0 - _opacityTween.evaluate(animation),
                           ),
                           child: Icon(
                             Icons.close,
                             size: 15.0,
                             color: CupertinoColors.white,
                           ),
                           onPressed: () {
                             if (animation.isDismissed)
                               return;
                             else
                               onClear();
                           })
                     ])
               ]))),
       SizedBox(
           width: _paddingTween.evaluate(animation),
           child: CupertinoButton(
               padding: const EdgeInsets.only(left: 8.0),
               onPressed: onCancel,
               child: Text('Cancel',
                   softWrap: false,
                   style: TextStyle(
                     inherit: false,
                     color: CupertinoColors.black,
                     fontSize: _kFontSize,
                   ))))
     ]),
   ));
 }
}

/// Creates the Cupertino-style search bar. See the README for an example on how to use.
class AndroidSearchBar extends AnimatedWidget {
 AndroidSearchBar({
   Key key,
   @required Animation<double> animation,
   @required this.controller,
   @required this.focusNode,
   this.onCancel,
   this.onClear,
   this.onSubmit,
   this.onUpdate,
 })  : assert(controller != null),
       assert(focusNode != null),
       super(key: key, listenable: animation);

 /// The text editing controller to control the search field
 final TextEditingController controller;

 /// The focus node needed to manually unfocus on clear/cancel
 final FocusNode focusNode;

 /// The function to call when the "Cancel" button is pressed
 final Function onCancel;

 /// The function to call when the "Clear" button is pressed
 final Function onClear;

 /// The function to call when the text is updated
 final Function(String) onUpdate;

 /// The function to call when the text field is submitted
 final Function(String) onSubmit;
 static final _opacityTween = new Tween(begin: 1.0, end: 0.0);
 static final _paddingTween = new Tween(begin: 0.0, end: 60.0);
 static final _kFontSize = 14.0;
 @override
 Widget build(BuildContext context) {
   final Animation<double> animation = listenable;
   return Material(
       child: Container(
     margin: EdgeInsets.symmetric(horizontal: 5.0, vertical: 2.0),
     child: Row(children: <Widget>[
       Expanded(
           child: Card(
         child: Container(
             padding: EdgeInsets.symmetric(horizontal: 12.0, vertical: 3.0),
             child: Stack(alignment: Alignment.centerLeft, children: <Widget>[
               Row(
                   mainAxisAlignment: MainAxisAlignment.start,
                   children: <Widget>[
                     Padding(
                         padding:
                             const EdgeInsets.fromLTRB(0.0, 0.0, 4.0, 1.0),
                         child: Icon(
                           CupertinoIcons.search,
                           color: CupertinoColors.darkBackgroundGray,
                           size: _kFontSize + 6.0,
                         ))
                   ]),
               Row(
                   mainAxisAlignment: MainAxisAlignment.end,
                   mainAxisSize: MainAxisSize.min,
                   children: <Widget>[
                     Expanded(
                       child: Padding(
                         padding: const EdgeInsets.only(left: 25.0),
                         child: TextField(
                           decoration: InputDecoration(
                               contentPadding: const EdgeInsets.all(10.0),
                               hintText: 'Search',
                               enabledBorder: UnderlineInputBorder(
                                 borderSide:
                                     BorderSide(color: Colors.transparent),
                               ),
                               focusedBorder: UnderlineInputBorder(
                                   borderSide:
                                       BorderSide(color: Colors.transparent))),
                           controller: controller,
                           style: TextStyle(
                             color: Colors.black,
                             fontSize: 15.0,
                           ),
                           autocorrect: false,
                           focusNode: focusNode,
                           onChanged: onUpdate,
                           onSubmitted: onSubmit,
                           cursorColor: CupertinoColors.black,
                         ),
                       ),
                     ),
                     CupertinoButton(
                         minSize: 20.0,
                         padding: EdgeInsets.all(0.0),
                         borderRadius: BorderRadius.circular(30.0),
                         color: Colors
                             .transparent /*CupertinoColors.inactiveGray.withOpacity(
                           1.0 - _opacityTween.evaluate(animation),
                         )*/
                         ,
                         child: Icon(
                           Icons.close,
                           size: 20.0,
                           color: CupertinoColors.black,
                         ),
                         onPressed: () {
                           if (animation.isDismissed)
                             return;
                           else
                             onClear();
                         })
                   ])
             ])),
       )) /*,
       SizedBox(
           width: _paddingTween.evaluate(animation),
           child: CupertinoButton(
               padding: const EdgeInsets.only(left: 8.0),
               onPressed: onCancel,
               child: Text('Cancel',
                   softWrap: false,
                   style: TextStyle(
                     inherit: false,
                     color: CupertinoColors.black,
                     fontSize: _kFontSize,
                   ))))*/
     ]),
   ));
 }
}