11package org.ninetripods.mq.study.activity
22
3- import android.graphics.BlurMaskFilter
4- import android.graphics.Color
5- import android.graphics.Typeface
3+ import android.graphics.*
64import android.os.Build
7- import android.text.Layout
85import android.text.SpannableStringBuilder
96import android.text.Spanned
107import android.text.method.LinkMovementMethod
@@ -27,6 +24,9 @@ class SpanStudyActivity : BaseActivity() {
2724 const val TITLE_2 =
2825 " ---> 2、影响度量的Span,实现UpdateLayout接口(UpdateLayout->UpdateAppearance),继承MetricAffectingSpan(MetricAffectingSpan->CharacterStyle)\n "
2926 const val TITLE_3 = " ---> 3、影响段落的Span \n "
27+ // const val TITLE_1 = ""
28+ // const val TITLE_2 = ""
29+ // const val TITLE_3 = ""
3030
3131 private const val SPAN_STR : String = TITLE_1 +
3232 " 北国风光,千里冰封,万里雪飘。\n\n " +
@@ -35,7 +35,8 @@ class SpanStudyActivity : BaseActivity() {
3535 " 须晴日,看红装素裹,_ 分外妖娆。\n\n 江山如此多娇,引无数英雄竞折腰。\n\n " +
3636 " 惜秦皇汉武,略输文采;唐宗宋祖,稍逊风骚。\n\n " +
3737 TITLE_3 +
38- " 一代天骄,成吉思汗,只识弯弓射大雕。\n\n " + " 俱往矣,数风流人物,还看今朝。"
38+ " 一代天骄,成吉思汗,只识弯弓射大雕。\n\n " + " 俱往矣,数风流人物,还看今朝。"
39+ private const val SPAN_STR2 = " 锄禾日当午,\n\t 汗滴禾下土。\n 谁知盘中餐,\n\t 粒粒皆辛苦。"
3940 const val SEG_1 = " 北国风光"
4041 const val SEG_2 = " 千里冰封"
4142 const val SEG_3 = " 万里雪飘"
@@ -60,10 +61,10 @@ class SpanStudyActivity : BaseActivity() {
6061 const val SEG_22 = " 只识弯弓射大雕"
6162 const val SEG_23 = " 俱往矣"
6263 const val SEG_24 = " 数风流人物"
63- const val SEG_25 = " 还看今朝"
64+ const val SEG_25 = " 还看今朝。 "
6465 const val ORIGIN_FLAGS = " 01234"
6566
66- val finalStr = SPAN_STR .replace(SEG_3 , " 万里雪飘 " )
67+ val finalStr = SPAN_STR .replace(SEG_3 , " 万里雪飘" )
6768 val index1 = finalStr.indexOf(SEG_1 )
6869 val index2 = finalStr.indexOf(SEG_2 )
6970 val index3 = finalStr.indexOf(SEG_3 )
@@ -118,14 +119,13 @@ class SpanStudyActivity : BaseActivity() {
118119 processAppearance(spanBuilder)
119120 // 2、影响度量的Span,实现UpdateLayout接口(UpdateLayout->UpdateAppearance),
120121 // 继承MetricAffectingSpan(MetricAffectingSpan->CharacterStyle)
121- processMetrics(spanBuilder)
122+ // processMetrics(spanBuilder)
122123 // 3、影响段落的Span
123- processParagraph(spanBuilder)
124+ // processParagraph(spanBuilder)
124125
125- tvSpan.highlightColor = Color .TRANSPARENT
126126 tvSpan.movementMethod = LinkMovementMethod .getInstance()
127127 tvSpan.text = spanBuilder
128- tvSpan.setText(spanBuilder, TextView .BufferType .SPANNABLE )
128+ // tvSpan.setText(spanBuilder, TextView.BufferType.SPANNABLE)
129129 tvSpan.setOnClickListener {
130130 // 避免ClickSpan与TextView本身同时相应点击事件
131131 (it as ? TextView )?.let { tv ->
@@ -250,6 +250,7 @@ class SpanStudyActivity : BaseActivity() {
250250 index12, index12 + SEG_12 .length, Spanned .SPAN_EXCLUSIVE_EXCLUSIVE
251251 )
252252
253+ // ImageSpan
253254 val imgDrawable =
254255 ResourcesCompat .getDrawable(resources, R .drawable.icon_flower, null )
255256 imgDrawable?.let {
@@ -259,13 +260,18 @@ class SpanStudyActivity : BaseActivity() {
259260 index13, index13 + 1 , Spanned .SPAN_EXCLUSIVE_EXCLUSIVE
260261 )
261262 }
263+
262264 // 自定义RelativeSizeSpan
263265 spanBuilder.setSpan(
264266 RelativeSizeColorSpan (0.8f , Color .RED ),
265267 index14, index14 + SEG_14 .length, Spanned .SPAN_EXCLUSIVE_EXCLUSIVE
266268 )
267269
268270 spanBuilder.setSpan(
271+ /* *
272+ * @param size 文本的绝对值大小,单位是像素px
273+ * @param dip 如果为true,则size变以为dp为单位;否则还是以像素px为单位。
274+ */
269275 AbsoluteSizeSpan (20 , true ),
270276 index15, index15 + SEG_15 .length, Spanned .SPAN_EXCLUSIVE_EXCLUSIVE
271277 )
@@ -296,64 +302,105 @@ class SpanStudyActivity : BaseActivity() {
296302 private fun processParagraph (spanBuilder : SpannableStringBuilder ) {
297303 spanBuilder.setSpan(
298304 /* *
299- * first: 每一个段落的首行缩进
300- * mRest: 每一个段落的其他行缩进
305+ * first: 每个段落的首行缩进
306+ * mRest: 每个段落的其他行缩进
301307 */
302308 LeadingMarginSpan .Standard (20 .dp2px(), 5 .dp2px()),
303309 0 , SPAN_STR .length, Spanned .SPAN_EXCLUSIVE_EXCLUSIVE
304310 )
311+
305312 // LineBackgroundSpan改变行的背景色,如果[start,end)不够一行按一行处理
306- if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .Q ) {
307- spanBuilder.setSpan(
308- LineBackgroundSpan .Standard (Color .YELLOW ),
309- index20, index20 + SEG_20 .length, Spanned .SPAN_EXCLUSIVE_EXCLUSIVE
310- )
311- }
313+ // if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
314+ // spanBuilder.setSpan(
315+ // LineBackgroundSpan.Standard(Color.YELLOW),
316+ // 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
317+ // )
318+ // }
319+
312320 // LineHeightSpan改变段落的行高
313- if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .Q ) {
314- // 注意,LineHeightSpan将改变整个段落的行高,即使它只覆盖段落的一部分。
315- spanBuilder.setSpan(
316- LineHeightSpan .Standard (30 .dp2px()),
317- index21, index21 + SEG_21 .length, Spanned .SPAN_EXCLUSIVE_EXCLUSIVE
318- )
319- }
321+ // spanBuilder.clear()
322+ // spanBuilder.append(SPAN_STR2)
323+ // if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
324+ // //注意,LineHeightSpan将改变整个段落的行高,即使它只覆盖段落的一部分。
325+ // spanBuilder.setSpan(
326+ // LineHeightSpan.Standard(20.dp2px()),
327+ // 0, SPAN_STR2.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
328+ // )
329+ // }
320330
321- // 在文本的行首添加一个带有指定边距的 Drawable TODO IconMarginSpan vs DrawableMarginSpan如何使用
322- // val imgDrawable =
323- // ResourcesCompat.getDrawable(resources, R.drawable.icon_flower, null).apply {
324- // this?.setBounds(0, 0, 20.dp2px(), 20.dp2px())
325- // }
331+ // 在文本的行首添加一个带有指定边距的 Drawable
332+ // val imgDrawable = ResourcesCompat.getDrawable(resources, R.drawable.icon_arrow_pull, null)
326333// spanBuilder.setSpan(
327- // IconMarginSpan(BitmapFactory.decodeResource(resources, R.drawable.icon_flower), 10.sp2px()),
334+ // IconMarginSpan(
335+ // BitmapFactory.decodeResource(resources, R.drawable.icon_arrow_pull), 10.sp2px()
336+ // ),
328337// //DrawableMarginSpan(imgDrawable!!, 10.sp2px()),
329- // index22, index22 + SEG_22 .length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
338+ // 0, SPAN_STR .length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
330339// )
331340
332- // QuoteSpan给文本添加引用样式。
333- // 注意:必须从一个段落的第一个字符连接到最后一个字符,否则不会显示该span。
334- spanBuilder.setSpan(
335- QuoteSpan (Color .RED ),
336- index23 - 1 , SPAN_STR .length, Spanned .SPAN_EXCLUSIVE_EXCLUSIVE
337- )
341+ // QuoteSpan可以在文本开始的地方添加引用样式(一个垂直的线条)。
342+ // val quoteSpan = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
343+ // /**
344+ // * QuoteSpan(int color, int stripeWidth, int gapWidth)
345+ // * @param color 垂直线条颜色。缺省情况下,条带颜色为0xff0000ff
346+ // * @param stripeWidth 线条的宽度,以像素为单位。默认值是2px。
347+ // * @param gapWidth 线条和段落之间的距离,以像素为单位。默认值是2px。
348+ // */
349+ // QuoteSpan(Color.RED, 20, 40)
350+ // } else {
351+ // QuoteSpan(Color.RED)
352+ // }
353+ // spanBuilder.setSpan(quoteSpan,
354+ // 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
355+ // )
338356
339- // 给文本添加项目符号样式 TODO
340- spanBuilder.setSpan(
341- BulletSpan (20 , 0xCE6454A ),
342- index24, index24 + SEG_24 .length, Spanned .SPAN_EXCLUSIVE_EXCLUSIVE
343- )
344357
345- // AlignmentSpan
346- spanBuilder.setSpan(
347- AlignmentSpan .Standard (Layout .Alignment .ALIGN_OPPOSITE ),
348- index25, index25 + SEG_25 .length, Spanned .SPAN_EXCLUSIVE_EXCLUSIVE
349- )
358+ // 给文本添加圆点符号
359+ // 第一行设置圆点
360+ // spanBuilder.setSpan( getBulletSpan(),
361+ // 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
362+ // val index23 = SPAN_STR.indexOf(SEG_23)
363+ // //最后一行设置圆点
364+ // spanBuilder.setSpan( getBulletSpan(),
365+ // index23, index23 + 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
366+ // )
367+ /* *
368+ * AlignmentSpan文本对齐方式
369+ */
370+ // spanBuilder.setSpan(
371+ // /**
372+ // * AlignmentSpan.Standard(Layout.Alignment align)
373+ // * align: Layout.Alignment类型的枚举值。包括三种情况:
374+ // * 1、ALIGN_CENTER 居中、
375+ // * 2、ALIGN_NORMAL 正常、
376+ // * 3、ALIGN_OPPOSITE相反方向。
377+ // */
378+ // AlignmentSpan.Standard(Layout.Alignment.ALIGN_CENTER),
379+ // 0, SPAN_STR.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
380+ // )
350381
351- // TabStopSpan
352- spanBuilder.setSpan(
353- TabStopSpan .Standard (20 .dp2px()),
354- index25, index25 + SEG_25 .length, Spanned .SPAN_EXCLUSIVE_EXCLUSIVE
355- )
382+ // TabStopSpan 段落中第一行的左侧偏移量(与\t有关系),默认实现为TabStopSpan.Standard
383+ // spanBuilder.clear()
384+ // spanBuilder.append(SPAN_STR2)
385+ // spanBuilder.setSpan(
386+ // TabStopSpan.Standard(40.dp2px()),
387+ // 0, SPAN_STR2.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
388+ // )
389+
390+ }
356391
392+ private fun getBulletSpan (): BulletSpan {
393+ return if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .P ) {
394+ /* *
395+ * BulletSpan(int gapWidth, int color, int bulletRadius)
396+ * @param gapWidth: 项目符号和段落之间的距离,单位是px,默认2px
397+ * @param color:项目符号颜色,默认是文本颜色
398+ * @param bulletRadius:符号半径,单位是px,默认是4px
399+ */
400+ BulletSpan (20 , Color .RED , 10 )
401+ } else {
402+ BulletSpan (20 , Color .RED )
403+ }
357404 }
358405
359406 private fun getSpanFlagStr (
0 commit comments