## (一).前言: 今天我们主要来学习一下新的开源框架,TextDrawable。我们经常在一些应用通讯录中看到这样的效果,例如我们加了一个好友,但是该用户没有上传头像图片,那么应用要么默认显示一个默认头像,或者我们就可以自动根据姓名第一个字或者首字母自动生成一个图片。OK,TextDrawable框架[(Github地址)](https://github.com/amulyakhare/TextDrawable)就是可以解决这个问题。TextDrawable扩展自Drawable,用于生成文本或者字母的图片的轻量级库,可用于现有/自定义/网络等ImageView类,并且包含一个流接口用于创建drawables以及一个定制的ColorGenerator。效果如下: ![](https://box.kancloud.cn/2016-01-18_569c8eb5222d2.jpg) FastDev4Android框架项目地址:[https://github.com/jiangqqlmj/FastDev4Android](https://github.com/jiangqqlmj/FastDev4Android) ## (二).使用方法: 2.1.AS进行集成配置TextDrawable,使用Gradle进行导入:  ~~~ dependencies { compile'com.amulyakhare:com.amulyakhare.textdrawable:1.0.1' } ~~~ 2.2.创建简单的标题: ![](https://box.kancloud.cn/2016-01-18_569c8eb53aa65.jpg) ~~~ <ImageViewandroid:layout_width="60dp" android:layout_height="60dp" android:id="@+id/image_view"/> ~~~ [注].为ImageView制定了width和height,那么drawable会自动适应大小。 2.3.创建圆角 ![](https://box.kancloud.cn/2016-01-18_569c8eb53aa65.jpg) ~~~ TextDrawabledrawable1 = TextDrawable.builder() .buildRoundRect("A",Color.RED, 10); // radius in px TextDrawabledrawable2 = TextDrawable.builder() .buildRound("A",Color.RED); ~~~ 2.4.增加圆角 ![](https://box.kancloud.cn/2016-01-18_569c8eb5527e9.jpg) ~~~ TextDrawabledrawable = TextDrawable.builder() .beginConfig() .withBorder(4) /* thicknessin px */ .endConfig() .buildRoundRect("A",Color.RED, 10); ~~~ 2.5.修改字体格式 ~~~ TextDrawabledrawable = TextDrawable.builder() .beginConfig() .textColor(Color.BLACK) .useFont(Typeface.DEFAULT) .fontSize(30) /* size in px*/ .bold() .toUpperCase() .endConfig() .buildRect("a",Color.RED) ~~~ 2.6.使用颜色引擎(颜色生成器) ~~~ ColorGeneratorgenerator = ColorGenerator.MATERIAL; // or use DEFAULT // generate randomcolor int color1 =generator.getRandomColor(); // generate colorbased on a key (same key returns the same color), useful for list/grid views int color2 =generator.getColor("user@gmail.com") // declare thebuilder object once. TextDrawable.IBuilderbuilder = TextDrawable.builder() .beginConfig() .withBorder(4) .endConfig() .rect(); // reuse the builderspecs to create multiple drawables TextDrawable ic1 =builder.build("A", color1); TextDrawable ic2 =builder.build("B", color2); ~~~ 2.7.制定宽度和高度 ~~~ <ImageViewandroid:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/image_view"/> ~~~ [注].这边的ImageView采用自使用width/height,可以使用编码来设置drawable的width/heigth。 ~~~ TextDrawabledrawable = TextDrawable.builder() .beginConfig() .width(60) // width in px .height(60) // height in px .endConfig() .buildRect("A",Color.RED); ImageView image =(ImageView) findViewById(R.id.image_view); image.setImageDrawable(drawable); ~~~ 2.8.其他特点 *  可以和其他drawables配合使用,和LayerDrawable,InsetDrawable,AnimationDrawable,TranstionDrawable等等结合使用。 * 和其他视图兼容(不仅仅是ImageView),可以把它作为TextView,Button等等控件的背景图片。 * 使用字母或者其他unicode字符来创建有趣的标题。 ## (三).使用实例: 下面我们来具体实例:首先看一下实现的效果: ![](https://box.kancloud.cn/2016-01-18_569c8eb575d42.jpg) 我们这边创建一个TextDrawablesTestActivity,在里面使用一个列表来分别展示11中不同的效果分别为: 1. SAMPLE_RECT 2. SAMPLE_ROUND_RECT 3. SAMPLE_ROUND 4. SAMPLE_RECT_BORDER 5. SAMPLE_ROUND_RECT_BORDER 6. SAMPLE_ROUND_BORDER 7. SAMPLE_MULTIPLE_LETTERS 8. SAMPLE_FONT 9. SAMPLE_SIZE 10. SAMPLE_ANIMATION 11. SAMPLE_MISC 具体实现代码如下: ~~~ packagecom.chinaztt.fda.test; importandroid.graphics.Color; importandroid.graphics.Typeface; importandroid.graphics.drawable.AnimationDrawable; importandroid.graphics.drawable.Drawable; importandroid.os.Bundle; importandroid.view.LayoutInflater; importandroid.view.View; importandroid.view.ViewGroup; importandroid.widget.BaseAdapter; importandroid.widget.ImageView; importandroid.widget.ListView; importandroid.widget.TextView; importcom.amulyakhare.textdrawable.TextDrawable; importcom.amulyakhare.textdrawable.util.ColorGenerator; importcom.chinaztt.fda.ui.R; importcom.chinaztt.fda.ui.base.BaseActivity; importorg.androidannotations.annotations.AfterViews; importorg.androidannotations.annotations.EActivity; importorg.androidannotations.annotations.ItemClick; importorg.androidannotations.annotations.ViewById; importorg.w3c.dom.Text; /** * 当前类注释:TextDrawables 效果实例演示 * 项目名:FastDev4Android * 包名:com.chinaztt.fda.test * 作者:江清清 on 15/11/5 22:13 * 邮箱:jiangqqlmj@163.com * QQ: 781931404 * 公司:江苏中天科技软件技术有限公司 */ @EActivity(R.layout.text_drawables_layout) public classTextDrawablesTestActivity extends BaseActivity { @ViewById ListView lv_textdrawable; private String[] mTitles; private LayoutInflater mLayoutInflater; private ColorGenerator mGenerator; @Override protected void onCreate(BundlesavedInstanceState) { super.onCreate(savedInstanceState); mTitles=newString[]{"SAMPLE_RECT" ,"SAMPLE_ROUND_RECT","SAMPLE_ROUND" ,"SAMPLE_RECT_BORDER","SAMPLE_ROUND_RECT_BORDER" ,"SAMPLE_ROUND_BORDER" ,"SAMPLE_MULTIPLE_LETTERS", "SAMPLE_FONT","SAMPLE_SIZE","SAMPLE_ANIMATION","SAMPLE_MISC" }; mGenerator=ColorGenerator.DEFAULT; mLayoutInflater=getLayouInflater(); } @AfterViews public void showLvDrawable(){ lv_textdrawable.setAdapter(newTextAdapter()); } class TextAdapter extends BaseAdapter{ @Override public int getCount() { return mTitles.length; } @Override public Object getItem(int position) { return mTitles[position]; } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, ViewconvertView, ViewGroup parent) { Hondler _Hondler=null; if(convertView==null){ _Hondler=new Hondler(); convertView=mLayoutInflater.inflate(R.layout.text_drawables_item_layout,null); _Hondler.lv_item_img=(ImageView)convertView.findViewById(R.id.lv_item_img); _Hondler.lv_item_text=(TextView)convertView.findViewById(R.id.lv_item_text); convertView.setTag(_Hondler); }else { _Hondler=(Hondler)convertView.getTag(); } _Hondler.lv_item_text.setText(mTitles[position]); Drawable drawable=null; switch (position){ case 0: //SAMPLE_RECT drawable=TextDrawable.builder().buildRect("R",Color.BLUE); break; case 1: //SAMPLE_ROUND_RECT drawable=TextDrawable.builder().buildRoundRect("S",Color.CYAN,10); break; case 2: //SAMPLE_ROUND drawable=TextDrawable.builder().buildRound("圆",Color.LTGRAY); break; case 3: //SAMPLE_RECT_BORDER drawable=TextDrawable.builder().beginConfig() .withBorder(5) .endConfig() .buildRect("粗",Color.RED); break; case 4: //SAMPLE_ROUND_RECT_BORDER drawable=TextDrawable.builder() .beginConfig() .withBorder(5) .endConfig() .buildRoundRect("S",Color.argb(220,122,122,1),10); break; case 5: //SAMPLE_ROUND_BORDER drawable=TextDrawable.builder() .beginConfig().withBorder(5).endConfig() .buildRound("圆",Color.LTGRAY); break; case 6: //SAMPLE_MULTIPLE_LETTERS drawable=TextDrawable.builder() .beginConfig() .fontSize(40) .toUpperCase() .endConfig() .buildRect("AK", mGenerator.getColor("AK")); break; case 7: //SAMPLE_FONT drawable =TextDrawable.builder() .beginConfig() .textColor(Color.BLACK) .useFont(Typeface.SERIF) .bold() .toUpperCase() .endConfig() .buildRect("a", Color.RED); break; case 8: //SAMPLE_SIZE drawable =TextDrawable.builder() .beginConfig() .textColor(Color.BLACK) .fontSize(30) /*size in px */ .bold() .toUpperCase() .endConfig() .buildRect("a", Color.RED); break; case 9: //SAMPLE_ANIMATION TextDrawable.IBuilderbuilder = TextDrawable.builder() .rect(); AnimationDrawableanimationDrawable = new AnimationDrawable(); for (int i = 10; i > 0;i--) { TextDrawable frame =builder.build(String.valueOf(i), mGenerator.getRandomColor()); animationDrawable.addFrame(frame, 1200); } animationDrawable.setOneShot(false); animationDrawable.start(); drawable=(Drawable)animationDrawable; break; case 10: //SAMPLE_MISC drawable=TextDrawable.builder() .buildRect("M", mGenerator.getColor("Misc")); break; } if(drawable!=null){ _Hondler.lv_item_img.setImageDrawable(drawable); } return convertView; } } final static class Hondler{ ImageView lv_item_img; TextView lv_item_text; } @ItemClick(R.id.lv_textdrawable) public void lv_ItemClick(int position){ showToastMsgShort("点击了TextDrawable列表..."); } } ~~~ ## (四).源码分析: 阅读整个该开源代码,其实实现这个效果只有两个类,ColorGenerator和TextDrawable。ColorGenerator为颜色生成引擎比较简单。 4.1.ColorGenerator.java ~~~ packagecom.amulyakhare.textdrawable.util; importjava.util.Arrays; importjava.util.List; importjava.util.Random; /** * @author amulya * @datetime 14 Oct 2014, 5:20 PM */ public classColorGenerator { //使用默认颜色 public static ColorGenerator DEFAULT; //使用物料模式颜色 public static ColorGenerator MATERIAL; static { DEFAULT = create(Arrays.asList( 0xfff16364, 0xfff58559, 0xfff9a43e, 0xffe4c62e, 0xff67bf74, 0xff59a2be, 0xff2093cd, 0xffad62a7, 0xff805781 )); MATERIAL = create(Arrays.asList( 0xffe57373, 0xfff06292, 0xffba68c8, 0xff9575cd, 0xff7986cb, 0xff64b5f6, 0xff4fc3f7, 0xff4dd0e1, 0xff4db6ac, 0xff81c784, 0xffaed581, 0xffff8a65, 0xffd4e157, 0xffffd54f, 0xffffb74d, 0xffa1887f, 0xff90a4ae )); } private final List<Integer> mColors; private final Random mRandom; //使用静态方法 来创建对象 public static ColorGeneratorcreate(List<Integer> colorList) { return new ColorGenerator(colorList); } private ColorGenerator(List<Integer>colorList) { mColors = colorList; mRandom = newRandom(System.currentTimeMillis()); } //生成一个随机颜色 public int getRandomColor() { returnmColors.get(mRandom.nextInt(mColors.size())); } //获取具体的衍生 public int getColor(Object key) { returnmColors.get(Math.abs(key.hashCode()) % mColors.size()); } } ~~~ 4.2.TextDrawable进行构建生成相应的drawble,该采用构建者模式生成,根据我们的需求,来进行相应的构建组装即可。具体代码就不注释了,阅读起来很清晰的。 ~~~ packagecom.amulyakhare.textdrawable; importandroid.graphics.*; importandroid.graphics.drawable.ShapeDrawable; importandroid.graphics.drawable.shapes.OvalShape; importandroid.graphics.drawable.shapes.RectShape; importandroid.graphics.drawable.shapes.RoundRectShape; /** * @author amulya * @datetime 14 Oct 2014, 3:53 PM */ public classTextDrawable extends ShapeDrawable { private final Paint textPaint; private final Paint borderPaint; private static final float SHADE_FACTOR =0.9f; private final String text; private final int color; private final RectShape shape; private final int height; private final int width; private final int fontSize; private final float radius; private final int borderThickness; private TextDrawable(Builder builder) { super(builder.shape); // shape properties shape = builder.shape; height = builder.height; width = builder.width; radius = builder.radius; // text and color text = builder.toUpperCase ?builder.text.toUpperCase() : builder.text; color = builder.color; // text paint settings fontSize = builder.fontSize; textPaint = new Paint(); textPaint.setColor(builder.textColor); textPaint.setAntiAlias(true); textPaint.setFakeBoldText(builder.isBold); textPaint.setStyle(Paint.Style.FILL); textPaint.setTypeface(builder.font); textPaint.setTextAlign(Paint.Align.CENTER); textPaint.setStrokeWidth(builder.borderThickness); // border paint settings borderThickness =builder.borderThickness; borderPaint = new Paint(); borderPaint.setColor(getDarkerShade(color)); borderPaint.setStyle(Paint.Style.STROKE); borderPaint.setStrokeWidth(borderThickness); // drawable paint color Paint paint = getPaint(); paint.setColor(color); } private int getDarkerShade(int color) { return Color.rgb((int)(SHADE_FACTOR *Color.red(color)), (int)(SHADE_FACTOR *Color.green(color)), (int)(SHADE_FACTOR *Color.blue(color))); } @Override public void draw(Canvas canvas) { super.draw(canvas); Rect r = getBounds(); // draw border if (borderThickness > 0) { drawBorder(canvas); } int count = canvas.save(); canvas.translate(r.left, r.top); // draw text int width = this.width < 0 ?r.width() : this.width; int height = this.height < 0 ?r.height() : this.height; int fontSize = this.fontSize < 0 ?(Math.min(width, height) / 2) : this.fontSize; textPaint.setTextSize(fontSize); canvas.drawText(text, width / 2, height/ 2 - ((textPaint.descent() + textPaint.ascent()) / 2), textPaint); canvas.restoreToCount(count); } private void drawBorder(Canvas canvas) { RectF rect = new RectF(getBounds()); rect.inset(borderThickness/2,borderThickness/2); if (shape instanceof OvalShape) { canvas.drawOval(rect, borderPaint); } else if (shape instanceofRoundRectShape) { canvas.drawRoundRect(rect, radius,radius, borderPaint); } else { canvas.drawRect(rect, borderPaint); } } @Override public void setAlpha(int alpha) { textPaint.setAlpha(alpha); } @Override public void setColorFilter(ColorFilter cf){ textPaint.setColorFilter(cf); } @Override public int getOpacity() { return PixelFormat.TRANSLUCENT; } @Override public int getIntrinsicWidth() { return width; } @Override public int getIntrinsicHeight() { return height; } public static IShapeBuilder builder() { return new Builder(); } public static class Builder implementsIConfigBuilder, IShapeBuilder, IBuilder { private String text; private int color; private int borderThickness; private int width; private int height; private Typeface font; private RectShape shape; public int textColor; private int fontSize; private boolean isBold; private boolean toUpperCase; public float radius; private Builder() { text = ""; color = Color.GRAY; textColor = Color.WHITE; borderThickness = 0; width = -1; height = -1; shape = new RectShape(); font =Typeface.create("sans-serif-light", Typeface.NORMAL); fontSize = -1; isBold = false; toUpperCase = false; } public IConfigBuilder width(int width){ this.width = width; return this; } public IConfigBuilder height(intheight) { this.height = height; return this; } public IConfigBuilder textColor(intcolor) { this.textColor = color; return this; } public IConfigBuilder withBorder(intthickness) { this.borderThickness = thickness; return this; } public IConfigBuilder useFont(Typefacefont) { this.font = font; return this; } public IConfigBuilder fontSize(intsize) { this.fontSize = size; return this; } public IConfigBuilder bold() { this.isBold = true; return this; } public IConfigBuilder toUpperCase() { this.toUpperCase = true; return this; } @Override public IConfigBuilder beginConfig() { return this; } @Override public IShapeBuilder endConfig() { return this; } @Override public IBuilder rect() { this.shape = new RectShape(); return this; } @Override public IBuilder round() { this.shape = new OvalShape(); return this; } @Override public IBuilder roundRect(int radius) { this.radius = radius; float[] radii = {radius, radius,radius, radius, radius, radius, radius, radius}; this.shape = newRoundRectShape(radii, null, null); return this; } @Override public TextDrawable buildRect(Stringtext, int color) { rect(); return build(text, color); } @Override public TextDrawablebuildRoundRect(String text, int color, int radius) { roundRect(radius); return build(text, color); } @Override public TextDrawable buildRound(Stringtext, int color) { round(); return build(text, color); } @Override public TextDrawable build(String text,int color) { this.color = color; this.text = text; return new TextDrawable(this); } } public interface IConfigBuilder { public IConfigBuilder width(int width); public IConfigBuilder height(intheight); public IConfigBuilder textColor(intcolor); public IConfigBuilder withBorder(intthickness); public IConfigBuilder useFont(Typefacefont); public IConfigBuilder fontSize(intsize); public IConfigBuilder bold(); public IConfigBuilder toUpperCase(); public IShapeBuilder endConfig(); } public static interface IBuilder { public TextDrawable build(String text,int color); } public static interface IShapeBuilder { public IConfigBuilder beginConfig(); public IBuilder rect(); public IBuilder round(); public IBuilder roundRect(int radius); public TextDrawable buildRect(Stringtext, int color); public TextDrawablebuildRoundRect(String text, int color, int radius); public TextDrawable buildRound(Stringtext, int color); } } ~~~ 我们的项目已经配置集成了TextDrawble的例子,大家以后在做通讯录相关的应用的时候列表中的图标根据根据姓名去设置了。同时欢迎大家去Github站点进行clone或者下载浏览: [https://github.com/jiangqqlmj/FastDev4Android](https://github.com/jiangqqlmj/FastDev4Android) 同时欢迎大家star和fork整个开源快速开发框架项目~