高效快捷解决一个TextView显示多种字体的控件SpannableTextView

这个控件本人强烈推荐,它会使得布局非常的简单且高效; 
下面这个布局如果是你,你会用多少层?多少控件生成? 

 

告诉你吧,一个SpannableTextView控件就搞定了! 

它把TextView和Spannable封装在了一起,可以在一个TextView中显示不同的字体颜色,大小,背景色等; 
它支持如下样式: 

* Babushka Method      Internal Span 
*     textSize            AbsoluteSizeSpan 
*     textColor           ForegroundColorSpan 
*     textSizeRelative    RelativeSizeSpan 
*     backgroundColor     BackgroundColorSpan 
*     style               StyleSpan 
*     underline           UnderlineSpan 
*     strike              StrikethroughSpan 
*     superscript         SuperscriptSpan 
*     subscript           SubscriptSpan 

用法也很简单: 

Java代码  收藏代码
  1. /** 
  2.      * 为一个TextView设置多种字体(大小,颜色,背景色等) 
  3.      *  
  4.      * @param tv 
  5.      * @param title 
  6.      * @param content 
  7.      */  
  8.     public void createSpannableTextView(SpannableTextView tv, String title, String content)  
  9.     {  
  10.   
  11.         // clear pieces  
  12.         tv.reset();  
  13.         // Add the first piece  
  14.         tv.addPiece(new SpannableTextView.Piece.Builder(title).textColor(App.res.getColor(R.color.text_color_c2))  
  15.                 .textSize((int) App.res.getDimension(R.dimen.font_xbig)).build());  
  16.   
  17.         // Add the second piece  
  18.         tv.addPiece(new SpannableTextView.Piece.Builder(content).textColor(App.res.getColor(R.color.text_color_c8))  
  19.                 .textSize((int) App.res.getDimension(R.dimen.font_middle)).build());  
  20.   
  21.         // Display the final, styled text  
  22.         tv.display();  
  23.     }  



Java代码  收藏代码
  1. SpannableTextView tv = null;  
  2.                 tv = (SpannableTextView) (v.findViewById(R.id.spannableTextView0));  
  3.                 context.createSpannableTextView(tv, "血糖\n", "记录血糖指数");  
  4.                 tv = (SpannableTextView) (v.findViewById(R.id.spannableTextView1));  
  5.                 context.createSpannableTextView(tv, "血压\n", "记录血压指数");  
  6.                 tv = (SpannableTextView) (v.findViewById(R.id.spannableTextView2));  
  7.                 context.createSpannableTextView(tv, "体重\n", "记录体重");  
  8.                 tv = (SpannableTextView) (v.findViewById(R.id.spannableTextView3));  
  9.                 context.createSpannableTextView(tv, "饮食\n", "记录日常饮食");  
  10.                 tv = (SpannableTextView) (v.findViewById(R.id.spannableTextView4));  
  11.                 context.createSpannableTextView(tv, "运动\n", "记录运动时间");  



Xml代码  收藏代码
  1. <cn.tangdada.tangbang.widget.SpannableTextView  
  2.                 android:id="@+id/spannableTextView0"  
  3.                 android:layout_width="match_parent"  
  4.                 android:layout_height="match_parent"  
  5.                 android:layout_gravity="center_vertical"  
  6.                 android:background="@drawable/line_bottom"  
  7.                 android:drawableRight="@drawable/arrow_right"  
  8.                 android:drawableLeft="@drawable/icon_0"  
  9.                 android:gravity="center_vertical"  
  10.                 android:lineSpacingExtra="4dp"  
  11.                 android:paddingRight="16dp"  
  12.                 android:singleLine="false" />  



源码: 

Java代码  收藏代码
  1. package cn.tangdada.tangbang.widget;  
  2.   
  3. /* 
  4.  * Copyright (C) 2014 Henrique Boregio. 
  5.  * 
  6.  * Licensed under the Apache License, Version 2.0 (the "License"); 
  7.  * you may not use this file except in compliance with the License. 
  8.  * You may obtain a copy of the License at 
  9.  * 
  10.  *      http://www.apache.org/licenses/LICENSE-2.0 
  11.  * 
  12.  * Unless required by applicable law or agreed to in writing, software 
  13.  * distributed under the License is distributed on an "AS IS" BASIS, 
  14.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
  15.  * See the License for the specific language governing permissions and 
  16.  * limitations under the License. 
  17.  * 
  18.  * @author Henrique Boregio (hboregio@gmail.com) 
  19.  */  
  20.   
  21. import java.util.ArrayList;  
  22. import java.util.List;  
  23.   
  24. import android.content.Context;  
  25. import android.graphics.Color;  
  26. import android.graphics.Typeface;  
  27. import android.text.Spannable;  
  28. import android.text.SpannableString;  
  29. import android.text.style.AbsoluteSizeSpan;  
  30. import android.text.style.BackgroundColorSpan;  
  31. import android.text.style.ForegroundColorSpan;  
  32. import android.text.style.RelativeSizeSpan;  
  33. import android.text.style.StrikethroughSpan;  
  34. import android.text.style.StyleSpan;  
  35. import android.text.style.SubscriptSpan;  
  36. import android.text.style.SuperscriptSpan;  
  37. import android.text.style.UnderlineSpan;  
  38. import android.util.AttributeSet;  
  39. import android.widget.TextView;  
  40.   
  41. /** 
  42.  * usage: 
  43.  *  
  44.  * <pre> 
  45.  * SpannableTextView tv = (SpannableTextView) findViewById(R.id.spannable_textview); 
  46.  *  
  47.  * // Add the first piece &quot;Central Park&quot; 
  48.  * tv.addPiece(new SpannableTextView.Piece.Builder(&quot;Central Park, NY\n&quot;).textColor(Color.parseColor(&quot;#414141&quot;)).build()); 
  49.  *  
  50.  * // Add the second piece &quot;1.2 mi&quot; 
  51.  * tv.addPiece(new SpannableTextView.Piece.Builder(&quot;1.2 mi &quot;).textColor(Color.parseColor(&quot;#0081E2&quot;)).textSizeRelative(0.9f).build()); 
  52.  *  
  53.  * // Add the third piece &quot;from here&quot; 
  54.  * tv.addPiece(new SpannableTextView.Piece.Builder(&quot;from here&quot;).textColor(Color.parseColor(&quot;#969696&quot;)).textSizeRelative(0.9f).build()); 
  55.  *  
  56.  * // Display the final, styled text 
  57.  * tv.display(); 
  58.  * </pre> 
  59.  *  
  60.  * <pre> 
  61.  * // grab the Piece at position 1 
  62.  * Piece piece = babushka.getPiece(1); 
  63.  *  
  64.  * // modify it's text 
  65.  * piece.setText(&quot;1.9 km &quot;); 
  66.  *  
  67.  * // you must always call display after you alter a Piece's text 
  68.  * tv.display(); 
  69.  * </pre> 
  70.  *  
  71.  * <pre> 
  72.  * Babushka Method      Internal Span 
  73.  *     textSize            AbsoluteSizeSpan 
  74.  *     textColor           ForegroundColorSpan 
  75.  *     textSizeRelative    RelativeSizeSpan 
  76.  *     backgroundColor     BackgroundColorSpan 
  77.  *     style               StyleSpan 
  78.  *     underline           UnderlineSpan 
  79.  *     strike              StrikethroughSpan 
  80.  *     superscript         SuperscriptSpan 
  81.  *     subscript           SubscriptSpan 
  82.  * </pre> 
  83.  *  
  84.  * BabushkaText is a TextView which lets you customize the styling of parts of your text via Spannables, but without the 
  85.  * hassle of having to deal directly with Spannable themselves. 
  86.  *  
  87.  * The idea behind a BabushkaText is that it is made up of {@code Piece}s. Each Piece represents a section of the final 
  88.  * text displayed by this TextView, and each Piece may be styled independently from the other Pieces. When you put it 
  89.  * all together, the final results is still a a single TextView, but with a a very different graphic output. 
  90.  *  
  91.  *  
  92.  * https://github.com/quiqueqs/BabushkaText 
  93.  */  
  94. public class SpannableTextView extends TextView  
  95. {  
  96.   
  97.     // some default params  
  98.     private static int DEFAULT_ABSOLUTE_TEXT_SIZE;  
  99.   
  100.     private static float DEFAULT_RELATIVE_TEXT_SIZE = 1;  
  101.   
  102.     private List<Piece> mPieces;  
  103.   
  104.     /** 
  105.      * Create a new instance of a this class 
  106.      *  
  107.      * @param context 
  108.      */  
  109.     public SpannableTextView(Context context)  
  110.     {  
  111.         super(context);  
  112.         init();  
  113.     }  
  114.   
  115.     public SpannableTextView(Context context, AttributeSet attrs)  
  116.     {  
  117.         super(context, attrs);  
  118.         init();  
  119.     }  
  120.   
  121.     public SpannableTextView(Context context, AttributeSet attrs, int defStyleAttr)  
  122.     {  
  123.         super(context, attrs, defStyleAttr);  
  124.         init();  
  125.     }  
  126.   
  127.     private void init()  
  128.     {  
  129.         mPieces = new ArrayList<Piece>();  
  130.         SpannableTextView.DEFAULT_ABSOLUTE_TEXT_SIZE = (int) getTextSize();  
  131.     }  
  132.   
  133.     /** 
  134.      * Use this method to add a {@link SpannableTextView.BabushkaText.Piece} to a BabushkaText. Each 
  135.      * {@link SpannableTextView.BabushkaText.Piece } is added sequentially, so the order you call this method matters. 
  136.      *  
  137.      * @param aPiece the Piece 
  138.      */  
  139.     public void addPiece(Piece aPiece)  
  140.     {  
  141.         mPieces.add(aPiece);  
  142.     }  
  143.   
  144.     /** 
  145.      * Adds a Piece at this specific location. The underlying data structure is a {@link java.util.List}, so expect the 
  146.      * same type of behaviour. 
  147.      *  
  148.      * @param aPiece the Piece to add. 
  149.      * @param location the index at which to add. 
  150.      */  
  151.     public void addPiece(Piece aPiece, int location)  
  152.     {  
  153.         mPieces.add(location, aPiece);  
  154.     }  
  155.   
  156.     /** 
  157.      * Replaces the Piece at the specified location with this new Piece. The underlying data structure is a 
  158.      * {@link java.util.List}, so expect the same type of behaviour. 
  159.      *  
  160.      * @param newPiece the Piece to insert. 
  161.      * @param location the index at which to insert. 
  162.      */  
  163.     public void replacePieceAt(int location, Piece newPiece)  
  164.     {  
  165.         mPieces.set(location, newPiece);  
  166.     }  
  167.   
  168.     /** 
  169.      * Removes the Piece at this specified location. The underlying data structure is a {@link java.util.List}, so 
  170.      * expect the same type of behaviour. 
  171.      *  
  172.      * @param location the index of the Piece to remove 
  173.      */  
  174.     public void removePiece(int location)  
  175.     {  
  176.         mPieces.remove(location);  
  177.     }  
  178.   
  179.     /** 
  180.      * Clear all the Pieces, same as reset() 
  181.      */  
  182.     public void clearPiece()  
  183.     {  
  184.         mPieces.clear();  
  185.     }  
  186.   
  187.     /** 
  188.      * Get a specific {@link SpannableTextView.BabushkaText.Piece} in position index. 
  189.      *  
  190.      * @param location position of Piece (0 based) 
  191.      * @return Piece o null if invalid index 
  192.      */  
  193.     public Piece getPiece(int location)  
  194.     {  
  195.         if (location >= 0 && location < mPieces.size())  
  196.         {  
  197.             return mPieces.get(location);  
  198.         }  
  199.   
  200.         return null;  
  201.     }  
  202.   
  203.     /** 
  204.      * Call this method when you're done adding {@link SpannableTextView.BabushkaText.Piece}s and want this TextView to 
  205.      * display the final, styled version of it's String contents. 
  206.      *  
  207.      * You MUST also call this method whenever you make a modification to the text of a Piece that has already been 
  208.      * displayed. 
  209.      */  
  210.     public void display()  
  211.     {  
  212.   
  213.         // generate the final string based on the pieces  
  214.         StringBuilder builder = new StringBuilder();  
  215.         for (Piece aPiece : mPieces)  
  216.         {  
  217.             builder.append(aPiece.text);  
  218.         }  
  219.   
  220.         // apply spans  
  221.         int cursor = 0;  
  222.         SpannableString finalString = new SpannableString(builder.toString());  
  223.         for (Piece aPiece : mPieces)  
  224.         {  
  225.             applySpannablesTo(aPiece, finalString, cursor, cursor + aPiece.text.length());  
  226.             cursor += aPiece.text.length();  
  227.         }  
  228.   
  229.         // set the styled text  
  230.         setText(finalString);  
  231.     }  
  232.   
  233.     private void applySpannablesTo(Piece aPiece, SpannableString finalString, int start, int end)  
  234.     {  
  235.   
  236.         if (aPiece.subscript)  
  237.         {  
  238.             finalString.setSpan(new SubscriptSpan(), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);  
  239.         }  
  240.   
  241.         if (aPiece.superscript)  
  242.         {  
  243.             finalString.setSpan(new SuperscriptSpan(), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);  
  244.         }  
  245.   
  246.         if (aPiece.strike)  
  247.         {  
  248.             finalString.setSpan(new StrikethroughSpan(), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);  
  249.         }  
  250.   
  251.         if (aPiece.underline)  
  252.         {  
  253.             finalString.setSpan(new UnderlineSpan(), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);  
  254.         }  
  255.   
  256.         // style  
  257.         finalString.setSpan(new StyleSpan(aPiece.style), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);  
  258.   
  259.         // absolute text size  
  260.         finalString.setSpan(new AbsoluteSizeSpan(aPiece.textSize), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);  
  261.   
  262.         // relative text size  
  263.         finalString.setSpan(new RelativeSizeSpan(aPiece.textSizeRelative), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);  
  264.   
  265.         // text color  
  266.         finalString.setSpan(new ForegroundColorSpan(aPiece.textColor), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);  
  267.   
  268.         // background color  
  269.         if (aPiece.backgroundColor != -1)  
  270.         {  
  271.             finalString.setSpan(new BackgroundColorSpan(aPiece.backgroundColor), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);  
  272.         }  
  273.     }  
  274.   
  275.     /** 
  276.      * Resets the styling of this view and sets it's content to an empty String. 
  277.      */  
  278.     public void reset()  
  279.     {  
  280.         mPieces = new ArrayList<Piece>();  
  281.         setText("");  
  282.     }  
  283.   
  284.     /** 
  285.      * Change text color of all pieces of textview. 
  286.      */  
  287.     public void changeTextColor(int textColor)  
  288.     {  
  289.         for (Piece mPiece : mPieces)  
  290.         {  
  291.             mPiece.setTextColor(textColor);  
  292.         }  
  293.         display();  
  294.     }  
  295.   
  296.     /** 
  297.      * A Piece represents a part of the text that you want to style. Say for example you want this BabushkaText to 
  298.      * display "Hello World" such that "Hello" is displayed in Bold and "World" is displayed in Italics. Since these 
  299.      * have different styles, they are both separate Pieces. 
  300.      *  
  301.      * You create a Piece by using it's {@link SpannableTextView.BabushkaText.Piece.Builder} 
  302.      *  
  303.      */  
  304.     public static class Piece  
  305.     {  
  306.   
  307.         private String text;  
  308.   
  309.         private int textColor;  
  310.   
  311.         private final int textSize;  
  312.   
  313.         private final int backgroundColor;  
  314.   
  315.         private final float textSizeRelative;  
  316.   
  317.         private final int style;  
  318.   
  319.         private final boolean underline;  
  320.   
  321.         private final boolean superscript;  
  322.   
  323.         private final boolean strike;  
  324.   
  325.         private final boolean subscript;  
  326.   
  327.         public Piece(Builder builder)  
  328.         {  
  329.             this.text = builder.text;  
  330.             this.textSize = builder.textSize;  
  331.             this.textColor = builder.textColor;  
  332.             this.backgroundColor = builder.backgroundColor;  
  333.             this.textSizeRelative = builder.textSizeRelative;  
  334.             this.style = builder.style;  
  335.             this.underline = builder.underline;  
  336.             this.superscript = builder.superscript;  
  337.             this.subscript = builder.subscript;  
  338.             this.strike = builder.strike;  
  339.         }  
  340.   
  341.         /** 
  342.          * Sets the text of this Piece. If you're creating a new Piece, you should do so using it's 
  343.          * {@link SpannableTextView.BabushkaText.Piece.Builder}. 
  344.          *  
  345.          * Use this method if you want to modify the text of an existing Piece that is already displayed. After doing 
  346.          * so, you MUST call {@code display()} for the changes to show up. 
  347.          *  
  348.          * @param text the text to display 
  349.          */  
  350.         public void setText(String text)  
  351.         {  
  352.             this.text = text;  
  353.         }  
  354.   
  355.         /** 
  356.          * Sets the text color of this Piece. If you're creating a new Piece, you should do so using it's 
  357.          * {@link SpannableTextView.BabushkaText.Piece.Builder}. 
  358.          *  
  359.          * Use this method if you want to change the text color of an existing Piece that is already displayed. After 
  360.          * doing so, you MUST call {@code display()} for the changes to show up. 
  361.          *  
  362.          * @param color of text (it is NOT android Color resources ID, use getResources().getColor(R.color.colorId) for 
  363.          *            it) 
  364.          */  
  365.         public void setTextColor(int textColor)  
  366.         {  
  367.             this.textColor = textColor;  
  368.         }  
  369.   
  370.         /** 
  371.          * Builder of Pieces 
  372.          */  
  373.         public static class Builder  
  374.         {  
  375.   
  376.             // required  
  377.             private final String text;  
  378.   
  379.             // optional  
  380.             private int textSize = DEFAULT_ABSOLUTE_TEXT_SIZE;  
  381.   
  382.             private int textColor = Color.BLACK;  
  383.   
  384.             private int backgroundColor = -1;  
  385.   
  386.             private float textSizeRelative = DEFAULT_RELATIVE_TEXT_SIZE;  
  387.   
  388.             private int style = Typeface.NORMAL;  
  389.   
  390.             private boolean underline = false;  
  391.   
  392.             private boolean strike = false;  
  393.   
  394.             private boolean superscript = false;  
  395.   
  396.             private boolean subscript = false;  
  397.   
  398.             /** 
  399.              * Creates a new Builder for this Piece. 
  400.              *  
  401.              * @param text the text of this Piece 
  402.              */  
  403.             public Builder(String text)  
  404.             {  
  405.                 this.text = text;  
  406.             }  
  407.   
  408.             /** 
  409.              * Sets the absolute text size. 
  410.              *  
  411.              * @param textSize text size in pixels 
  412.              * @return a Builder 
  413.              */  
  414.             public Builder textSize(int textSize)  
  415.             {  
  416.                 this.textSize = textSize;  
  417.                 return this;  
  418.             }  
  419.   
  420.             /** 
  421.              * Sets the text color. 
  422.              *  
  423.              * @param textColor the color 
  424.              * @return a Builder 
  425.              */  
  426.             public Builder textColor(int textColor)  
  427.             {  
  428.                 this.textColor = textColor;  
  429.                 return this;  
  430.             }  
  431.   
  432.             /** 
  433.              * Sets the background color. 
  434.              *  
  435.              * @param backgroundColor the color 
  436.              * @return a Builder 
  437.              */  
  438.             public Builder backgroundColor(int backgroundColor)  
  439.             {  
  440.                 this.backgroundColor = backgroundColor;  
  441.                 return this;  
  442.             }  
  443.   
  444.             /** 
  445.              * Sets the relative text size. 
  446.              *  
  447.              * @param textSizeRelative relative text size 
  448.              * @return a Builder 
  449.              */  
  450.             public Builder textSizeRelative(float textSizeRelative)  
  451.             {  
  452.                 this.textSizeRelative = textSizeRelative;  
  453.                 return this;  
  454.             }  
  455.   
  456.             /** 
  457.              * Sets a style to this Piece. 
  458.              *  
  459.              * @param style see {@link android.graphics.Typeface} 
  460.              * @return a Builder 
  461.              */  
  462.             public Builder style(int style)  
  463.             {  
  464.                 this.style = style;  
  465.                 return this;  
  466.             }  
  467.   
  468.             /** 
  469.              * Underlines this Piece. 
  470.              *  
  471.              * @return a Builder 
  472.              */  
  473.             public Builder underline()  
  474.             {  
  475.                 this.underline = true;  
  476.                 return this;  
  477.             }  
  478.   
  479.             /** 
  480.              * Strikes this Piece. 
  481.              *  
  482.              * @return a Builder 
  483.              */  
  484.             public Builder strike()  
  485.             {  
  486.                 this.strike = true;  
  487.                 return this;  
  488.             }  
  489.   
  490.             /** 
  491.              * Sets this Piece as a superscript. 
  492.              *  
  493.              * @return a Builder 
  494.              */  
  495.             public Builder superscript()  
  496.             {  
  497.                 this.superscript = true;  
  498.                 return this;  
  499.             }  
  500.   
  501.             /** 
  502.              * Sets this Piece as a subscript. 
  503.              *  
  504.              * @return a Builder 
  505.              */  
  506.             public Builder subscript()  
  507.             {  
  508.                 this.subscript = true;  
  509.                 return this;  
  510.             }  
  511.   
  512.             /** 
  513.              * Creates a {@link SpannableTextView.BabushkaText.Piece} with the customized parameters. 
  514.              *  
  515.              * @return a Piece 
  516.              */  
  517.             public Piece build()  
  518.             {  
  519.                 return new Piece(this);  
  520.             }  
  521.         }  
  522.     }  
  523.   
  524. }  



试着结合这个类Phrase.java那就更爽了; 
ColorPhrase实现处理带颜色的字符串 
https://github.com/THEONE10211024/ColorPhrase 

https://github.com/quiqueqs/BabushkaText 

Spanny实现字符串样式处理 
https://github.com/binaryfork/Spanny

 

posted @ 2015-09-30 15:27  gao_chun  阅读(443)  评论(0编辑  收藏  举报