自定义TextView支持字符串中指定字体的颜色 大小 样式

先看效果

图像 4.png

自定义属性简介

 颜色 :"#3bb64d"
 字体大小(sp):"20"
 字体下划线/删除线:"undeline/deleteline"
字体属性正常/加粗/倾斜/倾斜加粗:"normal/bold/italic/bold_italic”

傻瓜式使用方法

xml

<com.~~~~~~~.ColorFontTextView (单个颜色属性,null为不设置属性)   
android:layout_width="match_parent"    
android:layout_height="wrap_content"    
android:gravity="center"    
android:textColor="#252c3d"    
android:textSize="12sp"    
app:text_arrays="人|何事|画"    
app:style_arrays="bold|italic|bold_italic"
android:text="人生若只如初见,何事秋风悲画扇。" />

<com.~~~~~~~.ColorFontTextView   (多个属性,null为不设置属性) 
android:layout_width="match_parent"    
android:layout_height="wrap_content"    
android:gravity="center"    
android:textColor="#252c3d"    
android:textSize="12sp"    
app:text_arrays="人|何事|画"    
app:style_arrays="bold|italic|bold_italic"
app:textsize_arrays="20|35|null"
app:color_arrays="#fa5645|#3bb64d|#bd0a0a"
app:line_arrays="undeline|null|deleteline"
android:text="人生若只如初见,何事秋风悲画扇。" />

<com.~~~~~~.ColorFontTextView    (java代码中使用)
android:id="@+id/tv"    
android:layout_width="match_parent"    
android:layout_height="wrap_content"    
android:gravity="center"    
android:textColor="#252c3d"    
android:textSize="10sp"  />

Java代码中使用方法

参数1:要展示的字符串;参数2:指定要设置属性的字符;参数3:设置的相关参数(字体/颜色/属性)
((ColorFontTextView)findViewById(R.id.tv)).setTextStyle("Often hate  not as good as anyone","hate|not|anyone","20|null|35")(null为not不指定字体大小)
.setTextStyle("#fa5645|#3bb64d|#bd0a0a")(设置颜色)
.setTextStyle("bold|italic|bold_italic");(设置属性)
单个字符串设置属性
((ColorFontTextView)findViewById(R.id.tv)).setTextStyle("hello world","hello world","#3bb64d")
.setTextStyle("40")
.setTextStyle("deleteline")
.setTextStyle("undeline")
.setTextStyle("bold_italic");

ColorFontTextView.java

public class ColorFontTextView extends AppCompatTextView {
private ArrayList<String> mTexts = new ArrayList<>();    
private ArrayList<String> mColors = new ArrayList<>();    
private ArrayList<String> mTextSizes = new ArrayList<>();    
private ArrayList<String> mLines = new ArrayList<>();    
private ArrayList<String> mStyles = new ArrayList<>();    
private String mCurrentText;    
private Context mContext;    
private String styledTextString;    
private String styleTexts;    
public ColorFontTextView(Context context) {        
          super(context);        
          this.mContext = context;   
 }    
public ColorFontTextView(ontext context, AttributeSet attrs) {        
          super(context, attrs);        
          this.mContext = context;        
          init(attrs);    
}    
public ColorFontTextView(Context context, AttributeSet attrs, int defStyleAttr) {        
          super(context, attrs, defStyleAttr);        
          this.mContext = context;        
          init(attrs);    
}    
//获得我们所定义的自定义样式属性   
private void init(AttributeSet attrs) {        
          TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.ColorFountTextView);       
         String colors =typedArray.getString(R.styleable.ColorFountTextView_color_arrays);        
          String texts = typedArray.getString(R.styleable.ColorFountTextView_text_arrays);        
          String textsizes = typedArray.getString(R.styleable.ColorFountTextView_textsize_arrays);        
          String lines = typedArray.getString(R.styleable.ColorFountTextView_line_arrays);        
          String styles = typedArray.getString(R.styleable.ColorFountTextView_style_arrays);       
          typedArray.recycle();        
          initDate(getText().toString(), colors, texts, textsizes, lines, styles);        
          setTextDate();    
}    
//截取字符串添加到对应的集合 
private void initDate(String str, String colors, String texts, String textsizes, String lines, String styles) {       
 try {
 if (!TextUtils.isEmpty(texts)) {                
           String[] split = texts.split("\\|");                
           for (int i = 0; i < split.length; i++) {                    
           mTexts.add(split[i]);                      }            
}           
 if (!TextUtils.isEmpty(colors)) {                
            String[] split = colors.split("\\|");                
            for (int i = 0; i < split.length; i++) {                   
             mColors.add(split[i]);                }            
}            
if (!TextUtils.isEmpty(textsizes)) {                
            String[] split = textsizes.split("\\|");                
            for (int i = 0; i < split.length; i++) {                    
            mTextSizes.add(split[i]);                }            
}           
 if (!TextUtils.isEmpty(lines)) {                
            String[] split = lines.split("\\|");                
            for (int i = 0; i < split.length; i++) {                    
            mLines.add(split[i]);                }            
}           
 if (!TextUtils.isEmpty(styles)) {                
            String[] split = styles.split("\\|");                
            for (int i = 0; i < split.length; i++) {                    
            mStyles.add(split[i]);                }           
 }            
            mCurrentText = str;        
} catch (Exception e) {            
            e.printStackTrace();        
}    
}    
/**     * 根据相关属性赋值     */    
private void setTextDate() {       
try {       
 if (!TextUtils.isEmpty(mCurrentText)) {            
          SpannableString styledText = new SpannableString(mCurrentText);           
           if (mTextSizes != null && mTextSizes.size() != 0) {                
            int currentSize = mTextSizes.size() <=mTexts.size() ? mTextSizes.size() : mTexts.size();                
            for (int i = 0; i < currentSize; i++) {                    
            String size = mTexts.get(i);                    
            int startPostion = mCurrentText.indexOf(size);                    
            int endPostion = mCurrentText.indexOf(size) + size.length();                    
            if (!mTextSizes.get(i).contains("null")) {                        
styledText.setSpan(new AbsoluteSizeSpan(sp2px(mContext, Integer.valueOf(mTextSizes.get(i)))), startPostion, endPostion, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);                    }                }            
}           
 if (mColors != null && mColors.size() != 0) {               
             int currentSize = mColors.size() <= mTexts.size() ? mColors.size():mTexts.size() ;                
            for (int i = 0; i < currentSize; i++) {                    
            String size = mTexts.get(i);                    
           int startPostion = mCurrentText.indexOf(size);                    
          int endPostion = mCurrentText.indexOf(size) + size.length();                   
           if (!mColors.get(i).contains("null")) {                        
styledText.setSpan(new ForegroundColorSpan(Color.parseColor(mColors.get(i))), startPostion, endPostion, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);                    }                }            
}            
if (mLines != null && mLines.size() != 0) {               
           int currentSize = mLines.size() <= mTexts.size() ? mLines.size() : mTexts.size();                
          for (int i = 0; i < currentSize; i++) {                    
          String size = mTexts.get(i);                    
          int startPostion = mCurrentText.indexOf(size);                    
          int endPostion = mCurrentText.indexOf(size) + size.length();                    
if (!mLines.get(i).contains("null")) {                        
          if (mLines.get(i).contains("undeline")) {                            
          styledText.setSpan(new UnderlineSpan(), startPostion, endPostion, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);                        
} else if (mLines.get(i).contains("deleteline")) {                            
          styledText.setSpan(new StrikethroughSpan(), startPostion, endPostion, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);                        
} else {                            
          styledText.setSpan(new UnderlineSpan(), startPostion, endPostion, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);                        }
                    } 
               }            
}            
if (mStyles != null && mStyles.size() != 0) {                
          int currentSize = mStyles.size()<=mTexts.size() ?mStyles.size(): mTexts.size();                
          for (int i = 0; i < currentSize; i++) {                    
          String size = mTexts.get(i);                    
          int startPostion = mCurrentText.indexOf(size);                    
          int endPostion = mCurrentText.indexOf(size) + size.length();                    
if (!mStyles.get(i).contains("null")) {                        
          StyleSpan styleSpan;                        
if (("normal").equals(mStyles.get(i))) {                           
          styleSpan = new StyleSpan(Typeface.NORMAL);                        
} else if (("bold").equals(mStyles.get(i))) {                           
          styleSpan = new StyleSpan(android.graphics.Typeface.BOLD);                        
} else if (("italic").equals(mStyles.get(i))) {                            
          styleSpan = new StyleSpan(android.graphics.Typeface.ITALIC);                        
} else if (("bold_italic").equals(mStyles.get(i))) {                            
          styleSpan = new StyleSpan(android.graphics.Typeface.BOLD_ITALIC);                       
 } else {                            
          styleSpan = new StyleSpan(Typeface.NORMAL);                       
 }                        
          styledText.setSpan(styleSpan, startPostion, endPostion, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);                   
 } 
            }
            }           
         setText(styledText);            
        styledTextString=getText().toString();        }        
}catch (Exception e){
            e.printStackTrace();        }   
 }    

public ColorFontTextView  setTextStyle(String str,String texts,String all){        if(!TextUtils.isEmpty(all)&&!TextUtils.isEmpty(texts)){            
          styleTexts=texts;            
          String[] split = all.split("\\|");            
if(all.contains("#")){                
          initDate(str, all, texts,null, null, null);            
}else if(all.contains("undeline")||all.contains("deleteline")){                
          initDate(str,null,texts,null,all, null);            
}else if(all.contains("normal")||all.contains("bold")||all.contains("italic")||all.contains("bold_italic")){                
          initDate(str, null, texts, null, null, all);           
}else if(isNumeric(all)){                
          initDate(str, null, texts, all, null, null);            
}else{                
          initDate(str, null, texts, null, null, null);            
}            
          setTextDate();        
}else{            
          setText(str);        
}        
return this;
    }    
public ColorFontTextView setTextStyle(String all){        
if(!TextUtils.isEmpty(styledTextString)&&!TextUtils.isEmpty(styleTexts)){            
          setTextStyle(styledTextString,styleTexts,all);        }        
          return this;    
}    

/**     * 将sp值转换为px值,保证文字大小不变         */    
public static int sp2px(Context context, int spValue) {       
           float fontScale = context.getResources().getDisplayMetrics().scaledDensity;       
           return (int) (spValue * fontScale + 0.5f);    }    

/**     * 判断字符串是是数字     */    
public boolean isNumeric(String str){        
          Pattern pattern = Pattern.compile("[0-9]*");        
          Matcher isNum = pattern.matcher(str.replace("|",""));        
          if( !isNum.matches() ){            
          return false;        }        
          return true;    }}

attr.xml

<declare-styleable name="ColorFountTextView">    
<attr name="text_arrays" format="string"/>    
<attr name="color_arrays" format="string"/>    
<attr name="textsize_arrays" format="string"/>    
<attr name="line_arrays" format="string"/>    
<attr name="style_arrays" format="string"/>
</declare-styleable>

以上为全部代码

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容