import 'dart:io'; import 'dart:ui'; import 'package:emoji_picker_flutter/emoji_picker_flutter.dart'; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter/services.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:huixiang/retrofit/retrofit_api.dart'; import 'package:huixiang/view_widget/my_appbar.dart'; import 'package:flutter/cupertino.dart'; import 'package:image_pickers/image_pickers.dart'; import '../../community/release_dynamic.dart'; import '../../generated/l10n.dart'; import '../../utils/font_weight.dart'; import 'im_view/on_chat_message.dart'; import 'im_view/on_chat_msg_instance.dart'; class ChatDetailsPage extends StatefulWidget { @override State createState() { return _ChatDetailsPage(); } } class _ChatDetailsPage extends State with WidgetsBindingObserver implements OnChatMessage { ApiService apiService; List mediaPaths = []; int selectCount = 9; int dynamicType = 0; final TextEditingController chatController = TextEditingController(); bool emojiShowing = false; double keyboard = -1; bool needShowSmiley = false; bool needHideSmiley = false; bool isKeyBoardShow = false; bool moreShow = false; bool needShowMore = false; bool needHideMore = false; var commentFocus = FocusNode(); String hintText = "请输入消息内容..."; final OnChatMessage _tempOnChatMessage = OnChatMsgInstance.instance.onChatMessage; final ScrollController scrollController = ScrollController(); String tex = ""; int copyIndex = 0; @override void onMessage(txt) { // SmartDialog.showToast("聊天 $txt", alignment: Alignment.center); } @override void initState() { super.initState(); OnChatMsgInstance.instance.onChatMessage = this; WidgetsBinding.instance.addObserver(this); commentFocus.addListener(_focusNodeListener); Future.delayed(Duration.zero, () { jumpToBottom(); }); } void jumpToBottom(){ scrollController.position .jumpTo(scrollController.position.maxScrollExtent); } void didChangeMetrics() { WidgetsBinding.instance.addPostFrameCallback((_) { isKeyBoardShow = MediaQuery.of(context).viewInsets.bottom > 0; if (!mounted) return; if (MediaQuery.of(context).viewInsets.bottom == 0) { if (isKeyBoardShow) { FocusScope.of(context).requestFocus(FocusNode()); if (mounted) if (!emojiShowing) if (!moreShow) setState(() { hintText = "请输入消息内容..."; isKeyBoardShow = false; }); } } else { if (mounted) setState(() { isKeyBoardShow = true; }); } }); if (needShowSmiley && window.viewInsets.bottom <= 0.1) { needShowSmiley = false; setState(() { emojiShowing = true; }); } if (needHideSmiley && window.viewInsets.bottom > 0.1) { needHideSmiley = false; setState(() { emojiShowing = false; }); } if (needShowMore && window.viewInsets.bottom <= 0.1) { needShowMore = false; setState(() { moreShow = true; }); } if (needHideMore && window.viewInsets.bottom > 0.1) { needHideMore = false; setState(() { moreShow = false; }); } } @override void dispose() { super.dispose(); OnChatMsgInstance.instance.onChatMessage = _tempOnChatMessage; WidgetsBinding.instance.removeObserver(this); commentFocus.removeListener(_focusNodeListener); } void _focusNodeListener() { /*if (_focusNode.hasFocus || _focusNode.consumeKeyboardToken()){ setState(() { smileyPadGone = true; }); }*/ } ///输入框点击事件 _onTextFieldTap() { if (emojiShowing) { needHideSmiley = true; } if (moreShow) { needHideMore = true; } } ///表情包点击事件 _onSmileyTap() { if (!emojiShowing && commentFocus.hasFocus && isKeyBoardShow) { needShowSmiley = true; commentFocus.unfocus(); } else { setState(() { emojiShowing = !emojiShowing; isKeyBoardShow = emojiShowing; moreShow = false; }); } } ///更多点击事件 _onMoreTap() { if (!moreShow && commentFocus.hasFocus && isKeyBoardShow) { needShowMore = true; commentFocus.unfocus(); } else { setState(() { moreShow = !moreShow; isKeyBoardShow = moreShow; emojiShowing = false; }); } } ///图片/视频选择 Future getImageOrVideo(GalleryMode galleryMode) async { if (selectCount == 0) return; List medias = await ImagePickers.pickerPaths( galleryMode: galleryMode, selectCount: (galleryMode == GalleryMode.video) ? 1 : selectCount, showGif: true, showCamera: false, compressSize: 500, uiConfig: UIConfig( uiThemeColor: Color(0xFFFFFFFF), ), cropConfig: CropConfig( enableCrop: false, width: 200, height: 200, ), ); mediaPaths.addAll(medias.map((e) => Medias(e)).toList()); selectCount = 9 - mediaPaths.length; if (mediaPaths.length > 0) { if (galleryMode == GalleryMode.image) { dynamicType = 1; } else { dynamicType = 2; } } setState(() {}); } @override Widget build(BuildContext context) { double h = MediaQuery.of(context).viewInsets.bottom; if (h > 0) { jumpToBottom(); if(keyboard < h){ keyboard = h; // setState(() {}); } } return Scaffold( // resizeToAvoidBottomInset: false, backgroundColor: Color(0xFFF9FAF7), appBar: MyAppBar( title: "哈哈哈哈", titleColor: Colors.black, titleSize: 18.sp, background: Colors.white, leading: true, leadingColor: Colors.black, action: GestureDetector( behavior: HitTestBehavior.opaque, onTap: () { setState(() { Navigator.of(context).pushNamed('/router/chat_setting'); copyIndex = 0; }); }, child: Container( padding: EdgeInsets.only(top: 3.h, bottom: 16.h), alignment: Alignment.center, // color: Colors.red, child: Icon( Icons.more_horiz, color: Colors.black, size: 30, ), )), ), body: Container( child: Column( children: [ Expanded( child: SingleChildScrollView( physics: BouncingScrollPhysics(), controller: scrollController, child: Column( children: [ GestureDetector( behavior: HitTestBehavior.translucent, onTap: () { setState(() { emojiShowing = false; isKeyBoardShow = emojiShowing; moreShow = false; isKeyBoardShow = moreShow; FocusScope.of(context).requestFocus(FocusNode()); }); }, child: chatDetailsList()), ], ), ), flex: 1, ), input() ], ), ), ); } ///聊天列表 Widget chatDetailsList() { return Container( margin: EdgeInsets.only(bottom: 48.h), child: ListView.builder( itemCount: 10, shrinkWrap: true, physics: NeverScrollableScrollPhysics(), itemBuilder: (context, position) { return GestureDetector( behavior: HitTestBehavior.opaque, onTap: () { setState((){ copyIndex = 0; }); }, child: chatDetailsItem(), ); }), ); } Widget chatDetailsItem() { return Container( padding: EdgeInsets.only(top: 32.h,), child: Column( children: [ Text( "3月08日 上午 12:10", textAlign: TextAlign.center, style: TextStyle( color: Color(0xFFA29E9E), fontSize: 10.sp, fontWeight: MyFontWeight.regular, ), ), Padding( padding: EdgeInsets.only(top: 10.h, bottom: 24.h), child: Text( "在对方未回复或关注你之前,你只能发送一条信息", textAlign: TextAlign.center, style: TextStyle( color: Color(0xFFA29E9E), fontSize: 10.sp, fontWeight: MyFontWeight.regular, ), ), ), SizedBox( height: 16.h, ), if(copyIndex == 1) Stack( alignment: Alignment.bottomCenter, children: [ Container( padding: EdgeInsets.only(bottom:13.h), child: Container( width: 180.w, decoration: BoxDecoration( color: Color(0xFF2A2A2A), borderRadius: BorderRadius.circular(6), ), padding: EdgeInsets.symmetric(horizontal: 32.w,vertical: 7.5.h), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.center, children: [ GestureDetector( onTap: (){ setState((){ copyIndex = 0; this.copy(tex); }); }, child:Column( children: [ Image.asset( "assets/image/icon_chat_copy.webp", height:16, width: 16, ), SizedBox(height: 2.h,), Text( "复制", textAlign: TextAlign.center, style: TextStyle( color: Colors.white, fontSize: 12.sp, fontWeight: MyFontWeight.regular, ), ), ], ) , ), GestureDetector( onTap: (){}, child: Column( children: [ Image.asset( "assets/image/icon_chat_delete.webp", height:16, width: 16, ), SizedBox(height: 2.h,), Text( S.of(context).shanchu, textAlign: TextAlign.center, style: TextStyle( color: Colors.white, fontSize: 12.sp, fontWeight: MyFontWeight.regular, ), ), ], ), ) ], ), ), ), Image.asset( "assets/image/icon_copy_j.webp", height: 17, width: 17, ), ], ), Padding(padding:EdgeInsets.only(left: 17.w,right: 39.w), child: Row( children: [ // MImage( // "", // isCircle: true, // width: 44, // height: 44, // fit: BoxFit.cover, // errorSrc: "assets/image/default_user.webp", // fadeSrc: "assets/image/default_user.webp", // ), Image.asset( "assets/image/fuka_zj.webp", height: 44, width: 44, ), SizedBox( width: 12.w, ), Expanded( child: Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(6), color: Color(0xFFF0FAF4), ), padding: EdgeInsets.symmetric(vertical: 8.h, horizontal: 12.w), child:GestureDetector( onLongPress:(){ setState((){ copyIndex =1; }); }, child: Text( tex = "上次你在我这里买的水果钱是不是忘记付了?一共18块钱做点生意也是真的不容易啊。", textAlign: TextAlign.left, style: TextStyle( height: 1.2.h, color: Colors.black, fontSize: 17.sp, fontWeight: MyFontWeight.regular, ), ), ) )), ], ),), SizedBox(height: 40.h,), if(copyIndex == 1) Stack( alignment: Alignment.bottomCenter, children: [ Container( padding: EdgeInsets.only(bottom:13.h), child: Container( width: 180.w, decoration: BoxDecoration( color: Color(0xFF2A2A2A), borderRadius: BorderRadius.circular(6), ), padding: EdgeInsets.symmetric(horizontal: 32.w,vertical: 7.5.h), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.center, children: [ GestureDetector( onTap: (){ setState((){ copyIndex = 0; this.copy(tex); }); }, child:Column( children: [ Image.asset( "assets/image/icon_chat_copy.webp", height:16, width: 16, ), SizedBox(height: 2.h,), Text( "复制", textAlign: TextAlign.center, style: TextStyle( color: Colors.white, fontSize: 12.sp, fontWeight: MyFontWeight.regular, ), ), ], ) , ), GestureDetector( onTap: (){}, child: Column( children: [ Image.asset( "assets/image/icon_chat_delete.webp", height:16, width: 16, ), SizedBox(height: 2.h,), Text( S.of(context).shanchu, textAlign: TextAlign.center, style: TextStyle( color: Colors.white, fontSize: 12.sp, fontWeight: MyFontWeight.regular, ), ), ], ), ) ], ), ), ), Image.asset( "assets/image/icon_copy_j.webp", height: 17, width: 17, ), ], ), Padding(padding:EdgeInsets.only(left:36.w,right: 16.w), child: Row( children: [ Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(100), color: Color(0xFFFF441A), ), width: 20, height: 20, alignment: Alignment.center, child: Text( "!", textAlign: TextAlign.left, style: TextStyle( color: Colors.white, fontSize: 17.sp, fontWeight: MyFontWeight.regular, ), ), ), SizedBox( width: 12.w, ), Expanded( child: Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(6), color: Color(0xFF32A060), ), padding: EdgeInsets.symmetric(vertical: 8.h, horizontal: 12.w), child: GestureDetector( onLongPress:(){ setState((){ copyIndex = 1; }); }, child: Text( tex = "凭本事买的为啥要给你钱啊伙计", textAlign: TextAlign.left, style: TextStyle( height: 1.2.h, color: Colors.black, fontSize: 17.sp, fontWeight: MyFontWeight.regular, ), ), ), )), SizedBox( width: 12.w, ), // MImage( // "", // isCircle: true, // width: 44, // height: 44, // fit: BoxFit.cover, // errorSrc: "assets/image/default_user.webp", // fadeSrc: "assets/image/default_user.webp", // ), Image.asset( "assets/image/fuka_zj.webp", height: 44, width: 44, ), ], )), Padding( padding: EdgeInsets.only(left: 17.w, right: 17.w, top: 24.h), child: Text( "由于对方没有回复你,你只能发送一条消息,需要对方关注或回复后才能恢复正常聊天", textAlign: TextAlign.center, style: TextStyle( color: Color(0xFFA29E9E), fontSize: 10.sp, fontWeight: MyFontWeight.regular, ), ), ), ], ), ); } ///富文本输入框 Widget input() { return Container( color: Colors.white, padding: EdgeInsets.only(top: 16.h, bottom: 15.h), child: Column( children: [ Row( children: [ Expanded( flex: 1, child: Container( margin: EdgeInsets.only( left: 20.w, ), decoration: BoxDecoration( color: Color(0xFFF0FAF4), borderRadius: BorderRadius.circular(6), ), child: Container( margin: EdgeInsets.symmetric(horizontal: 12.w), alignment: Alignment.topLeft, child: TextField( textInputAction: TextInputAction.send, onTap: () { moreShow = false; _onTextFieldTap(); }, onEditingComplete: () { var commentText = chatController.text; if (commentText.trim() == "") { return; } // widget.queryMemberComment(commentText); }, maxLines: 8, minLines: 1, focusNode: commentFocus, controller: chatController, decoration: InputDecoration( border: InputBorder.none, hintText: hintText, hintStyle: TextStyle( fontSize: 14.sp, color: Color(0xFF868686), ), ), ), ), ), ), GestureDetector( behavior: HitTestBehavior.opaque, onTap: () { _onSmileyTap(); Future.delayed(Duration(milliseconds: 500), () { jumpToBottom(); }); }, child: Container( padding: EdgeInsets.only(left: 15.w, right: 8.w), child: Image.asset( "assets/image/icon_chat_emo.webp", height: 24, width: 24, )), ), GestureDetector( behavior: HitTestBehavior.opaque, onTap: () { _onMoreTap(); Future.delayed(Duration(milliseconds: 500), () { jumpToBottom(); }); }, child: Container( padding: EdgeInsets.only(left: 8.w, right: 19.w), child: Image.asset( "assets/image/fa_bu.webp", height: 24, width: 24, ), ), ), ], ), SizedBox( height: 16.h, ), ///表情 Offstage( offstage: !emojiShowing, child: SizedBox( height: keyboard == -1 ? 270 : keyboard, width: MediaQuery.of(context).size.width, child: EmojiPicker( textEditingController: chatController, config: Config( columns: 7, emojiSizeMax: 32 * (Platform.isIOS ? 1.10 : 1.0), verticalSpacing: 0, horizontalSpacing: 0, gridPadding: EdgeInsets.zero, initCategory: Category.RECENT, bgColor: const Color(0xFFF2F2F2), // indicatorColor: Colors.blue, iconColor: Colors.grey, iconColorSelected: Colors.blue, backspaceColor: Colors.blue, skinToneDialogBgColor: Colors.white, skinToneIndicatorColor: Colors.grey, enableSkinTones: true, showRecentsTab: true, recentsLimit: 28, replaceEmojiOnLimitExceed: false, noRecents: Text( "最近使用", style: TextStyle(fontSize: 20, color: Colors.black26), textAlign: TextAlign.center, ), loadingIndicator: const SizedBox.shrink(), tabIndicatorAnimDuration: Duration(milliseconds: 0), categoryIcons: const CategoryIcons(), buttonMode: ButtonMode.MATERIAL, checkPlatformCompatibility: true, ), )), ), ///更多 Offstage( offstage: !moreShow, child: Container( height: keyboard == -1 ? 270 : keyboard, child: Column( children: [ Container( width: double.infinity, height: 1.h, color: Color(0xFFF7F7F7), ), Row( children: [ GestureDetector( behavior: HitTestBehavior.opaque, onTap: () { getImageOrVideo(GalleryMode.video); }, child: Container( padding: EdgeInsets.only( left: 19.w, right: 16.w, top: 11.h, bottom: 5.h), child: Image.asset( "assets/image/icon_chat_camera.webp", height: 26, width: 24, ), ), ), GestureDetector( behavior: HitTestBehavior.opaque, onTap: () { getImageOrVideo(GalleryMode.image); }, child: Container( // color: Colors.yellow, padding: EdgeInsets.only( left: 16.w, right: 16.w, top: 13.h, bottom: 5.h), child: Image.asset( "assets/image/icon_chat_photo.webp", height: 24, width: 24, ), ), ), ], ) ], ), ), ) ], ), ); } showCustomDialog(BuildContext context,int position ){ showDialog( context: context, builder: (BuildContext context) { return new AlertDialog( backgroundColor: Color(0xFF2A2A2A), elevation: 0, contentPadding:EdgeInsets.only(top: 8.h,bottom: 5.h,), content: Container( height: 40.h, // width:20.w, alignment: Alignment.center, child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.center, children: [ Column( children: [ Image.asset( "assets/image/icon_chat_copy.webp", height:16, width: 16, ), Text( "复制", textAlign: TextAlign.center, style: TextStyle( color: Colors.white, fontSize: 12.sp, fontWeight: MyFontWeight.regular, ), ), ], ), Column( children: [ Image.asset( "assets/image/icon_chat_delete.webp", height:16, width: 16, ), Text( S.of(context).shanchu, textAlign: TextAlign.center, style: TextStyle( color: Colors.white, fontSize: 12.sp, fontWeight: MyFontWeight.regular, ), ), ], ) ], ), ), ); }); } /// 复制文本 copy(String tex) { print(tex); Clipboard.setData(ClipboardData(text: tex)); } }