├── README.md ├── contributing.md └── snippets ├── Animated_rainBow_test ├── Custom-sunflower.md ├── Elevated_Button.md ├── alert_dialog.md ├── animated-opacity.md ├── animated_loading_button.md ├── animated_switcher.md ├── api_network_exception.md ├── api_result.md ├── autocomplete_widget.md ├── bottom_nav_animated.md ├── bottom_nav_bar_action_middle.md ├── bottom_nav_bar_curved.md ├── bottom_sheet_with_key_board.md ├── button_animation.md ├── circle_progress_indicator.md ├── convert-color-to-material-color.md ├── counter-c.md ├── counter-with-theme.md ├── counter.md ├── counter_animation.md ├── counter_widget.md ├── customScrollView-example ├── custom_calender_widget.md ├── custom_progress_indicator.md ├── customized_shimmer_for_list.md ├── customized_table_widget.md ├── date_time.md ├── disable_scroll_glow.md ├── dismissible_widget.md ├── dotted_progress_indicator.md ├── drawer.md ├── error_widget.md ├── fade_app_bar.md ├── fade_out_animation.md ├── focus_next.md ├── getx_snackbar.md ├── glowing_button.md ├── gradient_action_button.dart ├── gradient_app_bar.md ├── gradient_button.md ├── horizontal_categories_view.md ├── ignore-pointer-with-switch.md ├── image_picker_and_cropper.md ├── listview_random_color.md ├── menu_bar_animated.md ├── multiple_floating_button.md ├── my-route.md ├── nanochat.md ├── no_connection_widget.md ├── notch_curve_widget.md ├── outlined_button.md ├── overlay_progress_loader.md ├── progress_hud_widget.md ├── random_dice.md ├── repaint_boundry.md ├── rich_text.md ├── rotate_text.md ├── round-container-with-image.md ├── round_corner_image.md ├── round_ripple_animation.md ├── search_delegate.dart ├── star-image.md ├── stateful_builder_use_case.md ├── stepper.md ├── text_input_field_color_scheme.md └── toggle_animated_icon_button.md /README.md: -------------------------------------------------------------------------------- 1 | # awesome-flutter-snippets 2 | A wonderful snippet that will boost you every day. 3 | 4 | ![hf10_banner_sponsors_1032x600](https://github.com/pratikbutani/awesome-flutter-snippets/assets/3306366/d12ddfc4-fd32-4ccd-8eaf-1cb9034f92b4) 5 | 6 | ## Idea 7 | 8 | During the Hacktoberfest 2022 season, I intend to collect all of the great snippets that are highly beneficial to all Flutter devs on a daily basis.  9 | 10 | Let's work together to collect incredibly fantastic snippets from all of the amazing devs. Continue to share. 11 | 12 | ## Contributing 13 | 14 | Contributions are always welcome! 15 | 16 | See [contributing.md](https://github.com/pratikbutani/awesome-flutter-snippets/blob/main/contributing.md) for ways to get started. 17 | 18 | 19 | ## Official Links 20 | - https://hacktoberfest.com/ 21 | 22 | ## Authors 23 | 24 | - [@pratikbutani](https://www.github.com/pratikbutani) 25 | -------------------------------------------------------------------------------- /contributing.md: -------------------------------------------------------------------------------- 1 | 2 | ## How to contribute 3 | 4 | - [Fork](https://github.com/pratikbutani/awesome-flutter-snippets/fork) this repository 5 | - Clone your forked repository to your PC (`git clone "url"`) 6 | - Create a new branch to add your work (i.e. `git checkout -b your-full-name-branch`) 7 | - Checkout the [round-container-with-image.md](https://github.com/pratikbutani/awesome-flutter-snippets/blob/main/snippets/round-container-with-image.md) for sample 8 | - Create **YourSnippetName.md** file in **/snippet** folder and add your cool snippet. 9 | - You must have to add your working example on https://dartpad.dev 10 | - Add your files (`git add .`), commit (`git commit -m "few cool words for your commit message"`) and push (`git push origin your-full-name-branch`) 11 | - Create a pull request with proper title & explanation 12 | - Star this repository 🌟 13 | - Spread the love 💙 14 | -------------------------------------------------------------------------------- /snippets/Animated_rainBow_test: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_animate/flutter_animate.dart'; 3 | 4 | class VisualView extends StatelessWidget { 5 | const VisualView({Key? key}) : super(key: key); 6 | 7 | @override 8 | Widget build(BuildContext context) { 9 | // create our stylish text: 10 | Widget title = const Text( 11 | 'SOME\nVISUAL\nEFFECTS\n\n on\n\nRAINBOW\nTEXT', 12 | style: TextStyle( 13 | fontWeight: FontWeight.w900, 14 | fontSize: 64, 15 | color: Color(0xFF666870), 16 | height: 0.9, 17 | letterSpacing: -5, 18 | ), 19 | ); 20 | 21 | // add a rainbow gradient: 22 | // I'm lazy so I'll just apply a ShimmerEffect, use a ValueAdapter to 23 | // pause it half way, and let it handle the details 24 | title = title.animate(adapter: ValueAdapter(0.5)).shimmer( 25 | colors: [ 26 | const Color(0xFFFFFF00), 27 | const Color(0xFF00FF00), 28 | const Color(0xFF00FFFF), 29 | const Color(0xFF0033FF), 30 | const Color(0xFFFF00FF), 31 | const Color(0xFFFF0000), 32 | const Color(0xFFFFFF00), 33 | ], 34 | ); 35 | 36 | // sequence some visual effects 37 | title = title 38 | .animate(onPlay: (controller) => controller.repeat(reverse: true)) 39 | .saturate(delay: 1.seconds, duration: 2.seconds) 40 | .then() // set delay to when the previous effect ends. 41 | .tint(color: const Color(0xFF80DDFF)) 42 | .then() 43 | .blur(end: 24) 44 | .fadeOut(); 45 | 46 | return Padding(padding: const EdgeInsets.all(24), child: title); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /snippets/Custom-sunflower.md: -------------------------------------------------------------------------------- 1 | 2 | import 'dart:math' as math; 3 | import 'package:flutter/material.dart'; 4 | 5 | const Color primaryColor = Colors.orange; 6 | const TargetPlatform platform = TargetPlatform.android; 7 | 8 | void main() { 9 | runApp(Sunflower()); 10 | } 11 | 12 | class SunflowerPainter extends CustomPainter { 13 | static const seedRadius = 1.0; 14 | static const scaleFactor = 3; 15 | static const tau = math.pi * 8; 16 | 17 | static final phi = (math.sqrt(10) + 1) / 2; 18 | 19 | final int seeds; 20 | 21 | SunflowerPainter(this.seeds); 22 | 23 | @override 24 | void paint(Canvas canvas, Size size) { 25 | final center = size.width / 2; 26 | 27 | for (var i = 0; i < seeds; i++) { 28 | final theta = i * tau / phi; 29 | final r = math.sqrt(i) * scaleFactor; 30 | final x = center + r * math.cos(theta); 31 | final y = center - r * math.sin(theta); 32 | final offset = Offset(x, y); 33 | if (!size.contains(offset)) { 34 | continue; 35 | } 36 | drawSeed(canvas, x, y); 37 | } 38 | } 39 | 40 | @override 41 | bool shouldRepaint(SunflowerPainter oldDelegate) { 42 | return oldDelegate.seeds != seeds; 43 | } 44 | 45 | // Draw a small circle representing a seed centered at (x,y). 46 | void drawSeed(Canvas canvas, double x, double y) { 47 | final paint = Paint() 48 | ..strokeWidth = 2 49 | ..style = PaintingStyle.fill 50 | ..color = primaryColor; 51 | canvas.drawCircle(Offset(x, y), seedRadius, paint); 52 | } 53 | } 54 | 55 | class Sunflower extends StatefulWidget { 56 | @override 57 | State createState() { 58 | return _SunflowerState(); 59 | } 60 | } 61 | 62 | class _SunflowerState extends State { 63 | double seeds = 100.0; 64 | 65 | int get seedCount => seeds.floor(); 66 | 67 | @override 68 | Widget build(BuildContext context) { 69 | return MaterialApp( 70 | debugShowCheckedModeBanner: false, 71 | theme: ThemeData().copyWith( 72 | platform: platform, 73 | brightness: Brightness.dark, 74 | sliderTheme: SliderThemeData.fromPrimaryColors( 75 | primaryColor: primaryColor, 76 | primaryColorLight: primaryColor, 77 | primaryColorDark: primaryColor, 78 | valueIndicatorTextStyle: const DefaultTextStyle.fallback().style, 79 | ), 80 | ), 81 | home: Scaffold( 82 | appBar: AppBar( 83 | title: const Text("Sunflower"), 84 | ), 85 | 86 | 87 | body: Container( 88 | constraints: const BoxConstraints.expand(), 89 | decoration: BoxDecoration( 90 | border: Border.all( 91 | color: Colors.transparent, 92 | ), 93 | ), 94 | child: Column( 95 | crossAxisAlignment: CrossAxisAlignment.center, 96 | mainAxisAlignment: MainAxisAlignment.start, 97 | children: [ 98 | Container( 99 | decoration: BoxDecoration( 100 | border: Border.all( 101 | color: Colors.transparent, 102 | ), 103 | ), 104 | child: SizedBox( 105 | width: 600, 106 | height: 600, 107 | child: CustomPaint( 108 | painter: SunflowerPainter(seedCount), 109 | ), 110 | ), 111 | ), 112 | Text("Showing $seedCount seeds"), 113 | ConstrainedBox( 114 | constraints: const BoxConstraints.tightFor(width: 300), 115 | child: Slider.adaptive( 116 | min: 20, 117 | max: 20000, 118 | value: seeds, 119 | onChanged: (newValue) { 120 | setState(() { 121 | seeds = newValue; 122 | }); 123 | }, 124 | ), 125 | ), 126 | ], 127 | ), 128 | ), 129 | ), 130 | ); 131 | } 132 | } 133 | 134 | 135 | // https://dartpad.dev/?id=e9f409dd287da7552832faa48c82f35c -------------------------------------------------------------------------------- /snippets/Elevated_Button.md: -------------------------------------------------------------------------------- 1 | ``` 2 | ElevatedButton( 3 | style: ElevatedButton.styleFrom( 4 | shadowColor: Colors.black, //specify the button's elevation color 5 | elevation: 4.0, //buttons Material shadow 6 | textStyle: TextStyle(fontFamily: 'roboto'), //specify the button's text TextStyle 7 | padding: const EdgeInsets.only(top: 4.0, bottom: 4.0, right: 8.0, left: 8.0), //specify the button's Padding 8 | minimumSize: Size(20, 40), //specify the button's first: width and second: height 9 | side: BorderSide(color: Colors.yellow, width: 2.0, style: BorderStyle.solid), //set border for the button 10 | shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(35.0)), // set the buttons shape. Make its birders rounded etc 11 | enabledMouseCursor: MouseCursor.defer, //used to construct ButtonStyle.mouseCursor 12 | disabledMouseCursor: MouseCursor.uncontrolled, //used to construct ButtonStyle.mouseCursor 13 | visualDensity: VisualDensity(horizontal: 0.0, vertical: 0.0), //set the button's visual density 14 | tapTargetSize: MaterialTapTargetSize.padded, // set the MaterialTapTarget size. can set to: values, padded and shrinkWrap properties 15 | animationDuration: Duration(milliseconds: 100), //the buttons animations duration 16 | enableFeedback: true, //to set the feedback to true or false 17 | alignment: Alignment.bottomCenter, //set the button's child Alignment 18 | ), 19 | onPressed: () => {} , //set both onPressed and onLongPressed to null to see the disabled properties 20 | onLongPress: () => {}, //set both onPressed and onLongPressed to null to see the disabled properties 21 | child: Text('ElevatedButton') 22 | ), 23 | ``` 24 | DartPad:https://dartpad.dev/?id=e75b493dae1287757c5e1d77a0dc73f1 25 | -------------------------------------------------------------------------------- /snippets/alert_dialog.md: -------------------------------------------------------------------------------- 1 | ## Alert Dialog 2 | 3 | Code: 4 | ``` 5 | import 'package:flutter/material.dart'; 6 | 7 | void main() => runApp(const MyApp()); 8 | 9 | class MyApp extends StatelessWidget { 10 | const MyApp({Key? key}) : super(key: key); 11 | 12 | @override 13 | Widget build(BuildContext context) { 14 | return const MaterialApp( 15 | home: HomePage(), 16 | ); 17 | } 18 | } 19 | 20 | class HomePage extends StatefulWidget { 21 | const HomePage({Key? key}) : super(key: key); 22 | 23 | @override 24 | _HomePageState createState() => _HomePageState(); 25 | } 26 | 27 | class _HomePageState extends State { 28 | @override 29 | Widget build(BuildContext context) { 30 | return Scaffold( 31 | appBar: AppBar( 32 | title: const Text("Alert Dialog"), 33 | backgroundColor: Colors.blue, 34 | ), 35 | body: Center( 36 | child: ElevatedButton( 37 | onPressed: () { 38 | showDialog( 39 | context: context, 40 | builder: (ctx) => AlertDialog( 41 | title: const Text("Alert Dialog Box"), 42 | content: const Text("This is Alert Dialog Box"), 43 | actions: [ 44 | TextButton( 45 | onPressed: () { 46 | Navigator.of(ctx).pop(); 47 | }, 48 | style: ButtonStyle( 49 | backgroundColor: MaterialStateProperty.all(Colors.blue), 50 | shape: 51 | MaterialStateProperty.all( 52 | RoundedRectangleBorder( 53 | borderRadius: BorderRadius.circular(4.0), 54 | side: BorderSide(color: Colors.blue)))), 55 | child: 56 | const Text("Ok", style: TextStyle(color: Colors.white)), 57 | ), 58 | ], 59 | ), 60 | ); 61 | }, 62 | child: const Text("Show Alert Dialog"), 63 | ), 64 | ), 65 | ); 66 | } 67 | } 68 | 69 | ``` 70 | 71 | ## Try out on [Dartpad](https://dartpad.dev/?id=7709c07e92d609213d018d51ac00e8e5). 72 | 73 | 74 | -------------------------------------------------------------------------------- /snippets/animated-opacity.md: -------------------------------------------------------------------------------- 1 | 2 | // Use it in your code 3 | 4 | Container( 5 | alignment: Alignment.center, 6 | child: Column(children: [ 7 | AnimatedOpacity( 8 | opacity: opacityLevel, 9 | duration: const Duration(seconds: 3), 10 | child: FlutterLogo( 11 | size: 100, 12 | ), 13 | ), 14 | SizedBox(height: 50,), 15 | ElevatedButton( 16 | onPressed: _changeOpacity, 17 | child: const Text('Animated Opacity'), 18 | ), 19 | ]), 20 | ), 21 | 22 | Here is the [Dartpad](https://dartpad.dev/?id=3c9244b75040da1f33b13d47a915754b) 23 | -------------------------------------------------------------------------------- /snippets/animated_loading_button.md: -------------------------------------------------------------------------------- 1 | #animate loading button 2 | 3 | https://dartpad.dev/?id=0acad9fad5d631503e835f483fa49815 -------------------------------------------------------------------------------- /snippets/animated_switcher.md: -------------------------------------------------------------------------------- 1 | # Animated Switcher Snippet 2 | 3 | Code: 4 | ``` 5 | import 'package:flutter/material.dart'; 6 | 7 | void main() { 8 | runApp(const MyApp()); 9 | } 10 | 11 | class MyApp extends StatelessWidget { 12 | const MyApp({Key? key}) : super(key: key); 13 | 14 | // This widget is the root of your application. 15 | @override 16 | Widget build(BuildContext context) { 17 | return MaterialApp( 18 | debugShowCheckedModeBanner: false, 19 | title: 'Flutter Demo', 20 | theme: ThemeData( 21 | primarySwatch: Colors.blue, 22 | ), 23 | home: const MyHomePage(title: 'Animated Switcher Demo'), 24 | ); 25 | } 26 | } 27 | 28 | class MyHomePage extends StatefulWidget { 29 | const MyHomePage({Key? key, required this.title}) : super(key: key); 30 | final String title; 31 | 32 | @override 33 | State createState() => _MyHomePageState(); 34 | } 35 | 36 | class _MyHomePageState extends State { 37 | 38 | bool showText = true; 39 | 40 | @override 41 | Widget build(BuildContext context) { 42 | return Scaffold( 43 | appBar: AppBar( 44 | title: Text(widget.title), 45 | ), 46 | body: Center( 47 | child: AnimatedSwitcher( 48 | duration: const Duration(milliseconds: 1000), 49 | 50 | child: showText 51 | 52 | ? Container( 53 | height: 100, 54 | width: 100, 55 | color: Colors.red, 56 | ): const Text('Hacktoberfest 2022',style: TextStyle(color:Colors.red)), 57 | ), 58 | ), 59 | floatingActionButton: FloatingActionButton.extended( 60 | onPressed: () { 61 | setState(() { 62 | showText = !showText; 63 | }); 64 | }, 65 | label: const Text('Animate'))); 66 | } 67 | } 68 | 69 | ``` 70 | 71 | ## Try out on [Dartpad](https://dartpad.dev/?id=1069aa3765c02c3bb02559dc4b1aa902). 72 | -------------------------------------------------------------------------------- /snippets/api_network_exception.md: -------------------------------------------------------------------------------- 1 | ### While working with the APIs we need to handle every possible status code for exceptions. Here we have guide along with the code snippet to handle the network exceptions. 2 | 3 | ### 1. Add dependencies 4 | - freezed 5 | - build_runner 6 | 7 | 8 | ### 2. Create a file with the name of the network_exceptions. 9 | - You can add or remove the exceptions and error message as per your need. 10 | 11 | ```dart 12 | import 'dart:io'; 13 | 14 | import 'package:dio/dio.dart'; 15 | import 'package:freezed_annotation/freezed_annotation.dart'; 16 | 17 | part 'network_exceptions.freezed.dart'; 18 | 19 | @freezed 20 | abstract class NetworkExceptions with _$NetworkExceptions { 21 | const factory NetworkExceptions.requestCancelled() = RequestCancelled; 22 | 23 | const factory NetworkExceptions.unauthorisedRequest() = UnauthorisedRequest; 24 | 25 | const factory NetworkExceptions.badRequest() = BadRequest; 26 | 27 | const factory NetworkExceptions.notFound(String reason) = NotFound; 28 | 29 | const factory NetworkExceptions.methodNotAllowed() = MethodNotAllowed; 30 | 31 | const factory NetworkExceptions.notAcceptable() = NotAcceptable; 32 | 33 | const factory NetworkExceptions.requestTimeout() = RequestTimeout; 34 | 35 | const factory NetworkExceptions.sendTimeout() = SendTimeout; 36 | 37 | const factory NetworkExceptions.conflict() = Conflict; 38 | 39 | const factory NetworkExceptions.internalServerError() = InternalServerError; 40 | 41 | const factory NetworkExceptions.notImplemented() = NotImplemented; 42 | 43 | const factory NetworkExceptions.serviceUnavailable() = ServiceUnavailable; 44 | 45 | const factory NetworkExceptions.noInternetConnection() = NoInternetConnection; 46 | 47 | const factory NetworkExceptions.formatException() = FormatException; 48 | 49 | const factory NetworkExceptions.unableToProcess() = UnableToProcess; 50 | 51 | const factory NetworkExceptions.defaultError(String error) = DefaultError; 52 | 53 | const factory NetworkExceptions.unexpectedError() = UnexpectedError; 54 | 55 | static NetworkExceptions getDioException(error) { 56 | if (error is Exception) { 57 | try { 58 | NetworkExceptions networkExceptions; 59 | if (error is DioError) { 60 | switch (error.type) { 61 | case DioErrorType.CANCEL: 62 | networkExceptions = NetworkExceptions.requestCancelled(); 63 | break; 64 | case DioErrorType.CONNECT_TIMEOUT: 65 | networkExceptions = NetworkExceptions.requestTimeout(); 66 | break; 67 | case DioErrorType.DEFAULT: 68 | networkExceptions = NetworkExceptions.noInternetConnection(); 69 | break; 70 | case DioErrorType.RECEIVE_TIMEOUT: 71 | networkExceptions = NetworkExceptions.sendTimeout(); 72 | break; 73 | case DioErrorType.RESPONSE: 74 | switch (error.response.statusCode) { 75 | case 400: 76 | networkExceptions = NetworkExceptions.unauthorisedRequest(); 77 | break; 78 | case 401: 79 | networkExceptions = NetworkExceptions.unauthorisedRequest(); 80 | break; 81 | case 403: 82 | networkExceptions = NetworkExceptions.unauthorisedRequest(); 83 | break; 84 | case 404: 85 | networkExceptions = NetworkExceptions.notFound("Not found"); 86 | break; 87 | case 409: 88 | networkExceptions = NetworkExceptions.conflict(); 89 | break; 90 | case 408: 91 | networkExceptions = NetworkExceptions.requestTimeout(); 92 | break; 93 | case 500: 94 | networkExceptions = NetworkExceptions.internalServerError(); 95 | break; 96 | case 503: 97 | networkExceptions = NetworkExceptions.serviceUnavailable(); 98 | break; 99 | default: 100 | var responseCode = error.response.statusCode; 101 | networkExceptions = NetworkExceptions.defaultError( 102 | "Received invalid status code: $responseCode", 103 | ); 104 | } 105 | break; 106 | case DioErrorType.SEND_TIMEOUT: 107 | networkExceptions = NetworkExceptions.sendTimeout(); 108 | break; 109 | } 110 | } else if (error is SocketException) { 111 | networkExceptions = NetworkExceptions.noInternetConnection(); 112 | } else { 113 | networkExceptions = NetworkExceptions.unexpectedError(); 114 | } 115 | return networkExceptions; 116 | } on FormatException catch (e) { 117 | return NetworkExceptions.formatException(); 118 | } catch (_) { 119 | return NetworkExceptions.unexpectedError(); 120 | } 121 | } else { 122 | if (error.toString().contains("is not a subtype of")) { 123 | return NetworkExceptions.unableToProcess(); 124 | } else { 125 | return NetworkExceptions.unexpectedError(); 126 | } 127 | } 128 | } 129 | 130 | static String getErrorMessage(NetworkExceptions networkExceptions) { 131 | var errorMessage = ""; 132 | networkExceptions.when(notImplemented: () { 133 | errorMessage = "Not Implemented"; 134 | }, requestCancelled: () { 135 | errorMessage = "Request Cancelled"; 136 | }, internalServerError: () { 137 | errorMessage = "Internal Server Error"; 138 | }, notFound: (String reason) { 139 | errorMessage = reason; 140 | }, serviceUnavailable: () { 141 | errorMessage = "Service unavailable"; 142 | }, methodNotAllowed: () { 143 | errorMessage = "Method Allowed"; 144 | }, badRequest: () { 145 | errorMessage = "Bad request"; 146 | }, unauthorisedRequest: () { 147 | errorMessage = "Unauthorised request"; 148 | }, unexpectedError: () { 149 | errorMessage = "Unexpected error occurred"; 150 | }, requestTimeout: () { 151 | errorMessage = "Connection request timeout"; 152 | }, noInternetConnection: () { 153 | errorMessage = "No internet connection"; 154 | }, conflict: () { 155 | errorMessage = "Error due to a conflict"; 156 | }, sendTimeout: () { 157 | errorMessage = "Send timeout in connection with API server"; 158 | }, unableToProcess: () { 159 | errorMessage = "Unable to process the data"; 160 | }, defaultError: (String error) { 161 | errorMessage = error; 162 | }, formatException: () { 163 | errorMessage = "Unexpected error occurred"; 164 | }, notAcceptable: () { 165 | errorMessage = "Not acceptable"; 166 | }); 167 | return errorMessage; 168 | } 169 | } 170 | ``` 171 | ### 4. Run the command in the terminal 172 | ``` 173 | flutter pub run build_runner build 174 | ``` 175 | This will generate the network_exceptions.freezed.dart file 176 | 177 | ### 3. Example of the usage 178 | #### Repository or Service level 179 | ```dart 180 | Future>> fetchPostList() async { 181 | try { 182 | // Dio or Http API client 183 | final response = await _apiClient.get('/posts'); 184 | List postList = PostResponse.fromJson(response).results; 185 | if(postList.isNotEmpty) { 186 | return ApiResult.success(postList); 187 | } else { 188 | // To show the cusome error message as per requirement 189 | return ApiResult.failure(NetworkExceptions.notFound("No data found")); 190 | } 191 | } catch (e) { 192 | return ApiResult.failure(error: NetworkExceptions.getDioException(e)); 193 | } 194 | } 195 | ``` 196 | #### UI level 197 | ```dart 198 | Text(NetworkExceptions.getErrorMessage(error)); 199 | ``` 200 | 201 | --- 202 | 203 | _**Refrence**_ 204 | - [Handling Network Calls and Exceptions in Flutter](https://dev.to/ashishrawat2911/handling-network-calls-and-exceptions-in-flutter-54me) 205 | - [Freezed](https://pub.dev/packages/freezed) 206 | -------------------------------------------------------------------------------- /snippets/api_result.md: -------------------------------------------------------------------------------- 1 | ### While working with the APIs we need to take care of the api result and every time we need to handle two cases only 2 | - Success: The data of the API call. 3 | - Failure: The error message of the API call. 4 | 5 | ### Here we have guide along with the code snippet to handle the API result 6 | 7 | ### 1. Add dependencies 8 | - freezed 9 | - build_runner 10 | 11 | 12 | ### 2. Create a file with the name of the api_result.dart 13 | ```dart 14 | import 'package:flutter/foundation.dart'; 15 | import 'package:freezed_annotation/freezed_annotation.dart'; 16 | 17 | // Check out about this here: https://github.com/pratikbutani/awesome-flutter-snippets/tree/main/snippets/api_network_exception.md 18 | import 'network_exceptions.dart'; 19 | 20 | part 'api_result.freezed.dart'; 21 | 22 | @freezed 23 | abstract class ApiResult with _$ApiResult { 24 | const factory ApiResult.success({@required T data}) = Success; 25 | 26 | const factory ApiResult.failure({@required NetworkExceptions error}) = 27 | Failure; 28 | } 29 | ``` 30 | ### 4. Run the command in the terminal 31 | ``` 32 | flutter pub run build_runner build 33 | ``` 34 | This will generate the api_result.freezed.dart file 35 | 36 | 37 | ### 3. Example of the usage 38 | #### Repository or Service level 39 | ```dart 40 | Future>> fetchPostList() async { 41 | try { 42 | // Dio or Http API client 43 | final response = await _apiClient.get('/posts'); 44 | List postList = PostResponse.fromJson(response).results; 45 | return ApiResult.success(data: postList); 46 | } catch (e) { 47 | return ApiResult.failure(error: NetworkExceptions.getDioException(e)); 48 | } 49 | } 50 | ``` 51 | #### BLoC or ViewModel level 52 | ```dart 53 | _onFetchPostListEvent(FetchPostListEvent event, Emitter<> emit) async { 54 | final result = await _postRepository.fetchPostList(); 55 | result.when( 56 | success: (data) { 57 | emit(PostListLoadedState(postList: data)); 58 | }, 59 | failure: (error) { 60 | emit(PostListErrorState(error: error)); 61 | }, 62 | ); 63 | } 64 | ``` 65 | 66 | --- 67 | 68 | _**Refrence**_ 69 | - [Handling Network Calls and Exceptions in Flutter](https://dev.to/ashishrawat2911/handling-network-calls-and-exceptions-in-flutter-54me) 70 | - [Freezed](https://pub.dev/packages/freezed) 71 | -------------------------------------------------------------------------------- /snippets/autocomplete_widget.md: -------------------------------------------------------------------------------- 1 | # Autocomplete 2 | 3 | Code: 4 | ``` 5 | Autocomplete( 6 | optionsBuilder: (TextEditingValue textEditingValue) { 7 | return countryOptions 8 | .where((Country county) => county.name.toLowerCase() 9 | .startsWith(textEditingValue.text.toLowerCase()) 10 | ) 11 | .toList(); 12 | }, 13 | displayStringForOption: (Country option) => option.name, 14 | fieldViewBuilder: ( 15 | BuildContext context, 16 | TextEditingController fieldTextEditingController, 17 | FocusNode fieldFocusNode, 18 | VoidCallback onFieldSubmitted 19 | ) { 20 | return TextField( 21 | controller: fieldTextEditingController, 22 | focusNode: fieldFocusNode, 23 | style: const TextStyle(fontWeight: FontWeight.bold), 24 | ); 25 | }, 26 | onSelected: (Country selection) { 27 | print('Selected: ${selection.name}'); 28 | }, 29 | optionsViewBuilder: ( 30 | BuildContext context, 31 | AutocompleteOnSelected onSelected, 32 | Iterable options 33 | ) { 34 | return Align( 35 | alignment: Alignment.topLeft, 36 | child: Material( 37 | child: Container( 38 | width: double.infinity, 39 | color: Colors.cyan, 40 | child: ListView.builder( 41 | shrinkWrap: true, 42 | padding: const EdgeInsets.all(10.0), 43 | itemCount: options.length, 44 | itemBuilder: (BuildContext context, int index) { 45 | final Country option = options.elementAt(index); 46 | 47 | return GestureDetector( 48 | onTap: () { 49 | onSelected(option); 50 | }, 51 | child: ListTile( 52 | title: Text(option.name, style: const TextStyle(color: Colors.white)), 53 | ), 54 | ); 55 | }, 56 | ), 57 | ), 58 | ), 59 | ); 60 | }, 61 | ), 62 | ``` 63 | 64 | ## Try out on [Dartpad](https://dartpad.dev/?id=09ac4aad5fe1b03958988470ee614530). 65 | -------------------------------------------------------------------------------- /snippets/bottom_nav_animated.md: -------------------------------------------------------------------------------- 1 | # Bottom Nav Animated 2 | 3 | You'll be able to customize your `bottomNavigationBar` with the `CurvedNavigationBar` widget. 4 | 5 | ![ezgif-2-1d2c991527](https://user-images.githubusercontent.com/32421196/194280494-e32f5fc2-33c8-47de-a3f1-1439453acbfb.gif) 6 | 7 | Example Code: 8 | ``` 9 | CurvedNavigationBar( 10 | backgroundColor: Colors.grey.shade200, 11 | buttonBackgroundColor: Colors.blueAccent.shade100, 12 | color: Colors.white, 13 | items: const [ 14 | Icon(Icons.home, color: Colors.black, size: 25), 15 | Icon(Icons.search, color: Colors.black, size: 25), 16 | Icon(Icons.create_outlined, color: Colors.black, size: 25), 17 | FaIcon(FontAwesomeIcons.heart, size: 25), 18 | Icon(Icons.person_outline, color: Colors.black, size: 25), 19 | ], 20 | index: _selectedIndex, 21 | onTap: _onItemTap, 22 | ) 23 | ``` 24 | 25 | 26 | ## Try out on [Dartpad](https://dartpad.dev/?id=ded70a5092034eed86dd9a801c74fca9). 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /snippets/bottom_nav_bar_action_middle.md: -------------------------------------------------------------------------------- 1 | #Bottom Naviagtion Bar with middle Action button 2 | 3 | 4 | https://dartpad.dev/?id=04040db97306fb47c2abbdce3acdfe48 -------------------------------------------------------------------------------- /snippets/bottom_nav_bar_curved.md: -------------------------------------------------------------------------------- 1 | #Curved Bottom bar 2 | 3 | https://dartpad.dev/?id=fab9c3c0e78fd2275f45f60b39701568 -------------------------------------------------------------------------------- /snippets/bottom_sheet_with_key_board.md: -------------------------------------------------------------------------------- 1 | ## How to Move bottomsheet along with keyboard which has textfield(autofocused is true)? 2 | 3 | DartPad : https://dartpad.dev/?id=d106a9415f25aa03fc0b5263d97719fa 4 | 5 | Check it out on real device for good output. 6 | -------------------------------------------------------------------------------- /snippets/button_animation.md: -------------------------------------------------------------------------------- 1 | #Button Animation 2 | 3 | Dart pad Link:- https://dartpad.dev/?id=ac8f6c19b1e54906e706b173e21759b4 4 | -------------------------------------------------------------------------------- /snippets/circle_progress_indicator.md: -------------------------------------------------------------------------------- 1 | # Circle Progress Indicator 2 | 3 | Dart Pad Link:- https://dartpad.dev/?id=4fa4499fa36ab3c993e56d7a715c37b6 4 | -------------------------------------------------------------------------------- /snippets/convert-color-to-material-color.md: -------------------------------------------------------------------------------- 1 | Description 2 | ----------- 3 | 4 | We can not use any color in primarySwatch as it accepts only MaterialColor. This snippet will help you convert a Color to MaterialColor. 5 | 6 | Snippet 7 | ------- 8 | 9 | `` 10 | MaterialColor getMaterialColor(Color color) { 11 | List strengths = [.05]; 12 | 13 | Map swatch = {}; 14 | final int r = color.red, g = color.green, b = color.blue; 15 | 16 | for (int i = 1; i < 10; i++) { 17 | strengths.add(0.1 * i); 18 | } 19 | for (var strength in strengths) { 20 | final double ds = 0.5 - strength; 21 | swatch[(strength * 1000).round()] = Color.fromRGBO( 22 | r + ((ds < 0 ? r : (255 - r)) * ds).round(), 23 | g + ((ds < 0 ? g : (255 - g)) * ds).round(), 24 | b + ((ds < 0 ? b : (255 - b)) * ds).round(), 25 | 1, 26 | ); 27 | } 28 | return MaterialColor(color.value, swatch); 29 | } 30 | `` 31 | 32 | `Here is the` [Dartpad](https://dartpad.dev/?id=8c2048c428bb6c47a2d3def2596a4aa6) 33 | -------------------------------------------------------------------------------- /snippets/counter-c.md: -------------------------------------------------------------------------------- 1 | 2 | import 'package:flutter/material.dart'; 3 | import 'package:flutter_riverpod/flutter_riverpod.dart'; 4 | 5 | // This is a reimplementation of the default Flutter application 6 | // using riverpod. 7 | void main() { 8 | runApp( 9 | // Adding ProviderScope enables Riverpod for the entire project 10 | const ProviderScope(child: MyApp()), 11 | ); 12 | } 13 | 14 | /// Providers are declared globally and specify how to create a state 15 | final counterProvider = StateProvider((ref) => 0); 16 | 17 | class MyApp extends StatelessWidget { 18 | const MyApp({Key? key}) : super(key: key); 19 | 20 | @override 21 | Widget build(BuildContext context) { 22 | return const MaterialApp( 23 | home: MyHomePage(), 24 | ); 25 | } 26 | } 27 | 28 | class MyHomePage extends ConsumerWidget { 29 | const MyHomePage({Key? key}) : super(key: key); 30 | 31 | @override 32 | Widget build(BuildContext context, WidgetRef ref) { 33 | return Scaffold( 34 | body: Center( 35 | child: Column( 36 | mainAxisSize: MainAxisSize.min, 37 | mainAxisAlignment: MainAxisAlignment.center, 38 | children: [ 39 | const Text('You have pushed the button this many times:'), 40 | Consumer( 41 | builder: (context, ref, _) { 42 | final count = ref.watch(counterProvider.state).state; 43 | return Text( 44 | '$count', 45 | key: const Key('counterState'), 46 | style: Theme.of(context).textTheme.headline1, 47 | ); 48 | }, 49 | ), 50 | ], 51 | ), 52 | ), 53 | floatingActionButton: FloatingActionButton( 54 | key: const Key('increment_floatingActionButton'), 55 | // The read method is a utility to read a provider without listening to it 56 | onPressed: () => ref.read(counterProvider.state).state++, 57 | tooltip: 'Increment', 58 | child: const Icon(Icons.add), 59 | ), 60 | ); 61 | } 62 | } 63 | 64 | https://dartpad.dev/?id=1cac6bbc480352f206a1f49c98e10e58 -------------------------------------------------------------------------------- /snippets/counter-with-theme.md: -------------------------------------------------------------------------------- 1 | 2 | import 'package:flutter/material.dart'; 3 | import 'package:flutter_bloc/flutter_bloc.dart'; 4 | 5 | void main() { 6 | Bloc.observer = AppBlocObserver(); 7 | runApp(const App()); 8 | } 9 | 10 | /// Custom [BlocObserver] that observes all bloc and cubit state changes. 11 | class AppBlocObserver extends BlocObserver { 12 | @override 13 | void onChange(BlocBase bloc, Change change) { 14 | super.onChange(bloc, change); 15 | if (bloc is Cubit) print(change); 16 | } 17 | 18 | @override 19 | void onTransition(Bloc bloc, Transition transition) { 20 | super.onTransition(bloc, transition); 21 | print(transition); 22 | } 23 | } 24 | 25 | /// {@template app} 26 | /// A [StatelessWidget] that: 27 | /// * uses [bloc](https://pub.dev/packages/bloc) and 28 | /// [flutter_bloc](https://pub.dev/packages/flutter_bloc) 29 | /// to manage the state of a counter and the app theme. 30 | /// {@endtemplate} 31 | class App extends StatelessWidget { 32 | /// {@macro app} 33 | const App({Key? key}) : super(key: key); 34 | 35 | @override 36 | Widget build(BuildContext context) { 37 | return BlocProvider( 38 | create: (_) => ThemeCubit(), 39 | child: const AppView(), 40 | ); 41 | } 42 | } 43 | 44 | /// {@template app_view} 45 | /// A [StatelessWidget] that: 46 | /// * reacts to state changes in the [ThemeCubit] 47 | /// and updates the theme of the [MaterialApp]. 48 | /// * renders the [CounterPage]. 49 | /// {@endtemplate} 50 | class AppView extends StatelessWidget { 51 | /// {@macro app_view} 52 | const AppView({Key? key}) : super(key: key); 53 | 54 | @override 55 | Widget build(BuildContext context) { 56 | return BlocBuilder( 57 | builder: (_, theme) { 58 | return MaterialApp( 59 | theme: theme, 60 | home: const CounterPage(), 61 | ); 62 | }, 63 | ); 64 | } 65 | } 66 | 67 | /// {@template counter_page} 68 | /// A [StatelessWidget] that: 69 | /// * provides a [CounterBloc] to the [CounterView]. 70 | /// {@endtemplate} 71 | class CounterPage extends StatelessWidget { 72 | /// {@macro counter_page} 73 | const CounterPage({Key? key}) : super(key: key); 74 | 75 | @override 76 | Widget build(BuildContext context) { 77 | return BlocProvider( 78 | create: (_) => CounterBloc(), 79 | child: const CounterView(), 80 | ); 81 | } 82 | } 83 | 84 | /// {@template counter_view} 85 | /// A [StatelessWidget] that: 86 | /// * demonstrates how to consume and interact with a [CounterBloc]. 87 | /// {@endtemplate} 88 | class CounterView extends StatelessWidget { 89 | /// {@macro counter_view} 90 | const CounterView({Key? key}) : super(key: key); 91 | 92 | @override 93 | Widget build(BuildContext context) { 94 | return Scaffold( 95 | appBar: AppBar(title: const Text('Counter')), 96 | body: Center( 97 | child: BlocBuilder( 98 | builder: (context, count) { 99 | return Text('$count', style: Theme.of(context).textTheme.displayLarge); 100 | }, 101 | ), 102 | ), 103 | floatingActionButton: Column( 104 | crossAxisAlignment: CrossAxisAlignment.end, 105 | mainAxisAlignment: MainAxisAlignment.end, 106 | children: [ 107 | FloatingActionButton( 108 | child: const Icon(Icons.add), 109 | onPressed: () => context.read().add(Increment()), 110 | ), 111 | const SizedBox(height: 4), 112 | FloatingActionButton( 113 | child: const Icon(Icons.remove), 114 | onPressed: () => context.read().add(Decrement()), 115 | ), 116 | const SizedBox(height: 4), 117 | FloatingActionButton( 118 | child: const Icon(Icons.brightness_6), 119 | onPressed: () => context.read().toggleTheme(), 120 | ), 121 | ], 122 | ), 123 | ); 124 | } 125 | } 126 | 127 | /// Event being processed by [CounterBloc]. 128 | abstract class CounterEvent {} 129 | 130 | /// Notifies bloc to increment state. 131 | class Increment extends CounterEvent {} 132 | 133 | /// Notifies bloc to decrement state. 134 | class Decrement extends CounterEvent {} 135 | 136 | /// {@template counter_bloc} 137 | /// A simple [Bloc] that manages an `int` as its state. 138 | /// {@endtemplate} 139 | class CounterBloc extends Bloc { 140 | /// {@macro counter_bloc} 141 | CounterBloc() : super(0) { 142 | on((event, emit) => emit(state + 1)); 143 | on((event, emit) => emit(state - 1)); 144 | } 145 | } 146 | 147 | /// {@template brightness_cubit} 148 | /// A simple [Cubit] that manages the [ThemeData] as its state. 149 | /// {@endtemplate} 150 | class ThemeCubit extends Cubit { 151 | /// {@macro brightness_cubit} 152 | ThemeCubit() : super(_lightTheme); 153 | 154 | static final _lightTheme = ThemeData( 155 | floatingActionButtonTheme: const FloatingActionButtonThemeData( 156 | foregroundColor: Colors.white, 157 | ), 158 | brightness: Brightness.light, 159 | ); 160 | 161 | static final _darkTheme = ThemeData( 162 | floatingActionButtonTheme: const FloatingActionButtonThemeData( 163 | foregroundColor: Colors.black, 164 | ), 165 | brightness: Brightness.dark, 166 | ); 167 | 168 | /// Toggles the current brightness between light and dark. 169 | void toggleTheme() { 170 | emit(state.brightness == Brightness.dark ? _lightTheme : _darkTheme); 171 | } 172 | } 173 | 174 | https://dartpad.dev/?id=a78d50beff55d9062e8d4628d1351de9 -------------------------------------------------------------------------------- /snippets/counter.md: -------------------------------------------------------------------------------- 1 | #counter 2 | 3 | Dart pad link:- https://dartpad.dev/?id=9121d9add8335feb6a0f06d2886d7b72 4 | -------------------------------------------------------------------------------- /snippets/counter_animation.md: -------------------------------------------------------------------------------- 1 | # Counter Animation 2 | 3 | ![counter_animation](https://user-images.githubusercontent.com/28589666/195819396-8b58d2fa-02a1-4652-9c97-1af013271a21.gif) 4 | 5 | Code: 6 | 7 | ``` 8 | late AnimationController _controller; 9 | late Animation _animation; 10 | final Tween _tween = Tween(begin: 0.75, end: 1.5); 11 | 12 | //Add this in initState() 13 | _controller = AnimationController( 14 | duration: const Duration(milliseconds: 500), vsync: this); 15 | 16 | //Add this in initState() 17 | _animation = _tween 18 | .animate(CurvedAnimation(parent: _controller, curve: Curves.easeOut) 19 | ..addStatusListener((AnimationStatus status) { 20 | if (status == AnimationStatus.completed) { 21 | _controller.reverse(); 22 | } 23 | })); 24 | 25 | ScaleTransition( 26 | scale: _animation, 27 | alignment: Alignment.center, 28 | child: Text( 29 | '$_counter', 30 | style: Theme.of(context).textTheme.headline4, 31 | ), 32 | ) 33 | ``` 34 | 35 | ## Try out on [Dartpad](https://dartpad.dev/?id=255c3ca5791bff96867b7c355e09a702). 36 | 37 | 38 | -------------------------------------------------------------------------------- /snippets/counter_widget.md: -------------------------------------------------------------------------------- 1 | #Counter Widget 2 | A count picker widget 3 | 4 | https://dartpad.dev/?id=0d0b207372c8c13f9770cdfb75bb6c89 -------------------------------------------------------------------------------- /snippets/customScrollView-example: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | void main() => runApp(const MyApp()); 4 | 5 | class MyApp extends StatelessWidget { 6 | const MyApp({super.key}); 7 | 8 | static const String _title = 'Flutter Code Sample'; 9 | 10 | @override 11 | Widget build(BuildContext context) { 12 | return const MaterialApp( 13 | title: _title, 14 | home: MyStatefulWidget(), 15 | ); 16 | } 17 | } 18 | 19 | class MyStatefulWidget extends StatefulWidget { 20 | const MyStatefulWidget({super.key}); 21 | 22 | @override 23 | State createState() => _MyStatefulWidgetState(); 24 | } 25 | 26 | class _MyStatefulWidgetState extends State { 27 | List top = []; 28 | List bottom = [0]; 29 | 30 | @override 31 | Widget build(BuildContext context) { 32 | const Key centerKey = ValueKey('bottom-sliver-list'); 33 | return Scaffold( 34 | appBar: AppBar( 35 | title: const Text('Press on the plus to add items above and below'), 36 | leading: IconButton( 37 | icon: const Icon(Icons.add), 38 | onPressed: () { 39 | setState(() { 40 | top.add(-top.length - 1); 41 | bottom.add(bottom.length); 42 | }); 43 | }, 44 | ), 45 | ), 46 | body: CustomScrollView( 47 | center: centerKey, 48 | slivers: [ 49 | SliverList( 50 | delegate: SliverChildBuilderDelegate( 51 | (BuildContext context, int index) { 52 | return Container( 53 | alignment: Alignment.center, 54 | color: Colors.blue[200 + top[index] % 4 * 100], 55 | height: 100 + top[index] % 4 * 20.0, 56 | child: Text('Item: ${top[index]}'), 57 | ); 58 | }, 59 | childCount: top.length, 60 | ), 61 | ), 62 | SliverList( 63 | key: centerKey, 64 | delegate: SliverChildBuilderDelegate( 65 | (BuildContext context, int index) { 66 | return Container( 67 | alignment: Alignment.center, 68 | color: Colors.blue[200 + bottom[index] % 4 * 100], 69 | height: 100 + bottom[index] % 4 * 20.0, 70 | child: Text('Item: ${bottom[index]}'), 71 | ); 72 | }, 73 | childCount: bottom.length, 74 | ), 75 | ), 76 | ], 77 | ), 78 | ); 79 | } 80 | } 81 | 82 | 83 | DartPad Link: https://dartpad.dev/? 84 | -------------------------------------------------------------------------------- /snippets/custom_calender_widget.md: -------------------------------------------------------------------------------- 1 | #Custom Calender Widget 2 | 3 | https://dartpad.dev/?id=736b2eb57b29bf1c5f49e4f9f3f119b1 4 | -------------------------------------------------------------------------------- /snippets/custom_progress_indicator.md: -------------------------------------------------------------------------------- 1 | #Custom Loader 2 | Custom circular progress indicator 3 | 4 | https://dartpad.dev/?id=6f54c8246d1bf8805d08931cb1e19280 -------------------------------------------------------------------------------- /snippets/customized_shimmer_for_list.md: -------------------------------------------------------------------------------- 1 | 2 | # You can create customize table with the use of following snippet. 3 | ``` 4 | import 'package:flutter/material.dart'; 5 | import 'package:shimmer/shimmer.dart'; 6 | 7 | class ListShimmerPage extends StatelessWidget { 8 | final double containerHeight, 9 | leftMargin, 10 | rightMargin, 11 | topMargin, 12 | bottomMargin, 13 | borderRadius; 14 | final double? width; 15 | final int count; 16 | final bool shinkWap; 17 | final bool physics; 18 | 19 | const ListShimmerPage( 20 | {Key? key, 21 | required this.containerHeight, 22 | required this.bottomMargin, 23 | required this.leftMargin, 24 | required this.rightMargin, 25 | required this.topMargin, 26 | required this.count, 27 | required this.borderRadius, 28 | required this.shinkWap, 29 | required this.physics, 30 | this.width}) 31 | : super(key: key); 32 | 33 | @override 34 | Widget build(BuildContext context) { 35 | return Shimmer.fromColors( 36 | baseColor: Colors.grey[400]!, 37 | highlightColor: Colors.grey[100]!, 38 | child: ListView.builder( 39 | shrinkWrap: shinkWap, 40 | physics: (physics) ? const NeverScrollableScrollPhysics() : null, 41 | itemCount: count, 42 | itemBuilder: (context, index) { 43 | return getProjectShimmer(); 44 | })); 45 | } 46 | 47 | Widget getProjectShimmer() { 48 | return Container( 49 | margin: EdgeInsets.only( 50 | left: leftMargin, 51 | right: rightMargin, 52 | top: topMargin, 53 | bottom: bottomMargin), 54 | height: containerHeight, 55 | width: width ?? 0, 56 | decoration: BoxDecoration( 57 | borderRadius: BorderRadius.all(Radius.circular(borderRadius)), 58 | color: Colors.grey[400], 59 | ), 60 | ); 61 | } 62 | } 63 | ``` 64 | `To access full code` [Dartpad](https://dartpad.dev/?id=eed39b9a98066e1b6f8e6eccbb0524c0) -------------------------------------------------------------------------------- /snippets/customized_table_widget.md: -------------------------------------------------------------------------------- 1 | 2 | # You can create customize table with the use of following snippet. 3 | ``` 4 | Column( 5 | children: [ 6 | Container( 7 | padding: const EdgeInsets.only(left: 10, right: 10), 8 | child: Table(columnWidths: const { 9 | 0: FlexColumnWidth(2), 10 | 1: FlexColumnWidth(4), 11 | 2: FlexColumnWidth(3), 12 | }, children: [ 13 | TableRow(children: [ 14 | Container( 15 | height: 31, 16 | margin: const EdgeInsets.only(right: 2), 17 | alignment: Alignment.center, 18 | padding: const EdgeInsets.all(5), 19 | decoration: BoxDecoration( 20 | color: Colors.black38, 21 | borderRadius: BorderRadius.circular(2), 22 | ), 23 | child: const FittedBox(child: Text("String 1"))), 24 | Container( 25 | height: 31, 26 | margin: const EdgeInsets.only(right: 2), 27 | alignment: Alignment.center, 28 | padding: const EdgeInsets.all(5), 29 | decoration: BoxDecoration( 30 | color: Colors.black38, 31 | borderRadius: BorderRadius.circular(2), 32 | ), 33 | child: const FittedBox(child: Text("String 2"))), 34 | Container( 35 | height: 31, 36 | margin: const EdgeInsets.only(right: 2), 37 | alignment: Alignment.center, 38 | padding: const EdgeInsets.all(5), 39 | decoration: BoxDecoration( 40 | color: Colors.black38, 41 | borderRadius: BorderRadius.circular(2), 42 | ), 43 | child: const FittedBox(child: Text("String 3"))), 44 | ]), 45 | ]), 46 | ), 47 | const SizedBox( 48 | height: 2, 49 | ), 50 | Expanded( 51 | child: ListView(children: [ 52 | Container( 53 | padding: const EdgeInsets.only(left: 10, right: 10), 54 | child: Table(columnWidths: const { 55 | 0: FlexColumnWidth(2), 56 | 1: FlexColumnWidth(4), 57 | 2: FlexColumnWidth(3), 58 | }, children: getChild()), 59 | ) 60 | ]), 61 | ), 62 | ), 63 | ], 64 | ``` 65 | 66 | `To access full code` [Dartpad](https://dartpad.dev/?id=ecacd980e27b9264ef323a1d6c534a21) 67 | 68 | -------------------------------------------------------------------------------- /snippets/date_time.md: -------------------------------------------------------------------------------- 1 | void main() { 2 | var timestamp = DateTime.now().toString(); 3 | print(timestamp); 4 | } 5 | 6 | link for dartpad: https://dartpad.dev/?id=67e1430b49883f6c2ff6edb38180d6c2 7 | -------------------------------------------------------------------------------- /snippets/disable_scroll_glow.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Disable Scroll GLow 4 | 5 | You'll be able to stop the blue scroll glow when reach to top or bottom. 6 | 7 | Just wrap your widget with ScrollConfigration widget and in the behaviour, give this widget's reference 8 | 9 | ''' 10 | class DisableScrollGlow extends ScrollBehavior { 11 | @override 12 | Widget buildViewportChrome( 13 | BuildContext context, Widget child, AxisDirection axisDirection) { 14 | return child; 15 | } 16 | } 17 | 18 | ''' 19 | 20 | ##Example code 21 | 22 | ''' 23 | ScrollConfiguration( 24 | behavior: DisableScrollGlow(), 25 | child: ListView.builder( 26 | itemCount: 10, 27 | itemBuilder: (ctx, index) { 28 | return Text("Demo list view"); 29 | ), 30 | ''' -------------------------------------------------------------------------------- /snippets/dismissible_widget.md: -------------------------------------------------------------------------------- 1 | # Dismissible Widget (Flutter) 2 | 3 | Code: 4 | 5 | ``` 6 | Dismissible( 7 | background: Container( 8 | color: Colors.orangeAccent, 9 | child: const Align( 10 | alignment: Alignment.centerLeft, 11 | child: Padding( 12 | padding: EdgeInsets.only(left: 16.0), 13 | child: Icon(Icons.archive), 14 | ))), 15 | behavior: HitTestBehavior.opaque, 16 | onDismissed: (DismissDirection direction) { 17 | if (direction == DismissDirection.startToEnd) { 18 | print("startToEnd"); 19 | } else { 20 | print("endToStart"); 21 | } 22 | }, 23 | crossAxisEndOffset: 0.2, 24 | direction: DismissDirection.horizontal, 25 | movementDuration: const Duration(milliseconds: 200), 26 | resizeDuration: const Duration(milliseconds: 1000), 27 | secondaryBackground: Container( 28 | color: Colors.red, 29 | child: const Align( 30 | alignment: Alignment.centerRight, 31 | child: Padding( 32 | padding: EdgeInsets.only(right: 16.0), 33 | child: Icon(Icons.delete), 34 | )), 35 | ), 36 | key: const ValueKey(0), 37 | child: const ListTile( 38 | title: Text('Swipe to Dismiss'), 39 | ), 40 | ); 41 | ``` 42 | 43 | ## Try out on [dartpad](https://dartpad.dev/?id=668b08d65450cd0f026f72272cc2c22e). 44 | 45 | 46 | -------------------------------------------------------------------------------- /snippets/dotted_progress_indicator.md: -------------------------------------------------------------------------------- 1 | #Dotted progress indicator 2 | dotted progress indicator with animation 3 | 4 | https://dartpad.dev/?id=31d17ec995b2db186c9e87234d03858b -------------------------------------------------------------------------------- /snippets/drawer.md: -------------------------------------------------------------------------------- 1 | #Drawer 2 | 3 | https://dartpad.dev/?id=708b024ff7ddbfb3bcb2cb1237b6f3df -------------------------------------------------------------------------------- /snippets/error_widget.md: -------------------------------------------------------------------------------- 1 | ``` 2 | import 'package:flutter/material.dart'; 3 | import 'package:flutter/services.dart'; 4 | 5 | 6 | 7 | void main() => runApp(MyApp()); 8 | 9 | class MyApp extends StatelessWidget { 10 | @override 11 | Widget build(BuildContext context) { 12 | return MaterialApp( 13 | title: 'Flutter Demo', 14 | debugShowCheckedModeBanner: false, 15 | theme: ThemeData( 16 | primarySwatch: Colors.blue, 17 | ), 18 | home: ErrorPage(error:"Something went wrong please try again"), 19 | ); 20 | } 21 | } 22 | 23 | 24 | 25 | class ErrorPage extends StatelessWidget { 26 | final IconData iconData; 27 | final String? error; 28 | 29 | 30 | const ErrorPage( 31 | {Key? key, 32 | this.iconData = Icons.error, 33 | this.error}) 34 | : super(key: key); 35 | 36 | @override 37 | Widget build(BuildContext context) { 38 | return Scaffold( 39 | body:Center( 40 | child: Column( 41 | mainAxisAlignment: MainAxisAlignment.center, 42 | children: [ 43 | Icon( 44 | iconData, 45 | size: 40, 46 | color: Colors.grey.shade400, 47 | ), 48 | Container( 49 | margin: const EdgeInsets.only( 50 | top: 12, 51 | ), 52 | child: Text( 53 | error ?? "", 54 | textAlign: TextAlign.center, 55 | ), 56 | ), 57 | ], 58 | ), 59 | ), 60 | ); 61 | } 62 | } 63 | 64 | ), 65 | ``` 66 | DartPad:https://dartpad.dev/?id=8f6a4554e3e9a8c2aac277da1724a95a 67 | -------------------------------------------------------------------------------- /snippets/fade_app_bar.md: -------------------------------------------------------------------------------- 1 | #Fade App Bar 2 | fade app bar with serach textfield 3 | 4 | https://dartpad.dev/?id=35300eda3c76e783279ce015ce22b06b -------------------------------------------------------------------------------- /snippets/fade_out_animation.md: -------------------------------------------------------------------------------- 1 | Example code 2 | 3 | ``` 4 | @override 5 | Widget build(BuildContext context) { 6 | return AnimatedContainer( 7 | margin: EdgeInsets.all(0), 8 | width: 200, 9 | duration: Duration(seconds: 2), 10 | child: Column( 11 | crossAxisAlignment: CrossAxisAlignment.center, 12 | children: [ 13 | SizedBox(height: 20.0), 14 | AnimatedOpacity( 15 | duration: Duration(seconds: 1), 16 | opacity: _opacity, 17 | curve: Curves.bounceInOut, 18 | child: ElevatedButton( 19 | style: ElevatedButton.styleFrom(primary: Colors.yellow), 20 | child: 21 | Text('Animate Me', style: TextStyle(color: Colors.black)), 22 | onPressed: () => setState(() => _opacity = 0)), 23 | ) 24 | ], 25 | ), 26 | ); 27 | } 28 | ``` 29 | DartPad:https://dartpad.dev/?id=3aca3166bd41e86b0a659618ed4c346a 30 | -------------------------------------------------------------------------------- /snippets/focus_next.md: -------------------------------------------------------------------------------- 1 | ``` 2 | import 'package:flutter/material.dart'; 3 | 4 | void main() => runApp(const MyApp()); 5 | 6 | class MyApp extends StatelessWidget { 7 | const MyApp({Key? key}) : super(key: key); 8 | 9 | @override 10 | Widget build(BuildContext context) { 11 | return const MaterialApp( 12 | title: 'Text Field Focus', 13 | home: MyCustomForm(), 14 | ); 15 | } 16 | } 17 | 18 | // Define a custom Form widget. 19 | class MyCustomForm extends StatefulWidget { 20 | const MyCustomForm({Key? key}) : super(key: key); 21 | 22 | @override 23 | _MyCustomFormState createState() => _MyCustomFormState(); 24 | } 25 | 26 | // Define a corresponding State class. 27 | // This class holds data related to the form. 28 | class _MyCustomFormState extends State { 29 | // Define the focus node. To manage the lifecycle, create the FocusNode in 30 | // the initState method, and clean it up in the dispose method. 31 | late FocusNode myFocusNode; 32 | 33 | @override 34 | void initState() { 35 | super.initState(); 36 | 37 | myFocusNode = FocusNode(); 38 | } 39 | 40 | @override 41 | void dispose() { 42 | // Clean up the focus node when the Form is disposed. 43 | myFocusNode.dispose(); 44 | 45 | super.dispose(); 46 | } 47 | 48 | @override 49 | Widget build(BuildContext context) { 50 | return Scaffold( 51 | appBar: AppBar( 52 | title: const Text('Text Field Focus'), 53 | ), 54 | body: Padding( 55 | padding: const EdgeInsets.all(16.0), 56 | child: Column( 57 | children: [ 58 | // The first text field is focused on as soon as the app starts. 59 | const TextField( 60 | autofocus: true, 61 | ), 62 | // The second text field is focused on when a user taps the 63 | // FloatingActionButton. 64 | TextField( 65 | focusNode: myFocusNode, 66 | ), 67 | ], 68 | ), 69 | ), 70 | floatingActionButton: FloatingActionButton( 71 | // When the button is pressed, 72 | // give focus to the text field using myFocusNode. 73 | onPressed: () => myFocusNode.requestFocus(), 74 | tooltip: 'Focus Second Text Field', 75 | child: const Icon(Icons.arrow_forward_rounded), 76 | ), // This trailing comma makes auto-formatting nicer for build methods. 77 | ); 78 | } 79 | } 80 | ``` 81 | [dartpad](https://dartpad.dev/?id=76a4e0825f6514a8198a6864621f1b2e) 82 | -------------------------------------------------------------------------------- /snippets/getx_snackbar.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Success and error snackbar using getx 4 | 5 | You'll be able to customize your `snackbar` with the enum. 6 | 7 | ## Dependencies 8 | 1. get 9 | 10 | 11 | ### Use this function wherever you want snackbar to be appear 12 | ''' 13 | enum SNACK { SUCCESS, FAILED } 14 | getSnackBar(String message, SNACK type, {String? title}) { 15 | return Get.snackbar(title ?? '', '', 16 | snackPosition: SnackPosition.BOTTOM, 17 | backgroundColor: type == SNACK.SUCCESS ? Colors.green : Colors.red, 18 | snackStyle: SnackStyle.GROUNDED, 19 | colorText: Colors.white, 20 | titleText: Container( 21 | height: 0, 22 | ), 23 | messageText: Text( 24 | message, 25 | style: TextStyle( 26 | color: Colors.white, 27 | fontSize: 12.sp, 28 | fontWeight: FontWeight.normal), 29 | ), 30 | padding: EdgeInsets.symmetric(horizontal: 10.sp, vertical: 10.sp), 31 | margin: const EdgeInsets.all(0)); 32 | } 33 | ''' -------------------------------------------------------------------------------- /snippets/glowing_button.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | # Glowing Button for dark mode 6 | 7 | You'll be able to customize your `action button` with the `GlowingActionButton` widget. 8 | 9 | 10 | Example Code: 11 | ``` 12 | class GlowingActionButton extends StatelessWidget { 13 | const GlowingActionButton({ 14 | Key? key, 15 | required this.color, 16 | required this.icon, 17 | this.size = 54, 18 | required this.onPressed, 19 | }) : super(key: key); 20 | 21 | final Color color; 22 | final IconData icon; 23 | final double size; 24 | final VoidCallback onPressed; 25 | 26 | @override 27 | Widget build(BuildContext context) { 28 | return Container( 29 | decoration: BoxDecoration( 30 | color: color, 31 | shape: BoxShape.circle, 32 | boxShadow: [ 33 | BoxShadow( 34 | color: color.withOpacity(0.3), 35 | spreadRadius: 10, 36 | blurRadius: 24, 37 | ), 38 | ], 39 | ), 40 | child: ClipOval( 41 | child: Material( 42 | color: color, 43 | child: InkWell( 44 | splashColor: AppColors.cardLight, 45 | onTap: onPressed, 46 | child: SizedBox( 47 | width: size, 48 | height: size, 49 | child: Icon( 50 | icon, 51 | size: 26, 52 | color: Colors.white, 53 | ), 54 | ), 55 | ), 56 | ), 57 | ), 58 | ); 59 | } 60 | }``` 61 | 62 | 63 | ## Try out on [Dartpad](https://dartpad.dev/?id=31dc0ed2b2cfd5cafc7f503a71739b60). 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /snippets/gradient_action_button.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | const Color darkBlue = Color.fromARGB(255, 18, 32, 47); 4 | 5 | void main() { 6 | runApp(MyApp()); 7 | } 8 | 9 | class MyApp extends StatelessWidget { 10 | @override 11 | Widget build(BuildContext context) { 12 | return MaterialApp( 13 | theme: ThemeData.dark().copyWith( 14 | scaffoldBackgroundColor: darkBlue, 15 | ), 16 | debugShowCheckedModeBanner: false, 17 | home: Scaffold( 18 | body: Center( 19 | child: progressHudWidget(context), 20 | ), 21 | ), 22 | ); 23 | } 24 | 25 | static Widget progressHudWidget(BuildContext context) { 26 | return Container( 27 | height: 50.0, 28 | child: Ink( 29 | decoration: BoxDecoration( 30 | gradient: LinearGradient( 31 | colors: [Color(0xff374ABE), Color(0xff64B6FF)], 32 | begin: Alignment.centerLeft, 33 | end: Alignment.centerRight, 34 | ), 35 | borderRadius: BorderRadius.circular(8.0)), 36 | child: Container( 37 | constraints: BoxConstraints(minHeight: 50.0), 38 | alignment: Alignment.center, 39 | child: Text( 40 | "Login", 41 | textAlign: TextAlign.center, 42 | style: TextStyle(color: Colors.white), 43 | ), 44 | ), 45 | ), 46 | ); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /snippets/gradient_app_bar.md: -------------------------------------------------------------------------------- 1 | #Gradient App Bar 2 | A gradient app bar built to use if you guys need a gradient app bar 3 | 4 | https://dartpad.dev/?id=a7d91fdf29d61f1fd085dc6ca5d89575 -------------------------------------------------------------------------------- /snippets/gradient_button.md: -------------------------------------------------------------------------------- 1 | #gradient Button 2 | 3 | https://dartpad.dev/?id=864d7eda3791cf33af028b0a1e6ea610 -------------------------------------------------------------------------------- /snippets/horizontal_categories_view.md: -------------------------------------------------------------------------------- 1 | #Horizontal Categories View 2 | 3 | https://dartpad.dev/?id=eb64dc0a437ecbfeb5cdaed673e206b5 -------------------------------------------------------------------------------- /snippets/ignore-pointer-with-switch.md: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | void main() { 4 | runApp(const MyApp()); 5 | } 6 | 7 | class MyApp extends StatelessWidget { 8 | const MyApp({Key? key}) : super(key: key); 9 | 10 | // This widget is the root of your application. 11 | @override 12 | Widget build(BuildContext context) { 13 | return MaterialApp( 14 | debugShowCheckedModeBanner: false, 15 | title: 'Flutter Demo', 16 | theme: ThemeData( 17 | primarySwatch: Colors.blue, 18 | ), 19 | home: const HomePage(), 20 | ); 21 | } 22 | } 23 | 24 | class HomePage extends StatefulWidget { 25 | const HomePage({Key? key}) : super(key: key); 26 | 27 | @override 28 | _HomePageState createState() => _HomePageState(); 29 | } 30 | 31 | class _HomePageState extends State { 32 | bool _ignoring = false; 33 | 34 | @override 35 | Widget build(BuildContext context) { 36 | return Scaffold( 37 | appBar: AppBar( 38 | title: const Text('Ignore Pointer Demo'), 39 | ), 40 | body: Builder( 41 | builder: (context) => Center( 42 | child: Padding( 43 | padding: const EdgeInsets.all(15.0), 44 | child: Column( 45 | mainAxisAlignment: MainAxisAlignment.center, 46 | children: [ 47 | IgnorePointer( 48 | ignoring: _ignoring, 49 | child: Column( 50 | children: [ 51 | ElevatedButton( 52 | child: const Text('Press the button'), 53 | onPressed: () { 54 | ScaffoldMessenger.of(context).showSnackBar( 55 | const SnackBar(content: Text('Button is pressed')) 56 | ); 57 | }, 58 | ), 59 | ], 60 | ), 61 | ), 62 | Row( 63 | mainAxisAlignment: MainAxisAlignment.center, 64 | children: [ 65 | const Text('Ignore Pointer?'), 66 | Switch( 67 | value: _ignoring, 68 | onChanged: (bool value) { 69 | setState(() { 70 | _ignoring = value; 71 | }); 72 | }), 73 | ], 74 | ), 75 | ], 76 | ), 77 | ), 78 | ), 79 | ), 80 | ); 81 | } 82 | 83 | } 84 | 85 | https://dartpad.dev/?id=94bf5020b43f300ec1310cca8cfee623 86 | -------------------------------------------------------------------------------- /snippets/image_picker_and_cropper.md: -------------------------------------------------------------------------------- 1 | # You can pick images from device's gallery and also cropped it with the use of below snippet. 2 | 3 | 4 | ```` 5 | Add below lines to AndroidManifest to avoid crash. 6 | 10 | ``` 11 | 12 | ``` 13 | import 'dart:io'; 14 | 15 | import 'package:flutter/material.dart'; 16 | import 'package:image_cropper/image_cropper.dart'; 17 | import 'package:image_picker/image_picker.dart'; 18 | import 'package:ready/app_styles.dart'; 19 | import 'package:rxdart/rxdart.dart'; 20 | 21 | class CommonAddPhotoWidget extends StatelessWidget { 22 | CommonAddPhotoWidget({Key? key, this.helperImage}) : super(key: key); 23 | final BehaviorSubject streamImage = BehaviorSubject(); 24 | final dynamic helperImage; 25 | @override 26 | Widget build(BuildContext context) { 27 | return Row( 28 | mainAxisAlignment: MainAxisAlignment.center, 29 | children: [ 30 | StreamBuilder( 31 | stream: streamImage, 32 | builder: (BuildContext context, AsyncSnapshot snapshot) { 33 | if (snapshot.hasData) { 34 | return Stack( 35 | alignment: Alignment.bottomRight, 36 | children: [ 37 | CircleAvatar( 38 | radius: 50, 39 | foregroundImage: Image.file( 40 | snapshot.data!, 41 | fit: BoxFit.cover, 42 | ).image), 43 | InkWell( 44 | onTap: () { 45 | getImage(); 46 | }, 47 | child: const CircleAvatar( 48 | radius: 15, 49 | backgroundColor: AppStyles.primary500Color, 50 | child: Icon( 51 | Icons.camera_alt, 52 | color: Colors.white, 53 | size: 18, 54 | )), 55 | ), 56 | ], 57 | ); 58 | } 59 | return InkWell( 60 | onTap: () { 61 | getImage(); 62 | }, 63 | child: Container( 64 | margin: const EdgeInsets.only(right: AppStyles.allMargin), 65 | decoration: const BoxDecoration( 66 | shape: BoxShape.circle, color: AppStyles.grey50Color), 67 | width: 90, 68 | height: 90, 69 | child: const Icon( 70 | Icons.add_a_photo, 71 | size: 30, 72 | color: AppStyles.grey300Color, 73 | ), 74 | ), 75 | ); 76 | }, 77 | ), 78 | ], 79 | ); 80 | } 81 | 82 | void getImage() async { 83 | final image = await ImagePicker().pickImage(source: ImageSource.gallery); 84 | final croppedImage = await ImageCropper().cropImage( 85 | sourcePath: image!.path, 86 | aspectRatioPresets: [CropAspectRatioPreset.ratio16x9], 87 | aspectRatio: const CropAspectRatio(ratioX: 1, ratioY: 1), 88 | compressQuality: 100); 89 | streamImage.add(File(croppedImage!.path)); 90 | } 91 | } 92 | ``` 93 | `To access full code` [Dartpad](https://dartpad.dev/?id=8085e2b2d4377b371a145911866fb21d) 94 | -------------------------------------------------------------------------------- /snippets/listview_random_color.md: -------------------------------------------------------------------------------- 1 | // Add random color function in listview 2 | 3 | Color randomColor(){ 4 | return (Colors.primaries[Random().nextInt(Colors.primaries.length)]); 5 | } 6 | 7 | // Add listview function in code 8 | 9 | Widget colorListView(int count) { 10 | return ListView.builder( 11 | itemCount: count, 12 | itemBuilder: (BuildContext context, int index) { 13 | Color selectColor = randomColor(); 14 | Color backgroundColor = randomColor(); 15 | return Container( 16 | margin: EdgeInsets.all(8.0), 17 | decoration: BoxDecoration( 18 | color:backgroundColor, 19 | borderRadius: BorderRadius.all(Radius.circular(8.0)), 20 | ), 21 | child: Column( 22 | children: [ 23 | ListTile( 24 | contentPadding: EdgeInsets.all(8), 25 | leading: Icon(Icons.heart_broken_outlined, 26 | color: selectColor), 27 | trailing: Text("Random Number : ${Random().nextInt(100)}", 28 | style: TextStyle(color: selectColor, fontSize: 15), 29 | ), 30 | title: Text("List item $index",style: TextStyle(color: selectColor, fontSize: 15))), 31 | ], 32 | ), 33 | ); 34 | }); 35 | } 36 | 37 | 38 | // Use it in your code 39 | 40 | Container( 41 | alignment: Alignment.center, 42 | child: Column( 43 | children: [ 44 | Container( 45 | margin: EdgeInsets.all(8.0), 46 | child: ElevatedButton( 47 | onPressed: (){ 48 | setState(() {}); 49 | }, 50 | child: const Text(' Update Color ListView'), 51 | ), 52 | ), 53 | Expanded(child: colorListView(5)), 54 | ], 55 | ), 56 | ), 57 | 58 | Here is the [Dartpad](https://dartpad.dev/?id=09c098da6e460390a5ac677fa38f39d7) 59 | -------------------------------------------------------------------------------- /snippets/menu_bar_animated.md: -------------------------------------------------------------------------------- 1 | # Menu Bar Animated 2 | 3 | You'll be able to customize your `menu_bar_animated` with the `AnimatedBuilder` widget. 4 | 5 | ![ezgif com-gif-maker](https://user-images.githubusercontent.com/90324652/194710937-60d5c90a-8a00-4ede-a951-7fea3250d5f3.gif) 6 | 7 | Example Code: 8 | ``` 9 | AnimatedBuilder( 10 | animation: _staggeredController, 11 | builder: (context, child) { 12 | final animationPercent = Curves.easeOut.transform( 13 | _itemSlideIntervals[i].transform(_staggeredController.value), 14 | ); 15 | final opacity = animationPercent; 16 | final slideDistance = (1.0 - animationPercent) * 150; 17 | return Opacity( 18 | opacity: opacity, 19 | child: Transform.translate( 20 | offset: Offset(slideDistance, 0), 21 | child: child, 22 | ), 23 | ); 24 | }, 25 | child: Padding( 26 | padding: const EdgeInsets.symmetric(horizontal: 36.0, vertical: 16), 27 | child: Text( 28 | _menuTitles[i], 29 | textAlign: TextAlign.left, 30 | style: const TextStyle( 31 | fontSize: 24, 32 | fontWeight: FontWeight.w500, 33 | ), 34 | ), 35 | ), 36 | ) 37 | ``` 38 | 39 | ## Try out on [Dartpad](https://dartpad.dev/?id=a5e47a3b8b33c7f59280ab95a4d5d876). 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /snippets/multiple_floating_button.md: -------------------------------------------------------------------------------- 1 | # Multiple Floating Button 2 | 3 | ![multiple_floating_button](https://user-images.githubusercontent.com/109585734/195868376-8f164239-5ec7-4413-a513-71614f445eb1.gif) 4 | 5 | Code: 6 | ``` 7 | Widget _buildItem(IconData icon) { 8 | return FloatingActionButton( 9 | onPressed: () { 10 | _myAnimation.status == AnimationStatus.completed 11 | ? _myAnimation.reverse() 12 | : _myAnimation.forward(); 13 | }, 14 | splashColor: Colors.grey, 15 | child: Icon(icon), 16 | ); 17 | } 18 | 19 | body: Flow( 20 | delegate: MyFlowDelegate(animation: _myAnimation), 21 | children: _icons.map((IconData icon) => _buildItem(icon)).toList(), 22 | ), 23 | ``` 24 | 25 | ## Try out on [Dartpad](https://dartpad.dev/?id=e6d92a37a9a3ab88b612e517a4106074). 26 | -------------------------------------------------------------------------------- /snippets/my-route.md: -------------------------------------------------------------------------------- 1 | 2 | import 'dart:math' as math; 3 | 4 | import 'package:flutter/material.dart'; 5 | import 'package:go_router/go_router.dart'; 6 | import 'package:english_words/english_words.dart'; 7 | 8 | void main() { 9 | runApp(MusicAppDemo()); 10 | } 11 | 12 | class MusicAppDemo extends StatelessWidget { 13 | MusicAppDemo({Key? key}) : super(key: key); 14 | 15 | final MusicDatabase database = MusicDatabase.mock(); 16 | 17 | final GoRouter _router = GoRouter( 18 | initialLocation: '/library', 19 | routes: [ 20 | ShellRoute( 21 | builder: (BuildContext context, GoRouterState state, Widget child) { 22 | return MusicAppShell( 23 | child: child, 24 | ); 25 | }, 26 | routes: [ 27 | GoRoute( 28 | path: '/library', 29 | pageBuilder: (context, state) { 30 | return FadeTransitionPage( 31 | child: const LibraryScreen(), 32 | key: state.pageKey, 33 | ); 34 | }, 35 | routes: [ 36 | GoRoute( 37 | path: 'album/:albumId', 38 | builder: (BuildContext context, GoRouterState state) { 39 | return AlbumScreen( 40 | albumId: state.params['albumId'], 41 | ); 42 | }, 43 | routes: [ 44 | GoRoute( 45 | path: 'song/:songId', 46 | // Display on the root Navigator 47 | builder: (BuildContext context, GoRouterState state) { 48 | return SongScreen( 49 | songId: state.params['songId']!, 50 | ); 51 | }, 52 | ), 53 | ], 54 | ), 55 | ], 56 | ), 57 | GoRoute( 58 | path: '/recents', 59 | pageBuilder: (context, state) { 60 | return FadeTransitionPage( 61 | child: const RecentlyPlayedScreen(), 62 | key: state.pageKey, 63 | ); 64 | }, 65 | routes: [ 66 | GoRoute( 67 | path: 'song/:songId', 68 | // Display on the root Navigator 69 | builder: (BuildContext context, GoRouterState state) { 70 | return SongScreen( 71 | songId: state.params['songId']!, 72 | ); 73 | }, 74 | ), 75 | ], 76 | ), 77 | GoRoute( 78 | path: '/search', 79 | pageBuilder: (context, state) { 80 | final query = state.queryParams['q'] ?? ''; 81 | return FadeTransitionPage( 82 | child: SearchScreen( 83 | query: query, 84 | ), 85 | key: state.pageKey, 86 | ); 87 | }, 88 | ), 89 | ], 90 | ), 91 | ], 92 | ); 93 | 94 | @override 95 | Widget build(BuildContext context) { 96 | return MaterialApp.router( 97 | title: 'Music app', 98 | theme: ThemeData(primarySwatch: Colors.pink), 99 | routerConfig: _router, 100 | builder: (context, child) { 101 | return MusicDatabaseScope( 102 | state: database, 103 | child: child!, 104 | ); 105 | }, 106 | ); 107 | } 108 | } 109 | 110 | class MusicAppShell extends StatelessWidget { 111 | final Widget child; 112 | 113 | const MusicAppShell({ 114 | Key? key, 115 | required this.child, 116 | }) : super(key: key); 117 | 118 | @override 119 | Widget build(BuildContext context) { 120 | return Scaffold( 121 | body: child, 122 | bottomNavigationBar: BottomNavigationBar( 123 | items: const [ 124 | BottomNavigationBarItem( 125 | icon: Icon(Icons.my_library_music_rounded), 126 | label: 'Library', 127 | ), 128 | BottomNavigationBarItem( 129 | icon: Icon(Icons.timelapse), 130 | label: 'Recently Played', 131 | ), 132 | BottomNavigationBarItem( 133 | icon: Icon(Icons.search), 134 | label: 'Search', 135 | ), 136 | ], 137 | currentIndex: _calculateSelectedIndex(context), 138 | onTap: (int idx) => _onItemTapped(idx, context), 139 | ), 140 | ); 141 | } 142 | 143 | static int _calculateSelectedIndex(BuildContext context) { 144 | final GoRouter route = GoRouter.of(context); 145 | final String location = route.location; 146 | if (location.startsWith('/recents')) { 147 | return 1; 148 | } else if (location.startsWith('/search')) { 149 | return 2; 150 | } else { 151 | return 0; 152 | } 153 | } 154 | 155 | void _onItemTapped(int index, BuildContext context) { 156 | switch (index) { 157 | case 1: 158 | GoRouter.of(context).go('/recents'); 159 | break; 160 | case 2: 161 | GoRouter.of(context).go('/search'); 162 | break; 163 | case 0: 164 | default: 165 | GoRouter.of(context).go('/library'); 166 | break; 167 | } 168 | } 169 | } 170 | 171 | class LibraryScreen extends StatelessWidget { 172 | const LibraryScreen({Key? key}) : super(key: key); 173 | 174 | @override 175 | Widget build(BuildContext context) { 176 | final database = MusicDatabase.of(context); 177 | return Scaffold( 178 | appBar: AppBar( 179 | title: const Text('Library'), 180 | ), 181 | body: ListView.builder( 182 | itemBuilder: (context, albumId) { 183 | final album = database.albums[albumId]; 184 | return AlbumTile( 185 | album: album, 186 | onTap: () { 187 | GoRouter.of(context).go('/library/album/$albumId'); 188 | }, 189 | ); 190 | }, 191 | itemCount: database.albums.length, 192 | ), 193 | ); 194 | } 195 | } 196 | 197 | class RecentlyPlayedScreen extends StatelessWidget { 198 | const RecentlyPlayedScreen({Key? key}) : super(key: key); 199 | 200 | @override 201 | Widget build(BuildContext context) { 202 | final database = MusicDatabase.of(context); 203 | final songs = database.recentlyPlayed; 204 | return Scaffold( 205 | appBar: AppBar( 206 | title: const Text('Recently Played'), 207 | ), 208 | body: ListView.builder( 209 | itemBuilder: (context, index) { 210 | final song = songs[index]; 211 | final albumIdInt = int.tryParse(song.albumId)!; 212 | final album = database.albums[albumIdInt]; 213 | return SongTile( 214 | album: album, 215 | song: song, 216 | onTap: () { 217 | GoRouter.of(context).go('/recents/song/${song.fullId}'); 218 | }, 219 | ); 220 | }, 221 | itemCount: songs.length, 222 | ), 223 | ); 224 | } 225 | } 226 | 227 | class SearchScreen extends StatefulWidget { 228 | final String query; 229 | 230 | const SearchScreen({Key? key, required this.query}) : super(key: key); 231 | 232 | @override 233 | State createState() => _SearchScreenState(); 234 | } 235 | 236 | class _SearchScreenState extends State { 237 | String? _currentQuery; 238 | 239 | @override 240 | Widget build(BuildContext context) { 241 | final database = MusicDatabase.of(context); 242 | final songs = database.search(widget.query); 243 | return Scaffold( 244 | appBar: AppBar( 245 | title: const Text('Search'), 246 | ), 247 | body: Column( 248 | children: [ 249 | Padding( 250 | padding: const EdgeInsets.all(12.0), 251 | child: TextField( 252 | decoration: const InputDecoration( 253 | hintText: 'Search...', 254 | border: OutlineInputBorder(), 255 | ), 256 | onChanged: (String? newSearch) { 257 | _currentQuery = newSearch; 258 | }, 259 | onEditingComplete: () { 260 | GoRouter.of(context).go( 261 | '/search?q=$_currentQuery', 262 | ); 263 | }, 264 | ), 265 | ), 266 | Expanded( 267 | child: ListView.builder( 268 | itemBuilder: (context, index) { 269 | final song = songs[index]; 270 | return SongTile( 271 | album: database.albums[int.tryParse(song.albumId)!], 272 | song: song, 273 | onTap: () { 274 | GoRouter.of(context).go( 275 | '/library/album/${song.albumId}/song/${song.fullId}'); 276 | }, 277 | ); 278 | }, 279 | itemCount: songs.length, 280 | ), 281 | ), 282 | ], 283 | ), 284 | ); 285 | } 286 | } 287 | 288 | class AlbumScreen extends StatelessWidget { 289 | final String? albumId; 290 | 291 | const AlbumScreen({ 292 | required this.albumId, 293 | Key? key, 294 | }) : super(key: key); 295 | 296 | @override 297 | Widget build(BuildContext context) { 298 | final database = MusicDatabase.of(context); 299 | final albumIdInt = int.tryParse(albumId ?? ''); 300 | final album = database.albums[albumIdInt!]; 301 | return Scaffold( 302 | appBar: AppBar( 303 | title: Text('Album - ${album.title}'), 304 | ), 305 | body: Center( 306 | child: Column( 307 | children: [ 308 | Row( 309 | children: [ 310 | SizedBox( 311 | width: 200, 312 | height: 200, 313 | child: Container( 314 | color: album.color, 315 | margin: const EdgeInsets.all(8), 316 | ), 317 | ), 318 | Column( 319 | crossAxisAlignment: CrossAxisAlignment.start, 320 | children: [ 321 | Text( 322 | album.title, 323 | style: Theme.of(context).textTheme.headlineMedium, 324 | ), 325 | Text( 326 | album.artist, 327 | style: Theme.of(context).textTheme.titleMedium, 328 | ), 329 | ], 330 | ), 331 | ], 332 | ), 333 | Expanded( 334 | child: ListView.builder( 335 | itemBuilder: (context, index) { 336 | final song = album.songs[index]; 337 | return ListTile( 338 | title: Text(song.title), 339 | leading: SizedBox( 340 | width: 50, 341 | height: 50, 342 | child: Container( 343 | color: album.color, 344 | margin: const EdgeInsets.all(8), 345 | ), 346 | ), 347 | trailing: SongDuration( 348 | duration: song.duration, 349 | ), 350 | onTap: () { 351 | GoRouter.of(context) 352 | .go('/library/album/$albumId/song/${song.fullId}'); 353 | }, 354 | ); 355 | }, 356 | itemCount: album.songs.length, 357 | ), 358 | ), 359 | ], 360 | ), 361 | ), 362 | ); 363 | } 364 | } 365 | 366 | class SongScreen extends StatelessWidget { 367 | final String songId; 368 | 369 | const SongScreen({ 370 | Key? key, 371 | required this.songId, 372 | }) : super(key: key); 373 | 374 | @override 375 | Widget build(BuildContext context) { 376 | final database = MusicDatabase.of(context); 377 | final song = database.getSongById(songId); 378 | final albumIdInt = int.tryParse(song.albumId); 379 | final album = database.albums[albumIdInt!]; 380 | 381 | return Scaffold( 382 | appBar: AppBar( 383 | title: Text('Song - ${song.title}'), 384 | ), 385 | body: Column( 386 | children: [ 387 | Row( 388 | children: [ 389 | SizedBox( 390 | width: 300, 391 | height: 300, 392 | child: Container( 393 | color: album.color, 394 | margin: const EdgeInsets.all(8), 395 | ), 396 | ), 397 | Padding( 398 | padding: const EdgeInsets.all(16.0), 399 | child: Column( 400 | crossAxisAlignment: CrossAxisAlignment.start, 401 | children: [ 402 | Text( 403 | song.title, 404 | style: Theme.of(context).textTheme.displayMedium, 405 | ), 406 | Text( 407 | album.title, 408 | style: Theme.of(context).textTheme.titleMedium, 409 | ), 410 | ], 411 | ), 412 | ) 413 | ], 414 | ) 415 | ], 416 | ), 417 | ); 418 | } 419 | } 420 | 421 | class MusicDatabase { 422 | final List albums; 423 | final List recentlyPlayed; 424 | final Map _allSongs = {}; 425 | 426 | MusicDatabase(this.albums, this.recentlyPlayed) { 427 | _populateAllSongs(); 428 | } 429 | 430 | factory MusicDatabase.mock() { 431 | final albums = _mockAlbums().toList(); 432 | final recentlyPlayed = _mockRecentlyPlayed(albums).toList(); 433 | return MusicDatabase(albums, recentlyPlayed); 434 | } 435 | 436 | Song getSongById(String songId) { 437 | if (_allSongs.containsKey(songId)) { 438 | return _allSongs[songId]!; 439 | } 440 | throw ('No song with ID $songId found.'); 441 | } 442 | 443 | List search(String searchString) { 444 | final songs = []; 445 | for (var song in _allSongs.values) { 446 | final album = albums[int.tryParse(song.albumId)!]; 447 | if (song.title.contains(searchString) || 448 | album.title.contains(searchString)) { 449 | songs.add(song); 450 | } 451 | } 452 | return songs; 453 | } 454 | 455 | void _populateAllSongs() { 456 | for (var album in albums) { 457 | for (var song in album.songs) { 458 | _allSongs[song.fullId] = song; 459 | } 460 | } 461 | } 462 | 463 | static MusicDatabase of(BuildContext context) { 464 | final routeStateScope = 465 | context.dependOnInheritedWidgetOfExactType(); 466 | if (routeStateScope == null) throw ('No RouteState in scope!'); 467 | return routeStateScope.state; 468 | } 469 | 470 | static Iterable _mockAlbums() sync* { 471 | for (var i = 0; i < Colors.primaries.length; i++) { 472 | final color = Colors.primaries[i]; 473 | final title = WordPair.random().toString(); 474 | final artist = WordPair.random().toString(); 475 | final songs = []; 476 | for (var j = 0; j < 12; j++) { 477 | final minutes = math.Random().nextInt(3) + 3; 478 | final seconds = math.Random().nextInt(60); 479 | final title = WordPair.random(); 480 | final duration = Duration(minutes: minutes, seconds: seconds); 481 | final song = Song('$j', '$i', '$title', duration); 482 | 483 | songs.add(song); 484 | } 485 | yield Album('$i', title, artist, color, songs); 486 | } 487 | } 488 | 489 | static Iterable _mockRecentlyPlayed(List albums) sync* { 490 | for (var album in albums) { 491 | final songIndex = math.Random().nextInt(album.songs.length); 492 | yield album.songs[songIndex]; 493 | } 494 | } 495 | } 496 | 497 | class MusicDatabaseScope extends InheritedWidget { 498 | final MusicDatabase state; 499 | 500 | const MusicDatabaseScope({ 501 | required this.state, 502 | required Widget child, 503 | Key? key, 504 | }) : super(child: child, key: key); 505 | 506 | @override 507 | bool updateShouldNotify(covariant InheritedWidget oldWidget) { 508 | return oldWidget is MusicDatabaseScope && state != oldWidget.state; 509 | } 510 | } 511 | 512 | class Album { 513 | final String id; 514 | final String title; 515 | final String artist; 516 | final Color color; 517 | final List songs; 518 | 519 | Album(this.id, this.title, this.artist, this.color, this.songs); 520 | } 521 | 522 | class Song { 523 | final String id; 524 | final String albumId; 525 | final String title; 526 | final Duration duration; 527 | 528 | Song(this.id, this.albumId, this.title, this.duration); 529 | 530 | String get fullId => '$albumId-$id'; 531 | } 532 | 533 | class AlbumTile extends StatelessWidget { 534 | final Album album; 535 | final VoidCallback? onTap; 536 | 537 | const AlbumTile({Key? key, required this.album, this.onTap}) : super(key: key); 538 | 539 | @override 540 | Widget build(BuildContext context) { 541 | return ListTile( 542 | leading: SizedBox( 543 | width: 50, 544 | height: 50, 545 | child: Container( 546 | color: album.color, 547 | ), 548 | ), 549 | title: Text(album.title), 550 | subtitle: Text(album.artist), 551 | onTap: onTap, 552 | ); 553 | } 554 | } 555 | 556 | class SongTile extends StatelessWidget { 557 | final Album album; 558 | final Song song; 559 | final VoidCallback? onTap; 560 | 561 | const SongTile({Key? key, required this.album, required this.song, this.onTap}) 562 | : super(key: key); 563 | 564 | @override 565 | Widget build(BuildContext context) { 566 | return ListTile( 567 | leading: SizedBox( 568 | width: 50, 569 | height: 50, 570 | child: Container( 571 | color: album.color, 572 | margin: const EdgeInsets.all(8), 573 | ), 574 | ), 575 | title: Text(song.title), 576 | trailing: SongDuration( 577 | duration: song.duration, 578 | ), 579 | onTap: onTap, 580 | ); 581 | } 582 | } 583 | 584 | class SongDuration extends StatelessWidget { 585 | final Duration duration; 586 | 587 | const SongDuration({ 588 | required this.duration, 589 | Key? key, 590 | }) : super(key: key); 591 | 592 | @override 593 | Widget build(BuildContext context) { 594 | return Text( 595 | '${duration.inMinutes.toString().padLeft(2, '0')}:${(duration.inSeconds % 60).toString().padLeft(2, '0')}'); 596 | } 597 | } 598 | 599 | /// A page that fades in an out. 600 | class FadeTransitionPage extends CustomTransitionPage { 601 | /// Creates a [FadeTransitionPage]. 602 | FadeTransitionPage({ 603 | required LocalKey key, 604 | required Widget child, 605 | }) : super( 606 | key: key, 607 | transitionsBuilder: (BuildContext context, 608 | Animation animation, 609 | Animation secondaryAnimation, 610 | Widget child) => 611 | FadeTransition( 612 | opacity: animation.drive(_curveTween), 613 | child: child, 614 | ), 615 | child: child); 616 | 617 | static final CurveTween _curveTween = CurveTween(curve: Curves.easeIn); 618 | } 619 | 620 | 621 | https://dartpad.dev/?id=2f8a1f806f2f67ce0426a4b0a00ce0d4 -------------------------------------------------------------------------------- /snippets/nanochat.md: -------------------------------------------------------------------------------- 1 | # Dartpad Nanochat using FlutterFire (Auth + Firestore) 2 | 3 | ### Code Snippets 4 | ``` 5 | import 'package:cloud_firestore/cloud_firestore.dart'; 6 | import 'package:firebase_auth/firebase_auth.dart'; 7 | import 'package:firebase_core/firebase_core.dart'; 8 | import 'package:flutter/material.dart'; 9 | import 'package:intl/intl.dart'; 10 | 11 | const Color darkBlue = Color.fromARGB(255, 18, 32, 47); 12 | 13 | const messageLimit = 30; 14 | 15 | void main() async { 16 | try { 17 | WidgetsFlutterBinding.ensureInitialized(); 18 | } catch (e, st) { 19 | print(e); 20 | print(st); 21 | } 22 | 23 | // The first step to using Firebase is to configure it so that our code can 24 | // find the Firebase project on the servers. This is not a security risk, as 25 | // explained here: https://stackoverflow.com/a/37484053 26 | await Firebase.initializeApp( 27 | options: const FirebaseOptions( 28 | apiKey: "AIzaSyAhE5iTdU1MflQxb4_M_uHiXJR9EC_mE_I", 29 | authDomain: "nanochat.firebaseapp.com", 30 | projectId: "firebase-nanochat", 31 | messagingSenderId: '137230848633', 32 | appId: '1:137230848633:web:89e9b54f881fa0b843baa8')); 33 | 34 | // We sign the user in anonymously, meaning they get a user ID without having 35 | // to provide credentials. While this doesn't allow us to identify the user, 36 | // this would, for example, still allow us to associate data in the database 37 | // with each user. 38 | await FirebaseAuth.instance.signInAnonymously(); 39 | 40 | runApp(MyApp()); 41 | } 42 | 43 | class MyApp extends StatelessWidget { 44 | final DateFormat formatter = DateFormat('MM/dd HH:mm:SS'); 45 | 46 | MyApp({Key? key}) : super(key: key); 47 | 48 | @override 49 | Widget build(BuildContext context) { 50 | return MaterialApp( 51 | home: Scaffold( 52 | body: Padding( 53 | padding: const EdgeInsets.symmetric(horizontal: 16.0), 54 | child: Column( 55 | crossAxisAlignment: CrossAxisAlignment.start, 56 | children: [ 57 | // The user can send a message to Firebase. What they can send is 58 | // protected by server-side security rules, which in this case 59 | // only allow chat messages that this regular expression: 60 | // 61 | // ^((?i)hello|\\s|firebase|welcome|to|summit|the|this| 62 | // everyone|good|morning|afternoon|firestore|meetup| 63 | // devfest|virtual|online)+ 64 | // 65 | // In a real project you'd probably expand that, for example by 66 | // only allowing users that you explicitly approve to post 67 | // messages. 68 | const SizedBox(height: 32), 69 | Text( 70 | 'Enter a new message', 71 | style: Theme.of(context).textTheme.headlineSmall, 72 | ), 73 | const SizedBox(height: 16), 74 | Text( 75 | 'You can type a message into this field and hit the enter key ' 76 | 'to add it to the stream. The security rules for the ' 77 | 'Firestore database only allow certain words, though! Check ' 78 | 'the comments in the code to the left for details.', 79 | style: Theme.of(context).textTheme.titleMedium, 80 | ), 81 | const SizedBox(height: 16), 82 | FractionallySizedBox( 83 | widthFactor: 0.5, 84 | child: TextField( 85 | decoration: const InputDecoration( 86 | border: OutlineInputBorder(), 87 | hintText: 'Enter your message and hit Enter'), 88 | onSubmitted: (String value) { 89 | FirebaseFirestore.instance.collection('chat').add( 90 | { 91 | 'message': value, 92 | 'timestamp': DateTime.now().millisecondsSinceEpoch 93 | }, 94 | ); 95 | }, 96 | ), 97 | ), 98 | // We use a stream builder to both read the initial data from the 99 | // database and listen to updates to that data in realtime. The 100 | // database we use is called Firestore, and we are asking the 10 101 | // most recent messages. 102 | const SizedBox(height: 32), 103 | Text( 104 | 'The latest messages', 105 | style: Theme.of(context).textTheme.headlineSmall, 106 | ), 107 | const SizedBox(height: 16), 108 | Expanded( 109 | child: StreamBuilder( 110 | stream: FirebaseFirestore.instance 111 | .collection('chat') 112 | .orderBy('timestamp', descending: true) 113 | .limit(messageLimit) 114 | .snapshots(), 115 | builder: (context, snapshot) { 116 | if (snapshot.hasError) { 117 | return Center(child: Text('$snapshot.error')); 118 | } else if (!snapshot.hasData) { 119 | return const Center( 120 | child: SizedBox( 121 | width: 50, 122 | height: 50, 123 | child: CircularProgressIndicator(), 124 | ), 125 | ); 126 | } 127 | 128 | var docs = snapshot.data!.docs; 129 | 130 | return ListView.builder( 131 | itemCount: docs.length, 132 | itemBuilder: (context, i) { 133 | return ListTile( 134 | leading: DefaultTextStyle.merge( 135 | style: const TextStyle(color: Colors.indigo), 136 | child: Text(formatter.format( 137 | DateTime.fromMillisecondsSinceEpoch( 138 | docs[i]['timestamp']))), 139 | ), 140 | title: Text('${docs[i]['message']}'), 141 | ); 142 | }, 143 | ); 144 | }, 145 | ), 146 | ), 147 | ], 148 | ), 149 | ), 150 | ), 151 | ); 152 | } 153 | } 154 | ``` 155 | ### Dart Pad : https://dartpad.dev/?id=d57c6c898dabb8c6fb41018588b8cf73 156 | -------------------------------------------------------------------------------- /snippets/no_connection_widget.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ```` 4 | class NoConnectionWidget extends StatelessWidget { 5 | const NoConnectionWidget({Key? key, this.pressed}) : super(key: key); 6 | final OnPressed? pressed; 7 | @override 8 | Widget build(BuildContext context) { 9 | return SingleChildScrollView( 10 | child: Padding( 11 | padding: const EdgeInsets.all(32.0), 12 | child: Column( 13 | mainAxisSize: MainAxisSize.max, 14 | mainAxisAlignment: MainAxisAlignment.end, 15 | children: [ 16 | SizedBox( 17 | child: Image.asset( 18 | 'assets/images/no_internet.jpg', 19 | //height: MediaQuery.of(context).size.height / 2, 20 | )), 21 | SizedBox( 22 | width: double.infinity, 23 | child: ElevatedButton( 24 | style: ButtonStyle( 25 | backgroundColor: 26 | MaterialStateProperty.all(AppStyles.info500Color), 27 | ), 28 | onPressed: () { 29 | debugPrint('NoConnectionWidget click : $pressed'); 30 | pressed?.call(); 31 | }, 32 | child: const Text('Retry'), 33 | ), 34 | ) 35 | ], 36 | ), 37 | ), 38 | ); 39 | } 40 | } 41 | ``` 42 | 43 | To access full code` [Dartpad](https://dartpad.dev/?id=7c1b183e77182ce7bdc3b45033f93db6) 44 | -------------------------------------------------------------------------------- /snippets/notch_curve_widget.md: -------------------------------------------------------------------------------- 1 | ## Notch Curve to Widget 2 | 3 | Dartpad Link : https://dartpad.dev/flutter?9bd55396e067e71a839851e18905f478&id=9bd55396e067e71a839851e18905f478 4 | 5 | Output: https://i.stack.imgur.com/wSFUi.png 6 | -------------------------------------------------------------------------------- /snippets/outlined_button.md: -------------------------------------------------------------------------------- 1 | ``` 2 | import 'package:flutter/material.dart'; 3 | 4 | const Color darkBlue = Color.fromARGB(255, 18, 32, 47); 5 | 6 | void main() { 7 | runApp(MyApp()); 8 | } 9 | 10 | class MyApp extends StatelessWidget { 11 | @override 12 | Widget build(BuildContext context) { 13 | return MaterialApp( 14 | theme: ThemeData.dark().copyWith( 15 | scaffoldBackgroundColor: darkBlue, 16 | ), 17 | debugShowCheckedModeBanner: false, 18 | home: Scaffold( 19 | backgroundColor: darkBlue, 20 | body: Center( 21 | child: MyOutlinedButton( 22 | onPressed: () {}, 23 | gradient: LinearGradient(colors: [Colors.indigo, Colors.pink]), 24 | child: Container(height : 50, width : 120,child : Center(child : Text('OutlinedButton'))), 25 | ), 26 | ), 27 | ), 28 | ); 29 | } 30 | } 31 | 32 | class MyOutlinedButton extends StatelessWidget { 33 | final VoidCallback onPressed; 34 | final Widget child; 35 | final ButtonStyle? style; 36 | final Gradient? gradient; 37 | final double thickness; 38 | 39 | const MyOutlinedButton({ 40 | Key? key, 41 | required this.onPressed, 42 | required this.child, 43 | this.style, 44 | this.gradient, 45 | this.thickness = 4, 46 | }) : super(key: key); 47 | 48 | @override 49 | Widget build(BuildContext context) { 50 | return DecoratedBox( 51 | decoration: BoxDecoration(gradient: gradient), 52 | child: Container( 53 | color: Colors.white, 54 | margin: EdgeInsets.all(thickness), 55 | child: OutlinedButton( 56 | onPressed: onPressed, 57 | style: style, 58 | child: child, 59 | ), 60 | ), 61 | ); 62 | } 63 | } 64 | 65 | ``` 66 | 67 | https://dartpad.dev/?id=83829439faaec3f7c17b36ad712534d1 68 | -------------------------------------------------------------------------------- /snippets/overlay_progress_loader.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | # Progress loader overlay 6 | 7 | You'll be able to customize your `loader` with the `ProgressDialogUtils` widget. 8 | 9 | ##Dependencies 10 | 1. get 11 | 2. flutter_spinkit 12 | 13 | Example Code: 14 | ``` 15 | class ProgressDialogUtils { 16 | static bool isProgressVisible = false; 17 | 18 | ///common method for showing progress dialog 19 | static void showProgressDialog({isCancellable = false}) async { 20 | if (!isProgressVisible) { 21 | Get.dialog( 22 | Center( 23 | child: SpinKitCircle( 24 | color: primaryColor, 25 | size: 20), 26 | ), 27 | barrierDismissible: isCancellable, 28 | ); 29 | isProgressVisible = true; 30 | } 31 | } 32 | 33 | ///common method for hiding progress dialog 34 | static void hideProgressDialog() { 35 | if (isProgressVisible) Get.back(); 36 | isProgressVisible = false; 37 | } 38 | } 39 | ``` 40 | 41 | 42 | ## Try out on [Dartpad](https://dartpad.dev/?id=802b01dbfd3552d4072c28302c616889). 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /snippets/progress_hud_widget.md: -------------------------------------------------------------------------------- 1 | #progress_hud_widget 2 | 3 | ``` 4 | import 'package:flutter/material.dart'; 5 | 6 | const Color darkBlue = Color.fromARGB(255, 18, 32, 47); 7 | 8 | void main() { 9 | runApp(MyApp()); 10 | } 11 | 12 | class MyApp extends StatelessWidget { 13 | @override 14 | Widget build(BuildContext context) { 15 | return MaterialApp( 16 | theme: ThemeData.dark().copyWith( 17 | scaffoldBackgroundColor: darkBlue, 18 | ), 19 | debugShowCheckedModeBanner: false, 20 | home: Scaffold( 21 | body: Center( 22 | child: progressHudWidget(context), 23 | ), 24 | ), 25 | ); 26 | } 27 | 28 | 29 | static Widget progressHudWidget(BuildContext context) { 30 | return const Center( 31 | child: CircularProgressIndicator(color: Colors.amber), 32 | ); 33 | } 34 | }``` 35 | 36 | Dart Pad : https://dartpad.dev/?id=fec16cb118ee2648f974b85905f0d5e1 37 | -------------------------------------------------------------------------------- /snippets/random_dice.md: -------------------------------------------------------------------------------- 1 | // Add global variable name 2 | 3 | int randomNumber = 1; 4 | double opacityLevel = 1.0; 5 | 6 | // Add Color change function 7 | 8 | Color randomColor() { 9 | return (Colors.primaries[Random().nextInt(Colors.primaries.length)]); 10 | } 11 | 12 | // Add Random dice number function 13 | 14 | Widget showDice() { 15 | return AnimatedOpacity( 16 | opacity: opacityLevel, 17 | duration: const Duration(seconds: 3), 18 | child: Container( 19 | height: 200, 20 | width: 200, 21 | decoration: BoxDecoration( 22 | color: randomColor(), 23 | borderRadius: const BorderRadius.all(Radius.circular(15))), 24 | alignment: Alignment.center, 25 | child: Text("${randomNumber + 1}", 26 | style: const TextStyle(fontSize: 50, color: Colors.white), 27 | ), 28 | ), 29 | ); 30 | } 31 | 32 | // Use it in your code 33 | 34 | Container( 35 | margin: const EdgeInsets.all(8), 36 | child: Center( 37 | child: Column( 38 | children: [ 39 | Container( 40 | margin: const EdgeInsets.all(8.0), 41 | child: ElevatedButton( 42 | onPressed: () { 43 | _changeOpacity(); 44 | }, 45 | child: const Text('Update Dice'), 46 | ), 47 | ), 48 | const SizedBox(height: 50), 49 | showDice(), 50 | ], 51 | ), 52 | ), 53 | ), 54 | 55 | Here is the [Dartpad](https://dartpad.dev/?id=d347c2d6b5de3731f36ba688faabffb8) 56 | -------------------------------------------------------------------------------- /snippets/repaint_boundry.md: -------------------------------------------------------------------------------- 1 | #Repaint Boundary 2 | 3 | Dart pad link:- https://dartpad.dev/?id=446ab37078c59d8dcb688c9d5f1eb7f4 4 | -------------------------------------------------------------------------------- /snippets/rich_text.md: -------------------------------------------------------------------------------- 1 | 2 | // Use it in your code 3 | 4 | Container( 5 | alignment: Alignment.center, 6 | child: const Text.rich( 7 | TextSpan( 8 | 9 | children: [ 10 | TextSpan( 11 | text: "Normal ", 12 | style: TextStyle(fontStyle: FontStyle.normal)), 13 | TextSpan( 14 | text: "Italic ", 15 | style: TextStyle(fontStyle: FontStyle.italic)), 16 | TextSpan( 17 | text: "Bold ", 18 | style: TextStyle(fontWeight: FontWeight.bold)), 19 | TextSpan( 20 | text: "Underline ", 21 | style: TextStyle(decoration: TextDecoration.underline)), 22 | TextSpan( 23 | text: "Text Color ", 24 | style: TextStyle(color: Colors.green)), 25 | TextSpan( 26 | text: "Font Size ", 27 | style: TextStyle(fontSize: 20)), 28 | ], 29 | ), 30 | )), 31 | 32 | Here is the [Dartpad](https://dartpad.dev/?id=c93ef591d980de280c1aed1af12dafa5) 33 | -------------------------------------------------------------------------------- /snippets/rotate_text.md: -------------------------------------------------------------------------------- 1 | Example Code 2 | 3 | ``` 4 | return Container( 5 | child: Transform.rotate( 6 | angle: 45, 7 | child: Text( 8 | 'Hello, World!', 9 | style: Theme.of(context).textTheme.headline4, 10 | ), 11 | ), 12 | ); 13 | ``` 14 | 15 | Dartpad: https://dartpad.dev/?id=a98bd495eb7fab653960ec21640f2c23 16 | -------------------------------------------------------------------------------- /snippets/round-container-with-image.md: -------------------------------------------------------------------------------- 1 | # Round Container with Image in Flutter 2 | 3 | Code: 4 | 5 | ``` 6 | Container( 7 | width: 200.0, 8 | height: 200.0, 9 | margin: const EdgeInsets.all(50.0), 10 | decoration: const BoxDecoration( 11 | borderRadius: BorderRadius.all( 12 | Radius.circular(100.0), 13 | ), 14 | image: DecorationImage( 15 | image: NetworkImage('https://cdn.pixabay.com/photo/2015/04/23/22/00/tree-736885__480.jpg'), 16 | fit: BoxFit.cover, 17 | ), 18 | ), 19 | ), 20 | ``` 21 | 22 | Alternative way using ClipRRect: 23 | 24 | ``` 25 | Container( 26 | width: 200.0, 27 | height: 200.0, 28 | margin: const EdgeInsets.all(50.0), 29 | child: ClipRRect( 30 | borderRadius: BorderRadius.circular(100.0), 31 | child: Image.network( 32 | 'https://cdn.pixabay.com/photo/2015/04/23/22/00/tree-736885__480.jpg', 33 | fit: BoxFit.cover, 34 | ), 35 | ) 36 | ), 37 | ``` 38 | 39 | ## Try out on [dartpad](https://dartpad.dev/?id=0783da4d7149326d41c5425114ecb84d). 40 | -------------------------------------------------------------------------------- /snippets/round_corner_image.md: -------------------------------------------------------------------------------- 1 | # Round Container with Image in Flutter 2 | 3 | Code: 4 | 5 | ``` 6 | return Container( 7 | width: 200.0, 8 | height: 200.0, 9 | margin: const EdgeInsets.all(50.0), 10 | decoration: const BoxDecoration( 11 | borderRadius: BorderRadius.all( 12 | Radius.circular(20.0), 13 | ), 14 | image: DecorationImage( 15 | image: NetworkImage('https://cdn.pixabay.com/photo/2015/04/23/22/00/tree-736885__480.jpg'), 16 | fit: BoxFit.cover, 17 | ), 18 | ), 19 | ); 20 | ``` 21 | 22 | ## Try out on [dartpad](https://dartpad.dev/?id=28c8fe4b5ca630a2963996f61c396878). 23 | -------------------------------------------------------------------------------- /snippets/round_ripple_animation.md: -------------------------------------------------------------------------------- 1 | #Round Ripple Animarion 2 | 3 | DartPad Link:- https://dartpad.dev/?id=d701a5c966f5154ba5329ad92476f86c 4 | -------------------------------------------------------------------------------- /snippets/search_delegate.dart: -------------------------------------------------------------------------------- 1 | # Search Delegate 2 | 3 | Code: 4 | ``` 5 | import 'package:flutter/material.dart'; 6 | 7 | void main() { 8 | runApp(const MyApp()); 9 | } 10 | 11 | class MyApp extends StatelessWidget { 12 | const MyApp({Key? key}) : super(key: key); 13 | 14 | // This widget is the root of your application. 15 | @override 16 | Widget build(BuildContext context) { 17 | return MaterialApp( 18 | debugShowCheckedModeBanner: false, 19 | title: 'Flutter Demo', 20 | theme: ThemeData( 21 | primarySwatch: Colors.blue, 22 | ), 23 | home: HomePage(), 24 | ); 25 | } 26 | } 27 | 28 | class HomePage extends StatefulWidget { 29 | final List list = List.generate(10, (index) => "Text $index"); 30 | 31 | @override 32 | _HomePageState createState() => _HomePageState(); 33 | } 34 | 35 | class _HomePageState extends State { 36 | @override 37 | Widget build(BuildContext context) { 38 | return Scaffold( 39 | appBar: AppBar( 40 | actions: [ 41 | IconButton( 42 | onPressed: () { 43 | showSearch(context: context, delegate: Search(widget.list)); 44 | }, 45 | icon: const Icon(Icons.search), 46 | ) 47 | ], 48 | centerTitle: true, 49 | title: const Text('Search Bar'), 50 | ), 51 | body: ListView.builder( 52 | itemCount: widget.list.length, 53 | itemBuilder: (context, index) => ListTile( 54 | title: Text( 55 | widget.list[index], 56 | ), 57 | ), 58 | ), 59 | ); 60 | } 61 | } 62 | 63 | class Search extends SearchDelegate { 64 | @override 65 | List buildActions(BuildContext context) { 66 | return [ 67 | IconButton( 68 | icon: const Icon(Icons.close), 69 | onPressed: () { 70 | query = ""; 71 | }, 72 | ), 73 | ]; 74 | } 75 | 76 | @override 77 | Widget buildLeading(BuildContext context) { 78 | return IconButton( 79 | icon: const Icon(Icons.arrow_back), 80 | onPressed: () { 81 | Navigator.pop(context); 82 | }, 83 | ); 84 | } 85 | 86 | String selectedResult = ""; 87 | 88 | @override 89 | Widget buildResults(BuildContext context) { 90 | return 91 | Center( 92 | child: Text(selectedResult), 93 | 94 | ); 95 | } 96 | 97 | final List listExample; 98 | Search(this.listExample); 99 | 100 | List recentList = ["Text 4", "Text 3"]; 101 | 102 | @override 103 | Widget buildSuggestions(BuildContext context) { 104 | List suggestionList = []; 105 | query.isEmpty 106 | ? suggestionList = recentList //In the true case 107 | : suggestionList.addAll(listExample.where( 108 | // In the false case 109 | (element) => element.contains(query), 110 | )); 111 | 112 | return ListView.builder( 113 | itemCount: suggestionList.length, 114 | itemBuilder: (context, index) { 115 | return ListTile( 116 | title: Text( 117 | suggestionList[index], 118 | ), 119 | leading: query.isEmpty ? const Icon(Icons.access_time) : const SizedBox(), 120 | onTap: (){ 121 | selectedResult = suggestionList[index]; 122 | showResults(context); 123 | }, 124 | ); 125 | }, 126 | ); 127 | } 128 | } 129 | ``` 130 | 131 | ## Try out on [Dartpad](https://dartpad.dev/?id=a0cde91e2b6c013f345c61dd3cfb86dd). 132 | -------------------------------------------------------------------------------- /snippets/star-image.md: -------------------------------------------------------------------------------- 1 | class StarClipper extends CustomClipper { 2 | StarClipper(this.numberOfPoints); 3 | 4 | /// The number of points of the star 5 | final int numberOfPoints; 6 | 7 | @override 8 | Path getClip(Size size) { 9 | double width = size.width; 10 | print(width); 11 | double halfWidth = width / 2; 12 | 13 | double bigRadius = halfWidth; 14 | 15 | double radius = halfWidth / 1.3; 16 | 17 | num degreesPerStep = _degToRad(360 / numberOfPoints); 18 | 19 | double halfDegreesPerStep = degreesPerStep / 2; 20 | 21 | var path = Path(); 22 | 23 | double max = 2 * math.pi; 24 | 25 | path.moveTo(width, halfWidth); 26 | 27 | for (double step = 0; step < max; step += degreesPerStep) { 28 | path.lineTo(halfWidth + bigRadius * math.cos(step), 29 | halfWidth + bigRadius * math.sin(step)); 30 | path.lineTo(halfWidth + radius * math.cos(step + halfDegreesPerStep), 31 | halfWidth + radius * math.sin(step + halfDegreesPerStep)); 32 | } 33 | 34 | path.close(); 35 | return path; 36 | } 37 | 38 | num _degToRad(num deg) => deg * (math.pi / 180.0); 39 | 40 | @override 41 | bool shouldReclip(CustomClipper oldClipper) { 42 | StarClipper oldie = oldClipper as StarClipper; 43 | return numberOfPoints != oldie.numberOfPoints; 44 | } 45 | } 46 | 47 | // Use it in your code 48 | 49 | Container( 50 | width: 200.0, 51 | height: 200.0, 52 | margin: const EdgeInsets.all(50.0), 53 | child: ClipPath( 54 | clipper: StarClipper(14), 55 | child: Container( 56 | height: 200, 57 | width: 200, 58 | child: Image.network( 59 | 'https://cdn.pixabay.com/photo/2015/04/23/22/00/tree-736885__480.jpg', 60 | fit: BoxFit.cover, 61 | ), 62 | ), 63 | ), 64 | ); 65 | 66 | Here is the [Dartpad](https://dartpad.dev/?id=86140bfe85c3e5c952bea5e6219d47d1) 67 | -------------------------------------------------------------------------------- /snippets/stateful_builder_use_case.md: -------------------------------------------------------------------------------- 1 | ## TextFormField obscureText in AlertDialog don't change 2 | 3 | ``` 4 | import 'package:flutter/foundation.dart'; 5 | import 'package:flutter/material.dart'; 6 | 7 | void main() { 8 | runApp(const MyApp()); 9 | } 10 | 11 | class MyApp extends StatelessWidget { 12 | const MyApp({Key? key}) : super(key: key); 13 | 14 | @override 15 | Widget build(BuildContext context) { 16 | return MaterialApp( 17 | debugShowCheckedModeBanner: false, 18 | title: 'Flutter Demo', 19 | theme: ThemeData( 20 | primarySwatch: Colors.blue, 21 | ), 22 | home: const MyHomePage(title: 'Flutter Demo Home Page'), 23 | ); 24 | } 25 | } 26 | 27 | class MyHomePage extends StatefulWidget { 28 | const MyHomePage({Key? key, required this.title}) : super(key: key); 29 | final String title; 30 | @override 31 | State createState() => _MyHomePageState(); 32 | } 33 | 34 | class _MyHomePageState extends State { 35 | final username = TextEditingController(text: ''); 36 | final password = TextEditingController(text: ''); 37 | final formKey = GlobalKey(); 38 | late bool obscure; 39 | 40 | @override 41 | void initState() { 42 | obscure = true; 43 | super.initState(); 44 | } 45 | 46 | @override 47 | void dispose() { 48 | username.dispose(); 49 | password.dispose(); 50 | super.dispose(); 51 | } 52 | 53 | @override 54 | Widget build(BuildContext context) { 55 | return Scaffold( 56 | appBar: AppBar( 57 | title: Text(widget.title), 58 | actions: [ 59 | IconButton( 60 | onPressed: () { 61 | 62 | showDialog( 63 | context: context, 64 | barrierDismissible: false, 65 | builder: (_) { 66 | return StatefulBuilder( 67 | builder: (context, setState) 68 | { 69 | return AlertDialog( 70 | title: const Text('Connection'), 71 | content: SizedBox( 72 | height: 400, 73 | width: 400, 74 | child: Form( 75 | key: formKey, 76 | child: Column( 77 | children: [ 78 | TextFormField( 79 | cursorColor: Colors.grey, 80 | textInputAction: TextInputAction.next, 81 | maxLines: 1, 82 | controller: username, 83 | validator: (value) { 84 | return null; 85 | }, 86 | decoration: const InputDecoration( 87 | isDense: true, 88 | prefixIcon: Icon( 89 | Icons.person_outlined, 90 | ), 91 | labelText: 'username', 92 | ), 93 | ), 94 | const SizedBox( 95 | height: 20.0, 96 | ), 97 | TextFormField( 98 | cursorColor: Colors.grey, 99 | controller: password, 100 | textInputAction: TextInputAction.next, 101 | decoration: InputDecoration( 102 | isDense: true, 103 | prefixIcon: const Icon(Icons.key), 104 | labelText: 'password', 105 | suffixIcon: IconButton( 106 | icon: const Icon(Icons.remove_red_eye_outlined), 107 | onPressed: () { 108 | // CHAGE OBSCURE 109 | setState(() { 110 | obscure = !obscure; 111 | if (kDebugMode) { 112 | print(obscure); // OK 113 | } 114 | }); 115 | }), 116 | ), 117 | obscureText: obscure, 118 | // NOT OK 119 | obscuringCharacter: '*', 120 | validator: (String? value) { 121 | return null; 122 | }, 123 | ), 124 | ], 125 | ), 126 | )), 127 | actions: [ 128 | TextButton( 129 | child: const Text('Send'), 130 | onPressed: () { 131 | if (formKey.currentState!.validate()) { 132 | Navigator.of(context).pop(); 133 | } 134 | }, 135 | ), 136 | ], 137 | ); 138 | }); 139 | }); 140 | 141 | }, 142 | icon: const Icon(Icons.person_outline_outlined), 143 | ), 144 | ], 145 | ), 146 | body: Center( 147 | child: Column( 148 | mainAxisAlignment: MainAxisAlignment.center, 149 | children: const [ 150 | Text( 151 | 'You have pushed the button this many times:', 152 | ), 153 | ], 154 | ), 155 | ), 156 | ); 157 | } 158 | } 159 | ``` 160 | 161 | Checkout the demo on [dartpad.dev](https://dartpad.dev/?id=4575689ba129c6f0f036ce5cf04cdb31) 162 | -------------------------------------------------------------------------------- /snippets/stepper.md: -------------------------------------------------------------------------------- 1 | # Stepper for providing steps in flutter 2 | 3 | ``` 4 | import 'package:flutter/material.dart'; 5 | 6 | class StepperDemo extends StatefulWidget { 7 | @override 8 | _StepperDemoState createState() => _StepperDemoState(); 9 | } 10 | 11 | class _StepperDemoState extends State { 12 | int _currentStep = 0; 13 | StepperType stepperType = StepperType.vertical; 14 | 15 | @override 16 | Widget build(BuildContext context) { 17 | return Scaffold( 18 | appBar: AppBar( 19 | automaticallyImplyLeading: false, 20 | title: const Text('Flutter Stepper Demo'), 21 | centerTitle: true, 22 | ), 23 | body: Container( 24 | child: Column( 25 | children: [ 26 | Expanded( 27 | child: Stepper( 28 | type: stepperType, 29 | physics: ScrollPhysics(), 30 | currentStep: _currentStep, 31 | onStepTapped: (step) => tapped(step), 32 | onStepContinue: continued, 33 | onStepCancel: cancel, 34 | steps: [ 35 | Step( 36 | title: const Text('Account'), 37 | content: Column( 38 | children: [ 39 | TextFormField( 40 | decoration: 41 | const InputDecoration(labelText: 'Email Address'), 42 | ), 43 | TextFormField( 44 | decoration: const InputDecoration(labelText: 'Password'), 45 | ), 46 | ], 47 | ), 48 | isActive: _currentStep >= 0, 49 | state: _currentStep >= 0 50 | ? StepState.complete 51 | : StepState.disabled, 52 | ), 53 | Step( 54 | title: const Text('Address'), 55 | content: Column( 56 | children: [ 57 | TextFormField( 58 | decoration: 59 | const InputDecoration(labelText: 'Home Address'), 60 | ), 61 | TextFormField( 62 | decoration: const InputDecoration(labelText: 'Postcode'), 63 | ), 64 | ], 65 | ), 66 | isActive: _currentStep >= 0, 67 | state: _currentStep >= 1 68 | ? StepState.complete 69 | : StepState.disabled, 70 | ), 71 | Step( 72 | title: const Text('Mobile Number'), 73 | content: Column( 74 | children: [ 75 | TextFormField( 76 | decoration: 77 | const InputDecoration(labelText: 'Mobile Number'), 78 | ), 79 | ], 80 | ), 81 | isActive: _currentStep >= 0, 82 | state: _currentStep >= 2 83 | ? StepState.complete 84 | : StepState.disabled, 85 | ), 86 | ], 87 | ), 88 | ), 89 | ], 90 | ), 91 | ), 92 | floatingActionButton: FloatingActionButton( 93 | onPressed: switchStepsType, 94 | child: const Icon(Icons.list), 95 | ), 96 | ); 97 | } 98 | 99 | switchStepsType() { 100 | setState(() => stepperType == StepperType.vertical 101 | ? stepperType = StepperType.horizontal 102 | : stepperType = StepperType.vertical); 103 | } 104 | 105 | tapped(int step) { 106 | setState(() => _currentStep = step); 107 | } 108 | 109 | continued() { 110 | _currentStep < 2 ? setState(() => _currentStep += 1) : null; 111 | } 112 | 113 | cancel() { 114 | _currentStep > 0 ? setState(() => _currentStep -= 1) : null; 115 | } 116 | } 117 | ``` 118 | ## Try out on [dartpad](https://dartpad.dev/?id=5784eb68cdc45ca22c3eb117e83f3de3) 119 | -------------------------------------------------------------------------------- /snippets/text_input_field_color_scheme.md: -------------------------------------------------------------------------------- 1 | ### How to use 2 | 3 | ``` 4 | theme: ThemeData().copyWith( 5 | scaffoldBackgroundColor: Colors.white, 6 | colorScheme: ThemeData().colorScheme.copyWith(primary: Colors.green), 7 | ), 8 | ``` 9 | 10 | Use above code with `MaterialApp`. It will change the color of TextInputField lines as well as Icons. 11 | 12 | Full Code: 13 | 14 | ``` 15 | import 'package:flutter/material.dart'; 16 | 17 | void main() { 18 | runApp(MyApp()); 19 | } 20 | 21 | class MyApp extends StatelessWidget { 22 | @override 23 | Widget build(BuildContext context) { 24 | return MaterialApp( 25 | theme: ThemeData().copyWith( 26 | scaffoldBackgroundColor: Colors.white, 27 | colorScheme: ThemeData().colorScheme.copyWith(primary: Colors.green), 28 | ), 29 | debugShowCheckedModeBanner: false, 30 | home: Scaffold( 31 | body: Center( 32 | child: Padding( 33 | padding: const EdgeInsets.all(24.0), 34 | child: MyWidget(), 35 | ), 36 | ), 37 | ), 38 | ); 39 | } 40 | } 41 | 42 | class MyWidget extends StatelessWidget { 43 | @override 44 | Widget build(BuildContext context) { 45 | return const TextField( 46 | decoration: InputDecoration( 47 | prefixIcon: Icon(Icons.lock_outline), 48 | hintText: 'Username', 49 | ), 50 | ); 51 | } 52 | } 53 | ``` 54 | 55 | Checkout the [demo](https://dartpad.dev/?id=1e9de65ff62acacfe2611706c5eb7246) 56 | -------------------------------------------------------------------------------- /snippets/toggle_animated_icon_button.md: -------------------------------------------------------------------------------- 1 | #Toggle Animated Icon Button 2 | 3 | https://dartpad.dev/?id=224c58d48ec6e86dfea6cd4dcc1f7bc8 --------------------------------------------------------------------------------