首页 文章

是否可以在TextView中包含多个样式?

提问于
浏览
510

是否可以为TextView中的不同文本设置多个样式?

例如,我将文本设置如下:

tv.setText(line1 + "\n" + line2 + "\n" + word1 + "\t" + word2 + "\t" + word3);

是否可以为每个文本元素设置不同的样式?例如,line1粗体,word1斜体等

开发人员指南的Common Tasks and How to Do Them in Android包括Selecting, Highlighting, or Styling Portions of Text

//获取我们的EditText对象 .
EditText vw =(EditText)findViewById(R.id.text);

//设置EditText的文本 .
vw.setText(“斜体,突出显示,粗体 . ”);

//如果这只是一个TextView,我们可以这样做:
// vw.setText(“斜体,突出显示,粗体 . ”,TextView.BufferType.SPANNABLE);
//强制它使用Spannable存储,以便附加样式 .
//或者我们可以在XML中指定它 .

//获取EditText的内部文本存储
Spannable str = vw.getText();

//创建我们的span部分,并为每个部分指定一种格式 .
str.setSpan(new StyleSpan(android.graphics.Typeface.ITALIC),0,7,Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
str.setSpan(new BackgroundColorSpan(0xFFFFFF00),8,19,Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
str.setSpan(new StyleSpan(android.graphics.Typeface.BOLD),21,str.length() - 1,Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

但是在文本中使用了明确的位置编号 . 有更清洁的方法吗?

17 回答

  • 0

    如果你不想使用html,你可以创建一个styles.xml并像这样使用它:

    TextView tv = (TextView) findViewById(R.id.textview);
    SpannableString text = new SpannableString(myString);
    
    text.setSpan(new TextAppearanceSpan(getContext(), R.style.myStyle), 0, 5, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
    text.setSpan(new TextAppearanceSpan(getContext(), R.style.myNextStyle), 6, 10, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
    
    tv.setText(text, TextView.BufferType.SPANNABLE);
    
  • 681

    如果有人想知道如何做到这一点,这是一种方式:(再次感谢马克!)

    mBox = new TextView(context);
    mBox.setText(Html.fromHtml("<b>" + title + "</b>" +  "
    " + "<small>" + description + "</small>" + "
    " + "<small>" + DateAdded + "</small>"));

    有关此方法支持的非官方标记列表,请参阅this link或此问题:Which HTML tags are supported by Android TextView?

  • 41

    Spanny使SpannableString更易于使用 .

    Spanny spanny = new Spanny("Underline text", new UnderlineSpan())
                    .append("\nRed text", new ForegroundColorSpan(Color.RED))
                    .append("\nPlain text");
    textView.setText(spanny)
    
  • 6

    实际上,除了Html对象之外,您还可以使用Spannable类型,例如TextAppearanceSpan或TypefaceSpan和SpannableString togather . Html类也使用这些机制 . 但是使用Spannable类型,您可以获得更多自由 .

  • 6

    如上所述,使用 TextView.setText(Html.fromHtml(String))

    并在Html格式的字符串中使用这些标记:

    <a href="...">
    <b>
    <big>
    <blockquote>
    <br>
    <cite>
    <dfn>
    <div align="...">
    <em>
    <font size="..." color="..." face="...">
    <h1>
    <h2>
    <h3>
    <h4>
    <h5>
    <h6>
    <i>
    <img src="...">
    <p>
    <small>
    <strike>
    <strong>
    <sub>
    <sup>
    <tt>
    <u>
    

    http://commonsware.com/blog/Android/2010/05/26/html-tags-supported-by-textview.html

  • 208

    It might be as simple as leveraging the String's length() method:

    • 将Strings XML文件中的文本字符串拆分为多个子字符串(从Android的角度来看是一个单独的字符串),因为你需要不同的样式,所以它可能像: str1, str2, str3 (如你的情况),加入时一起是你使用的整个单个字符串 .

    • 然后简单地按照“Span”方法,就像你提供代码一样 - 但不是单个字符串,而是将所有子字符串合并为一个字符串,每个子字符串都有不同的自定义样式 .

    你仍然使用这些数字,但不是直接使用 - 它们现在不再采用硬编码形式(如代码中所示),但它们被组合的length()方法所取代(注意str之前的两颗星和后缀 . length()代替绝对数字来表示变化):

    str.setSpan(new StyleSpan(android.graphics.Typeface.ITALIC), 0, **str.length()**, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
    

    对于第一个字符串大小,然后 str.length() + 1, str.length() + str2.length() 表示第二个字符串大小,依此类推,包含所有子字符串,而不是例如0,7或8,19等......

  • 38

    Me Too

    如何使用Kotlin和Anko使用一些漂亮的标记 -

    import org.jetbrains.anko.*
    override fun onCreate(savedInstanceState: Bundle?) {
        title = "Created with Beautiful Markup"
        super.onCreate(savedInstanceState)
    
        verticalLayout {
            editText {
                hint = buildSpanned {
                    append("Italic, ", Italic)
                    append("highlighted", backgroundColor(0xFFFFFF00.toInt()))
                    append(", Bold", Bold)
                }
            }
        }
    }
    
  • 0

    现在不推荐使用 <b> 元素 . <strong> 呈现为 <b><em> 呈现为 <i> .

    tv.setText(Html.fromHtml("<strong>bold</strong> and <em>italic</em> "));
    

    this works fine for me

  • 0

    支持的标签列表是:

    如果使用字符串资源,则可以使用HTML表示法添加一些简单样式,例如粗体或斜体 . 当前支持的标签是:B(粗体),I(斜体),U(下划线),TT(等宽),BIG,SMALL,SUP(上标),SUB(下标)和STRIKE(删除线) . 因此,例如,在res / values / strings.xml中,您可以声明:<resource>
    <string id =“@ id / styled_welcome_message”>我们<b> <i>所以</ i> </ b>很高兴见到你 . </ string>
    </资源>

    (来自http://developer.android.com/guide/faq/commontasks.html#selectingtext - 网站档案链接, <resource> 拼写错误!)

    它还表明,在简单的情况下,并不真正需要 Html.fromHtml .

  • 12

    我遇到了同样的问题 . 我可以使用fromHtml,但我现在是android,而不是web,所以我决定尝试一下 . 我必须将其本地化,所以我使用字符串替换概念给它一个镜头 . 我将TextView上的样式设置为主要样式,然后格式化其他peices .

    我希望这可以帮助其他人做同样的事情 - 我不知道为什么在框架中这不容易 .

    我的字符串看起来像这样:

    <string name="my_text">{0} You will need a {1} to complete this assembly</string>
    <string name="text_sub0">1:</string>
    <string name="text_sub1">screwdriver, hammer, and measuring tape</string>
    

    以下是款式:

    <style name="MainStyle">
        <item name="android:textSize">@dimen/regular_text</item>
        <item name="android:textColor">@color/regular_text</item>
    </style>
    <style name="style0">
        <item name="android:textSize">@dimen/paragraph_bullet</item>
        <item name="android:textColor">@color/standout_text</item>
        <item name="android:textStyle">bold</item>
    </style>
    <style name="style1">
        <item name="android:textColor">@color/standout_light_text</item>
        <item name="android:textStyle">italic</item>
    </style>
    

    这是我调用formatStyles方法的代码:

    SpannableString formattedSpan = formatStyles(getString(R.string.my_text), getString(R.string.text_sub0), R.style.style0, getString(R.string.main_text_sub1), R.style.style1);
    textView.setText(formattedSpan, TextView.BufferType.SPANNABLE);
    

    格式方法:

    private SpannableString formatStyles(String value, String sub0, int style0, String sub1, int style1)
    {
        String tag0 = "{0}";
        int startLocation0 = value.indexOf(tag0);
        value = value.replace(tag0, sub0);
    
        String tag1 = "{1}";
        int startLocation1 = value.indexOf(tag1);
        if (sub1 != null && !sub1.equals(""))
        {
            value = value.replace(tag1, sub1);
        }
    
        SpannableString styledText = new SpannableString(value);
        styledText.setSpan(new TextAppearanceSpan(getActivity(), style0), startLocation0, startLocation0 + sub0.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        if (sub1 != null && !sub1.equals(""))
        {
            styledText.setSpan(new TextAppearanceSpan(getActivity(), style1), startLocation1, startLocation1 + sub1.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        }
    
        return styledText;
    }
    
  • 106

    使用HTMLBuilder这是一种简单的方法

    myTextView.setText(new HtmlBuilder().
                        open(HtmlBuilder.Type.BOLD).
                        append("Some bold text ").
                        close(HtmlBuilder.Type.BOLD).
                        open(HtmlBuilder.Type.ITALIC).
                        append("Some italic text").
                        close(HtmlBuilder.Type.ITALIC).
                        build()
        );
    

    结果:

    Some bold text 一些斜体文字

  • 6

    在网页底部使用辅助Spannable Class作为Android String Resources份额 . 你可以通过创建 CharSquences 并给它们一个样式来解决这个问题 .

    但是在他们给我们的例子中,只是为了大胆,斜体,甚至为文本着色 . 我需要在 CharSequence 中包含多个样式,以便将它们设置在 TextView 中 . 所以对于那个类(我将其命名为 CharSequenceStyles ),我刚刚添加了这个功能 .

    public static CharSequence applyGroup(LinkedList<CharSequence> content){
        SpannableStringBuilder text = new SpannableStringBuilder();
        for (CharSequence item : content) {
            text.append(item);
        }
        return text;
    }
    

    在视图中我添加了这个 .

    message.push(postMessageText);
                message.push(limitDebtAmount);
                message.push(pretMessageText);
                TextView.setText(CharSequenceStyles.applyGroup(message));
    

    希望这对你有所帮助!

  • 16

    稍微偏离主题,但我发现这个太有用了,不在这里提及 .

    如果我们想从string.xml资源中读取Html文本并因此可以轻松进行本地化,那该怎么办? CDATA 使这成为可能:

    <string name="my_text">
      <![CDATA[
        <b>Autor:</b> Mr Nice Guy
    <b>Contact:</b> myemail@grail.com
    <i>Copyright © 2011-2012 Intergalactic Spacebar Confederation </i> ]]> </string>

    从我们的Java代码,我们现在可以像这样使用它:

    TextView tv = (TextView) findViewById(R.id.myTextView);
    tv.setText(Html.fromHtml(getString(R.string.my_text)));
    

    我没想到这会起作用 . 但确实如此 .

    希望对你们中的一些人有用!

  • 0

    作为Jon said,对我来说这是最好的解决方案,你不需要在运行时设置任何文本,只使用这个自定义类HtmlTextView

    public class HtmlTextView extends TextView {
    
      public HtmlTextView(Context context) {
          super(context);
      }
    
      public HtmlTextView(Context context, AttributeSet attrs) {
          super(context, attrs);
      }
    
      public HtmlTextView(Context context, AttributeSet attrs, int defStyleAttr) 
      {
          super(context, attrs, defStyleAttr);
      }
    
      @TargetApi(21)
      public HtmlTextView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
          super(context, attrs, defStyleAttr, defStyleRes);
      }
    
      @Override
      public void setText(CharSequence s,BufferType b){
          super.setText(Html.fromHtml(s.toString()),b);
      }
    
    }
    

    就是这样,现在只把它放在你的XML中

    <com.fitc.views.HtmlTextView
        android:id="@+id/html_TV"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/example_html" />
    

    用你的Html字符串

    <string name="example_html">
    <![CDATA[
    <b>Author:</b> Mr Donuthead
    <b>Contact:</b> me@donut.com
    <i>Donuts for life </i> ]]>
  • 0

    如果您希望能够在xml中添加样式文本,可以创建一个扩展TextView并覆盖setText()的自定义视图:

    public class HTMLStyledTextView extends TextView
    {
        public HTMLStyledTextView(Context context) {
            super(context);
        }
    
        public HTMLStyledTextView(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        public HTMLStyledTextView(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
        }
    
        @Override
        public void setText(CharSequence text, BufferType type)
        {
           super.setText(Html.fromHtml(text.toString()), type);
        }
    }
    

    然后,您可以像这样使用它(用您的包名替换 PACKAGE_NAME ):

    <PACKAGE_NAME.HTMLStyledTextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="<![CDATA[
            <b>Bolded Text:</b> Non-Bolded Text
        ]]>"
    />
    
  • 1

    使用 SpannableString 而不是html标记更轻量级 . 它帮助我看到视觉示例,所以这里是一个补充的答案 .

    这是一个 TextView .

    // set the text
    SpannableString s1 = new SpannableString("bold\n");
    SpannableString s2 = new SpannableString("italic\n");
    SpannableString s3 = new SpannableString("foreground color\n");
    SpannableString s4 = new SpannableString("background color\n");
    SpannableString s5 = new SpannableString("underline\n");
    SpannableString s6 = new SpannableString("strikethrough\n");
    SpannableString s7 = new SpannableString("bigger\n");
    SpannableString s8 = new SpannableString("smaller\n");
    SpannableString s9 = new SpannableString("font\n");
    SpannableString s10 = new SpannableString("URL span\n");
    SpannableString s11 = new SpannableString("clickable span\n");
    SpannableString s12 = new SpannableString("overlapping spans\n");
    
    // set the style
    int flag = Spanned.SPAN_EXCLUSIVE_EXCLUSIVE;
    s1.setSpan(new StyleSpan(Typeface.BOLD), 0, s1.length(), flag);
    s2.setSpan(new StyleSpan(Typeface.ITALIC), 0, s2.length(), flag);
    s3.setSpan(new ForegroundColorSpan(Color.RED), 0, s3.length(), flag);
    s4.setSpan(new BackgroundColorSpan(Color.YELLOW), 0, s4.length(), flag);
    s5.setSpan(new UnderlineSpan(), 0, s5.length(), flag);
    s6.setSpan(new StrikethroughSpan(), 0, s6.length(), flag);
    s7.setSpan(new RelativeSizeSpan(2), 0, s7.length(), flag);
    s8.setSpan(new RelativeSizeSpan(0.5f), 0, s8.length(), flag);
    s9.setSpan(new TypefaceSpan("monospace"), 0, s9.length(), flag);
    s10.setSpan(new URLSpan("https://developer.android.com"), 0, s10.length(), flag);
    s11.setSpan(new ClickableSpan() {
        @Override
        public void onClick(View widget) {
            Toast.makeText(getApplicationContext(), "Span clicked", Toast.LENGTH_SHORT).show();
        }
    }, 0, s11.length(), flag);
    s12.setSpan(new ForegroundColorSpan(Color.RED), 0, 11, flag);
    s12.setSpan(new BackgroundColorSpan(Color.YELLOW), 4, s12.length(), flag);
    s12.setSpan(new UnderlineSpan(), 4, 11, flag);
    
    // build the string
    SpannableStringBuilder builder = new SpannableStringBuilder();
    builder.append(s1);
    builder.append(s2);
    builder.append(s3);
    builder.append(s4);
    builder.append(s5);
    builder.append(s6);
    builder.append(s7);
    builder.append(s8);
    builder.append(s9);
    builder.append(s10);
    builder.append(s11);
    builder.append(s12);
    
    // set the text view with the styled text
    textView.setText(builder);
    // enables clicking on spans for clickable span and url span
    textView.setMovementMethod(LinkMovementMethod.getInstance());
    

    进一步研究

    这个例子最初的灵感来自here .

  • 179

    尝试 Html.fromHtml() ,并使用粗体和斜体HTML标记标记您的文字,例如:

    Spanned text = Html.fromHtml("This mixes <b>bold</b> and <i>italic</i> stuff");
    textView.setText(text);
    

相关问题