问题描述
正如我在之前关于该主题的帖子 (Multi-line flutter text field occupies all of Flexible space with ugly right padding) 中提到的,我有点完美主义者。不幸的是,我的 Flutter layout-fu 没有我的野心那么强大。我正在创建一个消息传递应用程序,我正在向消息框添加时间戳。到目前为止我的代码(也感谢这个答案:Complex alignment of a sub widget based on wrapping text like in the Telegram chat messenger)是这样的:
创建一行的代码:
Widget getAppUserMessageRow() {
return Row(
crossAxisAlignment: CrossAxisAlignment.center,mainAxisAlignment: MainAxisAlignment.end,children: <Widget>[
SizedBox(width: AppState.i.chatItemUserLeftInset),Flexible(
fit: FlexFit.loose,child: message.cm.messageType.getMessageWidget(message),),],);
}
创建消息框本身的代码:
Widget build(BuildContext context) {
bool isFromAppUser = message.cm.isFromAppUser(AppState.i.activeUserId);
return Container(
padding: EdgeInsets.symmetric(
vertical: AppState.i.chatItemmessageVerticalInset),child:
Container(
decoration: Boxdecoration(
color: isFromAppUser ? AppState.i.chatItemUserMessageBackgroundColour : Colors.white,//.withOpacity(!message.isFromAppUser ? 0.1 : 0.8),borderRadius: BorderRadius.only(
topLeft: Radius.circular(isFromAppUser ? AppState.i.chatItemmessageBorderRadius : 0),topRight: Radius.circular(isFromAppUser ? 0 : AppState.i.chatItemmessageBorderRadius),bottomright: Radius.circular(isFromAppUser ? AppState.i.chatItemmessageCurvedBorderRadius : AppState.i.chatItemmessageBorderRadius),bottomLeft: Radius.circular(isFromAppUser ? AppState.i.chatItemmessageBorderRadius : AppState.i.chatItemmessageCurvedBorderRadius),BoxShadow: [
BoxShadow(
color: AppState.i.chatItemmessageBoxShadowColour,spreadRadius: AppState.i.chatItemmessageBoxShadowSpreadRadius,blurRadius: AppState.i.chatItemmessageBoxShadowBlurRadius,offset: AppState.i.chatItemmessageBoxShadowOffset,// changes position of shadow
),padding: EdgeInsets.symmetric(
vertical: AppState.i.chatItemmessageVerInset,horizontal: AppState.i.chatItemmessageHorInset),child: Stack(
children: [
Text(
// WTF? This calculates enough space for the message receipt time to wrap
message.cm.messageText + (isFromAppUser ? ' \u202F' : ' \u202F'),style: TextStyle(
fontSize: AppState.i.chatItemmessageTextFontSize,color:
isFromAppUser ? AppState.i.chatItemmessageUserTextFontColour : AppState.i.chatItemmessageOtherUserTextFontColour,textWidthBasis: TextWidthBasis.longestLine,// This Positioned item creates the message timestamp in the area gained by adding the spaces above,assuming the spaces forced
// The text field into adding an extra line.
Positioned(
width: 60,height: 15,right: 0,bottom: -2,child: Row(
mainAxisSize: MainAxisSize.min,children: <Widget>[
Text(
DateFormat.Hm().format(message.cm.messagedisplayTime(AppState.i.activeUserId)),style: TextStyle(
fontSize: AppState.i.chatItemmessageTimeFontSize,color: isFromAppUser ? AppState.i.chatItemmessageUserTimeFontColour : AppState.i.chatItemmessageOtherUserTimeFontColour,textAlign: TextAlign.right,!isFromAppUser ? Container() :
Padding(
padding: EdgeInsets.only(left: AppState.i.chatItemmessageReceiptLeftInset),child: message.cm.getReadReceiptIcon()
)
],)
);
}
这里有一些好的和坏的例子 - 查看坏例子的右侧填充。时间戳应该与上面的文本更右对齐:
还有更多:
添加空格 + 一个不可打印的字符来为日期时间戳 + 阅读回执组合腾出空间是一个天才的把戏,但有一个缺点。当文本接近时间戳将占用的空间时,它会推出正确的对齐方式。因此,在上述某些情况下,盒子会占用不必要的空间。
那么,这是否可以修复,或者可以使用不同的布局来实现我正在寻找的效果?我不能使用太多计算量的东西,因为现在滚动长列表时性能相当不错。
为了让这更具体一些,一些“固定”的例子。
解决方法
我觉得你可以试试这个:
- 计算/模拟文本并检查消息是否与时间戳重叠。
- 如果重叠,请添加
Math.max
以更改行。否则,返回原来的。
您需要以下东西:
-
\n
:文本小部件上方的 BoxConstraint -
LayoutBuilder
:模拟布局(还需要TextPainter
、TextStyle
否则可能会影响布局结果)
代码如下:
textWidthBasis