【问题标题】:How to create vertically aligned superscript and subscript in TextView如何在 TextView 中创建垂直对齐的上标和下标
【发布时间】:2014-07-22 07:49:11
【问题描述】:

在下图示例中:

如何使上标和下标数字对齐以生成如下所示的通用科学记数法

TextView?如果有使用SpannableReplacementSpan 的方法,我希望看到一个工作示例。谢谢。

【问题讨论】:

  • 所以...您希望它们水平对齐!
  • ...击败我...但现在你明白了!
  • 好的,我唯一的(可怕的)想法是......将 2 个 TextViews 放在另一个上,并在那个上打印上标或下标字符,以便它可以占据相同的速度子/上标字符。您必须将相同的文本写两次,以使两个文本“完美”(或几乎)重叠
  • 或者(这个想法比以前的想法 10:1)... 制作自定义视图并自己绘制文本。然后你必须解析 sub / sup 标签。

标签: android textview subscript superscript


【解决方案1】:

如果您只需要下标和上标,请使用 SubscriptSpannable 和 SuperscriptSpannable。如果您出于某种原因不喜欢它们的绘制方式,您可以随时自定义 spannable 并自己绘制。

【讨论】:

  • 那么您可能需要使用自定义 Spannable。它将允许您直接接管 spannable 的绘图。你可以在这里看到一个例子:stackoverflow.com/questions/6612316/…
  • 恐怕我对此一无所知。你能提供一个具体的例子吗?我搜索了 SpannedStrings 的所有示例和教程,但没有一个是这样做的..
  • 我并不感到惊讶,大多数开发人员甚至都不知道 spannables 的存在。创建一个自定义的可能是 Android 中最罕见的事情。
  • @GabeSechan 实际上不是 Spannable 而是 span,在本例中为 ReplacementSpan
  • @pskink 你完全正确,我的错。就像我说的,Android 上最难得的事情之一 :)
【解决方案2】:

将此代码用于解决方案....

TextView txt = (TextView)findViewById(R.id.txt_label); txt.setText(Html.fromHtml("<sup>9</sup><sub>4</sub>Be"));

【讨论】:

    【解决方案3】:

    您可能想尝试这样的事情。

    它基本上是一个ReplacementSpan,它将应用它的文本分成两部分,然后在画布上绘制它们。尺寸因子和 y 平移是经过精心挑选的。我希望它是有用的(或者至少你或其他人可以在它的基础上发展)。

    public class SuperSubSpan extends ReplacementSpan
    {
        @Override
        public int getSize(Paint paint, CharSequence text, int start, int end, FontMetricsInt fm)
        {
            text = text.subSequence(start, end);
            String[] parts = text.toString().split(",");
    
            Paint p = getSuperSubPaint(paint);
            return (int) Math.max(p.measureText(parts[0]), p.measureText(parts[1]));
        }
    
        private static TextPaint getSuperSubPaint(Paint src)
        {
            TextPaint paint = new TextPaint(src);
            paint.setTextSize(src.getTextSize() / 2.5f);
            return paint;
        }
    
        @Override
        public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint paint)
        {
            text = text.subSequence(start, end);
            String[] parts = text.toString().split(",");
    
            Paint p = getSuperSubPaint(paint);
    
            float width1 = p.measureText(parts[0]);
            float width2 = p.measureText(parts[1]);
            float maxWidth = Math.max(width1, width2);
    
            canvas.drawText(parts[0], x + (maxWidth - width1), y - (bottom - top) / 3f, p);
            canvas.drawText(parts[1], x + (maxWidth - width2), y + (bottom - top) / 10f, p);
        }
    }
    

    然后将其用作:

    Spannable str = new SpannableString("9,4Be -> 2000,127Jo");
    str.setSpan(new SuperSubSpan(), 0, 3, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
    str.setSpan(new SuperSubSpan(), 9, 17, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
    mTextView.setText(str);
    

    产生以下结果:

    更好的解决方案是为这些字符串使用特殊格式(例如"{9,4}Be -&gt; {2000,127}Jo")并使用正则表达式处理字符串并添加相应的SuperSubSpans,这样您就不需要手动执行此操作.但实际的 Span 部分或多或少是相同的。

    【讨论】:

      【解决方案4】:

      你可以跟着我一步一步来。你可以从中得到帮助。比如

      MainActivity.java

      public class MainActivity extends Activity {
      
          @Override
          protected void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_main);
              TextView txtView = (TextView) findViewById(R.id.textView1);
              TextView water = (TextView) findViewById(R.id.textView2);
              txtView.setText(Html.fromHtml("a" + "<sup>" + "2" + "</sup>" + " + "
                      + "b" + "<sup>" + "2" + "</sup>" + "=" + "(" + "a-b" + ")"
                      + "<sup>" + "2" + "</sup>" + " + " + "2ab"));
      
              water.setText(Html.fromHtml("H" + "<sub>" + "2" + "</sub>" + "O"));
      
          }
      
      }
      

      这里sup府上标和子府下标。

      并且 activity_main.xml

      <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
          xmlns:tools="http://schemas.android.com/tools"
          android:id="@+id/container"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          android:orientation="vertical"
          android:gravity="center"
          tools:context="com.example.textview.MainActivity" >
      
          <TextView
              android:id="@+id/textView1"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:layout_weight="1"
              android:text="TextView" />
      
          <TextView
              android:id="@+id/textView2"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:layout_weight="1"
              android:text="TextView" />
      
      </LinearLayout>
      

      祝你好运!

      【讨论】:

        【解决方案5】:

        我不会尝试弯曲 TextView 小部件来做到这一点。相反,您可以轻松地制作具有 2 种不同颜色的自己的小部件:一种用于元素名称(大字体),另一种用于数字(小号,斜体)。

        您将制作适当的设置器并单独存储每个属性,而不是存储大的跨度或字符串。

        您还可以轻松地水平和垂直对齐(元素名称顶部和底部的数字)

        要计算宽度,您可以使用一个属性来调整数字和元素名称之间的填充。然后您可以使用每个绘制来计算文本宽度并添加所有这些(不要忘记添加小部件填充值)。

        【讨论】:

          【解决方案6】:

          你也可以参考我的答案link 只需使用SpannableString 即可解决您的问题。

           SpannableString styledString = new SpannableString("9-10th STD");
           styledString.setSpan(new SuperscriptSpan(), 4, 6, 0);
           textView.setText(styledString);
          

          并把你的android:textAllCaps="false"

          【讨论】:

            猜你喜欢
            • 2012-07-05
            • 1970-01-01
            • 2014-11-03
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-11-23
            • 1970-01-01
            相关资源
            最近更新 更多