TextView指定内容特定颜色表示

在Textview 中,例如“我昨天已给你发邮件”中的昨天如何用不一样的颜色表示呀?

可以用SpannableString实现的,可以参考一下http://blog.csdn.net/lizebin_bin/article/details/51453467

用两个textview步局,各指定不同的样式

或者用HTML的样式
参考:
http://blog.csdn.net/sziicool/article/details/17126715

tView.setText(Html.fromHtml("你好吗?我很好,谢谢"));

Html.fromHtml(),样式设置和html中的一致。

/**
* 关键字高亮显示(默认为红色)
*
* @param target
* 需要高亮的关键字
* @param text
* 需要显示的文字
* @return spannable 处理完后的结果,记得不要toString(),否则没有效果
*/
private static SpannableStringBuilder highlight(String text, String target) {
SpannableStringBuilder spannable = new SpannableStringBuilder(text);
CharacterStyle span = null;

    target = "(?i)" + target;//忽略大小写

    Pattern p = Pattern.compile(target);
    Matcher m = p.matcher(text);
    while (m.find()) {
        span = new ForegroundColorSpan(Color.RED);// 需要重复!颜色自行修改
        spannable.setSpan(span, m.start(), m.end(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
    }
    return spannable;
}

private static SpannableStringBuilder highlight(String text, String target) {
SpannableStringBuilder spannable = new SpannableStringBuilder(text);
CharacterStyle span = null;

target = "(?i)" + target;//忽略大小写

Pattern p = Pattern.compile(target);
Matcher m = p.matcher(text);
while (m.find()) {
    span = new ForegroundColorSpan(Color.RED);// 需要重复!颜色自行修改
    spannable.setSpan(span, m.start(), m.end(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
return spannable;

}

Html.fromHtml(),样式设置和html中的一致。

或者用2TextView 或者 自定义View

这么多人都提示了,我就不参加了吧
import java.util.Stack;

import android.annotation.TargetApi;
import android.app.Fragment;
import android.content.Context;
import android.content.res.Resources;
import android.os.Build;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.TextUtils;
import android.text.style.ForegroundColorSpan;
import android.view.View;
/**

  • A fluent API for formatting Strings. Canonical usage:
  • CharSequence chars = ColorPhrase.from("I'm,I love ").
  • withSeparator("<>").
  • innerColor(0xFFE6454A).
  • outerColor(0xFF666666).
  • format();
    • Surround keys with curly braces; use two {{ to escape.
    • Fails fast on any mismatched keys.
    The constructor parses the original pattern into a doubly-linked list of {@link Token}s. These tokens do not modify the original pattern, thus preserving any spans.

    The {@link #format()} method iterates over the tokens, replacing and coloring the text as it iterates. The

    doubly-linked list allows each token to ask its predecessor for the expanded length.
    /
    public class ColorPhrase {
    /
    * The unmodified original pattern. /
    private final CharSequence pattern;
    /
    * Cached result after replacing all keys with corresponding values. /
    private CharSequence formatted;
    /
    *

    • The constructor parses the original pattern into this doubly-linked list
    • of tokens. */ private Token head;

    /** When parsing, this is the current character. /
    private char curChar;
    private String separator;// default "{}"
    private int curCharIndex;
    private int outerColor;// color that outside the separators,default 0xFF666666
    private int innerColor;// color that between the separators,default 0xFFA6454A
    /
    * Indicates parsing is complete. */
    private static final int EOF = 0;

    /**

    • Entry point into this API.
    • @throws IllegalArgumentException
    • if pattern contains any syntax errors. */ @TargetApi(Build.VERSION_CODES.HONEYCOMB) public static ColorPhrase from(Fragment f, int patternResourceId) { return from(f.getResources(), patternResourceId); }

    /**

    • Entry point into this API.
    • @throws IllegalArgumentException
    • if pattern contains any syntax errors. */ public static ColorPhrase from(View v, int patternResourceId) { return from(v.getResources(), patternResourceId); }

    /**

    • Entry point into this API.
    • @throws IllegalArgumentException
    • if pattern contains any syntax errors. */ public static ColorPhrase from(Context c, int patternResourceId) { return from(c.getResources(), patternResourceId); }

    /**

    • Entry point into this API.
    • @throws IllegalArgumentException
    • if pattern contains any syntax errors. */ public static ColorPhrase from(Resources r, int patternResourceId) { return from(r.getText(patternResourceId)); }

    /**

    • Entry point into this API; pattern must be non-null.
    • @throws IllegalArgumentException
    • if pattern contains any syntax errors. */ public static ColorPhrase from(CharSequence pattern) { return new ColorPhrase(pattern); }

    private ColorPhrase(CharSequence pattern) {
    curChar = (pattern.length() > 0) ? pattern.charAt(0) : EOF;

    this.pattern = pattern;
    // Invalidate the cached formatted text.
    formatted = null;
    separator = "{}";// initialize the default separator
    outerColor = 0xFF666666;//initialize the default value
    innerColor =0xFFE6454A;//initialize the default value
    

    }

    /**

    • set the separator of the target,called after from() method.
    • @param _separator
    • @return */ public ColorPhrase withSeparator(String _separator) { if (TextUtils.isEmpty(_separator)) { throw new IllegalArgumentException("separator must not be empty!"); } if (_separator.length() > 2) { throw new IllegalArgumentException("separator‘s length must not be more than 3 charactors!"); } this.separator = _separator; return this; }

    /**

    • init the outerColor
    • @param _outerColor
    • @return */ public ColorPhrase outerColor(int _outerColor) { this.outerColor = _outerColor; return this; }

    /**

    • init the innerColor
    • @param _innerColor
    • @return */ public ColorPhrase innerColor(int _innerColor) { this.innerColor = _innerColor; return this; }

    /**

    • cut the pattern with the separators and linked them with double link
    • structure; */ private void createDoubleLinkWithToken() { // A hand-coded lexer based on the idioms in // "Building Recognizers By Hand". // http://www.antlr2.org/book/byhand.pdf. Token prev = null; Token next; while ((next = token(prev)) != null) { // Creates a doubly-linked list of tokens starting with head. if (head == null) head = next; prev = next; } }

    /**

    • Returns the next token from the input pattern, or null when finished
    • parsing. */ private Token token(Token prev) { if (curChar == EOF) { return null; } if (curChar == getLeftSeparator()) { char nextChar = lookahead(); if (nextChar == getLeftSeparator()) { return leftSeparator(prev); } else { return inner(prev); } } return outer(prev); }

    private char getLeftSeparator() {
    return separator.charAt(0);
    }

    private char getRightSeparator() {
    if (separator.length() == 2) {
    return separator.charAt(1);
    }
    return separator.charAt(0);
    }

    /**

    • Returns the text after replacing all keys with values.
    • @throws IllegalArgumentException
    •         if any keys are not replaced.
      

      */
      public CharSequence format() {
      if (formatted == null) {
      if (!checkPattern()) {
      throw new IllegalStateException("the separators don't match in the pattern!");
      }
      createDoubleLinkWithToken();
      // Copy the original pattern to preserve all spans, such as bold,
      // italic, etc.
      SpannableStringBuilder sb = new SpannableStringBuilder(pattern);
      for (Token t = head; t != null; t = t.next) {
      t.expand(sb);
      }

      formatted = sb;
      

      }
      return formatted;
      }

    /**

    • check if the pattern has legal separators
    • @return */ private boolean checkPattern() { if (pattern == null) { return false; } char leftSeparator = getLeftSeparator(); char rightSeparator = getRightSeparator(); Stack separatorStack = new Stack(); for (int i = 0; i < pattern.length(); i++) { char cur = pattern.charAt(i); if (cur == leftSeparator) { separatorStack.push(cur); } else if (cur == rightSeparator) { if (!separatorStack.isEmpty() && (separatorStack.pop() == leftSeparator)) { continue; } else { return false; } } } return separatorStack.isEmpty(); }

    private InnerToken inner(Token prev) {

    // Store keys as normal Strings; we don't want keys to contain spans.
    StringBuilder sb = new StringBuilder();
    
    // Consume the left separator.
    consume();
    char rightSeparator = getRightSeparator();
    while (curChar != rightSeparator && curChar != EOF) {
        sb.append(curChar);
        consume();
    }
    
    if (curChar == EOF) {
        throw new IllegalArgumentException("Missing closing separator");
    }
    //consume the right separator.
    consume();
    
    if (sb.length() == 0) {
        throw new IllegalStateException("Disallow empty content between separators,for example {}");
    }
    
    String key = sb.toString();
    return new InnerToken(prev, key, innerColor);
    

    }

    /** Consumes and returns a token for a sequence of text. */
    private OuterToken outer(Token prev) {
    int startIndex = curCharIndex;

    while (curChar != getLeftSeparator() && curChar != EOF) {
        consume();
    }
    return new OuterToken(prev, curCharIndex - startIndex, outerColor);
    

    }

    /**

    • Consumes and returns a token representing two consecutive curly brackets. */ private LeftSeparatorToken leftSeparator(Token prev) { consume(); consume(); return new LeftSeparatorToken(prev, getLeftSeparator()); }

    /** Returns the next character in the input pattern without advancing. */
    private char lookahead() {
    return curCharIndex < pattern.length() - 1 ? pattern.charAt(curCharIndex + 1) : EOF;
    }

    /**

    • Advances the current character position without any error checking.
    • Consuming beyond the end of the string can only happen if this parser
    • contains a bug. */ private void consume() { curCharIndex++; curChar = (curCharIndex == pattern.length()) ? EOF : pattern.charAt(curCharIndex); }

    /**

    • Returns the raw pattern without expanding keys; only useful for
    • debugging. Does not pass through to {@link #format()} because doing so
    • would drop all spans. */ @Override public String toString() { return pattern.toString(); }

    private abstract static class Token {
    private final Token prev;
    private Token next;

    protected Token(Token prev) {
        this.prev = prev;
        if (prev != null)
            prev.next = this;
    }
    
    /** Replace text in {@code target} with this token's associated value. */
    abstract void expand(SpannableStringBuilder target);
    
    /** Returns the number of characters after expansion. */
    abstract int getFormattedLength();
    
    /** Returns the character index after expansion. */
    final int getFormattedStart() {
        if (prev == null) {
            // The first token.
            return 0;
        } else {
            // Recursively ask the predecessor node for the starting index.
            return prev.getFormattedStart() + prev.getFormattedLength();
        }
    }
    

    }

    /** Ordinary text between tokens. */
    private static class OuterToken extends Token {
    private final int textLength;
    private int color;

    OuterToken(Token prev, int textLength, int _color) {
        super(prev);
        this.textLength = textLength;
        this.color = _color;
    }
    
    @Override
    void expand(SpannableStringBuilder target) {
    
        int startPoint = getFormattedStart();
        int endPoint = startPoint + textLength;
        target.setSpan(new ForegroundColorSpan(color), startPoint, endPoint, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
    }
    
    @Override
    int getFormattedLength() {
        return textLength;
    }
    

    }

    /** A sequence of two curly brackets. */
    private static class LeftSeparatorToken extends Token {
    private char leftSeparetor;

    LeftSeparatorToken(Token prev, char _leftSeparator) {
        super(prev);
        leftSeparetor = _leftSeparator;
    }
    
    @Override
    void expand(SpannableStringBuilder target) {
        int start = getFormattedStart();
        target.replace(start, start + 2, String.valueOf(leftSeparetor));
    }
    
    @Override
    int getFormattedLength() {
        // for example,,Replace "{{" with "{".
        return 1;
    }
    

    }

    private static class InnerToken extends Token {
    /** The InnerText without separators,like '{' and '}'. */
    private final String innerText;

    private int color;
    
    InnerToken(Token prev, String _inner, int _color) {
        super(prev);
        this.innerText = _inner;
        color = _color;
    }
    
    @Override
    void expand(SpannableStringBuilder target) {
    
        int replaceFrom = getFormattedStart();
        // Add 2 to account for the separators.
        int replaceTo = replaceFrom + innerText.length() + 2;
        target.replace(replaceFrom, replaceTo, innerText);
        target.setSpan(new ForegroundColorSpan(color), replaceFrom, replaceTo - 2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
    }
    
    @Override
    int getFormattedLength() {
        // Note that value is only present after expand. Don't error check
        // because this is all
        // private code.
        return innerText.length();
    }
    

    }
    }

    啊哦,搜索一下ColorPhrase就知道干嘛的了

    SpannableString或者HTML

    /**

    • 关键字高亮显示(默认为红色) *
    • @param target
    • 需要高亮的关键字
    • @param text
    • 需要显示的文字
    • @return spannable 处理完后的结果,记得不要toString(),否则没有效果
      */
      private static SpannableStringBuilder highlight(String text, String target) {
      SpannableStringBuilder spannable = new SpannableStringBuilder(text);
      CharacterStyle span = null;

      target = "(?i)" + target;//忽略大小写

      Pattern p = Pattern.compile(target);
      Matcher m = p.matcher(text);
      while (m.find()) {
      span = new ForegroundColorSpan(Color.RED);// 需要重复!颜色自行修改
      spannable.setSpan(span, m.start(), m.end(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
      }
      return spannable;
      }

    public class TextViewLinkActivity extends Activity {

    TextView mTextView = null;

    SpannableString msp = null;

    /** Called when the activity is first created. */  
    @Override  
    public void onCreate(Bundle savedInstanceState) {   
        super.onCreate(savedInstanceState);   
        setContentView(R.layout.main);   
    
        mTextView = (TextView)findViewById(R.id.myTextView);   
    
        //创建一个 SpannableString对象     
        msp = new SpannableString("字体测试字体大小一半两倍前景色背景色正常粗体斜体粗斜体下划线删除线x1x2电话邮件网站短信彩信地图X轴综合/bot");    
    
        //设置字体(default,default-bold,monospace,serif,sans-serif)   
        msp.setSpan(new TypefaceSpan("monospace"), 0, 2, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);   
        msp.setSpan(new TypefaceSpan("serif"), 2, 4, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);   
    
        //设置字体大小(绝对值,单位:像素)    
        msp.setSpan(new AbsoluteSizeSpan(20), 4, 6, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);   
        msp.setSpan(new AbsoluteSizeSpan(20,true), 6, 8, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);  //第二个参数boolean dip,如果为true,表示前面的字体大小单位为dip,否则为像素,同上。   
    
        //设置字体大小(相对值,单位:像素) 参数表示为默认字体大小的多少倍   
        msp.setSpan(new RelativeSizeSpan(0.5f), 8, 10, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);  //0.5f表示默认字体大小的一半   
        msp.setSpan(new RelativeSizeSpan(2.0f), 10, 12, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);  //2.0f表示默认字体大小的两倍   
    
        //设置字体前景色   
        msp.setSpan(new ForegroundColorSpan(Color.MAGENTA), 12, 15, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);  //设置前景色为洋红色   
    
        //设置字体背景色   
        msp.setSpan(new BackgroundColorSpan(Color.CYAN), 15, 18, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);  //设置背景色为青色   
    
        //设置字体样式正常,粗体,斜体,粗斜体   
        msp.setSpan(new StyleSpan(android.graphics.Typeface.NORMAL), 18, 20, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);  //正常   
        msp.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), 20, 22, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);  //粗体   
        msp.setSpan(new StyleSpan(android.graphics.Typeface.ITALIC), 22, 24, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);  //斜体   
        msp.setSpan(new StyleSpan(android.graphics.Typeface.BOLD_ITALIC), 24, 27, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);  //粗斜体   
    
        //设置下划线   
        msp.setSpan(new UnderlineSpan(), 27, 30, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);   
    
        //设置删除线   
        msp.setSpan(new StrikethroughSpan(), 30, 33, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);   
    
        //设置上下标   
        msp.setSpan(new SubscriptSpan(), 34, 35, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);     //下标      
        msp.setSpan(new SuperscriptSpan(), 36, 37, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);   //上标               
    
        //超级链接(需要添加setMovementMethod方法附加响应)   
        msp.setSpan(new URLSpan("tel:4155551212"), 37, 39, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);     //电话      
        msp.setSpan(new URLSpan("mailto:webmaster@google.com"), 39, 41, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);     //邮件      
        msp.setSpan(new URLSpan("http://www.baidu.com"), 41, 43, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);     //网络      
        msp.setSpan(new URLSpan("sms:4155551212"), 43, 45, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);     //短信   使用sms:或者smsto:   
        msp.setSpan(new URLSpan("mms:4155551212"), 45, 47, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);     //彩信   使用mms:或者mmsto:   
        msp.setSpan(new URLSpan("geo:38.899533,-77.036476"), 47, 49, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);     //地图      
    
        //设置字体大小(相对值,单位:像素) 参数表示为默认字体宽度的多少倍   
        msp.setSpan(new ScaleXSpan(2.0f), 49, 51, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); //2.0f表示默认字体宽度的两倍,即X轴方向放大为默认字体的两倍,而高度不变   
    
        //设置字体(依次包括字体名称,字体大小,字体样式,字体颜色,链接颜色)   
        ColorStateList csllink = null;   
        ColorStateList csl = null;   
        XmlResourceParser xppcolor=getResources().getXml (R.color.color);   
        try {   
            csl= ColorStateList.createFromXml(getResources(),xppcolor);   
        }catch(XmlPullParserException e){   
            // TODO: handle exception   
            e.printStackTrace();           
        }catch(IOException e){   
            // TODO: handle exception   
            e.printStackTrace();           
        }   
    
        XmlResourceParser xpplinkcolor=getResources().getXml(R.color.linkcolor);   
        try {   
            csllink= ColorStateList.createFromXml(getResources(),xpplinkcolor);   
        }catch(XmlPullParserException e){   
            // TODO: handle exception   
            e.printStackTrace();           
        }catch(IOException e){   
            // TODO: handle exception   
            e.printStackTrace();           
        }   
        msp.setSpan(new TextAppearanceSpan("monospace",android.graphics.Typeface.BOLD_ITALIC, 30, csl, csllink), 51, 53, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);    
    
        //设置项目符号   
        msp.setSpan(new BulletSpan(android.text.style.BulletSpan.STANDARD_GAP_WIDTH,Color.GREEN), 0 ,msp.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); //第一个参数表示项目符号占用的宽度,第二个参数为项目符号的颜色   
    
        //设置图片   
        Drawable drawable = getResources().getDrawable(R.drawable.icon);    
        drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());     
        msp.setSpan(new ImageSpan(drawable), 53, 57, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);   
    
        mTextView.setText(msp);   
        mTextView.setMovementMethod(LinkMovementMethod.getInstance());    
    }   
    

    }

    怎么韩厥大家回复的都好高大上啊

    可以使用SpannableString来指定字符串中某区间的字串样式,如字体颜色