【问题标题】:How to make Container widget take only the required space in flutter?如何使 Container 小部件在颤动中只占用所需的空间?
【发布时间】:2020-09-09 14:34:08
【问题描述】:

我正在使用 Flutter 开发一个聊天应用程序。在那,我必须创建一个包含消息的聊天屏幕。我希望每个消息容器只占用所需的空间。例如:短消息,短容器宽度和长消息,长容器。目前,无论消息的长度如何,它都会占用Column 容器的全部空间。

附带说明一下,我尝试将消息容器包装在灵活的内部,但它根本不起作用。

这是我的代码:

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 && data.data[chatId] != null) {
                        return buildChatMessagesUI(
                            context, data.data[chatId].messages);
                      } else {
                        return Text("No Data");
                      }
                    },
                  ),
                ),
                buildMessageInputUI(chatId: chatId),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

【问题讨论】:

  • 将 MainAxisSize 列更改为 MainAxisSize.min,它将表现为 wrap_content。让我知道这是否适合您,然后我会发布完整的答案。
  • 不,同样的结果!请帮帮我!
  • 你的意思是它占据了Column 的整个宽度吗?身高在这里应该不是问题。

标签: flutter dart


【解决方案1】:

如果有界,Align 小部件会将其自身调整为传入的约束,并且带有装饰的 Container 会放置在它周围。这意味着装饰将覆盖列的整个宽度。要解决此问题,DecoratedBox(由Container 生成)需要改为Align 的后代。

您可能已经注意到的另一个问题是,如果传入的约束已经有界,LimitedBox 什么也不做。为了收紧现有的界限,您需要在您的Container 中提供constraints(或等效的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,
        ),
      ),
    ),
  );
}

【讨论】:

  • 非常感谢您的努力!上帝保佑你!!
猜你喜欢
  • 1970-01-01
  • 2019-06-02
  • 2020-08-06
  • 2022-12-19
  • 1970-01-01
  • 1970-01-01
  • 2021-10-28
  • 2018-09-17
  • 2021-02-21
相关资源
最近更新 更多