From 4206df8fb660730e769508cbf35015e74057ba69 Mon Sep 17 00:00:00 2001 From: Max Onishi Date: Mon, 3 May 2021 15:03:25 +1000 Subject: [PATCH 1/2] null safety --- .gitignore | 1 + CHANGELOG.md | 9 +- README.md | 4 +- example/android/app/build.gradle | 12 +- .../android/app/src/main/AndroidManifest.xml | 19 +- .../reorderablesexample/MainActivity.java | 12 +- example/android/build.gradle | 2 +- example/android/gradle.properties | 17 +- .../gradle/wrapper/gradle-wrapper.properties | 4 +- example/ios/Runner.xcodeproj/project.pbxproj | 21 +- .../contents.xcworkspacedata | 2 +- example/lib/column_example1.dart | 18 +- example/lib/column_example2.dart | 15 +- example/lib/main.dart | 57 +-- example/lib/nested_wrap_example.dart | 8 +- example/lib/row_example.dart | 2 +- example/lib/sliver_example.dart | 26 +- example/lib/table_example.dart | 2 +- example/lib/wrap_example.dart | 2 +- example/pubspec.yaml | 6 +- example/web/favicon.png | Bin 0 -> 917 bytes example/web/icons/Icon-192.png | Bin 0 -> 5292 bytes example/web/icons/Icon-512.png | Bin 0 -> 8252 bytes example/web/index.html | 45 ++ example/web/manifest.json | 23 + lib/generated/i18n.dart | 126 ------ lib/src/rendering/tabluar_flex.dart | 225 ++++------ lib/src/rendering/transitions.dart | 11 +- lib/src/rendering/wrap.dart | 118 ++---- lib/src/widgets/basic.dart | 7 +- lib/src/widgets/passthrough_overlay.dart | 113 +++-- lib/src/widgets/reorderable_flex.dart | 238 ++++++----- lib/src/widgets/reorderable_mixin.dart | 4 +- lib/src/widgets/reorderable_sliver.dart | 192 +++++---- lib/src/widgets/reorderable_table.dart | 57 +-- lib/src/widgets/reorderable_widget.dart | 12 +- lib/src/widgets/reorderable_wrap.dart | 393 +++++++----------- lib/src/widgets/tabluar_flex.dart | 26 +- lib/src/widgets/transitions.dart | 6 +- lib/src/widgets/wrap.dart | 8 +- pubspec.yaml | 4 +- 41 files changed, 815 insertions(+), 1032 deletions(-) create mode 100644 example/web/favicon.png create mode 100644 example/web/icons/Icon-192.png create mode 100644 example/web/icons/Icon-512.png create mode 100644 example/web/index.html create mode 100644 example/web/manifest.json delete mode 100644 lib/generated/i18n.dart diff --git a/.gitignore b/.gitignore index 47e0b4d..62a5b66 100644 --- a/.gitignore +++ b/.gitignore @@ -59,6 +59,7 @@ build/ **/ios/Flutter/Generated.xcconfig **/ios/Flutter/app.flx **/ios/Flutter/app.zip +**/ios/Flutter/flutter_export_environment.sh **/ios/Flutter/flutter_assets/ **/ios/ServiceDefinitions.json **/ios/Runner/GeneratedPluginRegistrant.* diff --git a/CHANGELOG.md b/CHANGELOG.md index 40e4714..b5849cb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [0.4.1] - 11 April 2021. +* Addresses Issue [#111](https://github.com/hanshengchiu/reorderables/issues/111). Resolves ReorderableSliverList ScrollController conflict (thanks [qAison](https://github.com/qAison)). + +## [0.4.0] - 24 March 2021. + +* Initial Null-Safety release. + ## [0.3.2] - 10 March 2020. * Fix health suggestions. @@ -5,7 +12,7 @@ * Supports making individual child non-reorderable. See ReorderableColumn example 1. ## [0.3.0] - 10 Jan 2020. -* Fix: Bad type in onLeave +* Fix: Bad type in onLeave ## [0.2.12] - 22 June 2019. * Removed dependency of FlutterErrorDetails and other ErrorXXX classes. diff --git a/README.md b/README.md index 0bc4e77..26c6bce 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@ -** Kindly submit PR if you encounter issues and please make sure you're using stable channel releases. Updates might be slow... +** Kindly submit PR if you encounter issues and please make sure you're using stable channel releases.
+** Maintaining open source software ain't easy. If you've commercially used this software, please consider [support](https://www.buymeacoffee.com/q5gkeA4t2). # reorderables [![pub package](https://img.shields.io/pub/v/reorderables.svg)](https://pub.dartlang.org/packages/reorderables) [![Awesome Flutter](https://img.shields.io/badge/Awesome-Flutter-blue.svg?longCache=true&style=flat-square)](https://github.com/Solido/awesome-flutter) [![Buy Me A Coffee](https://img.shields.io/badge/Donate-Buy%20Me%20A%20Coffee-yellow.svg)](https://www.buymeacoffee.com/q5gkeA4t2) -[![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=2L56VGH228QJE) Various reorderable, a.k.a. drag and drop, Flutter widgets, including reorderable table, row, column, wrap, and sliver list, that make their children draggable and diff --git a/example/android/app/build.gradle b/example/android/app/build.gradle index ca7fe59..3703fd4 100644 --- a/example/android/app/build.gradle +++ b/example/android/app/build.gradle @@ -25,7 +25,7 @@ apply plugin: 'com.android.application' apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" android { - compileSdkVersion 28 + compileSdkVersion 30 lintOptions { disable 'InvalidPackage' @@ -34,11 +34,11 @@ android { defaultConfig { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId "com.example.reorderablesexample" - minSdkVersion 16 - targetSdkVersion 28 + minSdkVersion 23 + targetSdkVersion 30 versionCode flutterVersionCode.toInteger() versionName flutterVersionName - testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner' } buildTypes { @@ -56,6 +56,6 @@ flutter { dependencies { testImplementation 'junit:junit:4.12' - androidTestImplementation 'com.android.support.test:runner:1.0.2' - androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' + androidTestImplementation 'androidx.test.ext:junit:1.1.2' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' } diff --git a/example/android/app/src/main/AndroidManifest.xml b/example/android/app/src/main/AndroidManifest.xml index 7d46aa3..e19ed50 100644 --- a/example/android/app/src/main/AndroidManifest.xml +++ b/example/android/app/src/main/AndroidManifest.xml @@ -7,15 +7,13 @@ --> - + android:icon="@mipmap/ic_launcher" + android:allowBackup="false"> + - - diff --git a/example/android/app/src/main/java/com/example/reorderablesexample/MainActivity.java b/example/android/app/src/main/java/com/example/reorderablesexample/MainActivity.java index dd9ced6..ada12b8 100644 --- a/example/android/app/src/main/java/com/example/reorderablesexample/MainActivity.java +++ b/example/android/app/src/main/java/com/example/reorderablesexample/MainActivity.java @@ -1,13 +1,5 @@ package com.example.reorderablesexample; -import android.os.Bundle; -import io.flutter.app.FlutterActivity; -import io.flutter.plugins.GeneratedPluginRegistrant; +import io.flutter.embedding.android.FlutterActivity; -public class MainActivity extends FlutterActivity { - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - GeneratedPluginRegistrant.registerWith(this); - } -} +public class MainActivity extends FlutterActivity { } diff --git a/example/android/build.gradle b/example/android/build.gradle index bb8a303..fab3c2e 100644 --- a/example/android/build.gradle +++ b/example/android/build.gradle @@ -5,7 +5,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:3.2.1' + classpath 'com.android.tools.build:gradle:4.1.3' } } diff --git a/example/android/gradle.properties b/example/android/gradle.properties index 7be3d8b..8d7e07a 100644 --- a/example/android/gradle.properties +++ b/example/android/gradle.properties @@ -1,2 +1,17 @@ -org.gradle.jvmargs=-Xmx1536M +## For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html +# +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +# Default value: -Xmx1024m -XX:MaxPermSize=256m +# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 +# +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true +#Sat Mar 20 19:11:05 EDT 2021 +android.enableJetifier=true android.enableR8=true +android.useAndroidX=true +org.gradle.jvmargs=-Xmx1536M diff --git a/example/android/gradle/wrapper/gradle-wrapper.properties b/example/android/gradle/wrapper/gradle-wrapper.properties index 2819f02..8413cf2 100644 --- a/example/android/gradle/wrapper/gradle-wrapper.properties +++ b/example/android/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Fri Jun 23 08:50:38 CEST 2017 +#Sat Mar 20 19:06:23 EDT 2021 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/example/ios/Runner.xcodeproj/project.pbxproj index 5ca2738..3c3e6a0 100644 --- a/example/ios/Runner.xcodeproj/project.pbxproj +++ b/example/ios/Runner.xcodeproj/project.pbxproj @@ -8,12 +8,7 @@ /* Begin PBXBuildFile section */ 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; - 2D5378261FAA1A9400D5DBA9 /* flutter_assets in Resources */ = {isa = PBXBuildFile; fileRef = 2D5378251FAA1A9400D5DBA9 /* flutter_assets */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; - 3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; }; - 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; - 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; }; - 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB21CF90195004384FC /* Debug.xcconfig */; }; 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */; }; 97C146F31CF9000F007C117D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C146F21CF9000F007C117D /* main.m */; }; @@ -29,8 +24,6 @@ dstPath = ""; dstSubfolderSpec = 10; files = ( - 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */, - 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */, ); name = "Embed Frameworks"; runOnlyForDeploymentPostprocessing = 0; @@ -40,15 +33,12 @@ /* Begin PBXFileReference section */ 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; - 2D5378251FAA1A9400D5DBA9 /* flutter_assets */ = {isa = PBXFileReference; lastKnownFileType = folder; name = flutter_assets; path = Flutter/flutter_assets; sourceTree = SOURCE_ROOT; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; - 3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; - 9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = ""; }; 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; 97C146F21CF9000F007C117D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; @@ -62,8 +52,6 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */, - 3B80C3941E831B6300D905FE /* App.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -73,10 +61,7 @@ 9740EEB11CF90186004384FC /* Flutter */ = { isa = PBXGroup; children = ( - 2D5378251FAA1A9400D5DBA9 /* flutter_assets */, - 3B80C3931E831B6300D905FE /* App.framework */, 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, - 9740EEBA1CF902C7004384FC /* Flutter.framework */, 9740EEB21CF90195004384FC /* Debug.xcconfig */, 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, 9740EEB31CF90195004384FC /* Generated.xcconfig */, @@ -190,7 +175,6 @@ 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */, 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, - 2D5378261FAA1A9400D5DBA9 /* flutter_assets in Resources */, 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -210,7 +194,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin"; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; }; 9740EEB61CF901F6004384FC /* Run Script */ = { isa = PBXShellScriptBuildPhase; @@ -263,7 +247,6 @@ /* Begin XCBuildConfiguration section */ 249021D3217E4FDB00AE95B9 /* Profile */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; @@ -335,7 +318,6 @@ }; 97C147031CF9000F007C117D /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; @@ -389,7 +371,6 @@ }; 97C147041CF9000F007C117D /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; diff --git a/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata index 1d526a1..919434a 100644 --- a/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ b/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -2,6 +2,6 @@ + location = "self:"> diff --git a/example/lib/column_example1.dart b/example/lib/column_example1.dart index ed9e476..5c508fb 100644 --- a/example/lib/column_example1.dart +++ b/example/lib/column_example1.dart @@ -7,7 +7,7 @@ class ColumnExample1 extends StatefulWidget { } class _ColumnExample1State extends State { - List _rows; + late List _rows; @override void initState() { @@ -18,7 +18,11 @@ class _ColumnExample1State extends State { (int index) => ReorderableWidget( reorderable: true, key: ValueKey(index), - child: Text('This is row $index', textScaleFactor: 1.5), + child: Container( + width: double.infinity, + child: Align( + alignment: Alignment.centerLeft, + child: Text('This is row $index', textScaleFactor: 1.5))), )); _rows += [ @@ -34,7 +38,12 @@ class _ColumnExample1State extends State { (int index) => ReorderableWidget( reorderable: true, key: ValueKey(11 + index), - child: Text('This is row $index', textScaleFactor: 1.5), + child: Container( + width: double.infinity, + child: Align( + alignment: Alignment.centerLeft, + child: Text('This is row $index', textScaleFactor: 1.5)), + ), )); } @@ -55,7 +64,8 @@ class _ColumnExample1State extends State { onReorder: _onReorder, onNoReorder: (int index) { //this callback is optional - debugPrint('${DateTime.now().toString().substring(5, 22)} reorder cancelled. index:$index'); + debugPrint( + '${DateTime.now().toString().substring(5, 22)} reorder cancelled. index:$index'); }, ); } diff --git a/example/lib/column_example2.dart b/example/lib/column_example2.dart index 93e8922..6ffd4a5 100644 --- a/example/lib/column_example2.dart +++ b/example/lib/column_example2.dart @@ -1,5 +1,4 @@ import 'package:flutter/material.dart'; - import 'package:reorderables/reorderables.dart'; class ColumnExample2 extends StatefulWidget { @@ -8,15 +7,20 @@ class ColumnExample2 extends StatefulWidget { } class _ColumnExample2State extends State { - List _rows; + late List _rows; @override void initState() { super.initState(); _rows = List.generate( 10, - (int index) => Text('This is row $index', - key: ValueKey(index), textScaleFactor: 1.5)); + (int index) => Container( + key: ValueKey(index), + width: double.infinity, + child: Center( + child: Text('This is row $index', textScaleFactor: 1.5), + ), + )); } @override @@ -36,7 +40,8 @@ class _ColumnExample2State extends State { onReorder: _onReorder, onNoReorder: (int index) { //this callback is optional - debugPrint('${DateTime.now().toString().substring(5, 22)} reorder cancelled. index:$index'); + debugPrint( + '${DateTime.now().toString().substring(5, 22)} reorder cancelled. index:$index'); }, )); diff --git a/example/lib/main.dart b/example/lib/main.dart index 442d55f..5de16e4 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -1,12 +1,12 @@ import 'package:flutter/material.dart'; -import './table_example.dart'; -import './wrap_example.dart'; -import './nested_wrap_example.dart'; import './column_example1.dart'; import './column_example2.dart'; +import './nested_wrap_example.dart'; import './row_example.dart'; import './sliver_example.dart'; +import './table_example.dart'; +import './wrap_example.dart'; void main() => runApp(MyApp()); @@ -22,7 +22,7 @@ class MyApp extends StatelessWidget { } class MyHomePage extends StatefulWidget { - MyHomePage({Key key, this.title}) : super(key: key); + MyHomePage({Key? key, required this.title}) : super(key: key); // This widget is the home page of your application. It is stateful, meaning // that it has a State object (defined below) that contains fields that affect @@ -62,37 +62,42 @@ class _MyHomePageState extends State { ), body: _examples[_currentIndex], bottomNavigationBar: BottomNavigationBar( - currentIndex: _currentIndex, // this will be set when a new tab is tapped + fixedColor: _bottomNavigationColor, + showSelectedLabels: true, + showUnselectedLabels: false, + currentIndex: _currentIndex, + // this will be set when a new tab is tapped // type: BottomNavigationBarType.fixed, items: [ BottomNavigationBarItem( - icon: Icon(Icons.grid_on, color: _bottomNavigationColor), - title: Text('ReroderableTable', maxLines: 2, style: TextStyle(color: _bottomNavigationColor)), - ), + icon: Icon(Icons.grid_on, color: _bottomNavigationColor), + tooltip: "ReorderableTable", + label: "Table"), BottomNavigationBarItem( - icon: Icon(Icons.apps, color: _bottomNavigationColor), - title: Text('ReroderableWrap', maxLines: 2, style: TextStyle(color: _bottomNavigationColor)), - ), + icon: Icon(Icons.apps, color: _bottomNavigationColor), + tooltip: "ReorderableWrap", + label: "Wrap"), BottomNavigationBarItem( - icon: Icon(Icons.view_quilt, color: _bottomNavigationColor), - title: Text('Nested ReroderableWrap', maxLines: 3, style: TextStyle(color: _bottomNavigationColor)), - ), + icon: Icon(Icons.view_quilt, color: _bottomNavigationColor), + tooltip: 'Nested ReroderableWrap', + label: "Nested"), BottomNavigationBarItem( - icon: Icon(Icons.more_vert, color: _bottomNavigationColor), - title: Text('ReroderableColumn 1', maxLines: 2, style: TextStyle(color: _bottomNavigationColor)) - ), + icon: Icon(Icons.more_vert, color: _bottomNavigationColor), + tooltip: "ReorderableColumn 1", + label: "Column 1"), BottomNavigationBarItem( - icon: Icon(Icons.more_vert, color: _bottomNavigationColor), - title: Text('ReroderableColumn 2', maxLines: 2, style: TextStyle(color: _bottomNavigationColor)) - ), + icon: Icon(Icons.more_vert, color: _bottomNavigationColor), + tooltip: "ReroderableColumn 2", + label: "Column 2"), BottomNavigationBarItem( - icon: Icon(Icons.more_horiz, color: _bottomNavigationColor), - title: Text('ReroderableRow', maxLines: 2, style: TextStyle(color: _bottomNavigationColor)) - ), + icon: Icon(Icons.more_horiz, color: _bottomNavigationColor), + tooltip: "ReorderableRow", + label: "Row"), BottomNavigationBarItem( - icon: Icon(Icons.calendar_view_day, color: _bottomNavigationColor), - title: Text('ReroderableSliverList', maxLines: 2, style: TextStyle(color: _bottomNavigationColor)) - ), + icon: + Icon(Icons.calendar_view_day, color: _bottomNavigationColor), + tooltip: "ReroderableSliverList", + label: "SliverList"), ], onTap: (int index) { setState(() { diff --git a/example/lib/nested_wrap_example.dart b/example/lib/nested_wrap_example.dart index bff76c8..e1b4f21 100644 --- a/example/lib/nested_wrap_example.dart +++ b/example/lib/nested_wrap_example.dart @@ -4,14 +4,14 @@ import 'package:reorderables/reorderables.dart'; class NestedWrapExample extends StatefulWidget { NestedWrapExample({ - Key key, + Key? key, this.depth = 0, this.valuePrefix = '', this.color, }) : super(key: key); final int depth; final String valuePrefix; - final Color color; + final Color? color; final List _tiles = []; @override @@ -20,8 +20,8 @@ class NestedWrapExample extends StatefulWidget { class _NestedWrapExampleState extends State { // List _tiles; - Color _color; - Color _colorBrighter; + Color? _color; + Color? _colorBrighter; @override void initState() { diff --git a/example/lib/row_example.dart b/example/lib/row_example.dart index 2054928..7872509 100644 --- a/example/lib/row_example.dart +++ b/example/lib/row_example.dart @@ -8,7 +8,7 @@ class RowExample extends StatefulWidget { } class _RowExampleState extends State { - List _columns; + late List _columns; @override void initState() { diff --git a/example/lib/sliver_example.dart b/example/lib/sliver_example.dart index 14087c7..d311d94 100644 --- a/example/lib/sliver_example.dart +++ b/example/lib/sliver_example.dart @@ -1,5 +1,4 @@ import 'package:flutter/material.dart'; - import 'package:reorderables/reorderables.dart'; class SliverExample extends StatefulWidget { @@ -8,14 +7,19 @@ class SliverExample extends StatefulWidget { } class _SliverExampleState extends State { - List _rows; + late List _rows; @override void initState() { super.initState(); - _rows = List.generate(50, - (int index) => Text('This is sliver child $index', textScaleFactor: 2) - ); + _rows = List.generate( + 50, + (int index) => Container( + width: double.infinity, + child: Align( + alignment: Alignment.centerLeft, + child: + Text('This is sliver child $index', textScaleFactor: 2)))); } @override @@ -26,9 +30,11 @@ class _SliverExampleState extends State { _rows.insert(newIndex, row); }); } + // Make sure there is a scroll controller attached to the scroll view that contains ReorderableSliverList. // Otherwise an error will be thrown. - ScrollController _scrollController = PrimaryScrollController.of(context) ?? ScrollController(); + ScrollController _scrollController = + PrimaryScrollController.of(context) ?? ScrollController(); return CustomScrollView( // A ScrollController must be included in CustomScrollView, otherwise @@ -40,7 +46,7 @@ class _SliverExampleState extends State { flexibleSpace: FlexibleSpaceBar( title: Text('ReorderableSliverList'), background: Image.network( - 'https://upload.wikimedia.org/wikipedia/commons/thumb/6/68/Yushan' + 'https://upload.wikimedia.org/wikipedia/commons/thumb/6/68/Yushan' '_main_east_peak%2BHuang_Chung_Yu%E9%BB%83%E4%B8%AD%E4%BD%91%2B' '9030.png/640px-Yushan_main_east_peak%2BHuang_Chung_Yu%E9%BB%83' '%E4%B8%AD%E4%BD%91%2B9030.png'), @@ -56,10 +62,12 @@ class _SliverExampleState extends State { onReorder: _onReorder, onNoReorder: (int index) { //this callback is optional - debugPrint('${DateTime.now().toString().substring(5, 22)} reorder cancelled. index:$index'); + debugPrint( + '${DateTime.now().toString().substring(5, 22)} reorder cancelled. index:$index'); }, onReorderStarted: (int index) { - debugPrint('${DateTime.now().toString().substring(5, 22)} reorder started. index:$index'); + debugPrint( + '${DateTime.now().toString().substring(5, 22)} reorder started. index:$index'); }, ) ], diff --git a/example/lib/table_example.dart b/example/lib/table_example.dart index 037335f..6615d04 100644 --- a/example/lib/table_example.dart +++ b/example/lib/table_example.dart @@ -9,7 +9,7 @@ class TableExample extends StatefulWidget { class _TableExampleState extends State { //The children of ReorderableTableRow must be of type ReorderableTableRow - List _itemRows; + late List _itemRows; @override void initState() { diff --git a/example/lib/wrap_example.dart b/example/lib/wrap_example.dart index 9b9148e..b168269 100644 --- a/example/lib/wrap_example.dart +++ b/example/lib/wrap_example.dart @@ -9,7 +9,7 @@ class WrapExample extends StatefulWidget { class _WrapExampleState extends State { final double _iconSize = 90; - List _tiles; + late List _tiles; @override void initState() { diff --git a/example/pubspec.yaml b/example/pubspec.yaml index ee7d80c..62009df 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -1,6 +1,6 @@ name: reorderables_example description: Demonstrates how to use the reorderables package.. - +publish_to: none # The following defines the version and build number for your application. # A version number is three numbers separated by dots, like 1.2.43 # followed by an optional build number separated by a +. @@ -10,7 +10,7 @@ description: Demonstrates how to use the reorderables package.. version: 1.2.0 environment: - sdk: ">=2.1.0 <3.0.0" + sdk: '>=2.12.0 <3.0.0' dependencies: reorderables: @@ -21,7 +21,7 @@ dependencies: # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. - cupertino_icons: ^0.1.2 + cupertino_icons: ^1.0.2 dev_dependencies: flutter_test: diff --git a/example/web/favicon.png b/example/web/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..8aaa46ac1ae21512746f852a42ba87e4165dfdd1 GIT binary patch literal 917 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|I14-?iy0X7 zltGxWVyS%@P(fs7NJL45ua8x7ey(0(N`6wRUPW#JP&EUCO@$SZnVVXYs8ErclUHn2 zVXFjIVFhG^g!Ppaz)DK8ZIvQ?0~DO|i&7O#^-S~(l1AfjnEK zjFOT9D}DX)@^Za$W4-*MbbUihOG|wNBYh(yU7!lx;>x^|#0uTKVr7USFmqf|i<65o z3raHc^AtelCMM;Vme?vOfh>Xph&xL%(-1c06+^uR^q@XSM&D4+Kp$>4P^%3{)XKjo zGZknv$b36P8?Z_gF{nK@`XI}Z90TzwSQO}0J1!f2c(B=V`5aP@1P1a|PZ!4!3&Gl8 zTYqUsf!gYFyJnXpu0!n&N*SYAX-%d(5gVjrHJWqXQshj@!Zm{!01WsQrH~9=kTxW#6SvuapgMqt>$=j#%eyGrQzr zP{L-3gsMA^$I1&gsBAEL+vxi1*Igl=8#8`5?A-T5=z-sk46WA1IUT)AIZHx1rdUrf zVJrJn<74DDw`j)Ki#gt}mIT-Q`XRa2-jQXQoI%w`nb|XblvzK${ZzlV)m-XcwC(od z71_OEC5Bt9GEXosOXaPTYOia#R4ID2TiU~`zVMl08TV_C%DnU4^+HE>9(CE4D6?Fz oujB08i7adh9xk7*FX66dWH6F5TM;?E2b5PlUHx3vIVCg!0Dx9vYXATM literal 0 HcmV?d00001 diff --git a/example/web/icons/Icon-192.png b/example/web/icons/Icon-192.png new file mode 100644 index 0000000000000000000000000000000000000000..b749bfef07473333cf1dd31e9eed89862a5d52aa GIT binary patch literal 5292 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 literal 0 HcmV?d00001 diff --git a/example/web/icons/Icon-512.png b/example/web/icons/Icon-512.png new file mode 100644 index 0000000000000000000000000000000000000000..88cfd48dff1169879ba46840804b412fe02fefd6 GIT binary patch literal 8252 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 literal 0 HcmV?d00001 diff --git a/example/web/index.html b/example/web/index.html new file mode 100644 index 0000000..1460b5e --- /dev/null +++ b/example/web/index.html @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + example + + + + + + + + diff --git a/example/web/manifest.json b/example/web/manifest.json new file mode 100644 index 0000000..8c01291 --- /dev/null +++ b/example/web/manifest.json @@ -0,0 +1,23 @@ +{ + "name": "example", + "short_name": "example", + "start_url": ".", + "display": "standalone", + "background_color": "#0175C2", + "theme_color": "#0175C2", + "description": "A new Flutter project.", + "orientation": "portrait-primary", + "prefer_related_applications": false, + "icons": [ + { + "src": "icons/Icon-192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "icons/Icon-512.png", + "sizes": "512x512", + "type": "image/png" + } + ] +} diff --git a/lib/generated/i18n.dart b/lib/generated/i18n.dart deleted file mode 100644 index 30fdb7a..0000000 --- a/lib/generated/i18n.dart +++ /dev/null @@ -1,126 +0,0 @@ -import 'dart:async'; - -import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; - -// ignore_for_file: non_constant_identifier_names -// ignore_for_file: camel_case_types -// ignore_for_file: prefer_single_quotes - -// This file is automatically generated. DO NOT EDIT, all your changes would be lost. -class S implements WidgetsLocalizations { - const S(); - - static S current; - - static const GeneratedLocalizationsDelegate delegate = - GeneratedLocalizationsDelegate(); - - static S of(BuildContext context) => Localizations.of(context, S); - - @override - TextDirection get textDirection => TextDirection.ltr; - -} - -class $en extends S { - const $en(); -} - -class GeneratedLocalizationsDelegate extends LocalizationsDelegate { - const GeneratedLocalizationsDelegate(); - - List get supportedLocales { - return const [ - Locale("en", ""), - ]; - } - - LocaleListResolutionCallback listResolution({Locale fallback, bool withCountry = true}) { - return (List locales, Iterable supported) { - if (locales == null || locales.isEmpty) { - return fallback ?? supported.first; - } else { - return _resolve(locales.first, fallback, supported, withCountry); - } - }; - } - - LocaleResolutionCallback resolution({Locale fallback, bool withCountry = true}) { - return (Locale locale, Iterable supported) { - return _resolve(locale, fallback, supported, withCountry); - }; - } - - @override - Future load(Locale locale) { - final String lang = getLang(locale); - if (lang != null) { - switch (lang) { - case "en": - S.current = const $en(); - return SynchronousFuture(S.current); - default: - // NO-OP. - } - } - S.current = const S(); - return SynchronousFuture(S.current); - } - - @override - bool isSupported(Locale locale) => _isSupported(locale, true); - - @override - bool shouldReload(GeneratedLocalizationsDelegate old) => false; - - /// - /// Internal method to resolve a locale from a list of locales. - /// - Locale _resolve(Locale locale, Locale fallback, Iterable supported, bool withCountry) { - if (locale == null || !_isSupported(locale, withCountry)) { - return fallback ?? supported.first; - } - - final Locale languageLocale = Locale(locale.languageCode, ""); - if (supported.contains(locale)) { - return locale; - } else if (supported.contains(languageLocale)) { - return languageLocale; - } else { - final Locale fallbackLocale = fallback ?? supported.first; - return fallbackLocale; - } - } - - /// - /// Returns true if the specified locale is supported, false otherwise. - /// - bool _isSupported(Locale locale, bool withCountry) { - if (locale != null) { - for (Locale supportedLocale in supportedLocales) { - // Language must always match both locales. - if (supportedLocale.languageCode != locale.languageCode) { - continue; - } - - // If country code matches, return this locale. - if (supportedLocale.countryCode == locale.countryCode) { - return true; - } - - // If no country requirement is requested, check if this locale has no country. - if (true != withCountry && (supportedLocale.countryCode == null || supportedLocale.countryCode.isEmpty)) { - return true; - } - } - } - return false; - } -} - -String getLang(Locale l) => l == null - ? null - : l.countryCode != null && l.countryCode.isEmpty - ? l.languageCode - : l.toString(); diff --git a/lib/src/rendering/tabluar_flex.dart b/lib/src/rendering/tabluar_flex.dart index 9c5b2ab..5202348 100644 --- a/lib/src/rendering/tabluar_flex.dart +++ b/lib/src/rendering/tabluar_flex.dart @@ -1,32 +1,15 @@ -import 'dart:math' as math; import 'dart:collection'; +import 'dart:math' as math; -import 'package:flutter/rendering.dart'; import 'package:flutter/foundation.dart'; +import 'package:flutter/rendering.dart'; -bool _startIsTopLeft(Axis direction, TextDirection textDirection, +bool? _startIsTopLeft(Axis direction, TextDirection? textDirection, VerticalDirection verticalDirection) { - assert(direction != null); // If the relevant value of textDirection or verticalDirection is null, this returns null too. - switch (direction) { - case Axis.horizontal: - switch (textDirection) { - case TextDirection.ltr: - return true; - case TextDirection.rtl: - return false; - } - break; - case Axis.vertical: - switch (verticalDirection) { - case VerticalDirection.down: - return true; - case VerticalDirection.up: - return false; - } - break; - } - return null; + return direction == Axis.horizontal + ? (textDirection == null ? null : textDirection == TextDirection.ltr) + : verticalDirection == VerticalDirection.down; } typedef _ChildSizingFunction = double Function(RenderBox child, double extent); @@ -37,15 +20,15 @@ class RenderTabluarFlex extends RenderFlex { /// By default, the flex layout is horizontal and children are aligned to the /// start of the main axis and the center of the cross axis. RenderTabluarFlex({ - List children, + List? children, Axis direction = Axis.horizontal, MainAxisSize mainAxisSize = MainAxisSize.max, MainAxisAlignment mainAxisAlignment = MainAxisAlignment.start, CrossAxisAlignment crossAxisAlignment = CrossAxisAlignment.center, - TextDirection textDirection, + TextDirection? textDirection, VerticalDirection verticalDirection = VerticalDirection.down, - TextBaseline textBaseline, - Decoration decoration, + TextBaseline? textBaseline, + Decoration? decoration, ImageConfiguration configuration = ImageConfiguration.empty, }) : _decoration = decoration, _configuration = configuration, @@ -60,15 +43,15 @@ class RenderTabluarFlex extends RenderFlex { textBaseline: textBaseline, ); - BoxPainter _painter; + BoxPainter? _painter; /// What decoration to paint. /// /// Commonly a [BoxDecoration]. - Decoration get decoration => _decoration; - Decoration _decoration; + Decoration? get decoration => _decoration; + Decoration? _decoration; - set decoration(Decoration value) { + set decoration(Decoration? value) { // assert(value != null); if (value == _decoration) return; _painter?.dispose(); @@ -87,7 +70,6 @@ class RenderTabluarFlex extends RenderFlex { ImageConfiguration _configuration; set configuration(ImageConfiguration value) { - assert(value != null); if (value == _configuration) return; _configuration = value; markNeedsPaint(); @@ -107,52 +89,37 @@ class RenderTabluarFlex extends RenderFlex { } bool get _debugHasNecessaryDirections { - assert(direction != null); - assert(crossAxisAlignment != null); if (firstChild != null && lastChild != firstChild) { // i.e. there's more than one child - switch (direction) { - case Axis.horizontal: - assert(textDirection != null, - 'Horizontal $runtimeType with multiple children has a null textDirection, so the layout order is undefined.'); - break; - case Axis.vertical: - assert(verticalDirection != null, - 'Vertical $runtimeType with multiple children has a null verticalDirection, so the layout order is undefined.'); - break; - } + assert( + direction == Axis.vertical || textDirection != null, + 'Horizontal $runtimeType with multiple children has a ' + 'null textDirection, so the layout order is undefined.'); } if (mainAxisAlignment == MainAxisAlignment.start || mainAxisAlignment == MainAxisAlignment.end) { - switch (direction) { - case Axis.horizontal: - assert(textDirection != null, - 'Horizontal $runtimeType with $mainAxisAlignment has a null textDirection, so the alignment cannot be resolved.'); - break; - case Axis.vertical: - assert(verticalDirection != null, - 'Vertical $runtimeType with $mainAxisAlignment has a null verticalDirection, so the alignment cannot be resolved.'); - break; - } + assert( + direction == Axis.vertical || textDirection != null, + 'Horizontal $runtimeType with $mainAxisAlignment has a null ' + 'textDirection, so the alignment cannot be resolved.'); } if (crossAxisAlignment == CrossAxisAlignment.start || crossAxisAlignment == CrossAxisAlignment.end) { - switch (direction) { - case Axis.horizontal: - assert(verticalDirection != null, - 'Horizontal $runtimeType with $crossAxisAlignment has a null verticalDirection, so the alignment cannot be resolved.'); - break; - case Axis.vertical: - assert(textDirection != null, - 'Vertical $runtimeType with $crossAxisAlignment has a null textDirection, so the alignment cannot be resolved.'); - break; - } + assert( + direction == Axis.horizontal || textDirection != null, + 'Vertical $runtimeType with $crossAxisAlignment has a null ' + 'textDirection, so the alignment cannot be resolved.'); } return true; } // Set during layout if overflow occurred on the main axis. - double _overflow; + double _overflow = 0; + + /// + /// Determines whether the current overflow value is greater than zero. + /// + bool get _hasOverflow => _overflow > 0.0; final ListQueue> layoutCallbackQueue = ListQueue>(); @@ -168,10 +135,10 @@ class RenderTabluarFlex extends RenderFlex { // } double _getIntrinsicSize( - {Axis sizingDirection, - double + {required Axis sizingDirection, + required double extent, // the extent in the direction that isn't the sizing direction - _ChildSizingFunction + required _ChildSizingFunction childSize // a method to find the size in the sizing direction }) { if (direction == sizingDirection) { @@ -181,7 +148,7 @@ class RenderTabluarFlex extends RenderFlex { double totalFlex = 0.0; double inflexibleSpace = 0.0; double maxFlexFractionSoFar = 0.0; - RenderBox child = firstChild; + RenderBox? child = firstChild; while (child != null) { final int flex = _getFlex(child); totalFlex += flex; @@ -192,7 +159,8 @@ class RenderTabluarFlex extends RenderFlex { } else { inflexibleSpace += childSize(child, extent); } - final FlexParentData childParentData = child.parentData; + final FlexParentData childParentData = + child.parentData! as FlexParentData; child = childParentData.nextSibling; } return maxFlexFractionSoFar * totalFlex + inflexibleSpace; @@ -208,7 +176,7 @@ class RenderTabluarFlex extends RenderFlex { int totalFlex = 0; double inflexibleSpace = 0.0; double maxCrossSize = 0.0; - RenderBox child = firstChild; + RenderBox? child = firstChild; Map maxGrandchildCrossSize = {}; while (child != null) { final int flex = _getFlex(child); @@ -227,7 +195,7 @@ class RenderTabluarFlex extends RenderFlex { break; } - RenderTabluarFlex tabluarFlexChild = + RenderTabluarFlex? tabluarFlexChild = _findTabluarFlexDescendant(child); if (tabluarFlexChild is RenderTabluarFlex) { // RenderTabluarFlex _child = child as RenderTabluarFlex; @@ -245,7 +213,8 @@ class RenderTabluarFlex extends RenderFlex { inflexibleSpace += mainSize; maxCrossSize = math.max(maxCrossSize, crossSize); } - final FlexParentData childParentData = child.parentData; + final FlexParentData childParentData = + child.parentData! as FlexParentData; child = childParentData.nextSibling; } @@ -260,7 +229,7 @@ class RenderTabluarFlex extends RenderFlex { final int flex = _getFlex(child); if (flex > 0) { double mainSize = spacePerFlex * flex; - RenderTabluarFlex tabluarFlexChild = + RenderTabluarFlex? tabluarFlexChild = _findTabluarFlexDescendant(child); if (tabluarFlexChild is RenderTabluarFlex) { List grandchildren = @@ -275,7 +244,8 @@ class RenderTabluarFlex extends RenderFlex { // maxCrossSize = math.max(maxCrossSize, childSize(child, spacePerFlex * flex)); maxCrossSize = math.max(maxCrossSize, childSize(child, mainSize)); } - final FlexParentData childParentData = child.parentData; + final FlexParentData childParentData = + child.parentData! as FlexParentData; child = childParentData.nextSibling; } @@ -327,41 +297,27 @@ class RenderTabluarFlex extends RenderFlex { } int _getFlex(RenderBox child) { - final FlexParentData childParentData = child.parentData; - return childParentData.flex ?? 0; + final FlexParentData? childParentData = child.parentData as FlexParentData; + return childParentData?.flex ?? 0; } - FlexFit _getFit(RenderBox child) { - final FlexParentData childParentData = child.parentData; - return childParentData.fit ?? FlexFit.tight; + FlexFit _getFit(RenderBox? child) { + final FlexParentData? childParentData = child?.parentData as FlexParentData; + return childParentData?.fit ?? FlexFit.tight; } - double _getCrossSize(RenderBox child) { - switch (direction) { - case Axis.horizontal: - return child.size.height; - case Axis.vertical: - return child.size.width; - } - return null; - } + double _getCrossSize(RenderBox child) => + direction == Axis.horizontal ? child.size.height : child.size.width; - double _getMainSize(RenderBox child) { - switch (direction) { - case Axis.horizontal: - return child.size.width; - case Axis.vertical: - return child.size.height; - } - return null; - } + double _getMainSize(RenderBox child) => + direction == Axis.horizontal ? child.size.width : child.size.height; - RenderTabluarFlex _findTabluarFlexDescendant(RenderBox child) { - RenderObject curDescendant = child; + RenderTabluarFlex? _findTabluarFlexDescendant(RenderBox child) { + RenderObject? curDescendant = child; ListQueue childrenQueue = ListQueue(); while (curDescendant != null && curDescendant is! RenderTabluarFlex) { // RenderObject firstChildRenderer; - curDescendant.visitChildren((RenderObject renderObject) { + curDescendant!.visitChildren((RenderObject renderObject) { // firstChildRenderer ??= renderObject; if (curDescendant is! RenderTabluarFlex) { if (renderObject is RenderTabluarFlex) { @@ -378,8 +334,7 @@ class RenderTabluarFlex extends RenderFlex { } } - RenderTabluarFlex tabluarFlexDescendant = curDescendant; - return tabluarFlexDescendant; + return curDescendant == null ? null : curDescendant as RenderTabluarFlex; } @override @@ -388,7 +343,6 @@ class RenderTabluarFlex extends RenderFlex { // Determine used flex factor, size inflexible items, calculate free space. int totalFlex = 0; int totalChildren = 0; - assert(constraints != null); final double maxMainSize = direction == Axis.horizontal ? constraints.maxWidth : constraints.maxHeight; @@ -399,7 +353,7 @@ class RenderTabluarFlex extends RenderFlex { Map tabluarFlexDescendants = {}; void _layoutChild(RenderBox child, BoxConstraints constraints) { - RenderTabluarFlex tabluarFlexChild = _findTabluarFlexDescendant(child); + RenderTabluarFlex? tabluarFlexChild = _findTabluarFlexDescendant(child); // debugPrint('this:$this _layoutChild: child:$child tabluarFlexChild:$tabluarFlexChild'); if (tabluarFlexChild != null) { //when this is laying out its child (and descendants), this function will be called. So that we can get the grandchild's size @@ -466,12 +420,12 @@ class RenderTabluarFlex extends RenderFlex { case Axis.horizontal: innerConstraints = innerConstraints.copyWith( minWidth: math.max(innerConstraints.minWidth, - minChildrenMainSize[childIndex])); + minChildrenMainSize[childIndex]!)); break; case Axis.vertical: innerConstraints = innerConstraints.copyWith( minHeight: math.max(innerConstraints.minHeight, - minChildrenMainSize[childIndex])); + minChildrenMainSize[childIndex]!)); break; } } @@ -484,11 +438,12 @@ class RenderTabluarFlex extends RenderFlex { double crossSize = 0.0; double allocatedSize = 0.0; // Sum of the sizes of the non-flexible children. - RenderBox child = firstChild; - RenderBox lastFlexChild; + RenderBox? child = firstChild; + RenderBox? lastFlexChild; int childIndex = 0; while (child != null) { - final FlexParentData childParentData = child.parentData; + final FlexParentData childParentData = + child.parentData! as FlexParentData; totalChildren++; final int flex = _getFlex(child); if (flex > 0) { @@ -512,16 +467,16 @@ class RenderTabluarFlex extends RenderFlex { 'axis. Setting a flex on a child (e.g. using Expanded) indicates that the child is to ' 'expand to fill the remaining space in the $axis direction.'; final StringBuffer information = StringBuffer(); - RenderBox node = this; + RenderBox? node = this; switch (direction) { case Axis.horizontal: - while (!node.constraints.hasBoundedWidth && - node.parent is RenderBox) node = node.parent; + while (!node!.constraints.hasBoundedWidth && + node.parent is RenderBox) node = node.parent as RenderBox; if (!node.constraints.hasBoundedWidth) node = null; break; case Axis.vertical: - while (!node.constraints.hasBoundedHeight && - node.parent is RenderBox) node = node.parent; + while (!node!.constraints.hasBoundedHeight && + node.parent is RenderBox) node = node.parent as RenderBox; if (!node.constraints.hasBoundedHeight) node = null; break; } @@ -556,7 +511,7 @@ class RenderTabluarFlex extends RenderFlex { 'If none of the above helps enough to fix this problem, please don\'t hesitate to file a bug:\n' ' https://github.com/flutter/flutter/issues/new?template=BUG.md'); }()); - totalFlex += childParentData.flex; + totalFlex += childParentData.flex!; lastFlexChild = child; } else { BoxConstraints innerConstraints = _innerConstraints(childIndex); @@ -616,7 +571,6 @@ class RenderTabluarFlex extends RenderFlex { minChildExtent = 0.0; break; } - assert(minChildExtent != null); BoxConstraints innerConstraints; if (crossAxisAlignment == CrossAxisAlignment.stretch) { switch (direction) { @@ -657,12 +611,12 @@ class RenderTabluarFlex extends RenderFlex { case Axis.horizontal: innerConstraints = innerConstraints.copyWith( minWidth: math.max(innerConstraints.minWidth, - minChildrenMainSize[childIndex])); + minChildrenMainSize[childIndex]!)); break; case Axis.vertical: innerConstraints = innerConstraints.copyWith( minHeight: math.max(innerConstraints.minHeight, - minChildrenMainSize[childIndex])); + minChildrenMainSize[childIndex]!)); break; } } @@ -684,12 +638,13 @@ class RenderTabluarFlex extends RenderFlex { 'To use FlexAlignItems.baseline, you must also specify which baseline to use using the "baseline" argument.'); return true; }()); - final double distance = - child.getDistanceToBaseline(textBaseline, onlyReal: true); + final double? distance = + child.getDistanceToBaseline(textBaseline!, onlyReal: true); if (distance != null) maxBaselineDistance = math.max(maxBaselineDistance, distance); } - final FlexParentData childParentData = child.parentData; + final FlexParentData childParentData = + child.parentData! as FlexParentData; child = childParentData.nextSibling; childIndex++; } @@ -706,7 +661,7 @@ class RenderTabluarFlex extends RenderFlex { child = firstChild; while (child != null) { // debugPrint('this:$this relayout child:$child'); - BoxConstraints innerConstraints = childrenConstraints[child]; + BoxConstraints innerConstraints = childrenConstraints[child]!; switch (direction) { case Axis.horizontal: innerConstraints = innerConstraints.copyWith( @@ -725,7 +680,7 @@ class RenderTabluarFlex extends RenderFlex { callbackCalled = true; } - RenderTabluarFlex tabluarFlexChild = tabluarFlexDescendants[child]; + RenderTabluarFlex tabluarFlexChild = tabluarFlexDescendants[child]!; tabluarFlexChild.layoutCallbackQueue.addLast(_childLayoutCallback); tabluarFlexChild.minMainSizesQueue.addLast(maxGrandchildrenCrossSize); tabluarFlexChild.layout(innerConstraints, parentUsesSize: true); @@ -740,7 +695,8 @@ class RenderTabluarFlex extends RenderFlex { } crossSize = math.max(crossSize, _getCrossSize(child)); - final FlexParentData childParentData = child.parentData; + final FlexParentData childParentData = + child.parentData! as FlexParentData; child = childParentData.nextSibling; } // debugPrint('this:$this updated crossSize:$crossSize'); @@ -810,7 +766,8 @@ class RenderTabluarFlex extends RenderFlex { flipMainAxis ? actualSize - leadingSpace : leadingSpace; child = firstChild; while (child != null) { - final FlexParentData childParentData = child.parentData; + final FlexParentData childParentData = + child.parentData! as FlexParentData; double childCrossPosition; switch (crossAxisAlignment) { case CrossAxisAlignment.start: @@ -831,8 +788,8 @@ class RenderTabluarFlex extends RenderFlex { childCrossPosition = 0.0; if (direction == Axis.horizontal) { assert(textBaseline != null); - final double distance = - child.getDistanceToBaseline(textBaseline, onlyReal: true); + final double? distance = + child.getDistanceToBaseline(textBaseline!, onlyReal: true); if (distance != null) childCrossPosition = maxBaselineDistance - distance; } @@ -872,7 +829,7 @@ class RenderTabluarFlex extends RenderFlex { @override void paint(PaintingContext context, Offset offset) { - if (_overflow <= 0.0) { + if (!_hasOverflow) { defaultPaint(context, offset); return; } @@ -881,10 +838,10 @@ class RenderTabluarFlex extends RenderFlex { if (size.isEmpty) return; if (_decoration != null) { - _painter ??= _decoration.createBoxPainter(markNeedsPaint); + _painter ??= _decoration!.createBoxPainter(markNeedsPaint); final ImageConfiguration filledConfiguration = configuration.copyWith(size: size); - _painter.paint(context.canvas, offset, filledConfiguration); + _painter!.paint(context.canvas, offset, filledConfiguration); } // We have overflow. Clip it. @@ -934,13 +891,13 @@ class RenderTabluarFlex extends RenderFlex { } @override - Rect describeApproximatePaintClip(RenderObject child) => - _overflow > 0.0 ? Offset.zero & size : null; + Rect? describeApproximatePaintClip(RenderObject child) => + _hasOverflow ? Offset.zero & size : null; @override String toStringShort() { String header = super.toStringShort(); - if (_overflow is double && _overflow > 0.0) header += ' OVERFLOWING'; + if (_hasOverflow) header += ' OVERFLOWING'; return header; } } diff --git a/lib/src/rendering/transitions.dart b/lib/src/rendering/transitions.dart index 99d99d7..e2b5c6f 100644 --- a/lib/src/rendering/transitions.dart +++ b/lib/src/rendering/transitions.dart @@ -1,13 +1,12 @@ import 'package:flutter/rendering.dart'; import 'package:flutter/animation.dart'; -import 'package:flutter/foundation.dart'; class RenderSizeTransitionWithIntrinsicSize extends RenderProxyBox { RenderSizeTransitionWithIntrinsicSize({ this.axis = Axis.vertical, - @required this.sizeFactor, - RenderBox child, - }) : assert(sizeFactor != null), + required this.sizeFactor, + RenderBox? child, + }) : // _axis = axis, // _sizeFactor = sizeFactor, super(child); @@ -26,6 +25,7 @@ class RenderSizeTransitionWithIntrinsicSize extends RenderProxyBox { @override double computeMinIntrinsicWidth(double height) { + final child = this.child; if (child != null) { double childWidth = child.getMinIntrinsicWidth(height); return axis == Axis.horizontal @@ -37,6 +37,7 @@ class RenderSizeTransitionWithIntrinsicSize extends RenderProxyBox { @override double computeMaxIntrinsicWidth(double height) { + final child = this.child; if (child != null) { double childWidth = child.getMaxIntrinsicWidth(height); return axis == Axis.horizontal @@ -48,6 +49,7 @@ class RenderSizeTransitionWithIntrinsicSize extends RenderProxyBox { @override double computeMinIntrinsicHeight(double width) { + final child = this.child; if (child != null) { double childHeight = child.getMinIntrinsicHeight(width); return axis == Axis.vertical @@ -59,6 +61,7 @@ class RenderSizeTransitionWithIntrinsicSize extends RenderProxyBox { @override double computeMaxIntrinsicHeight(double width) { + final child = this.child; if (child != null) { double childHeight = child.getMaxIntrinsicHeight(width); return axis == Axis.vertical diff --git a/lib/src/rendering/wrap.dart b/lib/src/rendering/wrap.dart index 4b739d7..c41ba9c 100644 --- a/lib/src/rendering/wrap.dart +++ b/lib/src/rendering/wrap.dart @@ -19,14 +19,14 @@ class WrapWithMainAxisCountParentData extends WrapParentData { class RenderWrapWithMainAxisCount extends RenderWrap { RenderWrapWithMainAxisCount({ - List children, + List? children, Axis direction = Axis.horizontal, WrapAlignment alignment = WrapAlignment.start, double spacing = 0.0, WrapAlignment runAlignment = WrapAlignment.start, double runSpacing = 0.0, WrapCrossAlignment crossAxisAlignment = WrapCrossAlignment.start, - TextDirection textDirection, + TextDirection? textDirection, VerticalDirection verticalDirection = VerticalDirection.down, this.minMainAxisCount, this.maxMainAxisCount, @@ -36,24 +36,25 @@ class RenderWrapWithMainAxisCount extends RenderWrap { // _minMainAxisCount = minMainAxisCount, // _maxMainAxisCount = maxMainAxisCount, super( - children: children, - direction: direction, - alignment: alignment, - spacing: spacing, - runAlignment: runAlignment, - runSpacing: runSpacing, - crossAxisAlignment: crossAxisAlignment, - textDirection: textDirection, - verticalDirection: verticalDirection); - - int minMainAxisCount; + children: children, + direction: direction, + alignment: alignment, + spacing: spacing, + runAlignment: runAlignment, + runSpacing: runSpacing, + crossAxisAlignment: crossAxisAlignment, + textDirection: textDirection, + verticalDirection: verticalDirection, + ); + + int? minMainAxisCount; // int get minMainAxisCount => _minMainAxisCount; // set minMainAxisCount(int value) { // _minMainAxisCount = value; // } - int maxMainAxisCount; + int? maxMainAxisCount; // int get maxMainAxisCount => _maxMainAxisCount; // set maxMainAxisCount(int value) { @@ -61,60 +62,32 @@ class RenderWrapWithMainAxisCount extends RenderWrap { // } bool get _debugHasNecessaryDirections { - assert(direction != null); - assert(alignment != null); - assert(runAlignment != null); - assert(crossAxisAlignment != null); if (firstChild != null && lastChild != firstChild) { // i.e. there's more than one child - switch (direction) { - case Axis.horizontal: - assert(textDirection != null, - 'Horizontal $runtimeType with multiple children has a null textDirection, so the layout order is undefined.'); - break; - case Axis.vertical: - assert(verticalDirection != null, - 'Vertical $runtimeType with multiple children has a null verticalDirection, so the layout order is undefined.'); - break; - } + assert( + direction == Axis.vertical || textDirection != null, + 'Horizontal $runtimeType with multiple children has a null ' + 'textDirection, so the layout order is undefined.'); } if (alignment == WrapAlignment.start || alignment == WrapAlignment.end) { - switch (direction) { - case Axis.horizontal: - assert(textDirection != null, - 'Horizontal $runtimeType with alignment $alignment has a null textDirection, so the alignment cannot be resolved.'); - break; - case Axis.vertical: - assert(verticalDirection != null, - 'Vertical $runtimeType with alignment $alignment has a null verticalDirection, so the alignment cannot be resolved.'); - break; - } + assert( + direction == Axis.vertical || textDirection != null, + 'Horizontal $runtimeType with alignment $alignment has a null ' + 'textDirection, so the alignment cannot be resolved.'); } if (runAlignment == WrapAlignment.start || runAlignment == WrapAlignment.end) { - switch (direction) { - case Axis.horizontal: - assert(verticalDirection != null, - 'Horizontal $runtimeType with runAlignment $runAlignment has a null verticalDirection, so the alignment cannot be resolved.'); - break; - case Axis.vertical: - assert(textDirection != null, - 'Vertical $runtimeType with runAlignment $runAlignment has a null textDirection, so the alignment cannot be resolved.'); - break; - } + assert( + direction == Axis.horizontal || textDirection != null, + 'Horizontal $runtimeType with runAlignment $runAlignment has a null ' + 'verticalDirection, so the alignment cannot be resolved.'); } if (crossAxisAlignment == WrapCrossAlignment.start || crossAxisAlignment == WrapCrossAlignment.end) { - switch (direction) { - case Axis.horizontal: - assert(verticalDirection != null, - 'Horizontal $runtimeType with crossAxisAlignment $crossAxisAlignment has a null verticalDirection, so the alignment cannot be resolved.'); - break; - case Axis.vertical: - assert(textDirection != null, - 'Vertical $runtimeType with crossAxisAlignment $crossAxisAlignment has a null textDirection, so the alignment cannot be resolved.'); - break; - } + assert( + direction == Axis.horizontal || textDirection != null, + 'Vertical $runtimeType with crossAxisAlignment $crossAxisAlignment ' + 'has a null textDirection, so the alignment cannot be resolved.'); } return true; } @@ -132,7 +105,7 @@ class RenderWrapWithMainAxisCount extends RenderWrap { double runWidth = 0.0; double runHeight = 0.0; int childCount = 0; - RenderBox child = firstChild; + RenderBox? child = firstChild; int minChildCount = minMainAxisCount ?? 1; int maxChildCount = maxMainAxisCount ?? -1; while (child != null) { @@ -167,7 +140,7 @@ class RenderWrapWithMainAxisCount extends RenderWrap { double runHeight = 0.0; double runWidth = 0.0; int childCount = 0; - RenderBox child = firstChild; + RenderBox? child = firstChild; int minChildCount = minMainAxisCount ?? 1; int maxChildCount = maxMainAxisCount ?? -1; while (child != null) { @@ -199,14 +172,14 @@ class RenderWrapWithMainAxisCount extends RenderWrap { { // Axis sizingDirection, // double extent, // the extent in the direction that isn't the sizing direction - int childCountAlongMainAxis, - _ChildSizingFunction + required int childCountAlongMainAxis, + required _ChildSizingFunction childSize // a method to find the size in the sizing direction }) { double runMainAxisExtent = 0.0; double maxRunMainAxisExtent = 0.0; int childCount = 0; - RenderBox child = firstChild; + RenderBox? child = firstChild; // final List runMainAxisExtents = []; while (child != null) { final double childMainAxisExtent = childSize(child, double.infinity); @@ -238,7 +211,6 @@ class RenderWrapWithMainAxisCount extends RenderWrap { case Axis.vertical: return _computeIntrinsicWidthForHeight(height); } - return null; } @override @@ -252,7 +224,6 @@ class RenderWrapWithMainAxisCount extends RenderWrap { case Axis.vertical: return _computeIntrinsicWidthForHeight(height); } - return null; } @override @@ -266,7 +237,6 @@ class RenderWrapWithMainAxisCount extends RenderWrap { childSize: (RenderBox child, double extent) => child.getMinIntrinsicHeight(extent)); } - return null; } @override @@ -280,7 +250,6 @@ class RenderWrapWithMainAxisCount extends RenderWrap { childSize: (RenderBox child, double extent) => child.getMaxIntrinsicHeight(extent)); } - return null; } double _getMainAxisExtent(RenderBox child) { @@ -290,7 +259,6 @@ class RenderWrapWithMainAxisCount extends RenderWrap { case Axis.vertical: return child.size.height; } - return 0.0; } double _getCrossAxisExtent(RenderBox child) { @@ -300,7 +268,6 @@ class RenderWrapWithMainAxisCount extends RenderWrap { case Axis.vertical: return child.size.width; } - return 0.0; } Offset _getOffset(double mainAxisOffset, double crossAxisOffset) { @@ -310,7 +277,6 @@ class RenderWrapWithMainAxisCount extends RenderWrap { case Axis.vertical: return Offset(crossAxisOffset, mainAxisOffset); } - return Offset.zero; } double _getChildCrossAxisOffset(bool flipCrossAxis, double runCrossAxisExtent, @@ -324,17 +290,16 @@ class RenderWrapWithMainAxisCount extends RenderWrap { case WrapCrossAlignment.center: return freeSpace / 2.0; } - return 0.0; } bool _hasVisualOverflow = false; - List childRunIndexes; + late List childRunIndexes; @override void performLayout() { assert(_debugHasNecessaryDirections); _hasVisualOverflow = false; - RenderBox child = firstChild; + RenderBox? child = firstChild; if (child == null) { size = constraints.smallest; return; @@ -357,8 +322,6 @@ class RenderWrapWithMainAxisCount extends RenderWrap { if (textDirection == TextDirection.rtl) flipCrossAxis = true; break; } - assert(childConstraints != null); - assert(mainAxisLimit != null); final double spacing = this.spacing; final double runSpacing = this.runSpacing; final List<_RunMetrics> runMetrics = <_RunMetrics>[]; @@ -394,7 +357,8 @@ class RenderWrapWithMainAxisCount extends RenderWrap { if (childCount > 0) runMainAxisExtent += spacing; runCrossAxisExtent = math.max(runCrossAxisExtent, childCrossAxisExtent); childCount += 1; - final WrapWithMainAxisCountParentData childParentData = child.parentData; + final WrapWithMainAxisCountParentData childParentData = + child.parentData! as WrapWithMainAxisCountParentData; childParentData._runIndex = runMetrics.length; child = childParentData.nextSibling; childRunIndexes.add(runIndex); @@ -505,7 +469,7 @@ class RenderWrapWithMainAxisCount extends RenderWrap { while (child != null) { final WrapWithMainAxisCountParentData childParentData = - child.parentData; + child.parentData! as WrapWithMainAxisCountParentData; if (childParentData._runIndex != i) break; final double childMainAxisExtent = _getMainAxisExtent(child); final double childCrossAxisExtent = _getCrossAxisExtent(child); diff --git a/lib/src/widgets/basic.dart b/lib/src/widgets/basic.dart index 5762ff2..62fab31 100644 --- a/lib/src/widgets/basic.dart +++ b/lib/src/widgets/basic.dart @@ -12,10 +12,9 @@ class SafeStatefulBuilder extends StatefulWidget { /// /// The [builder] argument must not be null. const SafeStatefulBuilder({ - Key key, - @required this.builder, - }) : assert(builder != null), - super(key: key); + required this.builder, + Key? key, + }) : super(key: key); /// Called to obtain the child widget. /// diff --git a/lib/src/widgets/passthrough_overlay.dart b/lib/src/widgets/passthrough_overlay.dart index 3df491f..7226627 100644 --- a/lib/src/widgets/passthrough_overlay.dart +++ b/lib/src/widgets/passthrough_overlay.dart @@ -5,9 +5,8 @@ import 'dart:async'; import 'dart:collection'; -import 'package:flutter/material.dart'; - import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter/scheduler.dart'; @@ -61,13 +60,10 @@ class PassthroughOverlayEntry { /// [Overlay.of] and then call [OverlayState.insert]. To remove the entry, /// call [remove] on the overlay entry itself. PassthroughOverlayEntry({ - @required this.builder, + required this.builder, bool opaque = false, bool maintainState = false, - }) : assert(builder != null), - assert(opaque != null), - assert(maintainState != null), - _opaque = opaque, + }) : _opaque = opaque, _maintainState = maintainState; /// This entry will include the widget built by this builder in the overlay at @@ -84,11 +80,12 @@ class PassthroughOverlayEntry { /// set. bool get opaque => _opaque; bool _opaque; + set opaque(bool value) { if (_opaque == value) return; _opaque = value; assert(_overlay != null); - _overlay._didChangeEntryOpacity(); + _overlay!._didChangeEntryOpacity(); } /// Whether this entry must be included in the tree even if there is a fully @@ -107,15 +104,15 @@ class PassthroughOverlayEntry { /// from subsequent routes will be handled properly when they complete. bool get maintainState => _maintainState; bool _maintainState; + set maintainState(bool value) { - assert(_maintainState != null); if (_maintainState == value) return; _maintainState = value; assert(_overlay != null); - _overlay._didChangeEntryOpacity(); + _overlay!._didChangeEntryOpacity(); } - PassthroughOverlayState _overlay; + PassthroughOverlayState? _overlay; final GlobalKey<_OverlayEntryState> _key = GlobalKey<_OverlayEntryState>(); /// Remove this entry from the overlay. @@ -131,11 +128,11 @@ class PassthroughOverlayEntry { /// the next frame (i.e. many milliseconds later). void remove() { assert(_overlay != null); - final PassthroughOverlayState overlay = _overlay; + final PassthroughOverlayState overlay = _overlay!; _overlay = null; - if (SchedulerBinding.instance.schedulerPhase == + if (SchedulerBinding.instance!.schedulerPhase == SchedulerPhase.persistentCallbacks) { - SchedulerBinding.instance.addPostFrameCallback((Duration duration) { + SchedulerBinding.instance!.addPostFrameCallback((Duration duration) { overlay._remove(this); }); } else { @@ -156,9 +153,7 @@ class PassthroughOverlayEntry { } class _OverlayEntry extends StatefulWidget { - _OverlayEntry(this.entry) - : assert(entry != null), - super(key: entry._key); + _OverlayEntry(this.entry) : super(key: entry._key); final PassthroughOverlayEntry entry; @@ -173,7 +168,9 @@ class _OverlayEntryState extends State<_OverlayEntry> { } void _markNeedsBuild() { - setState(() {/* the state that changed is in the builder */}); + setState(() { + /* the state that changed is in the builder */ + }); } } @@ -202,10 +199,10 @@ class PassthroughOverlay extends StatefulWidget { /// /// Rather than creating an overlay, consider using the overlay that is /// created by the [WidgetsApp] or the [MaterialApp] for the application. - const PassthroughOverlay( - {Key key, this.initialEntries = const []}) - : assert(initialEntries != null), - super(key: key); + const PassthroughOverlay({ + this.initialEntries = const [], + Key? key, + }) : super(key: key); /// The entries to include in the overlay initially. /// @@ -236,8 +233,8 @@ class PassthroughOverlay extends StatefulWidget { /// OverlayState overlay = Overlay.of(context); /// ``` static PassthroughOverlayState of(BuildContext context, - {Widget debugRequiredFor}) { - final PassthroughOverlayState result = + {Widget? debugRequiredFor}) { + final PassthroughOverlayState? result = context.findAncestorStateOfType(); assert(() { if (debugRequiredFor != null && result == null) { @@ -253,7 +250,7 @@ class PassthroughOverlay extends StatefulWidget { } return true; }()); - return result; + return result!; } @override @@ -278,7 +275,7 @@ class PassthroughOverlayState extends State /// /// If [above] is non-null, the entry is inserted just above [above]. /// Otherwise, the entry is inserted on top. - void insert(PassthroughOverlayEntry entry, {PassthroughOverlayEntry above}) { + void insert(PassthroughOverlayEntry entry, {PassthroughOverlayEntry? above}) { assert(entry._overlay == null); assert( above == null || (above._overlay == this && _entries.contains(above))); @@ -295,7 +292,7 @@ class PassthroughOverlayState extends State /// If [above] is non-null, the entries are inserted just above [above]. /// Otherwise, the entries are inserted on top. void insertAll(Iterable entries, - {PassthroughOverlayEntry above}) { + {PassthroughOverlayEntry? above}) { assert( above == null || (above._overlay == this && _entries.contains(above))); if (entries.isEmpty) return; @@ -313,7 +310,9 @@ class PassthroughOverlayState extends State void _remove(PassthroughOverlayEntry entry) { if (mounted) { _entries.remove(entry); - setState(() {/* entry was removed */}); + setState(() { + /* entry was removed */ + }); } } @@ -367,8 +366,8 @@ class PassthroughOverlayState extends State } return _Theatre( onstage: Stack( - fit: StackFit - .passthrough, //HanSheng changed it to passthrough so that this widget doesn't change layout constraints + fit: StackFit.passthrough, + //HanSheng changed it to passthrough so that this widget doesn't change layout constraints children: onstageChildren.reversed.toList(growable: false), ), offstage: offstageChildren, @@ -395,12 +394,11 @@ class PassthroughOverlayState extends State /// widgets. class _Theatre extends RenderObjectWidget { _Theatre({ + required this.offstage, this.onstage, - @required this.offstage, - }) : assert(offstage != null), - assert(!offstage.any((Widget child) => child == null)); + }); - final Stack onstage; + final Stack? onstage; final List offstage; @@ -417,23 +415,23 @@ class _TheatreElement extends RenderObjectElement { super(widget); @override - _Theatre get widget => super.widget; + _Theatre get widget => super.widget as _Theatre; @override - _RenderTheatre get renderObject => super.renderObject; + _RenderTheatre get renderObject => super.renderObject as _RenderTheatre; - Element _onstage; + Element? _onstage; static final Object _onstageSlot = Object(); - List _offstage; + late List _offstage; final Set _forgottenOffstageChildren = HashSet(); @override - void insertChildRenderObject(RenderBox child, dynamic slot) { + void insertRenderObjectChild(RenderBox child, dynamic slot) { assert(renderObject.debugValidateChild(child)); if (slot == _onstageSlot) { assert(child is RenderStack); - renderObject.child = child; + renderObject.child = child as RenderStack?; } else { assert(slot == null || slot is Element); renderObject.insert(child, after: slot?.renderObject); @@ -441,11 +439,11 @@ class _TheatreElement extends RenderObjectElement { } @override - void moveChildRenderObject(RenderBox child, dynamic slot) { + void moveRenderObjectChild(RenderBox child, dynamic oldSlot, dynamic slot) { if (slot == _onstageSlot) { renderObject.remove(child); assert(child is RenderStack); - renderObject.child = child; + renderObject.child = child as RenderStack?; } else { assert(slot == null || slot is Element); if (renderObject.child == child) { @@ -458,7 +456,7 @@ class _TheatreElement extends RenderObjectElement { } @override - void removeChildRenderObject(RenderBox child) { + void removeRenderObjectChild(RenderBox child, dynamic slot) { if (renderObject.child == child) { renderObject.child = null; } else { @@ -468,7 +466,7 @@ class _TheatreElement extends RenderObjectElement { @override void visitChildren(ElementVisitor visitor) { - if (_onstage != null) visitor(_onstage); + if (_onstage != null) visitor(_onstage!); for (Element child in _offstage) { if (!_forgottenOffstageChildren.contains(child)) visitor(child); } @@ -476,11 +474,11 @@ class _TheatreElement extends RenderObjectElement { @override void debugVisitOnstageChildren(ElementVisitor visitor) { - if (_onstage != null) visitor(_onstage); + if (_onstage != null) visitor(_onstage!); } @override - bool forgetChild(Element child) { + void forgetChild(Element child) { if (child == _onstage) { _onstage = null; } else { @@ -488,15 +486,15 @@ class _TheatreElement extends RenderObjectElement { assert(!_forgottenOffstageChildren.contains(child)); _forgottenOffstageChildren.add(child); } - return true; + super.forgetChild(child); } @override - void mount(Element parent, dynamic newSlot) { + void mount(Element? parent, dynamic newSlot) { super.mount(parent, newSlot); _onstage = updateChild(_onstage, widget.onstage, _onstageSlot); - _offstage = List(widget.offstage.length); - Element previousChild; + _offstage = []; + Element? previousChild; for (int i = 0; i < _offstage.length; i += 1) { final Element newChild = inflateWidget(widget.offstage[i], previousChild); _offstage[i] = newChild; @@ -552,13 +550,13 @@ class _RenderTheatre extends RenderBox @override void redepthChildren() { - if (child != null) redepthChild(child); + if (child != null) redepthChild(child!); super.redepthChildren(); } @override void visitChildren(RenderObjectVisitor visitor) { - if (child != null) visitor(child); + if (child != null) visitor(child!); super.visitChildren(visitor); } @@ -566,10 +564,10 @@ class _RenderTheatre extends RenderBox List debugDescribeChildren() { final List children = []; - if (child != null) children.add(child.toDiagnosticsNode(name: 'onstage')); + if (child != null) children.add(child!.toDiagnosticsNode(name: 'onstage')); if (firstChild != null) { - RenderBox child = firstChild; + RenderBox child = firstChild!; int count = 1; while (true) { @@ -580,8 +578,9 @@ class _RenderTheatre extends RenderBox ), ); if (child == lastChild) break; - final StackParentData childParentData = child.parentData; - child = childParentData.nextSibling; + final StackParentData childParentData = + child.parentData! as StackParentData; + child = childParentData.nextSibling!; count += 1; } } else { @@ -597,6 +596,6 @@ class _RenderTheatre extends RenderBox @override void visitChildrenForSemantics(RenderObjectVisitor visitor) { - if (child != null) visitor(child); + if (child != null) visitor(child!); } } diff --git a/lib/src/widgets/reorderable_flex.dart b/lib/src/widgets/reorderable_flex.dart index 7abc888..da3d245 100644 --- a/lib/src/widgets/reorderable_flex.dart +++ b/lib/src/widgets/reorderable_flex.dart @@ -38,12 +38,12 @@ import './typedefs.dart'; class ReorderableFlex extends StatefulWidget { /// Creates a reorderable list. ReorderableFlex({ - Key key, + Key? key, this.header, this.footer, - @required this.children, - @required this.onReorder, - @required this.direction, + required this.children, + required this.onReorder, + required this.direction, this.scrollDirection = Axis.vertical, this.padding, this.buildItemsContainer, @@ -53,13 +53,10 @@ class ReorderableFlex extends StatefulWidget { this.scrollController, this.needsLongPressDraggable = true, this.draggingWidgetOpacity = 0.2, - this.reorderAnimationDuration = const Duration(milliseconds: 200), - this.scrollAnimationDuration = const Duration(milliseconds: 200), + this.reorderAnimationDuration, + this.scrollAnimationDuration, this.ignorePrimaryScrollController = false, - }) : assert(direction != null), - assert(onReorder != null), - assert(children != null), - assert( + }) : assert( children.every((Widget w) => w.key != null), 'All children of this widget must have a key.', ), @@ -68,12 +65,12 @@ class ReorderableFlex extends StatefulWidget { /// A non-reorderable header widget to show before the list. /// /// If null, no header will appear at the top/left of the widget. - final Widget header; + final Widget? header; /// A non-reorderable footer widget to show after the list. /// /// If null, no footer will appear at the bottom/right of the widget. - final Widget footer; + final Widget? footer; /// The widgets to display. final List children; @@ -83,26 +80,26 @@ class ReorderableFlex extends StatefulWidget { /// List [children] can only drag along this [Axis]. final Axis direction; final Axis scrollDirection; - final ScrollController scrollController; + final ScrollController? scrollController; /// The amount of space by which to inset the [children]. - final EdgeInsets padding; + final EdgeInsets? padding; /// Called when a child is dropped into a new position to shuffle the /// children. final ReorderCallback onReorder; - final NoReorderCallback onNoReorder; + final NoReorderCallback? onNoReorder; - final BuildItemsContainer buildItemsContainer; - final BuildDraggableFeedback buildDraggableFeedback; + final BuildItemsContainer? buildItemsContainer; + final BuildDraggableFeedback? buildDraggableFeedback; final MainAxisAlignment mainAxisAlignment; final bool needsLongPressDraggable; final double draggingWidgetOpacity; - final Duration reorderAnimationDuration; - final Duration scrollAnimationDuration; + final Duration? reorderAnimationDuration; + final Duration? scrollAnimationDuration; final bool ignorePrimaryScrollController; @override @@ -124,7 +121,7 @@ class _ReorderableFlexState extends State { GlobalKey(debugLabel: '$ReorderableFlex overlay key'); // This entry contains the scrolling list itself. - PassthroughOverlayEntry _listOverlayEntry; + late PassthroughOverlayEntry _listOverlayEntry; @override void initState() { @@ -147,8 +144,10 @@ class _ReorderableFlexState extends State { scrollController: widget.scrollController, needsLongPressDraggable: widget.needsLongPressDraggable, draggingWidgetOpacity: widget.draggingWidgetOpacity, - reorderAnimationDuration: widget.reorderAnimationDuration, - scrollAnimationDuration: widget.scrollAnimationDuration, + reorderAnimationDuration: widget.reorderAnimationDuration ?? + const Duration(milliseconds: 200), + scrollAnimationDuration: widget.scrollAnimationDuration ?? + const Duration(milliseconds: 200), ); }, ); @@ -173,33 +172,33 @@ class _ReorderableFlexContent extends StatefulWidget { const _ReorderableFlexContent({ this.header, this.footer, - @required this.children, - @required this.direction, - @required this.scrollDirection, - @required this.padding, - @required this.onReorder, - @required this.onNoReorder, - @required this.buildItemsContainer, - @required this.buildDraggableFeedback, - @required this.mainAxisAlignment, - @required this.scrollController, - @required this.needsLongPressDraggable, - @required this.draggingWidgetOpacity, - @required this.reorderAnimationDuration, - @required this.scrollAnimationDuration, + required this.children, + required this.direction, + required this.scrollDirection, + required this.onReorder, + required this.mainAxisAlignment, + required this.scrollController, + required this.needsLongPressDraggable, + required this.draggingWidgetOpacity, + required this.onNoReorder, + required this.buildItemsContainer, + required this.buildDraggableFeedback, + required this.padding, + this.reorderAnimationDuration = const Duration(milliseconds: 200), + this.scrollAnimationDuration = const Duration(milliseconds: 200), }); - final Widget header; - final Widget footer; + final Widget? header; + final Widget? footer; final List children; final Axis direction; final Axis scrollDirection; - final ScrollController scrollController; - final EdgeInsets padding; final ReorderCallback onReorder; - final NoReorderCallback onNoReorder; - final BuildItemsContainer buildItemsContainer; - final BuildDraggableFeedback buildDraggableFeedback; + final NoReorderCallback? onNoReorder; + final BuildItemsContainer? buildItemsContainer; + final BuildDraggableFeedback? buildDraggableFeedback; + final ScrollController? scrollController; + final EdgeInsets? padding; final MainAxisAlignment mainAxisAlignment; final bool needsLongPressDraggable; @@ -224,31 +223,31 @@ class _ReorderableFlexContentState extends State<_ReorderableFlexContent> static const double _dropAreaMargin = 0.0; // How long an animation to reorder an element in the list takes. - Duration _reorderAnimationDuration; + late Duration _reorderAnimationDuration; // How long an animation to scroll to an off-screen element in the // list takes. - Duration _scrollAnimationDuration; + late Duration _scrollAnimationDuration; // Controls scrolls and measures scroll progress. - ScrollController _scrollController; - ScrollPosition _attachedScrollPosition; + late ScrollController _scrollController; + ScrollPosition? _attachedScrollPosition; // This controls the entrance of the dragging widget into a new place. - AnimationController _entranceController; + late AnimationController _entranceController; // This controls the 'ghost' of the dragging widget, which is left behind // where the widget used to be. - AnimationController _ghostController; + late AnimationController _ghostController; // The member of widget.children currently being dragged. // // Null if no drag is underway. - Key _dragging; - Widget _draggingWidget; + Key? _dragging; + Widget? _draggingWidget; // The last computed size of the feedback widget being dragged. - Size _draggingFeedbackSize = Size(0, 0); + Size? _draggingFeedbackSize = Size(0, 0); // The location that the dragging widget occupied before it started to drag. int _dragStartIndex = -1; @@ -272,7 +271,7 @@ class _ReorderableFlexContentState extends State<_ReorderableFlexContent> if (_draggingFeedbackSize == null) { return Size(0, 0); } - return _draggingFeedbackSize + Offset(_dropAreaMargin, _dropAreaMargin); + return _draggingFeedbackSize! + Offset(_dropAreaMargin, _dropAreaMargin); // double dropAreaWithoutMargin; // switch (widget.direction) { // case Axis.horizontal: @@ -300,8 +299,8 @@ class _ReorderableFlexContentState extends State<_ReorderableFlexContent> @override void didChangeDependencies() { - if (_scrollController != null && _attachedScrollPosition != null) { - _scrollController.detach(_attachedScrollPosition); + if (_attachedScrollPosition != null) { + _scrollController.detach(_attachedScrollPosition!); _attachedScrollPosition = null; } @@ -310,14 +309,13 @@ class _ReorderableFlexContentState extends State<_ReorderableFlexContent> ScrollController(); if (_scrollController.hasClients) { - ScrollableState scrollableState = Scrollable.of(context); - _attachedScrollPosition = scrollableState?.position; + _attachedScrollPosition = Scrollable.of(context)?.position; } else { _attachedScrollPosition = null; } if (_attachedScrollPosition != null) { - _scrollController.attach(_attachedScrollPosition); + _scrollController.attach(_attachedScrollPosition!); } super.didChangeDependencies(); @@ -325,8 +323,8 @@ class _ReorderableFlexContentState extends State<_ReorderableFlexContent> @override void dispose() { - if (_scrollController != null && _attachedScrollPosition != null) { - _scrollController.detach(_attachedScrollPosition); + if (_attachedScrollPosition != null) { + _scrollController.detach(_attachedScrollPosition!); _attachedScrollPosition = null; } _entranceController.dispose(); @@ -364,10 +362,9 @@ class _ReorderableFlexContentState extends State<_ReorderableFlexContent> // Scrolls to a target context if that context is not on the screen. void _scrollTo(BuildContext context) { if (_scrolling) return; - final RenderObject contextObject = context.findRenderObject(); + final RenderObject contextObject = context.findRenderObject()!; final RenderAbstractViewport viewport = - RenderAbstractViewport.of(contextObject); - assert(viewport != null); + RenderAbstractViewport.of(contextObject)!; // If and only if the current scroll offset falls in-between the offsets // necessary to reveal the selected context at the top or bottom of the // screen, then it is already on-screen. @@ -407,7 +404,7 @@ class _ReorderableFlexContentState extends State<_ReorderableFlexContent> // Wraps children in Row or Column, so that the children flow in // the widget's scrollDirection. - Widget _buildContainerForMainAxis({List children}) { + Widget _buildContainerForMainAxis({required List children}) { switch (widget.direction) { case Axis.horizontal: return Row( @@ -427,7 +424,7 @@ class _ReorderableFlexContentState extends State<_ReorderableFlexContent> // Handles up the logic for dragging and reordering items in the list. Widget _wrap(Widget toWrap, int index) { assert(toWrap.key != null); - final GlobalObjectKey keyIndexGlobalKey = GlobalObjectKey(toWrap.key); + final GlobalObjectKey keyIndexGlobalKey = GlobalObjectKey(toWrap.key!); // We pass the toWrapWithGlobalKey into the Draggable so that when a list // item gets dragged, the accessibility framework can preserve the selected // state of the dragging item. @@ -441,7 +438,7 @@ class _ReorderableFlexContentState extends State<_ReorderableFlexContent> _ghostIndex = index; _currentIndex = index; _entranceController.value = 1.0; - _draggingFeedbackSize = keyIndexGlobalKey.currentContext.size; + _draggingFeedbackSize = keyIndexGlobalKey.currentContext?.size; }); } @@ -450,7 +447,7 @@ class _ReorderableFlexContentState extends State<_ReorderableFlexContent> // debugPrint('startIndex:$startIndex endIndex:$endIndex'); if (startIndex != endIndex) widget.onReorder(startIndex, endIndex); - else if (widget.onNoReorder != null) widget.onNoReorder(startIndex); + else if (widget.onNoReorder != null) widget.onNoReorder!(startIndex); // Animates leftover space in the drop area closed. // TODO(djshuckerow): bring the animation in line with the Material // specifications. @@ -495,34 +492,31 @@ class _ReorderableFlexContentState extends State<_ReorderableFlexContent> final MaterialLocalizations localizations = MaterialLocalizations.of(context); - if (localizations != null) { - // If the item can move to before its current position in the list. - if (index > 0) { - semanticsActions[CustomSemanticsAction( - label: localizations.reorderItemToStart)] = moveToStart; - String reorderItemBefore = localizations.reorderItemUp; - if (widget.direction == Axis.horizontal) { - reorderItemBefore = Directionality.of(context) == TextDirection.ltr - ? localizations.reorderItemLeft - : localizations.reorderItemRight; - } - semanticsActions[CustomSemanticsAction(label: reorderItemBefore)] = - moveBefore; + if (index > 0) { + semanticsActions[CustomSemanticsAction( + label: localizations.reorderItemToStart)] = moveToStart; + String reorderItemBefore = localizations.reorderItemUp; + if (widget.direction == Axis.horizontal) { + reorderItemBefore = Directionality.of(context) == TextDirection.ltr + ? localizations.reorderItemLeft + : localizations.reorderItemRight; } + semanticsActions[CustomSemanticsAction(label: reorderItemBefore)] = + moveBefore; + } - // If the item can move to after its current position in the list. - if (index < widget.children.length - 1) { - String reorderItemAfter = localizations.reorderItemDown; - if (widget.direction == Axis.horizontal) { - reorderItemAfter = Directionality.of(context) == TextDirection.ltr - ? localizations.reorderItemRight - : localizations.reorderItemLeft; - } - semanticsActions[CustomSemanticsAction(label: reorderItemAfter)] = - moveAfter; - semanticsActions[CustomSemanticsAction( - label: localizations.reorderItemToEnd)] = moveToEnd; + // If the item can move to after its current position in the list. + if (index < widget.children.length - 1) { + String reorderItemAfter = localizations.reorderItemDown; + if (widget.direction == Axis.horizontal) { + reorderItemAfter = Directionality.of(context) == TextDirection.ltr + ? localizations.reorderItemRight + : localizations.reorderItemLeft; } + semanticsActions[CustomSemanticsAction(label: reorderItemAfter)] = + moveAfter; + semanticsActions[CustomSemanticsAction( + label: localizations.reorderItemToEnd)] = moveToEnd; } // We pass toWrap with a GlobalKey into the Draggable so that when a list @@ -566,7 +560,7 @@ class _ReorderableFlexContentState extends State<_ReorderableFlexContent> ); } - Widget buildDragTarget(BuildContext context, List acceptedCandidates, + Widget buildDragTarget(BuildContext context, List acceptedCandidates, List rejectedCandidates) { final Widget toWrapWithSemantics = wrapWithSemantics(); @@ -574,7 +568,7 @@ class _ReorderableFlexContentState extends State<_ReorderableFlexContent> // RenderRepaintBoundary renderObject = _contentKey.currentContext.findRenderObject(); // BoxConstraints contentSizeConstraints = BoxConstraints.loose(renderObject.size); BoxConstraints contentSizeConstraints = BoxConstraints.loose( - _draggingFeedbackSize); //renderObject.constraints + _draggingFeedbackSize!); //renderObject.constraints // debugPrint('${DateTime.now().toString().substring(5, 22)} reorderable_flex.dart(515) $this.buildDragTarget: contentConstraints:$contentSizeConstraints _draggingFeedbackSize:$_draggingFeedbackSize'); return (widget.buildDraggableFeedback ?? defaultBuildDraggableFeedback)( context, contentSizeConstraints, toWrap); @@ -716,7 +710,7 @@ class _ReorderableFlexContentState extends State<_ReorderableFlexContent> return Builder(builder: (BuildContext context) { Widget dragTarget = DragTarget( builder: buildDragTarget, - onWillAccept: (Key toAccept) { + onWillAccept: (Key? toAccept) { bool willAccept = _dragging == toAccept && toAccept != toWrap.key; // debugPrint('${DateTime.now().toString().substring(5, 22)} reorderable_flex.dart(609) $this._wrap: ' @@ -744,7 +738,7 @@ class _ReorderableFlexContentState extends State<_ReorderableFlexContent> return willAccept; //_dragging == toAccept && toAccept != toWrap.key; }, onAccept: (Key accepted) {}, - onLeave: (Object leaving) {}, + onLeave: (Object? leaving) {}, ); dragTarget = KeyedSubtree(key: keyIndexGlobalKey, child: dragTarget); @@ -831,13 +825,13 @@ class _ReorderableFlexContentState extends State<_ReorderableFlexContent> // return LayoutBuilder(builder: (BuildContext context, BoxConstraints constraints) { final List wrappedChildren = []; if (widget.header != null) { - wrappedChildren.add(widget.header); + wrappedChildren.add(widget.header!); } for (int i = 0; i < widget.children.length; i += 1) { wrappedChildren.add(_wrap(widget.children[i], i)); } if (widget.footer != null) { - wrappedChildren.add(widget.footer); + wrappedChildren.add(widget.footer!); } // const Key endWidgetKey = Key('DraggableList - End Widget'); // Widget finalDropArea; @@ -960,25 +954,25 @@ class _ReorderableFlexContentState extends State<_ReorderableFlexContent> /// * [ReorderableColumn], for a version of this widget that is always vertical. class ReorderableRow extends ReorderableFlex { ReorderableRow({ - Key key, - Widget header, - Widget footer, - ReorderCallback onReorder, - EdgeInsets padding, + required ReorderCallback onReorder, + Key? key, + Widget? header, + Widget? footer, + EdgeInsets? padding, MainAxisAlignment mainAxisAlignment = MainAxisAlignment.start, MainAxisSize mainAxisSize = MainAxisSize.max, CrossAxisAlignment crossAxisAlignment = CrossAxisAlignment.center, - TextDirection textDirection, + TextDirection? textDirection, VerticalDirection verticalDirection = VerticalDirection.down, - TextBaseline textBaseline, + TextBaseline? textBaseline, List children = const [], - BuildDraggableFeedback buildDraggableFeedback, - NoReorderCallback onNoReorder, - ScrollController scrollController, + BuildDraggableFeedback? buildDraggableFeedback, + NoReorderCallback? onNoReorder, + ScrollController? scrollController, bool needsLongPressDraggable = true, double draggingWidgetOpacity = 0.2, - Duration reorderAnimationDuration, - Duration scrollAnimationDuration, + Duration? reorderAnimationDuration, + Duration? scrollAnimationDuration, bool ignorePrimaryScrollController = false, }) : super( key: key, @@ -1039,25 +1033,25 @@ class ReorderableRow extends ReorderableFlex { /// * [ReorderableRow], for a version of this widget that is always horizontal. class ReorderableColumn extends ReorderableFlex { ReorderableColumn({ - Key key, - Widget header, - Widget footer, - ReorderCallback onReorder, - EdgeInsets padding, + required ReorderCallback onReorder, + Key? key, + Widget? header, + Widget? footer, + EdgeInsets? padding, MainAxisAlignment mainAxisAlignment = MainAxisAlignment.start, MainAxisSize mainAxisSize = MainAxisSize.max, CrossAxisAlignment crossAxisAlignment = CrossAxisAlignment.center, - TextDirection textDirection, + TextDirection? textDirection, VerticalDirection verticalDirection = VerticalDirection.down, - TextBaseline textBaseline, + TextBaseline? textBaseline, List children = const [], - BuildDraggableFeedback buildDraggableFeedback, - NoReorderCallback onNoReorder, - ScrollController scrollController, + BuildDraggableFeedback? buildDraggableFeedback, + NoReorderCallback? onNoReorder, + ScrollController? scrollController, bool needsLongPressDraggable = true, double draggingWidgetOpacity = 0.2, - Duration reorderAnimationDuration = const Duration(milliseconds: 200), - Duration scrollAnimationDuration = const Duration(milliseconds: 200), + Duration? reorderAnimationDuration, + Duration? scrollAnimationDuration, bool ignorePrimaryScrollController = false, }) : super( key: key, diff --git a/lib/src/widgets/reorderable_mixin.dart b/lib/src/widgets/reorderable_mixin.dart index 96bc273..cbe44d0 100644 --- a/lib/src/widgets/reorderable_mixin.dart +++ b/lib/src/widgets/reorderable_mixin.dart @@ -7,7 +7,7 @@ mixin ReorderableMixin { Widget makeAppearingWidget( Widget child, AnimationController entranceController, - Size draggingFeedbackSize, + Size? draggingFeedbackSize, Axis direction, ) { if (null == draggingFeedbackSize) { @@ -35,7 +35,7 @@ mixin ReorderableMixin { Widget makeDisappearingWidget( Widget child, AnimationController ghostController, - Size draggingFeedbackSize, + Size? draggingFeedbackSize, Axis direction, ) { if (null == draggingFeedbackSize) { diff --git a/lib/src/widgets/reorderable_sliver.dart b/lib/src/widgets/reorderable_sliver.dart index 3366b1f..8044f61 100644 --- a/lib/src/widgets/reorderable_sliver.dart +++ b/lib/src/widgets/reorderable_sliver.dart @@ -19,10 +19,10 @@ import './reorderable_mixin.dart'; int _kDefaultSemanticIndexCallback(Widget _, int localIndex) => localIndex; mixin _ReorderableSliverChildDelegateMixin { - Widget Function(Widget toWrap, int index) _wrap; + Widget Function(Widget toWrap, int index)? _wrap; set wrap(Function value) { - _wrap = value; + _wrap = value as Widget Function(Widget toWrap, int index)?; } } @@ -48,7 +48,7 @@ class ReorderableSliverChildBuilderDelegate extends SliverChildBuilderDelegate /// null. ReorderableSliverChildBuilderDelegate( IndexedWidgetBuilder builder, { - int childCount, + int? childCount, bool addAutomaticKeepAlives = true, bool addRepaintBoundaries = true, bool addSemanticIndexes = true, @@ -84,11 +84,10 @@ class ReorderableSliverChildBuilderDelegate extends SliverChildBuilderDelegate // } @override - Widget build(BuildContext context, int index) { + Widget? build(BuildContext context, int index) { // Widget child = super.build(context, index); - assert(builder != null); - if (index < 0 || (childCount != null && index >= childCount)) return null; - Widget child = builder(context, index); + if (index < 0 || (childCount != null && index >= childCount!)) return null; + Widget? child = builder(context, index); // try { // child = builder(context, index); // } catch (exception, stackTrace) { @@ -97,7 +96,7 @@ class ReorderableSliverChildBuilderDelegate extends SliverChildBuilderDelegate if (child == null) return null; if (addRepaintBoundaries) child = RepaintBoundary.wrap(child, index); if (addSemanticIndexes) { - final int semanticIndex = semanticIndexCallback(child, index); + final int? semanticIndex = semanticIndexCallback(child, index); if (semanticIndex != null) child = IndexedSemantics( index: semanticIndex + semanticIndexOffset, child: child); @@ -110,7 +109,7 @@ class ReorderableSliverChildBuilderDelegate extends SliverChildBuilderDelegate // child: child // ); - child = _wrap(child, index); + child = _wrap!(child, index); if (addAutomaticKeepAlives) child = AutomaticKeepAlive(child: child); return child; @@ -159,16 +158,14 @@ class ReorderableSliverChildListDelegate extends SliverChildListDelegate true; @override - Widget build(BuildContext context, int index) { + Widget? build(BuildContext context, int index) { // Widget child = super.build(context, index); - assert(children != null); if (index < 0 || index >= children.length) return null; Widget child = children[index]; // debugPrint('${DateTime.now().toString().substring(5, 22)} reorderable_sliver.dart(97) $this.build: index:$index child:$child'); - assert(child != null); if (addRepaintBoundaries) child = RepaintBoundary.wrap(child, index); if (addSemanticIndexes) { - final int semanticIndex = semanticIndexCallback(child, index); + final int? semanticIndex = semanticIndexCallback(child, index); if (semanticIndex != null) child = IndexedSemantics( index: semanticIndex + semanticIndexOffset, child: child); @@ -182,7 +179,7 @@ class ReorderableSliverChildListDelegate extends SliverChildListDelegate // child: child // ); - child = _wrap(child, index); + child = _wrap!(child, index); if (addAutomaticKeepAlives) child = AutomaticKeepAlive(child: child); return child; @@ -241,9 +238,8 @@ class ReorderableSliverChildListDelegate extends SliverChildListDelegate class ReorderableSliverList extends StatefulWidget { /// Creates a reorderable list. ReorderableSliverList({ - Key key, - @required this.delegate, - @required this.onReorder, + required this.delegate, + required this.onReorder, this.buildItemsContainer, this.buildDraggableFeedback, this.onNoReorder, @@ -251,8 +247,10 @@ class ReorderableSliverList extends StatefulWidget { this.onDragStart, this.onDragEnd, this.enabled = true, - }): assert(onReorder != null && delegate != null), - super(key: key); + this.controller, + Key? key, + }) : super(key: key); + /// The delegate that provides the children for this widget. /// /// The children are constructed lazily using this widget to avoid creating @@ -268,30 +266,31 @@ class ReorderableSliverList extends StatefulWidget { /// Called when a child is dropped into a new position to shuffle the /// children. final ReorderCallback onReorder; - final NoReorderCallback onNoReorder; + final NoReorderCallback? onNoReorder; /// Called when a drag process is started - final VoidCallback onDragStart; + final VoidCallback? onDragStart; + /// Called when the drag process has ended, either via [Draggable.onDraggableCanceled] or [Draggable.onDragCompleted] - final VoidCallback onDragEnd; + final VoidCallback? onDragEnd; /// Called when the draggable starts being dragged. - final ReorderStartedCallback onReorderStarted; + final ReorderStartedCallback? onReorderStarted; - final BuildItemsContainer buildItemsContainer; - final BuildDraggableFeedback buildDraggableFeedback; + final BuildItemsContainer? buildItemsContainer; + final BuildDraggableFeedback? buildDraggableFeedback; /// Sets whether the children are reorderable or not final bool enabled; + final ScrollController? controller; + @override _ReorderableSliverListState createState() => _ReorderableSliverListState(); } class _ReorderableSliverListState extends State - with TickerProviderStateMixin, ReorderableMixin -{ - + with TickerProviderStateMixin, ReorderableMixin { // The extent along the [widget.scrollDirection] axis to allow a child to // drop into when the user reorders list children. // @@ -310,24 +309,24 @@ class _ReorderableSliverListState extends State static const Duration _scrollAnimationDuration = Duration(milliseconds: 200); // Controls scrolls and measures scroll progress. - ScrollController _scrollController; - ScrollPosition _attachedScrollPosition; + late ScrollController _scrollController; + ScrollPosition? _attachedScrollPosition; // This controls the entrance of the dragging widget into a new place. - AnimationController _entranceController; + late AnimationController _entranceController; // This controls the 'ghost' of the dragging widget, which is left behind // where the widget used to be. - AnimationController _ghostController; + late AnimationController _ghostController; // The member of widget.children currently being dragged. // // Null if no drag is underway. // Key _dragging; - Widget _draggingWidget; + Widget? _draggingWidget; // The last computed size of the feedback widget being dragged. - Size _draggingFeedbackSize; + Size? _draggingFeedbackSize; // BuildContext _draggingContext; @@ -349,7 +348,7 @@ class _ReorderableSliverListState extends State // final GlobalKey _contentKey = GlobalKey(debugLabel: '$ReorderableSliverList content key'); - int _childCount; + late int _childCount; final Map _setStateMap = {}; final List _spacedIndexes = []; @@ -358,7 +357,7 @@ class _ReorderableSliverListState extends State if (_draggingFeedbackSize == null) { return Size(0, 0); } - return _draggingFeedbackSize + Offset(_dropAreaMargin, _dropAreaMargin); + return _draggingFeedbackSize! + Offset(_dropAreaMargin, _dropAreaMargin); } @override @@ -379,23 +378,19 @@ class _ReorderableSliverListState extends State @override void didChangeDependencies() { - if (_scrollController != null && _attachedScrollPosition != null) { - _scrollController.detach(_attachedScrollPosition); + if (_attachedScrollPosition != null) { + _scrollController.detach(_attachedScrollPosition!); _attachedScrollPosition = null; } _scrollController = - PrimaryScrollController.of(context) ?? ScrollController(); + widget.controller ?? PrimaryScrollController.of(context) ?? ScrollController(); - if (!_scrollController.hasClients) { - ScrollableState scrollableState = Scrollable.of(context); - _attachedScrollPosition = scrollableState?.position; - } else { - _attachedScrollPosition = null; - } + _attachedScrollPosition = + _scrollController.hasClients ? null : Scrollable.of(context)?.position; if (_attachedScrollPosition != null) { - _scrollController.attach(_attachedScrollPosition); + _scrollController.attach(_attachedScrollPosition!); } super.didChangeDependencies(); @@ -403,8 +398,8 @@ class _ReorderableSliverListState extends State @override void dispose() { - if (_scrollController != null && _attachedScrollPosition != null) { - _scrollController.detach(_attachedScrollPosition); + if (_attachedScrollPosition != null) { + _scrollController.detach(_attachedScrollPosition!); _attachedScrollPosition = null; } _entranceController.dispose(); @@ -428,7 +423,7 @@ class _ReorderableSliverListState extends State // Animates the droppable space from _currentIndex to _nextIndex. void _requestAnimationToNextIndex( - {bool isAcceptingNewTarget = false, int updatingIndex}) { + {bool isAcceptingNewTarget = false, int? updatingIndex}) { // debugPrint('${DateTime.now().toString().substring(5, 22)} reorderable_sliver.dart(345) $this._requestAnimationToNextIndex: ' // '_dragStartIndex:$_dragStartIndex _ghostIndex:$_ghostIndex _currentIndex:$_currentIndex _nextIndex:$_nextIndex isAcceptingNewTarget:$isAcceptingNewTarget isCompleted:${_entranceController.isCompleted}'); @@ -478,7 +473,7 @@ class _ReorderableSliverListState extends State if (_setStateMap[index] == null) { // debugPrint('${DateTime.now().toString().substring(5, 22)} reorderable_sliver.dart(394) $this._setState: index:$index _setStateMap:$_setStateMap'); } - _setStateMap[index](_setState); + _setStateMap[index]!(_setState); } else { _update(); } @@ -500,10 +495,9 @@ class _ReorderableSliverListState extends State // Scrolls to a target context if that context is not on the screen. void _scrollTo(BuildContext context) { if (_scrolling) return; - final RenderObject contextObject = context.findRenderObject(); + final RenderObject contextObject = context.findRenderObject()!; final RenderAbstractViewport viewport = - RenderAbstractViewport.of(contextObject); - assert(viewport != null); + RenderAbstractViewport.of(contextObject)!; // if (_scrollController.positions.isEmpty) { // debugPrint('${DateTime.now().toString().substring(5, 22)} reorderable_sliver.dart(537) $this._scrollTo: empty pos'); @@ -555,7 +549,7 @@ class _ReorderableSliverListState extends State // Wraps children in Row or Column, so that the children flow in // the widget's scrollDirection. - Widget _buildContainerForMainAxis({List children}) { + Widget _buildContainerForMainAxis({required List children}) { var column = Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, @@ -582,14 +576,14 @@ class _ReorderableSliverListState extends State Widget _statefulWrap(Widget toWrap, int index, StateSetter setState) { // assert(toWrap.key != null); // final GlobalObjectKey keyIndexGlobalKey = GlobalObjectKey(toWrap.key); - BuildContext draggableContext; + BuildContext? draggableContext; // We pass the toWrapWithGlobalKey into the Draggable so that when a list // item gets dragged, the accessibility framework can preserve the selected // state of the dragging item. // Starts dragging toWrap. void onDragStarted() { - if (widget.onDragStart != null) widget.onDragStart(); + if (widget.onDragStart != null) widget.onDragStart!(); // debugPrint('${DateTime.now().toString().substring(5, 22)} reorderable_sliver.dart(419) $this.onDragStarted: index:$index'); setState(() { _draggingWidget = toWrap; @@ -599,11 +593,11 @@ class _ReorderableSliverListState extends State _currentIndex = index; _entranceController.value = 1.0; _draggingFeedbackSize = - draggableContext.size; //keyIndexGlobalKey.currentContext.size; + draggableContext!.size; //keyIndexGlobalKey.currentContext.size; // _draggingContext = draggableContext; }); if (widget.onReorderStarted != null) { - widget.onReorderStarted(index); + widget.onReorderStarted!(index); } } @@ -612,7 +606,7 @@ class _ReorderableSliverListState extends State // debugPrint('startIndex:$startIndex endIndex:$endIndex'); if (startIndex != endIndex) widget.onReorder(startIndex, endIndex); - else if (widget.onNoReorder != null) widget.onNoReorder(startIndex); + else if (widget.onNoReorder != null) widget.onNoReorder!(startIndex); // Animates leftover space in the drop area closed. // TODO(djshuckerow): bring the animation in line with the Material // specifications. @@ -634,7 +628,7 @@ class _ReorderableSliverListState extends State // Drops toWrap into the last position it was hovering over. void onDragEnded() { // reorder(_dragStartIndex, _currentIndex); - if (widget.onDragEnd != null) widget.onDragEnd(); + if (widget.onDragEnd != null) widget.onDragEnd!(); this.setState(() { void _update() { _reorder(_dragStartIndex, _currentIndex); @@ -653,7 +647,7 @@ class _ReorderableSliverListState extends State void _setState() { if (updateIndexes.length > 0) { int index = updateIndexes.removeLast(); - _setStateMap[index](_setState); + _setStateMap[index]!(_setState); } else { _update(); } @@ -679,34 +673,31 @@ class _ReorderableSliverListState extends State final MaterialLocalizations localizations = MaterialLocalizations.of(context); - if (localizations != null) { - // If the item can move to before its current position in the list. - if (index > 0) { - semanticsActions[CustomSemanticsAction( - label: localizations.reorderItemToStart)] = moveToStart; - String reorderItemBefore = localizations.reorderItemUp; + if (index > 0) { + semanticsActions[CustomSemanticsAction( + label: localizations.reorderItemToStart)] = moveToStart; + String reorderItemBefore = localizations.reorderItemUp; // if (widget.direction == Axis.horizontal) { // reorderItemBefore = Directionality.of(context) == TextDirection.ltr // ? localizations.reorderItemLeft // : localizations.reorderItemRight; // } - semanticsActions[CustomSemanticsAction(label: reorderItemBefore)] = - moveBefore; - } + semanticsActions[CustomSemanticsAction(label: reorderItemBefore)] = + moveBefore; + } - // If the item can move to after its current position in the list. - if (index < _childCount - 1) { - String reorderItemAfter = localizations.reorderItemDown; + // If the item can move to after its current position in the list. + if (index < _childCount - 1) { + String reorderItemAfter = localizations.reorderItemDown; // if (widget.direction == Axis.horizontal) { // reorderItemAfter = Directionality.of(context) == TextDirection.ltr // ? localizations.reorderItemRight // : localizations.reorderItemLeft; // } - semanticsActions[CustomSemanticsAction(label: reorderItemAfter)] = - moveAfter; - semanticsActions[CustomSemanticsAction( - label: localizations.reorderItemToEnd)] = moveToEnd; - } + semanticsActions[CustomSemanticsAction(label: reorderItemAfter)] = + moveAfter; + semanticsActions[CustomSemanticsAction( + label: localizations.reorderItemToEnd)] = moveToEnd; } // We pass toWrap with a GlobalKey into the Draggable so that when a list @@ -733,14 +724,24 @@ class _ReorderableSliverListState extends State } Widget _makeAppearingWidget(Widget child) { - return makeAppearingWidget(child, _entranceController, _draggingFeedbackSize, Axis.vertical,); + return makeAppearingWidget( + child, + _entranceController, + _draggingFeedbackSize, + Axis.vertical, + ); } Widget _makeDisappearingWidget(Widget child) { - return makeDisappearingWidget(child, _ghostController, _draggingFeedbackSize, Axis.vertical,); + return makeDisappearingWidget( + child, + _ghostController, + _draggingFeedbackSize, + Axis.vertical, + ); } - Widget buildDragTarget(BuildContext context, List acceptedCandidates, + Widget buildDragTarget(BuildContext context, List acceptedCandidates, List rejectedCandidates) { final Widget toWrapWithSemantics = wrapWithSemantics(); @@ -748,7 +749,7 @@ class _ReorderableSliverListState extends State // RenderRepaintBoundary renderObject = _contentKey.currentContext.findRenderObject(); // BoxConstraints contentSizeConstraints = BoxConstraints.loose(renderObject.size); BoxConstraints contentSizeConstraints = BoxConstraints.loose( - _draggingFeedbackSize); //renderObject.constraints + _draggingFeedbackSize!); //renderObject.constraints // debugPrint('${DateTime.now().toString().substring(5, 22)} reorderable_flex.dart(515) $this.buildDragTarget: contentConstraints:$contentSizeConstraints _draggingFeedbackSize:$_draggingFeedbackSize'); return (widget.buildDraggableFeedback ?? defaultBuildDraggableFeedback)( context, contentSizeConstraints, toWrap); @@ -766,7 +767,7 @@ class _ReorderableSliverListState extends State // We build the draggable inside of a layout builder so that we can // constrain the size of the feedback dragging widget. child = LongPressDraggable( - maxSimultaneousDrags: widget.enabled?1:0, + maxSimultaneousDrags: widget.enabled ? 1 : 0, axis: Axis.vertical, //widget.direction, data: index, @@ -799,17 +800,14 @@ class _ReorderableSliverListState extends State child: toWrapWithSemantics, behavior: HitTestBehavior.opaque), //toWrapWithSemantics,//_dragging == toWrap.key ? const SizedBox() : toWrapWithSemantics, childWhenDragging: IgnorePointer( - ignoring: true, - child: SizedBox( - // Small values (<50) cause an error when used with ListTile. - width: double.infinity, - child: Opacity( - opacity: 0, + ignoring: true, + child: SizedBox( + // Small values (<50) cause an error when used with ListTile. + width: double.infinity, + child: Opacity( + opacity: 0, // child: _makeAppearingWidget(toWrap) - child: Container(width: 0, height: 0, child: toWrap) - ) - ) - ), + child: Container(width: 0, height: 0, child: toWrap)))), //ConstrainedBox(constraints: contentConstraints),//SizedBox(), dragAnchor: DragAnchor.child, onDragStarted: onDragStarted, @@ -850,7 +848,7 @@ class _ReorderableSliverListState extends State return Builder(builder: (BuildContext context) { Widget dragTarget = DragTarget( builder: buildDragTarget, - onWillAccept: (int toAccept) { + onWillAccept: (int? toAccept) { bool willAccept = _dragStartIndex == toAccept && toAccept != index; // debugPrint('${DateTime.now().toString().substring(5, 22)} reorderable_sliver.dart(679) $this._statefulWrap: ' // 'onWillAccept: toAccept:$toAccept return:$willAccept _nextIndex:$_nextIndex index:$index _currentIndex:$_currentIndex _dragStartIndex:$_dragStartIndex'); @@ -880,7 +878,7 @@ class _ReorderableSliverListState extends State return willAccept; //_dragging == toAccept && toAccept != toWrap.key; }, onAccept: (int accepted) {}, - onLeave: (Object leaving) {}, + onLeave: (Object? leaving) {}, ); // dragTarget = KeyedSubtree( @@ -960,8 +958,8 @@ class _ReorderableSliverListState extends State assert(widget.delegate is _ReorderableSliverChildDelegateMixin); if (widget.delegate is ReorderableSliverChildBuilderDelegate) { - _childCount = - (widget.delegate as ReorderableSliverChildBuilderDelegate).childCount; + _childCount = (widget.delegate as ReorderableSliverChildBuilderDelegate) + .childCount!; } else if (widget.delegate is ReorderableSliverChildListDelegate) { _childCount = (widget.delegate as ReorderableSliverChildListDelegate) .children diff --git a/lib/src/widgets/reorderable_table.dart b/lib/src/widgets/reorderable_table.dart index 7db1345..d94210b 100644 --- a/lib/src/widgets/reorderable_table.dart +++ b/lib/src/widgets/reorderable_table.dart @@ -8,18 +8,17 @@ import '../rendering/tabluar_flex.dart'; class ReorderableTableRow extends TabluarRow { ReorderableTableRow({ - Key key, MainAxisAlignment mainAxisAlignment = MainAxisAlignment.start, MainAxisSize mainAxisSize = MainAxisSize.max, CrossAxisAlignment crossAxisAlignment = CrossAxisAlignment.center, - TextDirection textDirection, + TextDirection? textDirection, VerticalDirection verticalDirection = VerticalDirection.down, - TextBaseline textBaseline, + TextBaseline? textBaseline, List children = const [], - Decoration decoration, + Decoration? decoration, + Key? key, }) : super( children: children, - key: key, mainAxisAlignment: mainAxisAlignment, mainAxisSize: mainAxisSize, crossAxisAlignment: crossAxisAlignment, @@ -27,6 +26,7 @@ class ReorderableTableRow extends TabluarRow { verticalDirection: verticalDirection, textBaseline: textBaseline, decoration: decoration, + key: key, ); } @@ -56,7 +56,7 @@ class ReorderableTable extends StatelessWidget { /// The [children], [defaultColumnWidth], and [defaultVerticalAlignment] /// arguments must not be null. ReorderableTable({ - Key key, + required this.onReorder, this.children = const [], this.columnWidths, this.defaultColumnWidth = const FlexColumnWidth(1.0), @@ -66,26 +66,13 @@ class ReorderableTable extends StatelessWidget { this.textBaseline, this.header, this.footer, - @required this.onReorder, this.decorateDraggableFeedback, this.onNoReorder, - thi, this.reorderAnimationDuration, this.scrollAnimationDuration, this.ignorePrimaryScrollController = false, - }) : assert(children != null), - assert(defaultColumnWidth != null), - assert(defaultVerticalAlignment != null), - assert(() { - if (children.any((ReorderableTableRow row) => - row.children.any((Widget cell) => cell == null))) { - throw FlutterError( - 'One of the children of one of the rows of the table was null.\n' - 'The children of a ReorderableTableRow must not be null.'); - } - return true; - }()), - assert(() { + Key? key, + }) : assert(() { if (children.any((ReorderableTableRow row1) => row1.key != null && children.any((ReorderableTableRow row2) => @@ -145,7 +132,7 @@ class ReorderableTable extends StatelessWidget { /// sizing algorithms are used here. In particular, [IntrinsicColumnWidth] is /// quite expensive because it needs to measure each cell in the column to /// determine the intrinsic size of the column. - final Map columnWidths; + final Map? columnWidths; /// How to determine with widths of columns that don't have an explicit sizing algorithm. /// @@ -156,32 +143,32 @@ class ReorderableTable extends StatelessWidget { /// The direction in which the columns are ordered. /// /// Defaults to the ambient [Directionality]. - final TextDirection textDirection; + final TextDirection? textDirection; /// The style to use when painting the boundary and interior divisions of the table. - final TableBorder border; + final TableBorder? border; /// How cells that do not explicitly specify a vertical alignment are aligned vertically. final TableCellVerticalAlignment defaultVerticalAlignment; /// The text baseline to use when aligning rows using [TableCellVerticalAlignment.baseline]. - final TextBaseline textBaseline; + final TextBaseline? textBaseline; /// Non-reorderable widget at top of the table. Cells in [header] also affects /// alignment of columns. - final Widget header; + final Widget? header; /// Non-reorderable widget at top of the table. Cells in [footer] also affects /// alignment of columns. - final Widget footer; + final Widget? footer; /// Called when a child is dropped into a new position to shuffle the /// children. final ReorderCallback onReorder; - final NoReorderCallback onNoReorder; - final DecorateDraggableFeedback decorateDraggableFeedback; - final Duration reorderAnimationDuration; - final Duration scrollAnimationDuration; + final NoReorderCallback? onNoReorder; + final DecorateDraggableFeedback? decorateDraggableFeedback; + final Duration? reorderAnimationDuration; + final Duration? scrollAnimationDuration; final bool ignorePrimaryScrollController; @override @@ -220,9 +207,9 @@ class ReorderableTable extends StatelessWidget { buildDraggableFeedback: (BuildContext feedbackContext, BoxConstraints constraints, Widget child) { // The child is a ReorderableTableRow because children is a List - ReorderableTableRow tableRow = child; + ReorderableTableRow tableRow = child as ReorderableTableRow; RenderTabluarFlex renderTabluarFlex = - tableKey.currentContext.findRenderObject(); + tableKey.currentContext!.findRenderObject() as RenderTabluarFlex; int grandChildIndex = 0; for (; grandChildIndex < tableRow.children.length; @@ -230,7 +217,7 @@ class ReorderableTable extends StatelessWidget { tableRow.children[grandChildIndex] = ConstrainedBox( constraints: BoxConstraints( minWidth: renderTabluarFlex - .maxGrandchildrenCrossSize[grandChildIndex]), + .maxGrandchildrenCrossSize[grandChildIndex]!), child: tableRow.children[grandChildIndex]); } for (; @@ -240,7 +227,7 @@ class ReorderableTable extends StatelessWidget { tableRow.children.add(ConstrainedBox( constraints: BoxConstraints( minWidth: renderTabluarFlex - .maxGrandchildrenCrossSize[grandChildIndex]), + .maxGrandchildrenCrossSize[grandChildIndex]!), )); } diff --git a/lib/src/widgets/reorderable_widget.dart b/lib/src/widgets/reorderable_widget.dart index 74867c5..579e7b6 100644 --- a/lib/src/widgets/reorderable_widget.dart +++ b/lib/src/widgets/reorderable_widget.dart @@ -4,11 +4,11 @@ class ReorderableWidget extends StatelessWidget implements ReorderableItem { final Widget child; final bool reorderable; - ReorderableWidget( - {@required this.child, @required this.reorderable, @required Key key}) - : assert(reorderable != null && reorderable is bool), - assert(key != null, 'A key is mandatory for each Widget'), - super(key: key); + ReorderableWidget({ + required this.child, + required this.reorderable, + required Key key, + }) : super(key: key); @override Widget build(BuildContext context) { @@ -19,5 +19,5 @@ class ReorderableWidget extends StatelessWidget implements ReorderableItem { abstract class ReorderableItem extends Widget { final bool reorderable; - ReorderableItem({@required this.reorderable}); + ReorderableItem({required this.reorderable}); } diff --git a/lib/src/widgets/reorderable_wrap.dart b/lib/src/widgets/reorderable_wrap.dart index 6db7acc..c7dbb2d 100644 --- a/lib/src/widgets/reorderable_wrap.dart +++ b/lib/src/widgets/reorderable_wrap.dart @@ -9,11 +9,9 @@ import 'package:flutter/rendering.dart'; import 'package:reorderables/reorderables.dart'; import './passthrough_overlay.dart'; - //import './transitions.dart'; import './typedefs.dart'; import './wrap.dart'; - //import './transitions.dart'; import '../rendering/wrap.dart'; import 'reorderable_mixin.dart'; @@ -36,13 +34,11 @@ import 'reorderable_mixin.dart'; class ReorderableWrap extends StatefulWidget { /// Creates a reorderable wrap. ReorderableWrap({ - Key key, + required this.children, + required this.onReorder, this.header, this.footer, this.controller, - this.enabledDragging = true, - @required this.children, - @required this.onReorder, this.direction = Axis.horizontal, this.scrollDirection = Axis.vertical, this.padding = EdgeInsets.zero, @@ -63,9 +59,9 @@ class ReorderableWrap extends StatefulWidget { this.reorderAnimationDuration = const Duration(milliseconds: 200), this.scrollAnimationDuration = const Duration(milliseconds: 200), this.ignorePrimaryScrollController = false, - }) : assert(direction != null), - assert(onReorder != null), - assert(children != null), + this.enabledDragging = true, + Key? key, + }) : // assert( // children.every((Widget w) => w.key != null), // 'All children of this widget must have a key.', @@ -75,13 +71,13 @@ class ReorderableWrap extends StatefulWidget { /// A non-reorderable header widget to show before the list. /// /// If null, no header will appear before the list. - final List header; - final Widget footer; + final List? header; + final Widget? footer; /// A custom scroll [controller]. /// To control the initial scroll offset of the scroll view, provide a /// [controller] with its [ScrollController.initialScrollOffset] property set. - final ScrollController controller; + final ScrollController? controller; /// The widgets to display. final List children; @@ -96,18 +92,18 @@ class ReorderableWrap extends StatefulWidget { final Axis scrollDirection; /// The amount of space by which to inset the [children]. - final EdgeInsets padding; + final EdgeInsets? padding; /// Called when a child is dropped into a new position to shuffle the /// children. final ReorderCallback onReorder; - final NoReorderCallback onNoReorder; + final NoReorderCallback? onNoReorder; /// Called when the draggable starts being dragged. - final ReorderStartedCallback onReorderStarted; + final ReorderStartedCallback? onReorderStarted; - final BuildItemsContainer buildItemsContainer; - final BuildDraggableFeedback buildDraggableFeedback; + final BuildItemsContainer? buildItemsContainer; + final BuildDraggableFeedback? buildDraggableFeedback; /// The flag of whether needs long press to trigger dragging mode. /// true means it needs long press and false means no need. @@ -211,7 +207,7 @@ class ReorderableWrap extends StatefulWidget { /// [crossAxisAlignment] is either [WrapCrossAlignment.start] or /// [WrapCrossAlignment.end], or there's more than one child, then the /// [textDirection] (or the ambient [Directionality]) must not be null. - final TextDirection textDirection; + final TextDirection? textDirection; /// Determines the order to lay children out vertically and how to interpret /// `start` and `end` in the vertical direction. @@ -237,8 +233,8 @@ class ReorderableWrap extends StatefulWidget { /// [verticalDirection] must not be null. final VerticalDirection verticalDirection; - final int minMainAxisCount; - final int maxMainAxisCount; + final int? minMainAxisCount; + final int? maxMainAxisCount; final Duration reorderAnimationDuration; final Duration scrollAnimationDuration; final bool ignorePrimaryScrollController; @@ -260,11 +256,10 @@ class ReorderableWrap extends StatefulWidget { // insert Draggables into the Overlay above itself. class _ReorderableWrapState extends State { // We use an inner overlay so that the dragging list item doesn't draw outside of the list itself. - final GlobalKey _overlayKey = - GlobalKey(debugLabel: '$ReorderableWrap overlay key'); + final GlobalKey _overlayKey = GlobalKey(debugLabel: '$ReorderableWrap overlay key'); // This entry contains the scrolling list itself. - PassthroughOverlayEntry _listOverlayEntry; + late PassthroughOverlayEntry _listOverlayEntry; @override void initState() { @@ -281,7 +276,7 @@ class _ReorderableWrapState extends State { onReorder: widget.onReorder, onNoReorder: widget.onNoReorder, onReorderStarted: widget.onReorderStarted, - padding: widget.padding, + padding: widget.padding ?? EdgeInsets.zero, buildItemsContainer: widget.buildItemsContainer, buildDraggableFeedback: widget.buildDraggableFeedback, needsLongPressDraggable: widget.needsLongPressDraggable, @@ -305,11 +300,10 @@ class _ReorderableWrapState extends State { @override Widget build(BuildContext context) { - final PassthroughOverlay passthroughOverlay = PassthroughOverlay( - key: _overlayKey, - initialEntries: [ - _listOverlayEntry, - ]); + final PassthroughOverlay passthroughOverlay = + PassthroughOverlay(key: _overlayKey, initialEntries: [ + _listOverlayEntry, + ]); return widget.ignorePrimaryScrollController ? PrimaryScrollController.none(child: passthroughOverlay) : passthroughOverlay; @@ -320,45 +314,45 @@ class _ReorderableWrapState extends State { // ReorderableListView. class _ReorderableWrapContent extends StatefulWidget { const _ReorderableWrapContent({ + required this.children, + required this.direction, + required this.scrollDirection, + required this.padding, + required this.onReorder, + required this.onNoReorder, + required this.onReorderStarted, + required this.buildItemsContainer, + required this.buildDraggableFeedback, + required this.needsLongPressDraggable, + required this.alignment, + required this.spacing, + required this.runAlignment, + required this.runSpacing, + required this.crossAxisAlignment, + required this.textDirection, + required this.verticalDirection, + required this.minMainAxisCount, + required this.maxMainAxisCount, this.header, this.footer, this.controller, - @required this.children, - @required this.direction, - @required this.scrollDirection, - @required this.padding, - @required this.onReorder, - @required this.onNoReorder, - @required this.onReorderStarted, - @required this.buildItemsContainer, - @required this.buildDraggableFeedback, - @required this.needsLongPressDraggable, - @required this.alignment, - @required this.spacing, - @required this.runAlignment, - @required this.runSpacing, - @required this.crossAxisAlignment, - @required this.textDirection, - @required this.verticalDirection, - @required this.minMainAxisCount, - @required this.maxMainAxisCount, - @required this.reorderAnimationDuration, - @required this.scrollAnimationDuration, - @required this.enableDragging, + this.reorderAnimationDuration = const Duration(milliseconds: 200), + this.scrollAnimationDuration = const Duration(milliseconds: 200), + this.enableDragging = true, }); - final List header; - final Widget footer; - final ScrollController controller; + final List? header; + final Widget? footer; + final ScrollController? controller; final List children; final Axis direction; final Axis scrollDirection; final EdgeInsets padding; final ReorderCallback onReorder; - final NoReorderCallback onNoReorder; - final ReorderStartedCallback onReorderStarted; - final BuildItemsContainer buildItemsContainer; - final BuildDraggableFeedback buildDraggableFeedback; + final NoReorderCallback? onNoReorder; + final ReorderStartedCallback? onReorderStarted; + final BuildItemsContainer? buildItemsContainer; + final BuildDraggableFeedback? buildDraggableFeedback; final bool needsLongPressDraggable; final WrapAlignment alignment; @@ -366,13 +360,13 @@ class _ReorderableWrapContent extends StatefulWidget { final WrapAlignment runAlignment; final double runSpacing; final WrapCrossAlignment crossAxisAlignment; - final TextDirection textDirection; + final TextDirection? textDirection; final VerticalDirection verticalDirection; - final int minMainAxisCount; - final int maxMainAxisCount; - final bool enableDragging; + final int? minMainAxisCount; + final int? maxMainAxisCount; final Duration reorderAnimationDuration; final Duration scrollAnimationDuration; + final bool enableDragging; @override _ReorderableWrapContentState createState() => _ReorderableWrapContentState(); @@ -391,36 +385,36 @@ class _ReorderableWrapContentState extends State<_ReorderableWrapContent> static const double _dropAreaMargin = 0.0; // How long an animation to reorder an element in the list takes. - Duration _reorderAnimationDuration; + late Duration _reorderAnimationDuration; // How long an animation to scroll to an off-screen element in the // list takes. - Duration _scrollAnimationDuration; + late Duration _scrollAnimationDuration; // Controls scrolls and measures scroll progress. - ScrollController _scrollController; + late ScrollController _scrollController; // This controls the entrance of the dragging widget into a new place. - AnimationController _entranceController; + late AnimationController _entranceController; // This controls the 'ghost' of the dragging widget, which is left behind // where the widget used to be. - AnimationController _ghostController; + late AnimationController _ghostController; // The member of widget.children currently being dragged. // // Null if no drag is underway. // int _dragging; - Widget _draggingWidget; + Widget? _draggingWidget; // The last computed size of the feedback widget being dragged. - Size _draggingFeedbackSize; + Size? _draggingFeedbackSize; // List _childKeys; - List _childContexts; - List _childSizes; - List _childIndexToDisplayIndex; - List _childDisplayIndexToIndex; + late List _childContexts; + late List _childSizes; + late List _childIndexToDisplayIndex; + late List _childDisplayIndexToIndex; // The location that the dragging widget occupied before it started to drag. int _dragStartIndex = -1; @@ -439,16 +433,16 @@ class _ReorderableWrapContentState extends State<_ReorderableWrapContent> bool _scrolling = false; final GlobalKey _wrapKey = GlobalKey(debugLabel: '$ReorderableWrap wrap key'); - List _wrapChildRunIndexes; - List _childRunIndexes; - List _nextChildRunIndexes; - List _wrapChildren; + late List _wrapChildRunIndexes; + late List _childRunIndexes; + late List _nextChildRunIndexes; + late List _wrapChildren; Size get _dropAreaSize { if (_draggingFeedbackSize == null) { return Size(0, 0); } - return _draggingFeedbackSize + Offset(_dropAreaMargin, _dropAreaMargin); + return _draggingFeedbackSize! + Offset(_dropAreaMargin, _dropAreaMargin); // double dropAreaWithoutMargin; // switch (widget.direction) { // case Axis.horizontal: @@ -467,10 +461,8 @@ class _ReorderableWrapContentState extends State<_ReorderableWrapContent> super.initState(); _reorderAnimationDuration = widget.reorderAnimationDuration; _scrollAnimationDuration = widget.scrollAnimationDuration; - _entranceController = AnimationController( - value: 1.0, vsync: this, duration: _reorderAnimationDuration); - _ghostController = AnimationController( - value: 0, vsync: this, duration: _reorderAnimationDuration); + _entranceController = AnimationController(value: 1.0, vsync: this, duration: _reorderAnimationDuration); + _ghostController = AnimationController(value: 0, vsync: this, duration: _reorderAnimationDuration); _entranceController.addStatusListener(_onEntranceStatusChanged); // _childKeys = List.filled(widget.children.length, null); _childContexts = List.filled(widget.children.length, null); @@ -487,9 +479,7 @@ class _ReorderableWrapContentState extends State<_ReorderableWrapContent> @override void didChangeDependencies() { - _scrollController = widget.controller ?? - PrimaryScrollController.of(context) ?? - ScrollController(); + _scrollController = widget.controller ?? PrimaryScrollController.of(context) ?? ScrollController(); super.didChangeDependencies(); } @@ -528,16 +518,12 @@ class _ReorderableWrapContentState extends State<_ReorderableWrapContent> // Scrolls to a target context if that context is not on the screen. void _scrollTo(BuildContext context) { if (_scrolling) return; - final RenderObject contextObject = context.findRenderObject(); - final RenderAbstractViewport viewport = - RenderAbstractViewport.of(contextObject); - assert(viewport != null); + final RenderObject contextObject = context.findRenderObject()!; + final RenderAbstractViewport viewport = RenderAbstractViewport.of(contextObject)!; // If and only if the current scroll offset falls in-between the offsets // necessary to reveal the selected context at the top or bottom of the // screen, then it is already on-screen. - final double margin = widget.direction == Axis.horizontal - ? _dropAreaSize.width - : _dropAreaSize.height; + final double margin = widget.direction == Axis.horizontal ? _dropAreaSize.width : _dropAreaSize.height; final double scrollOffset = _scrollController.offset; final double topOffset = max( _scrollController.position.minScrollExtent, @@ -547,8 +533,7 @@ class _ReorderableWrapContentState extends State<_ReorderableWrapContent> _scrollController.position.maxScrollExtent, viewport.getOffsetToReveal(contextObject, 1.0).offset + margin, ); - final bool onScreen = - scrollOffset <= topOffset && scrollOffset >= bottomOffset; + final bool onScreen = scrollOffset <= topOffset && scrollOffset >= bottomOffset; // If the context is off screen, then we request a scroll to make it visible. if (!onScreen) { _scrolling = true; @@ -568,7 +553,7 @@ class _ReorderableWrapContentState extends State<_ReorderableWrapContent> // Wraps children in Row or Column, so that the children flow in // the widget's scrollDirection. - Widget _buildContainerForMainAxis({List children}) { + Widget _buildContainerForMainAxis({required List children}) { // MainAxisSize mainAxisSize = MainAxisSize.min; // CrossAxisAlignment crossAxisAlignment; WrapAlignment runAlignment; @@ -640,36 +625,32 @@ class _ReorderableWrapContentState extends State<_ReorderableWrapContent> // for (int i = 0; i < widget.children.length; i++) { // _childSizes[i] = _childKeys[i].currentContext.size; // } - _draggingFeedbackSize = _childContexts[index].size; + _draggingFeedbackSize = _childContexts[index]!.size; for (int i = 0; i < widget.children.length; i++) { - _childSizes[i] = _childContexts[i].size; + _childSizes[i] = _childContexts[i]!.size!; } if (_wrapKey.currentContext != null) { RenderWrapWithMainAxisCount wrapRenderObject = - _wrapKey.currentContext.findRenderObject(); + _wrapKey.currentContext!.findRenderObject() as RenderWrapWithMainAxisCount; _wrapChildRunIndexes = wrapRenderObject.childRunIndexes; for (int i = 0; i < _childRunIndexes.length; i++) { - _nextChildRunIndexes[i] = - _wrapChildRunIndexes[_childIndexToDisplayIndex[i]]; + _nextChildRunIndexes[i] = _wrapChildRunIndexes[_childIndexToDisplayIndex[i]]; } } else { if (widget.minMainAxisCount != null && widget.maxMainAxisCount != null && widget.minMainAxisCount == widget.maxMainAxisCount) { - _wrapChildRunIndexes = List.generate(widget.children.length, - (int index) => index ~/ widget.minMainAxisCount); + _wrapChildRunIndexes = + List.generate(widget.children.length, (int index) => index ~/ widget.minMainAxisCount!); for (int i = 0; i < _childRunIndexes.length; i++) { - _nextChildRunIndexes[i] = - _wrapChildRunIndexes[_childIndexToDisplayIndex[i]]; + _nextChildRunIndexes[i] = _wrapChildRunIndexes[_childIndexToDisplayIndex[i]]; } } } // debugPrint('onDragStarted: index:$index _ghostDisplayIndex:$_ghostDisplayIndex _currentDisplayIndex:$_currentDisplayIndex _dragStartIndex:$_dragStartIndex'); - if (widget.onReorderStarted != null) { - widget.onReorderStarted(index); - } + widget.onReorderStarted?.call(index); }); } @@ -678,7 +659,7 @@ class _ReorderableWrapContentState extends State<_ReorderableWrapContent> // debugPrint('_reorder: startIndex:$startIndex endIndex:$endIndex'); if (startIndex != endIndex) widget.onReorder(startIndex, endIndex); - else if (widget.onNoReorder != null) widget.onNoReorder(startIndex); + else if (widget.onNoReorder != null) widget.onNoReorder!(startIndex); // Animates leftover space in the drop area closed. // TODO(djshuckerow): bring the animation in line with the Material // specifications. @@ -711,8 +692,7 @@ class _ReorderableWrapContentState extends State<_ReorderableWrapContent> Widget wrapWithSemantics() { // First, determine which semantics actions apply. - final Map semanticsActions = - {}; + final Map semanticsActions = {}; // Create the appropriate semantics actions. void moveToStart() => reorder(index, 0); @@ -722,37 +702,29 @@ class _ReorderableWrapContentState extends State<_ReorderableWrapContent> // before index+2, which is after the space at index+1. void moveAfter() => reorder(index, index + 2); - final MaterialLocalizations localizations = - MaterialLocalizations.of(context); - - if (localizations != null) { - // If the item can move to before its current position in the list. - if (index > 0) { - semanticsActions[CustomSemanticsAction( - label: localizations.reorderItemToStart)] = moveToStart; - String reorderItemBefore = localizations.reorderItemUp; - if (widget.direction == Axis.horizontal) { - reorderItemBefore = Directionality.of(context) == TextDirection.ltr - ? localizations.reorderItemLeft - : localizations.reorderItemRight; - } - semanticsActions[CustomSemanticsAction(label: reorderItemBefore)] = - moveBefore; + final MaterialLocalizations localizations = MaterialLocalizations.of(context); + + if (index > 0) { + semanticsActions[CustomSemanticsAction(label: localizations.reorderItemToStart)] = moveToStart; + String reorderItemBefore = localizations.reorderItemUp; + if (widget.direction == Axis.horizontal) { + reorderItemBefore = Directionality.of(context) == TextDirection.ltr + ? localizations.reorderItemLeft + : localizations.reorderItemRight; } + semanticsActions[CustomSemanticsAction(label: reorderItemBefore)] = moveBefore; + } - // If the item can move to after its current position in the list. - if (index < widget.children.length - 1) { - String reorderItemAfter = localizations.reorderItemDown; - if (widget.direction == Axis.horizontal) { - reorderItemAfter = Directionality.of(context) == TextDirection.ltr - ? localizations.reorderItemRight - : localizations.reorderItemLeft; - } - semanticsActions[CustomSemanticsAction(label: reorderItemAfter)] = - moveAfter; - semanticsActions[CustomSemanticsAction( - label: localizations.reorderItemToEnd)] = moveToEnd; + // If the item can move to after its current position in the list. + if (index < widget.children.length - 1) { + String reorderItemAfter = localizations.reorderItemDown; + if (widget.direction == Axis.horizontal) { + reorderItemAfter = Directionality.of(context) == TextDirection.ltr + ? localizations.reorderItemRight + : localizations.reorderItemLeft; } + semanticsActions[CustomSemanticsAction(label: reorderItemAfter)] = moveAfter; + semanticsActions[CustomSemanticsAction(label: localizations.reorderItemToEnd)] = moveToEnd; } // We pass toWrap with a GlobalKey into the Draggable so that when a list @@ -803,8 +775,7 @@ class _ReorderableWrapContentState extends State<_ReorderableWrapContent> Widget feedbackBuilder = Builder(builder: (BuildContext context) { // RenderRepaintBoundary renderObject = _contentKey.currentContext.findRenderObject(); // BoxConstraints contentSizeConstraints = BoxConstraints.loose(renderObject.size); - BoxConstraints contentSizeConstraints = BoxConstraints.loose( - _draggingFeedbackSize); //renderObject.constraints + BoxConstraints contentSizeConstraints = BoxConstraints.loose(_draggingFeedbackSize!); //renderObject.constraints // debugPrint('feedbackBuilder: contentConstraints:$contentSizeConstraints'); return (widget.buildDraggableFeedback ?? defaultBuildDraggableFeedback)( context, contentSizeConstraints, toWrap); @@ -830,9 +801,7 @@ class _ReorderableWrapContentState extends State<_ReorderableWrapContent> feedback: feedbackBuilder, // Wrap toWrapWithSemantics with a widget that supports HitTestBehavior // to make sure the whole toWrapWithSemantics responds to pointer events, i.e. dragging - child: MetaData( - child: toWrapWithSemantics, - behavior: HitTestBehavior.opaque), + child: MetaData(child: toWrapWithSemantics, behavior: HitTestBehavior.opaque), //toWrapWithSemantics,//_dragging == toWrap.key ? const SizedBox() : toWrapWithSemantics, childWhenDragging: IgnorePointer( ignoring: true, @@ -849,8 +818,7 @@ class _ReorderableWrapContentState extends State<_ReorderableWrapContent> // When the drag does not end inside a DragTarget widget, the // drag fails, but we still reorder the widget to the last position it // had been dragged to. - onDraggableCanceled: (Velocity velocity, Offset offset) => - onDragEnded(), + onDraggableCanceled: (Velocity velocity, Offset offset) => onDragEnded(), ) : Draggable( maxSimultaneousDrags: widget.enableDragging ? 1 : 0, @@ -858,9 +826,7 @@ class _ReorderableWrapContentState extends State<_ReorderableWrapContent> //toWrap.key, ignoringFeedbackSemantics: false, feedback: feedbackBuilder, - child: MetaData( - child: toWrapWithSemantics, - behavior: HitTestBehavior.opaque), + child: MetaData(child: toWrapWithSemantics, behavior: HitTestBehavior.opaque), childWhenDragging: IgnorePointer( ignoring: true, child: Opacity( @@ -871,8 +837,7 @@ class _ReorderableWrapContentState extends State<_ReorderableWrapContent> dragAnchor: DragAnchor.child, onDragStarted: onDragStarted, onDragCompleted: onDragEnded, - onDraggableCanceled: (Velocity velocity, Offset offset) => - onDragEnded(), + onDraggableCanceled: (Velocity velocity, Offset offset) => onDragEnded(), ); } @@ -900,33 +865,27 @@ class _ReorderableWrapContentState extends State<_ReorderableWrapContent> // debugPrint('index:$index displayIndex:$displayIndex _nextDisplayIndex:$_nextDisplayIndex _currentDisplayIndex:$_currentDisplayIndex _ghostDisplayIndex:$_ghostDisplayIndex _dragStartIndex:$_dragStartIndex'); // debugPrint(' _childRunIndexes:$_childRunIndexes _nextChildRunIndexes:$_nextChildRunIndexes _wrapChildRunIndexes:$_wrapChildRunIndexes'); - List _includeMovedAdjacentChildIfNeeded( - Widget child, int childDisplayIndex) { + List _includeMovedAdjacentChildIfNeeded(Widget child, int childDisplayIndex) { // debugPrint(' checking ${_childDisplayIndexToIndex[childDisplayIndex]}($childDisplayIndex)'); int checkingTargetDisplayIndex = -1; - if (_ghostDisplayIndex < _currentDisplayIndex && - childDisplayIndex > _ghostDisplayIndex) { + if (_ghostDisplayIndex < _currentDisplayIndex && childDisplayIndex > _ghostDisplayIndex) { checkingTargetDisplayIndex = childDisplayIndex - 1; - } else if (_ghostDisplayIndex > _currentDisplayIndex && - childDisplayIndex < _ghostDisplayIndex) { + } else if (_ghostDisplayIndex > _currentDisplayIndex && childDisplayIndex < _ghostDisplayIndex) { checkingTargetDisplayIndex = childDisplayIndex + 1; } if (checkingTargetDisplayIndex == -1) { return [child]; } - int checkingTargetIndex = - _childDisplayIndexToIndex[checkingTargetDisplayIndex]; + int checkingTargetIndex = _childDisplayIndexToIndex[checkingTargetDisplayIndex]; if (checkingTargetIndex == _dragStartIndex) { return [child]; } if (_childRunIndexes[checkingTargetIndex] == -1 || - _childRunIndexes[checkingTargetIndex] == - _wrapChildRunIndexes[checkingTargetDisplayIndex]) { + _childRunIndexes[checkingTargetIndex] == _wrapChildRunIndexes[checkingTargetDisplayIndex]) { return [child]; } // debugPrint(' make $checkingTargetIndex($checkingTargetDisplayIndex) disappearing around $index'); - Widget disappearingPreChild = - _makeDisappearingWidget(_wrapChildren[checkingTargetIndex]); + Widget disappearingPreChild = _makeDisappearingWidget(_wrapChildren[checkingTargetIndex]!); // return _buildContainerForMainAxis( // children: _ghostDisplayIndex < _currentDisplayIndex // ? [disappearingPreChild, child] @@ -943,11 +902,10 @@ class _ReorderableWrapContentState extends State<_ReorderableWrapContent> if (_currentDisplayIndex == -1 || displayIndex == _currentDisplayIndex) { //we still wrap dragTarget with a container so that widget's depths are the same and it prevents layout alignment issue return _buildContainerForMainAxis( - children: _includeMovedAdjacentChildIfNeeded( - containedDraggable, displayIndex)); + children: _includeMovedAdjacentChildIfNeeded(containedDraggable, displayIndex)); } - bool _onWillAccept(int toAccept, bool isPre) { + bool _onWillAccept(int? toAccept, bool isPre) { int nextDisplayIndex; if (_currentDisplayIndex < displayIndex) { nextDisplayIndex = isPre ? displayIndex - 1 : displayIndex; @@ -956,8 +914,7 @@ class _ReorderableWrapContentState extends State<_ReorderableWrapContent> } bool movingToAdjacentChild = - nextDisplayIndex <= _currentDisplayIndex + 1 && - nextDisplayIndex >= _currentDisplayIndex - 1; + nextDisplayIndex <= _currentDisplayIndex + 1 && nextDisplayIndex >= _currentDisplayIndex - 1; bool willAccept = _dragStartIndex == toAccept && // toAccept != toWrap.key && toAccept != index && @@ -969,12 +926,13 @@ class _ReorderableWrapContentState extends State<_ReorderableWrapContent> if (!willAccept) { return false; } - assert(_childDisplayIndexToIndex[_currentDisplayIndex] != index && - _currentDisplayIndex != displayIndex); + if (!(_childDisplayIndexToIndex[_currentDisplayIndex] != index && _currentDisplayIndex != displayIndex)) { + return false; + } if (_wrapKey.currentContext != null) { RenderWrapWithMainAxisCount wrapRenderObject = - _wrapKey.currentContext.findRenderObject(); + _wrapKey.currentContext!.findRenderObject() as RenderWrapWithMainAxisCount; _wrapChildRunIndexes = wrapRenderObject.childRunIndexes; // for (int i=0; i<_childRunIndexes.length; i++) { // _childRunIndexes[i] = _wrapChildRunIndexes[_childIndexToDisplayIndex[i]]; @@ -983,8 +941,8 @@ class _ReorderableWrapContentState extends State<_ReorderableWrapContent> if (widget.minMainAxisCount != null && widget.maxMainAxisCount != null && widget.minMainAxisCount == widget.maxMainAxisCount) { - _wrapChildRunIndexes = List.generate(widget.children.length, - (int index) => index ~/ widget.minMainAxisCount); + _wrapChildRunIndexes = + List.generate(widget.children.length, (int index) => index ~/ widget.minMainAxisCount!); // for (int i=0; i<_childRunIndexes.length; i++) { // _childRunIndexes[i] = _wrapChildRunIndexes[_childIndexToDisplayIndex[i]]; // } @@ -1002,47 +960,35 @@ class _ReorderableWrapContentState extends State<_ReorderableWrapContent> } Widget preDragTarget = DragTarget( - builder: (BuildContext context, List acceptedCandidates, - List rejectedCandidates) => - SizedBox(), - onWillAccept: (int toAccept) => _onWillAccept(toAccept, true), + builder: (BuildContext context, List acceptedCandidates, List rejectedCandidates) => SizedBox(), + onWillAccept: (int? toAccept) => _onWillAccept(toAccept, true), onAccept: (int accepted) {}, - onLeave: (Object leaving) {}, + onLeave: (Object? leaving) {}, ); Widget nextDragTarget = DragTarget( - builder: (BuildContext context, List acceptedCandidates, - List rejectedCandidates) => - SizedBox(), - onWillAccept: (int toAccept) => _onWillAccept(toAccept, false), + builder: (BuildContext context, List acceptedCandidates, List rejectedCandidates) => SizedBox(), + onWillAccept: (int? toAccept) => _onWillAccept(toAccept, false), onAccept: (int accepted) {}, - onLeave: (Object leaving) {}, + onLeave: (Object? leaving) {}, ); Widget dragTarget = Stack( // key: keyIndexGlobalKey, // fit: StackFit.passthrough, - overflow: Overflow.clip, + clipBehavior: Clip.hardEdge, children: [ containedDraggable, Positioned( left: 0, top: 0, - width: widget.direction == Axis.horizontal - ? _childSizes[index].width / 2 - : _childSizes[index].width, - height: widget.direction == Axis.vertical - ? _childSizes[index].height / 2 - : _childSizes[index].height, + width: widget.direction == Axis.horizontal ? _childSizes[index].width / 2 : _childSizes[index].width, + height: widget.direction == Axis.vertical ? _childSizes[index].height / 2 : _childSizes[index].height, child: preDragTarget), Positioned( right: 0, bottom: 0, - width: widget.direction == Axis.horizontal - ? _childSizes[index].width / 2 - : _childSizes[index].width, - height: widget.direction == Axis.vertical - ? _childSizes[index].height / 2 - : _childSizes[index].height, + width: widget.direction == Axis.horizontal ? _childSizes[index].width / 2 : _childSizes[index].width, + height: widget.direction == Axis.vertical ? _childSizes[index].height / 2 : _childSizes[index].height, child: nextDragTarget), ], ); @@ -1093,8 +1039,7 @@ class _ReorderableWrapContentState extends State<_ReorderableWrapContent> : Opacity(opacity: 0.2, child: _draggingWidget); // Widget spacing = SizedBox.fromSize(size: _dropAreaSize, child: Container(color: Colors.red)); - if (_childRunIndexes[index] != -1 && - _childRunIndexes[index] != _wrapChildRunIndexes[displayIndex]) { + if (_childRunIndexes[index] != -1 && _childRunIndexes[index] != _wrapChildRunIndexes[displayIndex]) { dragTarget = _makeAppearingWidget(dragTarget); } @@ -1103,20 +1048,15 @@ class _ReorderableWrapContentState extends State<_ReorderableWrapContent> if (_ghostDisplayIndex < _currentDisplayIndex) { //ghost is on the left of current, so shift it to the right return _buildContainerForMainAxis( - children: [ghostSpacing] + - _includeMovedAdjacentChildIfNeeded(dragTarget, displayIndex)); + children: [ghostSpacing] + _includeMovedAdjacentChildIfNeeded(dragTarget, displayIndex)); } else if (_ghostDisplayIndex > _currentDisplayIndex) { return _buildContainerForMainAxis( - children: - _includeMovedAdjacentChildIfNeeded(dragTarget, displayIndex) + - [ghostSpacing]); + children: _includeMovedAdjacentChildIfNeeded(dragTarget, displayIndex) + [ghostSpacing]); } } //we still wrap dragTarget with a container so that widget's depths are the same and it prevent's layout alignment issue - return _buildContainerForMainAxis( - children: - _includeMovedAdjacentChildIfNeeded(dragTarget, displayIndex)); + return _buildContainerForMainAxis(children: _includeMovedAdjacentChildIfNeeded(dragTarget, displayIndex)); // if (shiftedIndex == _currentDisplayIndex) { // Widget entranceSpacing = SizeTransitionWithIntrinsicSize( @@ -1162,8 +1102,7 @@ class _ReorderableWrapContentState extends State<_ReorderableWrapContent> // _childSizes = List.filled(widget.children.length, Size(0, 0)); List _resizeListMember(List listVar, E initValue) { if (listVar.length < widget.children.length) { - return listVar + - List.filled(widget.children.length - listVar.length, initValue); + return listVar + List.filled(widget.children.length - listVar.length, initValue); } else if (listVar.length > widget.children.length) { return listVar.sublist(0, widget.children.length); } @@ -1174,15 +1113,10 @@ class _ReorderableWrapContentState extends State<_ReorderableWrapContent> _childContexts = _resizeListMember(_childContexts, null); _childSizes = _resizeListMember(_childSizes, Size(0, 0)); - _childDisplayIndexToIndex = - List.generate(widget.children.length, (int index) => index); - _childIndexToDisplayIndex = - List.generate(widget.children.length, (int index) => index); - if (_dragStartIndex >= 0 && - _currentDisplayIndex >= 0 && - _dragStartIndex != _currentDisplayIndex) { - _childDisplayIndexToIndex.insert(_currentDisplayIndex, - _childDisplayIndexToIndex.removeAt(_dragStartIndex)); + _childDisplayIndexToIndex = List.generate(widget.children.length, (int index) => index); + _childIndexToDisplayIndex = List.generate(widget.children.length, (int index) => index); + if (_dragStartIndex >= 0 && _currentDisplayIndex >= 0 && _dragStartIndex != _currentDisplayIndex) { + _childDisplayIndexToIndex.insert(_currentDisplayIndex, _childDisplayIndexToIndex.removeAt(_dragStartIndex)); } int index = 0; _childDisplayIndexToIndex.forEach((int element) { @@ -1202,40 +1136,33 @@ class _ReorderableWrapContentState extends State<_ReorderableWrapContent> for (int i = 0; i < widget.children.length; i++) { wrappedChildren.add(_wrap(widget.children[i], i)); } - if (_dragStartIndex >= 0 && - _currentDisplayIndex >= 0 && - _dragStartIndex != _currentDisplayIndex) { + if (_dragStartIndex >= 0 && _currentDisplayIndex >= 0 && _dragStartIndex != _currentDisplayIndex) { //we are dragging an widget - wrappedChildren.insert( - _currentDisplayIndex, wrappedChildren.removeAt(_dragStartIndex)); + wrappedChildren.insert(_currentDisplayIndex, wrappedChildren.removeAt(_dragStartIndex)); } if (widget.header != null) { - wrappedChildren.insertAll(0, widget.header); + wrappedChildren.insertAll(0, widget.header!); } if (widget.footer != null) { - wrappedChildren.add(widget.footer); + wrappedChildren.add(widget.footer!); } - if (widget.controller != null) { return Padding( - child: (widget.buildItemsContainer ?? defaultBuildItemsContainer)( - context, widget.direction, wrappedChildren), + child: (widget.buildItemsContainer ?? defaultBuildItemsContainer)(context, widget.direction, wrappedChildren), padding: widget.padding, ); } return SingleChildScrollView( // key: _contentKey, scrollDirection: widget.scrollDirection, - child: (widget.buildItemsContainer ?? defaultBuildItemsContainer)( - context, widget.direction, wrappedChildren), + child: (widget.buildItemsContainer ?? defaultBuildItemsContainer)(context, widget.direction, wrappedChildren), padding: widget.padding, controller: _scrollController, ); } - Widget defaultBuildItemsContainer( - BuildContext context, Axis direction, List children) { + Widget defaultBuildItemsContainer(BuildContext context, Axis direction, List children) { return WrapWithMainAxisCount( key: _wrapKey, direction: direction, @@ -1252,14 +1179,12 @@ class _ReorderableWrapContentState extends State<_ReorderableWrapContent> ); } - Widget defaultBuildDraggableFeedback( - BuildContext context, BoxConstraints constraints, Widget child) { + Widget defaultBuildDraggableFeedback(BuildContext context, BoxConstraints constraints, Widget child) { return Transform( transform: new Matrix4.rotationZ(0), alignment: FractionalOffset.topLeft, child: Material( - child: - Card(child: ConstrainedBox(constraints: constraints, child: child)), + child: Card(child: ConstrainedBox(constraints: constraints, child: child)), elevation: 6.0, color: Colors.transparent, borderRadius: BorderRadius.zero, diff --git a/lib/src/widgets/tabluar_flex.dart b/lib/src/widgets/tabluar_flex.dart index b95eb90..3638b6a 100644 --- a/lib/src/widgets/tabluar_flex.dart +++ b/lib/src/widgets/tabluar_flex.dart @@ -5,16 +5,16 @@ import '../rendering/tabluar_flex.dart'; class TabluarFlex extends Flex { TabluarFlex({ - Key key, - @required Axis direction, + required Axis direction, MainAxisAlignment mainAxisAlignment = MainAxisAlignment.start, MainAxisSize mainAxisSize = MainAxisSize.max, CrossAxisAlignment crossAxisAlignment = CrossAxisAlignment.center, - TextDirection textDirection, + TextDirection? textDirection, VerticalDirection verticalDirection = VerticalDirection.down, - TextBaseline textBaseline, + TextBaseline? textBaseline, List children = const [], this.decoration, + Key? key, }) : super( key: key, children: children, @@ -30,7 +30,7 @@ class TabluarFlex extends Flex { /// What decoration to paint. /// /// Commonly a [BoxDecoration]. - final Decoration decoration; + final Decoration? decoration; @override RenderTabluarFlex createRenderObject(BuildContext context) { @@ -231,15 +231,15 @@ class TabluarRow extends TabluarFlex { /// `start` or `end` values for the [mainAxisAlignment], the [textDirection] /// must not be null. TabluarRow({ - Key key, MainAxisAlignment mainAxisAlignment = MainAxisAlignment.start, MainAxisSize mainAxisSize = MainAxisSize.max, CrossAxisAlignment crossAxisAlignment = CrossAxisAlignment.center, - TextDirection textDirection, + TextDirection? textDirection, VerticalDirection verticalDirection = VerticalDirection.down, - TextBaseline textBaseline, + TextBaseline? textBaseline, List children = const [], - Decoration decoration, + Decoration? decoration, + Key? key, }) : super( children: children, key: key, @@ -429,15 +429,15 @@ class TabluarColumn extends TabluarFlex { /// to be necessary to disambiguate `start` or `end` values for the /// [crossAxisAlignment], the [textDirection] must not be null. TabluarColumn({ - Key key, MainAxisAlignment mainAxisAlignment = MainAxisAlignment.start, MainAxisSize mainAxisSize = MainAxisSize.max, CrossAxisAlignment crossAxisAlignment = CrossAxisAlignment.center, - TextDirection textDirection, VerticalDirection verticalDirection = VerticalDirection.down, - TextBaseline textBaseline, List children = const [], - Decoration decoration, + TextDirection? textDirection, + TextBaseline? textBaseline, + Decoration? decoration, + Key? key, }) : super( children: children, key: key, diff --git a/lib/src/widgets/transitions.dart b/lib/src/widgets/transitions.dart index da5167b..89b486a 100644 --- a/lib/src/widgets/transitions.dart +++ b/lib/src/widgets/transitions.dart @@ -11,11 +11,11 @@ class SizeTransitionWithIntrinsicSize extends SingleChildRenderObjectWidget { /// defaults to 0.0, which centers the child along the main axis during the /// transition. SizeTransitionWithIntrinsicSize({ - Key key, this.axis = Axis.vertical, - @required this.sizeFactor, + required this.sizeFactor, double axisAlignment = 0.0, - Widget child, + Widget? child, + Key? key, }) : super( key: key, child: SizeTransition( diff --git a/lib/src/widgets/wrap.dart b/lib/src/widgets/wrap.dart index e481e36..15c5dfd 100644 --- a/lib/src/widgets/wrap.dart +++ b/lib/src/widgets/wrap.dart @@ -5,14 +5,14 @@ import '../rendering/wrap.dart'; class WrapWithMainAxisCount extends Wrap { WrapWithMainAxisCount({ - Key key, + Key? key, Axis direction = Axis.horizontal, WrapAlignment alignment = WrapAlignment.start, double spacing = 0.0, WrapAlignment runAlignment = WrapAlignment.start, double runSpacing = 0.0, WrapCrossAlignment crossAxisAlignment = WrapCrossAlignment.start, - TextDirection textDirection, + TextDirection? textDirection, VerticalDirection verticalDirection = VerticalDirection.down, List children = const [], this.minMainAxisCount, @@ -29,8 +29,8 @@ class WrapWithMainAxisCount extends Wrap { verticalDirection: verticalDirection, children: children); - final int minMainAxisCount; - final int maxMainAxisCount; + final int? minMainAxisCount; + final int? maxMainAxisCount; @override RenderWrapWithMainAxisCount createRenderObject(BuildContext context) { diff --git a/pubspec.yaml b/pubspec.yaml index 2a651d8..93c33ae 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,10 +1,10 @@ name: reorderables description: Reorderable table, row, column, wrap, sliver list that allow drag and drop of their children. -version: 0.3.2 +version: 0.4.1 homepage: https://github.com/hanshengchiu/reorderables environment: - sdk: ">=2.1.0 <3.0.0" + sdk: ">=2.12.0 <3.0.0" # flutter: ">=1.6.3" dependencies: From f6f704c6f4fd609dea19327403e210bdce3f4293 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20P=C3=BChringer?= Date: Tue, 12 Jul 2022 10:30:17 +0200 Subject: [PATCH 2/2] Made haptic feedback customizable --- lib/src/widgets/reorderable_flex.dart | 40 ++++- lib/src/widgets/reorderable_wrap.dart | 205 ++++++++++++++++++-------- pubspec.yaml | 2 +- 3 files changed, 180 insertions(+), 67 deletions(-) diff --git a/lib/src/widgets/reorderable_flex.dart b/lib/src/widgets/reorderable_flex.dart index da3d245..1e7bf84 100644 --- a/lib/src/widgets/reorderable_flex.dart +++ b/lib/src/widgets/reorderable_flex.dart @@ -56,6 +56,9 @@ class ReorderableFlex extends StatefulWidget { this.reorderAnimationDuration, this.scrollAnimationDuration, this.ignorePrimaryScrollController = false, + this.hapticFeedbackOnStart = true, + this.onReorderGhostStep, + this.onReorderStarted, }) : assert( children.every((Widget w) => w.key != null), 'All children of this widget must have a key.', @@ -89,6 +92,8 @@ class ReorderableFlex extends StatefulWidget { /// children. final ReorderCallback onReorder; final NoReorderCallback? onNoReorder; + final ReorderCallback? onReorderGhostStep; + final ReorderStartedCallback? onReorderStarted; final BuildItemsContainer? buildItemsContainer; final BuildDraggableFeedback? buildDraggableFeedback; @@ -102,6 +107,8 @@ class ReorderableFlex extends StatefulWidget { final Duration? scrollAnimationDuration; final bool ignorePrimaryScrollController; + final bool hapticFeedbackOnStart; + @override _ReorderableFlexState createState() => _ReorderableFlexState(); } @@ -148,6 +155,9 @@ class _ReorderableFlexState extends State { const Duration(milliseconds: 200), scrollAnimationDuration: widget.scrollAnimationDuration ?? const Duration(milliseconds: 200), + onReorderGhostStep: widget.onReorderGhostStep, + hapticFeedbackOnStart: widget.hapticFeedbackOnStart, + onReorderStarted: widget.onReorderStarted, ); }, ); @@ -186,6 +196,9 @@ class _ReorderableFlexContent extends StatefulWidget { required this.padding, this.reorderAnimationDuration = const Duration(milliseconds: 200), this.scrollAnimationDuration = const Duration(milliseconds: 200), + this.onReorderGhostStep, + this.hapticFeedbackOnStart = true, + this.onReorderStarted, }); final Widget? header; @@ -205,6 +218,9 @@ class _ReorderableFlexContent extends StatefulWidget { final double draggingWidgetOpacity; final Duration reorderAnimationDuration; final Duration scrollAnimationDuration; + final bool hapticFeedbackOnStart; + final ReorderCallback? onReorderGhostStep; + final ReorderStartedCallback? onReorderStarted; @override _ReorderableFlexContentState createState() => _ReorderableFlexContentState(); @@ -344,6 +360,7 @@ class _ReorderableFlexContentState extends State<_ReorderableFlexContent> return; } + widget.onReorderGhostStep?.call(_currentIndex, _nextIndex); _currentIndex = _nextIndex; _ghostController.reverse(from: 1.0); _entranceController.forward(from: 0.0); @@ -439,6 +456,7 @@ class _ReorderableFlexContentState extends State<_ReorderableFlexContent> _currentIndex = index; _entranceController.value = 1.0; _draggingFeedbackSize = keyIndexGlobalKey.currentContext?.size; + widget.onReorderStarted?.call(index); }); } @@ -515,8 +533,9 @@ class _ReorderableFlexContentState extends State<_ReorderableFlexContent> } semanticsActions[CustomSemanticsAction(label: reorderItemAfter)] = moveAfter; - semanticsActions[CustomSemanticsAction( - label: localizations.reorderItemToEnd)] = moveToEnd; + semanticsActions[ + CustomSemanticsAction(label: localizations.reorderItemToEnd)] = + moveToEnd; } // We pass toWrap with a GlobalKey into the Draggable so that when a list @@ -634,6 +653,7 @@ class _ReorderableFlexContentState extends State<_ReorderableFlexContent> // had been dragged to. onDraggableCanceled: (Velocity velocity, Offset offset) => onDragEnded(), + hapticFeedbackOnStart: widget.hapticFeedbackOnStart, ) : Draggable( maxSimultaneousDrags: 1, @@ -974,6 +994,9 @@ class ReorderableRow extends ReorderableFlex { Duration? reorderAnimationDuration, Duration? scrollAnimationDuration, bool ignorePrimaryScrollController = false, + bool hapticFeedbackOnStart = true, + ReorderCallback? onReorderGhostStep, + ReorderStartedCallback? onReorderStarted, }) : super( key: key, header: header, @@ -1003,7 +1026,10 @@ class ReorderableRow extends ReorderableFlex { draggingWidgetOpacity: draggingWidgetOpacity, reorderAnimationDuration: reorderAnimationDuration, scrollAnimationDuration: scrollAnimationDuration, - ignorePrimaryScrollController: ignorePrimaryScrollController); + ignorePrimaryScrollController: ignorePrimaryScrollController, + hapticFeedbackOnStart: hapticFeedbackOnStart, + onReorderGhostStep: onReorderGhostStep, + onReorderStarted: onReorderStarted); } /// Reorderable (drag and drop) version of [Column], a widget that displays its @@ -1053,6 +1079,9 @@ class ReorderableColumn extends ReorderableFlex { Duration? reorderAnimationDuration, Duration? scrollAnimationDuration, bool ignorePrimaryScrollController = false, + bool hapticFeedbackOnStart = true, + ReorderCallback? onReorderGhostStep, + ReorderStartedCallback? onReorderStarted, }) : super( key: key, header: header, @@ -1081,5 +1110,8 @@ class ReorderableColumn extends ReorderableFlex { draggingWidgetOpacity: draggingWidgetOpacity, reorderAnimationDuration: reorderAnimationDuration, scrollAnimationDuration: scrollAnimationDuration, - ignorePrimaryScrollController: ignorePrimaryScrollController); + ignorePrimaryScrollController: ignorePrimaryScrollController, + hapticFeedbackOnStart: hapticFeedbackOnStart, + onReorderGhostStep: onReorderGhostStep, + onReorderStarted: onReorderStarted); } diff --git a/lib/src/widgets/reorderable_wrap.dart b/lib/src/widgets/reorderable_wrap.dart index c7dbb2d..43db99a 100644 --- a/lib/src/widgets/reorderable_wrap.dart +++ b/lib/src/widgets/reorderable_wrap.dart @@ -60,6 +60,8 @@ class ReorderableWrap extends StatefulWidget { this.scrollAnimationDuration = const Duration(milliseconds: 200), this.ignorePrimaryScrollController = false, this.enabledDragging = true, + this.hapticFeedbackOnStart = true, + this.onReorderGhostStep, Key? key, }) : // assert( @@ -98,6 +100,7 @@ class ReorderableWrap extends StatefulWidget { /// children. final ReorderCallback onReorder; final NoReorderCallback? onNoReorder; + final ReorderCallback? onReorderGhostStep; /// Called when the draggable starts being dragged. final ReorderStartedCallback? onReorderStarted; @@ -241,6 +244,8 @@ class ReorderableWrap extends StatefulWidget { final bool enabledDragging; + final bool hapticFeedbackOnStart; + @override _ReorderableWrapState createState() => _ReorderableWrapState(); } @@ -256,7 +261,8 @@ class ReorderableWrap extends StatefulWidget { // insert Draggables into the Overlay above itself. class _ReorderableWrapState extends State { // We use an inner overlay so that the dragging list item doesn't draw outside of the list itself. - final GlobalKey _overlayKey = GlobalKey(debugLabel: '$ReorderableWrap overlay key'); + final GlobalKey _overlayKey = + GlobalKey(debugLabel: '$ReorderableWrap overlay key'); // This entry contains the scrolling list itself. late PassthroughOverlayEntry _listOverlayEntry; @@ -293,6 +299,8 @@ class _ReorderableWrapState extends State { reorderAnimationDuration: widget.reorderAnimationDuration, scrollAnimationDuration: widget.scrollAnimationDuration, enableDragging: widget.enabledDragging, + hapticFeedbackOnStart: widget.hapticFeedbackOnStart, + onReorderGhostStep: widget.onReorderGhostStep, ); }, ); @@ -300,10 +308,11 @@ class _ReorderableWrapState extends State { @override Widget build(BuildContext context) { - final PassthroughOverlay passthroughOverlay = - PassthroughOverlay(key: _overlayKey, initialEntries: [ - _listOverlayEntry, - ]); + final PassthroughOverlay passthroughOverlay = PassthroughOverlay( + key: _overlayKey, + initialEntries: [ + _listOverlayEntry, + ]); return widget.ignorePrimaryScrollController ? PrimaryScrollController.none(child: passthroughOverlay) : passthroughOverlay; @@ -339,6 +348,8 @@ class _ReorderableWrapContent extends StatefulWidget { this.reorderAnimationDuration = const Duration(milliseconds: 200), this.scrollAnimationDuration = const Duration(milliseconds: 200), this.enableDragging = true, + this.hapticFeedbackOnStart = true, + this.onReorderGhostStep, }); final List? header; @@ -367,6 +378,8 @@ class _ReorderableWrapContent extends StatefulWidget { final Duration reorderAnimationDuration; final Duration scrollAnimationDuration; final bool enableDragging; + final bool hapticFeedbackOnStart; + final ReorderCallback? onReorderGhostStep; @override _ReorderableWrapContentState createState() => _ReorderableWrapContentState(); @@ -461,8 +474,10 @@ class _ReorderableWrapContentState extends State<_ReorderableWrapContent> super.initState(); _reorderAnimationDuration = widget.reorderAnimationDuration; _scrollAnimationDuration = widget.scrollAnimationDuration; - _entranceController = AnimationController(value: 1.0, vsync: this, duration: _reorderAnimationDuration); - _ghostController = AnimationController(value: 0, vsync: this, duration: _reorderAnimationDuration); + _entranceController = AnimationController( + value: 1.0, vsync: this, duration: _reorderAnimationDuration); + _ghostController = AnimationController( + value: 0, vsync: this, duration: _reorderAnimationDuration); _entranceController.addStatusListener(_onEntranceStatusChanged); // _childKeys = List.filled(widget.children.length, null); _childContexts = List.filled(widget.children.length, null); @@ -479,7 +494,9 @@ class _ReorderableWrapContentState extends State<_ReorderableWrapContent> @override void didChangeDependencies() { - _scrollController = widget.controller ?? PrimaryScrollController.of(context) ?? ScrollController(); + _scrollController = widget.controller ?? + PrimaryScrollController.of(context) ?? + ScrollController(); super.didChangeDependencies(); } @@ -499,7 +516,7 @@ class _ReorderableWrapContentState extends State<_ReorderableWrapContent> // && _dragStartIndex == _ghostIndex return; } - + widget.onReorderGhostStep?.call(_currentDisplayIndex, _nextDisplayIndex); _currentDisplayIndex = _nextDisplayIndex; _ghostController.reverse(from: 1.0); _entranceController.forward(from: 0.0); @@ -519,11 +536,14 @@ class _ReorderableWrapContentState extends State<_ReorderableWrapContent> void _scrollTo(BuildContext context) { if (_scrolling) return; final RenderObject contextObject = context.findRenderObject()!; - final RenderAbstractViewport viewport = RenderAbstractViewport.of(contextObject)!; + final RenderAbstractViewport viewport = + RenderAbstractViewport.of(contextObject)!; // If and only if the current scroll offset falls in-between the offsets // necessary to reveal the selected context at the top or bottom of the // screen, then it is already on-screen. - final double margin = widget.direction == Axis.horizontal ? _dropAreaSize.width : _dropAreaSize.height; + final double margin = widget.direction == Axis.horizontal + ? _dropAreaSize.width + : _dropAreaSize.height; final double scrollOffset = _scrollController.offset; final double topOffset = max( _scrollController.position.minScrollExtent, @@ -533,7 +553,8 @@ class _ReorderableWrapContentState extends State<_ReorderableWrapContent> _scrollController.position.maxScrollExtent, viewport.getOffsetToReveal(contextObject, 1.0).offset + margin, ); - final bool onScreen = scrollOffset <= topOffset && scrollOffset >= bottomOffset; + final bool onScreen = + scrollOffset <= topOffset && scrollOffset >= bottomOffset; // If the context is off screen, then we request a scroll to make it visible. if (!onScreen) { _scrolling = true; @@ -632,19 +653,22 @@ class _ReorderableWrapContentState extends State<_ReorderableWrapContent> if (_wrapKey.currentContext != null) { RenderWrapWithMainAxisCount wrapRenderObject = - _wrapKey.currentContext!.findRenderObject() as RenderWrapWithMainAxisCount; + _wrapKey.currentContext!.findRenderObject() + as RenderWrapWithMainAxisCount; _wrapChildRunIndexes = wrapRenderObject.childRunIndexes; for (int i = 0; i < _childRunIndexes.length; i++) { - _nextChildRunIndexes[i] = _wrapChildRunIndexes[_childIndexToDisplayIndex[i]]; + _nextChildRunIndexes[i] = + _wrapChildRunIndexes[_childIndexToDisplayIndex[i]]; } } else { if (widget.minMainAxisCount != null && widget.maxMainAxisCount != null && widget.minMainAxisCount == widget.maxMainAxisCount) { - _wrapChildRunIndexes = - List.generate(widget.children.length, (int index) => index ~/ widget.minMainAxisCount!); + _wrapChildRunIndexes = List.generate(widget.children.length, + (int index) => index ~/ widget.minMainAxisCount!); for (int i = 0; i < _childRunIndexes.length; i++) { - _nextChildRunIndexes[i] = _wrapChildRunIndexes[_childIndexToDisplayIndex[i]]; + _nextChildRunIndexes[i] = + _wrapChildRunIndexes[_childIndexToDisplayIndex[i]]; } } } @@ -692,7 +716,8 @@ class _ReorderableWrapContentState extends State<_ReorderableWrapContent> Widget wrapWithSemantics() { // First, determine which semantics actions apply. - final Map semanticsActions = {}; + final Map semanticsActions = + {}; // Create the appropriate semantics actions. void moveToStart() => reorder(index, 0); @@ -702,17 +727,20 @@ class _ReorderableWrapContentState extends State<_ReorderableWrapContent> // before index+2, which is after the space at index+1. void moveAfter() => reorder(index, index + 2); - final MaterialLocalizations localizations = MaterialLocalizations.of(context); + final MaterialLocalizations localizations = + MaterialLocalizations.of(context); if (index > 0) { - semanticsActions[CustomSemanticsAction(label: localizations.reorderItemToStart)] = moveToStart; + semanticsActions[CustomSemanticsAction( + label: localizations.reorderItemToStart)] = moveToStart; String reorderItemBefore = localizations.reorderItemUp; if (widget.direction == Axis.horizontal) { reorderItemBefore = Directionality.of(context) == TextDirection.ltr ? localizations.reorderItemLeft : localizations.reorderItemRight; } - semanticsActions[CustomSemanticsAction(label: reorderItemBefore)] = moveBefore; + semanticsActions[CustomSemanticsAction(label: reorderItemBefore)] = + moveBefore; } // If the item can move to after its current position in the list. @@ -723,8 +751,11 @@ class _ReorderableWrapContentState extends State<_ReorderableWrapContent> ? localizations.reorderItemRight : localizations.reorderItemLeft; } - semanticsActions[CustomSemanticsAction(label: reorderItemAfter)] = moveAfter; - semanticsActions[CustomSemanticsAction(label: localizations.reorderItemToEnd)] = moveToEnd; + semanticsActions[CustomSemanticsAction(label: reorderItemAfter)] = + moveAfter; + semanticsActions[ + CustomSemanticsAction(label: localizations.reorderItemToEnd)] = + moveToEnd; } // We pass toWrap with a GlobalKey into the Draggable so that when a list @@ -775,7 +806,8 @@ class _ReorderableWrapContentState extends State<_ReorderableWrapContent> Widget feedbackBuilder = Builder(builder: (BuildContext context) { // RenderRepaintBoundary renderObject = _contentKey.currentContext.findRenderObject(); // BoxConstraints contentSizeConstraints = BoxConstraints.loose(renderObject.size); - BoxConstraints contentSizeConstraints = BoxConstraints.loose(_draggingFeedbackSize!); //renderObject.constraints + BoxConstraints contentSizeConstraints = BoxConstraints.loose( + _draggingFeedbackSize!); //renderObject.constraints // debugPrint('feedbackBuilder: contentConstraints:$contentSizeConstraints'); return (widget.buildDraggableFeedback ?? defaultBuildDraggableFeedback)( context, contentSizeConstraints, toWrap); @@ -801,7 +833,9 @@ class _ReorderableWrapContentState extends State<_ReorderableWrapContent> feedback: feedbackBuilder, // Wrap toWrapWithSemantics with a widget that supports HitTestBehavior // to make sure the whole toWrapWithSemantics responds to pointer events, i.e. dragging - child: MetaData(child: toWrapWithSemantics, behavior: HitTestBehavior.opaque), + child: MetaData( + child: toWrapWithSemantics, + behavior: HitTestBehavior.opaque), //toWrapWithSemantics,//_dragging == toWrap.key ? const SizedBox() : toWrapWithSemantics, childWhenDragging: IgnorePointer( ignoring: true, @@ -818,7 +852,9 @@ class _ReorderableWrapContentState extends State<_ReorderableWrapContent> // When the drag does not end inside a DragTarget widget, the // drag fails, but we still reorder the widget to the last position it // had been dragged to. - onDraggableCanceled: (Velocity velocity, Offset offset) => onDragEnded(), + onDraggableCanceled: (Velocity velocity, Offset offset) => + onDragEnded(), + hapticFeedbackOnStart: widget.hapticFeedbackOnStart, ) : Draggable( maxSimultaneousDrags: widget.enableDragging ? 1 : 0, @@ -826,7 +862,9 @@ class _ReorderableWrapContentState extends State<_ReorderableWrapContent> //toWrap.key, ignoringFeedbackSemantics: false, feedback: feedbackBuilder, - child: MetaData(child: toWrapWithSemantics, behavior: HitTestBehavior.opaque), + child: MetaData( + child: toWrapWithSemantics, + behavior: HitTestBehavior.opaque), childWhenDragging: IgnorePointer( ignoring: true, child: Opacity( @@ -837,7 +875,8 @@ class _ReorderableWrapContentState extends State<_ReorderableWrapContent> dragAnchor: DragAnchor.child, onDragStarted: onDragStarted, onDragCompleted: onDragEnded, - onDraggableCanceled: (Velocity velocity, Offset offset) => onDragEnded(), + onDraggableCanceled: (Velocity velocity, Offset offset) => + onDragEnded(), ); } @@ -865,27 +904,33 @@ class _ReorderableWrapContentState extends State<_ReorderableWrapContent> // debugPrint('index:$index displayIndex:$displayIndex _nextDisplayIndex:$_nextDisplayIndex _currentDisplayIndex:$_currentDisplayIndex _ghostDisplayIndex:$_ghostDisplayIndex _dragStartIndex:$_dragStartIndex'); // debugPrint(' _childRunIndexes:$_childRunIndexes _nextChildRunIndexes:$_nextChildRunIndexes _wrapChildRunIndexes:$_wrapChildRunIndexes'); - List _includeMovedAdjacentChildIfNeeded(Widget child, int childDisplayIndex) { + List _includeMovedAdjacentChildIfNeeded( + Widget child, int childDisplayIndex) { // debugPrint(' checking ${_childDisplayIndexToIndex[childDisplayIndex]}($childDisplayIndex)'); int checkingTargetDisplayIndex = -1; - if (_ghostDisplayIndex < _currentDisplayIndex && childDisplayIndex > _ghostDisplayIndex) { + if (_ghostDisplayIndex < _currentDisplayIndex && + childDisplayIndex > _ghostDisplayIndex) { checkingTargetDisplayIndex = childDisplayIndex - 1; - } else if (_ghostDisplayIndex > _currentDisplayIndex && childDisplayIndex < _ghostDisplayIndex) { + } else if (_ghostDisplayIndex > _currentDisplayIndex && + childDisplayIndex < _ghostDisplayIndex) { checkingTargetDisplayIndex = childDisplayIndex + 1; } if (checkingTargetDisplayIndex == -1) { return [child]; } - int checkingTargetIndex = _childDisplayIndexToIndex[checkingTargetDisplayIndex]; + int checkingTargetIndex = + _childDisplayIndexToIndex[checkingTargetDisplayIndex]; if (checkingTargetIndex == _dragStartIndex) { return [child]; } if (_childRunIndexes[checkingTargetIndex] == -1 || - _childRunIndexes[checkingTargetIndex] == _wrapChildRunIndexes[checkingTargetDisplayIndex]) { + _childRunIndexes[checkingTargetIndex] == + _wrapChildRunIndexes[checkingTargetDisplayIndex]) { return [child]; } // debugPrint(' make $checkingTargetIndex($checkingTargetDisplayIndex) disappearing around $index'); - Widget disappearingPreChild = _makeDisappearingWidget(_wrapChildren[checkingTargetIndex]!); + Widget disappearingPreChild = + _makeDisappearingWidget(_wrapChildren[checkingTargetIndex]!); // return _buildContainerForMainAxis( // children: _ghostDisplayIndex < _currentDisplayIndex // ? [disappearingPreChild, child] @@ -902,7 +947,8 @@ class _ReorderableWrapContentState extends State<_ReorderableWrapContent> if (_currentDisplayIndex == -1 || displayIndex == _currentDisplayIndex) { //we still wrap dragTarget with a container so that widget's depths are the same and it prevents layout alignment issue return _buildContainerForMainAxis( - children: _includeMovedAdjacentChildIfNeeded(containedDraggable, displayIndex)); + children: _includeMovedAdjacentChildIfNeeded( + containedDraggable, displayIndex)); } bool _onWillAccept(int? toAccept, bool isPre) { @@ -914,7 +960,8 @@ class _ReorderableWrapContentState extends State<_ReorderableWrapContent> } bool movingToAdjacentChild = - nextDisplayIndex <= _currentDisplayIndex + 1 && nextDisplayIndex >= _currentDisplayIndex - 1; + nextDisplayIndex <= _currentDisplayIndex + 1 && + nextDisplayIndex >= _currentDisplayIndex - 1; bool willAccept = _dragStartIndex == toAccept && // toAccept != toWrap.key && toAccept != index && @@ -926,13 +973,15 @@ class _ReorderableWrapContentState extends State<_ReorderableWrapContent> if (!willAccept) { return false; } - if (!(_childDisplayIndexToIndex[_currentDisplayIndex] != index && _currentDisplayIndex != displayIndex)) { + if (!(_childDisplayIndexToIndex[_currentDisplayIndex] != index && + _currentDisplayIndex != displayIndex)) { return false; } if (_wrapKey.currentContext != null) { RenderWrapWithMainAxisCount wrapRenderObject = - _wrapKey.currentContext!.findRenderObject() as RenderWrapWithMainAxisCount; + _wrapKey.currentContext!.findRenderObject() + as RenderWrapWithMainAxisCount; _wrapChildRunIndexes = wrapRenderObject.childRunIndexes; // for (int i=0; i<_childRunIndexes.length; i++) { // _childRunIndexes[i] = _wrapChildRunIndexes[_childIndexToDisplayIndex[i]]; @@ -941,8 +990,8 @@ class _ReorderableWrapContentState extends State<_ReorderableWrapContent> if (widget.minMainAxisCount != null && widget.maxMainAxisCount != null && widget.minMainAxisCount == widget.maxMainAxisCount) { - _wrapChildRunIndexes = - List.generate(widget.children.length, (int index) => index ~/ widget.minMainAxisCount!); + _wrapChildRunIndexes = List.generate(widget.children.length, + (int index) => index ~/ widget.minMainAxisCount!); // for (int i=0; i<_childRunIndexes.length; i++) { // _childRunIndexes[i] = _wrapChildRunIndexes[_childIndexToDisplayIndex[i]]; // } @@ -960,13 +1009,17 @@ class _ReorderableWrapContentState extends State<_ReorderableWrapContent> } Widget preDragTarget = DragTarget( - builder: (BuildContext context, List acceptedCandidates, List rejectedCandidates) => SizedBox(), + builder: (BuildContext context, List acceptedCandidates, + List rejectedCandidates) => + SizedBox(), onWillAccept: (int? toAccept) => _onWillAccept(toAccept, true), onAccept: (int accepted) {}, onLeave: (Object? leaving) {}, ); Widget nextDragTarget = DragTarget( - builder: (BuildContext context, List acceptedCandidates, List rejectedCandidates) => SizedBox(), + builder: (BuildContext context, List acceptedCandidates, + List rejectedCandidates) => + SizedBox(), onWillAccept: (int? toAccept) => _onWillAccept(toAccept, false), onAccept: (int accepted) {}, onLeave: (Object? leaving) {}, @@ -981,14 +1034,22 @@ class _ReorderableWrapContentState extends State<_ReorderableWrapContent> Positioned( left: 0, top: 0, - width: widget.direction == Axis.horizontal ? _childSizes[index].width / 2 : _childSizes[index].width, - height: widget.direction == Axis.vertical ? _childSizes[index].height / 2 : _childSizes[index].height, + width: widget.direction == Axis.horizontal + ? _childSizes[index].width / 2 + : _childSizes[index].width, + height: widget.direction == Axis.vertical + ? _childSizes[index].height / 2 + : _childSizes[index].height, child: preDragTarget), Positioned( right: 0, bottom: 0, - width: widget.direction == Axis.horizontal ? _childSizes[index].width / 2 : _childSizes[index].width, - height: widget.direction == Axis.vertical ? _childSizes[index].height / 2 : _childSizes[index].height, + width: widget.direction == Axis.horizontal + ? _childSizes[index].width / 2 + : _childSizes[index].width, + height: widget.direction == Axis.vertical + ? _childSizes[index].height / 2 + : _childSizes[index].height, child: nextDragTarget), ], ); @@ -1039,7 +1100,8 @@ class _ReorderableWrapContentState extends State<_ReorderableWrapContent> : Opacity(opacity: 0.2, child: _draggingWidget); // Widget spacing = SizedBox.fromSize(size: _dropAreaSize, child: Container(color: Colors.red)); - if (_childRunIndexes[index] != -1 && _childRunIndexes[index] != _wrapChildRunIndexes[displayIndex]) { + if (_childRunIndexes[index] != -1 && + _childRunIndexes[index] != _wrapChildRunIndexes[displayIndex]) { dragTarget = _makeAppearingWidget(dragTarget); } @@ -1048,15 +1110,20 @@ class _ReorderableWrapContentState extends State<_ReorderableWrapContent> if (_ghostDisplayIndex < _currentDisplayIndex) { //ghost is on the left of current, so shift it to the right return _buildContainerForMainAxis( - children: [ghostSpacing] + _includeMovedAdjacentChildIfNeeded(dragTarget, displayIndex)); + children: [ghostSpacing] + + _includeMovedAdjacentChildIfNeeded(dragTarget, displayIndex)); } else if (_ghostDisplayIndex > _currentDisplayIndex) { return _buildContainerForMainAxis( - children: _includeMovedAdjacentChildIfNeeded(dragTarget, displayIndex) + [ghostSpacing]); + children: + _includeMovedAdjacentChildIfNeeded(dragTarget, displayIndex) + + [ghostSpacing]); } } //we still wrap dragTarget with a container so that widget's depths are the same and it prevent's layout alignment issue - return _buildContainerForMainAxis(children: _includeMovedAdjacentChildIfNeeded(dragTarget, displayIndex)); + return _buildContainerForMainAxis( + children: + _includeMovedAdjacentChildIfNeeded(dragTarget, displayIndex)); // if (shiftedIndex == _currentDisplayIndex) { // Widget entranceSpacing = SizeTransitionWithIntrinsicSize( @@ -1102,7 +1169,8 @@ class _ReorderableWrapContentState extends State<_ReorderableWrapContent> // _childSizes = List.filled(widget.children.length, Size(0, 0)); List _resizeListMember(List listVar, E initValue) { if (listVar.length < widget.children.length) { - return listVar + List.filled(widget.children.length - listVar.length, initValue); + return listVar + + List.filled(widget.children.length - listVar.length, initValue); } else if (listVar.length > widget.children.length) { return listVar.sublist(0, widget.children.length); } @@ -1113,10 +1181,15 @@ class _ReorderableWrapContentState extends State<_ReorderableWrapContent> _childContexts = _resizeListMember(_childContexts, null); _childSizes = _resizeListMember(_childSizes, Size(0, 0)); - _childDisplayIndexToIndex = List.generate(widget.children.length, (int index) => index); - _childIndexToDisplayIndex = List.generate(widget.children.length, (int index) => index); - if (_dragStartIndex >= 0 && _currentDisplayIndex >= 0 && _dragStartIndex != _currentDisplayIndex) { - _childDisplayIndexToIndex.insert(_currentDisplayIndex, _childDisplayIndexToIndex.removeAt(_dragStartIndex)); + _childDisplayIndexToIndex = + List.generate(widget.children.length, (int index) => index); + _childIndexToDisplayIndex = + List.generate(widget.children.length, (int index) => index); + if (_dragStartIndex >= 0 && + _currentDisplayIndex >= 0 && + _dragStartIndex != _currentDisplayIndex) { + _childDisplayIndexToIndex.insert(_currentDisplayIndex, + _childDisplayIndexToIndex.removeAt(_dragStartIndex)); } int index = 0; _childDisplayIndexToIndex.forEach((int element) { @@ -1136,9 +1209,12 @@ class _ReorderableWrapContentState extends State<_ReorderableWrapContent> for (int i = 0; i < widget.children.length; i++) { wrappedChildren.add(_wrap(widget.children[i], i)); } - if (_dragStartIndex >= 0 && _currentDisplayIndex >= 0 && _dragStartIndex != _currentDisplayIndex) { + if (_dragStartIndex >= 0 && + _currentDisplayIndex >= 0 && + _dragStartIndex != _currentDisplayIndex) { //we are dragging an widget - wrappedChildren.insert(_currentDisplayIndex, wrappedChildren.removeAt(_dragStartIndex)); + wrappedChildren.insert( + _currentDisplayIndex, wrappedChildren.removeAt(_dragStartIndex)); } if (widget.header != null) { wrappedChildren.insertAll(0, widget.header!); @@ -1149,20 +1225,23 @@ class _ReorderableWrapContentState extends State<_ReorderableWrapContent> if (widget.controller != null) { return Padding( - child: (widget.buildItemsContainer ?? defaultBuildItemsContainer)(context, widget.direction, wrappedChildren), + child: (widget.buildItemsContainer ?? defaultBuildItemsContainer)( + context, widget.direction, wrappedChildren), padding: widget.padding, ); } return SingleChildScrollView( // key: _contentKey, scrollDirection: widget.scrollDirection, - child: (widget.buildItemsContainer ?? defaultBuildItemsContainer)(context, widget.direction, wrappedChildren), + child: (widget.buildItemsContainer ?? defaultBuildItemsContainer)( + context, widget.direction, wrappedChildren), padding: widget.padding, controller: _scrollController, ); } - Widget defaultBuildItemsContainer(BuildContext context, Axis direction, List children) { + Widget defaultBuildItemsContainer( + BuildContext context, Axis direction, List children) { return WrapWithMainAxisCount( key: _wrapKey, direction: direction, @@ -1179,12 +1258,14 @@ class _ReorderableWrapContentState extends State<_ReorderableWrapContent> ); } - Widget defaultBuildDraggableFeedback(BuildContext context, BoxConstraints constraints, Widget child) { + Widget defaultBuildDraggableFeedback( + BuildContext context, BoxConstraints constraints, Widget child) { return Transform( transform: new Matrix4.rotationZ(0), alignment: FractionalOffset.topLeft, child: Material( - child: Card(child: ConstrainedBox(constraints: constraints, child: child)), + child: + Card(child: ConstrainedBox(constraints: constraints, child: child)), elevation: 6.0, color: Colors.transparent, borderRadius: BorderRadius.zero, diff --git a/pubspec.yaml b/pubspec.yaml index 93c33ae..ee11223 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -4,7 +4,7 @@ version: 0.4.1 homepage: https://github.com/hanshengchiu/reorderables environment: - sdk: ">=2.12.0 <3.0.0" + sdk: ">=2.14.0 <3.0.0" # flutter: ">=1.6.3" dependencies: