gpt4 book ai didi

android - 如何使 ImageSpan 按基线对齐

转载 作者:搜寻专家 更新时间:2023-11-01 07:42:21 26 4
gpt4 key购买 nike

问题:为什么 ImageSpan ALIGN_BASELINE 没有与基线准确对齐?如何解决此对齐问题?

在我的 Activity 中,我创建了一个 SpannableString 并将部分字符串替换为 ImageSpanImageSpan 使用 24x24 像素的纯黑色 png 图像并设置为 ALIGN_BASELINE

public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

TextView myTextView = findViewById(R.id.myTextView);
SpannableString ss = new SpannableString("Hello world!");

Drawable d = ContextCompat.getDrawable(this, R.drawable.box);
d.setBounds(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());
ImageSpan imageSpan = new ImageSpan(d, ImageSpan.ALIGN_BASELINE);
ss.setSpan(imageSpan, 2, 5, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);

myTextView.setText(ss);
}
}

我的布局中有两个 View :TextView 和一个用于显示基线的View

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">

<TextView
android:id="@+id/myTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#ff9800"
android:textSize="48sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<View
android:layout_width="match_parent"
android:layout_height="1px"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBaseline_toBaselineOf="@id/myTextView"
android:background="#de4caf50"/>

</android.support.constraint.ConstraintLayout>

如您所见,该行与 TextView 的基线正确对齐,但 ImageSpan 略低于基线。

enter image description here

最佳答案

那是错的。自 ALIGN_BASELINE 以来,可绘制对象的垂直放置已关闭定义如下:

A constant indicating that the bottom of this span should be aligned with the baseline of the surrounding text.

这显然不会发生。请参阅本文末尾的问题。我建议使用以下方法进行修复:

// Override draw() to place the drawable correctly when ALIGN_BASELINE.
ImageSpan imageSpan = new ImageSpan(d, ImageSpan.ALIGN_BASELINE) {
public void draw(Canvas canvas, CharSequence text, int start,
int end, float x, int top, int y, int bottom,
@NonNull Paint paint) {
if (mVerticalAlignment != ALIGN_BASELINE) {
super.draw(canvas, text, start, end, x, top, y, bottom, paint);
return;
}
Drawable b = getDrawable();
canvas.save();
// If we set transY = 0, then the drawable will be drawn at the top of the text.
// y is the the distance from the baseline to the top of the text, so
// transY = y will draw the top of the drawable on the baseline. We want the // bottom of the drawable on the baseline, so we subtract the height
// of the drawable.
int transY = y - b.getBounds().bottom;
canvas.translate(x, transY);
b.draw(canvas);

canvas.restore();
}
};

此代码生成以下图像,我认为它是正确的。

enter image description here


为什么框没有画在基线上?

这是从 DynamicDrawableSpan#draw() 中绘制框的来源:

public void draw(@NonNull Canvas canvas, CharSequence text,
@IntRange(from = 0) int start, @IntRange(from = 0) int end, float x,
int top, int y, int bottom, @NonNull Paint paint) {
Drawable b = getCachedDrawable();
canvas.save();
int transY = bottom - b.getBounds().bottom;
if (mVerticalAlignment == ALIGN_BASELINE) {
transY -= paint.getFontMetricsInt().descent;
}
canvas.translate(x, transY);
b.draw(canvas);
canvas.restore();
}

以及 DynamicDrawableSpan#draw() 的文档.我们感兴趣的 draw() 的唯一参数是 bottom:

bottom int: Bottom of the line.

对于解决方案代码和使用的模拟器,transYDynamicDrawableSpan 计算为94,即框将从顶部开始绘制94 像素。 top 为 178,而 baseline 定义为零,因此 178 - 94 = 84 像素是框的高度或 b.getBounds().bottom。这检查出来了。

在同一模拟器的 DynamicDrawableSpan#draw() 中,底部 = 224,而可绘制对象的高度仍为 84,如上所示。为什么底部是224?这是字体的行高。

transY 现在计算为 224 - 84 = 140 像素。这会将框的底部放在该行的底部但低于基线。

再做一个调整:

transY -= paint.getFontMetricsInt().descent;

在测试中,paint.getFontMetricsInt().descent 为 41,因此 transY 现在变为 99。由于 94 是正确答案,因此 99 将框放置五个像素太低了,这就是您所看到的。

参见 Android 101: Typography用于描述 Android 字体指标。

关于android - 如何使 ImageSpan 按基线对齐,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53541301/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com