diff --git a/.fvm/flutter_sdk b/.fvm/flutter_sdk deleted file mode 120000 index 6f06b69..0000000 --- a/.fvm/flutter_sdk +++ /dev/null @@ -1 +0,0 @@ -/Users/julianbissekkou/fvm/versions/3.16.9 \ No newline at end of file diff --git a/.fvm/fvm_config.json b/.fvm/fvm_config.json deleted file mode 100644 index 02e7826..0000000 --- a/.fvm/fvm_config.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "flutterSdkVersion": "3.16.9", - "flavors": {} -} \ No newline at end of file diff --git a/.fvmrc b/.fvmrc new file mode 100644 index 0000000..ee6eaac --- /dev/null +++ b/.fvmrc @@ -0,0 +1,3 @@ +{ + "flutter": "3.24.3" +} diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index c5a2ae5..90b17c4 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -17,12 +17,11 @@ concurrency: jobs: analyze: timeout-minutes: 5 - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 - uses: kuhnroyal/flutter-fvm-config-action@v2 - with: - path: '.fvm/fvm_config.json' + id: fvm-config-action - uses: subosito/flutter-action@v2 with: flutter-version: ${{ env.FLUTTER_VERSION }} @@ -35,20 +34,17 @@ jobs: cd .. flutter analyze - #format format: timeout-minutes: 5 - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 - uses: kuhnroyal/flutter-fvm-config-action@v2 - with: - path: '.fvm/fvm_config.json' + id: fvm-config-action - uses: subosito/flutter-action@v2 with: flutter-version: ${{ env.FLUTTER_VERSION }} channel: ${{ env.FLUTTER_CHANNEL }} - name: Check formatting run: find . -name "*.dart" ! -name "*.g.dart" ! -name "*.freezed.dart" ! -path '*/generated/*' ! -path '*/gen/*' | xargs dart format --set-exit-if-changed - - #tests + diff --git a/example/lib/home_page.dart b/example/lib/home_page.dart new file mode 100644 index 0000000..cf43fce --- /dev/null +++ b/example/lib/home_page.dart @@ -0,0 +1,88 @@ +import 'dart:async'; + +import 'package:flutter/material.dart'; +import 'package:tapped_bottom_sheet/scrollable_bottom_sheet.dart'; + +class HomePage extends StatefulWidget { + const HomePage({super.key}); + + @override + State createState() => _HomePageState(); +} + +class _HomePageState extends State { + ScrollController? _scrollController; + final _scrollableBSKey = GlobalKey(); + + @override + Widget build(BuildContext context) { + final maxHeight = MediaQuery.of(context).size.height; + + return Scaffold( + appBar: AppBar( + title: const Text('Bottom Sheet Example'), + ), + body: Stack( + children: [ + Positioned.fill( + child: Container( + color: Theme.of(context).colorScheme.primary, + ), + ), + Align( + alignment: Alignment.bottomCenter, + child: ScrollableBottomSheet( + key: _scrollableBSKey, + snapPositions: [maxHeight / 2], + initialPosition: maxHeight / 2, + maxHeight: maxHeight, + minHeight: 100, + builder: (context, scrollController) { + _scrollController = scrollController; + + return ListView.builder( + controller: scrollController, + itemCount: 100, + itemBuilder: (context, index) { + return ListTile( + title: ElevatedButton( + onPressed: index == 0 ? _open : () {}, + child: Text('Element $index'), + ), + ); + }, + ); + }, + borderRadiusTop: 15, + borderColor: Colors.black, + backgroundColor: Colors.white, + ), + ), + ], + ), + floatingActionButton: FloatingActionButton( + onPressed: _scrollToLastElementOfList, + child: const Icon(Icons.arrow_downward_rounded), + ), + ); + } + + Future _open() async { + await _scrollableBSKey.currentState!.open(); + } + + Future _scrollToLastElementOfList() async { + if (_scrollController == null || _scrollableBSKey.currentState == null) { + return; + } + + unawaited(_scrollableBSKey.currentState!.open()); + + final maxScrollExtent = _scrollController!.position.maxScrollExtent; + await _scrollController?.animateTo( + maxScrollExtent, + duration: const Duration(seconds: 1), + curve: Curves.bounceIn, + ); + } +} diff --git a/example/lib/main.dart b/example/lib/main.dart index c92e610..5d5c852 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -1,5 +1,5 @@ +import 'package:example/home_page.dart'; import 'package:flutter/material.dart'; -import 'package:tapped_bottom_sheet/scrollable_bottom_sheet.dart'; void main() { runApp(const MainApp()); @@ -10,44 +10,28 @@ class MainApp extends StatelessWidget { @override Widget build(BuildContext context) { - final maxHeight = MediaQuery.of(context).size.height - kToolbarHeight - 100; - return MaterialApp( - home: Scaffold( - appBar: AppBar( - title: const Text('Bottom Sheet Example'), - ), - body: Stack( - children: [ - Positioned.fill( - child: Container( - color: Colors.green, - ), - ), - Align( - alignment: Alignment.bottomCenter, - child: ScrollableBottomSheet( - snapPositions: [maxHeight / 2], - initialPosition: maxHeight / 2, - maxHeight: maxHeight, - minHeight: 100, - builder: (context, scrollController) { - return ListView.builder( - controller: scrollController, - itemCount: 100, - itemBuilder: (context, index) { - return ListTile( - title: Text('Element $index'), - ); - }, - ); - }, - borderRadiusTop: 15, - borderColor: Colors.black, - backgroundColor: Colors.white, - ), - ), - ], - ), + return const MaterialApp( + home: HomePage(), + ); + } +} + +class TestHomePage extends StatelessWidget { + const TestHomePage({super.key}); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text("Test"), + ), + body: ListView.builder( + itemBuilder: (context, index) { + return ElevatedButton( + onPressed: () {}, + child: Text(index.toString()), + ); + }, ), ); } diff --git a/example/pubspec.lock b/example/pubspec.lock index 4e68eab..a3d1a13 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -75,6 +75,30 @@ packages: description: flutter source: sdk version: "0.0.0" + leak_tracker: + dependency: transitive + description: + name: leak_tracker + sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05" + url: "https://pub.dev" + source: hosted + version: "10.0.5" + leak_tracker_flutter_testing: + dependency: transitive + description: + name: leak_tracker_flutter_testing + sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806" + url: "https://pub.dev" + source: hosted + version: "3.0.5" + leak_tracker_testing: + dependency: transitive + description: + name: leak_tracker_testing + sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" + url: "https://pub.dev" + source: hosted + version: "3.0.1" lints: dependency: transitive description: @@ -87,26 +111,26 @@ packages: dependency: transitive description: name: matcher - sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e" + sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb url: "https://pub.dev" source: hosted - version: "0.12.16" + version: "0.12.16+1" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41" + sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec url: "https://pub.dev" source: hosted - version: "0.5.0" + version: "0.11.1" meta: dependency: transitive description: name: meta - sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e + sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7 url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.15.0" non_uniform_border: dependency: transitive description: @@ -119,10 +143,10 @@ packages: dependency: transitive description: name: path - sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" + sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" url: "https://pub.dev" source: hosted - version: "1.8.3" + version: "1.9.0" sky_engine: dependency: transitive description: flutter @@ -188,10 +212,10 @@ packages: dependency: transitive description: name: test_api - sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" + sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb" url: "https://pub.dev" source: hosted - version: "0.6.1" + version: "0.7.2" vector_math: dependency: transitive description: @@ -200,14 +224,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.4" - web: + vm_service: dependency: transitive description: - name: web - sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152 + name: vm_service + sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d" url: "https://pub.dev" source: hosted - version: "0.3.0" + version: "14.2.5" sdks: - dart: ">=3.2.0-194.0.dev <4.0.0" - flutter: ">=1.17.0" + dart: ">=3.3.0 <4.0.0" + flutter: ">=3.18.0-18.0.pre.54" diff --git a/lib/scrollable_bottom_sheet.dart b/lib/scrollable_bottom_sheet.dart index 27791be..d0b4dfb 100644 --- a/lib/scrollable_bottom_sheet.dart +++ b/lib/scrollable_bottom_sheet.dart @@ -232,7 +232,9 @@ class ScrollableBottomSheetState extends State // by default without any calls from our implementation. if (!widget.canDrag) return; - if (!_isScrollingEnabled || _isScrollingBlocked) { + final isScrollingAllowed = _isPanelOpen ? true : _isScrollingEnabled; + + if (!isScrollingAllowed || _isScrollingBlocked) { _scrollController.jumpTo(0); } } @@ -317,7 +319,10 @@ class ScrollableBottomSheetState extends State return _animationController.fling(velocity: -1.0); } - Future open() { + Future open() async { + if (_isPanelOpen) return; + + setState(() => _isScrollingEnabled = true); return _animationController.fling(velocity: 1.0); } diff --git a/pubspec.lock b/pubspec.lock index b1aef11..9ac42a4 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -75,6 +75,30 @@ packages: description: flutter source: sdk version: "0.0.0" + leak_tracker: + dependency: transitive + description: + name: leak_tracker + sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05" + url: "https://pub.dev" + source: hosted + version: "10.0.5" + leak_tracker_flutter_testing: + dependency: transitive + description: + name: leak_tracker_flutter_testing + sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806" + url: "https://pub.dev" + source: hosted + version: "3.0.5" + leak_tracker_testing: + dependency: transitive + description: + name: leak_tracker_testing + sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" + url: "https://pub.dev" + source: hosted + version: "3.0.1" lints: dependency: transitive description: @@ -87,26 +111,26 @@ packages: dependency: transitive description: name: matcher - sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e" + sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb url: "https://pub.dev" source: hosted - version: "0.12.16" + version: "0.12.16+1" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41" + sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec url: "https://pub.dev" source: hosted - version: "0.5.0" + version: "0.11.1" meta: dependency: transitive description: name: meta - sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e + sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7 url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.15.0" non_uniform_border: dependency: "direct main" description: @@ -119,10 +143,10 @@ packages: dependency: transitive description: name: path - sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" + sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" url: "https://pub.dev" source: hosted - version: "1.8.3" + version: "1.9.0" sky_engine: dependency: transitive description: flutter @@ -181,10 +205,10 @@ packages: dependency: transitive description: name: test_api - sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" + sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb" url: "https://pub.dev" source: hosted - version: "0.6.1" + version: "0.7.2" vector_math: dependency: transitive description: @@ -193,14 +217,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.4" - web: + vm_service: dependency: transitive description: - name: web - sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152 + name: vm_service + sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d" url: "https://pub.dev" source: hosted - version: "0.3.0" + version: "14.2.5" sdks: - dart: ">=3.2.0-194.0.dev <4.0.0" - flutter: ">=1.17.0" + dart: ">=3.3.0 <4.0.0" + flutter: ">=3.18.0-18.0.pre.54"