简体   繁体   中英

Flutter align timestamp text on bubble chat message

My chat bubble looks like this:

在此处输入图像描述

I want its timestamp to stick to the right side like the following:

在此处输入图像描述

Here is my code:

   return Align(
      alignment: alignment,
      child: Bubble(
        margin: BubbleEdges.only(
          top: 10,
          left: leftMargin,
          right: rightMargin,
        ),
        color: backgroundColor,
        nip: bubbleNip,
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            content,
            const SizedBox(height: 5),
            Text(timeFormat01(timestamp)),
          ],
        ),
      ),
    );

How do I do that?

What doesn't work?

Using Row mainAxisAlignment: MainAxisAlignment.end or Align alignment: Alignment.centerRight leads to stretching all bubbles to max width.

在此处输入图像描述

Adding crossAxisAlignment: CrossAxisAlignment.end to the Column will align all texts that are smaller than the timestamp text to the right side.

在此处输入图像描述

wrap your timestamp with Align widget like this:

IntrinsicWidth(
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              content,
              SizedBox(height: 5),
              Align(
                alignment: Alignment.centerRight,
                child: Text(timeFormat01(timestamp)),
              ),
            ],
          ),
        )

You can achieve the desired effect by combining IntrinsicWidth and Align on your formatted Bubble widget.

Output:

在此处输入图像描述

Source:

Read the comments for explanation.

void main() => runApp(
      const MaterialApp(
        debugShowCheckedModeBanner: false,
        home: Scaffold(body: SafeArea(child: BubbleApp())),
      ),
    );

class BubbleApp extends StatelessWidget {
  const BubbleApp({super.key});

  @override
  Widget build(BuildContext context) {
    return Align(
      alignment: Alignment.topRight,
      /// [ConstrainedBox] is used to provide the maximum width
      /// of any one chat bubble.
      child: ConstrainedBox(
        /// In this case, let's use 300.0, but
        /// you can use MediaQuery.of(context) and a percentage.
        constraints: const BoxConstraints(maxWidth: 300.0),
        child: Column(
          mainAxisSize: MainAxisSize.min,
          mainAxisAlignment: MainAxisAlignment.end,
          crossAxisAlignment: CrossAxisAlignment.end,
          /// Populate [children] however you manage your state.
          children: const [
            BubbleMessage(
              message:
                  "Lorem ipsum dolor sit amet, consectetur adipiscing elit. "
                  " Aenean eleifend sed purus a tincidunt. Aenean varius erat "
                  " eget justo lacinia.",
            ),
            BubbleMessage(message: "kdo!"),
          ],
        ),
      ),
    );
  }
}

/// This is the wrapper around your [Bubble] class.
class BubbleMessage extends StatelessWidget {
  const BubbleMessage({super.key, required this.message});

  final String message;

  @override
  Widget build(BuildContext context) {
    /// Size the [BubbleMessage] class to the intrinsic width of the child.
    return IntrinsicWidth(
      /// Replace [Card] with your [Bubble] class.
      child: Card(
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,

          /// This ensures that the column height only take up as
          /// much height as needed by the children.
          mainAxisSize: MainAxisSize.min,

          children: [
            /// This is your content.
            Text(message, style: const TextStyle(fontSize: 20.0)),
            const SizedBox(height: 5.0),

            /// This is your formatted time. We align it to the right.
            Align(
              alignment: Alignment.centerRight,
              child: Text(
                DateFormat("hh:mm a").format(DateTime.now()),
                style: const TextStyle(fontSize: 20.0),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

Wrap timestamp text in Row and with mainaxisalignment set to end.

Use crossAxisAlignment: CrossAxisAlignment.end, on Column

 child: Column(
          crossAxisAlignment: CrossAxisAlignment.end,
          children: [
           content,

Another solution is

Row(
    crossAxisAlignment: CrossAxisAlignment.center,
    mainAxisSize: MainAxisSize.min,
    mainAxisAlignment: widget.isMyMessage! ? MainAxisAlignment.end : MainAxisAlignment.start,
    children: [ widget.isMyMessage! == true
                       ? Padding(
                         padding: const EdgeInsets.only(right: 4.0),
                          child: Image.asset(
                                 icRead,
                                 height: 16,
                                 width: 16,
                                ),
                         )
                         : Container(),
                        timeData != null ? Text( timeForChatMsg( timeData ),
                                          style: TextStyle(
                                          fontSize: fontSize12,
              color: widget.isMyMessage! ? Colors.white : Colors.black,
            ),
          )
        : Container(); ,
                        widget.isMyMessage! == false
                            ? Padding(
                                padding: const EdgeInsets.only(left: 4.0),
                                child: Image.asset(
                                  icRead,
                                  color: primaryColor,
                                  height: 16,
                                  width: 16,
                                ),
                              )
                            : Container(),
                      ],
                    )

Using IntrinsicWidth and Align solved my issue.

Here is the result:

return Align(
      alignment: alignment,
      child: Bubble(
        margin: BubbleEdges.only(
          top: 10,
          left: leftMargin,
          right: rightMargin,
        ),
        color: backgroundColor,
        nip: bubbleNip,
        child: IntrinsicWidth( // <--- here
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              content,
              const SizedBox(height: 5),
              Align(
                alignment: Alignment.centerRight, // <--- here
                child: Text(timeFormat01(timestamp)),
              ),
            ],
          ),
        ),
      ),
    );

Read more about IntrinsicWidth use cases and documentation .

Note:

This class is relatively expensive. Avoid using it where possible.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM