flutter ExpandContentWidget展开列表
2021-09-15 本文已影响0人
银弹星空
外层列表
import 'package:date_format/date_format.dart';
import 'package:flutter/material.dart';
import 'package:flutter_huiben/dao/comment_dao.dart';
import 'package:flutter_huiben/models/base/base_model.dart';
import 'package:flutter_huiben/models/book_model.dart';
import 'package:flutter_huiben/models/request/get_aud_request.dart';
import 'package:flutter_huiben/models/response/get_audio_chapter_response.dart';
import 'package:flutter_huiben/widget/bookdetail/expand_content_widget.dart';
import 'package:flutter_screenutil/screen_util.dart';
import 'package:fluttertoast/fluttertoast.dart';
/// 书本评论列表
class BookContentPage extends StatefulWidget {
final int bookID;
const BookContentPage({Key key, this.bookID}) : super(key: key);
@override
_BookContentPageState createState() => _BookContentPageState();
}
class _BookContentPageState extends State<BookContentPage>
with WidgetsBindingObserver {
List<AudComment> _audCommentList = [];
TextEditingController _editingController = new TextEditingController();
FocusNode _focusNode = FocusNode();
String hintTextString = '来吧有感而发';
bool isRespond = false;
int respondID;
@override
void initState() {
// TODO: implement initState
super.initState();
_getBookContent();
WidgetsBinding.instance.addObserver(this);
_editingController.addListener(() {});
}
@override
void didChangeMetrics() {
// TODO: implement didChangeMetrics
super.didChangeMetrics();
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
setState(() {
if (MediaQuery.of(context).viewInsets.bottom == 0) {
//关闭键盘
hintTextString = '来吧有感而发';
isRespond = false;
_focusNode.unfocus();
} else {
//打开键盘
}
});
});
}
@override
void dispose() {
// TODO: implement dispose
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
@override
Widget build(BuildContext context) {
return AnimatedPadding(
padding: MediaQuery.of(context).viewInsets,
duration: const Duration(milliseconds: 160),
child: DraggableScrollableSheet(
initialChildSize: 0.4,
maxChildSize: 1,
expand: false,
builder: (BuildContext context, ScrollController scrollController) {
return Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topRight: Radius.circular(7),
topLeft: Radius.circular(7),
),
),
child: Column(
children: <Widget>[
Container(
alignment: Alignment.center,
height: ScreenUtil().setHeight(84),
child: RichText(
text: TextSpan(
text: '评论',
style: TextStyle(
color: Color(0xff333333),
fontSize: ScreenUtil().setSp(28)),
children: [
TextSpan(
text: '(${_audCommentList.length})',
style: TextStyle(
color: Color(0xff999999),
fontSize: ScreenUtil().setSp(26),
fontWeight: FontWeight.bold),
),
],
),
),
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(
color: Color(0xffe8e8e8),
width: ScreenUtil().setHeight(1))),
),
),
Expanded(
flex: 1,
child: ListView.separated(
itemBuilder: (context, index) {
return ExpandContentWidget(
list: List.generate(3, (index) => '小王$index')
.toList(),
audComment: _audCommentList[index],
getFocus: (String text, int respondID) {
hintTextString = '回复@$text:';
this.respondID = respondID;
isRespond = true;
FocusScope.of(context).requestFocus(_focusNode);
},
);
},
separatorBuilder: (BuildContext context, int index) {
return Container(
margin: EdgeInsets.only(
left: ScreenUtil().setWidth(145)),
color: Color(0XFFE8E8E8),
height: ScreenUtil().setHeight(1),
);
},
itemCount: _audCommentList.length,
controller: scrollController,
)),
_inputContentWidget(),
],
),
);
}),
);
}
_inputContentWidget() {
return Container(
alignment: Alignment.center,
decoration: BoxDecoration(
color: Colors.white,
border: Border(
top: BorderSide(
color: Color(0xffe8e8e8), width: ScreenUtil().setHeight(1))),
),
padding: EdgeInsets.symmetric(
horizontal: ScreenUtil().setWidth(30),
vertical: ScreenUtil().setHeight(10)),
constraints: BoxConstraints(minHeight: ScreenUtil().setHeight(85)),
child: Row(
children: [
Expanded(
flex: 1,
child: TextField(
controller: _editingController,
focusNode: _focusNode,
maxLines: 3,
minLines: 1,
cursorColor: Color(0xffFCB605),
textInputAction: TextInputAction.send,
onEditingComplete: () {
print('onEditingComplete ');
},
onSubmitted: (text) {
print('onSubmitted text$text');
if (isRespond) {
_respondCommentFunction(text, respondID);
} else {
_commentFunction(text);
}
},
decoration: InputDecoration(
filled: true,
isDense: true,
hintText: hintTextString,
hintStyle: TextStyle(
color: Color(0xff999999), fontSize: ScreenUtil().setSp(26)),
contentPadding:
EdgeInsets.symmetric(vertical: 8, horizontal: 10),
border: OutlineInputBorder(
borderRadius:
BorderRadius.circular(ScreenUtil().setWidth(33)),
),
enabledBorder: OutlineInputBorder(
borderRadius:
BorderRadius.circular(ScreenUtil().setWidth(33)),
borderSide: BorderSide(color: Color(0xfff7f7f7), width: 0),
),
focusedBorder: OutlineInputBorder(
borderRadius:
BorderRadius.circular(ScreenUtil().setWidth(33)),
borderSide: BorderSide(color: Color(0xfff7f7f7), width: 0),
),
),
keyboardType: TextInputType.multiline,
),
),
Container(
margin: EdgeInsets.only(left: ScreenUtil().setWidth(12)),
child: InkWell(
child: Icon(Icons.sentiment_satisfied_rounded),
onTap: () {},
),
),
],
),
);
}
// 获取某个书籍的评论
void _getBookContent() async {
AudCommentRequest audCommentRequest = AudCommentRequest();
audCommentRequest.bookID = widget.bookID;
audCommentRequest.type = 1;
audCommentRequest.page = 1;
audCommentRequest.size = 30;
GetAudCommentModel getAudCommentModel =
await CommentDao.getBookComment(audCommentRequest);
if (getAudCommentModel.success) {
_audCommentList = getAudCommentModel.data.items;
setState(() {});
}
}
/**
* 评论
*/
void _commentFunction(String text) async {
BaseModel baseModel = await CommentDao.postAddComment(
bookID: widget.bookID, isRemind: true, comment: text);
if (baseModel.success) {
Fluttertoast.showToast(msg: '评论成功');
_getBookContent();
} else {
Fluttertoast.showToast(msg: '评论失败');
}
}
/**
* 回复一条评论
*/
void _respondCommentFunction(String text, int respondID) async {
BaseModel baseModel = await CommentDao.postRespondComment(
comment: text, respondID: respondID);
if (baseModel.success) {
Fluttertoast.showToast(msg: '评论成功');
_getBookContent();
} else {
Fluttertoast.showToast(msg: '评论失败');
}
}
}
内层列表
import 'package:date_format/date_format.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_huiben/dao/comment_dao.dart';
import 'package:flutter_huiben/models/base/base_model.dart';
import 'package:flutter_huiben/models/book_model.dart';
import 'package:flutter_huiben/models/request/get_aud_request.dart';
import 'package:flutter_huiben/pages/report/report_page.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:time_machine/time_machine.dart';
///展开关闭多人评论
class ExpandContentWidget extends StatefulWidget {
final List<String> list;
final Function(String userName, int respondID) getFocus;
final AudComment audComment;
const ExpandContentWidget(
{Key key, this.list, this.getFocus, this.audComment})
: super(key: key);
@override
_ExpandContentWidgetState createState() => _ExpandContentWidgetState();
}
class _ExpandContentWidgetState extends State<ExpandContentWidget> {
bool expand = false;
List<AudComment> _audCommentList = [];
final TextStyle style = TextStyle(fontSize: ScreenUtil().setSp(30));
@override
Widget build(BuildContext context) {
return Container(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
_contentItem(index: 0, audComment: widget.audComment),
!expand
? Container()
: Container(
constraints:
BoxConstraints(minHeight: ScreenUtil().setHeight(85)),
child: Column(
children: _audCommentList
.map<Widget>((e) => Container(
margin: EdgeInsets.only(
left: ScreenUtil().setWidth(108),
),
child: _contentItem(index: 0, audComment: e),
))
.toList(),
)),
widget.audComment.respondNum > 0
? GestureDetector(
behavior: HitTestBehavior.translucent,
onTap: () {
_getRespondComment();
},
child: Container(
margin: EdgeInsets.only(left: ScreenUtil().setWidth(145)),
child: Text(
expand ? '收起' : '${widget.audComment.respondNum}条回复>',
style: TextStyle(
fontSize: style != null ? style.fontSize : null,
color: Color(0xFF32689A))),
),
)
: Container(),
],
),
);
}
_contentItem({int index, AudComment audComment}) {
return InkWell(
child: Container(
// height: ScreenUtil().setHeight(160),
padding: EdgeInsets.symmetric(
vertical: ScreenUtil().setHeight(25),
horizontal: ScreenUtil().setWidth(37)),
child: Row(crossAxisAlignment: CrossAxisAlignment.start, children: <
Widget>[
Container(
width: ScreenUtil().setWidth(74),
height: ScreenUtil().setWidth(74),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(ScreenUtil().setWidth(37)),
),
child: PhysicalModel(
color: Colors.transparent,
clipBehavior: Clip.antiAlias,
borderRadius: BorderRadius.circular(ScreenUtil().setWidth(37)),
child: Image.network(
audComment.headURL ??
'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fb-ssl.duitang.com%2Fuploads%2Fitem%2F201901%2F14%2F20190114231742_cVVta.thumb.224_0.jpeg&refer=http%3A%2F%2Fb-ssl.duitang.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1625648523&t=65e15a4089d504351c38ad3d100fafc0',
),
),
),
Expanded(
flex: 1,
child: Container(
margin:
EdgeInsets.symmetric(horizontal: ScreenUtil().setWidth(34)),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
_titleWidget(index: index, audComment: audComment),
_subTitleWidget(index: index, audComment: audComment),
],
),
),
),
_trailing(index: index, audComment: audComment),
]),
),
onTap: () {
if (widget.getFocus != null) {
widget.getFocus(audComment.nickName ?? '小王', audComment.id);
}
},
onLongPress: () {
Fluttertoast.showToast(msg: '举报');
_showReport(index);
},
);
}
_titleWidget({int index, AudComment audComment}) {
return Container(
// height: ScreenUtil().setHeight(71),
alignment: Alignment.topLeft,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
audComment.nickName ?? '小王',
style: TextStyle(
fontSize: 14, color: Color.fromRGBO(118, 118, 118, 1)),
textAlign: TextAlign.left,
),
_date(index: index, audComment: audComment),
],
),
);
}
Widget _date({int index, AudComment audComment}) {
var createdAt_DateTime = DateTime.parse(
audComment.createdAt ?? '2021-08-16T09:25:48.930926+08:00');
LocalDateTime createdAt = LocalDateTime.dateTime(createdAt_DateTime);
LocalDateTime now = LocalDateTime.now();
Period diff = now.periodSince(createdAt);
String date;
if (diff.years >= 1 || (createdAt.year != now.year)) {
date = formatDate(createdAt_DateTime, [yyyy, "年", mm, "月", dd, "日"]);
} else if (diff.months >= 1 || (createdAt.monthOfYear != now.monthOfYear)) {
date = formatDate(createdAt_DateTime, [mm, "月", dd, "日"]);
} else if (diff.days >= 1 || (createdAt.dayOfMonth != now.dayOfMonth)) {
if (createdAt.dayOfMonth != now.dayOfMonth && diff.days == 0) {
date = "${(diff.days + 1).toString()}天前";
} else {
date = "${diff.days.toString()}天前";
}
;
} else {
date = "${diff.hours.toString()}小时前";
}
return Text(
date,
style: TextStyle(fontSize: 11, color: Color.fromRGBO(159, 159, 159, 1)),
);
}
_subTitleWidget({int index, AudComment audComment}) {
return Text(
audComment.comment ?? '',
maxLines: 3,
overflow: TextOverflow.ellipsis,
style: TextStyle(color: Colors.black),
);
}
_trailing({int index, AudComment audComment}) {
return Container(
width: ScreenUtil().setWidth(70),
// height: ScreenUtil().setHeight(30),
child: Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Text(audComment.praiseNum.toString() ?? '赞'),
InkWell(
child: Icon(
Icons.thumb_up_outlined,
color: Color(0xFF666666),
),
onTap: () {
Fluttertoast.showToast(msg: '赞赞');
praiseComment(audComment);
setState(() {
// audCommentList[index].isPraise = 1;
});
},
)
],
),
);
}
void _showReport(index) {
showDialog(
context: context,
builder: (context) {
return SimpleDialog(
contentPadding: EdgeInsets.all(ScreenUtil().setWidth(30)),
children: <Widget>[
InkWell(
child: Container(
alignment: Alignment.centerLeft,
height: ScreenUtil().setHeight(80),
child: Text('回复'),
),
onTap: () {
Navigator.pop(context);
if (widget.getFocus != null) {
widget.getFocus(widget.list[index], 1);
}
},
),
InkWell(
child: Container(
alignment: Alignment.centerLeft,
height: ScreenUtil().setHeight(80),
child: Text('举报'),
),
onTap: () {
Navigator.pop(context);
ReportPage.show(context, bookId: index);
},
),
InkWell(
child: Container(
alignment: Alignment.centerLeft,
height: ScreenUtil().setHeight(80),
child: Text('复制'),
),
onTap: () {
setData(widget.list[index]);
Navigator.pop(context);
},
),
],
);
});
}
//复制内容
static setData(String data) {
if (data != null && data != '') {
Clipboard.setData(ClipboardData(text: data));
}
}
//获取某条评论的回复
void _getRespondComment() async {
if (!expand) {
GetAudCommentModel getAudCommentModel =
await CommentDao.getRespondComment(widget.audComment.id);
if (getAudCommentModel.success) {
_audCommentList = getAudCommentModel.data.items;
Fluttertoast.showToast(msg: '获取某条评论的回复');
} else {
Fluttertoast.showToast(msg: '获取某条评论的回复失败');
}
}
setState(() {
expand = !expand;
});
}
/**
* 点赞
*/
void praiseComment(AudComment audComment) async {
BaseModel baseModel = await CommentDao.postPraiseComment(
commentID: audComment.id, isPraise: audComment.isPraise ?? true);
if(baseModel.success){
Fluttertoast.showToast(msg: '点赞成功');
audComment.isPraise = true;
}
setState(() {
});
}
}