Skip to content

Commit

Permalink
Merge pull request #6 from tappeddev/fix-horizontal-scroll
Browse files Browse the repository at this point in the history
updated horizontal scrolling inside bs
  • Loading branch information
JulianBissekkou authored Jan 9, 2025
2 parents 8201dbe + 386d3ff commit 9eeb9ba
Show file tree
Hide file tree
Showing 2 changed files with 123 additions and 56 deletions.
82 changes: 59 additions & 23 deletions example/lib/main.dart
Original file line number Diff line number Diff line change
@@ -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());
Expand All @@ -10,28 +10,64 @@ class MainApp extends StatelessWidget {

@override
Widget build(BuildContext context) {
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()),
);
},
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 SingleChildScrollView(
controller: scrollController,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text("Horizontal Scroll"),
const SizedBox(height: 8),
SizedBox(
height: 100,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.only(right: 8.0),
child: Container(
color: Colors.red,
width: 100,
child: Text(index.toString()),
),
);
},
),
),
Container(
height: 200,
),
],
),
);
},
borderRadiusTop: 15,
borderColor: Colors.black,
backgroundColor: Colors.white,
),
),
],
),
),
);
}
Expand Down
97 changes: 64 additions & 33 deletions lib/scrollable_bottom_sheet.dart
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ class ScrollableBottomSheetState extends State<ScrollableBottomSheet>

bool get _isPanelOpen => _animationController.value == 1.0;

bool _isHorizontalScrolling = false;

double _pixelToValue(double pixels) {
return (pixels - widget.minHeight) / (widget.maxHeight - widget.minHeight);
}
Expand Down Expand Up @@ -130,41 +132,68 @@ class ScrollableBottomSheetState extends State<ScrollableBottomSheet>
final borderRadius =
BorderRadius.vertical(top: Radius.circular(widget.borderRadiusTop));

return GestureListener(
canDrag: widget.canDrag,
onVerticalDragUpdate: (details) => _onDragUpdate(details),
onVerticalDragEnd: (details) => _onDragEnd(details),
onVerticalDragCancel: () => _handleDragCancel(),
child: MediaQuery.removePadding(
context: context,
removeTop: true,
child: Container(
decoration: BoxDecoration(
boxShadow: widget.shadows,
borderRadius: borderRadius,
color: widget.backgroundColor,
),
// Use a foreground decoration to make sure we don't allocate more height.
foregroundDecoration: ShapeDecoration(
shape: NonUniformBorder(
topWidth: 2,
color: widget.borderColor,
return NotificationListener(
// Disable vertical scrolling when the user is scrolling in a nested
// horizontal scroll view. Otherwise we should slightly move the bottom
// sheet vertically up and down which feels buggy.
onNotification: (scrollNotification) {
if (scrollNotification is ScrollStartNotification &&
scrollNotification.metrics.axis == Axis.horizontal) {
_isHorizontalScrolling = true;
}

if (scrollNotification is ScrollUpdateNotification &&
scrollNotification.metrics.axis == Axis.horizontal) {
if (scrollNotification.dragDetails == null) {
_isHorizontalScrolling = false;
}
}

// Drag details are null if the user started a scroll and the
// scrollview is continue to scroll without the user touching the view.
if (scrollNotification is ScrollEndNotification &&
scrollNotification.metrics.axis == Axis.horizontal) {
_isHorizontalScrolling = false;
}

return false;
},
child: GestureListener(
canDrag: widget.canDrag,
onVerticalDragUpdate: (details) => _onDragUpdate(details),
onVerticalDragEnd: (details) => _onDragEnd(details),
onVerticalDragCancel: () => _handleDragCancel(),
child: MediaQuery.removePadding(
context: context,
removeTop: true,
child: Container(
decoration: BoxDecoration(
boxShadow: widget.shadows,
borderRadius: borderRadius,
color: widget.backgroundColor,
),
),
child: ClipRRect(
borderRadius: borderRadius,
child: AnimatedBuilder(
animation: _animationController,
builder: (context, child) {
return SizedBox(
height: _sizeTween.transform(_animationController.value),
child: child,
);
},
child: Builder(
builder: (context) =>
widget.builder(context, _scrollController),
// Use a foreground decoration to make sure we don't allocate more height.
foregroundDecoration: ShapeDecoration(
shape: NonUniformBorder(
topWidth: 2,
color: widget.borderColor,
borderRadius: borderRadius,
),
),
child: ClipRRect(
borderRadius: borderRadius,
child: AnimatedBuilder(
animation: _animationController,
builder: (context, child) {
return SizedBox(
height: _sizeTween.transform(_animationController.value),
child: child,
);
},
child: Builder(
builder: (context) =>
widget.builder(context, _scrollController),
),
),
),
),
Expand All @@ -180,6 +209,8 @@ class ScrollableBottomSheetState extends State<ScrollableBottomSheet>
final primaryDelta = delta.dy;
_didStartScrolling = true;

if (_isHorizontalScrolling) return;

if (_isScrollingEnabled && _isPanelOpen) {
// _drag might be null if the drag activity ended and called _disposeDrag.
assert(_hold == null || _drag == null);
Expand Down

0 comments on commit 9eeb9ba

Please sign in to comment.