├── .gitignore
├── .metadata
├── CHANGELOG.md
├── LICENSE
├── README.md
├── analysis_options.yaml
├── example
├── .gitignore
├── .metadata
├── README.md
├── SponsoredByMyTextAi.png
├── analysis_options.yaml
├── android
│ ├── .gitignore
│ ├── app
│ │ ├── build.gradle
│ │ └── src
│ │ │ ├── debug
│ │ │ └── AndroidManifest.xml
│ │ │ ├── main
│ │ │ ├── AndroidManifest.xml
│ │ │ ├── kotlin
│ │ │ │ └── dev
│ │ │ │ │ └── glasberg
│ │ │ │ │ └── example_xaxa
│ │ │ │ │ └── MainActivity.kt
│ │ │ └── res
│ │ │ │ ├── drawable-v21
│ │ │ │ └── launch_background.xml
│ │ │ │ ├── drawable
│ │ │ │ └── launch_background.xml
│ │ │ │ ├── mipmap-hdpi
│ │ │ │ └── ic_launcher.png
│ │ │ │ ├── mipmap-mdpi
│ │ │ │ └── ic_launcher.png
│ │ │ │ ├── mipmap-xhdpi
│ │ │ │ └── ic_launcher.png
│ │ │ │ ├── mipmap-xxhdpi
│ │ │ │ └── ic_launcher.png
│ │ │ │ ├── mipmap-xxxhdpi
│ │ │ │ └── ic_launcher.png
│ │ │ │ ├── values-night
│ │ │ │ └── styles.xml
│ │ │ │ └── values
│ │ │ │ └── styles.xml
│ │ │ └── profile
│ │ │ └── AndroidManifest.xml
│ ├── build.gradle
│ ├── gradle.properties
│ ├── gradle
│ │ └── wrapper
│ │ │ └── gradle-wrapper.properties
│ └── settings.gradle
├── lib
│ ├── images
│ │ ├── buttonBar.png
│ │ ├── columnSuper.png
│ │ ├── fitHorizontally.png
│ │ ├── non_uniform_borders.png
│ │ ├── rowSuperWithFitHorizontally.jpg
│ │ ├── rowXRowSuperComparison.png
│ │ ├── sideBySide.png
│ │ ├── sideBySideComparison.gif
│ │ ├── wrapFit1.png
│ │ ├── wrapFit2.png
│ │ ├── wrapFit3.png
│ │ ├── wrapFit4.png
│ │ └── wrapType.jpg
│ ├── main_box.dart
│ ├── main_button_and_circle_button.dart
│ ├── main_button_bar_super.dart
│ ├── main_capture_gestures.dart
│ ├── main_column_removing_zero_height.dart
│ ├── main_column_row_gestures.dart
│ ├── main_column_super.dart
│ ├── main_column_super_playground.dart
│ ├── main_decorated_box.dart
│ ├── main_delayed.dart
│ ├── main_detect_scroll.dart
│ ├── main_fit_horizontally.dart
│ ├── main_fit_horizontally_baseline.dart
│ ├── main_global_keys.dart
│ ├── main_non_uniform_outline_input_border.dart
│ ├── main_non_uniform_rounded_rectangle_border.dart
│ ├── main_normalized_overflow_box.dart
│ ├── main_row_spacer.dart
│ ├── main_row_super.dart
│ ├── main_row_super_alignment.dart
│ ├── main_row_super_fill.dart
│ ├── main_row_super_playground.dart
│ ├── main_row_super_with_fit_horizontally.dart
│ ├── main_row_with_row_super_comparison.dart
│ ├── main_show_dialog_super.dart
│ ├── main_side_by_side.dart
│ ├── main_side_by_side_comparison.dart
│ ├── main_text_one_line.dart
│ ├── main_timer_builder.dart
│ ├── main_wrap_super.dart
│ └── main_wrap_super_fit.dart
└── pubspec.yaml
├── lib
├── assorted_layout_widgets.dart
└── src
│ ├── box.dart
│ ├── box_animating_width.dart
│ ├── button.dart
│ ├── button_bar_super.dart
│ ├── capture_gestures.dart
│ ├── circle_button.dart
│ ├── column_super.dart
│ ├── delayed.dart
│ ├── detect_scroll.dart
│ ├── fit_horizontally.dart
│ ├── global_keys.dart
│ ├── keyboard_dismiss.dart
│ ├── mask_function_text_input_formatter.dart
│ ├── minimum_raggedness.dart
│ ├── non_uniform_outline_input_border.dart
│ ├── non_uniform_rounded_rectangle_border.dart
│ ├── normalized_overflow_box.dart
│ ├── pad.dart
│ ├── row_super.dart
│ ├── scroll_shadow.dart
│ ├── show_dialog_super.dart
│ ├── side_by_side.dart
│ ├── text_one_line.dart
│ ├── time_builder.dart
│ └── wrap_super.dart
├── pubspec.yaml
└── test
└── src
├── global_keys_test.dart
└── minimum_raggedness_test.dart
/.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 | **/.flutter-plugins-dependencies
25 | **/flutter_export_environment.sh
26 | **/doc/api/
27 | .dart_tool/
28 | .flutter-plugins
29 | .packages
30 | .pub-cache/
31 | .pub/
32 | /build/
33 | build/
34 | ios/.generated/
35 | ios/Flutter/Generated.xcconfig
36 | ios/Runner/GeneratedPluginRegistrant.*
37 | pubspec.lock
38 | *.lock
39 | .flutter-plugins-dependencies
40 |
41 | # Android related
42 | **/android/**/gradle-wrapper.jar
43 | **/android/.gradle
44 | **/android/captures/
45 | **/android/gradlew
46 | **/android/gradlew.bat
47 | **/android/local.properties
48 | **/android/**/GeneratedPluginRegistrant.java
49 |
50 | # iOS/XCode related
51 | **/ios/**/*.mode1v3
52 | **/ios/**/*.mode2v3
53 | **/ios/**/*.moved-aside
54 | **/ios/**/*.pbxuser
55 | **/ios/**/*.perspectivev3
56 | **/ios/**/*sync/
57 | **/ios/**/.sconsign.dblite
58 | **/ios/**/.tags*
59 | **/ios/**/.vagrant/
60 | **/ios/**/DerivedData/
61 | **/ios/**/Icon?
62 | **/ios/**/Pods/
63 | **/ios/**/.symlinks/
64 | **/ios/**/profile
65 | **/ios/**/xcuserdata
66 | **/ios/.generated/
67 | **/ios/Flutter/App.framework
68 | **/ios/Flutter/Flutter.framework
69 | **/ios/Flutter/Generated.xcconfig
70 | **/ios/Flutter/app.flx
71 | **/ios/Flutter/app.zip
72 | **/ios/Flutter/flutter_assets/
73 | **/ios/Flutter/flutter_export_environment.sh
74 | **/ios/ServiceDefinitions.json
75 | **/ios/Runner/GeneratedPluginRegistrant.*
76 |
77 | # Exceptions to above rules.
78 | !**/ios/**/default.mode1v3
79 | !**/ios/**/default.mode2v3
80 | !**/ios/**/default.pbxuser
81 | !**/ios/**/default.perspectivev3
82 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
83 | /example/pubspec.lock
84 | /pubspec.lock
85 |
--------------------------------------------------------------------------------
/.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: 68587a0916366e9512a78df22c44163d041dd5f3
8 | channel: stable
9 |
10 | project_type: package
11 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright 2019 by Marcelo Glasberg
2 |
3 | Redistribution and use in source and binary forms, with or without modification, are permitted
4 | provided that the following conditions are met:
5 |
6 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions
7 | and the following disclaimer.
8 |
9 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of
10 | conditions and the following disclaimer in the documentation and/or other materials provided
11 | with the distribution.
12 |
13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
14 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
15 | AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
16 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
17 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
18 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
19 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
20 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
21 |
--------------------------------------------------------------------------------
/example/.gitignore:
--------------------------------------------------------------------------------
1 | # Miscellaneous
2 | *.class
3 | *.log
4 | *.pyc
5 | *.swp
6 | .DS_Store
7 | .atom/
8 | .buildlog/
9 | .history
10 | .svn/
11 | migrate_working_dir/
12 |
13 | # IntelliJ related
14 | *.iml
15 | *.ipr
16 | *.iws
17 | .idea/
18 |
19 | # The .vscode folder contains launch configuration and tasks you configure in
20 | # VS Code which you may wish to be included in version control, so this line
21 | # is commented out by default.
22 | #.vscode/
23 |
24 | # Flutter/Dart/Pub related
25 | **/doc/api/
26 | **/ios/Flutter/.last_build_id
27 | .dart_tool/
28 | .flutter-plugins
29 | .flutter-plugins-dependencies
30 | .pub-cache/
31 | .pub/
32 | /build/
33 |
34 | # Symbolication related
35 | app.*.symbols
36 |
37 | # Obfuscation related
38 | app.*.map.json
39 |
40 | # Android Studio will place build artifacts here
41 | /android/app/debug
42 | /android/app/profile
43 | /android/app/release
44 |
--------------------------------------------------------------------------------
/example/.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: "dec2ee5c1f98f8e84a7d5380c05eb8a3d0a81668"
8 | channel: "stable"
9 |
10 | project_type: app
11 |
12 | # Tracks metadata for the flutter migrate command
13 | migration:
14 | platforms:
15 | - platform: root
16 | create_revision: dec2ee5c1f98f8e84a7d5380c05eb8a3d0a81668
17 | base_revision: dec2ee5c1f98f8e84a7d5380c05eb8a3d0a81668
18 | - platform: android
19 | create_revision: dec2ee5c1f98f8e84a7d5380c05eb8a3d0a81668
20 | base_revision: dec2ee5c1f98f8e84a7d5380c05eb8a3d0a81668
21 |
22 | # User provided section
23 |
24 | # List of Local paths (relative to this file) that should be
25 | # ignored by the migrate tool.
26 | #
27 | # Files that are not part of the templates will be ignored by default.
28 | unmanaged_files:
29 | - 'lib/main.dart'
30 | - 'ios/Runner.xcodeproj/project.pbxproj'
31 |
--------------------------------------------------------------------------------
/example/README.md:
--------------------------------------------------------------------------------
1 | # Examples
2 |
3 | 1. ColumnSuper Example
4 |
5 | 2. RowSuper Example
6 |
7 | 3. RowSuper Fill Example
8 |
9 | 4. ColumnSuper Playground
10 |
11 | 5. RowSuper Playground
12 |
13 | 6. RowSuper with RowSpacer Example
14 |
15 | 7. RowSuper with FitHorizontally Example
16 |
17 | 8. FitHorizontally Example
18 |
19 | 9. Box Example
20 |
21 | 10. WrapSuper Example
22 |
23 | 11. WrapSuper WrapFit Example
24 |
25 | 12. ButtonBarSuper Example
26 |
27 | 13. NormalizedOverflowBox Example
28 |
29 | 14. TimeBuilder Example
30 |
31 | 15. SideBySide Example
32 |
33 | 16. SideBySide vs. Row vs. RowSuper
34 |
35 | 17. Button and CircleButton Example Example
36 |
37 | 18. CaptureGesture Example
38 |
39 | 19. NonUniformOutlineInputBorder Example
40 |
41 | 20. NonUniformRoundedRectangleBorder Example
42 |
--------------------------------------------------------------------------------
/example/SponsoredByMyTextAi.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcglasberg/assorted_layout_widgets/d07de6a67b54d534612329896e78e3e7941fff32/example/SponsoredByMyTextAi.png
--------------------------------------------------------------------------------
/example/analysis_options.yaml:
--------------------------------------------------------------------------------
1 | analyzer:
2 | errors:
3 | # treat missing required parameters as a warning (not a hint)
4 | missing_required_param: warning
5 | # treat missing returns as a warning (not a hint)
6 | missing_return: error
7 | # allow having TODOs in the code
8 | todo: ignore
9 | exclude:
10 | - 'bin/cache/**'
11 | - 'lib/src/http/**'
12 |
13 | # https://github.com/dart-lang/linter/blob/master/example/all.yaml
14 | linter:
15 | rules:
16 | - always_declare_return_types
17 | - annotate_overrides
18 | - avoid_empty_else
19 | - avoid_field_initializers_in_const_classes
20 | # - avoid_function_literals_in_foreach_calls
21 | - avoid_init_to_null
22 | - avoid_null_checks_in_equality_operators
23 | - avoid_relative_lib_imports
24 | - avoid_renaming_method_parameters
25 | - avoid_return_types_on_setters
26 | - avoid_slow_async_io
27 | - await_only_futures
28 | # - camel_case_types
29 | - cancel_subscriptions
30 | - control_flow_in_finally
31 | - directives_ordering
32 | - empty_catches
33 | - empty_constructor_bodies
34 | - empty_statements
35 | - hash_and_equals
36 | - implementation_imports
37 | - collection_methods_unrelated_type
38 | - library_names
39 | - library_prefixes
40 | - no_duplicate_case_values
41 | - overridden_fields
42 | - package_names
43 | - package_prefixed_library_names
44 | - prefer_adjacent_string_concatenation
45 | - prefer_asserts_in_initializer_lists
46 | - prefer_collection_literals
47 | - prefer_conditional_assignment
48 | - prefer_const_constructors
49 | # - prefer_const_constructors_in_immutables
50 | - prefer_const_declarations
51 | - prefer_contains
52 | - prefer_final_fields
53 | # - prefer_foreach
54 | - prefer_generic_function_type_aliases
55 | - prefer_initializing_formals
56 | - prefer_is_empty
57 | - prefer_is_not_empty
58 | - prefer_typing_uninitialized_variables
59 | - recursive_getters
60 | - slash_for_doc_comments
61 | - sort_unnamed_constructors_first
62 | - test_types_in_equals
63 | - throw_in_finally
64 | - type_init_formals
65 | - unnecessary_brace_in_string_interps
66 | - unnecessary_getters_setters
67 | - unnecessary_null_aware_assignments
68 | - unnecessary_null_in_if_null_operators
69 | - unnecessary_overrides
70 | - unnecessary_this
71 | - unrelated_type_equality_checks
72 | - use_rethrow_when_possible
73 | - valid_regexps
74 | # - unnecessary_new
75 | # - unnecessary_const
76 | # - non_constant_identifier_names
77 | # - always_put_control_body_on_new_line
78 | # - always_put_required_named_parameters_first # we prefer having parameters in the same order as fields https://github.com/flutter/flutter/issues/10219
79 | # - always_specify_types
80 | # - avoid_annotating_with_dynamic # conflicts with always_specify_types
81 | # - avoid_as
82 | # - avoid_bool_literals_in_conditional_expressions # not yet tested
83 | # - avoid_catches_without_on_clauses # we do this commonly
84 | # - avoid_catching_errors # we do this commonly
85 | # - avoid_classes_with_only_static_members
86 | # - avoid_double_and_int_checks # only useful when targeting JS runtime
87 | # - avoid_js_rounded_ints # only useful when targeting JS runtime
88 | # - avoid_positional_boolean_parameters # not yet tested
89 | # - avoid_private_typedef_functions # we prefer having typedef (discussion in https://github.com/flutter/flutter/pull/16356)
90 | # - avoid_returning_null # we do this commonly
91 | # - avoid_returning_this # https://github.com/dart-lang/linter/issues/842
92 | # - avoid_setters_without_getters # not yet tested
93 | # - avoid_single_cascade_in_expression_statements # not yet tested
94 | # - avoid_types_as_parameter_names # https://github.com/dart-lang/linter/pull/954/files
95 | # - avoid_types_on_closure_parameters # conflicts with always_specify_types
96 | # - avoid_unused_constructor_parameters # https://github.com/dart-lang/linter/pull/847
97 | # - cascade_invocations # not yet tested
98 | # - close_sinks # https://github.com/flutter/flutter/issues/5789
99 | # - comment_references # blocked on https://github.com/dart-lang/dartdoc/issues/1153
100 | # - constant_identifier_names # https://github.com/dart-lang/linter/issues/204
101 | # - invariant_booleans # https://github.com/flutter/flutter/issues/5790
102 | # - join_return_with_assignment # not yet tested
103 | # - literal_only_boolean_expressions # https://github.com/flutter/flutter/issues/5791
104 | # - no_adjacent_strings_in_list
105 | # - omit_local_variable_types # opposite of always_specify_types
106 | # - one_member_abstracts # too many false positives
107 | # - only_throw_errors # https://github.com/flutter/flutter/issues/5792
108 | # - parameter_assignments # we do this commonly
109 | # - prefer_const_literals_to_create_immutables
110 | # - prefer_constructors_over_static_methods # not yet tested
111 | # - prefer_expression_function_bodies # conflicts with https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo#consider-using--for-short-functions-and-methods
112 | # - prefer_final_locals
113 | # - prefer_function_declarations_over_variables # not yet tested
114 | # - prefer_interpolation_to_compose_strings # not yet tested
115 | # - prefer_iterable_whereType # https://github.com/dart-lang/sdk/issues/32463
116 | # - prefer_single_quotes
117 | # - sort_constructors_first
118 | # - type_annotate_public_apis # subset of always_specify_types
119 | # - unawaited_futures # https://github.com/flutter/flutter/issues/5793
120 | # - unnecessary_lambdas # https://github.com/dart-lang/linter/issues/498
121 | # - unnecessary_parenthesis
122 | # - unnecessary_statements # not yet tested
123 | # - use_setters_to_change_properties # not yet tested
124 | # - use_string_buffers # https://github.com/dart-lang/linter/pull/664
125 | # - use_to_and_as_if_applicable # has false positives, so we prefer to catch this by code-review
126 | # - void_checks # not yet tested
127 |
--------------------------------------------------------------------------------
/example/android/.gitignore:
--------------------------------------------------------------------------------
1 | gradle-wrapper.jar
2 | /.gradle
3 | /captures/
4 | /gradlew
5 | /gradlew.bat
6 | /local.properties
7 | GeneratedPluginRegistrant.java
8 |
9 | # Remember to never publicly share your keystore.
10 | # See https://flutter.dev/to/reference-keystore
11 | key.properties
12 | **/*.keystore
13 | **/*.jks
14 |
--------------------------------------------------------------------------------
/example/android/app/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id "com.android.application"
3 | id "kotlin-android"
4 | // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
5 | id "dev.flutter.flutter-gradle-plugin"
6 | }
7 |
8 | android {
9 | namespace = "dev.glasberg.example"
10 | compileSdk = flutter.compileSdkVersion
11 | ndkVersion = flutter.ndkVersion
12 |
13 | compileOptions {
14 | sourceCompatibility = JavaVersion.VERSION_1_8
15 | targetCompatibility = JavaVersion.VERSION_1_8
16 | }
17 |
18 | kotlinOptions {
19 | jvmTarget = JavaVersion.VERSION_1_8
20 | }
21 |
22 | defaultConfig {
23 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
24 | applicationId = "dev.glasberg.example"
25 | // You can update the following values to match your application needs.
26 | // For more information, see: https://flutter.dev/to/review-gradle-config.
27 | minSdk = flutter.minSdkVersion
28 | targetSdk = flutter.targetSdkVersion
29 | versionCode = flutter.versionCode
30 | versionName = flutter.versionName
31 | }
32 |
33 | buildTypes {
34 | release {
35 | // TODO: Add your own signing config for the release build.
36 | // Signing with the debug keys for now, so `flutter run --release` works.
37 | signingConfig = signingConfigs.debug
38 | }
39 | }
40 | }
41 |
42 | flutter {
43 | source = "../.."
44 | }
45 |
--------------------------------------------------------------------------------
/example/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/example/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
15 |
19 |
23 |
24 |
25 |
26 |
27 |
28 |
30 |
33 |
34 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/example/android/app/src/main/kotlin/dev/glasberg/example_xaxa/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package dev.glasberg.example
2 |
3 | import io.flutter.embedding.android.FlutterActivity
4 |
5 | class MainActivity: FlutterActivity()
6 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/drawable-v21/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/drawable/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcglasberg/assorted_layout_widgets/d07de6a67b54d534612329896e78e3e7941fff32/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcglasberg/assorted_layout_widgets/d07de6a67b54d534612329896e78e3e7941fff32/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcglasberg/assorted_layout_widgets/d07de6a67b54d534612329896e78e3e7941fff32/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcglasberg/assorted_layout_widgets/d07de6a67b54d534612329896e78e3e7941fff32/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcglasberg/assorted_layout_widgets/d07de6a67b54d534612329896e78e3e7941fff32/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/values-night/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/example/android/app/src/profile/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/example/android/build.gradle:
--------------------------------------------------------------------------------
1 | allprojects {
2 | repositories {
3 | google()
4 | mavenCentral()
5 | }
6 | }
7 |
8 | rootProject.buildDir = "../build"
9 | subprojects {
10 | project.buildDir = "${rootProject.buildDir}/${project.name}"
11 | }
12 | subprojects {
13 | project.evaluationDependsOn(":app")
14 | }
15 |
16 | tasks.register("clean", Delete) {
17 | delete rootProject.buildDir
18 | }
19 |
--------------------------------------------------------------------------------
/example/android/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx4G -XX:MaxMetaspaceSize=2G -XX:+HeapDumpOnOutOfMemoryError
2 | android.useAndroidX=true
3 | android.enableJetifier=true
4 |
--------------------------------------------------------------------------------
/example/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | zipStoreBase=GRADLE_USER_HOME
4 | zipStorePath=wrapper/dists
5 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-all.zip
6 |
--------------------------------------------------------------------------------
/example/android/settings.gradle:
--------------------------------------------------------------------------------
1 | pluginManagement {
2 | def flutterSdkPath = {
3 | def properties = new Properties()
4 | file("local.properties").withInputStream { properties.load(it) }
5 | def flutterSdkPath = properties.getProperty("flutter.sdk")
6 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
7 | return flutterSdkPath
8 | }()
9 |
10 | includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
11 |
12 | repositories {
13 | google()
14 | mavenCentral()
15 | gradlePluginPortal()
16 | }
17 | }
18 |
19 | plugins {
20 | id "dev.flutter.flutter-plugin-loader" version "1.0.0"
21 | id "com.android.application" version "8.1.0" apply false
22 | id "org.jetbrains.kotlin.android" version "1.8.22" apply false
23 | }
24 |
25 | include ":app"
26 |
--------------------------------------------------------------------------------
/example/lib/images/buttonBar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcglasberg/assorted_layout_widgets/d07de6a67b54d534612329896e78e3e7941fff32/example/lib/images/buttonBar.png
--------------------------------------------------------------------------------
/example/lib/images/columnSuper.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcglasberg/assorted_layout_widgets/d07de6a67b54d534612329896e78e3e7941fff32/example/lib/images/columnSuper.png
--------------------------------------------------------------------------------
/example/lib/images/fitHorizontally.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcglasberg/assorted_layout_widgets/d07de6a67b54d534612329896e78e3e7941fff32/example/lib/images/fitHorizontally.png
--------------------------------------------------------------------------------
/example/lib/images/non_uniform_borders.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcglasberg/assorted_layout_widgets/d07de6a67b54d534612329896e78e3e7941fff32/example/lib/images/non_uniform_borders.png
--------------------------------------------------------------------------------
/example/lib/images/rowSuperWithFitHorizontally.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcglasberg/assorted_layout_widgets/d07de6a67b54d534612329896e78e3e7941fff32/example/lib/images/rowSuperWithFitHorizontally.jpg
--------------------------------------------------------------------------------
/example/lib/images/rowXRowSuperComparison.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcglasberg/assorted_layout_widgets/d07de6a67b54d534612329896e78e3e7941fff32/example/lib/images/rowXRowSuperComparison.png
--------------------------------------------------------------------------------
/example/lib/images/sideBySide.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcglasberg/assorted_layout_widgets/d07de6a67b54d534612329896e78e3e7941fff32/example/lib/images/sideBySide.png
--------------------------------------------------------------------------------
/example/lib/images/sideBySideComparison.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcglasberg/assorted_layout_widgets/d07de6a67b54d534612329896e78e3e7941fff32/example/lib/images/sideBySideComparison.gif
--------------------------------------------------------------------------------
/example/lib/images/wrapFit1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcglasberg/assorted_layout_widgets/d07de6a67b54d534612329896e78e3e7941fff32/example/lib/images/wrapFit1.png
--------------------------------------------------------------------------------
/example/lib/images/wrapFit2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcglasberg/assorted_layout_widgets/d07de6a67b54d534612329896e78e3e7941fff32/example/lib/images/wrapFit2.png
--------------------------------------------------------------------------------
/example/lib/images/wrapFit3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcglasberg/assorted_layout_widgets/d07de6a67b54d534612329896e78e3e7941fff32/example/lib/images/wrapFit3.png
--------------------------------------------------------------------------------
/example/lib/images/wrapFit4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcglasberg/assorted_layout_widgets/d07de6a67b54d534612329896e78e3e7941fff32/example/lib/images/wrapFit4.png
--------------------------------------------------------------------------------
/example/lib/images/wrapType.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcglasberg/assorted_layout_widgets/d07de6a67b54d534612329896e78e3e7941fff32/example/lib/images/wrapType.jpg
--------------------------------------------------------------------------------
/example/lib/main_box.dart:
--------------------------------------------------------------------------------
1 | // ignore_for_file: deprecated_member_use
2 | import 'package:assorted_layout_widgets/assorted_layout_widgets.dart';
3 | import 'package:flutter/material.dart';
4 |
5 | void main() => runApp(const MaterialApp(home: Demo()));
6 |
7 | class Demo extends StatelessWidget {
8 | const Demo({ super.key });
9 |
10 | @override
11 | Widget build(BuildContext context) {
12 | //
13 | return Scaffold(
14 | appBar: AppBar(title: const Text('Box Example')),
15 | body: SingleChildScrollView(
16 | child: Center(
17 | child: Column(
18 | children: [
19 | example1(),
20 | example2(),
21 | example3(),
22 | example4(),
23 | example5(),
24 | example6(),
25 | example7(),
26 | example8(),
27 | example9(),
28 | example10(),
29 | example11(),
30 | example12(),
31 | example13(),
32 | example14(),
33 | example15(),
34 | example16(),
35 | example17(),
36 | example18(),
37 | ],
38 | ),
39 | ),
40 | ),
41 | );
42 | }
43 |
44 | Widget example1() => const Box(
45 | color: Colors.purple,
46 | child: Text("Test 1"),
47 | );
48 |
49 | Widget example2() => const Box.r(
50 | child: Text("Test 2"),
51 | );
52 |
53 | // This is hidden because of show: false.
54 | Widget example3() => const Box.g(
55 | show: false,
56 | padding: Pad(top: 20),
57 | child: Text("Test 3"),
58 | );
59 |
60 | Widget example4() => const Box.b(
61 | padding: Pad(top: 10, bottom: 10),
62 | child: Text("Test 4"),
63 | );
64 |
65 | // This is hidden because child is null. Padding is applied.
66 | Widget example5() => const Box.y(
67 | color: Colors.purple,
68 | padding: Pad(top: 20),
69 | );
70 |
71 | // This is the same as top:10, bottom:10.
72 | Widget example6() => const Box.r(
73 | padding: Pad(vertical: 10),
74 | child: Text("Test 6"),
75 | );
76 |
77 | // This is the same as right:10, left:10.
78 | Widget example7() => const Box.g(
79 | padding: Pad(horizontal: 10),
80 | child: Text("Test 7"),
81 | );
82 |
83 | Widget example8() => const Box.b(
84 | width: 200,
85 | height: 100,
86 | child: Text("Test 8"),
87 | );
88 |
89 | Widget example9() => const Box.y(
90 | padding: Pad(vertical: 20, horizontal: 40),
91 | width: 200,
92 | height: 100,
93 | child: Text("Test 9"),
94 | );
95 |
96 | // This will change color in each rebuild.
97 | Widget example10() => const Box.rand(
98 | padding: Pad(vertical: 20, horizontal: 40),
99 | child: Text("Test 10"),
100 | );
101 |
102 | Box redBox(String text) => Box(
103 | color: Colors.red,
104 | padding: const Pad(vertical: 5, horizontal: 5),
105 | width: 280,
106 | height: 35,
107 | child: Text(text),
108 | );
109 |
110 | Widget example11() => Padding(
111 | padding: const Pad(all: 2.0),
112 | child: redBox('box'),
113 | );
114 |
115 | Widget example12() => Padding(
116 | padding: const Pad(all: 2.0),
117 | child: redBox('box + Colors.blue') + Colors.blue,
118 | );
119 |
120 | Widget example13() => Padding(
121 | padding: const Pad(all: 2.0),
122 | child: redBox('box + Pad(left: 10)') + const Pad(left: 10),
123 | );
124 |
125 | Widget example14() => Padding(
126 | padding: const Pad(all: 2.0),
127 | child: redBox('box + Alignment.bottomRight') + Alignment.bottomRight,
128 | );
129 |
130 | Widget example15() => Padding(
131 | padding: const Pad(all: 2.0),
132 | child: const Box.b(padding: Pad(all: 8.0)) + redBox('Box.b(padding: Pad(all: 8.0)) + box'),
133 | );
134 |
135 | // Must remove padding when has no child. But has child, so don't remove padding.
136 | Widget example16() => const Box(
137 | color: Colors.red,
138 | padding: Pad(all: 20.0),
139 | removePaddingWhenNoChild: true,
140 | child: Text('Has padding'),
141 | );
142 |
143 | // Not visible:
144 | // Must remove padding when has no child. Has child, so removes padding.
145 | Widget example17() => const Box(
146 | color: Colors.green,
147 | padding: Pad(all: 20.0),
148 | removePaddingWhenNoChild: true,
149 | );
150 |
151 | // Must NOT remove padding when has no child. Has no child, but don't remove padding.
152 | Widget example18() => const Box(
153 | color: Colors.green,
154 | padding: Pad(all: 20.0),
155 | removePaddingWhenNoChild: false,
156 | );
157 | }
158 |
--------------------------------------------------------------------------------
/example/lib/main_button_and_circle_button.dart:
--------------------------------------------------------------------------------
1 | import 'package:assorted_layout_widgets/assorted_layout_widgets.dart';
2 | import 'package:flutter/material.dart';
3 |
4 | void main() => runApp(const MaterialApp(home: Demo()));
5 |
6 | class Demo extends StatelessWidget {
7 | const Demo({super.key});
8 |
9 | @override
10 | Widget build(BuildContext context) {
11 | //
12 | return Scaffold(
13 | appBar: AppBar(title: const Text('Button and CircleButton Example')),
14 | body: SingleChildScrollView(
15 | child: Center(
16 | child: Column(
17 | children: [
18 | _button(),
19 | const Box(height: 16),
20 | _circleButton(),
21 | const Box(height: 16),
22 | ],
23 | ),
24 | ),
25 | ),
26 | );
27 | }
28 |
29 | Box _button() {
30 | return Box(
31 | padding: const EdgeInsets.all(16.0),
32 | color: Colors.indigo,
33 | child: Column(
34 | children: [
35 | const Text('Button',
36 | style: TextStyle(
37 | fontSize: 20, fontWeight: FontWeight.bold, color: Colors.white)),
38 | const Box(height: 20),
39 | Row(
40 | children: [
41 | Expanded(
42 | child: Center(
43 | child: Button(
44 | builder: ({required bool isPressed}) {
45 | return Box(
46 | padding: const Pad(all: 8.0),
47 | color: isPressed ? Colors.blue : Colors.transparent,
48 | child: Text(
49 | 'Click Me',
50 | style: TextStyle(
51 | fontSize: 23,
52 | color: isPressed ? Colors.black : Colors.white),
53 | ),
54 | );
55 | },
56 | minVisualTapDuration: const Duration(milliseconds: 500),
57 | clickAreaMargin: const Pad(horizontal: 10.0, vertical: 45),
58 | onTap: () {},
59 | ),
60 | ),
61 | ),
62 | Expanded(
63 | child: Center(
64 | child: Button(
65 | builder: ({required bool isPressed}) {
66 | return Box(
67 | padding: const Pad(all: 8.0),
68 | color: isPressed ? Colors.blue : Colors.transparent,
69 | child: Text(
70 | 'Click Me',
71 | style: TextStyle(
72 | fontSize: 23,
73 | color: isPressed ? Colors.black : Colors.white),
74 | ),
75 | );
76 | },
77 | minVisualTapDuration: const Duration(milliseconds: 500),
78 | clickAreaMargin: const Pad(horizontal: 10.0, vertical: 45),
79 | debugShowClickableArea: true,
80 | onTap: () {},
81 | ),
82 | ),
83 | ),
84 | ],
85 | ),
86 | const Box(height: 20),
87 | const Text(
88 | 'Button(\n'
89 | ' builder: ({required bool isPressed}) => ...\n'
90 | ' minVisualTapDuration: Duration(milliseconds: 500),\n'
91 | ' clickAreaMargin: Pad(horizontal: 10.0, vertical: 45),\n'
92 | ' debugShowClickableArea: false / true',
93 | style: TextStyle(color: Colors.white),
94 | ),
95 | ],
96 | ),
97 | );
98 | }
99 |
100 | Box _circleButton() {
101 | return Box(
102 | padding: const EdgeInsets.all(16.0),
103 | color: Colors.indigo,
104 | child: Column(
105 | children: [
106 | const Text('CircleButton',
107 | style: TextStyle(
108 | fontSize: 20, fontWeight: FontWeight.bold, color: Colors.white)),
109 | const Box(height: 20),
110 | Row(
111 | children: [
112 | Expanded(
113 | child: Center(
114 | child: CircleButton(
115 | icon: const Icon(Icons.shopping_cart, color: Colors.white),
116 | clickAreaMargin: const Pad(left: 30, right: 50, vertical: 20),
117 | backgroundColor: Colors.white30,
118 | tapColor: Colors.black,
119 | border: Border.all(width: 1, color: Colors.black),
120 | size: 56,
121 | onTap: () {},
122 | builder: ({
123 | required bool isHover,
124 | required bool isPressed,
125 | required Widget child,
126 | }) =>
127 | AnimatedScale(
128 | scale: isPressed ? 1.15 : 1,
129 | duration: const Duration(milliseconds: 50),
130 | child: child,
131 | ),
132 | ),
133 | ),
134 | ),
135 | Expanded(
136 | child: Center(
137 | child: CircleButton(
138 | icon: const Icon(Icons.shopping_cart, color: Colors.white),
139 | clickAreaMargin: const Pad(left: 50, right: 30, vertical: 20),
140 | debugShowClickableArea: true,
141 | backgroundColor: Colors.white30,
142 | tapColor: Colors.black,
143 | border: Border.all(width: 1, color: Colors.black),
144 | size: 56,
145 | onTap: () {},
146 | builder: ({
147 | required bool isHover,
148 | required bool isPressed,
149 | required Widget child,
150 | }) =>
151 | AnimatedScale(
152 | scale: isPressed ? 0.85 : 1,
153 | duration: const Duration(milliseconds: 50),
154 | child: child,
155 | ),
156 | ),
157 | ),
158 | ),
159 | ],
160 | ),
161 | const Box(height: 20),
162 | const Text(
163 | 'CircleButton(\n'
164 | ' icon: Icon(Icons.shopping_cart, color: Colors.white),\n'
165 | ' backgroundColor: Colors.white30,\n'
166 | ' tapColor: Colors.black,\n'
167 | ' border: Border.all(width: 1, color: Colors.black),\n'
168 | ' size: 56,\n'
169 | ' onTap: () {},\n'
170 | ' builder: ({isPressed, ...} => AnimatedScale(...),\n'
171 | ' clickAreaMargin: Pad(left: 50, right: 30, vertical: 20),\n'
172 | ' debugShowClickableArea: false / true',
173 | style: TextStyle(color: Colors.white),
174 | ),
175 | ],
176 | ),
177 | );
178 | }
179 | }
180 |
--------------------------------------------------------------------------------
/example/lib/main_button_bar_super.dart:
--------------------------------------------------------------------------------
1 | import 'package:assorted_layout_widgets/assorted_layout_widgets.dart';
2 | import 'package:flutter/material.dart';
3 |
4 | void main() => runApp(const MaterialApp(home: Demo()));
5 |
6 | class Demo extends StatelessWidget {
7 | const Demo({ super.key });
8 |
9 | @override
10 | Widget build(BuildContext context) => Scaffold(
11 | appBar: AppBar(title: const Text('ButtonBarSuper Example')),
12 | body: Container(
13 | color: Colors.grey,
14 | alignment: Alignment.center,
15 | child: SingleChildScrollView(
16 | child: Column(
17 | children: [
18 | _example(WrapType.fit, WrapFit.min),
19 | _example(WrapType.fit, WrapFit.proportional),
20 | _example(WrapType.fit, WrapFit.divided),
21 | _example(WrapType.fit, WrapFit.larger),
22 | _example(WrapType.balanced, WrapFit.min),
23 | _example(WrapType.balanced, WrapFit.proportional),
24 | _example(WrapType.balanced, WrapFit.divided),
25 | _example(WrapType.balanced, WrapFit.larger),
26 | const Box(height: 20),
27 | ],
28 | ),
29 | ),
30 | ),
31 | );
32 |
33 | Column _example(WrapType wrapType, WrapFit wrapFit) {
34 | return Column(
35 | children: [
36 | const Box(height: 22),
37 | Text('$wrapType | $wrapFit'),
38 | const Box(height: 5),
39 | Container(
40 | width: 300,
41 | color: Colors.grey[300],
42 | child: _bar(wrapType, wrapFit),
43 | ),
44 | ],
45 | );
46 | }
47 |
48 | ButtonBarSuper _bar(WrapType wrapType, WrapFit wrapFit) {
49 | return ButtonBarSuper(
50 | buttonTextTheme: ButtonTextTheme.primary,
51 | wrapType: wrapType,
52 | wrapFit: wrapFit,
53 | spacing: 2.0,
54 | lineSpacing: 10.0,
55 | buttonHeight: 48,
56 | buttonMinWidth: 40,
57 | children: [
58 | ElevatedButton(
59 | style: ElevatedButton.styleFrom(backgroundColor: Colors.blue),
60 | onPressed: () {},
61 | child: const Text('I am a blue button like you')),
62 | ElevatedButton(
63 | style: ElevatedButton.styleFrom(backgroundColor: Colors.blue),
64 | onPressed: () {},
65 | child: const Text('Hey'),
66 | ),
67 | ElevatedButton(
68 | style: ElevatedButton.styleFrom(backgroundColor: Colors.blue),
69 | onPressed: () {},
70 | child: const Text('I am a blue button, ok?'),
71 | ),
72 | ],
73 | );
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/example/lib/main_capture_gestures.dart:
--------------------------------------------------------------------------------
1 | import 'package:assorted_layout_widgets/assorted_layout_widgets.dart';
2 | import 'package:flutter/material.dart';
3 |
4 | void main() => runApp(const MaterialApp(home: Demo()));
5 |
6 | class Demo extends StatelessWidget {
7 | const Demo({ super.key });
8 |
9 | @override
10 | Widget build(BuildContext context) => Scaffold(
11 | appBar: AppBar(title: const Text('CaptureGestures Example')),
12 | body: ListView(
13 | physics: const BouncingScrollPhysics(),
14 | children: [
15 | const Box(height: 30),
16 | _greenArea(),
17 | const Box(height: 30),
18 | _yellowArea(),
19 | const Box(height: 2000),
20 | //
21 | ],
22 | ),
23 | );
24 |
25 | Material _greenArea() {
26 | return Material(
27 | color: Colors.green[200],
28 | child: InkWell(
29 | highlightColor: Colors.green,
30 | splashColor: Colors.green,
31 | onTap: () {
32 | print('Green area tapped.');
33 | },
34 | child: CaptureGestures.only(
35 | child: Padding(
36 | padding: const Pad(vertical: 30, horizontal: 50),
37 | child: Column(
38 | children: [
39 | ElevatedButton(
40 | onPressed: () {},
41 | child: const Text('Button'),
42 | ),
43 | const Box(height: 20),
44 | const Text('CaptureGestures.only()\n\n'
45 | 'This green area can be used to scroll.\n'
46 | 'The Button (child) feels taps.\n'
47 | 'The green area (parent) feels taps.'),
48 | ],
49 | ),
50 | ),
51 | ),
52 | ),
53 | );
54 | }
55 |
56 | Material _yellowArea() {
57 | return Material(
58 | color: Colors.yellow,
59 | child: InkWell(
60 | highlightColor: Colors.yellow[800],
61 | splashColor: Colors.yellow[800],
62 | onTap: () {
63 | print('Yellow area tapped.');
64 | },
65 | child: CaptureGestures.scroll(
66 | child: Padding(
67 | padding: const Pad(vertical: 30, horizontal: 50),
68 | child: Column(
69 | children: [
70 | Center(
71 | child: ElevatedButton(
72 | onPressed: () {},
73 | child: const Text('Button'),
74 | ),
75 | ),
76 | const Box(height: 20),
77 | const Text('CaptureGestures.scroll()\n\n'
78 | 'This yellow area CANNOT be used to scroll.\n'
79 | 'The Button (child) feels taps.\n'
80 | 'The yellow area (parent) feels taps.'),
81 | ],
82 | ),
83 | ),
84 | ),
85 | ),
86 | );
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/example/lib/main_column_removing_zero_height.dart:
--------------------------------------------------------------------------------
1 | import 'package:assorted_layout_widgets/assorted_layout_widgets.dart';
2 | import 'package:flutter/material.dart';
3 |
4 | void main() => runApp(const MaterialApp(home: Demo()));
5 |
6 | class Demo extends StatelessWidget {
7 | const Demo({super.key});
8 |
9 | @override
10 | Widget build(BuildContext context) {
11 | return Scaffold(
12 | appBar: AppBar(title: const Text('ColumnSuper Remove Children')),
13 | body: const Column(
14 | children: [
15 | Padding(
16 | padding: Pad(all: 20),
17 | child:
18 | Text("Click the colored boxes to turn their height to zero (they keep their width)."
19 | "\n\n"
20 | "The left column has removeChildrenWithNoHeight: false"
21 | "\n\n"
22 | "The right column has removeChildrenWithNoHeight: true"),
23 | ),
24 | Expanded(
25 | child: Center(
26 | child: Row(
27 | mainAxisSize: MainAxisSize.min,
28 | children: [
29 | ColoredColumn(removeChildrenWithNoHeight: false),
30 | Box(width: 50),
31 | ColoredColumn(removeChildrenWithNoHeight: true),
32 | ],
33 | ),
34 | ),
35 | ),
36 | ],
37 | ),
38 | );
39 | }
40 |
41 | Widget coloredBox(Color color, double height) => Container(
42 | color: color.withOpacity(0.8),
43 | width: 50,
44 | height: height,
45 | );
46 | }
47 |
48 | class ColoredColumn extends StatefulWidget {
49 | final bool removeChildrenWithNoHeight;
50 |
51 | const ColoredColumn({super.key, required this.removeChildrenWithNoHeight});
52 |
53 | @override
54 | State createState() => _ColoredColumnState();
55 | }
56 |
57 | class _ColoredColumnState extends State {
58 | static const separator = Box(width: 80, height: 3, color: Colors.black38);
59 |
60 | Set zeroHeight = {};
61 |
62 | @override
63 | Widget build(BuildContext context) {
64 | return Box(
65 | color: Colors.black12,
66 | child: ColumnSuper(
67 | separator: separator,
68 | innerDistance: 20,
69 | outerDistance: 10,
70 | removeChildrenWithNoHeight: widget.removeChildrenWithNoHeight,
71 | children: [
72 | coloredBox(0, Colors.red, zeroHeight.contains(0) ? 0 : 10),
73 | coloredBox(1, Colors.green, zeroHeight.contains(1) ? 0 : 30),
74 | coloredBox(2, Colors.blue, zeroHeight.contains(2) ? 0 : 130),
75 | coloredBox(3, Colors.purple, zeroHeight.contains(3) ? 0 : 90),
76 | coloredBox(4, Colors.orange, zeroHeight.contains(4) ? 0 : 60),
77 | ],
78 | ),
79 | );
80 | }
81 |
82 | Widget coloredBox(int index, Color color, double height) => GestureDetector(
83 | onTap: () {
84 | setState(() {
85 | zeroHeight.add(index);
86 | });
87 | },
88 | child: Container(
89 | color: color.withOpacity(0.8),
90 | width: 50 + index * 20,
91 | height: height,
92 | ),
93 | );
94 | }
95 |
--------------------------------------------------------------------------------
/example/lib/main_column_row_gestures.dart:
--------------------------------------------------------------------------------
1 | import 'package:assorted_layout_widgets/assorted_layout_widgets.dart';
2 | import 'package:flutter/material.dart';
3 |
4 | void main() => runApp(const MaterialApp(home: Demo()));
5 |
6 | class Demo extends StatefulWidget {
7 | const Demo({super.key});
8 |
9 | @override
10 | State createState() => _DemoState();
11 | }
12 |
13 | class _DemoState extends State {
14 | @override
15 | Widget build(BuildContext context) {
16 | //
17 | return Scaffold(
18 | appBar: AppBar(title: const Text('Gestures: ColumnSuper/RowSuper')),
19 | body: SizedBox.expand(
20 | child: Box(
21 | color: Colors.grey[300],
22 | child: SingleChildScrollView(
23 | child: Column(
24 | crossAxisAlignment: CrossAxisAlignment.stretch,
25 | children: [
26 | const Padding(
27 | padding: Pad(all: 24.0),
28 | child: Center(
29 | child: Text('This demonstrate that the GestureDetector '
30 | 'works as it should when applied to colum/row cells.'),
31 | ),
32 | ),
33 | Row(
34 | mainAxisAlignment: MainAxisAlignment.center,
35 | children: [
36 | Column(
37 | children: [
38 | const Text('normal'),
39 | ColumnSuper(
40 | innerDistance: -40.0,
41 | outerDistance: 0.0,
42 | children: [
43 | box(Colors.red, 'red'),
44 | box(Colors.green, 'green'),
45 | box(Colors.blue, 'blue'),
46 | ],
47 | ),
48 | ],
49 | ),
50 | //
51 | const Box(width: 30),
52 | //
53 | Column(
54 | children: [
55 | const Text('inverted'),
56 | ColumnSuper(
57 | innerDistance: -40.0,
58 | outerDistance: 0.0,
59 | invert: true,
60 | children: [
61 | box(Colors.red, 'red'),
62 | box(Colors.green, 'green'),
63 | box(Colors.blue, 'blue'),
64 | ],
65 | ),
66 | ],
67 | ),
68 | ],
69 | ),
70 | //
71 | const Box(height: 50),
72 | //
73 | Column(
74 | children: [
75 | Column(
76 | children: [
77 | const Text('normal'),
78 | RowSuper(
79 | innerDistance: -40.0,
80 | outerDistance: 8.0,
81 | children: [
82 | box(Colors.red, 'red'),
83 | box(Colors.green, 'green'),
84 | box(Colors.blue, 'blue'),
85 | ],
86 | ),
87 | ],
88 | ),
89 | //
90 | const Box(height: 30),
91 | //
92 | Column(
93 | children: [
94 | const Text('inverted'),
95 | RowSuper(
96 | innerDistance: -40.0,
97 | outerDistance: 8.0,
98 | invert: true,
99 | children: [
100 | box(Colors.red, 'red'),
101 | box(Colors.green, 'green'),
102 | box(Colors.blue, 'blue'),
103 | ],
104 | ),
105 | ],
106 | ),
107 | ],
108 | ),
109 | ],
110 | ),
111 | ),
112 | ),
113 | ),
114 | );
115 | }
116 |
117 | Widget box(Color color, String name) {
118 | return GestureDetector(
119 | onTap: () {
120 | ScaffoldMessenger.of(context).showSnackBar(
121 | SnackBar(
122 | content: Text(
123 | 'Tapped ${name.toUpperCase()}',
124 | style: const TextStyle(fontSize: 24),
125 | ),
126 | duration: const Duration(seconds: 1),
127 | ),
128 | );
129 | },
130 | child: Box(width: 100, height: 100, color: color.withOpacity(0.95)),
131 | );
132 | }
133 | }
134 |
--------------------------------------------------------------------------------
/example/lib/main_column_super.dart:
--------------------------------------------------------------------------------
1 | import 'package:assorted_layout_widgets/assorted_layout_widgets.dart';
2 | import 'package:flutter/material.dart';
3 |
4 | void main() => runApp(const MaterialApp(home: Demo()));
5 |
6 | class Demo extends StatelessWidget {
7 | const Demo({super.key});
8 |
9 | @override
10 | Widget build(BuildContext context) {
11 | //
12 | return Scaffold(
13 | appBar: AppBar(title: const Text('ColumnSuper Example')),
14 | body: SizedBox.expand(
15 | child: SingleChildScrollView(
16 | child: ColumnSuper(
17 | innerDistance: 8.0,
18 | outerDistance: 8.0,
19 | children: [
20 | example1(),
21 | example2(),
22 | example3(),
23 | example4(),
24 | example5(),
25 | example6(),
26 | example7(),
27 | example8(),
28 | example9(),
29 | example10(),
30 | example11(),
31 | example12(),
32 | example13(),
33 | example14(),
34 | example15(),
35 | example16(),
36 | ],
37 | ),
38 | ),
39 | ),
40 | );
41 | }
42 |
43 | Widget example1() => Container(
44 | color: Colors.yellow,
45 | child: ColumnSuper(
46 | alignment: Alignment.center,
47 | invert: false,
48 | children: [redBox(), blueBox()],
49 | ),
50 | );
51 |
52 | Widget example2() => Container(
53 | color: Colors.yellow,
54 | child: ColumnSuper(
55 | outerDistance: -3,
56 | alignment: Alignment.center,
57 | invert: false,
58 | children: [redBox(), blueBox()],
59 | ),
60 | );
61 |
62 | Widget example3() => Container(
63 | color: Colors.yellow,
64 | child: ColumnSuper(
65 | alignment: Alignment.center,
66 | invert: false,
67 | innerDistance: -15,
68 | children: [redBox(), blueBox()],
69 | ),
70 | );
71 |
72 | Widget example4() => Container(
73 | color: Colors.yellow,
74 | child: ColumnSuper(
75 | alignment: Alignment.center,
76 | invert: true,
77 | innerDistance: -15,
78 | children: [redBox(), blueBox()],
79 | ),
80 | );
81 |
82 | Widget example5() => Container(
83 | color: Colors.yellow,
84 | child: ColumnSuper(
85 | alignment: Alignment.center,
86 | invert: false,
87 | outerDistance: 5,
88 | innerDistance: -15,
89 | children: [null, redBox(), null, blueBox(), null],
90 | ),
91 | );
92 |
93 | Widget example6() => Container(
94 | color: Colors.yellow,
95 | child: ColumnSuper(
96 | alignment: Alignment.centerRight,
97 | innerDistance: -15,
98 | children: [redBox(), blueBox()],
99 | ),
100 | );
101 |
102 | Widget example7() => Container(
103 | color: Colors.yellow,
104 | child: ColumnSuper(
105 | alignment: Alignment.centerLeft,
106 | innerDistance: -15,
107 | children: [redBox(), blueBox()],
108 | ),
109 | );
110 |
111 | Widget example8() => Container(
112 | color: Colors.yellow,
113 | child: ColumnSuper(
114 | alignment: Alignment.centerLeft,
115 | innerDistance: 20,
116 | separator: separator(),
117 | children: [redBox(), blueBox()],
118 | ),
119 | );
120 |
121 | Widget example9() => Container(
122 | color: Colors.yellow,
123 | child: ColumnSuper(
124 | alignment: Alignment.center,
125 | innerDistance: 20,
126 | separator: separator(),
127 | children: [redBox(), blueBox()],
128 | ),
129 | );
130 |
131 | Widget example10() => Container(
132 | color: Colors.yellow,
133 | child: ColumnSuper(
134 | alignment: Alignment.center,
135 | innerDistance: 0,
136 | separator: separator(),
137 | children: [redBox(), blueBox()],
138 | ),
139 | );
140 |
141 | Widget example11() => Container(
142 | color: Colors.yellow,
143 | child: ColumnSuper(
144 | alignment: Alignment.center,
145 | innerDistance: 0,
146 | separator: separator(),
147 | separatorOnTop: false,
148 | children: [redBox(), blueBox()],
149 | ),
150 | );
151 |
152 | Widget example12() => Container(
153 | color: Colors.yellow,
154 | child: ColumnSuper(
155 | alignment: Alignment.center,
156 | innerDistance: -45,
157 | separatorOnTop: false,
158 | children: const [
159 | Text("Text", style: TextStyle(fontSize: 50, color: Colors.red)),
160 | Text("Text", style: TextStyle(fontSize: 50, color: Colors.blue)),
161 | Text("Text", style: TextStyle(fontSize: 50, color: Colors.green)),
162 | ],
163 | ),
164 | );
165 |
166 | Widget example13() => Container(
167 | color: Colors.yellow,
168 | child: ColumnSuper(
169 | alignment: Alignment.center,
170 | innerDistance: -45,
171 | invert: true,
172 | separatorOnTop: false,
173 | children: const [
174 | Text("Text", style: TextStyle(fontSize: 50, color: Colors.red)),
175 | Text("Text", style: TextStyle(fontSize: 50, color: Colors.blue)),
176 | Text("Text", style: TextStyle(fontSize: 50, color: Colors.green)),
177 | ],
178 | ),
179 | );
180 |
181 | Widget example14() => Container(
182 | color: Colors.yellow,
183 | child: ColumnSuper(
184 | alignment: Alignment.center,
185 | innerDistance: 0,
186 | separator: Container(
187 | width: 200,
188 | height: 1,
189 | color: Colors.black,
190 | ),
191 | separatorOnTop: false,
192 | children: const [
193 | Text("Text", style: TextStyle(fontSize: 50, color: Colors.red)),
194 | Text("Text", style: TextStyle(fontSize: 50, color: Colors.blue)),
195 | Text("Text", style: TextStyle(fontSize: 50, color: Colors.green)),
196 | ],
197 | ),
198 | );
199 |
200 | Widget example15() => Container(
201 | color: Colors.yellow,
202 | child: ColumnSuper(
203 | alignment: Alignment.center,
204 | innerDistance: 0,
205 | separator: Container(
206 | width: 200,
207 | height: 40,
208 | color: Colors.black,
209 | ),
210 | separatorOnTop: false,
211 | children: const [
212 | Text("Text", style: TextStyle(fontSize: 50, color: Colors.red)),
213 | Text("Text", style: TextStyle(fontSize: 50, color: Colors.blue)),
214 | Text("Text", style: TextStyle(fontSize: 50, color: Colors.green)),
215 | ],
216 | ),
217 | );
218 |
219 | Widget example16() => Container(
220 | color: Colors.yellow,
221 | child: ColumnSuper(
222 | alignment: Alignment.center,
223 | innerDistance: 0,
224 | separator: Container(
225 | width: 200,
226 | height: 40,
227 | color: Colors.black,
228 | ),
229 | separatorOnTop: true,
230 | children: const [
231 | Text("Text", style: TextStyle(fontSize: 50, color: Colors.red)),
232 | Text("Text", style: TextStyle(fontSize: 50, color: Colors.blue)),
233 | Text("Text", style: TextStyle(fontSize: 50, color: Colors.green)),
234 | ],
235 | ),
236 | );
237 |
238 | Widget separator() => Container(
239 | width: 70,
240 | height: 14,
241 | color: Colors.black.withOpacity(0.5),
242 | );
243 |
244 | Widget redBox() => Container(
245 | width: 50,
246 | height: 50,
247 | color: Colors.red,
248 | );
249 |
250 | Widget blueBox() => Container(
251 | width: 70,
252 | height: 30,
253 | color: Colors.blue.withOpacity(0.80),
254 | );
255 | }
256 |
--------------------------------------------------------------------------------
/example/lib/main_column_super_playground.dart:
--------------------------------------------------------------------------------
1 | import 'package:assorted_layout_widgets/assorted_layout_widgets.dart';
2 | import 'package:flutter/material.dart';
3 |
4 | void main() => runApp(const MaterialApp(home: Demo()));
5 |
6 | class Demo extends StatefulWidget {
7 | const Demo({super.key});
8 |
9 | @override
10 | State createState() => _DemoState();
11 | }
12 |
13 | class _DemoState extends State {
14 | late int itemCount;
15 | late double width;
16 | late double height;
17 | late double outer;
18 | late double inner;
19 | late bool withSeparator;
20 | late Alignment alignment;
21 | late double separatorHeight;
22 | late double? parentWidth;
23 | late bool intrinsic;
24 |
25 | @override
26 | void initState() {
27 | super.initState();
28 | itemCount = 5;
29 | width = height = 10.0;
30 | inner = 8.0;
31 | outer = 16.0;
32 | withSeparator = true;
33 | alignment = Alignment.center;
34 | separatorHeight = 1.0;
35 | parentWidth = null;
36 | intrinsic = false;
37 | }
38 |
39 | void _reset() {
40 | itemCount = 0;
41 | width = height = 10.0;
42 | inner = 0.0;
43 | outer = 0.0;
44 | withSeparator = true;
45 | alignment = Alignment.center;
46 | separatorHeight = 1.0;
47 | parentWidth = null;
48 | intrinsic = false;
49 | }
50 |
51 | @override
52 | Widget build(BuildContext context) {
53 | print('---');
54 | print('count = $itemCount');
55 | print('width = $width');
56 | print('height = $height');
57 | print('inner = $inner');
58 | print('outer = $outer');
59 | print('withSeparator = $withSeparator');
60 | print('separatorHeight = $separatorHeight');
61 |
62 | return Scaffold(
63 | appBar: AppBar(title: const Text('ColumnSuper Playground')),
64 | body: Column(
65 | children: [
66 | Expanded(
67 | child: Center(
68 | child: SingleChildScrollView(
69 | child: Column(
70 | children: [
71 | blueBox(),
72 | if (intrinsic)
73 | IntrinsicWidth(
74 | child: IntrinsicHeight(child: _content()),
75 | )
76 | else
77 | _content(),
78 | blueBox(),
79 | ],
80 | ),
81 | ),
82 | ),
83 | ),
84 | //
85 | Container(
86 | width: double.infinity,
87 | color: Colors.grey,
88 | padding: const EdgeInsets.symmetric(vertical: 6.0),
89 | child: Column(
90 | children: [
91 | Row(
92 | mainAxisSize: MainAxisSize.min,
93 | children: [
94 | button("Add Item", () => itemCount++, color: Colors.green),
95 | button("Reset", _reset, color: Colors.red),
96 | ],
97 | ),
98 | Row(
99 | mainAxisSize: MainAxisSize.min,
100 | children: [
101 | button("- Width", () => width -= (width > 0.0) ? 1.0 : 0.0),
102 | button("+ Width", () => width += 1.0),
103 | const Box(width: 10.0),
104 | button("- Height", () => height -= (height > 0.0) ? 1.0 : 0.0),
105 | button("+ Height", () => height += 1.0),
106 | ],
107 | ),
108 | Row(
109 | mainAxisSize: MainAxisSize.min,
110 | children: [
111 | button("- Inner", () => inner -= 1.0),
112 | button("+ Inner", () => inner += 1.0),
113 | Text(" $inner"),
114 | ],
115 | ),
116 | Row(
117 | mainAxisSize: MainAxisSize.min,
118 | children: [
119 | button("- Outer", () => outer -= 1.0),
120 | button("+ Outer", () => outer += 1.0),
121 | Text(" $outer"),
122 | ],
123 | ),
124 | Row(
125 | mainAxisSize: MainAxisSize.min,
126 | children: [
127 | button("Separator ${withSeparator ? 'On' : 'Off'}",
128 | () => withSeparator = !withSeparator),
129 | button(
130 | "- Sep",
131 | withSeparator
132 | ? () => separatorHeight -= (separatorHeight > 0.0) ? 1.0 : 0.0
133 | : null),
134 | button("+ Sep", withSeparator ? () => separatorHeight += 1.0 : null),
135 | Text(" $separatorHeight"),
136 | ],
137 | ),
138 | Row(
139 | mainAxisSize: MainAxisSize.min,
140 | children: [
141 | button("Parent Width = $parentWidth", () {
142 | if (parentWidth == null) {
143 | parentWidth = 70.0;
144 | } else if (parentWidth == 70.0) {
145 | parentWidth = double.infinity;
146 | } else if (parentWidth == double.infinity) {
147 | parentWidth = null;
148 | }
149 | }),
150 | const Box(width: 10.0),
151 | button("Alignment = $alignment", () {
152 | if (alignment == Alignment.center) {
153 | alignment = Alignment.topLeft;
154 | } else if (alignment == Alignment.topLeft) {
155 | alignment = Alignment.topRight;
156 | } else if (alignment == Alignment.topRight) {
157 | alignment = Alignment.center;
158 | }
159 | }),
160 | ],
161 | ),
162 | button("Intrinsic Width/Height = $intrinsic", () => intrinsic = !intrinsic),
163 | ],
164 | ),
165 | ),
166 | ],
167 | ),
168 | );
169 | }
170 |
171 | Container _content() {
172 | return Container(
173 | color: Colors.yellow,
174 | width: parentWidth,
175 | child: ColumnSuper(
176 | alignment: alignment,
177 | separator: withSeparator ? separator() : null,
178 | innerDistance: inner,
179 | outerDistance: outer,
180 | removeChildrenWithNoHeight: true,
181 | children: [
182 | for (int i = 0; i < itemCount; i++) coloredBox(i),
183 | ],
184 | ),
185 | );
186 | }
187 |
188 | Widget button(String label, VoidCallback? func, {Color color = Colors.blue}) => Padding(
189 | padding: const EdgeInsets.symmetric(vertical: 4.0),
190 | child: MaterialButton(
191 | visualDensity: const VisualDensity(vertical: -1.0, horizontal: -3.0),
192 | materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
193 | color: color,
194 | onPressed: (func == null) ? null : () => setState(func),
195 | child: Text(label),
196 | ),
197 | );
198 |
199 | Widget separator() => Container(
200 | width: 100,
201 | height: separatorHeight,
202 | color: Colors.black.withOpacity(0.5),
203 | );
204 |
205 | Widget coloredBox(int index) => Container(
206 | decoration: BoxDecoration(
207 | color: Colors.red.withOpacity(0.5),
208 | border: Border.all(width: 0.5, color: Colors.black),
209 | ),
210 | width: width + index * 10.0,
211 | height: height,
212 | );
213 |
214 | Widget blueBox() => Container(
215 | width: 120,
216 | height: 15,
217 | color: Colors.blue.withOpacity(0.80),
218 | );
219 | }
220 |
--------------------------------------------------------------------------------
/example/lib/main_decorated_box.dart:
--------------------------------------------------------------------------------
1 | import 'package:assorted_layout_widgets/assorted_layout_widgets.dart';
2 | import 'package:flutter/material.dart';
3 |
4 | void main() => runApp(const MaterialApp(home: Demo()));
5 |
6 | /// Here we test the Box widget with decoration.
7 | /// If Box.color is defined, then the decoration cannot be defined, or it can
8 | /// be defined without a color (works for BoxDecoration and ShapeDecoration only).
9 | class Demo extends StatelessWidget {
10 | const Demo({super.key});
11 |
12 | @override
13 | Widget build(BuildContext context) {
14 | //
15 | return Scaffold(
16 | appBar: AppBar(title: const Text('Box with Decoration Example')),
17 | body: SingleChildScrollView(
18 | child: Center(
19 | child: Column(
20 | children: [
21 | example1(),
22 | const Box.gap(24),
23 | example2(),
24 | const Box.gap(24),
25 | example3(),
26 | const Box.gap(24),
27 | example4(),
28 | const Box.gap(24),
29 | example5(),
30 | ],
31 | ),
32 | ),
33 | ),
34 | );
35 | }
36 |
37 | /// Color is separate, and Box decoration without color.
38 | Widget example1() => const Box(
39 | width: 100,
40 | height: 100,
41 | child: Text("Test 1"),
42 | color: Colors.purple,
43 | // Separate color.
44 | decoration: BoxDecoration(
45 | border: Border.symmetric(
46 | vertical: BorderSide(color: Colors.red, width: 6),
47 | horizontal: BorderSide(color: Colors.green, width: 16),
48 | ),
49 | ),
50 | );
51 |
52 | /// Box decoration with color.
53 | Widget example2() => const Box(
54 | width: 100,
55 | height: 100,
56 | child: Text("Test 2"),
57 | decoration: BoxDecoration(
58 | color: Colors.yellow, // Color in decoration.
59 | border: Border.symmetric(
60 | vertical: BorderSide(color: Colors.red, width: 6),
61 | horizontal: BorderSide(color: Colors.green, width: 16),
62 | ),
63 | ),
64 | );
65 |
66 | /// Bor.r etc overrides the color.
67 | Widget example3() => const Box.r(
68 | width: 100,
69 | height: 100,
70 | child: Text("Test 3"),
71 | color: Colors.black,
72 | decoration: BoxDecoration(
73 | color: Colors.black,
74 | border: Border.symmetric(
75 | vertical: BorderSide(color: Colors.red, width: 6),
76 | horizontal: BorderSide(color: Colors.green, width: 16),
77 | ),
78 | ),
79 | );
80 |
81 | /// Bor.r etc overrides the color in the decoration.
82 | Widget example4() => const Box.r(
83 | width: 100,
84 | height: 100,
85 | child: Text("Test 4"),
86 | decoration: BoxDecoration(
87 | color: Colors.black,
88 | border: Border.symmetric(
89 | vertical: BorderSide(color: Colors.red, width: 6),
90 | horizontal: BorderSide(color: Colors.green, width: 16),
91 | ),
92 | ),
93 | );
94 |
95 | /// Bor.rand etc overrides the color in the decoration.
96 | Widget example5() => const Box.rand(
97 | width: 100,
98 | height: 100,
99 | child: Text("Test 5"),
100 | color: Colors.black,
101 | decoration: BoxDecoration(
102 | color: Colors.black,
103 | border: Border.symmetric(
104 | vertical: BorderSide(color: Colors.red, width: 6),
105 | horizontal: BorderSide(color: Colors.green, width: 16),
106 | ),
107 | ),
108 | );
109 | }
110 |
--------------------------------------------------------------------------------
/example/lib/main_delayed.dart:
--------------------------------------------------------------------------------
1 | import 'package:assorted_layout_widgets/assorted_layout_widgets.dart';
2 | import 'package:flutter/material.dart';
3 |
4 | void main() => runApp(const MaterialApp(home: Demo()));
5 |
6 | class Demo extends StatelessWidget {
7 | const Demo({super.key});
8 |
9 | @override
10 | Widget build(BuildContext context) {
11 | //
12 | return Scaffold(
13 | appBar: AppBar(title: const Text('Delayed Example')),
14 | key: UniqueKey(), // Forces restart on hot reload.
15 | body: SingleChildScrollView(
16 | child: Column(
17 | children: [
18 | for (int i = 0; i <= 100; i++)
19 | _delayed(i == 0 ? null : Duration(milliseconds: i * 500)),
20 | ],
21 | ),
22 | ),
23 | );
24 | }
25 |
26 | Widget _delayed(Duration? delay) {
27 | return Delayed(
28 | delay: delay,
29 | builder: (_, bool initialized) => AnimatedOpacity(
30 | opacity: initialized ? 1.0 : 0.0,
31 | duration: const Duration(milliseconds: 500),
32 | child: _myWidget(delay?.inMilliseconds),
33 | ),
34 | );
35 | }
36 |
37 | Widget _myWidget(int? delay) {
38 | // ignore: deprecated_member_use
39 | return Box.rand(
40 | height: 50.0,
41 | child: Center(child: Text(delay.toString())),
42 | );
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/example/lib/main_detect_scroll.dart:
--------------------------------------------------------------------------------
1 | // ignore_for_file: deprecated_member_use
2 | import 'package:assorted_layout_widgets/assorted_layout_widgets.dart';
3 | import 'package:flutter/material.dart';
4 |
5 | void main() {
6 | runApp(
7 | const HomePage(),
8 | );
9 | }
10 |
11 | class HomePage extends StatelessWidget {
12 | const HomePage({super.key});
13 |
14 | @override
15 | Widget build(BuildContext context) {
16 | return MaterialApp(
17 | theme: ThemeData(scrollbarTheme: _scrollbarTheme()),
18 | home: const Demo(),
19 | );
20 | }
21 |
22 | /// This theme makes the scrollbar always visible, with a thickness of 20 px.
23 | ScrollbarThemeData _scrollbarTheme() {
24 | return ScrollbarThemeData(
25 | thumbVisibility: MaterialStateProperty.all(true),
26 | trackVisibility: MaterialStateProperty.all(true),
27 | thickness: MaterialStateProperty.all(20.0),
28 | interactive: true,
29 | radius: const Radius.circular(8),
30 | minThumbLength: 32,
31 | trackColor: MaterialStateProperty.all(Colors.blue[100]),
32 | thumbColor: MaterialStateProperty.all(Colors.blue[900]),
33 | crossAxisMargin: 0,
34 | mainAxisMargin: 0,
35 | );
36 | }
37 | }
38 |
39 | class Demo extends StatefulWidget {
40 | const Demo({super.key});
41 |
42 | @override
43 | State createState() => _DemoState();
44 | }
45 |
46 | class _DemoState extends State {
47 | int lines = 10;
48 |
49 | bool canScroll = false;
50 | double scrollbarWidth = 0;
51 |
52 | @override
53 | Widget build(BuildContext context) {
54 | return Scaffold(
55 | appBar: AppBar(title: const Text('DetectScroll Example')),
56 | body: Column(
57 | children: [
58 | //
59 | Expanded(
60 | child: DetectScroll(
61 | onChange: _onChange,
62 | child: LinesOfText(lines: lines),
63 | ),
64 | ),
65 | //
66 | const Box.gap(20),
67 | Text('onChange gets: canScroll=$canScroll, scrollbarWidth=$scrollbarWidth'),
68 | const Box.gap(20),
69 | Padding(
70 | padding: const Pad(horizontal: 20),
71 | child: Row(
72 | children: [
73 | Expanded(
74 | child: ElevatedButton(
75 | onPressed: () {
76 | setState(() {
77 | lines += 10;
78 | });
79 | },
80 | child: const Text('Add lines'),
81 | ),
82 | ),
83 | const Box.gap(20),
84 | Expanded(
85 | child: ElevatedButton(
86 | onPressed: () {
87 | setState(() {
88 | lines -= 10;
89 | if (lines < 0) lines = 0;
90 | });
91 | },
92 | child: const Text('Remove lines'),
93 | ),
94 | ),
95 | ],
96 | ),
97 | ),
98 | const Box.gap(40),
99 | ],
100 | ),
101 | );
102 | }
103 |
104 | /// This callback is called whenever the scroll state changes.
105 | void _onChange({
106 | required bool canScroll,
107 | required double scrollbarWidth,
108 | }) {
109 | setState(() {
110 | this.canScroll = canScroll;
111 | this.scrollbarWidth = scrollbarWidth;
112 | });
113 | }
114 | }
115 |
116 | class LinesOfText extends StatelessWidget {
117 | final int lines;
118 |
119 | const LinesOfText({
120 | super.key,
121 | required this.lines,
122 | });
123 |
124 | @override
125 | Widget build(BuildContext context) {
126 | final ScrollController scrollController = ScrollController();
127 |
128 | return Box(
129 | color: Colors.blue[200],
130 | width: double.infinity,
131 | child: Stack(
132 | children: [
133 | Scrollbar(
134 | child: SingleChildScrollView(
135 | controller: scrollController,
136 | child: Padding(
137 | padding: const Pad(horizontal: 12, vertical: 6),
138 | child: Column(
139 | mainAxisSize: MainAxisSize.max,
140 | children: List.generate(
141 | lines,
142 | (index) => SizedBox(
143 | width: double.infinity,
144 | child: Text('$lines lines of text'),
145 | ),
146 | ),
147 | ),
148 | ),
149 | ),
150 | ),
151 | Positioned(
152 | top: 0,
153 | right: DetectScroll.of(context).canScroll
154 | ? DetectScroll.of(context).scrollbarWidth
155 | : 0,
156 | child: IconButton(
157 | icon: const Icon(Icons.help_outline),
158 | onPressed: () {
159 | bool canScroll = DetectScroll.of(context).canScroll;
160 | double scrollbarWidth = DetectScroll.of(context).scrollbarWidth;
161 |
162 | showDialog(
163 | context: context,
164 | builder: (BuildContext context) {
165 | return AlertDialog(
166 | content: Text(
167 | 'DetectScroll.of(context).canScroll = $canScroll'
168 | '\n\n'
169 | 'DetectScroll.of(context).scrollbarWidth = $scrollbarWidth'
170 | '\n\n'
171 | 'Note the help button will move '
172 | 'when the scrollbar is shown and removed.',
173 | ),
174 | );
175 | },
176 | );
177 | },
178 | ),
179 | ),
180 | ],
181 | ),
182 | );
183 | }
184 | }
185 |
--------------------------------------------------------------------------------
/example/lib/main_fit_horizontally.dart:
--------------------------------------------------------------------------------
1 | import 'package:assorted_layout_widgets/assorted_layout_widgets.dart';
2 | import 'package:flutter/material.dart';
3 |
4 | void main() => runApp(const MaterialApp(home: Demo()));
5 |
6 | class Demo extends StatelessWidget {
7 | const Demo({super.key});
8 |
9 | @override
10 | Widget build(BuildContext context) {
11 | //
12 | return Scaffold(
13 | appBar: AppBar(title: const Text('FitHorizontally Example')),
14 | body: Padding(
15 | padding: const EdgeInsets.all(8.0),
16 | child: Center(
17 | child: Column(
18 | mainAxisSize: MainAxisSize.min,
19 | crossAxisAlignment: CrossAxisAlignment.start,
20 | children: [
21 | //
22 | const Box(height: 10),
23 | const Text("Simple text:"),
24 | const Box(height: 10),
25 | //
26 | Container(
27 | alignment: Alignment.centerLeft,
28 | color: Colors.yellow,
29 | width: double.infinity,
30 | height: 30,
31 | child: text(),
32 | ),
33 | Container(
34 | alignment: Alignment.centerLeft,
35 | color: Colors.yellow,
36 | width: 250,
37 | height: 30,
38 | child: text(),
39 | ),
40 | Container(
41 | alignment: Alignment.centerLeft,
42 | color: Colors.yellow,
43 | width: 150,
44 | height: 30,
45 | child: text(),
46 | ),
47 | //
48 | const Box(height: 30),
49 | const Text("Text wrapped with FitHorizontally:"),
50 | const Box(height: 10),
51 | //
52 | Container(
53 | alignment: Alignment.centerLeft,
54 | color: Colors.yellow,
55 | width: double.infinity,
56 | height: 30,
57 | child: FitHorizontally(child: text()),
58 | ),
59 | Container(
60 | alignment: Alignment.centerLeft,
61 | color: Colors.yellow,
62 | width: 250,
63 | height: 30,
64 | child: FitHorizontally(child: text()),
65 | ),
66 | Container(
67 | alignment: Alignment.centerLeft,
68 | color: Colors.yellow,
69 | width: 150,
70 | height: 30,
71 | child: FitHorizontally(child: text()),
72 | ),
73 | const Box(height: 50),
74 | ],
75 | ),
76 | ),
77 | ),
78 | );
79 | }
80 |
81 | Container separator() => Container(width: 2, height: 50, color: Colors.black26);
82 |
83 | Text text() => const Text(
84 | "So long, farewell, auf Wiedersehen.",
85 | overflow: TextOverflow.fade,
86 | style: TextStyle(fontSize: 20, color: Colors.blue),
87 | maxLines: 1,
88 | softWrap: false,
89 | );
90 | }
91 |
--------------------------------------------------------------------------------
/example/lib/main_fit_horizontally_baseline.dart:
--------------------------------------------------------------------------------
1 | // ignore_for_file: deprecated_member_use
2 | import 'package:assorted_layout_widgets/assorted_layout_widgets.dart';
3 | import 'package:flutter/material.dart';
4 |
5 | void main() => runApp(const MaterialApp(home: Demo()));
6 |
7 | class Demo extends StatelessWidget {
8 | const Demo({super.key});
9 |
10 | @override
11 | Widget build(BuildContext context) {
12 | //
13 | return Scaffold(
14 | appBar: AppBar(title: const Text('FitHorizontally Baseline Example')),
15 | body: Box(
16 | // color: Colors.red[800],
17 | child: Center(
18 | child: Column(
19 | children: [
20 | const Box(height: 40),
21 | const Text("Row with CrossAxisAlignment.center:"),
22 | const Box(height: 20),
23 | _row(false),
24 | const Box(height: 70),
25 | const Text("Row with CrossAxisAlignment.baseline:"),
26 | const Box(height: 20),
27 | _row(true),
28 | ],
29 | ),
30 | ),
31 | ),
32 | );
33 | }
34 |
35 | Row _row(bool baseline) {
36 | return Row(
37 | crossAxisAlignment: baseline ? CrossAxisAlignment.baseline : CrossAxisAlignment.center,
38 | textBaseline: TextBaseline.alphabetic,
39 | children: const [
40 | //
41 | SizedBox(height: 10),
42 | Box.g(
43 | child: TextOneLine("Hello", style: TextStyle(fontSize: 28)),
44 | ),
45 | Box.y(
46 | width: 45,
47 | child: FitHorizontally(
48 | alignment: Alignment.centerLeft,
49 | child: TextOneLine("Hello", style: TextStyle(fontSize: 28)),
50 | ),
51 | ),
52 | Box.g(
53 | child: TextOneLine("Hello", style: TextStyle(fontSize: 60)),
54 | ),
55 | Box.y(
56 | width: 56,
57 | child: FitHorizontally(
58 | alignment: Alignment.centerLeft,
59 | child: TextOneLine("Hello", style: TextStyle(fontSize: 60)),
60 | ),
61 | ),
62 | ],
63 | );
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/example/lib/main_global_keys.dart:
--------------------------------------------------------------------------------
1 | import 'package:assorted_layout_widgets/assorted_layout_widgets.dart';
2 | import 'package:flutter/material.dart';
3 |
4 | void main() {
5 | runApp(const MyApp());
6 | }
7 |
8 | class MyApp extends StatelessWidget {
9 | const MyApp({super.key});
10 |
11 | @override
12 | Widget build(BuildContext context) => const MaterialApp(
13 | home: MyHomePage(),
14 | );
15 | }
16 |
17 | class MyHomePage extends StatelessWidget {
18 | const MyHomePage({super.key});
19 |
20 | @override
21 | Widget build(BuildContext context) {
22 | return Scaffold(
23 | appBar: AppBar(
24 | title: const Text('Example'),
25 | ),
26 | body: Center(
27 | child: Column(
28 | mainAxisAlignment: MainAxisAlignment.center,
29 | children: [
30 | UserWidget(user: User('Bob')),
31 | UserWidget(user: User('Alice')),
32 | UserWidget(user: User('Marcelo')),
33 | const Divider(color: Colors.black),
34 | toggleUser(User('Bob')),
35 | toggleUser(User('Alice')),
36 | toggleUser(User('Marcelo')),
37 | ],
38 | ),
39 | ),
40 | // This trailing comma makes auto-formatting nicer for build methods.
41 | );
42 | }
43 |
44 | Widget toggleUser(User user) => ElevatedButton(
45 | onPressed: () => UserWidget.toggleSelected(user),
46 | child: Text('Toggle $user'),
47 | );
48 | }
49 |
50 | ///////////////////////////////////////////////////////////////////////////////
51 |
52 | class UserWidget extends StatefulWidget {
53 | final User user;
54 |
55 | static UserWidgetState? currentState(User user) =>
56 | GlobalValueKey(user).currentState;
57 |
58 | static void toggleSelected(User user) => currentState(user)?.toggleSelected();
59 |
60 | UserWidget({required this.user}) : super(key: GlobalValueKey(user));
61 |
62 | @override
63 | State createState() => UserWidgetState();
64 | }
65 |
66 | class UserWidgetState extends State {
67 | bool _selected = false;
68 |
69 | void toggleSelected() {
70 | setState(() {
71 | _selected = !_selected;
72 | });
73 | }
74 |
75 | @override
76 | Widget build(BuildContext context) {
77 | return Container(
78 | color: _selected ? Colors.red : Colors.white,
79 | width: 120,
80 | height: 50,
81 | margin: const EdgeInsets.all(8.0),
82 | child: Center(
83 | child: Text(
84 | widget.user.toString(),
85 | style: TextStyle(
86 | color: _selected ? Colors.white : Colors.grey,
87 | fontWeight: FontWeight.bold,
88 | fontSize: 20),
89 | ),
90 | ));
91 | }
92 | }
93 |
94 | ///////////////////////////////////////////////////////////////////////////////
95 |
96 | class User {
97 | final String name;
98 |
99 | User(this.name);
100 |
101 | @override
102 | String toString() => name;
103 |
104 | @override
105 | bool operator ==(Object other) =>
106 | identical(this, other) ||
107 | other is User && runtimeType == other.runtimeType && name == other.name;
108 |
109 | @override
110 | int get hashCode => name.hashCode;
111 | }
112 |
113 | ///////////////////////////////////////////////////////////////////////////////
114 |
--------------------------------------------------------------------------------
/example/lib/main_non_uniform_outline_input_border.dart:
--------------------------------------------------------------------------------
1 | // ignore_for_file: deprecated_member_use
2 | import 'package:assorted_layout_widgets/assorted_layout_widgets.dart';
3 | import 'package:flutter/material.dart';
4 |
5 | void main() => runApp(const MaterialApp(home: Demo()));
6 |
7 | class Demo extends StatelessWidget {
8 | const Demo({super.key});
9 |
10 | @override
11 | Widget build(BuildContext context) {
12 | //
13 | return Scaffold(
14 | appBar: AppBar(
15 | title: const Text(
16 | 'NonUniformOutlineInputBorder Example',
17 | style: TextStyle(fontSize: 18),
18 | ),
19 | ),
20 | body: SizedBox.expand(
21 | child: SingleChildScrollView(
22 | child: Padding(
23 | padding: const Pad(all: 10.0),
24 | child: Column(
25 | crossAxisAlignment: CrossAxisAlignment.start,
26 | children: _children(),
27 | ),
28 | ),
29 | ),
30 | ),
31 | );
32 | }
33 |
34 | List _children() {
35 | return [
36 | textfield('show all sides'),
37 | //
38 | textfield('hideRightSide', hideRightSide: true),
39 | textfield('hideBottomSide', hideBottomSide: true),
40 | textfield('hideLeftSide', hideLeftSide: true),
41 | textfield('hideTopSide', hideTopSide: true),
42 | //
43 | textfield('hideTopSide & hideRightSide', hideTopSide: true, hideRightSide: true),
44 | textfield('hideTopSide & hideBottomSide', hideTopSide: true, hideBottomSide: true),
45 | textfield('hideTopSide & hideLeftSide', hideTopSide: true, hideLeftSide: true),
46 | //
47 | textfield('hideRightSide & hideBottomSide', hideRightSide: true, hideBottomSide: true),
48 | textfield('hideRightSide & hideLeftSide', hideRightSide: true, hideLeftSide: true),
49 | //
50 | textfield('hideBottomSide & hideLeftSide', hideBottomSide: true, hideLeftSide: true),
51 | //
52 | textfield('show top only', hideRightSide: true, hideBottomSide: true, hideLeftSide: true),
53 | textfield('show right only', hideTopSide: true, hideBottomSide: true, hideLeftSide: true),
54 | textfield('show bottom only', hideTopSide: true, hideRightSide: true, hideLeftSide: true),
55 | textfield('show left only', hideTopSide: true, hideRightSide: true, hideBottomSide: true),
56 | ];
57 | }
58 |
59 | Widget textfield(
60 | String label, {
61 | bool hideTopSide = false,
62 | bool hideBottomSide = false,
63 | bool hideRightSide = false,
64 | bool hideLeftSide = false,
65 | }) =>
66 | Padding(
67 | padding: const Pad(bottom: 20.0),
68 | child: Box.g(
69 | child: TextField(
70 | style: const TextStyle(fontSize: 16),
71 | controller: TextEditingController(text: label),
72 | decoration: InputDecoration(
73 | contentPadding: const Pad(horizontal: 30, vertical: 40),
74 | fillColor: Colors.yellow,
75 | filled: true,
76 | enabledBorder: border(hideTopSide, hideBottomSide, hideRightSide, hideLeftSide),
77 | ),
78 | ),
79 | ),
80 | );
81 |
82 | NonUniformOutlineInputBorder border(
83 | bool hideTopSide,
84 | bool hideBottomSide,
85 | bool hideRightSide,
86 | bool hideLeftSide,
87 | ) {
88 | return NonUniformOutlineInputBorder(
89 | hideTopSide: hideTopSide,
90 | hideBottomSide: hideBottomSide,
91 | hideRightSide: hideRightSide,
92 | hideLeftSide: hideLeftSide,
93 | borderSide: const BorderSide(width: 10),
94 | borderRadius: const BorderRadius.only(
95 | topLeft: Radius.circular(38),
96 | topRight: Radius.circular(38),
97 | bottomLeft: Radius.circular(38),
98 | bottomRight: Radius.circular(38),
99 | ),
100 | );
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/example/lib/main_non_uniform_rounded_rectangle_border.dart:
--------------------------------------------------------------------------------
1 | import 'package:assorted_layout_widgets/assorted_layout_widgets.dart';
2 | import 'package:flutter/material.dart';
3 |
4 | void main() => runApp(const MaterialApp(home: Demo()));
5 |
6 | class Demo extends StatelessWidget {
7 | const Demo({super.key});
8 |
9 | @override
10 | Widget build(BuildContext context) {
11 | //
12 | return Scaffold(
13 | appBar: AppBar(
14 | title: const Text(
15 | 'NonUniformRoundedRectangleBorder Example',
16 | style: TextStyle(fontSize: 15),
17 | ),
18 | ),
19 | body: SizedBox.expand(
20 | child: SingleChildScrollView(
21 | child: Padding(
22 | padding: const Pad(all: 10.0),
23 | child: Column(
24 | crossAxisAlignment: CrossAxisAlignment.start,
25 | children: _children(),
26 | ),
27 | ),
28 | ),
29 | ),
30 | );
31 | }
32 |
33 | List _children() {
34 | return [
35 | button('show all sides'),
36 | //
37 | button('hideRightSide', hideRightSide: true),
38 | button('hideBottomSide', hideBottomSide: true),
39 | button('hideLeftSide', hideLeftSide: true),
40 | button('hideTopSide', hideTopSide: true),
41 | //
42 | button('hideTopSide & hideRightSide', hideTopSide: true, hideRightSide: true),
43 | button('hideTopSide & hideBottomSide', hideTopSide: true, hideBottomSide: true),
44 | button('hideTopSide & hideLeftSide', hideTopSide: true, hideLeftSide: true),
45 | //
46 | button('hideRightSide & hideBottomSide', hideRightSide: true, hideBottomSide: true),
47 | button('hideRightSide & hideLeftSide', hideRightSide: true, hideLeftSide: true),
48 | //
49 | button('hideBottomSide & hideLeftSide', hideBottomSide: true, hideLeftSide: true),
50 | //
51 | button('show top only', hideRightSide: true, hideBottomSide: true, hideLeftSide: true),
52 | button('show right only', hideTopSide: true, hideBottomSide: true, hideLeftSide: true),
53 | button('show bottom only', hideTopSide: true, hideRightSide: true, hideLeftSide: true),
54 | button('show left only', hideTopSide: true, hideRightSide: true, hideBottomSide: true),
55 | ];
56 | }
57 |
58 | Widget button(
59 | String label, {
60 | bool hideTopSide = false,
61 | bool hideBottomSide = false,
62 | bool hideRightSide = false,
63 | bool hideLeftSide = false,
64 | }) =>
65 | Padding(
66 | padding: const Pad(bottom: 20.0),
67 | child: Box(
68 | height: 70,
69 | child: ElevatedButton(
70 | style: ElevatedButton.styleFrom(
71 | elevation: 0,
72 | shadowColor: Colors.transparent,
73 | backgroundColor: Colors.lightGreen,
74 | foregroundColor: Colors.white,
75 | textStyle: const TextStyle(fontSize: 18),
76 | shape: shape(hideTopSide, hideBottomSide, hideRightSide, hideLeftSide),
77 | ),
78 | onPressed: () {},
79 | child: Text(label),
80 | ),
81 | ),
82 | );
83 |
84 | NonUniformRoundedRectangleBorder shape(
85 | bool hideTopSide,
86 | bool hideBottomSide,
87 | bool hideRightSide,
88 | bool hideLeftSide,
89 | ) {
90 | return NonUniformRoundedRectangleBorder(
91 | side: const BorderSide(color: Colors.black87, width: 15.0),
92 | borderRadius: const BorderRadius.only(
93 | topLeft: Radius.circular(30),
94 | topRight: Radius.circular(30),
95 | bottomLeft: Radius.circular(30),
96 | bottomRight: Radius.circular(30),
97 | ),
98 | hideTopSide: hideTopSide,
99 | hideBottomSide: hideBottomSide,
100 | hideRightSide: hideRightSide,
101 | hideLeftSide: hideLeftSide,
102 | );
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/example/lib/main_normalized_overflow_box.dart:
--------------------------------------------------------------------------------
1 | import 'package:assorted_layout_widgets/assorted_layout_widgets.dart';
2 | import 'package:flutter/material.dart';
3 |
4 | void main() => runApp(const MaterialApp(home: Demo()));
5 |
6 | class Demo extends StatelessWidget {
7 | const Demo({super.key});
8 |
9 | static const text = Text("If you set your goals ridiculously high and it's a failure, "
10 | "you will fail above everyone else's success.");
11 |
12 | @override
13 | Widget build(BuildContext context) {
14 | return Scaffold(
15 | appBar: AppBar(title: const Text('NormalizedOverflowBox Example')),
16 | body: const Center(
17 | child: Box(
18 | width: 300,
19 | child: Column(
20 | children: [
21 | SizedBox(height: 10),
22 | Box(
23 | color: Colors.green,
24 | height: 105,
25 | width: 110,
26 | child: NormalizedOverflowBox(minWidth: 50, child: text),
27 | ),
28 | Box(height: 10),
29 | Box(
30 | color: Colors.blue,
31 | height: 105,
32 | width: 110,
33 | child: OverflowBox(minWidth: 100, child: text),
34 | ),
35 | Box(height: 10),
36 | Box(
37 | color: Colors.red,
38 | height: 105,
39 | width: 110,
40 | child: NormalizedOverflowBox(minWidth: 130, child: text),
41 | ),
42 | Box(height: 10),
43 | Box(
44 | color: Colors.purple,
45 | height: 105,
46 | width: 110,
47 | child: NormalizedOverflowBox(minWidth: 200, child: text),
48 | ),
49 | ],
50 | ),
51 | ),
52 | ),
53 | );
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/example/lib/main_row_spacer.dart:
--------------------------------------------------------------------------------
1 | import 'package:assorted_layout_widgets/assorted_layout_widgets.dart';
2 | import 'package:flutter/material.dart';
3 |
4 | void main() => runApp(const MaterialApp(home: Demo()));
5 |
6 | class Demo extends StatelessWidget {
7 | const Demo({super.key});
8 |
9 | @override
10 | Widget build(BuildContext context) {
11 | //
12 | return Scaffold(
13 | appBar: AppBar(title: const Text('RowSpacer Example')),
14 | body: Column(
15 | children: [
16 | //
17 | const SizedBox(height: 10),
18 | //
19 | Container(
20 | color: Colors.yellow,
21 | child: RowSuper(
22 | children: [
23 | text1(),
24 | text2(),
25 | ],
26 | ),
27 | ),
28 | //
29 | const SizedBox(height: 10),
30 | //
31 | Container(
32 | color: Colors.yellow,
33 | child: RowSuper(
34 | children: [
35 | text1(),
36 | text2(),
37 | RowSpacer(),
38 | ],
39 | ),
40 | ),
41 | //
42 | const SizedBox(height: 10),
43 | //
44 | Container(
45 | color: Colors.yellow,
46 | child: RowSuper(
47 | mainAxisSize: MainAxisSize.max,
48 | children: [
49 | text1(),
50 | text2(),
51 | ],
52 | ),
53 | ),
54 | //
55 | const SizedBox(height: 10),
56 | //
57 | Container(
58 | width: 165.0,
59 | color: Colors.yellow,
60 | child: RowSuper(
61 | children: [
62 | RowSpacer(),
63 | text1(),
64 | RowSpacer(),
65 | text2(),
66 | RowSpacer(),
67 | ],
68 | ),
69 | ),
70 | //
71 | const SizedBox(height: 10),
72 | //
73 | Container(
74 | width: 165.0,
75 | color: Colors.yellow,
76 | child: RowSuper(
77 | fitHorizontally: true,
78 | children: [
79 | RowSpacer(),
80 | text1(),
81 | RowSpacer(),
82 | text2(),
83 | RowSpacer(),
84 | ],
85 | ),
86 | ),
87 | //
88 | const SizedBox(height: 10),
89 | Container(width: double.infinity, height: 2.0, color: Colors.black),
90 | const SizedBox(height: 10),
91 | //
92 | // ------------
93 | //
94 | Container(
95 | color: Colors.yellow,
96 | child: RowSuper(
97 | alignment: Alignment.bottomRight,
98 | innerDistance: 5.0,
99 | children: [
100 | Container(
101 | color: Colors.orange,
102 | child: RowSuper(
103 | alignment: Alignment.topRight,
104 | children: [
105 | text1(),
106 | text2(),
107 | ],
108 | ),
109 | ),
110 | RowSpacer(),
111 | box1(),
112 | box2(),
113 | ],
114 | ),
115 | ),
116 | //
117 | ],
118 | ),
119 | );
120 | }
121 |
122 | Container text1() => Container(
123 | color: Colors.red,
124 | child: const Text("Hello!",
125 | maxLines: 1,
126 | overflow: TextOverflow.fade,
127 | softWrap: false,
128 | style: TextStyle(fontSize: 27.0)),
129 | );
130 |
131 | Container text2() => Container(
132 | color: Colors.blue,
133 | child: const Text("How are you doing?",
134 | maxLines: 1,
135 | overflow: TextOverflow.fade,
136 | softWrap: false,
137 | style: TextStyle(fontSize: 20.0)),
138 | );
139 |
140 | Container box1() => Container(width: 30, height: 40, color: Colors.green);
141 |
142 | Container box2() => Container(width: 30, height: 50, color: Colors.purple);
143 | }
144 |
--------------------------------------------------------------------------------
/example/lib/main_row_super.dart:
--------------------------------------------------------------------------------
1 | import 'package:assorted_layout_widgets/assorted_layout_widgets.dart';
2 | import 'package:flutter/material.dart';
3 |
4 | void main() => runApp(const MaterialApp(home: Demo()));
5 |
6 | class Demo extends StatelessWidget {
7 | const Demo({super.key});
8 |
9 | @override
10 | Widget build(BuildContext context) {
11 | //
12 | return Scaffold(
13 | appBar: AppBar(title: const Text('RowSuper Example')),
14 | body: SizedBox.expand(
15 | child: SingleChildScrollView(
16 | scrollDirection: Axis.horizontal,
17 | child: RowSuper(
18 | innerDistance: 8.0,
19 | outerDistance: 8.0,
20 | children: [
21 | example1(),
22 | example2(),
23 | example3(),
24 | example4(),
25 | example5(),
26 | example6(),
27 | example7(),
28 | example8(),
29 | example9(),
30 | example10(),
31 | example11(),
32 | example12(),
33 | example13(),
34 | example14(),
35 | example15(),
36 | example16(),
37 | ],
38 | ),
39 | ),
40 | ),
41 | );
42 | }
43 |
44 | Widget example1() => Container(
45 | color: Colors.yellow,
46 | child: RowSuper(
47 | alignment: Alignment.center,
48 | invert: false,
49 | children: [redBox(), blueBox()],
50 | ),
51 | );
52 |
53 | Widget example2() => Container(
54 | color: Colors.yellow,
55 | child: RowSuper(
56 | outerDistance: -3,
57 | alignment: Alignment.center,
58 | invert: false,
59 | children: [redBox(), blueBox()],
60 | ),
61 | );
62 |
63 | Widget example3() => Container(
64 | color: Colors.yellow,
65 | child: RowSuper(
66 | alignment: Alignment.center,
67 | invert: false,
68 | innerDistance: -15,
69 | children: [redBox(), blueBox()],
70 | ),
71 | );
72 |
73 | Widget example4() => Container(
74 | color: Colors.yellow,
75 | child: RowSuper(
76 | alignment: Alignment.center,
77 | invert: true,
78 | innerDistance: -15,
79 | children: [redBox(), blueBox()],
80 | ),
81 | );
82 |
83 | Widget example5() => Container(
84 | color: Colors.yellow,
85 | child: RowSuper(
86 | alignment: Alignment.center,
87 | invert: false,
88 | outerDistance: 5,
89 | innerDistance: -15,
90 | children: [null, redBox(), null, blueBox(), null],
91 | ),
92 | );
93 |
94 | Widget example6() => Container(
95 | color: Colors.yellow,
96 | child: RowSuper(
97 | alignment: Alignment.bottomCenter,
98 | innerDistance: -15,
99 | children: [redBox(), blueBox()],
100 | ),
101 | );
102 |
103 | Widget example7() => Container(
104 | color: Colors.yellow,
105 | child: RowSuper(
106 | alignment: Alignment.topCenter,
107 | innerDistance: -15,
108 | children: [redBox(), blueBox()],
109 | ),
110 | );
111 |
112 | Widget example8() => Container(
113 | color: Colors.yellow,
114 | child: RowSuper(
115 | alignment: Alignment.topCenter,
116 | innerDistance: 20,
117 | separator: separator(),
118 | children: [redBox(), blueBox()],
119 | ),
120 | );
121 |
122 | Widget example9() => Container(
123 | color: Colors.yellow,
124 | child: RowSuper(
125 | alignment: Alignment.center,
126 | innerDistance: 20,
127 | separator: separator(),
128 | children: [redBox(), blueBox()],
129 | ),
130 | );
131 |
132 | Widget example10() => Container(
133 | color: Colors.yellow,
134 | child: RowSuper(
135 | alignment: Alignment.center,
136 | innerDistance: 0,
137 | separator: separator(),
138 | children: [redBox(), blueBox()],
139 | ),
140 | );
141 |
142 | Widget example11() => Container(
143 | color: Colors.yellow,
144 | child: RowSuper(
145 | alignment: Alignment.center,
146 | innerDistance: 0,
147 | separator: separator(),
148 | separatorOnTop: false,
149 | children: [redBox(), blueBox()],
150 | ),
151 | );
152 |
153 | Widget example12() => Container(
154 | color: Colors.yellow,
155 | child: RowSuper(
156 | alignment: Alignment.center,
157 | innerDistance: -45,
158 | separatorOnTop: false,
159 | children: const [
160 | Text("Text", style: TextStyle(fontSize: 50, color: Colors.red)),
161 | Text("Text", style: TextStyle(fontSize: 50, color: Colors.blue)),
162 | Text("Text", style: TextStyle(fontSize: 50, color: Colors.green)),
163 | ],
164 | ),
165 | );
166 |
167 | Widget example13() => Container(
168 | color: Colors.yellow,
169 | child: RowSuper(
170 | alignment: Alignment.center,
171 | innerDistance: -45,
172 | invert: true,
173 | separatorOnTop: false,
174 | children: const [
175 | Text("Text", style: TextStyle(fontSize: 50, color: Colors.red)),
176 | Text("Text", style: TextStyle(fontSize: 50, color: Colors.blue)),
177 | Text("Text", style: TextStyle(fontSize: 50, color: Colors.green)),
178 | ],
179 | ),
180 | );
181 |
182 | Widget example14() => Container(
183 | color: Colors.yellow,
184 | child: RowSuper(
185 | alignment: Alignment.center,
186 | innerDistance: 0,
187 | separator: Container(
188 | height: 200,
189 | width: 1,
190 | color: Colors.black,
191 | ),
192 | separatorOnTop: false,
193 | children: const [
194 | Text("Text", style: TextStyle(fontSize: 50, color: Colors.red)),
195 | Text("Text", style: TextStyle(fontSize: 50, color: Colors.blue)),
196 | Text("Text", style: TextStyle(fontSize: 50, color: Colors.green)),
197 | ],
198 | ),
199 | );
200 |
201 | Widget example15() => Container(
202 | color: Colors.yellow,
203 | child: RowSuper(
204 | alignment: Alignment.center,
205 | innerDistance: 0,
206 | separator: Container(
207 | height: 200,
208 | width: 40,
209 | color: Colors.black,
210 | ),
211 | separatorOnTop: false,
212 | children: const [
213 | Text("Text", style: TextStyle(fontSize: 50, color: Colors.red)),
214 | Text("Text", style: TextStyle(fontSize: 50, color: Colors.blue)),
215 | Text("Text", style: TextStyle(fontSize: 50, color: Colors.green)),
216 | ],
217 | ),
218 | );
219 |
220 | Widget example16() => Container(
221 | color: Colors.yellow,
222 | child: RowSuper(
223 | alignment: Alignment.center,
224 | innerDistance: 0,
225 | separator: Container(
226 | height: 200,
227 | width: 40,
228 | color: Colors.black,
229 | ),
230 | separatorOnTop: true,
231 | children: const [
232 | Text("Text", style: TextStyle(fontSize: 50, color: Colors.red)),
233 | Text("Text", style: TextStyle(fontSize: 50, color: Colors.blue)),
234 | Text("Text", style: TextStyle(fontSize: 50, color: Colors.green)),
235 | ],
236 | ),
237 | );
238 |
239 | Widget separator() => Container(
240 | width: 14,
241 | height: 70,
242 | color: Colors.black.withOpacity(0.5),
243 | );
244 |
245 | Widget redBox() => Container(
246 | width: 50,
247 | height: 50,
248 | color: Colors.red,
249 | );
250 |
251 | Widget blueBox() => Container(
252 | width: 30,
253 | height: 70,
254 | color: Colors.blue.withOpacity(0.80),
255 | );
256 | }
257 |
--------------------------------------------------------------------------------
/example/lib/main_row_super_alignment.dart:
--------------------------------------------------------------------------------
1 | // ignore_for_file: deprecated_member_use
2 | import 'package:assorted_layout_widgets/assorted_layout_widgets.dart';
3 | import 'package:flutter/material.dart';
4 |
5 | void main() => runApp(const MaterialApp(home: Demo()));
6 |
7 | class Demo extends StatelessWidget {
8 | const Demo({super.key});
9 |
10 | //
11 | static const List boxes = [
12 | Box.r(width: 50, height: 20),
13 | Box.g(width: 50, height: 35),
14 | Box.b(width: 50, height: 50),
15 | ];
16 |
17 | @override
18 | Widget build(BuildContext context) {
19 | //
20 | return Scaffold(
21 | appBar: AppBar(title: const Text('RowSuper Alignment')),
22 | body: SizedBox.expand(
23 | child: Column(
24 | children: [
25 | //
26 | const Text("topLeft"),
27 | Box(
28 | color: Colors.black,
29 | width: double.infinity,
30 | child: RowSuper(
31 | alignment: Alignment.topLeft,
32 | innerDistance: 6.0,
33 | outerDistance: 20.0,
34 | children: boxes,
35 | ),
36 | ),
37 | //
38 | const Box(height: 4.0),
39 | //
40 | const Text("topCenter"),
41 | Box(
42 | color: Colors.black,
43 | width: double.infinity,
44 | child: RowSuper(
45 | alignment: Alignment.topCenter,
46 | innerDistance: 6.0,
47 | outerDistance: 20.0,
48 | children: boxes,
49 | ),
50 | ),
51 | //
52 | const Box(height: 4.0),
53 | //
54 | const Text("topRight"),
55 | Box(
56 | color: Colors.black,
57 | width: double.infinity,
58 | child: RowSuper(
59 | alignment: Alignment.topRight,
60 | innerDistance: 6.0,
61 | outerDistance: 20.0,
62 | children: boxes,
63 | ),
64 | ),
65 | //
66 | const Box(height: 15.0),
67 | //
68 | const Text("centerLeft"),
69 | Box(
70 | color: Colors.black,
71 | width: double.infinity,
72 | child: RowSuper(
73 | alignment: Alignment.centerLeft,
74 | outerDistance: 20.0,
75 | children: boxes,
76 | ),
77 | ),
78 | //
79 | const Box(height: 4.0),
80 | //
81 | const Text("center"),
82 | Box(
83 | color: Colors.black,
84 | width: double.infinity,
85 | child: RowSuper(
86 | alignment: Alignment.center,
87 | outerDistance: 20.0,
88 | children: boxes,
89 | ),
90 | ),
91 | //
92 | const Box(height: 4.0),
93 | //
94 | const Text("centerRight"),
95 | Box(
96 | color: Colors.black,
97 | width: double.infinity,
98 | child: RowSuper(
99 | alignment: Alignment.centerRight,
100 | outerDistance: 20.0,
101 | children: boxes,
102 | ),
103 | ),
104 | //
105 | const Box(height: 15.0),
106 | //
107 | const Text("bottomLeft"),
108 | Box(
109 | color: Colors.black,
110 | width: double.infinity,
111 | child: RowSuper(
112 | alignment: Alignment.bottomLeft,
113 | children: boxes,
114 | ),
115 | ),
116 | //
117 | const Box(height: 4.0),
118 | //
119 | const Text("bottomCenter"),
120 | Box(
121 | color: Colors.black,
122 | width: double.infinity,
123 | child: RowSuper(
124 | alignment: Alignment.bottomCenter,
125 | children: boxes,
126 | ),
127 | ),
128 | //
129 | const Box(height: 4.0),
130 | //
131 | const Text("bottomRight"),
132 | Box(
133 | color: Colors.black,
134 | width: double.infinity,
135 | child: RowSuper(
136 | alignment: Alignment.bottomRight,
137 | children: boxes,
138 | ),
139 | ),
140 | ],
141 | ),
142 | ),
143 | );
144 | }
145 | }
146 |
--------------------------------------------------------------------------------
/example/lib/main_row_super_fill.dart:
--------------------------------------------------------------------------------
1 | import 'package:assorted_layout_widgets/assorted_layout_widgets.dart';
2 | import 'package:flutter/material.dart';
3 |
4 | void main() => runApp(const MaterialApp(home: Demo()));
5 |
6 | class Demo extends StatelessWidget {
7 | const Demo({super.key});
8 |
9 | @override
10 | Widget build(BuildContext context) {
11 | //
12 | return Scaffold(
13 | appBar: AppBar(title: const Text('RowSuper Fill Example')),
14 | body: Center(
15 | child: Column(
16 | children: [
17 | //
18 | const SizedBox(height: 20.0),
19 | const Text("fill: false"),
20 | const SizedBox(height: 10.0),
21 | Container(
22 | color: Colors.yellow,
23 | child: RowSuper(
24 | mainAxisSize: MainAxisSize.max,
25 | children: [
26 | Container(
27 | alignment: Alignment.center,
28 | color: Colors.red,
29 | child: const Text("MainAxisSize.max"),
30 | ),
31 | Container(
32 | alignment: Alignment.center,
33 | color: Colors.blue.withOpacity(0.80),
34 | child: const Text("MainAxisSize.max"),
35 | )
36 | ],
37 | ),
38 | ),
39 | const SizedBox(height: 10.0),
40 | Container(
41 | color: Colors.yellow,
42 | child: RowSuper(
43 | mainAxisSize: MainAxisSize.min,
44 | children: [
45 | Container(
46 | alignment: Alignment.center,
47 | color: Colors.red,
48 | child: const Text("MainAxisSize.min"),
49 | ),
50 | Container(
51 | alignment: Alignment.center,
52 | color: Colors.blue.withOpacity(0.80),
53 | child: const Text("MainAxisSize.min"),
54 | )
55 | ],
56 | ),
57 | ),
58 | const SizedBox(height: 10.0),
59 | Container(
60 | color: Colors.yellow,
61 | child: RowSuper(
62 | children: [
63 | Container(
64 | alignment: Alignment.center,
65 | color: Colors.red,
66 | child: const Text("Hello"),
67 | ),
68 | Container(
69 | alignment: Alignment.center,
70 | color: Colors.blue.withOpacity(0.80),
71 | child: const Text("This is some larger text"),
72 | )
73 | ],
74 | ),
75 | ),
76 | const SizedBox(height: 10.0),
77 | Container(
78 | color: Colors.yellow,
79 | child: RowSuper(
80 | children: [
81 | Container(
82 | alignment: Alignment.center,
83 | color: Colors.red,
84 | child: const Text("Hello"),
85 | ),
86 | Container(
87 | alignment: Alignment.center,
88 | color: Colors.blue.withOpacity(0.80),
89 | child: const Text("This is some really very, "
90 | "extremely large text "
91 | "that won't fit a single line at all"),
92 | )
93 | ],
94 | ),
95 | ),
96 | //
97 | // -------------------
98 | //
99 | const SizedBox(height: 40.0),
100 | Container(width: double.infinity, height: 1.0, color: Colors.black),
101 | const SizedBox(height: 40.0),
102 | const Text("fill: true"),
103 | const SizedBox(height: 10.0),
104 | Container(
105 | color: Colors.yellow,
106 | child: RowSuper(
107 | fill: true,
108 | mainAxisSize: MainAxisSize.max,
109 | children: [
110 | Container(
111 | alignment: Alignment.center,
112 | color: Colors.red,
113 | child: const Text("MainAxisSize.max"),
114 | ),
115 | Container(
116 | alignment: Alignment.center,
117 | color: Colors.blue.withOpacity(0.80),
118 | child: const Text("MainAxisSize.max"),
119 | )
120 | ],
121 | ),
122 | ),
123 | const SizedBox(height: 10.0),
124 | Container(
125 | color: Colors.yellow,
126 | child: RowSuper(
127 | fill: true,
128 | mainAxisSize: MainAxisSize.min,
129 | children: [
130 | Container(
131 | alignment: Alignment.center,
132 | color: Colors.red,
133 | child: const Text("MainAxisSize.min"),
134 | ),
135 | Container(
136 | alignment: Alignment.center,
137 | color: Colors.blue.withOpacity(0.80),
138 | child: const Text("MainAxisSize.min"),
139 | )
140 | ],
141 | ),
142 | ),
143 | const SizedBox(height: 10.0),
144 | Container(
145 | color: Colors.yellow,
146 | child: RowSuper(
147 | fill: true,
148 | children: [
149 | Container(
150 | alignment: Alignment.center,
151 | color: Colors.red,
152 | child: const Text("Hello"),
153 | ),
154 | Container(
155 | alignment: Alignment.center,
156 | color: Colors.blue.withOpacity(0.80),
157 | child: const Text("This is some larger text"),
158 | ),
159 | ],
160 | ),
161 | ),
162 | const SizedBox(height: 10.0),
163 | Container(
164 | color: Colors.yellow,
165 | child: RowSuper(
166 | fill: true,
167 | children: [
168 | Container(
169 | alignment: Alignment.center,
170 | color: Colors.red,
171 | child: const Text("Hello"),
172 | ),
173 | Container(
174 | alignment: Alignment.center,
175 | color: Colors.blue.withOpacity(0.80),
176 | child: const Text("This is some really very, "
177 | "extremely large text "
178 | "that won't fit a single line at all"),
179 | )
180 | ],
181 | ),
182 | ),
183 | ],
184 | ),
185 | ),
186 | );
187 | }
188 | }
189 |
--------------------------------------------------------------------------------
/example/lib/main_row_super_playground.dart:
--------------------------------------------------------------------------------
1 | import 'package:assorted_layout_widgets/assorted_layout_widgets.dart';
2 | import 'package:flutter/material.dart';
3 |
4 | void main() => runApp(const MaterialApp(home: Demo()));
5 |
6 | class Demo extends StatefulWidget {
7 | const Demo({super.key});
8 |
9 | @override
10 | State createState() => _DemoState();
11 | }
12 |
13 | class _DemoState extends State {
14 | late int itemCount;
15 | late double height;
16 | late double width;
17 | late double outer;
18 | late double inner;
19 | late bool withSeparator;
20 | late Alignment alignment;
21 | late double separatorWidth;
22 | late double? parentHeight;
23 | late bool intrinsic;
24 |
25 | @override
26 | void initState() {
27 | super.initState();
28 | itemCount = 5;
29 | height = width = 10.0;
30 | inner = 8.0;
31 | outer = 16.0;
32 | withSeparator = true;
33 | alignment = Alignment.center;
34 | separatorWidth = 1.0;
35 | parentHeight = null;
36 | intrinsic = false;
37 | }
38 |
39 | void _reset() {
40 | itemCount = 0;
41 | height = width = 10.0;
42 | inner = 0.0;
43 | outer = 0.0;
44 | withSeparator = true;
45 | alignment = Alignment.center;
46 | separatorWidth = 1.0;
47 | parentHeight = null;
48 | intrinsic = false;
49 | }
50 |
51 | @override
52 | Widget build(BuildContext context) {
53 | print('---');
54 | print('count = $itemCount');
55 | print('width = $height');
56 | print('height = $width');
57 | print('inner = $inner');
58 | print('outer = $outer');
59 | print('withSeparator = $withSeparator');
60 | print('separatorHeight = $separatorWidth');
61 | print('parentHeight = $parentHeight');
62 |
63 | return Scaffold(
64 | appBar: AppBar(title: const Text('RowSuper Playground')),
65 | body: Column(
66 | children: [
67 | Expanded(
68 | child: Center(
69 | child: SingleChildScrollView(
70 | scrollDirection: Axis.horizontal,
71 | child: Row(
72 | children: [
73 | blueBox(),
74 | if (intrinsic)
75 | IntrinsicWidth(
76 | child: IntrinsicHeight(child: _content()),
77 | )
78 | else
79 | _content(),
80 | blueBox(),
81 | ],
82 | ),
83 | ),
84 | ),
85 | ),
86 | //
87 | Container(
88 | width: double.infinity,
89 | color: Colors.grey,
90 | padding: const EdgeInsets.symmetric(vertical: 6.0),
91 | child: Column(
92 | children: [
93 | Row(
94 | mainAxisSize: MainAxisSize.min,
95 | children: [
96 | button("Add Item", () => itemCount++, color: Colors.green),
97 | button("Reset", _reset, color: Colors.red),
98 | ],
99 | ),
100 | Row(
101 | mainAxisSize: MainAxisSize.min,
102 | children: [
103 | button("- Width", () => width -= (width > 0.0) ? 1.0 : 0.0),
104 | button("+ Width", () => width += 1.0),
105 | const Box(width: 10.0),
106 | button("- Height", () => height -= (height > 0.0) ? 1.0 : 0.0),
107 | button("+ Height", () => height += 1.0),
108 | ],
109 | ),
110 | Row(
111 | mainAxisSize: MainAxisSize.min,
112 | children: [
113 | button("- Inner", () => inner -= 1.0),
114 | button("+ Inner", () => inner += 1.0),
115 | Text(" $inner"),
116 | ],
117 | ),
118 | Row(
119 | mainAxisSize: MainAxisSize.min,
120 | children: [
121 | button("- Outer", () => outer -= 1.0),
122 | button("+ Outer", () => outer += 1.0),
123 | Text(" $outer"),
124 | ],
125 | ),
126 | Row(
127 | mainAxisSize: MainAxisSize.min,
128 | children: [
129 | button("Separator ${withSeparator ? 'On' : 'Off'}",
130 | () => withSeparator = !withSeparator),
131 | button(
132 | "- Sep",
133 | withSeparator
134 | ? () => separatorWidth -= (separatorWidth > 0.0) ? 1.0 : 0.0
135 | : null),
136 | button("+ Sep", withSeparator ? () => separatorWidth += 1.0 : null),
137 | Text(" $separatorWidth"),
138 | ],
139 | ),
140 | Row(
141 | mainAxisSize: MainAxisSize.min,
142 | children: [
143 | button("Parent Height = $parentHeight", () {
144 | if (parentHeight == null) {
145 | parentHeight = 70.0;
146 | } else if (parentHeight == 70.0) {
147 | parentHeight = double.infinity;
148 | } else if (parentHeight == double.infinity) {
149 | parentHeight = null;
150 | }
151 | }),
152 | const Box(width: 10.0),
153 | button("Alignment = $alignment", () {
154 | if (alignment == Alignment.center) {
155 | alignment = Alignment.topLeft;
156 | } else if (alignment == Alignment.topLeft) {
157 | alignment = Alignment.bottomLeft;
158 | } else if (alignment == Alignment.bottomLeft) {
159 | alignment = Alignment.center;
160 | }
161 | })
162 | ],
163 | ),
164 | button("Intrinsic Width/Height = $intrinsic", () => intrinsic = !intrinsic),
165 | ],
166 | ),
167 | ),
168 | ],
169 | ),
170 | );
171 | }
172 |
173 | Container _content() {
174 | return Container(
175 | color: Colors.yellow,
176 | height: parentHeight,
177 | child: RowSuper(
178 | alignment: alignment,
179 | separator: withSeparator ? separator() : null,
180 | innerDistance: inner,
181 | outerDistance: outer,
182 | children: [
183 | for (int i = 0; i < itemCount; i++) coloredBox(i),
184 | ],
185 | ),
186 | );
187 | }
188 |
189 | Widget button(String label, VoidCallback? func, {Color color = Colors.blue}) => Padding(
190 | padding: const EdgeInsets.symmetric(vertical: 4.0),
191 | child: MaterialButton(
192 | visualDensity: const VisualDensity(vertical: -1.0, horizontal: -3.0),
193 | materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
194 | color: color,
195 | onPressed: (func == null) ? null : () => setState(func),
196 | child: Text(label),
197 | ),
198 | );
199 |
200 | Widget separator() => Container(
201 | height: 100,
202 | width: separatorWidth,
203 | color: Colors.black.withOpacity(0.5),
204 | );
205 |
206 | Widget coloredBox(int index) => Container(
207 | decoration: BoxDecoration(
208 | color: Colors.red.withOpacity(0.5),
209 | border: Border.all(width: 0.5, color: Colors.black),
210 | ),
211 | height: height + index * 10.0,
212 | width: width,
213 | );
214 |
215 | Widget blueBox() => Container(
216 | height: 120,
217 | width: 15,
218 | color: Colors.blue.withOpacity(0.80),
219 | );
220 | }
221 |
--------------------------------------------------------------------------------
/example/lib/main_row_super_with_fit_horizontally.dart:
--------------------------------------------------------------------------------
1 | import 'package:assorted_layout_widgets/assorted_layout_widgets.dart';
2 | import 'package:flutter/material.dart';
3 |
4 | void main() => runApp(const MaterialApp(home: Demo()));
5 |
6 | class Demo extends StatelessWidget {
7 | const Demo({super.key});
8 |
9 | @override
10 | Widget build(BuildContext context) {
11 | //
12 | return Scaffold(
13 | appBar: AppBar(title: const Text('RowSuper with FitHorizontally Example')),
14 | body: Center(
15 | child: SingleChildScrollView(
16 | child: Column(
17 | mainAxisSize: MainAxisSize.min,
18 | crossAxisAlignment: CrossAxisAlignment.start,
19 | children: [
20 | //
21 | const SizedBox(height: 10),
22 | //
23 | for (double width = 360; width >= 0.0; width -= 100)
24 | Column(children: [
25 | const SizedBox(height: 8),
26 | //
27 | // fitHorizontally: false
28 | Container(
29 | alignment: Alignment.centerLeft,
30 | width: width,
31 | height: 55,
32 | color: Colors.yellow[600],
33 | child: RowSuper(
34 | separator: separator(),
35 | outerDistance: 6.0,
36 | innerDistance: 12.0,
37 | fitHorizontally: false,
38 | children: [
39 | text1(),
40 | text2(),
41 | text3(),
42 | ],
43 | ),
44 | ),
45 | //
46 | // fitHorizontally: true
47 | // (shrinkLimit is the default: 67%)
48 | Container(
49 | alignment: Alignment.centerLeft,
50 | width: width,
51 | height: 55,
52 | color: Colors.yellow[500],
53 | child: RowSuper(
54 | separator: separator(),
55 | outerDistance: 6.0,
56 | innerDistance: 12.0,
57 | fitHorizontally: true,
58 | children: [
59 | text1(),
60 | text2(),
61 | text3(),
62 | ],
63 | ),
64 | ),
65 | // fitHorizontally: true
66 | // shrinkLimit: 0.0
67 | Container(
68 | alignment: Alignment.centerLeft,
69 | width: width,
70 | height: 55,
71 | color: Colors.yellow[300],
72 | child: RowSuper(
73 | separator: separator(),
74 | outerDistance: 6.0,
75 | innerDistance: 12.0,
76 | fitHorizontally: true,
77 | shrinkLimit: 0.0,
78 | children: [
79 | text1(),
80 | text2(),
81 | text3(),
82 | ],
83 | ),
84 | ),
85 | ]),
86 | //
87 | ],
88 | ),
89 | ),
90 | ),
91 | );
92 | }
93 |
94 | Container separator() => Container(width: 2, height: 50, color: Colors.black26);
95 |
96 | Text text1() => const Text(
97 | "So long",
98 | overflow: TextOverflow.fade,
99 | style: TextStyle(fontSize: 20, color: Colors.blue),
100 | maxLines: 1,
101 | softWrap: false,
102 | );
103 |
104 | Text text2() => const Text(
105 | "farewell",
106 | overflow: TextOverflow.fade,
107 | style: TextStyle(fontSize: 20, color: Colors.red),
108 | maxLines: 1,
109 | softWrap: false,
110 | );
111 |
112 | Text text3() => const Text(
113 | "auf Wiedersehen",
114 | overflow: TextOverflow.fade,
115 | style: TextStyle(fontSize: 20, color: Colors.red),
116 | maxLines: 1,
117 | softWrap: false,
118 | );
119 | }
120 |
--------------------------------------------------------------------------------
/example/lib/main_row_with_row_super_comparison.dart:
--------------------------------------------------------------------------------
1 | // ignore_for_file: deprecated_member_use
2 | import 'package:assorted_layout_widgets/assorted_layout_widgets.dart';
3 | import 'package:flutter/material.dart';
4 |
5 | void main() => runApp(const MaterialApp(home: Demo()));
6 |
7 | class Demo extends StatelessWidget {
8 | const Demo({super.key});
9 |
10 | @override
11 | Widget build(BuildContext context) {
12 | //
13 | return Scaffold(
14 | appBar: AppBar(title: const Text('Row × RowSuper Comparison')),
15 | body: Box(
16 | width: double.infinity,
17 | child: SingleChildScrollView(
18 | child: Column(
19 | crossAxisAlignment: CrossAxisAlignment.stretch,
20 | children: [
21 | //
22 | // ------------------
23 | //
24 | explanation("Row where cells are SMALLER that the available width:"),
25 | Row(children: [
26 | text("How"),
27 | text("are you all,"),
28 | text("my dearest friends?"),
29 | ]),
30 | //
31 | //
32 | explanation(
33 | "RowSuper with `fill:false` (the default) where cells are SMALLER that the available width. "
34 | "Similar to a Row:"),
35 | RowSuper(fill: false, children: [
36 | text("How"),
37 | text("are you all,"),
38 | text("my dearest friends?"),
39 | ]),
40 | //
41 | // ------------------
42 | //
43 | divider(),
44 | //
45 | explanation("Row where cells are SMALLER that the available width, but use Expanded. "
46 | "It fills the whole space, but cells have the same size:"),
47 | Row(children: [
48 | Expanded(child: text("How")),
49 | Expanded(child: text("are you,")),
50 | Expanded(child: text("my dear friend?")),
51 | ]),
52 | //
53 | //
54 | explanation(
55 | "RowSuper with `fill:true` where cells are SMALLER that the available width. "
56 | "It fills the whole space, and cells are proportional to their content width:"),
57 | RowSuper(fill: true, children: [
58 | text("How"),
59 | text("are you all,"),
60 | text("my dearest friends?"),
61 | ]),
62 | //
63 | // ------------------
64 | //
65 | divider(),
66 | //
67 | explanation("Row where cells are LARGER that the available width. "
68 | "It will overflow (and show the overflow warning):"),
69 | Row(children: [
70 | text("this is a very long text"),
71 | text("that surely won't fit the available space in a regular cell phone's screen."),
72 | ]),
73 | //
74 | explanation("RowSuper where cells are LARGER that the available width "
75 | "(it doesn't matter if `fill:false` or `true`). "
76 | "It fills the whole space, and cells are proportional to their content width:"),
77 | RowSuper(fill: false, children: [
78 | text("this is a long text"),
79 | text("that surely won't fit the available space in a regular cell phone's screen."),
80 | ]),
81 | //
82 | // ------------------
83 | //
84 | divider(),
85 | ],
86 | ),
87 | ),
88 | ),
89 | );
90 | }
91 |
92 | Column divider() => Column(
93 | children: [
94 | const SizedBox(height: 40),
95 | Container(color: Colors.black, height: 1, width: double.infinity),
96 | const SizedBox(height: 10),
97 | ],
98 | );
99 |
100 | Widget explanation(String text) => Padding(
101 | padding: const EdgeInsets.only(top: 30, left: 8.0, right: 15.0, bottom: 10),
102 | child: Text(text),
103 | );
104 |
105 | List texts() => [
106 | text("How"),
107 | text("are you all,"),
108 | text("my dearest friends?"),
109 | ];
110 |
111 | Widget text(String text) => Box.rand(
112 | padding: const Pad(top: 4.0, bottom: 4.0),
113 | child: Text(
114 | text,
115 | maxLines: 1,
116 | overflow: TextOverflow.ellipsis,
117 | style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w600),
118 | ),
119 | );
120 | }
121 |
--------------------------------------------------------------------------------
/example/lib/main_show_dialog_super.dart:
--------------------------------------------------------------------------------
1 | import 'package:assorted_layout_widgets/assorted_layout_widgets.dart';
2 | import 'package:flutter/material.dart';
3 |
4 | void main() => runApp(const MaterialApp(home: Demo()));
5 |
6 | class Demo extends StatelessWidget {
7 | const Demo({super.key});
8 |
9 | @override
10 | Widget build(BuildContext context) {
11 | //
12 | return Material(
13 | child: MaterialApp(
14 | home: Scaffold(
15 | appBar: AppBar(title: const Text('showDialogSuper Example')),
16 | body: const DemoApp(),
17 | ),
18 | ),
19 | );
20 | }
21 | }
22 |
23 | class DemoApp extends StatefulWidget {
24 | const DemoApp({super.key});
25 |
26 | @override
27 | State createState() => _DemoAppState();
28 | }
29 |
30 | class _DemoAppState extends State {
31 | int count = 1;
32 |
33 | @override
34 | Widget build(BuildContext context) {
35 | return Center(
36 | child: Column(
37 | mainAxisAlignment: MainAxisAlignment.center,
38 | children: [
39 | Expanded(child: Center(child: Text("The dialog has opened $count times."))),
40 | Expanded(
41 | child: Center(
42 | child: ElevatedButton(
43 | onPressed: () {
44 | showDialogSuper(
45 | context: context,
46 | builder: (context) {
47 | return AlertDialog(
48 | content: Text("This dialog has opened $count times."
49 | "\n\n"
50 | "The counter is incremented in the `onDismissed` callback."),
51 | actions: [
52 | ElevatedButton(
53 | onPressed: () {
54 | Navigator.pop(context, 1);
55 | },
56 | child: const Text("OK"),
57 | ),
58 | ElevatedButton(
59 | onPressed: () {
60 | Navigator.pop(context, 2);
61 | },
62 | child: const Text("CANCEL"),
63 | )
64 | ],
65 | );
66 | },
67 | onDismissed: (int? result) {
68 | if (result == 1) {
69 | print("Pressed the OK button.");
70 | } else if (result == 2) {
71 | print("Pressed the CANCEL button.");
72 | } else if (result == null) {
73 | print("Dismissed with BACK or tapping the barrier.");
74 | } else {
75 | throw AssertionError();
76 | }
77 | setState(() {
78 | count++;
79 | });
80 | });
81 | },
82 | child: const Text("Open Dialog"),
83 | ),
84 | ),
85 | ),
86 | const Expanded(child: Box()),
87 | ],
88 | ),
89 | );
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/example/lib/main_text_one_line.dart:
--------------------------------------------------------------------------------
1 | import 'package:assorted_layout_widgets/assorted_layout_widgets.dart';
2 | import 'package:flutter/material.dart';
3 |
4 | void main() => runApp(const MaterialApp(home: Demo()));
5 |
6 | class Demo extends StatelessWidget {
7 | const Demo({super.key});
8 |
9 | @override
10 | Widget build(BuildContext context) {
11 | //
12 | return Scaffold(
13 | appBar: AppBar(title: const Text('TextOneLine Example')),
14 | key: UniqueKey(), // Forces restart on hot reload.
15 | body: const SingleChildScrollView(
16 | child: Column(
17 | crossAxisAlignment: CrossAxisAlignment.start,
18 | children: [
19 | //
20 | // -------------------
21 | //
22 | SizedBox(height: 10),
23 | Text("Text with ELLIPSIS, maxLines: 1, softWrap: false",
24 | maxLines: 1,
25 | softWrap: false,
26 | overflow: TextOverflow.ellipsis,
27 | style: TextStyle(fontWeight: FontWeight.bold)),
28 | SizedBox(height: 5),
29 | Text("short: Lorem ipsum",
30 | maxLines: 1, softWrap: false, overflow: TextOverflow.ellipsis),
31 | SizedBox(height: 5),
32 | Text(
33 | "long: Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.",
34 | maxLines: 1,
35 | softWrap: false,
36 | overflow: TextOverflow.ellipsis),
37 | SizedBox(height: 5),
38 | Text(
39 | "long without spaces: This is a verylongtextwithoutanyspacesthatdemonstratestheproblemwegetwhentryingtousethenativetextwidget.",
40 | maxLines: 1,
41 | softWrap: false,
42 | overflow: TextOverflow.ellipsis),
43 | SizedBox(height: 40),
44 | //
45 | // -------------------
46 | //
47 | TextOneLine("TextOneLine with ELLIPSIS", style: TextStyle(fontWeight: FontWeight.bold)),
48 | SizedBox(height: 5),
49 | TextOneLine("short: Lorem ipsum"),
50 | SizedBox(height: 5),
51 | TextOneLine(
52 | "long: Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."),
53 | SizedBox(height: 5),
54 | TextOneLine(
55 | "long without spaces: This is a verylongtextwithoutanyspacesthatdemonstratestheproblemwegetwhentryingtousethenativetextwidget.",
56 | overflow: TextOverflow.ellipsis),
57 | SizedBox(height: 40),
58 | //
59 | // -------------------
60 | //
61 | TextOneLine("TextOneLine with FADE",
62 | overflow: TextOverflow.fade, style: TextStyle(fontWeight: FontWeight.bold)),
63 | SizedBox(height: 5),
64 | TextOneLine("short: Lorem ipsum", overflow: TextOverflow.fade),
65 | SizedBox(height: 5),
66 | TextOneLine(
67 | "long: Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.",
68 | overflow: TextOverflow.fade,
69 | ),
70 | SizedBox(height: 5),
71 | TextOneLine(
72 | "long without spaces: This is a verylongtextwithoutanyspacesthatdemonstratestheproblemwegetwhentryingtousethenativetextwidget.",
73 | overflow: TextOverflow.fade),
74 | SizedBox(height: 40),
75 | //
76 | // -------------------
77 | //
78 | TextOneLine("TextOneLine with CLIP",
79 | overflow: TextOverflow.clip, style: TextStyle(fontWeight: FontWeight.bold)),
80 | SizedBox(height: 5),
81 | TextOneLine("short: Lorem ipsum", overflow: TextOverflow.clip),
82 | SizedBox(height: 5),
83 | TextOneLine(
84 | "long: Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.",
85 | overflow: TextOverflow.clip,
86 | ),
87 | SizedBox(height: 5),
88 | TextOneLine(
89 | "long without spaces: This is a verylongtextwithoutanyspacesthatdemonstratestheproblemwegetwhentryingtousethenativetextwidget.",
90 | overflow: TextOverflow.clip),
91 | //
92 | // -------------------
93 | //
94 | SizedBox(height: 20),
95 | Divider(),
96 | SizedBox(height: 20),
97 | //
98 | Text("With letter-spacing: 0 - Text",
99 | maxLines: 1,
100 | softWrap: false,
101 | overflow: TextOverflow.clip,
102 | style: TextStyle(letterSpacing: 0)),
103 | TextOneLine("With letter-spacing: 0 - TextOneLine",
104 | overflow: TextOverflow.clip, style: TextStyle(letterSpacing: 0)),
105 | SizedBox(height: 10),
106 | //
107 | Text("With letter-spacing: 1.1 - Text",
108 | maxLines: 1,
109 | softWrap: false,
110 | overflow: TextOverflow.clip,
111 | style: TextStyle(letterSpacing: 1.1)),
112 | TextOneLine("With letter-spacing: 1.1 - TextOneLine",
113 | overflow: TextOverflow.clip, style: TextStyle(letterSpacing: 1.1)),
114 | SizedBox(height: 10),
115 | Text("With letter-spacing: 2 - Text",
116 | maxLines: 1,
117 | softWrap: false,
118 | overflow: TextOverflow.clip,
119 | style: TextStyle(letterSpacing: 2)),
120 | TextOneLine("With letter-spacing: 2 - TextOneLine",
121 | overflow: TextOverflow.clip, style: TextStyle(letterSpacing: 2)),
122 | ],
123 | ),
124 | ),
125 | );
126 | }
127 | }
128 |
--------------------------------------------------------------------------------
/example/lib/main_wrap_super.dart:
--------------------------------------------------------------------------------
1 | // ignore_for_file: deprecated_member_use
2 | import 'package:assorted_layout_widgets/assorted_layout_widgets.dart';
3 | import 'package:flutter/material.dart';
4 |
5 | void main() => runApp(const MaterialApp(home: Demo()));
6 |
7 | class Demo extends StatelessWidget {
8 | const Demo({super.key});
9 |
10 | @override
11 | Widget build(BuildContext context) => Scaffold(
12 | appBar: AppBar(title: const Text('WrapSuper Example')),
13 | body: Container(
14 | color: Colors.grey[800],
15 | alignment: Alignment.center,
16 | child: Container(
17 | width: 200,
18 | color: Colors.grey[300],
19 | child: WrapSuper(
20 | alignment: WrapSuperAlignment.center,
21 | wrapType: WrapType.balanced,
22 | spacing: 5.0,
23 | lineSpacing: 2.0,
24 | children: [
25 | const Box(color: Colors.black, width: 200, height: 2),
26 | const Box.r(width: 100 - 5.0, height: 20),
27 | const Box.g(width: 100, height: 20),
28 | const Box(color: Colors.black, width: 200, height: 2),
29 | const Box.r(width: 60, height: 20),
30 | const Box.g(width: 60, height: 20),
31 | const Box.b(width: 60, height: 20),
32 | const Box.y(width: 60, height: 20),
33 | const Box(color: Colors.black, width: 200, height: 2),
34 | const Box.r(width: 50, height: 30),
35 | const Box.g(width: 140, height: 50),
36 | const Box.b(width: 180, height: 70),
37 | const Box.y(width: 40, height: 25),
38 | const Box.r(width: 50, height: 25),
39 | const Box.g(width: 60, height: 25),
40 | const Box.b(width: 80, height: 25),
41 | const Box.y(width: 120, height: 30),
42 | const Box.r(width: 5, height: 40),
43 | const Box(color: Colors.black, width: 200, height: 2),
44 | ...List.filled(200 ~/ (4 + 5), const Box.g(width: 4, height: 5)),
45 | ],
46 | ),
47 | ),
48 | ),
49 | );
50 | }
51 |
--------------------------------------------------------------------------------
/example/lib/main_wrap_super_fit.dart:
--------------------------------------------------------------------------------
1 | import 'package:assorted_layout_widgets/assorted_layout_widgets.dart';
2 | import 'package:flutter/material.dart';
3 |
4 | void main() => runApp(const MaterialApp(home: Demo()));
5 |
6 | class Demo extends StatelessWidget {
7 | const Demo({super.key});
8 |
9 | //
10 | static const divider =
11 | Box(color: Colors.black, width: double.infinity, height: 2.0);
12 |
13 | @override
14 | Widget build(BuildContext context) {
15 | return Scaffold(
16 | appBar: AppBar(title: const Text('WrapSuper WrapFit Example')),
17 | body: Container(
18 | color: const Color(0xFFEEEEEE),
19 | alignment: Alignment.center,
20 | child: SingleChildScrollView(
21 | child: ColumnSuper(
22 | innerDistance: 25.0,
23 | children: [
24 | //
25 | divider,
26 | //
27 | _title('A bar of 400 pixels.'),
28 | _wrap(WrapFit.min, [box(400, 300)]),
29 | _wrap(WrapFit.divided, [box(400, 300)]),
30 | _wrap(WrapFit.proportional, [box(400, 300)]),
31 | _wrap(WrapFit.larger, [box(400, 300)]),
32 | //
33 | divider,
34 | //
35 | _title('A bar of 230 pixels.'),
36 | _wrap(WrapFit.min, [box(230, 230)]),
37 | _wrap(WrapFit.divided, [box(230, 300)]),
38 | _wrap(WrapFit.proportional, [box(230, 300)]),
39 | _wrap(WrapFit.larger, [box(230, 300)]),
40 | //
41 | divider,
42 | //
43 | _title('A bar of 140 pixels and another of 220.'),
44 | _wrap(WrapFit.min, [box(140, 140), box(220, 220)]),
45 | _wrap(WrapFit.divided, [box(140, 300), box(220, 300)]),
46 | _wrap(WrapFit.proportional, [box(140, 300), box(220, 300)]),
47 | _wrap(WrapFit.larger, [box(140, 300), box(220, 300)]),
48 | //
49 | divider,
50 | //
51 | _title('Four bars: 200, 120, 60 and 80 pixels.'),
52 | _wrap(WrapFit.min,
53 | [box(200, 200), box(120, 120), box(60, 60), box(80, 80)]),
54 | _wrap(WrapFit.divided,
55 | [box(200, 300), box(120, 100), box(60, 100), box(80, 100)]),
56 | _wrap(WrapFit.proportional, [
57 | box(200, 300),
58 | box(120, (120 / (120 + 60 + 80) * 300).toInt()),
59 | box(60, (60 / (120 + 60 + 80) * 300).toInt()),
60 | box(80, (80 / (120 + 60 + 80) * 300).toInt())
61 | ]),
62 | _wrap(
63 | WrapFit.larger,
64 | [box(200, 300), box(120, 120), box(60, 90), box(80, 90)],
65 | ),
66 | //
67 | divider,
68 | //
69 | ],
70 | ),
71 | ),
72 | ),
73 | );
74 | }
75 |
76 | Widget _title(String text) => Text(
77 | '$text\nAvailable width is 300:',
78 | textAlign: TextAlign.center,
79 | );
80 |
81 | Widget _wrap(WrapFit wrapFit, List children) {
82 | return Column(
83 | children: [
84 | Text(wrapFit.toString()),
85 | const Box(height: 8.0),
86 | Box(
87 | color: Colors.purple,
88 | padding: const Pad(all: 3.0),
89 | child: Box(
90 | width: 300,
91 | color: Colors.purple,
92 | child: WrapSuper(
93 | wrapFit: wrapFit,
94 | spacing: 3.0,
95 | lineSpacing: 9.0,
96 | children: children,
97 | ),
98 | ),
99 | ),
100 | ],
101 | );
102 | }
103 |
104 | Widget box(double width, int newWidth) => Box(
105 | color: Colors.lightGreen,
106 | width: width,
107 | height: 30,
108 | child: Center(child: Text("${width.toInt()} ➜ $newWidth")),
109 | );
110 | }
111 |
--------------------------------------------------------------------------------
/example/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: example
2 | description: Examples for assorted_layout_widgets
3 | publish_to: "none"
4 | version: 1.0.0+1
5 |
6 | environment:
7 | sdk: '>=3.2.0 <4.0.0'
8 |
9 | dependencies:
10 | assorted_layout_widgets:
11 | path: ../
12 | flutter:
13 | sdk: flutter
14 |
15 | dev_dependencies:
16 | flutter_test:
17 | sdk: flutter
18 | flutter_lints: ^3.0.1
19 |
20 | flutter:
21 | uses-material-design: true
22 |
--------------------------------------------------------------------------------
/lib/assorted_layout_widgets.dart:
--------------------------------------------------------------------------------
1 | export "src/box.dart";
2 | export "src/box_animating_width.dart";
3 | export "src/button.dart";
4 | export "src/button_bar_super.dart";
5 | export "src/capture_gestures.dart";
6 | export "src/circle_button.dart";
7 | export "src/column_super.dart";
8 | export "src/delayed.dart";
9 | export "src/detect_scroll.dart";
10 | export "src/fit_horizontally.dart";
11 | export "src/global_keys.dart";
12 | export "src/keyboard_dismiss.dart";
13 | export "src/mask_function_text_input_formatter.dart";
14 | export "src/non_uniform_outline_input_border.dart";
15 | export "src/non_uniform_rounded_rectangle_border.dart";
16 | export "src/normalized_overflow_box.dart";
17 | export "src/pad.dart";
18 | export "src/row_super.dart";
19 | export "src/scroll_shadow.dart";
20 | export "src/show_dialog_super.dart";
21 | export "src/side_by_side.dart";
22 | export "src/text_one_line.dart";
23 | export "src/time_builder.dart";
24 | export "src/wrap_super.dart";
25 |
--------------------------------------------------------------------------------
/lib/src/box_animating_width.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | /// This widget is meant only to be used for layout demonstrations of other widgets.
4 | ///
5 | /// The child widget will be wrapped in a container that animates its width,
6 | /// between [maxWidth] and [minWidth], with the given [border] around it.
7 | /// The animation will repeat indefinitely. It takes [moveDuration] to move from
8 | /// [maxWidth] to [minWidth] and vice versa. It will hold at [maxWidth] for
9 | /// [maxHoldDuration] and at [minWidth] for [minHoldDuration].
10 | ///
11 | class BoxAnimatingWidth extends StatefulWidget {
12 | //
13 | final Widget child;
14 | final double minWidth;
15 | final double? maxWidth;
16 | final Duration moveDuration;
17 | final Duration maxHoldDuration;
18 | final Duration minHoldDuration;
19 | final Border? border;
20 |
21 | const BoxAnimatingWidth({
22 | Key? key,
23 | required this.child,
24 | this.minWidth = 80.0,
25 | this.maxWidth,
26 | this.moveDuration = const Duration(milliseconds: 3500),
27 | this.maxHoldDuration = const Duration(seconds: 1),
28 | this.minHoldDuration = const Duration(seconds: 1),
29 | this.border,
30 | }) : super(key: key);
31 |
32 | @override
33 | State createState() => _BoxAnimatingWidthState();
34 | }
35 |
36 | class _BoxAnimatingWidthState extends State
37 | with SingleTickerProviderStateMixin {
38 | late final AnimationController _controller;
39 |
40 | @override
41 | void initState() {
42 | super.initState();
43 |
44 | // Total duration is the sum of all durations.
45 | final totalDuration =
46 | widget.moveDuration * 2 + widget.maxHoldDuration + widget.minHoldDuration;
47 |
48 | _controller = AnimationController(
49 | vsync: this,
50 | duration: totalDuration,
51 | );
52 |
53 | _controller.repeat();
54 | }
55 |
56 | @override
57 | void dispose() {
58 | _controller.dispose();
59 | super.dispose();
60 | }
61 |
62 | @override
63 | Widget build(BuildContext context) {
64 | return LayoutBuilder(
65 | builder: (context, constraints) {
66 | double parentWidth = constraints.maxWidth;
67 |
68 | final Animation _widthAnimation = TweenSequence([
69 | TweenSequenceItem(
70 | tween:
71 | Tween(begin: widget.maxWidth ?? parentWidth, end: widget.minWidth)
72 | .chain(CurveTween(curve: Curves.easeInOut)),
73 | weight: widget.moveDuration.inMilliseconds.toDouble(),
74 | ),
75 | TweenSequenceItem(
76 | tween: ConstantTween(widget.minWidth),
77 | weight: widget.minHoldDuration.inMilliseconds.toDouble(),
78 | ),
79 | TweenSequenceItem(
80 | tween:
81 | Tween(begin: widget.minWidth, end: widget.maxWidth ?? parentWidth)
82 | .chain(CurveTween(curve: Curves.easeInOut)),
83 | weight: widget.moveDuration.inMilliseconds.toDouble(),
84 | ),
85 | TweenSequenceItem(
86 | tween: ConstantTween(widget.maxWidth ?? parentWidth),
87 | weight: widget.maxHoldDuration.inMilliseconds.toDouble(),
88 | ),
89 | ]).animate(_controller);
90 |
91 | return AnimatedBuilder(
92 | animation: _widthAnimation,
93 | builder: (context, child) {
94 | return Container(
95 | width: _widthAnimation.value,
96 | constraints: const BoxConstraints(minHeight: 10),
97 | decoration: BoxDecoration(
98 | border: widget.border ?? Border.all(color: Colors.black, width: 1),
99 | ),
100 | child: widget.child,
101 | );
102 | },
103 | );
104 | },
105 | );
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/lib/src/button.dart:
--------------------------------------------------------------------------------
1 | import "dart:async";
2 |
3 | import "package:flutter/cupertino.dart";
4 | import "package:flutter/material.dart";
5 |
6 | typedef ButtonBuilder = Widget Function({
7 | /// True when the button is tapped-down.
8 | required bool isPressed,
9 | });
10 |
11 | /// Transforms any widget in a button, with visual feedback in the onPointerDown.
12 | /// The widget must be created with a [builder] of type [ButtonBuilder], which provides an
13 | /// [isPressed] boolean to indicate whether the button is pressed or not.
14 | ///
15 | /// Thus, the widget can change its look according to these values.
16 | ///
17 | /// There are 3 possibilities to detect gestures:
18 | ///
19 | /// 1) Use the [onTap] parameter.
20 | ///
21 | /// 2) The widget itself can contain a [GestureDetector].
22 | ///
23 | /// 3) The Button can be inside a parent that detects gestures. Even with a null [onTap], the look
24 | /// still changes when you touch the button. This allows the button to be used inside other widgets
25 | /// that detect gestures. Note that [isPressed] is changed immediately as soon as the user touches
26 | /// the button, through a listener, which is faster than GestureDetector (which has a delay to
27 | /// differentiate between the various types of gestures).
28 | ///
29 | class Button extends StatefulWidget {
30 | //
31 | static const delayMillis = 75;
32 |
33 | final ButtonBuilder builder;
34 | final VoidCallback? onTap;
35 | final VoidCallback? onDragUp;
36 |
37 | /// You should pass delay=true only when the widget is inside a scrollable. This makes the button
38 | /// color change wait a few milliseconds (for when the user actually wants to start a scroll and
39 | /// not press the button).
40 | final bool delay;
41 |
42 | /// The minimum duration you want the button to show it was tapped.
43 | final Duration? minVisualTapDuration;
44 |
45 | /// The button does not allow calling [onTap] more than once per [tapThrottle]. Note: Visually it
46 | /// may appear to respond, but [onTap] is not called. Note: If [tapThrottle] doesn't seem to be
47 | /// working, check that you're not accidentally calling initState. Obviously, initState resets
48 | /// the time count.
49 | final Duration? tapThrottle;
50 |
51 | /// If [disable] is true, the [onTap] and [onDragUp] won't work.
52 | final bool disable;
53 |
54 | final EdgeInsetsGeometry? clickAreaMargin;
55 |
56 | final Color colorOfClickableArea;
57 |
58 | const Button({
59 | Key? key,
60 | required this.builder,
61 | required this.onTap,
62 | bool? disable,
63 | this.onDragUp,
64 | this.delay = false,
65 | this.minVisualTapDuration,
66 | this.tapThrottle,
67 | this.clickAreaMargin,
68 | bool debugShowClickableArea = false,
69 | }) : disable = disable ?? false,
70 | colorOfClickableArea =
71 | debugShowClickableArea ? const Color(0xBBFF0000) : const Color(0x00000000),
72 | super(key: key);
73 |
74 | @override
75 | _ButtonState createState() => _ButtonState();
76 | }
77 |
78 | class _ButtonState extends State