如何在Flutter中的聊天屏幕的AppBar中显示用户头像和姓名?

问题描述 投票:0回答:2

我正在构建一个 Flutter 应用程序,用户可以在其中互相聊天。我已经实现了用户身份验证,并且可以在 Firestore 中存储用户个人资料信息,例如个人资料图像链接和名称。现在,我想在聊天屏幕的AppBar中显示用户的个人资料图片和姓名。要求:

存储个人资料数据:我已将用户个人资料信息(图像链接和名称)存储在 Firestore 中。 检索个人资料数据:我需要检索此数据并将其显示在聊天屏幕的应用栏中。

聊天屏幕 此页面应该在应用栏中显示所选用户的个人资料图片和姓名。

import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';

class ChatScreen extends StatefulWidget {
  static const String screenRoute = "ChatScreen";
  const ChatScreen({Key? key}) : super(key: key);

  @override
  State<ChatScreen> createState() => _ChatScreenState();
}

class _ChatScreenState extends State<ChatScreen> {
  late User? signedInUser;
  TextEditingController _messageController = TextEditingController();

  @override
  void initState() {
    super.initState();
    getSignedInUser();
  }

  void getSignedInUser() {
    final user = FirebaseAuth.instance.currentUser;
    setState(() {
      signedInUser = user;
    });
  }

  Future<void> sendMessage(String message, String receiverEmail) async {
    try {
      if (signedInUser != null) {
        final messageData = {
          'message': message,
          'senderId': signedInUser!.uid,
          'senderEmail': signedInUser!.email,
          'receiverEmail': receiverEmail,
          'timestamp': Timestamp.now(),
        };

        await FirebaseFirestore.instance.collection('messages').add(messageData);
        _messageController.clear();
      }
    } catch (e) {
      print('Error sending message: $e');
    }
  }

  @override
  Widget build(BuildContext context) {
    final routeArguments = ModalRoute.of(context)?.settings.arguments as Map<String, String>;

    return Scaffold(
      appBar: AppBar(
        backgroundColor: Colors.blue,
        leading: CircleAvatar(
          backgroundImage: NetworkImage(routeArguments['imageLink'] ?? ''),
        ),
        title: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text(routeArguments['title'] ?? ''),
            Text(
              'Last seen: ${routeArguments['lastSeen'] ?? ''}',
              style: TextStyle(fontSize: 12),
            ),
          ],
        ),
      ),
      body: Column(
        children: [
          Expanded(
            child: StreamBuilder<QuerySnapshot>(
              stream: FirebaseFirestore.instance.collection('messages').snapshots(),
              builder: (context, snapshot) {
                if (!snapshot.hasData) {
                  return Center(
                    child: CircularProgressIndicator(backgroundColor: Colors.blue),
                  );
                }

                final messages = snapshot.data!.docs;
                return ListView.builder(
                  itemCount: messages.length,
                  itemBuilder: (context, index) {
                    final message = messages[index];
                    final messageText = message['message'];
                    final senderId = message['senderId'];
                    final isMe = signedInUser?.uid == senderId;

                    return MessageReplay(
                      sendMessage: messageText,
                      isMe: isMe,
                    );
                  },
                );
              },
            ),
          ),
          Padding(
            padding: const EdgeInsets.all(8.0),
            child: Row(
              children: [
                Expanded(
                  child: TextField(
                    controller: _messageController,
                    decoration: InputDecoration(
                      hintText: 'Type a message...',
                    ),
                  ),
                ),
                IconButton(
                  icon: Icon(Icons.send),
                  onPressed: () {
                    final message = _messageController.text.trim();
                    final receiverEmail = routeArguments['email'] ?? '';
                    if (message.isNotEmpty && receiverEmail.isNotEmpty) {
                      sendMessage(message, receiverEmail);
                    }
                  },
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

class MessageReplay extends StatelessWidget {
  final String sendMessage;
  final bool isMe;

  const MessageReplay({Key? key, required this.sendMessage, required this.isMe}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(10.0),
      child: Column(
        crossAxisAlignment: isMe ? CrossAxisAlignment.end : CrossAxisAlignment.start,
        children: [
          Material(
            elevation: 5,
            borderRadius: BorderRadius.only(
              topLeft: Radius.circular(30),
              bottomLeft: isMe ? Radius.circular(30) : Radius.circular(0),
              bottomRight: isMe ? Radius.circular(0) : Radius.circular(30),
              topRight: Radius.circular(30),
            ),
            color: isMe ? Colors.blue : Colors.white,
            child: Padding(
              padding: const EdgeInsets.all(12.0),
              child: Text(
                sendMessage,
                style: TextStyle(
                  fontSize: 15,
                  color: isMe ? Colors.white : Colors.black,
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }
}

用户资料页面

import 'dart:io';
import 'package:path/path.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:proguard_86/screens/home_screen.dart'; // Ensure this import is correct

class UserProfile extends StatefulWidget {
  static const String screenRoute = "userProfile";
  final String email;
  const UserProfile({Key? key, required this.email}) : super(key: key); 

  @override
  State<UserProfile> createState() => _UserProfileState();
}

class _UserProfileState extends State<UserProfile> {
  File? file;
  String? url;
  final TextEditingController _nameController = TextEditingController();
  var emailcontroller = TextEditingController();
  final FirebaseAuth _auth = FirebaseAuth.instance;

  Future<void> getImage() async {
    final ImagePicker picker = ImagePicker();
    final XFile? image = await picker.pickImage(source: ImageSource.gallery);
    if (image != null) {
      file = File(image.path);
      var imageName = basename(image.path);
      var refStorage = FirebaseStorage.instance.ref(imageName);
      await refStorage.putFile(file!);
      url = await refStorage.getDownloadURL();
      setState(() {});
    }
  }

  Future<void> saveUserProfile(BuildContext context) async {
    String uid = _auth.currentUser!.uid;
    if (url != null && _nameController.text.isNotEmpty) {
      await FirebaseFirestore.instance
          .collection('signup')
          .doc(widget.email)
          .collection('user_profile')
          .doc(uid) // You can use another identifier if needed
          .set({
        'name': _nameController.text,
        'image_link': url,
      });
      // Navigate to the home screen after saving the profile
      Navigator.pushNamed(context, Homescreen.screenroute); // Ensure the correct reference to HomeScreen
    } else {
      // Handle error, either url or name is not provided
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(
          content: Text("Please provide both name and image."),
          backgroundColor: Colors.red,
        ),
      );
    }
  }

  @override
  Widget build(BuildContext context) {
    //String email=widget.email!;
    return Scaffold(
      backgroundColor: Colors.red,
      appBar: AppBar(
        backgroundColor: Colors.red,
        title: const Text(
          "Profile Info",
          style: TextStyle(color: Colors.white),
        ),
        centerTitle: true,
      ),
      body: SingleChildScrollView(
        padding: const EdgeInsets.symmetric(horizontal: 20),
        child: Column(
          children: [
            const Text(
              "Please provide your name and an optional profile photo",
              style: TextStyle(color: Colors.white, fontSize: 12.5),
              textAlign: TextAlign.center,
            ),
            const SizedBox(height: 40),
            Container(
              padding: const EdgeInsets.all(26),
              decoration: const BoxDecoration(
                shape: BoxShape.circle,
                color: Colors.white,
              ),
              child: const Icon(Icons.add_a_photo_rounded),
            ),
            const SizedBox(height: 40),
            ElevatedButton(
              onPressed: getImage,
              child: const Text("Upload Image"),
            ),
            if (url != null)
              Image.network(
                url!,
                width: 100,
                height: 100,
                fit: BoxFit.fill,
              ),
            Row(
              children: [
                Expanded(
                  child: TextFormField(
                    controller: _nameController,
                    decoration: const InputDecoration(
                      hintText: "Type your name here",
                    ),
                  ),
                ),
                const Icon(
                  Icons.emoji_emotions_outlined,
                  color: Colors.white,
                )
              ],
            ),
            const SizedBox(height: 20),
            ElevatedButton(
              onPressed: () => saveUserProfile(context),
              child: const Text("Save Profile"),
            ),
          ],
        ),
      ),
    );
  }
}

问题:

高效获取数据:是否有更有效的方法来获取用户的个人资料数据并将其显示在AppBar中? 处理错误:我应该如何处理用户数据可能不可用或图像 URL 无效的情况? 更新个人资料:如果用户的个人资料数据发生变化,AppBar 是否会自动更新,还是需要实现额外的逻辑来处理实时更新? UI/UX 最佳实践:是否有我应该考虑在 AppBar 中显示用户个人资料信息的最佳实践?

我需要检索此数据并将其显示在聊天屏幕的 AppBar 中

flutter firebase dart google-cloud-firestore firebase-realtime-database
2个回答
0
投票

您可以将虚拟图像上传到 firebase Firestore,然后在聊天屏幕上您可以通过您在 firebase 上上传的虚拟图像的 url 检查用户图像是否为空。


0
投票

要在 AppBar 中显示用户的个人资料图片和姓名,请创建一行,其中包含用于照片的 CircleAvatar 和用于名称的文本小部件。从数据源(例如 Firebase)检索用户数据并将其传递到 AppBar。这种个性化的触摸改善了用户体验并增强了聊天应用程序的身份。

© www.soinside.com 2019 - 2024. All rights reserved.