Java Android TextView中真正的顶部对齐文本
我试图在Android中显示一个文本,以便视图中的文本与上对齐:Java Android TextView中真正的顶部对齐文本,java,android,textview,vertical-alignment,Java,Android,Textview,Vertical Alignment,我试图在Android中显示一个文本,以便视图中的文本与上对齐: @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Create container layout FrameLayout layout = new FrameLayout(this); // Create text label Text
@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);
}
此代码输出以下图像:
注意事项:
- 蓝色框有25像素高,就像要求的那样
- 文本边界也按要求报告为25像素高(6-(-19)=25)
- 文本不从标签顶部开始,但其上方有一些填充,忽略setPadding()
- 这将导致文本被剪裁在底部,即使从技术上讲,该框足够高
- 不过,我确实需要保持文本顶部对齐,因此,如果有一些技巧需要底部对齐或垂直居中,我就不能使用它,因为我有一些场景中文本视图比需要的高
- 我是一个兼容性怪胎,所以如果可能的话,我想坚持使用早期Android API中提供的调用(最好是1,但绝对不高于7)
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);
这条线
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);
这将使框变大,同样,也会留出足够的空间来显示文本
或添加此行
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)。使用抽象类在画布上:
垂直偏移量lbbaseline
计算为行底减去字体下降:
两个被调用的函数
getLineTop
和getLineDescent
是抽象的,但是可以在(见图…:)中找到一个简单的实现,它只返回MBOTOM
和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;
}
此处,includepad
是一个布尔值,指定文本是否应包含额外的填充,以允许延伸超过指定上升的图示符。它可以通过TextView的方法进行设置(正如@ggc所指出的)
如果includepad设置为true(默认值),则文本的定位基线由字体的度量标准的值给定。否则,文本的基线将取自。
因此,从技术上讲,这意味着我们需要做的就是关闭IncludeFontPadding,但不幸的是,这会产生以下结果:
这样做的原因是字体的升幅报告为-23.2,而边界框报告的最大值为-19。我不知道这是字体中的“bug”还是应该是这样的。不幸的是,FontMetrics没有提供任何与边界框报告的19相匹配的值,即使您试图以某种方式合并报告的屏幕分辨率240dpi与字体点定义72dpi,因此没有“官方”方法来解决此问题
但是,当然,可用的信息可以用来破解解决方案。有两种方法可以做到这一点:
- 将IncludeFontPadding单独保留,即设置为true: i、 e.设置垂直填充以补偿从文本边界报告的y值与字体度量的顶部值之间的差异。结果:
- IncludeFontPadding设置为false时: i、 e.设置垂直填充以补偿从文本边界报告的y值与字体度量的上升值之间的差异。结果:
请注意,将IncludeFontPadding设置为false并没有什么神奇之处这两个版本都应该可以使用。它们产生不同结果的原因是字体度量的浮点值转换为整数时的舍入误差略有不同。碰巧在这种特殊情况下,IncludeFontPadding设置为false会更好,但对于不同的字体或字体大小,这可能会有所不同。调整顶部填充的计算可能相当容易,以产生与BoringLayout使用的计算相同的精确舍入误差。我还没有这样做,因为我宁愿使用“无bug”字体,但如果我有时间,我可能会在以后添加它。那么,IncludeFontPadding是设置为false还是true应该是无关紧要的。?我不确定我在听你的回答。。。标签没有被任何其他元素遮挡,因为您可以看到我设置的25像素的全高。。。这只是因为它将文本放置在它的内部,使其与标签不匹配。(参见示例代码)但您至少尝试过我的答案吗?我告诉过你,它对我有用,只是试一下不会有什么坏处。当然,我可以把标签放大,但这只能解决这个具体问题,我需要放大多少取决于确切的字体、大小等等。因此,虽然你的答案肯定会修正我发布的示例,但我希望找到一种方法,通过去掉文本上方的填充物,使文本只适合它应该需要的大小。例如,你的解决方案会使蓝盒变大,这不是我在设计中想要的。好吧,我终于得到了你想要的。您必须添加以下内容:label.setIncludeFontPadding(false);这将删除周围的字体paddi