大佬教程收集整理的这篇文章主要介绍了Flutter实战一Flutter聊天应用(九),大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
在这篇文章中,我们将允许用户在聊天消息中发送图像,从设备检索图像文件,并将文本和图像数据存储在Google云端存储Bucket中。由于我们使用Firebase云储存,应用程序将变得更加健壮和可扩展。它能够在上传和下载期间处理网络中断,安全地存储数据,并在用户群扩展时保持相同的性能。
要将数据(如文本和照片)从移动设备上传到云端,我们需要使用firebase_storage
插件。在@H_549_7@main.dart文件中,确保导入相应的包。
@H_404_15@import 'package:firebase_storage/firebase_storage.dart';
要访问存储在移动设备上的数据并在Flutter应用程序中使用它,我们需要Flutter的平台服务API和image_picker
插件。在@H_549_7@main.dart文件中,导入image_picker
包。另外还要导入dart:math
和dart:io
库,用于在设备上生成随机文件名和处理文件操作。
@H_404_15@import 'package:image_picker/image_picker.dart';
@H_404_15@import 'dart:math';
@H_404_15@import 'dart:io';
此时,@R_382_9616@程序可以让用户发送和接收消息。现在,我们将在用户界面中添加一个按钮来撰写消息,使用户可以从应用访问设备的相机。然后我们将给UI处理二进制数据的能力。
需要注意的是,如果我们正在iOS设备上进行测试,那么需要添加一个设置,让图像选择器插件访问相机和设备上存储的图像。要启用访问,需要将以下条目添加到应用程序的Info.plist
文件的主字典中。
<Dict>
<key>NSCameraUsageDescription</key>
<String>Share images with other chat users</String>
<key>NSPhotoLibraryUsageDescription</key>
<String>Share images with other chat users</String>
...
</Dict>
<String>
元素可以包含任何文本值。我们还可以在xcode中添加这些设置,使用Privacy - Camera Usage Description
和Privacy - Photo Library Usage Description
属性的新行。
用户需要一种访问存储在设备上的图像的方法,我们将在用于撰写聊天消息的UI旁边创建一个按钮。应用程序UI的这一部分由ChatScreenState
中的私有方法_buildTextComposer()
定义。添加一个IconButton
小部件,用于访问相机和存储的图像到_buildTextComposer
方法。输入字段和发送按钮的现有Row
控件应该是父级,将IconButton
控件包装在新的Container
控件中,Container
控件让我们能自定义按钮的边距间距,使其在输入字段旁边更好看。
class ChatScreenState extends State<ChatScreen> {
//@H_404_15@...
Widget _buildTextComposer() {
@H_404_15@return new IconTheme(
data: new IconThemeData(color: Theme.of(context).accentColor),child: new Container(
margin: const EdgeInsets.symmetric(horizontal: 8.0),child: new Row(
children: <Widget> [
new Container(
margin: new EdgeInsets.symmetric(horizontal: 4.0),child: new IconButton(
icon: new Icon(Icons.photo_camera),onPressed: (){}
),),new Flexible(
//@H_404_15@...
),new Container(
//@H_404_15@...
)
]
)
)
);
}
//@H_404_15@...
}
在icon
属性中,使用Icons.photo_camera
常量创建一个新的Icon
实例,此常量可以让控件使用Flutter素材图标库提供的“相机”图标。
现在修改相机按钮的onPressed
回调。我们需要引用Google云端存储Bucket,并在用户选择之后立即开始上传图像。对于按钮的onPressed
属性,我们将调用async
函数并将其与几个await
表达式组合,以特定顺序执行与图像相关的任务。
class ChatScreenState extends State<ChatScreen> { //@H_404_15@... Widget _buildTextComposer() { //@H_404_15@... child: new IconButton( icon: new Icon(Icons.photo_camera),onPressed: () async { await _ensureLoggedIn(); File imageFile = await ImagePicker.pickImage(); } ),//@H_404_15@... } //@H_404_15@... }
在允许用户选择、上传和发送图像之前,确保通过执行私有_ensureLoggedIn()
方法登录。然后等待用户选择一个图像,并从pickImage()
方法获取一个名为imageFile
的新的File
对象。此方法由之前导入的Flutter Image Picker插件提供。它不需要参数,并返回一个名为path
的String值作为图像文件的URL。接下来,修改_sendmessage()
以添加imageUrl
参数。
class ChatScreenState extends State<ChatScreen> {
//@H_404_15@...
void _sendmessage({ String text,String imageUrl }) {
reference.push().set({
'text': text,'imageUrl': imageUrl,'senderName': googleSignIn.currentUser.displayName,'senderPhotoUrl': googleSignIn.currentUser.photoUrl,});
analytics.logEvent(name: 'send_message');
}
//@H_404_15@...
}
创建一个用于将文件上传到Google Cloud Storage的实例变量,初始化它以获取对File
对象的引用,并将其传递给put()
方法。给每个文件一个唯一的名称,使用image_
作为前缀,然后是随机整数。
class ChatScreenState extends State<ChatScreen> {
//@H_404_15@...
Widget _buildTextComposer() {
//@H_404_15@...
child: new IconButton(
icon: new Icon(Icons.photo_camera),onPressed: () async {
await _ensureLoggedIn();
File imageFile = await ImagePicker.pickImage();
int random = new Random().nexTint(100000);
StorageReference ref = FirebaseStorage.instance.ref().child("image_$random.jpg");
StorageUploadTask uploadTask = ref.put(imageFilE);
Uri downloadUrl = (await uploadTask.futurE).downloadUrl;
}
),//@H_404_15@...
}
//@H_404_15@...
}
put()
方法由Firebase的Cloud Storage API定义,它需要一个File
对象作为参数,并将其上传到Google云端存储Bucket。之前导入的Flutter Firebase Storage插件提供对该API的访问,并定义了StorageUploadTask
类。上传完成后,您可以获取图像的downloadURL
,现在调用_sendmessage()并传递downloadURL来发送图像。
class ChatScreenState extends State<ChatScreen> {
//@H_404_15@...
Widget _buildTextComposer() {
//@H_404_15@...
child: new IconButton(
icon: new Icon(Icons.photo_camera),onPressed: () async {
await _ensureLoggedIn();
File imageFile = await ImagePicker.pickImage();
int random = new Random().nexTint(100000);
StorageReference ref = FirebaseStorage.instance.ref().child("image_$random.jpg");
StorageUploadTask uploadTask = ref.put(imageFilE);
Uri downloadUrl = (await uploadTask.futurE).downloadUrl;
_sendmessage(imageUrl: downloadUrl.toString());
}
),//@H_404_15@...
}
//@H_404_15@...
}
这个URL用于应用程序UI从Google云端存储下载图像到本地,让发送人在聊天对话中查看他们发送的图像。发送或接收的每个聊天消息都需要能够显示图像和文本。接下来,我们将增强Chatmessage
类,以检测用户何时发送图像并使用其URL获取图像。
class Chatmessage extends StatelessWidget {
//@H_404_15@...
@override
Widget build(BuildContext context) {
@H_404_15@return new SizeTransition(
//@H_404_15@...
child: new Container(
margin: const EdgeInsets.symmetric(vertical: 10.0),child: new Row(
crossAxisAlignment: CrossAxisAlignment.start,children: <Widget>[
//@H_404_15@...
new column(
crossAxisAlignment: CrossAxisAlignment.start,children: <Widget>[
new Text(
snapshot.value['senderName'],style: Theme.of(context).textTheme.subhead),new Container(
margin: const EdgeInsets.only(top: 5.0),child: snapshot.value['imageUrl'] != null ?
new Image.network(
snapshot.value['imageUrl'],width: 250.0,):
new Text(snapshot.value['text']),)
]
)
]
)
)
);
}
}
在上面的代码中,如果数据库行的值字段是imageUrl
,那么应用程序将创建一个Image
窗口控件,并将其与图像的内容填充。为了一致性,将宽度设置为特定数量的逻辑像素。如果消息不包含图像,则应用程序将在完成此步骤之前创建一个Text
窗口控件。
因为我们在更改了iOS的Info.plist
配置文件,所以我们现在需要重新启动应用程序,而不是重新加载。
以上是大佬教程为你收集整理的Flutter实战一Flutter聊天应用(九)全部内容,希望文章能够帮你解决Flutter实战一Flutter聊天应用(九)所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。