├── .editorconfig ├── .gitignore ├── .metadata ├── CHANGELOG.md ├── LICENSE ├── README.md ├── analysis_options.yaml ├── example ├── README.md └── main.dart ├── lib ├── conditional.dart ├── conditional_switch.dart └── flutter_conditional_rendering.dart ├── pubspec.lock ├── pubspec.yaml └── test ├── conditional_switch_test.dart └── conditional_test.dart /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | # define and maintain consistent coding styles between different editors and IDEs 3 | 4 | root = true 5 | 6 | [*] 7 | indent_style = space 8 | indent_size = 2 9 | end_of_line = lf 10 | charset = utf-8 11 | trim_trailing_whitespace = true 12 | insert_final_newline = true 13 | 14 | [*.md] 15 | indent_size = 2 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # IntelliJ related 13 | *.iml 14 | *.ipr 15 | *.iws 16 | .idea/ 17 | 18 | # The .vscode folder contains launch configuration and tasks you configure in 19 | # VS Code which you may wish to be included in version control, so this line 20 | # is commented out by default. 21 | #.vscode/ 22 | 23 | # Flutter/Dart/Pub related 24 | **/doc/api/ 25 | .dart_tool/ 26 | .flutter-plugins 27 | .packages 28 | .pub-cache/ 29 | .pub/ 30 | build/ 31 | 32 | # Android related 33 | **/android/**/gradle-wrapper.jar 34 | **/android/.gradle 35 | **/android/captures/ 36 | **/android/gradlew 37 | **/android/gradlew.bat 38 | **/android/local.properties 39 | **/android/**/GeneratedPluginRegistrant.java 40 | 41 | # iOS/XCode related 42 | **/ios/**/*.mode1v3 43 | **/ios/**/*.mode2v3 44 | **/ios/**/*.moved-aside 45 | **/ios/**/*.pbxuser 46 | **/ios/**/*.perspectivev3 47 | **/ios/**/*sync/ 48 | **/ios/**/.sconsign.dblite 49 | **/ios/**/.tags* 50 | **/ios/**/.vagrant/ 51 | **/ios/**/DerivedData/ 52 | **/ios/**/Icon? 53 | **/ios/**/Pods/ 54 | **/ios/**/.symlinks/ 55 | **/ios/**/profile 56 | **/ios/**/xcuserdata 57 | **/ios/.generated/ 58 | **/ios/Flutter/App.framework 59 | **/ios/Flutter/Flutter.framework 60 | **/ios/Flutter/Flutter.podspec 61 | **/ios/Flutter/Generated.xcconfig 62 | **/ios/Flutter/app.flx 63 | **/ios/Flutter/app.zip 64 | **/ios/Flutter/flutter_assets/ 65 | **/ios/Flutter/flutter_export_environment.sh 66 | **/ios/ServiceDefinitions.json 67 | **/ios/Runner/GeneratedPluginRegistrant.* 68 | 69 | # Exceptions to above rules. 70 | !**/ios/**/default.mode1v3 71 | !**/ios/**/default.mode2v3 72 | !**/ios/**/default.pbxuser 73 | !**/ios/**/default.perspectivev3 74 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages 75 | -------------------------------------------------------------------------------- /.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: 798e4272a2e43d7daab75f225a13442e384ee0cd 8 | channel: unknown 9 | 10 | project_type: package 11 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## [2.1.0] - 2024-03-05 2 | 3 | - Make `fallbackBuilder` optional. 4 | 5 | ## [2.0.0] - 2020-03-12 6 | 7 | - Migrate to null safety. 8 | 9 | ## [1.1.1] - 2020-02-08 10 | 11 | - Minor code format update. 12 | 13 | ## [1.1.0] - 2020-02-08 14 | 15 | - Added `BuildContext` parameter to builder functions. 16 | 17 | - Added generic type to switch functions. 18 | 19 | ## [1.0.2] - 2019-12-13 20 | 21 | - Added example. 22 | 23 | ## [1.0.1] - 2019-12-11 24 | 25 | - Updated package description. 26 | 27 | ## [1.0.0] - 2019-12-11 28 | 29 | - Added two classes: `Conditional` and `ConditionalSwitch`, both of them support `.single()` and `.list()` functions. 30 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (C) 2019, Crizant Lai 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a 6 | copy of this software and associated documentation files (the "Software"), 7 | to deal in the Software without restriction, including without limitation 8 | the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | and/or sell copies of the Software, and to permit persons to whom the 10 | Software is furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | DEALINGS IN THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # flutter_conditional_rendering 2 | 3 | A flutter package which enhances conditional rendering, supports `if`-`else` and `switch` conditions. 4 | 5 | ## Why 6 | 7 | In flutter if you want to do conditional rendering, you may do this: 8 | 9 | ```dart 10 | class MyWidget extends StatelessWidget { 11 | @override 12 | Widget build(BuildContext context) { 13 | return Column( 14 | children: [ 15 | if (someCondition == true) 16 | Text('The condition is true!'), 17 | ], 18 | ); 19 | } 20 | } 21 | ``` 22 | 23 | But what if you want to use a tertiary (`if`-`else`) condition? 24 | 25 | ```dart 26 | class MyWidget extends StatelessWidget { 27 | @override 28 | Widget build(BuildContext context) { 29 | return Column( 30 | children: [ 31 | someCondition == true ? 32 | Text('The condition is true!'): 33 | Text('The condition is false!'), 34 | ], 35 | ); 36 | } 37 | } 38 | ``` 39 | 40 | It is okay for a single `Text` widget, but the readability quickly become very bad when the child widget is multi-layered. 41 | 42 | ## Usage 43 | 44 | ### If-Else condition: 45 | 46 | ```dart 47 | class MyWidget extends StatelessWidget { 48 | @override 49 | Widget build(BuildContext context) { 50 | return Column( 51 | children: [ 52 | Conditional.single( 53 | context: context, 54 | conditionBuilder: (BuildContext context) => someCondition == true, 55 | widgetBuilder: (BuildContext context) => Text('The condition is true!'), 56 | fallbackBuilder: (BuildContext context) => Text('The condition is false!'), 57 | ), 58 | ], 59 | ); 60 | } 61 | } 62 | ``` 63 | 64 | ### Switch condition: 65 | 66 | ```dart 67 | class MyWidget extends StatelessWidget { 68 | @override 69 | Widget build(BuildContext context) { 70 | return Column( 71 | children: [ 72 | ConditionalSwitch.single( 73 | context: context, 74 | valueBuilder: (BuildContext context) => 'A', 75 | caseBuilders: { 76 | 'A': (BuildContext context) => Text('The value is A!'), 77 | 'B': (BuildContext context) => Text('The value is B!'), 78 | }, 79 | fallbackBuilder: (BuildContext context) => Text('None of the cases matched!'), 80 | ), 81 | ], 82 | ); 83 | } 84 | } 85 | ``` 86 | 87 | ## Want a list of widgets? 88 | 89 | If you want to conditionally render a list of widgets (`List`) instead of a single one. Use `Conditional.list()` and `ConditionalSwitch.list()`! 90 | 91 | ## Contributions 92 | 93 | Feel free to contribute to this project. 94 | 95 | If you find a bug or want a feature, but don't know how to fix/implement it, please fill an [issue](https://github.com/crizant/flutter_conditional_rendering/issues). 96 | If you fixed a bug or implemented a feature, please send a [pull request](https://github.com/crizant/flutter_conditional_rendering/pulls). 97 | -------------------------------------------------------------------------------- /analysis_options.yaml: -------------------------------------------------------------------------------- 1 | linter: 2 | rules: 3 | always_declare_return_types: true 4 | avoid_unused_constructor_parameters: true 5 | camel_case_types: true 6 | cancel_subscriptions: true 7 | file_names: true 8 | library_names: true 9 | library_prefixes: true 10 | lines_longer_than_80_chars: true 11 | non_constant_identifier_names: true 12 | prefer_const_constructors: true 13 | prefer_const_declarations: true 14 | prefer_final_fields: true 15 | prefer_final_locals: true 16 | prefer_single_quotes: true 17 | unnecessary_const: true 18 | unnecessary_new: true 19 | unnecessary_this: true 20 | -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | # Example 2 | 3 | This is an example of `flutter_conditional_rendering` package. 4 | 5 | ## Getting Started 6 | 7 | 1. Create a new flutter project 8 | 2. Follow step 1 and 2 of [this guide](https://pub.dev/packages/flutter_conditional_rendering#-installing-tab-) to install the package. 9 | 3. Copy the `main.dart` in this folder, replace the `lib/main.dart` in your project. 10 | 4. Start the application by `flutter run` command. 11 | -------------------------------------------------------------------------------- /example/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_conditional_rendering/conditional.dart'; 3 | 4 | void main() => runApp(MyApp()); 5 | 6 | class MyApp extends StatelessWidget { 7 | // This widget is the root of your application. 8 | @override 9 | Widget build(BuildContext context) { 10 | return MaterialApp( 11 | title: 'Flutter Demo', 12 | theme: ThemeData( 13 | primarySwatch: Colors.blue, 14 | ), 15 | home: MyHomePage(title: 'Flutter Demo Home Page'), 16 | ); 17 | } 18 | } 19 | 20 | class MyHomePage extends StatefulWidget { 21 | MyHomePage({Key? key, required this.title}) : super(key: key); 22 | 23 | final String title; 24 | 25 | @override 26 | _MyHomePageState createState() => _MyHomePageState(); 27 | } 28 | 29 | class _MyHomePageState extends State { 30 | int _counter = 0; 31 | 32 | void _incrementCounter() { 33 | setState(() { 34 | _counter++; 35 | }); 36 | } 37 | 38 | @override 39 | Widget build(BuildContext context) { 40 | return Scaffold( 41 | appBar: AppBar( 42 | title: Text(widget.title), 43 | ), 44 | body: Center( 45 | child: Column( 46 | mainAxisAlignment: MainAxisAlignment.center, 47 | children: [ 48 | const Text( 49 | 'You have pushed the button this many times:', 50 | ), 51 | const SizedBox( 52 | height: 15.0, 53 | ), 54 | Text( 55 | '$_counter', 56 | style: Theme.of(context).textTheme.displayLarge, 57 | ), 58 | const SizedBox( 59 | height: 30.0, 60 | ), 61 | Conditional.single( 62 | context: context, 63 | conditionBuilder: (BuildContext context) => _counter % 2 == 0, 64 | widgetBuilder: (BuildContext context) { 65 | return const Column( 66 | children: [ 67 | Text( 68 | 'The number is even.', 69 | style: TextStyle( 70 | fontWeight: FontWeight.bold, 71 | ), 72 | ), 73 | SizedBox( 74 | height: 10.0, 75 | ), 76 | Icon( 77 | Icons.check, 78 | size: 60.0, 79 | color: Colors.green, 80 | ), 81 | ], 82 | ); 83 | }, 84 | fallbackBuilder: (BuildContext context) { 85 | return const Column( 86 | children: [ 87 | Text( 88 | 'The number is not even.', 89 | style: TextStyle( 90 | fontWeight: FontWeight.bold, 91 | ), 92 | ), 93 | SizedBox( 94 | height: 10.0, 95 | ), 96 | Icon( 97 | Icons.close, 98 | size: 60.0, 99 | color: Colors.red, 100 | ), 101 | ], 102 | ); 103 | }, 104 | ), 105 | ], 106 | ), 107 | ), 108 | floatingActionButton: FloatingActionButton( 109 | onPressed: _incrementCounter, 110 | tooltip: 'Increment', 111 | child: const Icon(Icons.add), 112 | ), 113 | ); 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /lib/conditional.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | /// Conditional rendering class 4 | class Conditional { 5 | Conditional._(); 6 | 7 | /// A function which returns a single `Widget` 8 | /// 9 | /// - [conditionBuilder] is a function which returns a boolean. 10 | /// - [widgetBuilder] is a function which returns a `Widget`, 11 | /// when [conditionBuilder] returns `true`. 12 | /// - [fallbackBuilder] is a function which returns a `Widget`, 13 | /// when [conditionBuilder] returns `false`. If [fallbackBuilder] is 14 | /// not provided, a `Container()` will be returned. 15 | static Widget single({ 16 | required BuildContext context, 17 | required bool Function(BuildContext context) conditionBuilder, 18 | required Widget Function(BuildContext context) widgetBuilder, 19 | Widget Function(BuildContext context)? fallbackBuilder, 20 | }) { 21 | if (conditionBuilder(context) == true) { 22 | return widgetBuilder(context); 23 | } else { 24 | return fallbackBuilder?.call(context) ?? Container(); 25 | } 26 | } 27 | 28 | /// A function which returns a `List` 29 | /// 30 | /// - [conditionBuilder] is the function which returns a boolean. 31 | /// - [widgetBuilder] is a function which returns a `List`, 32 | /// when [conditionBuilder] returns `true`. 33 | /// - [fallbackBuilder] is a function which returns a `List`, 34 | /// when [conditionBuilder] returns `false`. If [fallbackBuilder] is 35 | /// not provided, an empty list will be returned. 36 | static List list({ 37 | required BuildContext context, 38 | required bool Function(BuildContext context) conditionBuilder, 39 | required List Function(BuildContext context) widgetBuilder, 40 | List Function(BuildContext context)? fallbackBuilder, 41 | }) { 42 | if (conditionBuilder(context) == true) { 43 | return widgetBuilder(context); 44 | } else { 45 | return fallbackBuilder?.call(context) ?? []; 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /lib/conditional_switch.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | /// Conditional rendering switch class 4 | class ConditionalSwitch { 5 | ConditionalSwitch._(); 6 | 7 | /// A function which returns a single `Widget` 8 | /// 9 | /// - [valueBuilder] is a function which returns a value. 10 | /// - [caseBuilders] is a `Map` of value to `Widget` builders, 11 | /// when one of the keys matches the value returns by [valueBuilder], 12 | /// the corresponding `Widget` builder will be used. 13 | /// - [fallbackBuilder] is a function which returns a `Widget`, 14 | /// it is used when none of the keys in [caseBuilders]matches 15 | /// the value returns by [valueBuilder]. If [fallbackBuilder] is 16 | /// not provided, a `Container()` will be returned. 17 | static Widget single({ 18 | required BuildContext context, 19 | required T Function(BuildContext context) valueBuilder, 20 | required Map caseBuilders, 21 | Widget Function(BuildContext context)? fallbackBuilder, 22 | }) { 23 | final T value = valueBuilder(context); 24 | if (caseBuilders[value] != null) { 25 | return caseBuilders[value]!(context); 26 | } else { 27 | return fallbackBuilder?.call(context) ?? Container(); 28 | } 29 | } 30 | 31 | /// A function which returns a `List` 32 | /// 33 | /// - [valueBuilder] is a function which returns a value. 34 | /// - [caseBuilders] is a `Map` of value to `List` builders, 35 | /// when one of the keys matches the value returns by [valueBuilder], 36 | /// the corresponding `List` builder will be used. 37 | /// - [fallbackBuilder] is a function which returns a `List`, 38 | /// it is used when none of the keys in [caseBuilders] matches 39 | /// the value returns by [valueBuilder]. If [fallbackBuilder] is 40 | /// not provided, an empty list will be returned. 41 | static List list({ 42 | required BuildContext context, 43 | required T Function(BuildContext context) valueBuilder, 44 | required Map Function(BuildContext context)> caseBuilders, 45 | List Function(BuildContext context)? fallbackBuilder, 46 | }) { 47 | final T value = valueBuilder(context); 48 | if (caseBuilders[value] != null) { 49 | return caseBuilders[value]!(context); 50 | } else { 51 | return fallbackBuilder?.call(context) ?? []; 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /lib/flutter_conditional_rendering.dart: -------------------------------------------------------------------------------- 1 | library flutter_conditional_rendering; 2 | 3 | export 'conditional.dart'; 4 | export 'conditional_switch.dart'; 5 | -------------------------------------------------------------------------------- /pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/tools/pub/glossary#lockfile 3 | packages: 4 | async: 5 | dependency: transitive 6 | description: 7 | name: async 8 | sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" 9 | url: "https://pub.dev" 10 | source: hosted 11 | version: "2.11.0" 12 | boolean_selector: 13 | dependency: transitive 14 | description: 15 | name: boolean_selector 16 | sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" 17 | url: "https://pub.dev" 18 | source: hosted 19 | version: "2.1.1" 20 | characters: 21 | dependency: transitive 22 | description: 23 | name: characters 24 | sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" 25 | url: "https://pub.dev" 26 | source: hosted 27 | version: "1.3.0" 28 | clock: 29 | dependency: transitive 30 | description: 31 | name: clock 32 | sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf 33 | url: "https://pub.dev" 34 | source: hosted 35 | version: "1.1.1" 36 | collection: 37 | dependency: transitive 38 | description: 39 | name: collection 40 | sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a 41 | url: "https://pub.dev" 42 | source: hosted 43 | version: "1.18.0" 44 | fake_async: 45 | dependency: transitive 46 | description: 47 | name: fake_async 48 | sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" 49 | url: "https://pub.dev" 50 | source: hosted 51 | version: "1.3.1" 52 | flutter: 53 | dependency: "direct main" 54 | description: flutter 55 | source: sdk 56 | version: "0.0.0" 57 | flutter_test: 58 | dependency: "direct dev" 59 | description: flutter 60 | source: sdk 61 | version: "0.0.0" 62 | matcher: 63 | dependency: transitive 64 | description: 65 | name: matcher 66 | sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e" 67 | url: "https://pub.dev" 68 | source: hosted 69 | version: "0.12.16" 70 | material_color_utilities: 71 | dependency: transitive 72 | description: 73 | name: material_color_utilities 74 | sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41" 75 | url: "https://pub.dev" 76 | source: hosted 77 | version: "0.5.0" 78 | meta: 79 | dependency: transitive 80 | description: 81 | name: meta 82 | sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e 83 | url: "https://pub.dev" 84 | source: hosted 85 | version: "1.10.0" 86 | path: 87 | dependency: transitive 88 | description: 89 | name: path 90 | sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" 91 | url: "https://pub.dev" 92 | source: hosted 93 | version: "1.8.3" 94 | sky_engine: 95 | dependency: transitive 96 | description: flutter 97 | source: sdk 98 | version: "0.0.99" 99 | source_span: 100 | dependency: transitive 101 | description: 102 | name: source_span 103 | sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" 104 | url: "https://pub.dev" 105 | source: hosted 106 | version: "1.10.0" 107 | stack_trace: 108 | dependency: transitive 109 | description: 110 | name: stack_trace 111 | sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" 112 | url: "https://pub.dev" 113 | source: hosted 114 | version: "1.11.1" 115 | stream_channel: 116 | dependency: transitive 117 | description: 118 | name: stream_channel 119 | sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 120 | url: "https://pub.dev" 121 | source: hosted 122 | version: "2.1.2" 123 | string_scanner: 124 | dependency: transitive 125 | description: 126 | name: string_scanner 127 | sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" 128 | url: "https://pub.dev" 129 | source: hosted 130 | version: "1.2.0" 131 | term_glyph: 132 | dependency: transitive 133 | description: 134 | name: term_glyph 135 | sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 136 | url: "https://pub.dev" 137 | source: hosted 138 | version: "1.2.1" 139 | test_api: 140 | dependency: transitive 141 | description: 142 | name: test_api 143 | sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" 144 | url: "https://pub.dev" 145 | source: hosted 146 | version: "0.6.1" 147 | vector_math: 148 | dependency: transitive 149 | description: 150 | name: vector_math 151 | sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" 152 | url: "https://pub.dev" 153 | source: hosted 154 | version: "2.1.4" 155 | web: 156 | dependency: transitive 157 | description: 158 | name: web 159 | sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152 160 | url: "https://pub.dev" 161 | source: hosted 162 | version: "0.3.0" 163 | sdks: 164 | dart: ">=3.2.0-194.0.dev <4.0.0" 165 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: flutter_conditional_rendering 2 | description: A flutter package which enhances conditional rendering, supports if-else and switch conditions. 3 | version: 2.1.0 4 | homepage: https://github.com/crizant/flutter_conditional_rendering 5 | 6 | environment: 7 | sdk: ">=2.12.0 <4.0.0" 8 | 9 | dependencies: 10 | flutter: 11 | sdk: flutter 12 | 13 | dev_dependencies: 14 | flutter_test: 15 | sdk: flutter 16 | 17 | # For information on the generic Dart part of this file, see the 18 | # following page: https://dart.dev/tools/pub/pubspec 19 | 20 | # The following section is specific to Flutter. 21 | flutter: 22 | 23 | # To add assets to your package, add an assets section, like this: 24 | # assets: 25 | # - images/a_dot_burr.jpeg 26 | # - images/a_dot_ham.jpeg 27 | # 28 | # For details regarding assets in packages, see 29 | # https://flutter.dev/assets-and-images/#from-packages 30 | # 31 | # An image asset can refer to one or more resolution-specific "variants", see 32 | # https://flutter.dev/assets-and-images/#resolution-aware. 33 | 34 | # To add custom fonts to your package, add a fonts section here, 35 | # in this "flutter" section. Each entry in this list should have a 36 | # "family" key with the font family name, and a "fonts" key with a 37 | # list giving the asset and other descriptors for the font. For 38 | # example: 39 | # fonts: 40 | # - family: Schyler 41 | # fonts: 42 | # - asset: fonts/Schyler-Regular.ttf 43 | # - asset: fonts/Schyler-Italic.ttf 44 | # style: italic 45 | # - family: Trajan Pro 46 | # fonts: 47 | # - asset: fonts/TrajanPro.ttf 48 | # - asset: fonts/TrajanPro_Bold.ttf 49 | # weight: 700 50 | # 51 | # For details regarding fonts in packages, see 52 | # https://flutter.dev/custom-fonts/#from-packages 53 | -------------------------------------------------------------------------------- /test/conditional_switch_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_test/flutter_test.dart'; 2 | import 'package:flutter/material.dart'; 3 | 4 | import 'package:flutter_conditional_rendering/flutter_conditional_rendering.dart'; 5 | 6 | void main() { 7 | testWidgets( 8 | 'Render widget by case "A" builder if `valueBuilder` returns "A"', 9 | (WidgetTester tester) async { 10 | final Widget aConditionWidget = Container(); 11 | final Widget fallbackWidget = Container(); 12 | await tester.pumpWidget( 13 | Builder( 14 | builder: (BuildContext context) { 15 | return ConditionalSwitch.single( 16 | context: context, 17 | valueBuilder: (_) => 'A', 18 | caseBuilders: {'A': (_) => aConditionWidget}, 19 | fallbackBuilder: (_) => fallbackWidget, 20 | ); 21 | }, 22 | ), 23 | ); 24 | 25 | expect(find.byWidget(aConditionWidget), findsOneWidget); 26 | expect(find.byWidget(fallbackWidget), findsNothing); 27 | }, 28 | ); 29 | 30 | testWidgets( 31 | 'Render widget by `fallbackBuilder` if `valueBuilder` returns `0`', 32 | (WidgetTester tester) async { 33 | final Widget aConditionWidget = Container(); 34 | final Widget fallbackWidget = Container(); 35 | await tester.pumpWidget( 36 | Builder( 37 | builder: (BuildContext context) { 38 | return ConditionalSwitch.single( 39 | context: context, 40 | valueBuilder: (_) => 0, 41 | caseBuilders: {'A': (_) => aConditionWidget}, 42 | fallbackBuilder: (_) => fallbackWidget, 43 | ); 44 | }, 45 | ), 46 | ); 47 | 48 | expect(find.byWidget(fallbackWidget), findsOneWidget); 49 | expect(find.byWidget(aConditionWidget), findsNothing); 50 | }, 51 | ); 52 | 53 | testWidgets( 54 | 'Render a `Container()` widget if `fallbackBuilder` is not provided and ' + 55 | '`valueBuilder` returns `0`', 56 | (WidgetTester tester) async { 57 | final Widget aConditionWidget = Container(); 58 | final Widget fallbackWidget = Container(); 59 | await tester.pumpWidget( 60 | Builder( 61 | builder: (BuildContext context) { 62 | return ConditionalSwitch.single( 63 | context: context, 64 | valueBuilder: (_) => 0, 65 | caseBuilders: {'A': (_) => aConditionWidget}, 66 | ); 67 | }, 68 | ), 69 | ); 70 | 71 | expect(find.byWidget(fallbackWidget), findsNothing); 72 | expect(find.byWidget(aConditionWidget), findsNothing); 73 | expect(find.byType(Container), findsOne); 74 | }, 75 | ); 76 | 77 | testWidgets( 78 | 'Render a list of widgets by case "A" builder if ' + 79 | '`valueBuilder` returns "A"', 80 | (WidgetTester tester) async { 81 | final List aConditionWidgetList = [Container()]; 82 | final List fallbackWidgetList = [Container()]; 83 | await tester.pumpWidget( 84 | Builder( 85 | builder: (BuildContext context) { 86 | return Column( 87 | children: ConditionalSwitch.list( 88 | context: context, 89 | valueBuilder: (_) => 'A', 90 | caseBuilders: {'A': (_) => aConditionWidgetList}, 91 | fallbackBuilder: (_) => fallbackWidgetList, 92 | ), 93 | ); 94 | }, 95 | ), 96 | ); 97 | 98 | for (Widget widget in aConditionWidgetList) { 99 | expect(find.byWidget(widget), findsOneWidget); 100 | } 101 | 102 | for (Widget widget in fallbackWidgetList) { 103 | expect(find.byWidget(widget), findsNothing); 104 | } 105 | }, 106 | ); 107 | 108 | testWidgets( 109 | 'Render a list of widgets by `fallbackBuilder` if ' + 110 | '`valueBuilder` returns `0`', 111 | (WidgetTester tester) async { 112 | final List aConditionWidgetList = [Container()]; 113 | final List fallbackWidgetList = [Container()]; 114 | await tester.pumpWidget( 115 | Builder( 116 | builder: (BuildContext context) { 117 | return Column( 118 | children: ConditionalSwitch.list( 119 | context: context, 120 | valueBuilder: (_) => 0, 121 | caseBuilders: {'A': (_) => aConditionWidgetList}, 122 | fallbackBuilder: (_) => fallbackWidgetList, 123 | ), 124 | ); 125 | }, 126 | ), 127 | ); 128 | 129 | for (Widget widget in fallbackWidgetList) { 130 | expect(find.byWidget(widget), findsOneWidget); 131 | } 132 | 133 | for (Widget widget in aConditionWidgetList) { 134 | expect(find.byWidget(widget), findsNothing); 135 | } 136 | }, 137 | ); 138 | 139 | testWidgets( 140 | 'Render an empty list if `fallbackBuilder` is not provided ' + 141 | 'and `valueBuilder` returns `0`', 142 | (WidgetTester tester) async { 143 | final List aConditionWidgetList = [Container()]; 144 | await tester.pumpWidget( 145 | Builder( 146 | builder: (BuildContext context) { 147 | return Column( 148 | children: ConditionalSwitch.list( 149 | context: context, 150 | valueBuilder: (_) => 0, 151 | caseBuilders: {'A': (_) => aConditionWidgetList}, 152 | ), 153 | ); 154 | }, 155 | ), 156 | ); 157 | 158 | for (Widget widget in aConditionWidgetList) { 159 | expect(find.byWidget(widget), findsNothing); 160 | } 161 | }, 162 | ); 163 | } 164 | -------------------------------------------------------------------------------- /test/conditional_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_test/flutter_test.dart'; 2 | import 'package:flutter/material.dart'; 3 | 4 | import 'package:flutter_conditional_rendering/flutter_conditional_rendering.dart'; 5 | 6 | void main() { 7 | testWidgets( 8 | 'Render widget by `widgetBuilder` if `conditionBuilder` returns `true`', 9 | (WidgetTester tester) async { 10 | final Widget trueWidget = Container(); 11 | final Widget falseWidget = Container(); 12 | await tester.pumpWidget( 13 | Builder( 14 | builder: (BuildContext context) { 15 | return Conditional.single( 16 | context: context, 17 | conditionBuilder: (_) => true, 18 | widgetBuilder: (_) => trueWidget, 19 | fallbackBuilder: (_) => falseWidget, 20 | ); 21 | }, 22 | ), 23 | ); 24 | 25 | expect(find.byWidget(trueWidget), findsOneWidget); 26 | expect(find.byWidget(falseWidget), findsNothing); 27 | }, 28 | ); 29 | 30 | testWidgets( 31 | 'Render widget by `fallbackBuilder` if `conditionBuilder` returns `false`', 32 | (WidgetTester tester) async { 33 | final Widget trueWidget = Container(); 34 | final Widget falseWidget = Container(); 35 | await tester.pumpWidget( 36 | Builder( 37 | builder: (BuildContext context) { 38 | return Conditional.single( 39 | context: context, 40 | conditionBuilder: (_) => false, 41 | widgetBuilder: (_) => trueWidget, 42 | fallbackBuilder: (_) => falseWidget, 43 | ); 44 | }, 45 | ), 46 | ); 47 | 48 | expect(find.byWidget(falseWidget), findsOneWidget); 49 | expect(find.byWidget(trueWidget), findsNothing); 50 | }, 51 | ); 52 | 53 | testWidgets( 54 | 'Render a `Container()` widget if `fallbackBuilder` is not provided and ' 55 | '`conditionBuilder` returns `false`', 56 | (WidgetTester tester) async { 57 | final Widget trueWidget = Container(); 58 | final Widget falseWidget = Container(); 59 | await tester.pumpWidget( 60 | Builder( 61 | builder: (BuildContext context) { 62 | return Conditional.single( 63 | context: context, 64 | conditionBuilder: (_) => false, 65 | widgetBuilder: (_) => trueWidget, 66 | ); 67 | }, 68 | ), 69 | ); 70 | 71 | expect(find.byWidget(falseWidget), findsNothing); 72 | expect(find.byWidget(trueWidget), findsNothing); 73 | expect(find.byType(Container), findsOne); 74 | }, 75 | ); 76 | 77 | testWidgets( 78 | 'Render a list of widgets by `widgetBuilder` if ' + 79 | '`conditionBuilder` returns `true`', 80 | (WidgetTester tester) async { 81 | final List trueWidgetList = [Container()]; 82 | final List falseWidgetList = [Container()]; 83 | await tester.pumpWidget( 84 | Builder( 85 | builder: (BuildContext context) { 86 | return Column( 87 | children: Conditional.list( 88 | context: context, 89 | conditionBuilder: (_) => true, 90 | widgetBuilder: (_) => trueWidgetList, 91 | fallbackBuilder: (_) => falseWidgetList, 92 | ), 93 | ); 94 | }, 95 | ), 96 | ); 97 | 98 | for (Widget widget in trueWidgetList) { 99 | expect(find.byWidget(widget), findsOneWidget); 100 | } 101 | 102 | for (Widget widget in falseWidgetList) { 103 | expect(find.byWidget(widget), findsNothing); 104 | } 105 | }, 106 | ); 107 | 108 | testWidgets( 109 | 'Render a list of widgets by `widgetBuilder` if ' + 110 | '`conditionBuilder` returns `false`', 111 | (WidgetTester tester) async { 112 | final List trueWidgetList = [Container()]; 113 | final List falseWidgetList = [Container()]; 114 | await tester.pumpWidget( 115 | Builder( 116 | builder: (BuildContext context) { 117 | return Column( 118 | children: Conditional.list( 119 | context: context, 120 | conditionBuilder: (_) => false, 121 | widgetBuilder: (_) => trueWidgetList, 122 | fallbackBuilder: (_) => falseWidgetList, 123 | ), 124 | ); 125 | }, 126 | ), 127 | ); 128 | 129 | for (Widget widget in falseWidgetList) { 130 | expect(find.byWidget(widget), findsOneWidget); 131 | } 132 | 133 | for (Widget widget in trueWidgetList) { 134 | expect(find.byWidget(widget), findsNothing); 135 | } 136 | }, 137 | ); 138 | 139 | testWidgets( 140 | 'Render an empty list if `fallbackBuilder` is not provided and ' + 141 | '`conditionBuilder` returns `false`', 142 | (WidgetTester tester) async { 143 | final List trueWidgetList = [Container()]; 144 | await tester.pumpWidget( 145 | Builder( 146 | builder: (BuildContext context) { 147 | return Column( 148 | children: Conditional.list( 149 | context: context, 150 | conditionBuilder: (_) => false, 151 | widgetBuilder: (_) => trueWidgetList, 152 | ), 153 | ); 154 | }, 155 | ), 156 | ); 157 | 158 | for (Widget widget in trueWidgetList) { 159 | expect(find.byWidget(widget), findsNothing); 160 | } 161 | }, 162 | ); 163 | } 164 | --------------------------------------------------------------------------------