Flutter评论展示插件comment_sheet的使用
Flutter评论展示插件comment_sheet的使用
comment_sheet
是一个Flutter插件,它提供了一个可以拖动到其他位置的底部弹出表单(Sheet)。这个插件非常适合用于展示评论、聊天记录或其他需要交互的列表内容。下面是一个完整的示例demo,展示了如何使用 comment_sheet
插件。
示例Demo
使用方法
要使用 comment_sheet
插件,首先需要在 pubspec.yaml
文件中添加依赖:
dependencies:
comment_sheet: ^最新版本号
然后在你的Dart文件中导入 comment_sheet
包:
import 'package:comment_sheet/comment_sheet.dart';
接下来,我们可以通过以下代码来创建一个包含评论功能的页面。
完整示例代码
import 'dart:math';
import 'package:comment_sheet/comment_sheet.dart';
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
[@override](/user/override)
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
// 创建一个CommentSheetController实例,用于控制Sheet的行为
final CommentSheetController commentSheetController = CommentSheetController();
ScrollController scrollController = ScrollController();
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Builder(builder: (context) {
return CustomScrollView(
physics: const BouncingScrollPhysics(parent: AlwaysScrollableScrollPhysics()),
slivers: [
// 添加下拉刷新控件
SliverFillRemaining(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ListTile(
title: const Text("Open Sheet"),
onTap: () {
// 显示底部Sheet
showBottomSheet(
context: context,
backgroundColor: Colors.transparent,
builder: (context) {
return CommentSheet(
slivers: [
buildSliverList(), // 构建评论列表
],
grabbingPosition: WidgetPosition.above, // 抓取区域的位置
initTopPosition: 200, // 初始化顶部位置
calculateTopPosition: calculateTopPosition, // 计算顶部位置的方法
scrollController: scrollController, // 滚动控制器
grabbing: Builder(builder: (context) {
return buildGrabbing(context); // 构建抓取区域
}),
topWidget: (info) {
return Positioned(
top: 0,
left: 0,
right: 0,
height: max(0, info.currentTop),
child: const Placeholder(color: Colors.green), // 顶部占位符
);
},
topPosition: WidgetPosition.below, // 顶部Widget的位置
bottomWidget: buildBottomWidget(), // 底部Widget
onPointerUp: (
BuildContext context,
CommentSheetInfo info,
) {
// 手指抬起时的回调
},
onAnimationComplete: (
BuildContext context,
CommentSheetInfo info,
) {
// 动画完成时的回调
if (info.currentTop >= info.size.maxHeight - 100) {
Navigator.of(context).pop(); // 如果Sheet滑动到顶部,则关闭
}
},
commentSheetController: commentSheetController, // 控制器
onTopChanged: (top) {
// 顶部位置变化时的回调
},
child: const Placeholder(), // Sheet内部的子Widget
backgroundBuilder: (context) {
return Container(
color: const Color(0xFF0F0F0F), // 背景颜色
margin: const EdgeInsets.only(top: 20), // 背景边距
);
},
);
},
);
},
),
ListTile(
title: const Text("Show Sheet in Stack"),
onTap: () {
// 导航到另一个页面,展示Sheet在Stack中
Navigator.push(
context,
MaterialPageRoute(
builder: (context) {
return const ScreenSheetDemo();
},
),
);
},
),
],
),
)
],
);
}),
),
);
}
// 构建底部Widget
Container buildBottomWidget() {
return Container(
color: Colors.transparent,
height: 50,
child: const Placeholder(color: Colors.blue),
);
}
// 计算顶部位置的逻辑
double calculateTopPosition(CommentSheetInfo info) {
final vy = info.velocity.getVelocity().pixelsPerSecond.dy;
final top = info.currentTop;
double p0 = 0;
double p1 = 200;
double p2 = info.size.maxHeight - 100;
if (top > p1) {
if (vy > 0) {
if (info.isAnimating && info.animatingTarget == p1 && top < p1 + 10) {
return p1;
} else {
return p2;
}
} else {
return p1;
}
} else if (top == p1) {
return p1;
} else if (top == p0) {
return p0;
} else {
if (vy > 0) {
if (info.isAnimating && info.animatingTarget == p0 && top < p0 + 10) {
return p0;
} else {
return p1;
}
} else {
return p0;
}
}
}
// 构建抓取区域
Widget buildGrabbing(BuildContext context) {
return const GrabbingWidget();
}
// 构建评论列表
Widget buildSliverList() {
return SliverList(
delegate: SliverChildBuilderDelegate((context, index) {
return const ListItemWidget();
}, childCount: 20),
);
}
}
// 抓取区域的Widget
class GrabbingWidget extends StatelessWidget {
const GrabbingWidget({Key? key}) : super(key: key);
[@override](/user/override)
Widget build(BuildContext context) {
return Container(
decoration: const BoxDecoration(
color: Color(0xFF0F0F0F),
borderRadius: BorderRadius.only(
topLeft: Radius.circular(12),
topRight: Radius.circular(12),
),
),
padding: const EdgeInsets.only(top: 10),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Container(
width: 40,
height: 4,
margin: const EdgeInsets.only(top: 4),
decoration: BoxDecoration(
color: Colors.white60,
borderRadius: BorderRadius.circular(100)),
),
Row(
children: [
const Padding(
padding: EdgeInsets.only(left: 15),
child: Text(
"Bình luận", // 评论标题
style: TextStyle(
fontWeight: FontWeight.w700,
color: Colors.white,
fontSize: 16,
),
),
),
const Padding(
padding: EdgeInsets.only(left: 6.0),
child: Text(
"48", // 评论数量
style: TextStyle(
fontWeight: FontWeight.w400,
color: Colors.white70,
fontSize: 13,
),
),
),
const Spacer(),
const Icon(
Icons.menu_sharp, // 菜单图标
size: 26,
color: Colors.white,
),
Padding(
padding: const EdgeInsets.only(left: 10.0, right: 10),
child: IconButton(
onPressed: () {
Navigator.of(context).pop(); // 关闭Sheet
},
icon: const Icon(
Icons.close, // 关闭按钮
size: 26,
color: Colors.white,
),
),
)
],
),
Container(
color: const Color(0xFF292929),
width: double.infinity,
height: 1,
),
],
),
);
}
}
// 评论项的Widget
class ListItemWidget extends StatelessWidget {
const ListItemWidget({Key? key}) : super(key: key);
[@override](/user/override)
Widget build(BuildContext context) {
return Material(
color: const Color(0xFF0F0F0F),
child: InkWell(
onTap: () {
Navigator.of(context).pop(); // 点击评论项时关闭Sheet
},
child: Container(
width: double.infinity,
padding: const EdgeInsets.only(top: 12, bottom: 0, left: 10, right: 10),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.only(left: 5, right: 10),
child: ClipOval(
child: Image.network(
"https://yt3.ggpht.com/yti/AJo0G0kUnHqoybmWPJG4GNm0G-lfCiCPbEP62v5tq9PZsA=s48-c-k-c0x00ffffff-no-rj",
width: 25,
height: 25,
),
),
),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'Andrea Quintanilla * 3 tháng trước', // 评论者信息
style: TextStyle(
fontSize: 10,
fontWeight: FontWeight.w400,
color: Color(0xFFAEAEAE)),
),
const Padding(
padding: EdgeInsets.only(top: 6, bottom: 12),
child: Text(
'Que buen trabajo, que buenos enganches, genial!!!! MTV la tenes adentro, jajaja. Saludos cordiales desde Buenos Aires, Argentina, Argentina, Argentina!', // 评论内容
style: TextStyle(
fontSize: 13,
fontWeight: FontWeight.w400,
color: Color(0xFFF6F6F6)),
),
),
Row(
children: const [
Icon(
Icons.thumb_up_outlined, // 点赞图标
size: 15,
color: Colors.white,
),
Padding(
padding: EdgeInsets.only(left: 16.0, right: 16.0),
child: Icon(
Icons.thumb_down_alt_outlined, // 点踩图标
size: 15,
color: Colors.white,
),
),
Icon(
Icons.comment_outlined, // 回复图标
size: 15,
color: Colors.white,
),
],
)
],
),
)
],
),
),
),
);
}
}
更多关于Flutter评论展示插件comment_sheet的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter评论展示插件comment_sheet的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是一个关于如何使用Flutter的comment_sheet
插件来展示评论的示例代码。comment_sheet
是一个假设的插件名称,因为Flutter社区中并没有一个广泛使用的名为comment_sheet
的官方插件。不过,我会根据常见的Flutter插件使用模式来模拟一个类似的实现。
假设我们有一个自定义的CommentSheet
插件,它允许我们展示评论列表,并支持添加新评论。以下是如何在Flutter项目中集成和使用这个插件的示例代码。
1. 添加依赖
首先,我们需要在pubspec.yaml
文件中添加这个假设的comment_sheet
插件依赖(注意:这只是一个示例,你需要替换为实际存在的插件):
dependencies:
flutter:
sdk: flutter
comment_sheet: ^0.1.0 # 假设的版本号
然后运行flutter pub get
来安装依赖。
2. 使用插件
接下来,我们在main.dart
文件中使用CommentSheet
插件来展示评论。
import 'package:flutter/material.dart';
import 'package:comment_sheet/comment_sheet.dart'; // 假设的导入路径
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Comment Sheet Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: CommentScreen(),
);
}
}
class CommentScreen extends StatefulWidget {
@override
_CommentScreenState createState() => _CommentScreenState();
}
class _CommentScreenState extends State<CommentScreen> {
List<String> comments = [
"This is a great app!",
"I love the new features!",
"Keep up the good work!",
];
final TextEditingController _controller = TextEditingController();
void _addComment() {
setState(() {
if (_controller.text.isNotEmpty) {
comments.add(_controller.text);
_controller.clear();
}
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Comments'),
),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
Expanded(
child: CommentSheet(
comments: comments,
onCommentPressed: () {}, // 假设的回调,可以处理点击评论的动作
),
),
TextField(
controller: _controller,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Add a comment',
),
onSubmitted: _addComment,
),
ElevatedButton(
onPressed: _addComment,
child: Text('Post'),
),
],
),
),
);
}
}
// 假设的 CommentSheet 组件实现(实际上你需要从插件中获取)
class CommentSheet extends StatelessWidget {
final List<String> comments;
final VoidCallback onCommentPressed;
CommentSheet({required this.comments, required this.onCommentPressed});
@override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: comments.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(comments[index]),
onTap: onCommentPressed,
);
},
);
}
}
注意事项
-
插件实际存在性:
comment_sheet
是一个假设的插件名称。在实际使用中,你需要找到一个真实存在的Flutter评论展示插件,或者自己实现一个。 -
插件功能:上述示例中的
CommentSheet
组件是一个简单的ListView,用于展示评论列表。实际插件可能包含更多功能,如评论点赞、回复、加载更多评论等。 -
错误处理:在实际应用中,你还需要添加错误处理逻辑,例如处理网络请求失败、评论添加失败等情况。
-
样式定制:你可以根据需要定制评论列表的样式,使其更符合你的应用风格。
-
数据持久化:如果评论数据需要持久化存储(例如保存到数据库或服务器),你需要添加相应的逻辑来处理数据的保存和加载。