Как сделать, чтобы виджет контейнера занимал только необходимое место в flutter?

#flutter #dart

#flutter #dart

Вопрос:

Я работаю над приложением чата с использованием flutter. Для этого мне нужно создать экран чата, содержащий сообщения. Я хочу, чтобы каждый контейнер сообщений занимал только необходимое пространство. Например: короткое сообщение, короткая ширина контейнера и длинное сообщение, длинный контейнер. В настоящее время он занимает все пространство Column контейнера независимо от длины сообщения.

В качестве примечания я попытался обернуть контейнер сообщений внутри flexible, но это вообще не сработало.

Вот мой код:

 import 'package:flutter/material.dart';
import 'package:memomessenger/Services/Chats.dart';
import 'package:memomessenger/Services/Constants.dart';
import 'package:memomessenger/Services/Types/Chat.dart';
import 'package:memomessenger/Services/Types/ChatsActivity.dart';
import 'package:memomessenger/Services/User.dart';

Widget buildMessageWidget(
    BuildContext context, Message message, String currentUserId) {
  final bool isFromCurrentUser = message.senderId == currentUserId;
  return LimitedBox(
    maxWidth: MediaQuery.of(context).size.width * .75,
    child: Container(
      margin: EdgeInsets.symmetric(vertical: 2),
      padding: EdgeInsets.symmetric(vertical: 10, horizontal: 10),
      decoration: BoxDecoration(
        borderRadius: BorderRadius.only(
          topRight: Radius.circular(
            isFromCurrentUser ? 0 : messageBorderRadius,
          ),
          topLeft: Radius.circular(
            isFromCurrentUser ? messageBorderRadius : 0,
          ),
          bottomLeft: Radius.circular(messageBorderRadius),
          bottomRight: Radius.circular(messageBorderRadius),
        ),
        color: isFromCurrentUser ? themeAccentColor[500] : Colors.cyan,
      ),
      child: Align(
        alignment:
            isFromCurrentUser ? Alignment.centerRight : Alignment.centerLeft,
        child: Text(
          message.text,
          style: TextStyle(
            color: isFromCurrentUser ? Colors.white : Colors.black,
          ),
        ),
      ),
    ),
  );
}

Widget buildChatMessagesUI(BuildContext context, List<Message> messages) {
  final String currentUserId = currentUser.value.id;
  return SingleChildScrollView(
    child: Column(
      verticalDirection: VerticalDirection.up,
      children: messages.reversed.map((Message message) {
        return buildMessageWidget(context, message, currentUserId);
      }).toList(),
    ),
  );
}

Widget buildMessageInputUI({@required String chatId}) {
  final String currentUserId = currentUser.value.id;
  return TextFormField(
    decoration: const InputDecoration(
      hintText: 'Enter your email',
    ),
    onChanged: (String message) {
      sendMessage(chatId, Message(text: message, senderId: currentUserId));
    },
    validator: (value) {
      if (value.isEmpty) {
        return 'Please enter some text';
      }
      return null;
    },
    autofocus: true,
    autocorrect: true,
    keyboardType: TextInputType.multiline,
  );
}

class ChatActivity extends StatelessWidget {
  final String chatId;

  ChatActivity({@required this.chatId});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: SafeArea(
          child: Container(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Expanded(
                  child: StreamBuilder<Map<String, Chat>>(
                    stream: chatActivityChatList,
                    initialData: {},
                    builder: (BuildContext context,
                        AsyncSnapshot<Map<String, Chat>> data) {
                      if (data.hasData amp;amp; data.data[chatId] != null) {
                        return buildChatMessagesUI(
                            context, data.data[chatId].messages);
                      } else {
                        return Text("No Data");
                      }
                    },
                  ),
                ),
                buildMessageInputUI(chatId: chatId),
              ],
            ),
          ),
        ),
      ),
    );
  }
}
  

Комментарии:

1. Измените столбец MainAxisSize на MainAxisSize.min, который будет вести себя как wrap_content . Дайте мне знать, если это сработает для вас, я опубликую полный ответ.

2. Нет, тот же результат! Пожалуйста, помогите мне!

3. Вы имеете в виду, что он занимает всю ширину Column ? Высота здесь не должна быть проблемой.

4. i.imgur.com/D35N68m.jpeg это результат

Ответ №1:

Align Размер виджета соответствует его входящим ограничениям, если он ограничен, и ваш Container с украшением размещается вокруг него. Это означает, что оформление будет охватывать всю ширину столбца. Чтобы исправить это, DecoratedBox (созданный Container ) должен быть потомком Align вместо этого.

Другая проблема, которую вы, возможно, заметили, заключается в том, что LimitedBox ничего не делает, если входящее ограничение уже ограничено. Чтобы ужесточить существующую привязку, вам нужно будет предоставить constraints в вашем Container (или, что эквивалентно, ConstrainedBox виджете). FractionallySizedBox также может стоить рассмотреть.

 Widget buildMessageWidget(
    BuildContext context, Message message, String currentUserId) {
  final bool isFromCurrentUser = message.senderId == currentUserId;
  return Align(
    alignment:
      isFromCurrentUser ? Alignment.centerRight : Alignment.centerLeft,
    child: Container(
      margin: EdgeInsets.symmetric(vertical: 2),
      padding: EdgeInsets.symmetric(vertical: 10, horizontal: 10),
      constraints: BoxConstraints(
        maxWidth: MediaQuery.of(context).size.width * .75
      ),
      decoration: BoxDecoration(
        borderRadius: BorderRadius.only(
          topRight: Radius.circular(
            isFromCurrentUser ? 0 : messageBorderRadius,
          ),
          topLeft: Radius.circular(
            isFromCurrentUser ? messageBorderRadius : 0,
          ),
          bottomLeft: Radius.circular(messageBorderRadius),
          bottomRight: Radius.circular(messageBorderRadius),
        ),
        color: isFromCurrentUser ? themeAccentColor[500] : Colors.cyan,
      ),
      child: Text(
        message.text,
        style: TextStyle(
          color: isFromCurrentUser ? Colors.white : Colors.black,
        ),
      ),
    ),
  );
}
  

Комментарии:

1. Большое вам спасибо за ваши усилия! Да благословит вас Бог!!