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

时间:2022-09-03 14:46:23

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

高效快捷解决一个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

用法也很简单:

  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. // clear pieces
  11. tv.reset();
  12. // Add the first piece
  13. tv.addPiece(new SpannableTextView.Piece.Builder(title).textColor(App.res.getColor(R.color.text_color_c2))
  14. .textSize((int) App.res.getDimension(R.dimen.font_xbig)).build());
  15. // Add the second piece
  16. tv.addPiece(new SpannableTextView.Piece.Builder(content).textColor(App.res.getColor(R.color.text_color_c8))
  17. .textSize((int) App.res.getDimension(R.dimen.font_middle)).build());
  18. // Display the final, styled text
  19. tv.display();
  20. }
  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", "记录运动时间");
  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" />

源码:

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

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

https://github.com/quiqueqs/BabushkaText

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

高效快捷解决一个TextView显示多种字体的控件SpannableTextView的更多相关文章

  1. 解决CentOS无法显示中文字体 &vert; 系统运维 &vert; Web2&period;0

    解决CentOS无法显示中文字体 | 系统运维 | Web2.0 About Me    博客园    devops    前端    张家港水蜜桃 傍晚好! 2013年09月12日 17:56:08 ...

  2. 一个Activity掌握Android5&period;0新控件 (转)

    原文地址:http://blog.csdn.net/lavor_zl/article/details/51279386 谷歌在推出Android5.0的同时推出了一些新控件,Android5.0中最常 ...

  3. WebBrowser无法显示招商银行password输入控件的问题

    本文由CharlesSimonyi发表于CSDN博客:http://blog.csdn.net/charlessimonyi/article/details/30479131转载请注明出处 之前就看到 ...

  4. 一个Activity掌握Android4&period;0新控件 (转)

    原文地址:http://blog.csdn.net/lavor_zl/article/details/51261380 谷歌在推出Android4.0的同时推出了一些新控件,Android4.0中最常 ...

  5. C&num; 时间控件 竖直进度条 饼图显示 仪表盘 按钮基础控件库

    Prepare 本文将使用一个NuGet公开的组件来实现一些特殊的控件显示,方便大家进行快速的开发系统. 在Visual Studio 中的NuGet管理器中可以下载安装,也可以直接在NuGet控制台 ...

  6. 解决SurfaceView调用setZOrderOnTop&lpar;true&rpar;遮挡其他控件

    解决SurfaceView调用setZOrderOnTop(true)遮挡其他控件的问题 http://marller.blog.51cto.com/8699646/1762028 FAQ: Surf ...

  7. Android中查找一个Layout中指定的子控件

    我们通常希望查找一个页面中指定类型的控件,单个控件知道id很容易找到,但是如果是多个呢?或者说是在程序中自定义的控件,且不知道id怎么办呢?如想找到页面中的Spinner,可用以下方法 /** * 从 ...

  8. 解决tableView中cell动态加载控件的重用问题

    解决tableView中cell动态加载控件的重用问题 tableView的cell,有时候需要在运行时取得对应的数据后才能够动态的创建该cell中的控件并加载到该cell中,此时,你一定会遇到重用问 ...

  9. SilverLight:基础控件使用(4)-日期显示和选择类控件

    ylbtech-SilverLight-Basic-Control:基础控件使用(4)-日期显示和选择类控件 Calendar,DatePicker 1.A,返回顶部 Calendar控件(日期控件) ...

随机推荐

  1. php常用的数组函数

    array_change_key_case -- 返回字符串键名全为小写或大写的数组 array_chunk -- 将一个数组分割成多个 array_combine --  创建一个数组,用一个数组的 ...

  2. 在代码中设置IE9的默认文档模式

    要在旧系统中加一个jquery插件,本地demo测试没问题,部署到服务器后却报错.使用的是IE9浏览器,打开F12调试台,发现默认的文档模式是IE7,调成IE9后,报错消失.可以确认是该插件不兼容IE ...

  3. 控件(选择类)&colon; ListBox&comma; RadioButton&comma; CheckBox&comma; ToggleSwitch

    1.ListBox 的示例Controls/SelectionControl/ListBoxDemo.xaml <Page x:Class="Windows10.Controls.Se ...

  4. Spring事务解析2-标签解析

    根据自定义标签的使用规则,可以知道会执行AnnotationDrivenBeanDefinitionParser的parse @Override public BeanDefinition parse ...

  5. Hive variable demo

    create table ori_trans (account string, maker string, tdate string) partitioned by (country string); ...

  6. 酷Q机器人,QQ机器人使用教程

    软件介绍: 酷Q,软件酷Q机器人是一款基于webqq开发的一款自动接收.处理qq消息的软件. 改程序使用易语言编写,精简大量不必要代码,减小了软件体积,优化程序速度,使得酷Q更加轻巧好用. 在消息处理 ...

  7. js原生之scrollTop、offsetHeight和offsetTop等属性用法详解

    scrollTop.offsetHeight和offsetTop等属性用法详解:标题中的几个相关相关属性在网页中有这大量的应用,尤其是在运动框架中,但是由于有些属性相互之间的概念比较混杂或者浏览器兼容 ...

  8. centos7下安装docker(23&period;docker-swarm之如何访问service)

    如何访问service呢? 为了便于分析,我们重新部署web-server 1.删除service 执行命令docker service rm web-server docker service rm ...

  9. Zephyr的Time、Timer、sleep

    正如Linux下一样,关于时间的系统函数可以分为三类:时间值.睡眠一段时间以及延迟执行. 在Zephyr上对应是什么样子呢?带着这个疑问,去了解一下这些函数. 以及他们与suspend之间的关系? 是 ...

  10. ChangeSort

    package com.home.test; import java.util.Arrays; public class ChangeSort { public String[] changeLoca ...