我的应用程序使用unicode字符\ u2192在TextView元素中显示右箭头.但是,箭头显示在最底部,但应垂直居中:
但是,如果我使用标准输出打印unicode字符,一切都很好:
public class Main {
public static void main(String[] args) {
System.out.println("A" + Character.toString("\u2192".toCharArray()[0]));
}
}
我如何强制使用右箭头在TextView中居中?我的TextView已经使用了android:gravity="center_vertical|left"
.
更新:我使用的是Android Studio 3.0.1和Android SDK 26. TextView的XML代码:
在代码中填充TextView:
TextView textView = findViewById(R.id.my_text_view);
textView.setText("A" + Character.toString("\u2192".toCharArray()[0]) + "B");
Rapunzel Van..
5
由于Android的Roboto字体似乎不包含箭头字形,因此,如果可能的话,这将导致它显示后备字体中的字符(尽管我找不到此行为的文档)。我猜您的设备上的“后备”箭头出于某种原因位于基线上。
但是,有一个技巧可能会帮助您:您可以包含特殊字符的图像,并将该图像插入输出文本中。
首先,在中添加一个新的Drawable资源文件(ic_arrow.xml
)res/drawable
,然后将其复制粘贴到其中:
现在,我们需要将箭头图像嵌入到您可以在TextView中显示的SpannableString中。我将引导您完成(令人惊讶的很多)代码行,我们需要完成以下操作:
获取Drawable资源,以便我们可以在显示它之前使其尺寸正确。
Drawable arrow = ContextCompat.getDrawable(this, R.drawable.ic_arrow);
根据字体指标确定箭头的大小。
Float ascent = textView.getPaint().getFontMetrics().ascent;
这是负面的(出于原因),因此使其正面。
int h = (int) -ascent;
最后,我们可以设置Drawable的边界以匹配文本大小。
arrow.setBounds(0,0,h,h);
接下来,创建一个使用我们的文本初始化的SpannableString。我只是*
在这里用作占位符,但是它可以是任何字符(或空格)。如果您打算将不同的位与多个箭头图像连接在一起SpannableStringBuilder
,请为此使用a 。
SpannableString stringWithImage = new SpannableString("A*B");
现在,我们终于可以将图像插入到跨度中(使用带有“箭头”图像并与基线对齐的新ImageSpan )。该1
和2
是从零开始的起点和终点指标(告诉在何处插入图像),并SPAN_EXCLUSIVE_EXCLUSIVE
表示
跨度不扩展到包括插入的文本。
stringWithImage.setSpan(new ImageSpan(arrow, DynamicDrawableSpan.ALIGN_BASELINE), 1, 2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
最后,我们可以显示文本(包括自定义箭头图像):
textView.setText(stringWithImage);
总之,代码应如下所示。
TextView textView = findViewById(R.id.my_text_view);
Drawable arrow = ContextCompat.getDrawable(this, R.drawable.ic_arrow);
Float ascent = textView.getPaint().getFontMetrics().ascent;
int h = (int) -ascent;
arrow.setBounds(0,0,h,h);
SpannableString stringWithImage = new SpannableString("A*B");
stringWithImage.setSpan(new ImageSpan(arrow, DynamicDrawableSpan.ALIGN_BASELINE), 1, 2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(stringWithImage);
我希望Android有更好的方法来执行此类操作,但至少可以通过某种方式来完成。生成的TextView应该如下所示:
1> Rapunzel Van..:
由于Android的Roboto字体似乎不包含箭头字形,因此,如果可能的话,这将导致它显示后备字体中的字符(尽管我找不到此行为的文档)。我猜您的设备上的“后备”箭头出于某种原因位于基线上。
但是,有一个技巧可能会帮助您:您可以包含特殊字符的图像,并将该图像插入输出文本中。
首先,在中添加一个新的Drawable资源文件(ic_arrow.xml
)res/drawable
,然后将其复制粘贴到其中:
现在,我们需要将箭头图像嵌入到您可以在TextView中显示的SpannableString中。我将引导您完成(令人惊讶的很多)代码行,我们需要完成以下操作:
获取Drawable资源,以便我们可以在显示它之前使其尺寸正确。
Drawable arrow = ContextCompat.getDrawable(this, R.drawable.ic_arrow);
根据字体指标确定箭头的大小。
Float ascent = textView.getPaint().getFontMetrics().ascent;
这是负面的(出于原因),因此使其正面。
int h = (int) -ascent;
最后,我们可以设置Drawable的边界以匹配文本大小。
arrow.setBounds(0,0,h,h);
接下来,创建一个使用我们的文本初始化的SpannableString。我只是*
在这里用作占位符,但是它可以是任何字符(或空格)。如果您打算将不同的位与多个箭头图像连接在一起SpannableStringBuilder
,请为此使用a 。
SpannableString stringWithImage = new SpannableString("A*B");
现在,我们终于可以将图像插入到跨度中(使用带有“箭头”图像并与基线对齐的新ImageSpan )。该1
和2
是从零开始的起点和终点指标(告诉在何处插入图像),并SPAN_EXCLUSIVE_EXCLUSIVE
表示
跨度不扩展到包括插入的文本。
stringWithImage.setSpan(new ImageSpan(arrow, DynamicDrawableSpan.ALIGN_BASELINE), 1, 2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
最后,我们可以显示文本(包括自定义箭头图像):
textView.setText(stringWithImage);
总之,代码应如下所示。
TextView textView = findViewById(R.id.my_text_view);
Drawable arrow = ContextCompat.getDrawable(this, R.drawable.ic_arrow);
Float ascent = textView.getPaint().getFontMetrics().ascent;
int h = (int) -ascent;
arrow.setBounds(0,0,h,h);
SpannableString stringWithImage = new SpannableString("A*B");
stringWithImage.setSpan(new ImageSpan(arrow, DynamicDrawableSpan.ALIGN_BASELINE), 1, 2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(stringWithImage);
我希望Android有更好的方法来执行此类操作,但至少可以通过某种方式来完成。生成的TextView应该如下所示: