为什么TextView在底行显示Unicode右箭头(\ u2192)? [英] Why is TextView showing the unicode right arrow (\u2192) at the bottom line?

查看:70
本文介绍了为什么TextView在底行显示Unicode右箭头(\ u2192)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的应用程序使用Unicode字符\ u2192在TextView元素内显示向右箭头.但是,箭头显示在最底端,但应垂直居中:

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

 公共类Main {公共静态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 SDK26.TextView的XML代码:

 < TextViewandroid: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"); 

解决方案

由于

My application uses the unicode character \u2192 to display a right arrow within a TextView element. However, the arrow is shown at the very bottom line, but should be centered vertically:

However, if I print the unicode character using the standard output, everything is fine:

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

How I can enforce the right arrow to be centered in the TextView, too? My TextView already uses android:gravity="center_vertical|left".

Update: I use Android Studio 3.0.1 and Android SDK 26. The XML code of the TextView:

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

Filling the TextView in the code:

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

解决方案

Since Android's Roboto font doesn't seem to contain arrow glyphs, this would cause it to display a character from a fallback font if possible (though I couldn't find the documentation of this behavior). I'm guessing that the "fallback" arrow on your device is lying on the baseline for some reason.

However, there's a trick that might help you: You can include an image of the special character and insert the image into your output text.

First, add a new Drawable resource file (ic_arrow.xml) in res/drawable, and copy-paste this into it:

<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>

Now, we'll need to embed the arrow image into a SpannableString that you can display in your TextView. I'll walk you through the (surprisingly many) lines of code that we'll need to accomplish this:

  • Get the Drawable resource so that we can make it the correct size before displaying it.

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

  • Figure out what size the arrow needs to be, based on the font metrics.

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

  • This is negative (for reasons), so make it positive.

    int h = (int) -ascent;

  • Finally, we can set the bounds of the Drawable to match the text size.

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

  • Next, create a SpannableString initialized with our text. I just used * for a placeholder here, but it could be any character (or a blank space). If you're planning to concatenate different bits together along with multiple arrow images, use a SpannableStringBuilder for this.

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

  • Now, we can finally insert the image into the span (using a new ImageSpan with our "arrow" image, aligned with the baseline). The 1 and 2 are zero-based start and end indices (telling where to insert the image), and SPAN_EXCLUSIVE_EXCLUSIVE indicates that the span doesn't expand to include inserted text.

    stringWithImage.setSpan(new ImageSpan(arrow, DynamicDrawableSpan.ALIGN_BASELINE), 1, 2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

  • Finally, we can display the text (including the custom arrow image):

    textView.setText(stringWithImage);

Altogether, the code should look like this.

    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);

I wish Android had a better way to do this sort of thing, but at least it can be done somehow. The resulting TextView should look like this:

这篇关于为什么TextView在底行显示Unicode右箭头(\ u2192)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆