TextView指定内容特定颜色表示

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

14个回答

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

/**
* 关键字高亮显示(默认为红色)
*
* @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;
}

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

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

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

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

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

    共14条数据 1 尾页
    Csdn user default icon
    上传中...
    上传图片
    插入图片
    抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
    立即提问