为什么TextView在底部显示unicode右箭头(\ u2192)?

时间:2018-03-16 07:51:56

标签: android unicode textview

我的应用程序使用unicode字符\ u2192在TextView元素中显示右箭头。但是,箭头显示在最底线,但应垂直居中:

enter image description here

但是,如果我使用标准输出打印unicode字符,一切都很好:

public class Main {
  public static void main(String[] args) {
    System.out.println("A" + Character.toString("\u2192".toCharArray()[0]));
  }
}

enter image description here

如何强制使用右箭头在TextView中居中?我的TextView已使用android:gravity="center_vertical|left"

更新:我使用Android Studio 3.0.1和Android SDK 26. TextView的XML代码:

 <TextView
    android:id="@+id/my_text_view"
    android:layout_width="match_parent"
    android:fontFamily="monospace"
    android:gravity="center_vertical|left"
    android:textSize="26sp" />

在代码中填写TextView:

    TextView textView = findViewById(R.id.my_text_view);
    textView.setText("A" + Character.toString("\u2192".toCharArray()[0]) + "B");

3 个答案:

答案 0 :(得分:4)

Android's Roboto font doesn't seem to contain arrow glyphs开始,如果可能的话,这将导致它显示回退字体中的字符(尽管我无法找到此行为的文档)。我猜测&#34;后退&#34;由于某种原因,您设备上的箭头位于基线上。

但是,有一个技巧可以帮助您:您可以包含特殊字符的图像并将图像插入到输出文本中。

首先,在ic_arrow.xml中添加一个新的Drawable资源文件(res/drawable),并将其复制粘贴到其中:

<vector android:alpha="0.78" android:height="24dp"
  android:viewportHeight="24.0" android:viewportWidth="24.0"
  android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
  <path android:fillColor="#FF000000" android:pathData="M3,12L21.5,12"
    android:strokeColor="#000000" android:strokeWidth="1"/>
  <path android:fillColor="#FF000000" android:pathData="M21,12L17,8"
    android:strokeColor="#000000" android:strokeWidth="1"/>
  <path android:fillColor="#FF000000" android:pathData="M21,12L17,16"
    android:strokeColor="#000000" android:strokeWidth="1"/>
</vector>

现在,我们需要将箭头图像嵌入到您可以在TextView中显示的SpannableString中。我将引导您完成我们需要完成的代码(令人惊讶的很多):

  • 获取Drawable资源,以便在显示之前使其大小正确。

    Drawable arrow = ContextCompat.getDrawable(this, R.drawable.ic_arrow);

  • 确定箭头需要的大小based on the font metrics

    Float ascent = textView.getPaint().getFontMetrics().ascent;

  • 这是否定的(for reasons),因此请将其设为正数。

    int h = (int) -ascent;

  • 最后,我们可以设置Drawable的边界以匹配文本 大小

    arrow.setBounds(0,0,h,h);

  • 接下来,创建一个用我们的文本初始化的SpannableString。我在这里只使用*作为占位符,但它可以是任何字符(或空格)。如果您计划将不同位与多个箭头图像连接在一起,请使用SpannableStringBuilder

    SpannableString stringWithImage = new SpannableString("A*B");

  • 现在,我们最终可以将图像插入跨度(使用新的 ImageSpan与我们的&#34;箭头&#34; image,aligned with the baseline)。 12是从零开始和结束的索引(告诉在哪里 插入图像),SPAN_EXCLUSIVE_EXCLUSIVE表示 the span doesn't expand to include inserted text

    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应如下所示:

screenshot

答案 1 :(得分:1)

试试:

SpannableString st = new SpannableString("A" + "\u2192" + "B");
st.setSpan(new RelativeSizeSpan(2f), 1, 2, 0);
textView.setText(st);

我知道但这并没有完全回答。

答案 2 :(得分:0)

尝试使用html实体编码的其他符号。看看这个link,也许你在这里找到更方便的右箭头,但我选择了这个例子:&#10132

String formula = "A &#10132 B";
textView.setText(Html.fromHtml(formula));

这个第三方lib也许适合你