snap_bottom_sheet 0.1.0 copy "snap_bottom_sheet: ^0.1.0" to clipboard
snap_bottom_sheet: ^0.1.0 copied to clipboard

A customizable bottom sheet with snap positions for Flutter, inspired by iOS-style sheet detents.

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:snap_bottom_sheet/snap_bottom_sheet.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'SnapBottomSheet 예제',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: const SnapSheetDemo(),
    );
  }
}

class SnapSheetDemo extends StatefulWidget {
  const SnapSheetDemo({super.key});

  @override
  State<SnapSheetDemo> createState() => _SnapSheetDemoState();
}

class _SnapSheetDemoState extends State<SnapSheetDemo> {
  // 시트 컨트롤러 생성
  final _controller = SnapSheetController();
  SnapPosition _currentPosition = SnapPosition.medium;

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return SnapBottomSheetScaffold(
      // 앱바 설정
      appBar: AppBar(
        title: const Text('SnapBottomSheet 예제'),
        actions: [
          IconButton(
            icon: const Icon(Icons.arrow_upward),
            onPressed: () {
              // 단계적으로 시트 높이 증가
              if (_currentPosition == SnapPosition.minimum) {
                _controller.snapToMedium();
              } else if (_currentPosition == SnapPosition.medium) {
                _controller.snapToMaximum();
              }
            },
          ),
          IconButton(
            icon: const Icon(Icons.arrow_downward),
            onPressed: () {
              // 단계적으로 시트 높이 감소
              if (_currentPosition == SnapPosition.maximum) {
                _controller.snapToMedium();
              } else if (_currentPosition == SnapPosition.medium) {
                _controller.snapToMinimum();
              }
            },
          ),
        ],
      ),

      // 메인 화면 콘텐츠
      body: Container(
        decoration: const BoxDecoration(
          gradient: LinearGradient(
            begin: Alignment.topCenter,
            end: Alignment.bottomCenter,
            colors: [Colors.blue, Colors.lightBlueAccent],
          ),
        ),
        child: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              const Text(
                'SnapBottomSheet 라이브러리 데모',
                style: TextStyle(
                  color: Colors.white,
                  fontSize: 24,
                  fontWeight: FontWeight.bold,
                ),
              ),
              const SizedBox(height: 20),
              Text(
                '현재 시트 위치: $_currentPosition',
                style: const TextStyle(color: Colors.white, fontSize: 16),
              ),
              const SizedBox(height: 20),
              ElevatedButton(
                style: ElevatedButton.styleFrom(
                  backgroundColor: Colors.white,
                  foregroundColor: Colors.blue,
                ),
                onPressed: () {
                  _controller.snapToMaximum();
                },
                child: const Text('시트 최대화'),
              ),
            ],
          ),
        ),
      ),

      // 시트 설정
      controller: _controller,
      minHeightRatio: 0.1,
      mediumHeightRatio: 0.5,
      maxHeightRatio: 0.9,
      sheetBackgroundColor: Colors.white,
      borderRadius: 24.0,
      showDragHandle: true,
      animationCurve: const SpringCurve(
        mass: 1.0,
        stiffness: 200.0,
        damping: 25.0,
      ),

      // 시트 위치 변경 콜백
      onPositionChanged: (position) {
        setState(() {
          _currentPosition = position;
        });
      },

      // 시트 내부 콘텐츠
      sheetContent: ListView(
        padding: const EdgeInsets.all(16.0),
        children: [
          const Text(
            'SnapBottomSheet',
            style: TextStyle(fontSize: 22, fontWeight: FontWeight.bold),
          ),
          const SizedBox(height: 16),
          const Text('이 시트는 세 가지 위치로 스냅됩니다:', style: TextStyle(fontSize: 16)),
          const SizedBox(height: 8),
          ListTile(
            leading: const Icon(Icons.arrow_downward),
            title: const Text('최소 높이 (화면의 10%)'),
            tileColor:
                _currentPosition == SnapPosition.minimum
                    ? Colors.blue.withValues(alpha: 0.1)
                    : null,
          ),
          ListTile(
            leading: const Icon(Icons.drag_handle),
            title: const Text('중간 높이 (화면의 50%)'),
            tileColor:
                _currentPosition == SnapPosition.medium
                    ? Colors.blue.withValues(alpha: 0.1)
                    : null,
          ),
          ListTile(
            leading: const Icon(Icons.arrow_upward),
            title: const Text('최대 높이 (화면의 90%)'),
            tileColor:
                _currentPosition == SnapPosition.maximum
                    ? Colors.blue.withValues(alpha: 0.1)
                    : null,
          ),
          const SizedBox(height: 16),
          const Text(
            '사용 방법:',
            style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
          ),
          const SizedBox(height: 8),
          const Text('• 시트를 위아래로 드래그하여 위치 변경'),
          const Text('• 빠르게 쓸어올리거나 내려서 다음 위치로 이동'),
          const Text('• 앱바의 화살표 버튼으로 위치 제어'),

          // 스크롤 테스트를 위한 추가 콘텐츠
          const SizedBox(height: 40),
          ...List.generate(
            15,
            (index) => ListTile(
              title: Text('항목 ${index + 1}'),
              subtitle: Text('스크롤 테스트 항목'),
              onTap: () {
                ScaffoldMessenger.of(context).showSnackBar(
                  SnackBar(
                    content: Text('항목 ${index + 1} 선택됨'),
                    duration: const Duration(seconds: 1),
                  ),
                );
              },
            ),
          ),
        ],
      ),
    );
  }
}
1
likes
160
points
12
downloads

Publisher

unverified uploader

Weekly Downloads

A customizable bottom sheet with snap positions for Flutter, inspired by iOS-style sheet detents.

Homepage

Documentation

API reference

License

MIT (license)

Dependencies

flutter

More

Packages that depend on snap_bottom_sheet