安卓开发进阶之文字上标(翻译)
来源:互联网 发布:java就业培训教程豆瓣 编辑:程序博客网 时间:2024/05/18 00:18
原文链接
https://blog.stylingandroid.com/superscript/
本文讨论的上标类似为1st,需要说明的是上标使用于任何语言而不仅仅限于英语。
本文涉及到两个关键技术,正则表达与正则读者,前者用来匹配任意给定串的序数(类似第一第二称为序数)。
下面是正则表达式:
(?<=\b\d{1,10})(st|nd|rd|th)(?=\b)
看起来恐怖吗,恐怖就对了(逗你的...)。实际上我们只要把它分为三部分就豁然开朗了。
(?<=\b\d{1,10})
(st|nd|rd|th)
(?=\b)
第一部分是后行断言(lookbehind),用来匹配我们希望展示内容之前的指定模式。后行断言用?<=表示,后面跟着我们希望匹配的模式。
此处\b\d{1,10}要么匹配一个空格或者是一个字符串的开始(\b代表);然后后面跟1到10的数字(\d{1,10}代表)。
在java中不可能用通配符匹配后行断言,因为假如编译器无法确定后行断言的最大长度正则编辑会失败,这就是我为什么在这里指定了一个范围,而不是使用\\d+。
第二部分是我们真正要展示的内容。正如我们想要展示的序数后缀,我们使用(st|nd|rd|th)。
第三部分是先行断言(lookahead),用来匹配我们希望展示内容之后的指定模式。后行断言用?=表示,后面跟着我们希望匹配的模式。
此处\b要么匹配一个空格要么匹配一个字符串的结尾(\b代表)。
认真的你可能会想到一个问题,为什么我们不只用第二个部分就可以了呢?
因为这样我们会在“first”上匹配"st"成first,很明显这不是我们想要的。
正确使用先行断言与后行断言才能达到我们的目的,最后我们要匹配如下的模式:
<whitespace or start><one or more digits>st|nd|rd|th<whitespace or end>
要知道我们真正要作为上标的部分是st,nd,rd,th。在Demo中有个JUnit5测试单元用例测试正则表达式的结果。
当然,我的正则表达式也不是完美的,我也知道有些特殊情况会有问题。比如说错误的匹配成11st,尽管我能够解决这个问题,
但是为了降低正则表达式的复杂度,我并不打算这么做。
为了实现我们上标的目的,我们使用SuperscriptSpan和RelativeSizeSpan ,前者用来升高文字基准线,后者用来改变TextView文字大小。
代码如下:
public class OrdinalSuperscriptFormatter { private static final String SUPERSCRIPT_REGEX = "(?<=\\b\\d{0,10})(st|nd|rd|th)(?=\\b)"; private static final Pattern PATTERN = Pattern.compile(SUPERSCRIPT_REGEX); private static final float PROPORTION = 0.5f; private final SpannableStringBuilder stringBuilder; public OrdinalSuperscriptFormatter(@NonNull SpannableStringBuilder stringBuilder) { this.stringBuilder = stringBuilder; } //执行正则表达式的逻辑 public void format(TextView textView) { CharSequence text = textView.getText(); Matcher matcher = PATTERN.matcher(text); stringBuilder.clear(); stringBuilder.append(text); while (matcher.find()) { int start = matcher.start(); int end = matcher.end(); createSuperscriptSpan(start, end); } textView.setText(stringBuilder); } private void createSuperscriptSpan(int start, int end) { SuperscriptSpan superscript = new SuperscriptSpan(); RelativeSizeSpan size = new RelativeSizeSpan(PROPORTION); stringBuilder.setSpan(superscript, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); stringBuilder.setSpan(size, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); }}
使用:
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); TextView textView = (TextView) findViewById(R.id.text_view); OrdinalSuperscriptFormatter formatter = new OrdinalSuperscriptFormatter(new SpannableStringBuilder()); formatter.format(textView); }}
运行结果:
源码下载
https://github.com/StylingAndroid/Superscript
原文链接
https://blog.stylingandroid.com/superscript/
- 安卓开发进阶之文字上标(翻译)
- 安卓开发进阶之弹性布局FlexboxLayout--Part1(翻译)
- 安卓开发进阶之弹性布局FlexboxLayout--Part2(翻译)
- 安卓开发进阶之弹性布局FlexboxLayout--Part3(翻译)
- 安卓自定义View进阶-Canvas之图片文字
- 安卓自定义View进阶-Canvas之图片文字
- 安卓自定义View进阶-Canvas之图片文字
- 安卓自定义 View 进阶: 图片文字
- 安卓自定义 View 进阶: 图片文字
- 安卓软件开发进阶之工具也疯狂
- 安卓开发入门之自定义View(翻译)
- 安卓开发入门之底部导航BottomNavigationView(翻译)
- 安卓开发入门之图片缩放(翻译)
- 安卓开发入门之自动补全文本(翻译)
- 安卓开发入门之自定义字体(翻译)
- 关于安卓开发工具翻译理解
- 关于安卓开发工具翻译
- 安卓开发—使用有道翻译
- nginx服务器有什么作用以及什么是反向代理?
- 正态分布的最大似然估计
- SVN几个常用的命令(windows)
- iOS 文件目录及NSUserDefaults
- Entity Framework 动态构造select表达式
- 安卓开发进阶之文字上标(翻译)
- 如何快速转载CSDN中的博客
- macx下安装HTMLTestReport
- 360浏览器兼容模式文档模式默认以ie7标准渲染?
- SoapUI Pro 5.1.2破解方法
- maven环境变量配置
- POJ 3207 Ikki's Story IV
- 简单解读安卓开发中shape的具体用法
- Android-androidstudio懒惰开发-必备插件