| // Copyright 2014 The Flutter Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| import 'package:flutter/foundation.dart'; |
| import 'package:flutter/material.dart'; |
| |
| /// Flutter code sample for [DraggableScrollableSheet]. |
| |
| void main() => runApp(const DraggableScrollableSheetExampleApp()); |
| |
| class DraggableScrollableSheetExampleApp extends StatelessWidget { |
| const DraggableScrollableSheetExampleApp({super.key}); |
| |
| @override |
| Widget build(BuildContext context) { |
| return MaterialApp( |
| theme: ThemeData( |
| colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue.shade100), |
| ), |
| home: Scaffold( |
| appBar: AppBar( |
| title: const Text('DraggableScrollableSheet Sample'), |
| ), |
| body: const DraggableScrollableSheetExample(), |
| ), |
| ); |
| } |
| } |
| |
| class DraggableScrollableSheetExample extends StatefulWidget { |
| const DraggableScrollableSheetExample({super.key}); |
| |
| @override |
| State<DraggableScrollableSheetExample> createState() => _DraggableScrollableSheetExampleState(); |
| } |
| |
| class _DraggableScrollableSheetExampleState extends State<DraggableScrollableSheetExample> { |
| double _sheetPosition = 0.5; |
| final double _dragSensitivity = 600; |
| |
| @override |
| Widget build(BuildContext context) { |
| final ColorScheme colorScheme = Theme.of(context).colorScheme; |
| |
| return DraggableScrollableSheet( |
| initialChildSize: _sheetPosition, |
| builder: (BuildContext context, ScrollController scrollController) { |
| return ColoredBox( |
| color: colorScheme.primary, |
| child: Column( |
| children: <Widget>[ |
| Grabber( |
| onVerticalDragUpdate: (DragUpdateDetails details) { |
| setState(() { |
| _sheetPosition -= details.delta.dy / _dragSensitivity; |
| if (_sheetPosition < 0.25) { |
| _sheetPosition = 0.25; |
| } |
| if (_sheetPosition > 1.0) { |
| _sheetPosition = 1.0; |
| } |
| }); |
| }, |
| isOnDesktopAndWeb: _isOnDesktopAndWeb, |
| ), |
| Flexible( |
| child: ListView.builder( |
| controller: _isOnDesktopAndWeb ? null : scrollController, |
| itemCount: 25, |
| itemBuilder: (BuildContext context, int index) { |
| return ListTile( |
| title: Text( |
| 'Item $index', |
| style: TextStyle(color: colorScheme.surface), |
| ), |
| ); |
| }, |
| ), |
| ), |
| ], |
| ), |
| ); |
| }, |
| ); |
| } |
| |
| bool get _isOnDesktopAndWeb { |
| if (kIsWeb) { |
| return true; |
| } |
| switch (defaultTargetPlatform) { |
| case TargetPlatform.macOS: |
| case TargetPlatform.linux: |
| case TargetPlatform.windows: |
| return true; |
| case TargetPlatform.android: |
| case TargetPlatform.iOS: |
| case TargetPlatform.fuchsia: |
| return false; |
| } |
| } |
| } |
| |
| /// A draggable widget that accepts vertical drag gestures |
| /// and this is only visible on desktop and web platforms. |
| class Grabber extends StatelessWidget { |
| const Grabber({ |
| super.key, |
| required this.onVerticalDragUpdate, |
| required this.isOnDesktopAndWeb, |
| }); |
| |
| final ValueChanged<DragUpdateDetails> onVerticalDragUpdate; |
| final bool isOnDesktopAndWeb; |
| |
| @override |
| Widget build(BuildContext context) { |
| if (!isOnDesktopAndWeb) { |
| return const SizedBox.shrink(); |
| } |
| final ColorScheme colorScheme = Theme.of(context).colorScheme; |
| |
| return GestureDetector( |
| onVerticalDragUpdate: onVerticalDragUpdate, |
| child: Container( |
| width: double.infinity, |
| color: colorScheme.onSurface, |
| child: Align( |
| alignment: Alignment.topCenter, |
| child: Container( |
| margin: const EdgeInsets.symmetric(vertical: 8.0), |
| width: 32.0, |
| height: 4.0, |
| decoration: BoxDecoration( |
| color: colorScheme.surfaceContainerHighest, |
| borderRadius: BorderRadius.circular(8.0), |
| ), |
| ), |
| ), |
| ), |
| ); |
| } |
| } |