From 904b4f71e47ff0c1ad7fdcbd77d9a940989af91f Mon Sep 17 00:00:00 2001 From: kjxbyz <47768002+kjxbyz@users.noreply.github.com> Date: Wed, 26 Aug 2026 19:07:08 +0800 Subject: [PATCH 1/2] feat: decoupled design systems --- CHANGELOG.md | 5 ++ example/android/app/build.gradle | 48 ------------------- example/android/app/build.gradle.kts | 46 ++++++++++++++++++ example/android/build.gradle | 18 ------- example/android/build.gradle.kts | 22 +++++++++ example/android/gradle.properties | 7 ++- .../gradle/wrapper/gradle-wrapper.properties | 2 +- example/android/settings.gradle | 25 ---------- example/android/settings.gradle.kts | 25 ++++++++++ example/lib/example_widget.dart | 4 +- example/lib/main.dart | 9 +--- .../macos/Runner.xcodeproj/project.pbxproj | 6 +-- example/pubspec.lock | 30 +++++++++--- example/pubspec.yaml | 10 ++-- example/test/widget_test.dart | 2 +- lib/bottom_picker.dart | 4 +- lib/cupertino/cupertino_date_picker.dart | 2 +- lib/resources/arrays.dart | 2 +- lib/resources/context_extension.dart | 2 +- lib/widgets/bottom_picker_button.dart | 2 +- lib/widgets/date_picker.dart | 2 +- lib/widgets/range_picker.dart | 2 +- lib/widgets/simple_picker.dart | 2 +- lib/widgets/time_picker.dart | 4 +- lib/widgets/year_picker.dart | 2 +- pubspec.lock | 41 +++++++++++++--- pubspec.yaml | 10 ++-- test/button_builder_test.dart | 2 +- test/simple_bottom_picker_test.dart | 2 +- 29 files changed, 197 insertions(+), 141 deletions(-) delete mode 100644 example/android/app/build.gradle create mode 100644 example/android/app/build.gradle.kts delete mode 100644 example/android/build.gradle create mode 100644 example/android/build.gradle.kts delete mode 100644 example/android/settings.gradle create mode 100644 example/android/settings.gradle.kts diff --git a/CHANGELOG.md b/CHANGELOG.md index 47d85e3..12b985e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +## [5.0.0] + +- Migrates to material_ui and cupertino_ui. +- Updates minimum supported SDK version to Flutter 3.44/Dart 3.12. + ## [4.2.0] - 07/07/2026 ### Features diff --git a/example/android/app/build.gradle b/example/android/app/build.gradle deleted file mode 100644 index 19a563e..0000000 --- a/example/android/app/build.gradle +++ /dev/null @@ -1,48 +0,0 @@ -plugins { - id "com.android.application" - id "kotlin-android" - // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins. - id "dev.flutter.flutter-gradle-plugin" -} - - -android { - namespace = "com.example.example" - compileSdk = flutter.compileSdkVersion - ndkVersion = flutter.ndkVersion - - compileOptions { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 - } - - kotlinOptions { - jvmTarget = JavaVersion.VERSION_1_8 - } - - sourceSets { - main.java.srcDirs += 'src/main/kotlin' - } - - defaultConfig { - // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). - applicationId "com.example.example" - minSdkVersion flutter.minSdkVersion - targetSdkVersion 35 - versionCode 1 - versionName "1.0" - } - - buildTypes { - release { - // TODO: Add your own signing config for the release build. - // Signing with the debug keys for now, so `flutter run --release` works. - signingConfig signingConfigs.debug - } - } -} - -flutter { - source '../..' -} - diff --git a/example/android/app/build.gradle.kts b/example/android/app/build.gradle.kts new file mode 100644 index 0000000..2f59384 --- /dev/null +++ b/example/android/app/build.gradle.kts @@ -0,0 +1,46 @@ +plugins { + id("com.android.application") + id("kotlin-android") + id("dev.flutter.flutter-gradle-plugin") +} + +android { + namespace = "com.example.example" + compileSdk = flutter.compileSdkVersion + ndkVersion = flutter.ndkVersion + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + } + + kotlinOptions { + jvmTarget = JavaVersion.VERSION_17.toString() + } + + sourceSets.getByName("main") { + java.setSrcDirs(listOf("src/main/java", "src/main/kotlin")) + } + + defaultConfig { + // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). + applicationId = "com.example.example" + minSdk = flutter.minSdkVersion + targetSdk = flutter.targetSdkVersion + versionCode = flutter.versionCode + versionName = flutter.versionName + } + + buildTypes { + getByName("release") { + // TODO: Add your own signing config for the release build. + // Signing with the debug keys for now, so `flutter run --release` works. + signingConfig = signingConfigs.getByName("debug") + } + } +} + +flutter { + source = "../.." +} + diff --git a/example/android/build.gradle b/example/android/build.gradle deleted file mode 100644 index d2ffbff..0000000 --- a/example/android/build.gradle +++ /dev/null @@ -1,18 +0,0 @@ -allprojects { - repositories { - google() - mavenCentral() - } -} - -rootProject.buildDir = "../build" -subprojects { - project.buildDir = "${rootProject.buildDir}/${project.name}" -} -subprojects { - project.evaluationDependsOn(":app") -} - -tasks.register("clean", Delete) { - delete rootProject.buildDir -} diff --git a/example/android/build.gradle.kts b/example/android/build.gradle.kts new file mode 100644 index 0000000..82abfb1 --- /dev/null +++ b/example/android/build.gradle.kts @@ -0,0 +1,22 @@ +allprojects { + repositories { + google() + mavenCentral() + } +} + +val newBuildDir: Directory = rootProject.layout.buildDirectory.dir("../../build").get() +rootProject.layout.buildDirectory.value(newBuildDir) + +subprojects { + val newSubprojectBuildDir: Directory = newBuildDir.dir(project.name) + project.layout.buildDirectory.value(newSubprojectBuildDir) +} + +subprojects { + project.evaluationDependsOn(":app") +} + +tasks.register("clean") { + delete(rootProject.layout.buildDirectory) +} diff --git a/example/android/gradle.properties b/example/android/gradle.properties index 94adc3a..2b25595 100644 --- a/example/android/gradle.properties +++ b/example/android/gradle.properties @@ -1,3 +1,8 @@ -org.gradle.jvmargs=-Xmx1536M +org.gradle.jvmargs=-Xmx8G -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m -XX:+HeapDumpOnOutOfMemoryError android.useAndroidX=true android.enableJetifier=true + +# This builtInKotlin flag was added automatically by Flutter migrator +android.builtInKotlin=false +# This newDsl flag was added automatically by Flutter migrator +android.newDsl=false diff --git a/example/android/gradle/wrapper/gradle-wrapper.properties b/example/android/gradle/wrapper/gradle-wrapper.properties index 81a4301..e496849 100644 --- a/example/android/gradle/wrapper/gradle-wrapper.properties +++ b/example/android/gradle/wrapper/gradle-wrapper.properties @@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-bin.zip diff --git a/example/android/settings.gradle b/example/android/settings.gradle deleted file mode 100644 index 02fb0cf..0000000 --- a/example/android/settings.gradle +++ /dev/null @@ -1,25 +0,0 @@ -pluginManagement { - def flutterSdkPath = { - def properties = new Properties() - file("local.properties").withInputStream { properties.load(it) } - def flutterSdkPath = properties.getProperty("flutter.sdk") - assert flutterSdkPath != null, "flutter.sdk not set in local.properties" - return flutterSdkPath - }() - - includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") - - repositories { - google() - mavenCentral() - gradlePluginPortal() - } -} - -plugins { - id "dev.flutter.flutter-plugin-loader" version "1.0.0" - id "com.android.application" version '8.7.0' apply false - id "org.jetbrains.kotlin.android" version "1.8.22" apply false -} - -include ":app" diff --git a/example/android/settings.gradle.kts b/example/android/settings.gradle.kts new file mode 100644 index 0000000..da20e6d --- /dev/null +++ b/example/android/settings.gradle.kts @@ -0,0 +1,25 @@ +pluginManagement { + val flutterSdkPath = run { + val properties = java.util.Properties() + file("local.properties").inputStream().use { properties.load(it) } + val flutterSdkPath = properties.getProperty("flutter.sdk") + require(flutterSdkPath != null) { "flutter.sdk not set in local.properties" } + flutterSdkPath + } + + includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") + + repositories { + google() + mavenCentral() + gradlePluginPortal() + } +} + +plugins { + id("dev.flutter.flutter-plugin-loader") version "1.0.0" + id("com.android.application") version "8.11.1" apply false + id("org.jetbrains.kotlin.android") version "2.2.20" apply false +} + +include(":app") diff --git a/example/lib/example_widget.dart b/example/lib/example_widget.dart index f58eb8e..65bd5a7 100644 --- a/example/lib/example_widget.dart +++ b/example/lib/example_widget.dart @@ -2,9 +2,9 @@ import 'dart:developer'; import 'package:bottom_picker/bottom_picker.dart'; import 'package:bottom_picker/cupertino/cupertino_date_picker.dart'; import 'package:bottom_picker/resources/arrays.dart'; +import 'package:cupertino_ui/cupertino_ui.dart'; import 'package:example/country_data.dart'; -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; +import 'package:material_ui/material_ui.dart'; class ExampleApp extends StatelessWidget { final buttonWidth = 300.0; diff --git a/example/lib/main.dart b/example/lib/main.dart index c432108..890e414 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -1,6 +1,5 @@ import 'package:example/example_widget.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_localizations/flutter_localizations.dart'; +import 'package:material_ui/material_ui.dart'; void main() { runApp(MyApp()); @@ -13,11 +12,7 @@ class MyApp extends StatelessWidget { return MaterialApp( title: 'Flutter Demo', theme: ThemeData(primarySwatch: Colors.blueGrey), - localizationsDelegates: [ - GlobalMaterialLocalizations.delegate, - GlobalWidgetsLocalizations.delegate, - GlobalCupertinoLocalizations.delegate, - ], + localizationsDelegates: GlobalMaterialLocalizations.delegates, supportedLocales: [Locale('en'), Locale('ar')], home: Scaffold(body: ExampleApp()), ); diff --git a/example/macos/Runner.xcodeproj/project.pbxproj b/example/macos/Runner.xcodeproj/project.pbxproj index daa7bf1..a548a46 100644 --- a/example/macos/Runner.xcodeproj/project.pbxproj +++ b/example/macos/Runner.xcodeproj/project.pbxproj @@ -461,7 +461,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.14; + MACOSX_DEPLOYMENT_TARGET = 10.15; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; SWIFT_COMPILATION_MODE = wholemodule; @@ -543,7 +543,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.14; + MACOSX_DEPLOYMENT_TARGET = 10.15; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; @@ -593,7 +593,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.14; + MACOSX_DEPLOYMENT_TARGET = 10.15; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; SWIFT_COMPILATION_MODE = wholemodule; diff --git a/example/pubspec.lock b/example/pubspec.lock index 7384bdd..a279d7e 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -56,6 +56,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.8" + cupertino_ui: + dependency: "direct main" + description: + name: cupertino_ui + sha256: "2137c0d41f3b62cc4d3d2495e6c354bd6b6133cd21c6bb155736cc31dbd49a11" + url: "https://pub.dev" + source: hosted + version: "1.0.1" fake_async: dependency: transitive description: @@ -70,7 +78,7 @@ packages: source: sdk version: "0.0.0" flutter_localizations: - dependency: "direct main" + dependency: transitive description: flutter source: sdk version: "0.0.0" @@ -127,14 +135,22 @@ packages: url: "https://pub.dev" source: hosted version: "0.13.0" + material_ui: + dependency: "direct main" + description: + name: material_ui + sha256: "7ba1ca315d50a004791dbab290417c52a61466d56db2822fe3c5c2994903110c" + url: "https://pub.dev" + source: hosted + version: "1.1.0" meta: dependency: transitive description: name: meta - sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394" + sha256: "1741988757a65eb6b36abe716829688cf01910bbf91c34354ff7ec1c3de2b349" url: "https://pub.dev" source: hosted - version: "1.17.0" + version: "1.18.0" path: dependency: transitive description: @@ -192,10 +208,10 @@ packages: dependency: transitive description: name: test_api - sha256: "8161c84903fd860b26bfdefb7963b3f0b68fee7adea0f59ef805ecca346f0c7a" + sha256: "949a932224383300f01be9221c39180316445ecb8e7547f70a41a35bf421fb9e" url: "https://pub.dev" source: hosted - version: "0.7.10" + version: "0.7.11" vector_math: dependency: transitive description: @@ -213,5 +229,5 @@ packages: source: hosted version: "15.0.0" sdks: - dart: ">=3.10.0 <4.0.0" - flutter: ">=3.18.0-18.0.pre.54" + dart: ">=3.12.0 <4.0.0" + flutter: ">=3.44.0" diff --git a/example/pubspec.yaml b/example/pubspec.yaml index 2b9efbb..2964c6c 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -3,18 +3,20 @@ description: A new Flutter project. publish_to: none version: 1.0.0+1 environment: - sdk: '>=3.10.0 <4.0.0' + sdk: '>=3.12.0 <4.0.0' dependencies: + cupertino_icons: ^1.0.2 + cupertino_ui: ^1.0.0 flutter: sdk: flutter - flutter_localizations: - sdk: flutter intl: any + material_ui: ^1.0.0 bottom_picker: path: ../ - cupertino_icons: ^1.0.2 + dev_dependencies: flutter_test: sdk: flutter + flutter: uses-material-design: true diff --git a/example/test/widget_test.dart b/example/test/widget_test.dart index 747db1d..97c05dc 100644 --- a/example/test/widget_test.dart +++ b/example/test/widget_test.dart @@ -5,7 +5,7 @@ // gestures. You can also use WidgetTester to find child widgets in the widget // tree, read text, and verify that the values of widget properties are correct. -import 'package:flutter/material.dart'; +import 'package:material_ui/material_ui.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:example/main.dart'; diff --git a/lib/bottom_picker.dart b/lib/bottom_picker.dart index 5aa77d8..3df0ed4 100644 --- a/lib/bottom_picker.dart +++ b/lib/bottom_picker.dart @@ -11,9 +11,9 @@ import 'package:bottom_picker/widgets/range_picker.dart'; import 'package:bottom_picker/widgets/simple_picker.dart'; import 'package:bottom_picker/widgets/time_picker.dart'; import 'package:bottom_picker/widgets/year_picker.dart'; -import 'package:flutter/cupertino.dart'; +import 'package:cupertino_ui/cupertino_ui.dart'; import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; +import 'package:material_ui/material_ui.dart'; import 'package:flutter/services.dart'; export 'package:bottom_picker/resources/time.dart'; diff --git a/lib/cupertino/cupertino_date_picker.dart b/lib/cupertino/cupertino_date_picker.dart index 1779356..7e852fa 100644 --- a/lib/cupertino/cupertino_date_picker.dart +++ b/lib/cupertino/cupertino_date_picker.dart @@ -4,7 +4,7 @@ library; import 'dart:math' as math; -import 'package:flutter/cupertino.dart'; +import 'package:cupertino_ui/cupertino_ui.dart'; import 'package:flutter/scheduler.dart'; // Values derived from https://developer.apple.com/design/resources/ and on iOS diff --git a/lib/resources/arrays.dart b/lib/resources/arrays.dart index 93ec208..dbbfab4 100644 --- a/lib/resources/arrays.dart +++ b/lib/resources/arrays.dart @@ -1,4 +1,4 @@ -import 'package:flutter/cupertino.dart'; +import 'package:cupertino_ui/cupertino_ui.dart'; enum BottomPickerType { simple, diff --git a/lib/resources/context_extension.dart b/lib/resources/context_extension.dart index e29c2a5..d288f58 100644 --- a/lib/resources/context_extension.dart +++ b/lib/resources/context_extension.dart @@ -1,5 +1,5 @@ import 'package:bottom_picker/resources/values.dart'; -import 'package:flutter/cupertino.dart'; +import 'package:cupertino_ui/cupertino_ui.dart'; extension ContextExtensions on BuildContext { double get bottomPickerWidth => diff --git a/lib/widgets/bottom_picker_button.dart b/lib/widgets/bottom_picker_button.dart index acfa25b..ac6589f 100644 --- a/lib/widgets/bottom_picker_button.dart +++ b/lib/widgets/bottom_picker_button.dart @@ -1,5 +1,5 @@ import 'package:bottom_picker/resources/arrays.dart'; -import 'package:flutter/material.dart'; +import 'package:material_ui/material_ui.dart'; /// A button widget that can be used to open the bottom picker. @Deprecated( diff --git a/lib/widgets/date_picker.dart b/lib/widgets/date_picker.dart index 80937b6..e2fa094 100644 --- a/lib/widgets/date_picker.dart +++ b/lib/widgets/date_picker.dart @@ -1,5 +1,5 @@ import 'package:bottom_picker/cupertino/cupertino_date_picker.dart'; -import 'package:flutter/cupertino.dart'; +import 'package:cupertino_ui/cupertino_ui.dart'; /// A date picker widget that can be used to select a date or time. class DatePicker extends StatelessWidget { diff --git a/lib/widgets/range_picker.dart b/lib/widgets/range_picker.dart index 6084fa2..a0d62e9 100644 --- a/lib/widgets/range_picker.dart +++ b/lib/widgets/range_picker.dart @@ -1,5 +1,5 @@ import 'package:bottom_picker/widgets/date_picker.dart'; -import 'package:flutter/cupertino.dart'; +import 'package:cupertino_ui/cupertino_ui.dart'; /// A range picker widget that can be used to select a range of dates or times. class RangePicker extends StatefulWidget { diff --git a/lib/widgets/simple_picker.dart b/lib/widgets/simple_picker.dart index 00137e1..f7fd204 100644 --- a/lib/widgets/simple_picker.dart +++ b/lib/widgets/simple_picker.dart @@ -1,6 +1,6 @@ import 'dart:io'; -import 'package:flutter/cupertino.dart'; +import 'package:cupertino_ui/cupertino_ui.dart'; import 'package:flutter/foundation.dart'; /// A simple picker widget that can be used to select an item from a list of items. diff --git a/lib/widgets/time_picker.dart b/lib/widgets/time_picker.dart index 9ac7eb3..fd33b23 100644 --- a/lib/widgets/time_picker.dart +++ b/lib/widgets/time_picker.dart @@ -1,5 +1,5 @@ -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; +import 'package:cupertino_ui/cupertino_ui.dart'; +import 'package:material_ui/material_ui.dart'; /// A time picker widget that can be used to select a time duration /// based on the Time picker mode [CupertinoTimerPickerMode]. diff --git a/lib/widgets/year_picker.dart b/lib/widgets/year_picker.dart index 4f213b7..18b5200 100644 --- a/lib/widgets/year_picker.dart +++ b/lib/widgets/year_picker.dart @@ -1,5 +1,5 @@ import 'package:bottom_picker/widgets/simple_picker.dart'; -import 'package:flutter/cupertino.dart'; +import 'package:cupertino_ui/cupertino_ui.dart'; /// A year picker widget that can be used to select a year. class BottomYearDatePicker extends StatefulWidget { diff --git a/pubspec.lock b/pubspec.lock index 161ed16..69beeb4 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -41,6 +41,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.19.1" + cupertino_ui: + dependency: "direct main" + description: + name: cupertino_ui + sha256: "2137c0d41f3b62cc4d3d2495e6c354bd6b6133cd21c6bb155736cc31dbd49a11" + url: "https://pub.dev" + source: hosted + version: "1.0.1" fake_async: dependency: transitive description: @@ -62,11 +70,24 @@ packages: url: "https://pub.dev" source: hosted version: "6.0.0" + flutter_localizations: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" flutter_test: dependency: "direct dev" description: flutter source: sdk version: "0.0.0" + intl: + dependency: transitive + description: + name: intl + sha256: "3df61194eb431efc39c4ceba583b95633a403f46c9fd341e550ce0bfa50e9aa5" + url: "https://pub.dev" + source: hosted + version: "0.20.2" leak_tracker: dependency: transitive description: @@ -115,14 +136,22 @@ packages: url: "https://pub.dev" source: hosted version: "0.13.0" + material_ui: + dependency: "direct main" + description: + name: material_ui + sha256: "7ba1ca315d50a004791dbab290417c52a61466d56db2822fe3c5c2994903110c" + url: "https://pub.dev" + source: hosted + version: "1.1.0" meta: dependency: transitive description: name: meta - sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394" + sha256: "1741988757a65eb6b36abe716829688cf01910bbf91c34354ff7ec1c3de2b349" url: "https://pub.dev" source: hosted - version: "1.17.0" + version: "1.18.0" path: dependency: transitive description: @@ -180,10 +209,10 @@ packages: dependency: transitive description: name: test_api - sha256: "8161c84903fd860b26bfdefb7963b3f0b68fee7adea0f59ef805ecca346f0c7a" + sha256: "949a932224383300f01be9221c39180316445ecb8e7547f70a41a35bf421fb9e" url: "https://pub.dev" source: hosted - version: "0.7.10" + version: "0.7.11" vector_math: dependency: transitive description: @@ -201,5 +230,5 @@ packages: source: hosted version: "15.0.0" sdks: - dart: ">=3.9.0-0 <4.0.0" - flutter: ">=3.18.0-18.0.pre.54" + dart: ">=3.12.0 <4.0.0" + flutter: ">=3.44.0" diff --git a/pubspec.yaml b/pubspec.yaml index d3ac0d0..7ea1bd4 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,16 +1,18 @@ name: bottom_picker description: An easy way that let you create a bottom item picker or date & time picker with minmum parameters -version: 4.2.0 +version: 5.0.0 homepage: 'https://github.com/koukibadr/Bottom-Picker' environment: - sdk: '>=2.19.0 <4.0.0' - flutter: '>=1.17.0' + sdk: ^3.12.0 + flutter: '>=3.44.0' dependencies: + cupertino_ui: ^1.0.0 flutter: sdk: flutter + material_ui: ^1.0.0 + dev_dependencies: flutter_test: sdk: flutter flutter_lints: ^6.0.0 -flutter: null diff --git a/test/button_builder_test.dart b/test/button_builder_test.dart index 8b8bfe8..4d9ef71 100644 --- a/test/button_builder_test.dart +++ b/test/button_builder_test.dart @@ -1,6 +1,6 @@ import 'package:bottom_picker/bottom_picker.dart'; import 'package:bottom_picker/widgets/bottom_picker_button.dart'; -import 'package:flutter/material.dart'; +import 'package:material_ui/material_ui.dart'; import 'package:flutter_test/flutter_test.dart'; void main() { diff --git a/test/simple_bottom_picker_test.dart b/test/simple_bottom_picker_test.dart index 75f8931..2122060 100644 --- a/test/simple_bottom_picker_test.dart +++ b/test/simple_bottom_picker_test.dart @@ -1,7 +1,7 @@ import 'package:bottom_picker/bottom_picker.dart'; import 'package:bottom_picker/resources/arrays.dart'; import 'package:bottom_picker/widgets/bottom_picker_button.dart'; -import 'package:flutter/material.dart'; +import 'package:material_ui/material_ui.dart'; import 'package:flutter_test/flutter_test.dart'; void main() { From f96fe6da99c4d10ceb87205c37b28102d9234567 Mon Sep 17 00:00:00 2001 From: kjxbyz <47768002+kjxbyz@users.noreply.github.com> Date: Sun, 30 Aug 2026 18:06:20 +0800 Subject: [PATCH 2/2] fix: formatting code --- example/pubspec.lock | 2 +- lib/bottom_picker.dart | 266 ++++----- lib/cupertino/cupertino_date_picker.dart | 720 ++++++++++++----------- lib/resources/arrays.dart | 46 +- lib/resources/context_extension.dart | 8 +- lib/resources/time.dart | 18 +- lib/widgets/bottom_picker_button.dart | 13 +- lib/widgets/date_picker.dart | 7 +- lib/widgets/range_picker.dart | 6 +- lib/widgets/simple_picker.dart | 24 +- lib/widgets/time_picker.dart | 25 +- lib/widgets/year_picker.dart | 6 +- test/button_builder_test.dart | 177 +++--- test/simple_bottom_picker_test.dart | 265 ++++----- 14 files changed, 766 insertions(+), 817 deletions(-) diff --git a/example/pubspec.lock b/example/pubspec.lock index a279d7e..d73ee84 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -23,7 +23,7 @@ packages: path: ".." relative: true source: path - version: "4.2.0" + version: "5.0.0" characters: dependency: transitive description: diff --git a/lib/bottom_picker.dart b/lib/bottom_picker.dart index 3df0ed4..fdc7c7d 100644 --- a/lib/bottom_picker.dart +++ b/lib/bottom_picker.dart @@ -419,14 +419,10 @@ class BottomPicker extends StatefulWidget { use24hFormat = true; assertInitialValues(); if (minSecondDate != null && initialSecondDate != null) { - assert( - initialSecondDate!.isAtSameMomentOrAfter(minSecondDate!), - ); + assert(initialSecondDate!.isAtSameMomentOrAfter(minSecondDate!)); } if (minFirstDate != null && initialFirstDate != null) { - assert( - initialFirstDate!.isAtSameMomentOrAfter(minFirstDate!), - ); + assert(initialFirstDate!.isAtSameMomentOrAfter(minFirstDate!)); } } @@ -717,7 +713,7 @@ class BottomPicker extends StatefulWidget { /// and returns a [Widget] that will be used as the button. /// If it's null, the default button widget will be used (will be removed in the future). final Widget Function(BottomPicker instance, BuildContext context)? - buttonBuilder; + buttonBuilder; /// Invoked when pressing on the submit button when using range picker /// it return two dates (first time, end time) @@ -826,9 +822,7 @@ class BottomPicker extends StatefulWidget { context: context, isDismissible: dismissable, enableDrag: false, - constraints: BoxConstraints( - maxWidth: context.bottomPickerWidth, - ), + constraints: BoxConstraints(maxWidth: context.bottomPickerWidth), backgroundColor: Colors.transparent, builder: (context) { return BottomSheet( @@ -936,9 +930,7 @@ class BottomPickerState extends State> { @override Widget build(BuildContext context) { if (widget.useSafeArea) { - return SafeArea( - child: _bottomPickerWidget(context), - ); + return SafeArea(child: _bottomPickerWidget(context)); } return _bottomPickerWidget(context); } @@ -958,9 +950,7 @@ class BottomPickerState extends State> { child: Column( children: [ Padding( - padding: const EdgeInsets.symmetric( - horizontal: 20, - ), + padding: const EdgeInsets.symmetric(horizontal: 20), child: Directionality( textDirection: widget.layoutOrientation ?? TextDirection.ltr, child: Column( @@ -969,11 +959,7 @@ class BottomPickerState extends State> { Row( children: [ if (widget.headerBuilder != null) - Expanded( - child: widget.headerBuilder!( - context, - ), - ), + Expanded(child: widget.headerBuilder!(context)), ], ), ], @@ -1018,137 +1004,123 @@ class BottomPickerState extends State> { diameterRatio: widget.diameterRatio, ) : widget.bottomPickerType == BottomPickerType.timer - ? TimePicker( - mode: widget.timerPickerMode!, - minuteInterval: widget.minuteInterval, - textStyle: widget.pickerTextStyle, - itemExtent: widget.itemExtent, - initialDuration: widget.initialTimerDuration, - onChange: (p0) { - widget.onChange?.call(p0 as T); - _selectedTimerDuration = p0; - }, - secondInterval: widget.timerSecondsInterval, - pickerThemeData: widget.pickerThemeData, - ) - : widget.bottomPickerType == BottomPickerType.time - ? DatePicker( - initialDateTime: widget.initialTime.toDateTime, - minuteInterval: widget.minuteInterval, - maxDateTime: widget.maxTime.toDateTime, - minDateTime: widget.minTime.toDateTime, - mode: widget.datePickerMode, - onDateChanged: (DateTime date) { - _selectedDateTime = date; - widget.onChange?.call(date as T); - }, - use24hFormat: widget.use24hFormat, - dateOrder: widget.dateOrder, - textStyle: widget.pickerTextStyle, - itemExtent: widget.itemExtent, - showTimeSeparator: widget.showTimeSeparator, - pickerThemeData: widget.pickerThemeData, - ) - : widget.bottomPickerType == BottomPickerType.dateTime - ? DatePicker( - initialDateTime: widget.initialDateTime, - minuteInterval: widget.minuteInterval, - maxDateTime: widget.maxDateTime, - minDateTime: widget.minDateTime, - mode: widget.datePickerMode, - onDateChanged: (DateTime date) { - if (widget.calendarDays.isNotEmpty && - !widget.calendarDays - .contains(date.weekday)) { - return; - } - _selectedDateTime = date; - widget.onChange?.call(date as T); - }, - use24hFormat: widget.use24hFormat, - dateOrder: widget.dateOrder, - textStyle: widget.pickerTextStyle, - itemExtent: widget.itemExtent, - showTimeSeparator: widget.showTimeSeparator, - pickerThemeData: widget.pickerThemeData, - calendarDays: widget.calendarDays, - hourPredicate: widget.hourPredicate, - ) - : widget.bottomPickerType == BottomPickerType.year - ? BottomYearDatePicker( - initialDateTime: widget.initialDateTime, - maxDateTime: widget.maxDateTime, - minDateTime: widget.minDateTime, - onDateChanged: (DateTime date) { - _selectedDateTime = date; - widget.onChange?.call(date as T); - }, - itemExtent: widget.itemExtent, - pickerThemeData: widget.pickerThemeData, - ) - : widget.bottomPickerType == - BottomPickerType.rangeTime - ? RangePicker( - mode: CupertinoDatePickerMode.time, - use24hFormat: widget.use24hFormat, - initialFirstDateTime: - widget.initialFirstTime, - initialSecondDateTime: - widget.initialSecondTime, - maxFirstDate: widget.maxFirstTime, - minFirstDateTime: widget.minFirstTime, - maxSecondDate: widget.maxSecondTime, - minSecondDateTime: - widget.minSecondTime, - onFirstDateChanged: (DateTime date) { - _selectedFirstDateTime = date; - }, - onSecondDateChanged: (DateTime date) { - _selectedSecondDateTime = date; - }, - dateOrder: widget.dateOrder, - textStyle: widget.pickerTextStyle, - minuteInterval: widget.minuteInterval, - itemExtent: widget.itemExtent, - showTimeSeperator: - widget.showTimeSeparator, - pickerThemeData: - widget.pickerThemeData, - ) - : RangePicker( - mode: CupertinoDatePickerMode.date, - use24hFormat: widget.use24hFormat, - initialFirstDateTime: - widget.initialFirstDate, - initialSecondDateTime: - widget.initialSecondDate, - maxFirstDate: widget.maxFirstDate, - minFirstDateTime: widget.minFirstDate, - maxSecondDate: widget.maxSecondDate, - minSecondDateTime: - widget.minSecondDate, - onFirstDateChanged: (DateTime date) { - _selectedFirstDateTime = date; - }, - onSecondDateChanged: (DateTime date) { - _selectedSecondDateTime = date; - }, - dateOrder: widget.dateOrder, - textStyle: widget.pickerTextStyle, - itemExtent: widget.itemExtent, - showTimeSeperator: - widget.showTimeSeparator, - pickerThemeData: - widget.pickerThemeData, - ), + ? TimePicker( + mode: widget.timerPickerMode!, + minuteInterval: widget.minuteInterval, + textStyle: widget.pickerTextStyle, + itemExtent: widget.itemExtent, + initialDuration: widget.initialTimerDuration, + onChange: (p0) { + widget.onChange?.call(p0 as T); + _selectedTimerDuration = p0; + }, + secondInterval: widget.timerSecondsInterval, + pickerThemeData: widget.pickerThemeData, + ) + : widget.bottomPickerType == BottomPickerType.time + ? DatePicker( + initialDateTime: widget.initialTime.toDateTime, + minuteInterval: widget.minuteInterval, + maxDateTime: widget.maxTime.toDateTime, + minDateTime: widget.minTime.toDateTime, + mode: widget.datePickerMode, + onDateChanged: (DateTime date) { + _selectedDateTime = date; + widget.onChange?.call(date as T); + }, + use24hFormat: widget.use24hFormat, + dateOrder: widget.dateOrder, + textStyle: widget.pickerTextStyle, + itemExtent: widget.itemExtent, + showTimeSeparator: widget.showTimeSeparator, + pickerThemeData: widget.pickerThemeData, + ) + : widget.bottomPickerType == BottomPickerType.dateTime + ? DatePicker( + initialDateTime: widget.initialDateTime, + minuteInterval: widget.minuteInterval, + maxDateTime: widget.maxDateTime, + minDateTime: widget.minDateTime, + mode: widget.datePickerMode, + onDateChanged: (DateTime date) { + if (widget.calendarDays.isNotEmpty && + !widget.calendarDays.contains(date.weekday)) { + return; + } + _selectedDateTime = date; + widget.onChange?.call(date as T); + }, + use24hFormat: widget.use24hFormat, + dateOrder: widget.dateOrder, + textStyle: widget.pickerTextStyle, + itemExtent: widget.itemExtent, + showTimeSeparator: widget.showTimeSeparator, + pickerThemeData: widget.pickerThemeData, + calendarDays: widget.calendarDays, + hourPredicate: widget.hourPredicate, + ) + : widget.bottomPickerType == BottomPickerType.year + ? BottomYearDatePicker( + initialDateTime: widget.initialDateTime, + maxDateTime: widget.maxDateTime, + minDateTime: widget.minDateTime, + onDateChanged: (DateTime date) { + _selectedDateTime = date; + widget.onChange?.call(date as T); + }, + itemExtent: widget.itemExtent, + pickerThemeData: widget.pickerThemeData, + ) + : widget.bottomPickerType == BottomPickerType.rangeTime + ? RangePicker( + mode: CupertinoDatePickerMode.time, + use24hFormat: widget.use24hFormat, + initialFirstDateTime: widget.initialFirstTime, + initialSecondDateTime: widget.initialSecondTime, + maxFirstDate: widget.maxFirstTime, + minFirstDateTime: widget.minFirstTime, + maxSecondDate: widget.maxSecondTime, + minSecondDateTime: widget.minSecondTime, + onFirstDateChanged: (DateTime date) { + _selectedFirstDateTime = date; + }, + onSecondDateChanged: (DateTime date) { + _selectedSecondDateTime = date; + }, + dateOrder: widget.dateOrder, + textStyle: widget.pickerTextStyle, + minuteInterval: widget.minuteInterval, + itemExtent: widget.itemExtent, + showTimeSeperator: widget.showTimeSeparator, + pickerThemeData: widget.pickerThemeData, + ) + : RangePicker( + mode: CupertinoDatePickerMode.date, + use24hFormat: widget.use24hFormat, + initialFirstDateTime: widget.initialFirstDate, + initialSecondDateTime: widget.initialSecondDate, + maxFirstDate: widget.maxFirstDate, + minFirstDateTime: widget.minFirstDate, + maxSecondDate: widget.maxSecondDate, + minSecondDateTime: widget.minSecondDate, + onFirstDateChanged: (DateTime date) { + _selectedFirstDateTime = date; + }, + onSecondDateChanged: (DateTime date) { + _selectedSecondDateTime = date; + }, + dateOrder: widget.dateOrder, + textStyle: widget.pickerTextStyle, + itemExtent: widget.itemExtent, + showTimeSeperator: widget.showTimeSeparator, + pickerThemeData: widget.pickerThemeData, + ), ), if (widget.buttonBuilder != null) widget.buttonBuilder!(widget, context) else if (widget.displaySubmitButton) Padding( - padding: const EdgeInsets.symmetric( - vertical: 20, - ), + padding: const EdgeInsets.symmetric(vertical: 20), child: Row( mainAxisAlignment: widget.buttonAlignment, children: [ diff --git a/lib/cupertino/cupertino_date_picker.dart b/lib/cupertino/cupertino_date_picker.dart index 7e852fa..cf301c2 100644 --- a/lib/cupertino/cupertino_date_picker.dart +++ b/lib/cupertino/cupertino_date_picker.dart @@ -20,9 +20,7 @@ const double _kDatePickerPadSize = 12.0; // Eyeballed from iOS. const double _kSqueeze = 1.25; -const TextStyle _kDefaultPickerTextStyle = TextStyle( - letterSpacing: -0.83, -); +const TextStyle _kDefaultPickerTextStyle = TextStyle(letterSpacing: -0.83); // The item height is 32 and the magnifier height is 34, from // iOS simulators with "Debug View Hierarchy". @@ -50,8 +48,9 @@ const double _kTimerPickerColumnIntrinsicWidth = 106; typedef SelectableHourPredicate = bool Function(int hour); TextStyle _themeTextStyle(BuildContext context, {bool isValid = true}) { - final TextStyle style = - CupertinoTheme.of(context).textTheme.dateTimePickerTextStyle; + final TextStyle style = CupertinoTheme.of( + context, + ).textTheme.dateTimePickerTextStyle; return isValid ? style.copyWith( color: CupertinoDynamicColor.maybeResolve(style.color, context), @@ -75,22 +74,25 @@ void _animateColumnControllerToItem( ); } -const Widget _startSelectionOverlay = - CupertinoPickerDefaultSelectionOverlay(capEndEdge: false); +const Widget _startSelectionOverlay = CupertinoPickerDefaultSelectionOverlay( + capEndEdge: false, +); const Widget _centerSelectionOverlay = CupertinoPickerDefaultSelectionOverlay( capStartEdge: false, capEndEdge: false, ); -const Widget _endSelectionOverlay = - CupertinoPickerDefaultSelectionOverlay(capStartEdge: false); +const Widget _endSelectionOverlay = CupertinoPickerDefaultSelectionOverlay( + capStartEdge: false, +); /// Defines a function signature for creating a widget that serves as a selection overlay, /// given the current context, the selected item's index, and the total number of columns. -typedef SelectionOverlayBuilder = Widget? Function( - BuildContext context, { - required int columnCount, - required int selectedIndex, -}); +typedef SelectionOverlayBuilder = + Widget? Function( + BuildContext context, { + required int columnCount, + required int selectedIndex, + }); // Lays out the date picker based on how much space each single column needs. // @@ -126,8 +128,9 @@ class _DatePickerLayoutDelegate extends MultiChildLayoutDelegate { } for (int i = 0; i < columnWidths.length; i++) { - final int index = - textDirectionFactor == 1 ? i : columnWidths.length - i - 1; + final int index = textDirectionFactor == 1 + ? i + : columnWidths.length - i - 1; double childWidth = columnWidths[index] + _kDatePickerPadSize * 2; if (index == 0 || index == columnWidths.length - 1) { @@ -287,15 +290,12 @@ class CupertinoDatePickerWidget extends StatefulWidget { this.showTimeSeparator = false, this.calendarDays = fullWeek, this.selectableHourPredicate, - }) : initialDateTime = initialDateTime ?? DateTime.now(), - assert( - itemExtent > 0, - 'item extent should be greater than 0', - ), - assert( - minuteInterval > 0 && 60 % minuteInterval == 0, - 'minute interval is not a positive integer factor of 60', - ) { + }) : initialDateTime = initialDateTime ?? DateTime.now(), + assert(itemExtent > 0, 'item extent should be greater than 0'), + assert( + minuteInterval > 0 && 60 % minuteInterval == 0, + 'minute interval is not a positive integer factor of 60', + ) { assert( mode != CupertinoDatePickerMode.dateAndTime || minimumDate == null || @@ -488,10 +488,7 @@ class CupertinoDatePickerWidget extends StatefulWidget { DateTime.saturday, DateTime.sunday, ]; - static const List weekend = [ - DateTime.saturday, - DateTime.sunday, - ]; + static const List weekend = [DateTime.saturday, DateTime.sunday]; static const List workDays = [ DateTime.monday, @@ -533,8 +530,9 @@ class CupertinoDatePickerWidget extends StatefulWidget { switch (columnType) { case _PickerColumnType.date: for (int i = 1; i <= 12; i++) { - final String date = - localizations.datePickerMediumDate(DateTime(2018, i, 25)); + final String date = localizations.datePickerMediumDate( + DateTime(2018, i, 25), + ); longTexts.add(date); } break; @@ -567,8 +565,10 @@ class CupertinoDatePickerWidget extends StatefulWidget { if (showDayOfWeek) { for (int wd = 1; wd < DateTime.daysPerWeek; wd++) { - final String dayOfMonth = - localizations.datePickerDayOfMonth(longestDayOfMonth, wd); + final String dayOfMonth = localizations.datePickerDayOfMonth( + longestDayOfMonth, + wd, + ); longTexts.add(dayOfMonth); } } @@ -625,11 +625,12 @@ class CupertinoDatePickerWidget extends StatefulWidget { } } -typedef _ColumnBuilder = Widget Function( - double offAxisFraction, - TransitionBuilder itemPositioningBuilder, - Widget? selectionOverlay, -); +typedef _ColumnBuilder = + Widget Function( + double offAxisFraction, + TransitionBuilder itemPositioningBuilder, + Widget? selectionOverlay, + ); class _CupertinoDatePickerDateTimeState extends State { @@ -751,8 +752,9 @@ class _CupertinoDatePickerDateTimeState meridiemRegion = selectedAmPm; meridiemController = FixedExtentScrollController(initialItem: selectedAmPm); - hourController = - FixedExtentScrollController(initialItem: initialDateTime.hour); + hourController = FixedExtentScrollController( + initialItem: initialDateTime.hour, + ); minuteController = FixedExtentScrollController( initialItem: initialDateTime.minute ~/ widget.minuteInterval, ); @@ -792,8 +794,9 @@ class _CupertinoDatePickerDateTimeState minuteController.dispose(); meridiemController.dispose(); - PaintingBinding.instance.systemFonts - .removeListener(_handleSystemFontsChange); + PaintingBinding.instance.systemFonts.removeListener( + _handleSystemFontsChange, + ); super.dispose(); } @@ -810,8 +813,9 @@ class _CupertinoDatePickerDateTimeState // Thanks to the physical and meridiem region mapping, the only thing we // need to update is the meridiem controller, if it's not previously attached. meridiemController.dispose(); - meridiemController = - FixedExtentScrollController(initialItem: selectedAmPm); + meridiemController = FixedExtentScrollController( + initialItem: selectedAmPm, + ); } } @@ -819,14 +823,17 @@ class _CupertinoDatePickerDateTimeState void didChangeDependencies() { super.didChangeDependencies(); - textDirectionFactor = - Directionality.of(context) == TextDirection.ltr ? 1 : -1; + textDirectionFactor = Directionality.of(context) == TextDirection.ltr + ? 1 + : -1; localizations = CupertinoLocalizations.of(context); - alignCenterLeft = - textDirectionFactor == 1 ? Alignment.centerLeft : Alignment.centerRight; - alignCenterRight = - textDirectionFactor == 1 ? Alignment.centerRight : Alignment.centerLeft; + alignCenterLeft = textDirectionFactor == 1 + ? Alignment.centerLeft + : Alignment.centerRight; + alignCenterRight = textDirectionFactor == 1 + ? Alignment.centerRight + : Alignment.centerLeft; estimatedColumnWidths.clear(); } @@ -835,11 +842,11 @@ class _CupertinoDatePickerDateTimeState double _getEstimatedColumnWidth(_PickerColumnType columnType) { estimatedColumnWidths[columnType.index] ??= CupertinoDatePickerWidget._getColumnWidth( - columnType, - localizations, - context, - widget.showDayOfWeek, - ); + columnType, + localizations, + context, + widget.showDayOfWeek, + ); return estimatedColumnWidths[columnType.index]!; } @@ -859,7 +866,8 @@ class _CupertinoDatePickerDateTimeState void _onSelectedItemChange(int index) { final DateTime selected = selectedDateTime; - bool isDateInvalid = (widget.minimumDate?.isAfter(selected) ?? false) || + bool isDateInvalid = + (widget.minimumDate?.isAfter(selected) ?? false) || (widget.maximumDate?.isBefore(selected) ?? false); if (isDateInvalid) { @@ -932,8 +940,8 @@ class _CupertinoDatePickerDateTimeState final String dateText = rangeStart == DateTime(now.year, now.month, now.day) - ? localizations.todayLabel - : localizations.datePickerMediumDate(rangeStart); + ? localizations.todayLabel + : localizations.datePickerMediumDate(rangeStart); return itemPositioningBuilder( context, @@ -1025,15 +1033,17 @@ class _CupertinoDatePickerDateTimeState selectionOverlay: selectionOverlay, children: List.generate(24, (int index) { final int hour = isHourRegionFlipped ? (index + 12) % 24 : index; - final int displayHour = - widget.use24hFormat ? hour : (hour + 11) % 12 + 1; + final int displayHour = widget.use24hFormat + ? hour + : (hour + 11) % 12 + 1; return itemPositioningBuilder( context, Text( localizations.datePickerHour(displayHour), - semanticsLabel: - localizations.datePickerHourSemanticsLabel(displayHour), + semanticsLabel: localizations.datePickerHourSemanticsLabel( + displayHour, + ), style: _themeTextStyle( context, isValid: _isValidHour(selectedAmPm, index), @@ -1072,8 +1082,9 @@ class _CupertinoDatePickerDateTimeState onSelectedItemChanged: _onSelectedItemChange, looping: true, selectionOverlay: selectionOverlay, - children: - List.generate(60 ~/ widget.minuteInterval, (int index) { + children: List.generate(60 ~/ widget.minuteInterval, ( + int index, + ) { final int minute = index * widget.minuteInterval; final DateTime date = DateTime( @@ -1086,14 +1097,15 @@ class _CupertinoDatePickerDateTimeState final bool isInvalidMinute = (widget.minimumDate?.isAfter(date) ?? false) || - (widget.maximumDate?.isBefore(date) ?? false); + (widget.maximumDate?.isBefore(date) ?? false); return itemPositioningBuilder( context, Text( localizations.datePickerMinute(minute), - semanticsLabel: - localizations.datePickerMinuteSemanticsLabel(minute), + semanticsLabel: localizations.datePickerMinuteSemanticsLabel( + minute, + ), style: _themeTextStyle(context, isValid: !isInvalidMinute), ), ); @@ -1119,10 +1131,7 @@ class _CupertinoDatePickerDateTimeState children: List.generate(1, (int index) { return itemPositioningBuilder( context, - Text( - ':', - style: _themeTextStyle(context), - ), + Text(':', style: _themeTextStyle(context)), ); }), ); @@ -1182,8 +1191,9 @@ class _CupertinoDatePickerDateTimeState if (!widget.calendarDays.contains(selectedDate.weekday)) { const int daysThreshold = 1; - final DateTime targetDate = - selectedDate.add(const Duration(days: daysThreshold)); + final DateTime targetDate = selectedDate.add( + const Duration(days: daysThreshold), + ); _scrollToDate( targetDate, @@ -1200,8 +1210,9 @@ class _CupertinoDatePickerDateTimeState if (widget.selectableHourPredicate?.call(selectedDate.hour) == false) { const int daysThreshold = 1; - final DateTime targetDate = - selectedDate.add(const Duration(hours: daysThreshold)); + final DateTime targetDate = selectedDate.add( + const Duration(hours: daysThreshold), + ); _scrollToDate( targetDate, @@ -1232,8 +1243,9 @@ class _CupertinoDatePickerDateTimeState _checkOnHourDisplay(); if (minCheck || maxCheck) { // We have minCheck === !maxCheck. - final DateTime targetDate = - minCheck ? widget.minimumDate! : widget.maximumDate!; + final DateTime targetDate = minCheck + ? widget.minimumDate! + : widget.maximumDate!; _scrollToDate(targetDate, selectedDate, minCheck); } } @@ -1244,48 +1256,47 @@ class _CupertinoDatePickerDateTimeState bool minCheck, { int? newItemIndex, }) { - SchedulerBinding.instance.addPostFrameCallback( - (Duration timestamp) { - if (fromDate.year != newDate.year || - fromDate.month != newDate.month || - fromDate.day != newDate.day) { + SchedulerBinding.instance.addPostFrameCallback((Duration timestamp) { + if (fromDate.year != newDate.year || + fromDate.month != newDate.month || + fromDate.day != newDate.day) { + _animateColumnControllerToItem( + dateController, + newItemIndex ?? selectedDayFromInitial, + ); + } + + if (fromDate.hour != newDate.hour) { + final bool needsMeridiemChange = + !widget.use24hFormat && fromDate.hour ~/ 12 != newDate.hour ~/ 12; + // In AM/PM mode, the pickers should not scroll all the way to the other hour region. + if (needsMeridiemChange) { _animateColumnControllerToItem( - dateController, - newItemIndex ?? selectedDayFromInitial, + meridiemController, + 1 - meridiemController.selectedItem, ); - } - - if (fromDate.hour != newDate.hour) { - final bool needsMeridiemChange = - !widget.use24hFormat && fromDate.hour ~/ 12 != newDate.hour ~/ 12; - // In AM/PM mode, the pickers should not scroll all the way to the other hour region. - if (needsMeridiemChange) { - _animateColumnControllerToItem( - meridiemController, - 1 - meridiemController.selectedItem, - ); - // Keep the target item index in the current 12-h region. - final int newItem = (hourController.selectedItem ~/ 12) * 12 + - (hourController.selectedItem + newDate.hour - fromDate.hour) % - 12; - _animateColumnControllerToItem(hourController, newItem); - } else { - _animateColumnControllerToItem( - hourController, - hourController.selectedItem + newDate.hour - fromDate.hour, - ); - } + // Keep the target item index in the current 12-h region. + final int newItem = + (hourController.selectedItem ~/ 12) * 12 + + (hourController.selectedItem + newDate.hour - fromDate.hour) % 12; + _animateColumnControllerToItem(hourController, newItem); + } else { + _animateColumnControllerToItem( + hourController, + hourController.selectedItem + newDate.hour - fromDate.hour, + ); } + } - if (fromDate.minute != newDate.minute) { - final double positionDouble = newDate.minute / widget.minuteInterval; - final int position = - minCheck ? positionDouble.ceil() : positionDouble.floor(); - _animateColumnControllerToItem(minuteController, position); - } - }, - ); + if (fromDate.minute != newDate.minute) { + final double positionDouble = newDate.minute / widget.minuteInterval; + final int position = minCheck + ? positionDouble.ceil() + : positionDouble.floor(); + _animateColumnControllerToItem(minuteController, position); + } + }); } @override @@ -1306,8 +1317,8 @@ class _CupertinoDatePickerDateTimeState // Swap the hours and minutes if RTL to ensure they are in the correct position. final List<_ColumnBuilder> pickerBuilders = Directionality.of(context) == TextDirection.rtl - ? <_ColumnBuilder>[_buildMinutePicker, _buildHourPicker] - : <_ColumnBuilder>[_buildHourPicker, _buildMinutePicker]; + ? <_ColumnBuilder>[_buildMinutePicker, _buildHourPicker] + : <_ColumnBuilder>[_buildHourPicker, _buildMinutePicker]; if (widget.showTimeSeparator) { pickerBuilders.insert(1, _buildTimeSeperatorWidget); @@ -1319,8 +1330,9 @@ class _CupertinoDatePickerDateTimeState case DatePickerDateTimeOrder.date_time_dayPeriod: case DatePickerDateTimeOrder.time_dayPeriod_date: pickerBuilders.add(_buildAmPmPicker); - columnWidths - .add(_getEstimatedColumnWidth(_PickerColumnType.dayPeriod)); + columnWidths.add( + _getEstimatedColumnWidth(_PickerColumnType.dayPeriod), + ); break; case DatePickerDateTimeOrder.date_dayPeriod_time: @@ -1398,31 +1410,32 @@ class _CupertinoDatePickerDateTimeState pickers.add( LayoutId( id: i, - child: pickerBuilders[i]( - offAxisFraction, - (BuildContext context, Widget? child) { - late final Widget constrained = ConstrainedBox( - constraints: - BoxConstraints(maxWidth: width + _kDatePickerPadSize), - child: child, - ); + child: pickerBuilders[i](offAxisFraction, ( + BuildContext context, + Widget? child, + ) { + late final Widget constrained = ConstrainedBox( + constraints: BoxConstraints( + maxWidth: width + _kDatePickerPadSize, + ), + child: child, + ); - return Padding( - padding: padding, - child: Align( - alignment: lastColumn ? alignCenterLeft : alignCenterRight, - child: firstColumn || lastColumn ? constrained : child, - ), - ); - }, - selectionOverlay, - ), + return Padding( + padding: padding, + child: Align( + alignment: lastColumn ? alignCenterLeft : alignCenterRight, + child: firstColumn || lastColumn ? constrained : child, + ), + ); + }, selectionOverlay), ), ); } - final double maxPickerWidth = - totalColumnWidths > _kPickerWidth ? totalColumnWidths : _kPickerWidth; + final double maxPickerWidth = totalColumnWidths > _kPickerWidth + ? totalColumnWidths + : _kPickerWidth; return MediaQuery.withNoTextScaling( child: DefaultTextStyle.merge( @@ -1441,9 +1454,7 @@ class _CupertinoDatePickerDateTimeState } class _CupertinoDatePickerDateState extends State { - _CupertinoDatePickerDateState({ - required this.dateOrder, - }); + _CupertinoDatePickerDateState({required this.dateOrder}); final DatePickerDateOrder? dateOrder; @@ -1485,8 +1496,9 @@ class _CupertinoDatePickerDateState extends State { selectedYear = widget.initialDateTime.year; dayController = FixedExtentScrollController(initialItem: selectedDay - 1); - monthController = - FixedExtentScrollController(initialItem: selectedMonth - 1); + monthController = FixedExtentScrollController( + initialItem: selectedMonth - 1, + ); yearController = FixedExtentScrollController(initialItem: selectedYear); PaintingBinding.instance.systemFonts.addListener(_handleSystemFontsChange); @@ -1505,8 +1517,9 @@ class _CupertinoDatePickerDateState extends State { monthController.dispose(); yearController.dispose(); - PaintingBinding.instance.systemFonts - .removeListener(_handleSystemFontsChange); + PaintingBinding.instance.systemFonts.removeListener( + _handleSystemFontsChange, + ); super.dispose(); } @@ -1514,14 +1527,17 @@ class _CupertinoDatePickerDateState extends State { void didChangeDependencies() { super.didChangeDependencies(); - textDirectionFactor = - Directionality.of(context) == TextDirection.ltr ? 1 : -1; + textDirectionFactor = Directionality.of(context) == TextDirection.ltr + ? 1 + : -1; localizations = CupertinoLocalizations.of(context); - alignCenterLeft = - textDirectionFactor == 1 ? Alignment.centerLeft : Alignment.centerRight; - alignCenterRight = - textDirectionFactor == 1 ? Alignment.centerRight : Alignment.centerLeft; + alignCenterLeft = textDirectionFactor == 1 + ? Alignment.centerLeft + : Alignment.centerRight; + alignCenterRight = textDirectionFactor == 1 + ? Alignment.centerRight + : Alignment.centerLeft; _refreshEstimatedColumnWidths(); } @@ -1529,25 +1545,25 @@ class _CupertinoDatePickerDateState extends State { void _refreshEstimatedColumnWidths() { estimatedColumnWidths[_PickerColumnType.dayOfMonth.index] = CupertinoDatePickerWidget._getColumnWidth( - _PickerColumnType.dayOfMonth, - localizations, - context, - widget.showDayOfWeek, - ); + _PickerColumnType.dayOfMonth, + localizations, + context, + widget.showDayOfWeek, + ); estimatedColumnWidths[_PickerColumnType.month.index] = CupertinoDatePickerWidget._getColumnWidth( - _PickerColumnType.month, - localizations, - context, - widget.showDayOfWeek, - ); + _PickerColumnType.month, + localizations, + context, + widget.showDayOfWeek, + ); estimatedColumnWidths[_PickerColumnType.year.index] = CupertinoDatePickerWidget._getColumnWidth( - _PickerColumnType.year, - localizations, - context, - widget.showDayOfWeek, - ); + _PickerColumnType.year, + localizations, + context, + widget.showDayOfWeek, + ); } // The DateTime of the last day of a given month in a given year. @@ -1559,8 +1575,10 @@ class _CupertinoDatePickerDateState extends State { TransitionBuilder itemPositioningBuilder, Widget? selectionOverlay, ) { - final int daysInCurrentMonth = - _lastDayInMonth(selectedYear, selectedMonth).day; + final int daysInCurrentMonth = _lastDayInMonth( + selectedYear, + selectedMonth, + ).day; return NotificationListener( onNotification: (ScrollNotification notification) { if (notification is ScrollStartNotification) { @@ -1595,7 +1613,8 @@ class _CupertinoDatePickerDateState extends State { final int? dayOfWeek = widget.showDayOfWeek ? DateTime(selectedYear, selectedMonth, day).weekday : null; - final bool isInvalidDay = (day > daysInCurrentMonth) || + final bool isInvalidDay = + (day > daysInCurrentMonth) || (widget.minimumDate?.year == selectedYear && widget.minimumDate!.month == selectedMonth && widget.minimumDate!.day > day) || @@ -1652,13 +1671,13 @@ class _CupertinoDatePickerDateState extends State { final int month = index + 1; final bool isInvalidMonth = (widget.minimumDate?.year == selectedYear && - widget.minimumDate!.month > month) || - (widget.maximumDate?.year == selectedYear && - widget.maximumDate!.month < month); + widget.minimumDate!.month > month) || + (widget.maximumDate?.year == selectedYear && + widget.maximumDate!.month < month); final String monthName = (widget.mode == CupertinoDatePickerMode.monthYear) - ? localizations.datePickerStandaloneMonth(month) - : localizations.datePickerMonth(month); + ? localizations.datePickerStandaloneMonth(month) + : localizations.datePickerMonth(month); return itemPositioningBuilder( context, @@ -1712,7 +1731,8 @@ class _CupertinoDatePickerDateState extends State { return null; } - final bool isValidYear = (widget.minimumDate == null || + final bool isValidYear = + (widget.minimumDate == null || widget.minimumDate!.year <= year) && (widget.maximumDate == null || widget.maximumDate!.year >= year); @@ -1731,10 +1751,16 @@ class _CupertinoDatePickerDateState extends State { bool get _isCurrentDateValid { // The current date selection represents a range [minSelectedData, maxSelectDate]. - final DateTime minSelectedDate = - DateTime(selectedYear, selectedMonth, selectedDay); - final DateTime maxSelectedDate = - DateTime(selectedYear, selectedMonth, selectedDay + 1); + final DateTime minSelectedDate = DateTime( + selectedYear, + selectedMonth, + selectedDay, + ); + final DateTime maxSelectedDate = DateTime( + selectedYear, + selectedMonth, + selectedDay + 1, + ); final bool minCheck = widget.minimumDate?.isBefore(maxSelectedDate) ?? true; final bool maxCheck = @@ -1755,18 +1781,25 @@ class _CupertinoDatePickerDateState extends State { // Whenever scrolling lands on an invalid entry, the picker // automatically scrolls to a valid one. - final DateTime minSelectDate = - DateTime(selectedYear, selectedMonth, selectedDay); - final DateTime maxSelectDate = - DateTime(selectedYear, selectedMonth, selectedDay + 1); + final DateTime minSelectDate = DateTime( + selectedYear, + selectedMonth, + selectedDay, + ); + final DateTime maxSelectDate = DateTime( + selectedYear, + selectedMonth, + selectedDay + 1, + ); final bool minCheck = widget.minimumDate?.isBefore(maxSelectDate) ?? true; final bool maxCheck = widget.maximumDate?.isBefore(minSelectDate) ?? false; if (!minCheck || maxCheck) { // We have minCheck === !maxCheck. - final DateTime targetDate = - minCheck ? widget.maximumDate! : widget.minimumDate!; + final DateTime targetDate = minCheck + ? widget.maximumDate! + : widget.minimumDate!; _scrollToDate(targetDate); return; } @@ -1780,21 +1813,19 @@ class _CupertinoDatePickerDateState extends State { } void _scrollToDate(DateTime newDate) { - SchedulerBinding.instance.addPostFrameCallback( - (Duration timestamp) { - if (selectedYear != newDate.year) { - _animateColumnControllerToItem(yearController, newDate.year); - } + SchedulerBinding.instance.addPostFrameCallback((Duration timestamp) { + if (selectedYear != newDate.year) { + _animateColumnControllerToItem(yearController, newDate.year); + } - if (selectedMonth != newDate.month) { - _animateColumnControllerToItem(monthController, newDate.month - 1); - } + if (selectedMonth != newDate.month) { + _animateColumnControllerToItem(monthController, newDate.month - 1); + } - if (selectedDay != newDate.day) { - _animateColumnControllerToItem(dayController, newDate.day - 1); - } - }, - ); + if (selectedDay != newDate.day) { + _animateColumnControllerToItem(dayController, newDate.day - 1); + } + }); } @override @@ -1895,32 +1926,31 @@ class _CupertinoDatePickerDateState extends State { pickers.add( LayoutId( id: i, - child: pickerBuilders[i]( - offAxisFraction, - (BuildContext context, Widget? child) { - return Padding( - padding: firstColumn ? EdgeInsets.zero : padding, - child: Align( - alignment: lastColumn ? alignCenterLeft : alignCenterRight, - child: SizedBox( - width: width + _kDatePickerPadSize, - child: Align( - alignment: - firstColumn ? alignCenterLeft : alignCenterRight, - child: child, - ), + child: pickerBuilders[i](offAxisFraction, ( + BuildContext context, + Widget? child, + ) { + return Padding( + padding: firstColumn ? EdgeInsets.zero : padding, + child: Align( + alignment: lastColumn ? alignCenterLeft : alignCenterRight, + child: SizedBox( + width: width + _kDatePickerPadSize, + child: Align( + alignment: firstColumn ? alignCenterLeft : alignCenterRight, + child: child, ), ), - ); - }, - selectionOverlay, - ), + ), + ); + }, selectionOverlay), ), ); } - final double maxPickerWidth = - totalColumnWidths > _kPickerWidth ? totalColumnWidths : _kPickerWidth; + final double maxPickerWidth = totalColumnWidths > _kPickerWidth + ? totalColumnWidths + : _kPickerWidth; return MediaQuery.withNoTextScaling( child: DefaultTextStyle.merge( @@ -1940,9 +1970,7 @@ class _CupertinoDatePickerDateState extends State { class _CupertinoDatePickerMonthYearState extends State { - _CupertinoDatePickerMonthYearState({ - required this.dateOrder, - }); + _CupertinoDatePickerMonthYearState({required this.dateOrder}); final DatePickerDateOrder? dateOrder; @@ -1978,8 +2006,9 @@ class _CupertinoDatePickerMonthYearState selectedMonth = widget.initialDateTime.month; selectedYear = widget.initialDateTime.year; - monthController = - FixedExtentScrollController(initialItem: selectedMonth - 1); + monthController = FixedExtentScrollController( + initialItem: selectedMonth - 1, + ); yearController = FixedExtentScrollController(initialItem: selectedYear); PaintingBinding.instance.systemFonts.addListener(_handleSystemFontsChange); @@ -1997,8 +2026,9 @@ class _CupertinoDatePickerMonthYearState monthController.dispose(); yearController.dispose(); - PaintingBinding.instance.systemFonts - .removeListener(_handleSystemFontsChange); + PaintingBinding.instance.systemFonts.removeListener( + _handleSystemFontsChange, + ); super.dispose(); } @@ -2006,14 +2036,17 @@ class _CupertinoDatePickerMonthYearState void didChangeDependencies() { super.didChangeDependencies(); - textDirectionFactor = - Directionality.of(context) == TextDirection.ltr ? 1 : -1; + textDirectionFactor = Directionality.of(context) == TextDirection.ltr + ? 1 + : -1; localizations = CupertinoLocalizations.of(context); - alignCenterLeft = - textDirectionFactor == 1 ? Alignment.centerLeft : Alignment.centerRight; - alignCenterRight = - textDirectionFactor == 1 ? Alignment.centerRight : Alignment.centerLeft; + alignCenterLeft = textDirectionFactor == 1 + ? Alignment.centerLeft + : Alignment.centerRight; + alignCenterRight = textDirectionFactor == 1 + ? Alignment.centerRight + : Alignment.centerLeft; _refreshEstimatedColumnWidths(); } @@ -2021,19 +2054,19 @@ class _CupertinoDatePickerMonthYearState void _refreshEstimatedColumnWidths() { estimatedColumnWidths[_PickerColumnType.month.index] = CupertinoDatePickerWidget._getColumnWidth( - _PickerColumnType.month, - localizations, - context, - false, - standaloneMonth: widget.mode == CupertinoDatePickerMode.monthYear, - ); + _PickerColumnType.month, + localizations, + context, + false, + standaloneMonth: widget.mode == CupertinoDatePickerMode.monthYear, + ); estimatedColumnWidths[_PickerColumnType.year.index] = CupertinoDatePickerWidget._getColumnWidth( - _PickerColumnType.year, - localizations, - context, - false, - ); + _PickerColumnType.year, + localizations, + context, + false, + ); } Widget _buildMonthPicker( @@ -2072,13 +2105,13 @@ class _CupertinoDatePickerMonthYearState final int month = index + 1; final bool isInvalidMonth = (widget.minimumDate?.year == selectedYear && - widget.minimumDate!.month > month) || - (widget.maximumDate?.year == selectedYear && - widget.maximumDate!.month < month); + widget.minimumDate!.month > month) || + (widget.maximumDate?.year == selectedYear && + widget.maximumDate!.month < month); final String monthName = (widget.mode == CupertinoDatePickerMode.monthYear) - ? localizations.datePickerStandaloneMonth(month) - : localizations.datePickerMonth(month); + ? localizations.datePickerStandaloneMonth(month) + : localizations.datePickerMonth(month); return itemPositioningBuilder( context, @@ -2130,7 +2163,8 @@ class _CupertinoDatePickerMonthYearState return null; } - final bool isValidYear = (widget.minimumDate == null || + final bool isValidYear = + (widget.minimumDate == null || widget.minimumDate!.year <= year) && (widget.maximumDate == null || widget.maximumDate!.year >= year); @@ -2150,8 +2184,11 @@ class _CupertinoDatePickerMonthYearState bool get _isCurrentDateValid { // The current date selection represents a range [minSelectedData, maxSelectDate]. final DateTime minSelectedDate = DateTime(selectedYear, selectedMonth); - final DateTime maxSelectedDate = - DateTime(selectedYear, selectedMonth, widget.initialDateTime.day + 1); + final DateTime maxSelectedDate = DateTime( + selectedYear, + selectedMonth, + widget.initialDateTime.day + 1, + ); final bool minCheck = widget.minimumDate?.isBefore(maxSelectedDate) ?? true; final bool maxCheck = @@ -2173,33 +2210,35 @@ class _CupertinoDatePickerMonthYearState // Whenever scrolling lands on an invalid entry, the picker // automatically scrolls to a valid one. final DateTime minSelectDate = DateTime(selectedYear, selectedMonth); - final DateTime maxSelectDate = - DateTime(selectedYear, selectedMonth, widget.initialDateTime.day + 1); + final DateTime maxSelectDate = DateTime( + selectedYear, + selectedMonth, + widget.initialDateTime.day + 1, + ); final bool minCheck = widget.minimumDate?.isBefore(maxSelectDate) ?? true; final bool maxCheck = widget.maximumDate?.isBefore(minSelectDate) ?? false; if (!minCheck || maxCheck) { // We have minCheck === !maxCheck. - final DateTime targetDate = - minCheck ? widget.maximumDate! : widget.minimumDate!; + final DateTime targetDate = minCheck + ? widget.maximumDate! + : widget.minimumDate!; _scrollToDate(targetDate); return; } } void _scrollToDate(DateTime newDate) { - SchedulerBinding.instance.addPostFrameCallback( - (Duration timestamp) { - if (selectedYear != newDate.year) { - _animateColumnControllerToItem(yearController, newDate.year); - } + SchedulerBinding.instance.addPostFrameCallback((Duration timestamp) { + if (selectedYear != newDate.year) { + _animateColumnControllerToItem(yearController, newDate.year); + } - if (selectedMonth != newDate.month) { - _animateColumnControllerToItem(monthController, newDate.month - 1); - } - }, - ); + if (selectedMonth != newDate.month) { + _animateColumnControllerToItem(monthController, newDate.month - 1); + } + }); } @override @@ -2261,38 +2300,39 @@ class _CupertinoDatePickerMonthYearState pickers.add( LayoutId( id: i, - child: pickerBuilders[i]( - offAxisFraction, - (BuildContext context, Widget? child) { - final Widget contents = Align( - alignment: lastColumn ? alignCenterLeft : alignCenterRight, - child: SizedBox( - width: width + _kDatePickerPadSize, - child: Align( - alignment: firstColumn ? alignCenterLeft : alignCenterRight, - child: child, - ), + child: pickerBuilders[i](offAxisFraction, ( + BuildContext context, + Widget? child, + ) { + final Widget contents = Align( + alignment: lastColumn ? alignCenterLeft : alignCenterRight, + child: SizedBox( + width: width + _kDatePickerPadSize, + child: Align( + alignment: firstColumn ? alignCenterLeft : alignCenterRight, + child: child, ), - ); - if (firstColumn) { - return contents; - } - - const EdgeInsets padding = - EdgeInsets.only(right: _kDatePickerPadSize); - return Padding( - padding: textDirectionFactor == -1 ? padding.flipped : padding, - child: contents, - ); - }, - selectionOverlay, - ), + ), + ); + if (firstColumn) { + return contents; + } + + const EdgeInsets padding = EdgeInsets.only( + right: _kDatePickerPadSize, + ); + return Padding( + padding: textDirectionFactor == -1 ? padding.flipped : padding, + child: contents, + ); + }, selectionOverlay), ), ); } - final double maxPickerWidth = - totalColumnWidths > _kPickerWidth ? totalColumnWidths : _kPickerWidth; + final double maxPickerWidth = totalColumnWidths > _kPickerWidth + ? totalColumnWidths + : _kPickerWidth; return MediaQuery.withNoTextScaling( child: DefaultTextStyle.merge( @@ -2376,13 +2416,13 @@ class CupertinoTimerPicker extends StatefulWidget { this.itemExtent = _kItemExtent, required this.onTimerDurationChanged, this.selectionOverlayBuilder, - }) : assert(initialTimerDuration >= Duration.zero), - assert(initialTimerDuration < const Duration(days: 1)), - assert(minuteInterval > 0 && 60 % minuteInterval == 0), - assert(secondInterval > 0 && 60 % secondInterval == 0), - assert(initialTimerDuration.inMinutes % minuteInterval == 0), - assert(initialTimerDuration.inSeconds % secondInterval == 0), - assert(itemExtent > 0, 'item extent should be greater than 0'); + }) : assert(initialTimerDuration >= Duration.zero), + assert(initialTimerDuration < const Duration(days: 1)), + assert(minuteInterval > 0 && 60 % minuteInterval == 0), + assert(secondInterval > 0 && 60 % secondInterval == 0), + assert(initialTimerDuration.inMinutes % minuteInterval == 0), + assert(initialTimerDuration.inSeconds % secondInterval == 0), + assert(itemExtent > 0, 'item extent should be greater than 0'); /// The mode of the timer picker. final CupertinoTimerPickerMode mode; @@ -2527,8 +2567,9 @@ class _CupertinoTimerPickerState extends State { @override void dispose() { - PaintingBinding.instance.systemFonts - .removeListener(_handleSystemFontsChange); + PaintingBinding.instance.systemFonts.removeListener( + _handleSystemFontsChange, + ); textPainter.dispose(); _hourScrollController?.dispose(); @@ -2559,8 +2600,10 @@ class _CupertinoTimerPickerState extends State { void _measureLabelMetrics() { textPainter.textDirection = textDirection; - final TextStyle textStyle = - _textStyleFrom(context, _kTimerPickerMagnification); + final TextStyle textStyle = _textStyleFrom( + context, + _kTimerPickerMagnification, + ); double maxWidth = double.negativeInfinity; String? widestNumber; @@ -2573,10 +2616,7 @@ class _CupertinoTimerPickerState extends State { // - If two different 1-digit numbers are of the same width, their corresponding // 2 digit numbers are of the same width. for (final String input in numbers) { - textPainter.text = TextSpan( - text: input, - style: textStyle, - ); + textPainter.text = TextSpan(text: input, style: textStyle); textPainter.layout(); if (textPainter.maxIntrinsicWidth > maxWidth) { @@ -2593,8 +2633,9 @@ class _CupertinoTimerPickerState extends State { textPainter.layout(); numberLabelWidth = textPainter.maxIntrinsicWidth; numberLabelHeight = textPainter.height; - numberLabelBaseline = - textPainter.computeDistanceToActualBaseline(TextBaseline.alphabetic); + numberLabelBaseline = textPainter.computeDistanceToActualBaseline( + TextBaseline.alphabetic, + ); minuteLabelWidth = _measureLabelsMaxWidth( localizations.timerPickerMinuteLabels, @@ -2701,8 +2742,9 @@ class _CupertinoTimerPickerState extends State { EdgeInsetsDirectional additionalPadding, Widget? selectionOverlay, ) { - _hourScrollController ??= - FixedExtentScrollController(initialItem: selectedHour!); + _hourScrollController ??= FixedExtentScrollController( + initialItem: selectedHour!, + ); return CupertinoPicker( scrollController: _hourScrollController, magnification: _kMagnification, @@ -2762,8 +2804,9 @@ class _CupertinoTimerPickerState extends State { child: _buildHourPicker(additionalPadding, selectionOverlay), ), _buildLabel( - localizations - .timerPickerHourLabel(lastSelectedHour ?? selectedHour!) ?? + localizations.timerPickerHourLabel( + lastSelectedHour ?? selectedHour!, + ) ?? '', additionalPadding, ), @@ -2936,8 +2979,9 @@ class _CupertinoTimerPickerState extends State { // Returns [CupertinoTextThemeData.pickerTextStyle] and magnifies the fontSize // by [magnification]. TextStyle _textStyleFrom(BuildContext context, [double magnification = 1.0]) { - final TextStyle textStyle = - CupertinoTheme.of(context).textTheme.pickerTextStyle; + final TextStyle textStyle = CupertinoTheme.of( + context, + ).textTheme.pickerTextStyle; return textStyle.copyWith( color: CupertinoDynamicColor.maybeResolve(textStyle.color, context), fontSize: textStyle.fontSize! * magnification, @@ -2970,7 +3014,8 @@ class _CupertinoTimerPickerState extends State { if (widget.mode == CupertinoTimerPickerMode.hms) { // Pad the widget to make it as wide as `_kPickerWidth`. - pickerColumnWidth = _kTimerPickerColumnIntrinsicWidth + + pickerColumnWidth = + _kTimerPickerColumnIntrinsicWidth + (_kTimerPickerHalfColumnPadding * 2); totalWidth = pickerColumnWidth * 3; } else { @@ -2981,7 +3026,8 @@ class _CupertinoTimerPickerState extends State { if (constraints.maxWidth < totalWidth) { totalWidth = constraints.maxWidth; - pickerColumnWidth = totalWidth / + pickerColumnWidth = + totalWidth / (widget.mode == CupertinoTimerPickerMode.hms ? 3 : 2); } @@ -2995,14 +3041,16 @@ class _CupertinoTimerPickerState extends State { // Pad the widget to make it as wide as `_kPickerWidth`. final double hourLabelContentWidth = baseLabelContentWidth + hourLabelWidth; - double hourColumnStartPadding = pickerColumnWidth - + double hourColumnStartPadding = + pickerColumnWidth - hourLabelContentWidth - _kTimerPickerHalfColumnPadding; if (hourColumnStartPadding < _kTimerPickerMinHorizontalPadding) { hourColumnStartPadding = _kTimerPickerMinHorizontalPadding; } - double minuteColumnEndPadding = pickerColumnWidth - + double minuteColumnEndPadding = + pickerColumnWidth - minuteLabelContentWidth - _kTimerPickerHalfColumnPadding; if (minuteColumnEndPadding < _kTimerPickerMinHorizontalPadding) { @@ -3029,7 +3077,8 @@ class _CupertinoTimerPickerState extends State { _buildHourColumn( EdgeInsetsDirectional.only( start: hourColumnStartPadding, - end: pickerColumnWidth - + end: + pickerColumnWidth - hourColumnStartPadding - hourLabelContentWidth, ), @@ -3037,7 +3086,8 @@ class _CupertinoTimerPickerState extends State { ), _buildMinuteColumn( EdgeInsetsDirectional.only( - start: pickerColumnWidth - + start: + pickerColumnWidth - minuteColumnEndPadding - minuteLabelContentWidth, end: minuteColumnEndPadding, @@ -3049,14 +3099,16 @@ class _CupertinoTimerPickerState extends State { case CupertinoTimerPickerMode.ms: final double secondLabelContentWidth = baseLabelContentWidth + secondLabelWidth; - double secondColumnEndPadding = pickerColumnWidth - + double secondColumnEndPadding = + pickerColumnWidth - secondLabelContentWidth - _kTimerPickerHalfColumnPadding; if (secondColumnEndPadding < _kTimerPickerMinHorizontalPadding) { secondColumnEndPadding = _kTimerPickerMinHorizontalPadding; } - double minuteColumnStartPadding = pickerColumnWidth - + double minuteColumnStartPadding = + pickerColumnWidth - minuteLabelContentWidth - _kTimerPickerHalfColumnPadding; if (minuteColumnStartPadding < _kTimerPickerMinHorizontalPadding) { @@ -3083,7 +3135,8 @@ class _CupertinoTimerPickerState extends State { _buildMinuteColumn( EdgeInsetsDirectional.only( start: minuteColumnStartPadding, - end: pickerColumnWidth - + end: + pickerColumnWidth - minuteColumnStartPadding - minuteLabelContentWidth, ), @@ -3091,7 +3144,8 @@ class _CupertinoTimerPickerState extends State { ), _buildSecondColumn( EdgeInsetsDirectional.only( - start: pickerColumnWidth - + start: + pickerColumnWidth - secondColumnEndPadding - minuteLabelContentWidth, end: secondColumnEndPadding, @@ -3101,13 +3155,15 @@ class _CupertinoTimerPickerState extends State { ]; break; case CupertinoTimerPickerMode.hms: - final double hourColumnEndPadding = pickerColumnWidth - + final double hourColumnEndPadding = + pickerColumnWidth - baseLabelContentWidth - hourLabelWidth - _kTimerPickerMinHorizontalPadding; final double minuteColumnPadding = (pickerColumnWidth - minuteLabelContentWidth) / 2; - final double secondColumnStartPadding = pickerColumnWidth - + final double secondColumnStartPadding = + pickerColumnWidth - baseLabelContentWidth - secondLabelWidth - _kTimerPickerMinHorizontalPadding; @@ -3172,8 +3228,10 @@ class _CupertinoTimerPickerState extends State { ), ), ); - final Color? color = - CupertinoDynamicColor.maybeResolve(widget.backgroundColor, context); + final Color? color = CupertinoDynamicColor.maybeResolve( + widget.backgroundColor, + context, + ); if (color != null) { contents = ColoredBox(color: color, child: contents); } @@ -3185,8 +3243,10 @@ class _CupertinoTimerPickerState extends State { child: CupertinoTheme( data: themeData.copyWith( textTheme: themeData.textTheme.copyWith( - pickerTextStyle: - _textStyleFrom(context, _kTimerPickerMagnification), + pickerTextStyle: _textStyleFrom( + context, + _kTimerPickerMagnification, + ), ), ), child: Align(alignment: widget.alignment, child: contents), diff --git a/lib/resources/arrays.dart b/lib/resources/arrays.dart index dbbfab4..62c5522 100644 --- a/lib/resources/arrays.dart +++ b/lib/resources/arrays.dart @@ -11,46 +11,14 @@ enum BottomPickerType { } enum BottomPickerTheme { - blue( - gradientColors: [ - Color(0xFF3366FF), - Color(0xFF00CCFF), - ], - ), - orange( - gradientColors: [ - Color(0xFFff7e5f), - Color(0xFFfeb47b), - ], - ), - temptingAzure( - gradientColors: [ - Color(0xFF84fab0), - Color(0xFF8fd3f4), - ], - ), - heavyRain( - gradientColors: [ - Color(0xFFcfd9df), - Color(0xFFe2ebf0), - ], - ), - plumPlate( - gradientColors: [ - Color(0xFF667eea), - Color(0xFF764ba2), - ], - ), - morningSalad( - gradientColors: [ - Color(0xFFB7F8DB), - Color(0xFF50A7C2), - ], - ); + blue(gradientColors: [Color(0xFF3366FF), Color(0xFF00CCFF)]), + orange(gradientColors: [Color(0xFFff7e5f), Color(0xFFfeb47b)]), + temptingAzure(gradientColors: [Color(0xFF84fab0), Color(0xFF8fd3f4)]), + heavyRain(gradientColors: [Color(0xFFcfd9df), Color(0xFFe2ebf0)]), + plumPlate(gradientColors: [Color(0xFF667eea), Color(0xFF764ba2)]), + morningSalad(gradientColors: [Color(0xFFB7F8DB), Color(0xFF50A7C2)]); final List gradientColors; - const BottomPickerTheme({ - required this.gradientColors, - }); + const BottomPickerTheme({required this.gradientColors}); } diff --git a/lib/resources/context_extension.dart b/lib/resources/context_extension.dart index d288f58..6e6d597 100644 --- a/lib/resources/context_extension.dart +++ b/lib/resources/context_extension.dart @@ -4,11 +4,11 @@ import 'package:cupertino_ui/cupertino_ui.dart'; extension ContextExtensions on BuildContext { double get bottomPickerWidth => MediaQuery.of(this).size.width >= tabletMinSize - ? MediaQuery.of(this).size.width * 0.7 - : MediaQuery.of(this).size.width; + ? MediaQuery.of(this).size.width * 0.7 + : MediaQuery.of(this).size.width; double get bottomPickerHeight => MediaQuery.of(this).size.height >= tabletMinSize - ? MediaQuery.of(this).size.height * 0.35 - : MediaQuery.of(this).size.height * 0.45; + ? MediaQuery.of(this).size.height * 0.35 + : MediaQuery.of(this).size.height * 0.45; } diff --git a/lib/resources/time.dart b/lib/resources/time.dart index 4d05c5b..08b9426 100644 --- a/lib/resources/time.dart +++ b/lib/resources/time.dart @@ -2,10 +2,8 @@ class Time { late int hours; late int minutes; - Time({ - this.hours = 0, - this.minutes = 0, - }) : assert(minutes < 60 && minutes >= 0 && hours >= 0 && hours < 24); + Time({this.hours = 0, this.minutes = 0}) + : assert(minutes < 60 && minutes >= 0 && hours >= 0 && hours < 24); Time.now() { hours = DateTime.now().hour; @@ -13,10 +11,10 @@ class Time { } DateTime get toDateTime => DateTime( - DateTime.now().year, - DateTime.now().month, - DateTime.now().day, - hours, - minutes, - ); + DateTime.now().year, + DateTime.now().month, + DateTime.now().day, + hours, + minutes, + ); } diff --git a/lib/widgets/bottom_picker_button.dart b/lib/widgets/bottom_picker_button.dart index ac6589f..6d8c5d6 100644 --- a/lib/widgets/bottom_picker_button.dart +++ b/lib/widgets/bottom_picker_button.dart @@ -51,7 +51,8 @@ class BottomPickerButton extends StatelessWidget { child: Container( width: buttonWidth ?? 100, padding: EdgeInsets.all(buttonPadding ?? 8.0), - decoration: style ?? + decoration: + style ?? BoxDecoration( borderRadius: BorderRadius.circular(5), color: solidColor, @@ -65,14 +66,10 @@ class BottomPickerButton extends StatelessWidget { ) : null, ), - child: buttonChild ?? + child: + buttonChild ?? const Center( - child: Text( - 'Select', - style: TextStyle( - color: Colors.white, - ), - ), + child: Text('Select', style: TextStyle(color: Colors.white)), ), ), ); diff --git a/lib/widgets/date_picker.dart b/lib/widgets/date_picker.dart index e2fa094..9ce87af 100644 --- a/lib/widgets/date_picker.dart +++ b/lib/widgets/date_picker.dart @@ -67,10 +67,9 @@ class DatePicker extends StatelessWidget { Widget build(BuildContext context) { return CupertinoTheme( data: CupertinoThemeData( - textTheme: pickerThemeData ?? - CupertinoTextThemeData( - dateTimePickerTextStyle: textStyle, - ), + textTheme: + pickerThemeData ?? + CupertinoTextThemeData(dateTimePickerTextStyle: textStyle), ), child: CupertinoDatePickerWidget( itemExtent: itemExtent ?? 0, diff --git a/lib/widgets/range_picker.dart b/lib/widgets/range_picker.dart index a0d62e9..a81a0e0 100644 --- a/lib/widgets/range_picker.dart +++ b/lib/widgets/range_picker.dart @@ -88,14 +88,16 @@ class _RangePickerState extends State { if (widget.mode == CupertinoDatePickerMode.time) { // If it is a time range, the minimum time uses the date of the day, ignores the date, and only needs the time // The default is 0:0:0 - minFirstDateTime = widget.minFirstDateTime ?? + minFirstDateTime = + widget.minFirstDateTime ?? DateTime( DateTime.now().year, DateTime.now().month, DateTime.now().day, ); initialFirstDateTime = widget.initialFirstDateTime ?? minFirstDateTime; - minSecondDateTime = widget.minSecondDateTime ?? + minSecondDateTime = + widget.minSecondDateTime ?? DateTime( DateTime.now().year, DateTime.now().month, diff --git a/lib/widgets/simple_picker.dart b/lib/widgets/simple_picker.dart index f7fd204..f99878a 100644 --- a/lib/widgets/simple_picker.dart +++ b/lib/widgets/simple_picker.dart @@ -49,16 +49,16 @@ class SimplePicker extends StatelessWidget { if (!kIsWeb && (Platform.isIOS || Platform.isAndroid)) { return CupertinoTheme( data: CupertinoThemeData( - textTheme: pickerThemeData ?? - CupertinoTextThemeData( - pickerTextStyle: textStyle, - ), + textTheme: + pickerThemeData ?? + CupertinoTextThemeData(pickerTextStyle: textStyle), ), child: CupertinoPicker( offAxisFraction: 2.0, diameterRatio: diameterRatio, itemExtent: itemExtent, - selectionOverlay: selectionOverlay ?? + selectionOverlay: + selectionOverlay ?? const CupertinoPickerDefaultSelectionOverlay(), scrollController: FixedExtentScrollController( initialItem: selectedItemIndex, @@ -69,10 +69,7 @@ class SimplePicker extends StatelessWidget { if (itemBuilder != null) { return itemBuilder!(items[index], index); } else { - return Text( - items[index].toString(), - style: textStyle, - ); + return Text(items[index].toString(), style: textStyle); } }), ), @@ -84,17 +81,12 @@ class SimplePicker extends StatelessWidget { if (itemBuilder != null) { return itemBuilder!(items[index], index); } else { - return Text( - items[index].toString(), - style: textStyle, - ); + return Text(items[index].toString(), style: textStyle); } }), useMagnifier: true, magnification: 1.5, - controller: FixedExtentScrollController( - initialItem: selectedItemIndex, - ), + controller: FixedExtentScrollController(initialItem: selectedItemIndex), onSelectedItemChanged: onChange, ); } diff --git a/lib/widgets/time_picker.dart b/lib/widgets/time_picker.dart index fd33b23..f55aa91 100644 --- a/lib/widgets/time_picker.dart +++ b/lib/widgets/time_picker.dart @@ -56,24 +56,23 @@ class TimePicker extends StatelessWidget { this.initialDuration, this.secondInterval = 1, this.pickerThemeData, - }) : assert( - minuteInterval > 0 && minuteInterval < 60, - 'minuteInterval must be a positive integer from 1 to 59.', - ), - assert(itemExtent > 0, 'itemExtent must be a positive number.'), - assert( - secondInterval > 0 && secondInterval < 60, - 'secondInterval must be a positive integer from 1 to 59.', - ); + }) : assert( + minuteInterval > 0 && minuteInterval < 60, + 'minuteInterval must be a positive integer from 1 to 59.', + ), + assert(itemExtent > 0, 'itemExtent must be a positive number.'), + assert( + secondInterval > 0 && secondInterval < 60, + 'secondInterval must be a positive integer from 1 to 59.', + ); @override Widget build(BuildContext context) { return CupertinoTheme( data: CupertinoThemeData( - textTheme: pickerThemeData ?? - CupertinoTextThemeData( - dateTimePickerTextStyle: textStyle, - ), + textTheme: + pickerThemeData ?? + CupertinoTextThemeData(dateTimePickerTextStyle: textStyle), ), child: CupertinoTimerPicker( itemExtent: itemExtent, diff --git a/lib/widgets/year_picker.dart b/lib/widgets/year_picker.dart index 18b5200..cf3010a 100644 --- a/lib/widgets/year_picker.dart +++ b/lib/widgets/year_picker.dart @@ -68,11 +68,7 @@ class _BottomYearDatePicker extends State { return SimplePicker( items: years, onChange: (index) { - widget.onDateChanged( - DateTime( - years[index], - ), - ); + widget.onDateChanged(DateTime(years[index])); }, selectedItemIndex: 0, itemExtent: widget.itemExtent ?? 0, diff --git a/test/button_builder_test.dart b/test/button_builder_test.dart index 4d9ef71..dcef15c 100644 --- a/test/button_builder_test.dart +++ b/test/button_builder_test.dart @@ -5,113 +5,98 @@ import 'package:flutter_test/flutter_test.dart'; void main() { group('Button builder tests...', () { - late List items = List.generate( - 10, - (index) => index, - ); + late List items = List.generate(10, (index) => index); testWidgets( - 'Use case: no button builder provided, displaySubmitButton = false', - (tester) async { - var bottomPicker = BottomPicker( - headerBuilder: (context) { - return Text('Item picker'); - }, - items: items, - displaySubmitButton: false, - ); - await tester.pumpWidget( - MaterialApp( - home: Scaffold( - body: bottomPicker, - ), - ), - ); + 'Use case: no button builder provided, displaySubmitButton = false', + (tester) async { + var bottomPicker = BottomPicker( + headerBuilder: (context) { + return Text('Item picker'); + }, + items: items, + displaySubmitButton: false, + ); + await tester.pumpWidget( + MaterialApp(home: Scaffold(body: bottomPicker)), + ); - expect(find.byType(BottomPickerButton), findsNothing); - expect(bottomPicker.buttonBuilder, isNull); - }); + expect(find.byType(BottomPickerButton), findsNothing); + expect(bottomPicker.buttonBuilder, isNull); + }, + ); testWidgets( - 'Use case: buttonBuilder provided, displaySubmitButton = false, buttonBuilder should be used', - (tester) async { - var bottomPicker = BottomPicker( - headerBuilder: (context) { - return Text('Item picker'); - }, - items: items, - displaySubmitButton: false, - buttonBuilder: (instance, context) { - return ElevatedButton( - onPressed: () {}, - child: Text('Custom Button'), - ); - }, - ); - await tester.pumpWidget( - MaterialApp( - home: Scaffold( - body: bottomPicker, - ), - ), - ); + 'Use case: buttonBuilder provided, displaySubmitButton = false, buttonBuilder should be used', + (tester) async { + var bottomPicker = BottomPicker( + headerBuilder: (context) { + return Text('Item picker'); + }, + items: items, + displaySubmitButton: false, + buttonBuilder: (instance, context) { + return ElevatedButton( + onPressed: () {}, + child: Text('Custom Button'), + ); + }, + ); + await tester.pumpWidget( + MaterialApp(home: Scaffold(body: bottomPicker)), + ); - expect(find.byType(BottomPickerButton), findsNothing); - expect(bottomPicker.buttonBuilder, isNotNull); - expect(find.text('Custom Button'), findsOneWidget); - }); + expect(find.byType(BottomPickerButton), findsNothing); + expect(bottomPicker.buttonBuilder, isNotNull); + expect(find.text('Custom Button'), findsOneWidget); + }, + ); testWidgets( - 'Use case: buttonBuilder is not provided but displaySubmitButton = true, default button should be used', - (tester) async { - var bottomPicker = BottomPicker( - headerBuilder: (context) { - return Text('Item picker'); - }, - items: items, - buttonContent: Text('Submit'), - buttonBuilder: null, - ); - await tester.pumpWidget( - MaterialApp( - home: Scaffold( - body: bottomPicker, - ), - ), - ); + 'Use case: buttonBuilder is not provided but displaySubmitButton = true, default button should be used', + (tester) async { + var bottomPicker = BottomPicker( + headerBuilder: (context) { + return Text('Item picker'); + }, + items: items, + buttonContent: Text('Submit'), + buttonBuilder: null, + ); + await tester.pumpWidget( + MaterialApp(home: Scaffold(body: bottomPicker)), + ); - expect(find.byType(BottomPickerButton), findsOneWidget); - expect(find.text('Submit'), findsOneWidget); - expect(bottomPicker.buttonBuilder, isNull); - }); + expect(find.byType(BottomPickerButton), findsOneWidget); + expect(find.text('Submit'), findsOneWidget); + expect(bottomPicker.buttonBuilder, isNull); + }, + ); testWidgets( - 'Use case: buttonBuilder is provided and displaySubmitButton = true, buttonBuilder should be used', - (tester) async { - var bottomPicker = BottomPicker( - headerBuilder: (context) { - return Text('Item picker'); - }, - items: items, - buttonContent: Text('Submit'), - buttonBuilder: (instance, context) { - return ElevatedButton( - onPressed: () {}, - child: Text('Custom Button'), - ); - }, - ); - await tester.pumpWidget( - MaterialApp( - home: Scaffold( - body: bottomPicker, - ), - ), - ); + 'Use case: buttonBuilder is provided and displaySubmitButton = true, buttonBuilder should be used', + (tester) async { + var bottomPicker = BottomPicker( + headerBuilder: (context) { + return Text('Item picker'); + }, + items: items, + buttonContent: Text('Submit'), + buttonBuilder: (instance, context) { + return ElevatedButton( + onPressed: () {}, + child: Text('Custom Button'), + ); + }, + ); + await tester.pumpWidget( + MaterialApp(home: Scaffold(body: bottomPicker)), + ); - expect(find.byType(BottomPickerButton), findsNothing); - expect(find.text('Custom Button'), findsOneWidget); - expect(bottomPicker.buttonBuilder, isNotNull); - }); + expect(find.byType(BottomPickerButton), findsNothing); + expect(find.text('Custom Button'), findsOneWidget); + expect(bottomPicker.buttonBuilder, isNotNull); + }, + ); }); } diff --git a/test/simple_bottom_picker_test.dart b/test/simple_bottom_picker_test.dart index 2122060..790b741 100644 --- a/test/simple_bottom_picker_test.dart +++ b/test/simple_bottom_picker_test.dart @@ -6,26 +6,18 @@ import 'package:flutter_test/flutter_test.dart'; void main() { group('Simple picker item testing...', () { - late List items = List.generate( - 10, - (index) => index, - ); + late List items = List.generate(10, (index) => index); - testWidgets('Simple use case: picker should function properly', - (tester) async { + testWidgets('Simple use case: picker should function properly', ( + tester, + ) async { var bottomPicker = BottomPicker( headerBuilder: (context) { return Text('Item picker'); }, items: items, ); - await tester.pumpWidget( - MaterialApp( - home: Scaffold( - body: bottomPicker, - ), - ), - ); + await tester.pumpWidget(MaterialApp(home: Scaffold(body: bottomPicker))); // Verify that the picker title is displayed expect(find.text('Item picker'), findsOneWidget); @@ -46,91 +38,95 @@ void main() { expect(bottomPicker.bottomPickerType, BottomPickerType.simple); }); - testWidgets('On change callback should be called when an item is selected', - (tester) async { - // Arrange - int itemIndex = -1; - await tester.pumpWidget( - MaterialApp( - home: Scaffold( - body: BottomPicker( - headerBuilder: (context) { - return Text('Item picker'); - }, - items: items, - itemBuilder: (item, index) { - return Text('Item $item'); - }, - onChange: (item) { - itemIndex = item; - }, + testWidgets( + 'On change callback should be called when an item is selected', + (tester) async { + // Arrange + int itemIndex = -1; + await tester.pumpWidget( + MaterialApp( + home: Scaffold( + body: BottomPicker( + headerBuilder: (context) { + return Text('Item picker'); + }, + items: items, + itemBuilder: (item, index) { + return Text('Item $item'); + }, + onChange: (item) { + itemIndex = item; + }, + ), ), ), - ), - ); + ); - // Act - expect(itemIndex, -1); + // Act + expect(itemIndex, -1); - await tester.drag( - find.text('Item 1'), - const Offset(0.0, -20.0), - ); // see top of file - await tester.pump(); - expect(itemIndex, 1); + await tester.drag( + find.text('Item 1'), + const Offset(0.0, -20.0), + ); // see top of file + await tester.pump(); + expect(itemIndex, 1); - await tester.drag( - find.text('Item 2'), - const Offset(0.0, -40.0), - ); // see top of file - await tester.pump(); - expect(itemIndex, 2); + await tester.drag( + find.text('Item 2'), + const Offset(0.0, -40.0), + ); // see top of file + await tester.pump(); + expect(itemIndex, 2); - await tester.drag( - find.text('Item 3'), - const Offset(0.0, -60.0), - ); // see top of file - await tester.pump(); - expect(itemIndex, 3); - }); + await tester.drag( + find.text('Item 3'), + const Offset(0.0, -60.0), + ); // see top of file + await tester.pump(); + expect(itemIndex, 3); + }, + ); testWidgets( - 'On submit callback invoked when pressing submit button: index should be changed', - (tester) async { - var index = -1; - await tester.pumpWidget( - MaterialApp( - home: Scaffold( - body: BottomPicker( - headerBuilder: (context) { - return Text('Item picker'); - }, - items: items, - onSubmit: (p0) { - if (p0 != null) { - index = p0; - } - }, + 'On submit callback invoked when pressing submit button: index should be changed', + (tester) async { + var index = -1; + await tester.pumpWidget( + MaterialApp( + home: Scaffold( + body: BottomPicker( + headerBuilder: (context) { + return Text('Item picker'); + }, + items: items, + onSubmit: (p0) { + if (p0 != null) { + index = p0; + } + }, + ), ), ), - ), - ); + ); - await tester.drag( - find.text('2'), - const Offset(0.0, -60.0), - ); // see top of file - await tester.pump(); - await tester.tap(find.byType(BottomPickerButton)); - await tester.pumpAndSettle(); - expect(index, 2); + await tester.drag( + find.text('2'), + const Offset(0.0, -60.0), + ); // see top of file + await tester.pump(); + await tester.tap(find.byType(BottomPickerButton)); + await tester.pumpAndSettle(); + expect(index, 2); - // Test that the picker is closed after submit - expect(find.byType(BottomPicker), findsNothing); - }); + // Test that the picker is closed after submit + expect(find.byType(BottomPicker), findsNothing); + }, + ); - testWidgets('On dismiss callback invoked when pressing submit button', - (tester) async { + testWidgets('On dismiss callback invoked when pressing submit button', ( + tester, + ) async { var index = -1; await tester.pumpWidget( MaterialApp( @@ -162,54 +158,52 @@ void main() { }); testWidgets( - 'onCloseButtonPressed callback invoked when pressing the close icon', - (tester) async { - var index = -1; - await tester.pumpWidget( - MaterialApp( - home: Scaffold( - body: BottomPicker( - headerBuilder: (context) { - return Row( - children: [ - Text('Item picker'), - InkWell( - onTap: () { - Navigator.pop(context); - index = 9; - }, - child: Icon(Icons.close), - ), - ], - ); - }, - items: items, + 'onCloseButtonPressed callback invoked when pressing the close icon', + (tester) async { + var index = -1; + await tester.pumpWidget( + MaterialApp( + home: Scaffold( + body: BottomPicker( + headerBuilder: (context) { + return Row( + children: [ + Text('Item picker'), + InkWell( + onTap: () { + Navigator.pop(context); + index = 9; + }, + child: Icon(Icons.close), + ), + ], + ); + }, + items: items, + ), ), ), - ), - ); + ); - await tester.drag( - find.text('2'), - const Offset(0.0, -60.0), - ); // see top of file - await tester.pump(); - await tester.tap(find.byIcon(Icons.close)); - await tester.pumpAndSettle(); - expect(index, 9); + await tester.drag( + find.text('2'), + const Offset(0.0, -60.0), + ); // see top of file + await tester.pump(); + await tester.tap(find.byIcon(Icons.close)); + await tester.pumpAndSettle(); + expect(index, 9); - // Test that the picker is closed after submit - expect(find.byType(BottomPicker), findsNothing); - }); + // Test that the picker is closed after submit + expect(find.byType(BottomPicker), findsNothing); + }, + ); testWidgets('Testing picker widgets display flags', (tester) async { await tester.pumpWidget( MaterialApp( home: Scaffold( - body: BottomPicker( - displaySubmitButton: false, - items: items, - ), + body: BottomPicker(displaySubmitButton: false, items: items), ), ), ); @@ -222,11 +216,7 @@ void main() { test('Testing bottom picker assertions', () async { expect( () => MaterialApp( - home: Scaffold( - body: BottomPicker( - items: items, - ), - ), + home: Scaffold(body: BottomPicker(items: items)), ), returnsNormally, ); @@ -234,15 +224,10 @@ void main() { expect( () => MaterialApp( home: Scaffold( - body: BottomPicker( - displaySubmitButton: false, - items: [], - ), + body: BottomPicker(displaySubmitButton: false, items: []), ), ), - throwsA( - isA(), - ), + throwsA(isA()), ); expect( @@ -255,9 +240,7 @@ void main() { ), ), ), - throwsA( - isA(), - ), + throwsA(isA()), ); expect( @@ -270,9 +253,7 @@ void main() { ), ), ), - throwsA( - isA(), - ), + throwsA(isA()), ); }); });