Browse Source
feat(message): 实现聊天页面图片发送功能
feat(message): 实现聊天页面图片发送功能
- 新增图片和视频读取权限声明 (Android)- 新增相册访问权限描述 (iOS) - 添加图片消息发送方法到聊天控制器- 创建更多选项视图组件用于选择图片和拍照 - 在聊天输入栏集成图片选择和相机功能- 更新依赖项以支持图片和相机相关功能- 实现从相册选择图片并发送的功能- 实现拍照并发送图片的功能ios
8 changed files with 389 additions and 73 deletions
Split View
Diff Options
-
2android/app/src/main/AndroidManifest.xml
-
2ios/Runner/Info.plist
-
19lib/controller/message/chat_controller.dart
-
6lib/pages/message/chat_page.dart
-
102lib/widget/message/chat_input_bar.dart
-
137lib/widget/message/more_options_view.dart
-
192pubspec.lock
-
2pubspec.yaml
@ -0,0 +1,137 @@ |
|||
import 'package:flutter/material.dart'; |
|||
import 'package:flutter_screenutil/flutter_screenutil.dart'; |
|||
import 'package:get/get.dart'; |
|||
import 'package:wechat_assets_picker/wechat_assets_picker.dart'; |
|||
import 'package:wechat_camera_picker/wechat_camera_picker.dart'; |
|||
|
|||
import '../../generated/assets.dart'; |
|||
|
|||
class MoreOptionsView extends StatelessWidget { |
|||
final bool isVisible; |
|||
final ValueChanged<List<String>> onImageSelected; |
|||
final ValueChanged<String> onCameraSelected; |
|||
|
|||
const MoreOptionsView({ |
|||
required this.isVisible, |
|||
required this.onImageSelected, |
|||
required this.onCameraSelected, |
|||
super.key, |
|||
}); |
|||
|
|||
@override |
|||
Widget build(BuildContext context) { |
|||
return AnimatedContainer( |
|||
duration: Duration(milliseconds: 300), |
|||
height: isVisible ? 180.h : 0, |
|||
color: Colors.white, |
|||
child: isVisible |
|||
? Container( |
|||
padding: EdgeInsets.symmetric(horizontal: 20.w, vertical: 20.h), |
|||
child: Column( |
|||
children: [ |
|||
SizedBox(height: 10.h), |
|||
// 第一行选项 |
|||
Row( |
|||
mainAxisAlignment: MainAxisAlignment.start, |
|||
children: [ |
|||
// 图片选项 |
|||
GestureDetector( |
|||
onTap: () async{ |
|||
try { |
|||
List<AssetEntity>? result = await AssetPicker.pickAssets(context); |
|||
if (result != null && result.isNotEmpty) { |
|||
// 获取所有选中图片的文件路径 |
|||
List<String> imagePaths = []; |
|||
for (var asset in result) { |
|||
final file = await asset.file; |
|||
if (file != null) { |
|||
imagePaths.add(file.path); |
|||
} |
|||
} |
|||
if (imagePaths.isNotEmpty) { |
|||
onImageSelected(imagePaths); |
|||
} |
|||
} |
|||
} catch (e) { |
|||
if (Get.isLogEnable) { |
|||
Get.log("选择图片失败: $e"); |
|||
} |
|||
} |
|||
}, |
|||
child: Column( |
|||
children: [ |
|||
Container( |
|||
width: 60.w, |
|||
height: 60.w, |
|||
decoration: BoxDecoration( |
|||
color: Color(0xffF0F5FF), |
|||
borderRadius: BorderRadius.circular(8.w), |
|||
), |
|||
padding: EdgeInsets.all(10.w), |
|||
child: Image.asset(Assets.imagesPhoto, width: 40.w, height: 40.w), |
|||
), |
|||
SizedBox(height: 8.h), |
|||
Text( |
|||
"图片", |
|||
style: TextStyle( |
|||
fontSize: 12.sp, |
|||
color: Colors.black, |
|||
), |
|||
), |
|||
], |
|||
), |
|||
), |
|||
SizedBox(width: 40.w), |
|||
// 相机选项 |
|||
GestureDetector( |
|||
onTap: () async{ |
|||
try { |
|||
AssetEntity? entity = await CameraPicker.pickFromCamera( |
|||
context, |
|||
pickerConfig: const CameraPickerConfig(), |
|||
); |
|||
if (entity != null) { |
|||
// 获取拍摄照片的文件路径 |
|||
final file = await entity.file; |
|||
if (file != null) { |
|||
onCameraSelected(file.path); |
|||
} |
|||
} |
|||
} catch (e) { |
|||
if (Get.isLogEnable) { |
|||
Get.log("拍照失败: $e"); |
|||
} |
|||
} |
|||
}, |
|||
child: Column( |
|||
children: [ |
|||
Container( |
|||
width: 60.w, |
|||
height: 60.w, |
|||
decoration: BoxDecoration( |
|||
color: Color(0xffF0F5FF), |
|||
borderRadius: BorderRadius.circular(8.w), |
|||
), |
|||
padding: EdgeInsets.all(10.w), |
|||
child: Image.asset(Assets.imagesCamera, width: 40.w, height: 40.w), |
|||
), |
|||
SizedBox(height: 8.h), |
|||
Text( |
|||
"相机", |
|||
style: TextStyle( |
|||
fontSize: 12.sp, |
|||
color: Colors.black, |
|||
), |
|||
), |
|||
], |
|||
), |
|||
), |
|||
], |
|||
), |
|||
], |
|||
), |
|||
) |
|||
: null, |
|||
); |
|||
} |
|||
} |
|||
Write
Preview
Loading…
Cancel
Save