我正在尝试在Android中显示TextView,以使视图中的文字顶部对齐:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Create container layout
FrameLayout layout = new FrameLayout(this);
// Create text label
TextView label = new TextView(this);
label.setTextSize(TypedValue.COMPLEX_UNIT_PX, 25); // 25 pixels tall
label.setGravity(Gravity.TOP + Gravity.CENTER); // Align text top-center
label.setPadding(0, 0, 0, 0); // No padding
Rect bounds = new Rect();
label.getPaint().getTextBounds("gdyl!", 0, 5, bounds); // Measure height
label.setText("good day, world! "+bounds.top+" to "+bounds.bottom);
label.setTextColor (0xFF000000); // Black text
label.setBackgroundColor(0xFF00FFFF); // Blue background
// Position text label
FrameLayout.LayoutParams layoutParams =
new FrameLayout.LayoutParams(300, 25, Gravity.LEFT + Gravity.TOP);
// also 25 pixels tall
layoutParams.setMargins(50, 50, 0, 0);
label.setLayoutParams(layoutParams);
// Compose screen
layout.addView(label);
setContentView(layout);
}
此代码输出以下图像:
需要注意的事项:
如何告诉TextView启动文本顶部的文本?
我对可能的答案有两个限制:
答案 0 :(得分:9)
TextViews在画布上使用抽象类android.text.Layout到draw the text:
canvas.drawText(buf, start, end, x, lbaseline, paint);
垂直偏移lbaseline
计算为线的底部减去字体的下降:
int lbottom = getLineTop(i+1);
int lbaseline = lbottom - getLineDescent(i);
两个被称为函数getLineTop
和getLineDescent
是抽象的,但是可以在BoringLayout中找到一个简单的实现(go figure ... :),它只返回{的值{ {1}}和mBottom
。这些是用init方法计算的,如下所示:
mDesc
这里,if (includepad) {
spacing = metrics.bottom - metrics.top;
} else {
spacing = metrics.descent - metrics.ascent;
}
if (spacingmult != 1 || spacingadd != 0) {
spacing = (int)(spacing * spacingmult + spacingadd + 0.5f);
}
mBottom = spacing;
if (includepad) {
mDesc = spacing + metrics.top;
} else {
mDesc = spacing + metrics.ascent;
}
是一个布尔值,指定文本是否应包含额外的填充以允许延伸超过指定上升的字形。它可以通过TextView的setIncludeFontPadding方法设置(如@ggc指出的那样)。
如果将includepad设置为true(默认值),则会定位文本,其基线由字体指标的top
-field给出。否则,文本的基线取自descent
-field。
因此,从技术上讲,这应该意味着我们需要做的就是关闭IncludeFontPadding,但不幸的是,这会产生以下结果:
原因是字体报告-23.2作为其上升,而边界框报告的顶值为-19。我不知道这是字体中的“bug”还是应该是这样的。不幸的是,FontMetrics没有提供与边界框报告的19相匹配的任何值,即使您尝试以某种方式合并报告的240dpi的屏幕分辨率与72dpi的字体点定义,因此没有“官方”方式解决这个问题。
但是,当然,可用的信息可用于破解解决方案。有两种方法可以做到:
单独使用IncludeFontPadding,即设置为 true :
includepad
即。垂直填充设置为补偿从文本边界和字体度量的最高值报告的y值的差异。结果:
将IncludeFontPadding设置为 false :
double top = label.getPaint().getFontMetrics().top;
label.setPadding(0, (int) (top - bounds.top - 0.5), 0, 0);
即。垂直填充设置为补偿从文本边界和字体度量的上升值报告的y值的差异。结果:
请注意,将IncludeFontPadding设置为 false 并不神奇。 两个版本应该工作。当字体度量的浮点值转换为整数时,它们产生不同结果的原因是舍入错误略有不同。恰好在这种特殊情况下,将IncludeFontPadding设置为 false 会更好看,但对于不同的字体或字体大小,这可能会有所不同。调整顶部填充的计算可能相当容易,以产生与BoringLayout使用的计算相同的精确舍入误差。我还没有这样做,因为我宁愿使用“无错误”的字体,但如果我找到一些时间,我可能会在以后添加它。那么,IncludeFontPadding是否设置为 false 或 true 应该是真的无关紧要。
答案 1 :(得分:1)
如果TextView位于其他布局中,请务必检查它们之间是否有足够的空间。您可以在父视图的底部添加填充,看看是否获得了全文。它对我有用!
示例:在FrameLayout中有一个textView但FrameLayout太小并且正在剪切textView。在FrameLayout中添加填充以查看它是否有效。
修改:更改此行
FrameLayout.LayoutParams layoutParams =
new FrameLayout.LayoutParams(300, 25, Gravity.LEFT + Gravity.TOP);
这一行
FrameLayout.LayoutParams layoutParams =
new FrameLayout.LayoutParams(300, 50, Gravity.LEFT + Gravity.TOP);
这将使框更大,同样地,为文本留出足够的空间。
或添加此行
label.setIncludeFontPadding(false);
这将删除周围的字体填充并让文本被看到。但是在你的情况下唯一不起作用的是它不会完全显示像'g'这样的字母......也许你将不得不改变盒子或文本的大小(如2-3)如果你真的想让它发挥作用。