Reputation: 21
What UI Have?
What should it do?
Issue
DraggableScrollableSheet Code
DraggableScrollableSheet(
controller: _sheetController,
initialChildSize: 0.3,
minChildSize: 0.3,
maxChildSize: 0.9,
builder: (context, scrollController) {
return Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius:
BorderRadius.vertical(top: Radius.circular(16)),
),
child: Column(
children: [
// Sticky Header with Drag Handle
Container(
padding: EdgeInsets.all(16),
child: Column(
children: [
Container(
width: 40,
height: 4,
decoration: BoxDecoration(
color: Colors.grey,
borderRadius: BorderRadius.circular(2),
),
),
SizedBox(height: 8),
Text(
"Nearby Charging Stations",
style: TextStyle(
fontSize: 18, fontWeight: FontWeight.bold),
),
],
),
),
// Scrollable List (Expanded to take available space)
Expanded(
child: ListView.builder(
controller:
scrollController, // Inherited scroll behavior
physics: BouncingScrollPhysics(),
itemCount: 20,
itemBuilder: (context, index) {
return ListTile(
leading: Icon(Icons.ev_station),
title: Text("Location name"),
subtitle: Text("Address details"),
);
},
),
),
],
),
);
},
)
Full Screen Code
import 'package:flutter/material.dart';
class DraggableSheetExample extends StatefulWidget {
@override
_DraggableSheetExampleState createState() => _DraggableSheetExampleState();
}
class _DraggableSheetExampleState extends State<DraggableSheetExample> {
final DraggableScrollableController _sheetController =
DraggableScrollableController();
final ScrollController _scrollController = ScrollController();
@override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: [
// Main Content
Positioned.fill(
child: Container(
color: Colors.blueGrey[100],
child: Center(child: Text("Main Content")),
),
),
// Draggable Sheet
Align(
alignment: Alignment.bottomCenter,
child: DraggableScrollableSheet(
controller: _sheetController,
initialChildSize: 0.3,
minChildSize: 0.3,
maxChildSize: 0.9,
builder: (context, scrollController) {
return Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius:
BorderRadius.vertical(top: Radius.circular(16)),
),
child: Column(
children: [
// Sticky Header with Drag Handle
Container(
padding: EdgeInsets.all(16),
child: Column(
children: [
Container(
width: 40,
height: 4,
decoration: BoxDecoration(
color: Colors.grey,
borderRadius: BorderRadius.circular(2),
),
),
SizedBox(height: 8),
Text(
"Nearby Charging Stations",
style: TextStyle(
fontSize: 18, fontWeight: FontWeight.bold),
),
],
),
),
// Scrollable List (Expanded to take available space)
Expanded(
child: ListView.builder(
controller:
scrollController, // Inherited scroll behavior
physics: BouncingScrollPhysics(),
itemCount: 20,
itemBuilder: (context, index) {
return ListTile(
leading: Icon(Icons.ev_station),
title: Text("Location name"),
subtitle: Text("Address details"),
);
},
),
),
],
),
);
},
),
)
],
),
);
}
}
Upvotes: 2
Views: 43
Reputation: 148
Scroll over top of the UI to achieve this, you can use a GestureDetector wrapped around the header section to detect drag gestures and programmatically control the sheet's size using the DraggableScrollableController. Meanwhile, the ListView.builder() will handle its own scrolling independently.
// Draggable Header Section
GestureDetector(
onVerticalDragUpdate: (details) {
// Adjust the sheet size based on drag gestures
double newSize = _sheetController.size - (details.primaryDelta! / MediaQuery.of(context).size.height);
_sheetController.jumpTo(newSize.clamp(0.3, 1.0));
},
child: Container(
width: MediaQuery.of(context).size.width,
padding: const EdgeInsets.all(16),
child: Column(
children: [
Container(
width: 40,
height: 4,
decoration: BoxDecoration(
color: Colors.grey,
borderRadius: BorderRadius.circular(2),
),
),
const SizedBox(height: 8),
const Text(
"Nearby Charging Stations",
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
],
),
),
),
Full Code :
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const DraggableSheetExample(),
);
}
}
class DraggableSheetExample extends StatefulWidget {
const DraggableSheetExample({super.key});
@override
_DraggableSheetExampleState createState() => _DraggableSheetExampleState();
}
class _DraggableSheetExampleState extends State<DraggableSheetExample> {
final DraggableScrollableController _sheetController = DraggableScrollableController();
@override
void dispose() {
_sheetController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: [
// Main Content
Positioned.fill(
child: Container(
color: Colors.blueGrey[100],
child: const Center(child: Text("Main Content")),
),
),
// Draggable Sheet
Align(
alignment: Alignment.bottomCenter,
child: DraggableScrollableSheet(
controller: _sheetController,
initialChildSize: 0.3,
minChildSize: 0.3,
maxChildSize: 1,
builder: (context, scrollController) {
return Container(
decoration: const BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.vertical(top: Radius.circular(16)),
),
child: Column(
children: [
// Draggable Header Section
GestureDetector(
onVerticalDragUpdate: (details) {
// Adjust the sheet size based on drag gestures
double newSize = _sheetController.size - (details.primaryDelta! / MediaQuery.of(context).size.height);
_sheetController.jumpTo(newSize.clamp(0.3, 1.0));
},
child: Container(
width: MediaQuery.of(context).size.width,
padding: const EdgeInsets.all(16),
child: Column(
children: [
Container(
width: 40,
height: 4,
decoration: BoxDecoration(
color: Colors.grey,
borderRadius: BorderRadius.circular(2),
),
),
const SizedBox(height: 8),
const Text(
"Nearby Charging Stations",
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
],
),
),
),
// Scrollable List (Expanded to take available space)
Expanded(
child: ListView.builder(
controller: scrollController, // Inherited scroll behavior
physics: const ClampingScrollPhysics(),
itemCount: 20,
itemBuilder: (context, index) {
return const ListTile(
leading: Icon(Icons.ev_station),
title: Text("Location name"),
subtitle: Text("Address details"),
);
},
),
),
],
),
);
},
),
)
],
),
);
}
}
Upvotes: 2