flutter_sliding_comment_sheet 1.0.0
flutter_sliding_comment_sheet: ^1.0.0 copied to clipboard
A comment sheet that slides up and shrinks the content above it, like TikTok, Instagram Reels and YouTube Shorts.
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_sliding_comment_sheet/flutter_sliding_comment_sheet.dart';
import 'comments_view.dart';
import 'models.dart';
import 'video_page.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle.light);
runApp(const ExampleApp());
}
class ExampleApp extends StatelessWidget {
const ExampleApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'sliding_comment_sheet',
debugShowCheckedModeBanner: false,
theme: ThemeData(
useMaterial3: true,
brightness: Brightness.dark,
scaffoldBackgroundColor: Colors.black,
),
home: const FeedScreen(),
);
}
}
/// A short-video feed with a comment sheet, the way TikTok, Instagram Reels and
/// YouTube Shorts all arrange it.
///
/// One [SlidingCommentSheet] wraps the whole feed rather than one per video:
/// the sheet belongs to the screen, and its contents follow whichever reel is
/// on show. That is also how the real apps behave — the sheet stays put while
/// the video behind it changes.
class FeedScreen extends StatefulWidget {
const FeedScreen({super.key});
@override
State<FeedScreen> createState() => _FeedScreenState();
}
class _FeedScreenState extends State<FeedScreen> {
final _sheet = SlidingCommentSheetController();
final _pages = PageController();
final _input = TextEditingController();
int _current = 0;
Reel get _reel => feed[_current];
@override
void dispose() {
_sheet.dispose();
_pages.dispose();
_input.dispose();
super.dispose();
}
void _send() {
final text = _input.text.trim();
if (text.isEmpty) return;
setState(() {
_reel.comments.insert(
0,
Comment(author: 'you', body: text, age: 'now', isMine: true),
);
});
_input.clear();
FocusManager.instance.primaryFocus?.unfocus();
}
@override
Widget build(BuildContext context) {
return Scaffold(
// The sheet lifts itself above the keyboard, so the scaffold must not
// shrink the page for it as well.
resizeToAvoidBottomInset: false,
body: SlidingCommentSheet(
controller: _sheet,
semanticLabel: 'Comments',
maxSheetHeight: MediaQuery.sizeOf(context).height * 0.58,
backgroundColor: backgroundColor,
onCollapse: () => FocusManager.instance.primaryFocus?.unfocus(),
// Shrinks as the sheet opens, instead of being covered by it.
content: PageView.builder(
controller: _pages,
scrollDirection: Axis.vertical,
itemCount: feed.length,
onPageChanged: (i) => setState(() => _current = i),
itemBuilder: (context, i) => VideoPage(
reel: feed[i],
isCurrent: i == _current,
onComments: _sheet.expand,
sheet: _sheet,
),
),
// Handing the controller to the comment list is what lets pulling the
// list down close the sheet, and pushing it up open the sheet before
// the list starts scrolling.
sheetBuilder: (context, scrollController) => CommentsView(
reel: _reel,
scrollController: scrollController,
input: _input,
onSend: _send,
onClose: _sheet.collapse,
),
),
);
}
}