我正在尝试在两个“文本”小部件的左侧对齐一个彩色矩形。具体来说,我希望彩色矩形的底部与下部Text的基线对齐,而矩形的顶部与上部Text的字体高度对齐。这是我要达到的目标的模拟: 到目前为止,我的代码:
final TextStyle helloTextStyle = const TextStyle(
fontWeight: FontWeight.w600,
fontSize: 28,
letterSpacing: 0,
wordSpacing: 0,
fontFamily: "DejaVuSansCondensed",
color: Color(0XFF232444),
decoration: TextDecoration.none,
);
final TextStyle everyoneTextStyle = const TextStyle(
fontWeight: FontWeight.w700,
fontSize: 38,
letterSpacing: 0,
fontFamily: "DejaVuSansCondensed",
color: Color(0XFF232444),
decoration: TextDecoration.none,
);
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
decoration: BoxDecoration(
border: Border(
left: BorderSide(
width: 16.0,
color: Colors.red),
),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text("HELLO", style: helloTextStyle),
Text("EVERYONE", style: everyoneTextStyle),
],
),
),
],
)
我该如何将彩色矩形的底部与下部文本的基线对齐,并将矩形的顶部与上部文本的字体高度对齐?
编辑:一种解决方案是确定基线和“文本”小部件的底部之间的距离以及顶盖高度和“文本”小部件的顶部之间的距离。文本小部件似乎没有提供这些值。
答案 0 :(得分:0)
将Row
包装在Container
中,并定义其height
属性:
Container(
height: MediaQuery.of(context).size.height/4 ,
child: Row(
children: <Widget>[
Column(
children: <Widget>[
Container(
width: 16.0,
color: Colors.red,
),
]
),
Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text("HELLO", style: helloTextStyle),
Text("EVERYONE", style: everyoneTextStyle),
]
),
]
),
),
答案 1 :(得分:0)
您不需要像以前一样将Column
用作Container
的子代。这样,它就不会以文本为基准。
一种方法:
double fontSize1 = 38.0;
double fontSize2 = 28.0;
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: IntrinsicHeight(
child: Row(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Padding(
padding: EdgeInsets.only(top:(fontSize2 / 4.5),bottom: (fontSize1 / 4.2)),
child: Container(
decoration: BoxDecoration(
border: Border(
left: BorderSide(
width: 16.0,
color: Colors.red),
),
),
),
),
Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text("HELLO", style: helloTextStyle),
Text("EVERYONE", style: everyoneTextStyle),
],
),
],
),
),
),
);
}
输出:
具有:
double fontSize1 = 68.0;
double fontSize2 = 18.0;
因此填充是立即自动计算的。
答案 2 :(得分:0)
没有Flutter API可以获取文本的确切边界。 Flutter: finding the exact bounds of text涵盖了这一点。就是说,我有一个基于相同讨论的解决方案。
方法是在画布上绘制一个字符(在我的情况下为大写“ I”),然后扫描图像像素以查找字符的边缘。我计算字符和图像边缘之间的像素行,并使用它来设置彩色块上的填充。我的解决方案更加复杂,因为我在一个列中有两个Text小部件,每个Text的大小都不同。
注意:除非您真正关心与字符边缘的精确对齐,否则我不会建议这种解决方案。
布局代码:
IntrinsicHeight(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
FutureBuilder<TopBottomPadding>(
future: _calcPadding(
TextSpan(
text: "I", style: helloTextStyle),
TextSpan(
text: "I", style: everyoneTextStyle),
mediaQueryData.textScaleFactor),
builder: (BuildContext context, tuple) {
return Padding(
padding: EdgeInsets.only(
top: tuple.data.top,
bottom: tuple.data.bottom,
),
child: Container(
decoration: BoxDecoration(
border: Border(
left: BorderSide(
width: 16.0, color: Colors.red),
),
),
),
);
}),
Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text("HELLO", style: helloTextStyle),
Text("EVERYONE", style: everyoneTextStyle),
],
),
],
),
)
生成图像涉及异步调用,因此我已经注册了FutureBuilder小部件。
Future<TopBottomPadding> _calcPadding(final TextSpan topSpan,
final TextSpan bottomSpan, final double textScaleFactor) async {
final topPadding = await _calcTopPadding(topSpan, textScaleFactor);
final bottomPadding = await _calcBottomPadding(bottomSpan, textScaleFactor);
return TopBottomPadding(topPadding, bottomPadding);
}
Future<double> _calcTopPadding(TextSpan span, double textScaleFactor) async {
final int bytesPerPixel = 4;
final imageData =
await _getImageByteData(span, ImageByteFormat.rawRgba, textScaleFactor);
final Size imageSize = imageData.size;
final ByteData byteData = imageData.byteData;
final numRows =
(byteData.lengthInBytes / (bytesPerPixel * imageSize.width)).round();
int foundRow;
/// Scan each pixel from top to bottom keeping track of the row
for (int row = 0; row < numRows && foundRow == null; row++) {
final int rowLength = bytesPerPixel * imageSize.width.round();
final int startRowByteIndex = row * rowLength;
/// Only looking at first byte of each pixel is good enough
for (int byteArrayIndex = startRowByteIndex;
byteArrayIndex < row * rowLength + rowLength;
byteArrayIndex += bytesPerPixel) {
final int byteValue = byteData.getUint8(byteArrayIndex);
/// The background is white so look for a non-white pixel.
if (foundRow == null && byteValue != 0xff) {
foundRow = row;
break;
}
}
}
final double result = foundRow == null ? 0 : foundRow.toDouble();
return result;
}
Future<double> _calcBottomPadding(
final TextSpan span, final textScaleFactor) async {
final int bytesPerPixel = 4;
final imageData =
await _getImageByteData(span, ImageByteFormat.rawRgba, textScaleFactor);
final Size imageSize = imageData.size;
final ByteData byteData = imageData.byteData;
final numRows =
(byteData.lengthInBytes / (bytesPerPixel * imageSize.width)).round();
int foundRow;
/// Scan each pixel from bottom to top keeping track of the row
for (int row = numRows - 1; row >= 0 && foundRow == null; row--) {
final int rowLength = bytesPerPixel * imageSize.width.round();
final int startRowByteIndex = row * rowLength;
/// Only looking at first byte of each pixel is good enough
for (int byteArrayIndex = startRowByteIndex;
byteArrayIndex < row * rowLength + rowLength;
byteArrayIndex += bytesPerPixel) {
final int byteValue = byteData.getUint8(byteArrayIndex);
/// The background is white so look for a non-white pixel.
if (foundRow == null && byteValue != 0xff) {
foundRow = row;
break;
}
}
}
final double foundRowIndex = foundRow == null ? 0 : foundRow.toDouble();
final int heightAsZeroBasedIndex = imageSize.height.round() - 1;
final double paddingValue = heightAsZeroBasedIndex - foundRowIndex;
return paddingValue;
}
Future<ImageData> _getImageByteData(final TextSpan span,
final ImageByteFormat byteFormat, final double textScaleFactor) async {
final painter = TextPainter(
text: span,
textDirection: TextDirection.ltr,
textScaleFactor: textScaleFactor);
painter.layout();
final imageData = ImageData();
imageData.size = Size(painter.width, painter.height);
final recorder = PictureRecorder();
final screen = Offset.zero & imageData.size;
final canvas = Canvas(recorder);
drawBackground(canvas, screen);
painter.paint(canvas, Offset.zero);
final picture = recorder.endRecording();
final image =
await picture.toImage(screen.width.round(), screen.height.round());
final ByteData byteData = await image.toByteData(format: byteFormat);
imageData.byteData = byteData;
return imageData;
}
void drawBackground(final Canvas canvas, final Rect screen) {
canvas.drawRect(
screen,
Paint()
..color = Colors.white
..style = PaintingStyle.fill);
}
class TopBottomPadding {
double top;
double bottom;
TopBottomPadding(this.top, this.bottom);
}
class ImageData {
ByteData byteData;
Size size;
}
此解决方案适用于任何屏幕密度,字体大小或文本比例因子。