这个控件本人强烈推荐,它会使得布局非常的简单且高效;
下面这个布局如果是你,你会用多少层?多少控件生成?
告诉你吧,一个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
用法也很简单:
源码:
试着结合这个类 Phrase.java那就更爽了;
ColorPhrase实现处理带颜色的字符串
https://github.com/THEONE10211024/ColorPhrase
https://github.com/quiqueqs/BabushkaText
Spanny实现字符串样式处理
https://github.com/binaryfork/Spanny
下面这个布局如果是你,你会用多少层?多少控件生成?
告诉你吧,一个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
用法也很简单:
/**
* 为一个TextView设置多种字体(大小,颜色,背景色等)
*
* @param tv
* @param title
* @param content
*/
public void createSpannableTextView(SpannableTextView tv, String title, String content)
{
// clear pieces
tv.reset();
// Add the first piece
tv.addPiece(new SpannableTextView.Piece.Builder(title).textColor(App.res.getColor(R.color.text_color_c2))
.textSize((int) App.res.getDimension(R.dimen.font_xbig)).build());
// Add the second piece
tv.addPiece(new SpannableTextView.Piece.Builder(content).textColor(App.res.getColor(R.color.text_color_c8))
.textSize((int) App.res.getDimension(R.dimen.font_middle)).build());
// Display the final, styled text
tv.display();
}
SpannableTextView tv = null;
tv = (SpannableTextView) (v.findViewById(R.id.spannableTextView0));
context.createSpannableTextView(tv, "血糖\n", "记录血糖指数");
tv = (SpannableTextView) (v.findViewById(R.id.spannableTextView1));
context.createSpannableTextView(tv, "血压\n", "记录血压指数");
tv = (SpannableTextView) (v.findViewById(R.id.spannableTextView2));
context.createSpannableTextView(tv, "体重\n", "记录体重");
tv = (SpannableTextView) (v.findViewById(R.id.spannableTextView3));
context.createSpannableTextView(tv, "饮食\n", "记录日常饮食");
tv = (SpannableTextView) (v.findViewById(R.id.spannableTextView4));
context.createSpannableTextView(tv, "运动\n", "记录运动时间");
<cn.tangdada.tangbang.widget.SpannableTextView android:id="@+id/spannableTextView0" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="center_vertical" android:background="@drawable/line_bottom" android:drawableRight="@drawable/arrow_right" android:drawableLeft="@drawable/icon_0" android:gravity="center_vertical" android:lineSpacingExtra="4dp" android:paddingRight="16dp" android:singleLine="false" />
源码:
package cn.tangdada.tangbang.widget;
/*
* Copyright (C) 2014 Henrique Boregio.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* @author Henrique Boregio (hboregio@gmail.com)
*/
import java.util.ArrayList;
import java.util.List;
import android.content.Context;
import android.graphics.Color;
import android.graphics.Typeface;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.style.AbsoluteSizeSpan;
import android.text.style.BackgroundColorSpan;
import android.text.style.ForegroundColorSpan;
import android.text.style.RelativeSizeSpan;
import android.text.style.StrikethroughSpan;
import android.text.style.StyleSpan;
import android.text.style.SubscriptSpan;
import android.text.style.SuperscriptSpan;
import android.text.style.UnderlineSpan;
import android.util.AttributeSet;
import android.widget.TextView;
/**
* usage:
*
* <pre>
* SpannableTextView tv = (SpannableTextView) findViewById(R.id.spannable_textview);
*
* // Add the first piece "Central Park"
* tv.addPiece(new SpannableTextView.Piece.Builder("Central Park, NY\n").textColor(Color.parseColor("#414141")).build());
*
* // Add the second piece "1.2 mi"
* tv.addPiece(new SpannableTextView.Piece.Builder("1.2 mi ").textColor(Color.parseColor("#0081E2")).textSizeRelative(0.9f).build());
*
* // Add the third piece "from here"
* tv.addPiece(new SpannableTextView.Piece.Builder("from here").textColor(Color.parseColor("#969696")).textSizeRelative(0.9f).build());
*
* // Display the final, styled text
* tv.display();
* </pre>
*
* <pre>
* // grab the Piece at position 1
* Piece piece = babushka.getPiece(1);
*
* // modify it's text
* piece.setText("1.9 km ");
*
* // you must always call display after you alter a Piece's text
* tv.display();
* </pre>
*
* <pre>
* Babushka Method Internal Span
* textSize AbsoluteSizeSpan
* textColor ForegroundColorSpan
* textSizeRelative RelativeSizeSpan
* backgroundColor BackgroundColorSpan
* style StyleSpan
* underline UnderlineSpan
* strike StrikethroughSpan
* superscript SuperscriptSpan
* subscript SubscriptSpan
* </pre>
*
* BabushkaText is a TextView which lets you customize the styling of parts of your text via Spannables, but without the
* hassle of having to deal directly with Spannable themselves.
*
* The idea behind a BabushkaText is that it is made up of {@code Piece}s. Each Piece represents a section of the final
* text displayed by this TextView, and each Piece may be styled independently from the other Pieces. When you put it
* all together, the final results is still a a single TextView, but with a a very different graphic output.
*
*
* https://github.com/quiqueqs/BabushkaText
*/
public class SpannableTextView extends TextView
{
// some default params
private static int DEFAULT_ABSOLUTE_TEXT_SIZE;
private static float DEFAULT_RELATIVE_TEXT_SIZE = 1;
private List<Piece> mPieces;
/**
* Create a new instance of a this class
*
* @param context
*/
public SpannableTextView(Context context)
{
super(context);
init();
}
public SpannableTextView(Context context, AttributeSet attrs)
{
super(context, attrs);
init();
}
public SpannableTextView(Context context, AttributeSet attrs, int defStyleAttr)
{
super(context, attrs, defStyleAttr);
init();
}
private void init()
{
mPieces = new ArrayList<Piece>();
SpannableTextView.DEFAULT_ABSOLUTE_TEXT_SIZE = (int) getTextSize();
}
/**
* Use this method to add a {@link SpannableTextView.BabushkaText.Piece} to a BabushkaText. Each
* {@link SpannableTextView.BabushkaText.Piece } is added sequentially, so the order you call this method matters.
*
* @param aPiece the Piece
*/
public void addPiece(Piece aPiece)
{
mPieces.add(aPiece);
}
/**
* Adds a Piece at this specific location. The underlying data structure is a {@link java.util.List}, so expect the
* same type of behaviour.
*
* @param aPiece the Piece to add.
* @param location the index at which to add.
*/
public void addPiece(Piece aPiece, int location)
{
mPieces.add(location, aPiece);
}
/**
* Replaces the Piece at the specified location with this new Piece. The underlying data structure is a
* {@link java.util.List}, so expect the same type of behaviour.
*
* @param newPiece the Piece to insert.
* @param location the index at which to insert.
*/
public void replacePieceAt(int location, Piece newPiece)
{
mPieces.set(location, newPiece);
}
/**
* Removes the Piece at this specified location. The underlying data structure is a {@link java.util.List}, so
* expect the same type of behaviour.
*
* @param location the index of the Piece to remove
*/
public void removePiece(int location)
{
mPieces.remove(location);
}
/**
* Clear all the Pieces, same as reset()
*/
public void clearPiece()
{
mPieces.clear();
}
/**
* Get a specific {@link SpannableTextView.BabushkaText.Piece} in position index.
*
* @param location position of Piece (0 based)
* @return Piece o null if invalid index
*/
public Piece getPiece(int location)
{
if (location >= 0 && location < mPieces.size())
{
return mPieces.get(location);
}
return null;
}
/**
* Call this method when you're done adding {@link SpannableTextView.BabushkaText.Piece}s and want this TextView to
* display the final, styled version of it's String contents.
*
* You MUST also call this method whenever you make a modification to the text of a Piece that has already been
* displayed.
*/
public void display()
{
// generate the final string based on the pieces
StringBuilder builder = new StringBuilder();
for (Piece aPiece : mPieces)
{
builder.append(aPiece.text);
}
// apply spans
int cursor = 0;
SpannableString finalString = new SpannableString(builder.toString());
for (Piece aPiece : mPieces)
{
applySpannablesTo(aPiece, finalString, cursor, cursor + aPiece.text.length());
cursor += aPiece.text.length();
}
// set the styled text
setText(finalString);
}
private void applySpannablesTo(Piece aPiece, SpannableString finalString, int start, int end)
{
if (aPiece.subscript)
{
finalString.setSpan(new SubscriptSpan(), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
if (aPiece.superscript)
{
finalString.setSpan(new SuperscriptSpan(), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
if (aPiece.strike)
{
finalString.setSpan(new StrikethroughSpan(), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
if (aPiece.underline)
{
finalString.setSpan(new UnderlineSpan(), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
// style
finalString.setSpan(new StyleSpan(aPiece.style), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
// absolute text size
finalString.setSpan(new AbsoluteSizeSpan(aPiece.textSize), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
// relative text size
finalString.setSpan(new RelativeSizeSpan(aPiece.textSizeRelative), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
// text color
finalString.setSpan(new ForegroundColorSpan(aPiece.textColor), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
// background color
if (aPiece.backgroundColor != -1)
{
finalString.setSpan(new BackgroundColorSpan(aPiece.backgroundColor), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
/**
* Resets the styling of this view and sets it's content to an empty String.
*/
public void reset()
{
mPieces = new ArrayList<Piece>();
setText("");
}
/**
* Change text color of all pieces of textview.
*/
public void changeTextColor(int textColor)
{
for (Piece mPiece : mPieces)
{
mPiece.setTextColor(textColor);
}
display();
}
/**
* A Piece represents a part of the text that you want to style. Say for example you want this BabushkaText to
* display "Hello World" such that "Hello" is displayed in Bold and "World" is displayed in Italics. Since these
* have different styles, they are both separate Pieces.
*
* You create a Piece by using it's {@link SpannableTextView.BabushkaText.Piece.Builder}
*
*/
public static class Piece
{
private String text;
private int textColor;
private final int textSize;
private final int backgroundColor;
private final float textSizeRelative;
private final int style;
private final boolean underline;
private final boolean superscript;
private final boolean strike;
private final boolean subscript;
public Piece(Builder builder)
{
this.text = builder.text;
this.textSize = builder.textSize;
this.textColor = builder.textColor;
this.backgroundColor = builder.backgroundColor;
this.textSizeRelative = builder.textSizeRelative;
this.style = builder.style;
this.underline = builder.underline;
this.superscript = builder.superscript;
this.subscript = builder.subscript;
this.strike = builder.strike;
}
/**
* Sets the text of this Piece. If you're creating a new Piece, you should do so using it's
* {@link SpannableTextView.BabushkaText.Piece.Builder}.
*
* Use this method if you want to modify the text of an existing Piece that is already displayed. After doing
* so, you MUST call {@code display()} for the changes to show up.
*
* @param text the text to display
*/
public void setText(String text)
{
this.text = text;
}
/**
* Sets the text color of this Piece. If you're creating a new Piece, you should do so using it's
* {@link SpannableTextView.BabushkaText.Piece.Builder}.
*
* Use this method if you want to change the text color of an existing Piece that is already displayed. After
* doing so, you MUST call {@code display()} for the changes to show up.
*
* @param color of text (it is NOT android Color resources ID, use getResources().getColor(R.color.colorId) for
* it)
*/
public void setTextColor(int textColor)
{
this.textColor = textColor;
}
/**
* Builder of Pieces
*/
public static class Builder
{
// required
private final String text;
// optional
private int textSize = DEFAULT_ABSOLUTE_TEXT_SIZE;
private int textColor = Color.BLACK;
private int backgroundColor = -1;
private float textSizeRelative = DEFAULT_RELATIVE_TEXT_SIZE;
private int style = Typeface.NORMAL;
private boolean underline = false;
private boolean strike = false;
private boolean superscript = false;
private boolean subscript = false;
/**
* Creates a new Builder for this Piece.
*
* @param text the text of this Piece
*/
public Builder(String text)
{
this.text = text;
}
/**
* Sets the absolute text size.
*
* @param textSize text size in pixels
* @return a Builder
*/
public Builder textSize(int textSize)
{
this.textSize = textSize;
return this;
}
/**
* Sets the text color.
*
* @param textColor the color
* @return a Builder
*/
public Builder textColor(int textColor)
{
this.textColor = textColor;
return this;
}
/**
* Sets the background color.
*
* @param backgroundColor the color
* @return a Builder
*/
public Builder backgroundColor(int backgroundColor)
{
this.backgroundColor = backgroundColor;
return this;
}
/**
* Sets the relative text size.
*
* @param textSizeRelative relative text size
* @return a Builder
*/
public Builder textSizeRelative(float textSizeRelative)
{
this.textSizeRelative = textSizeRelative;
return this;
}
/**
* Sets a style to this Piece.
*
* @param style see {@link android.graphics.Typeface}
* @return a Builder
*/
public Builder style(int style)
{
this.style = style;
return this;
}
/**
* Underlines this Piece.
*
* @return a Builder
*/
public Builder underline()
{
this.underline = true;
return this;
}
/**
* Strikes this Piece.
*
* @return a Builder
*/
public Builder strike()
{
this.strike = true;
return this;
}
/**
* Sets this Piece as a superscript.
*
* @return a Builder
*/
public Builder superscript()
{
this.superscript = true;
return this;
}
/**
* Sets this Piece as a subscript.
*
* @return a Builder
*/
public Builder subscript()
{
this.subscript = true;
return this;
}
/**
* Creates a {@link SpannableTextView.BabushkaText.Piece} with the customized parameters.
*
* @return a Piece
*/
public Piece build()
{
return new Piece(this);
}
}
}
}
试着结合这个类 Phrase.java那就更爽了;
ColorPhrase实现处理带颜色的字符串
https://github.com/THEONE10211024/ColorPhrase
https://github.com/quiqueqs/BabushkaText
Spanny实现字符串样式处理
https://github.com/binaryfork/Spanny