1
1
package org.ninetripods.mq.study.activity
2
2
3
- import android.graphics.BlurMaskFilter
4
- import android.graphics.Color
5
- import android.graphics.Typeface
3
+ import android.graphics.*
6
4
import android.os.Build
7
- import android.text.Layout
8
5
import android.text.SpannableStringBuilder
9
6
import android.text.Spanned
10
7
import android.text.method.LinkMovementMethod
@@ -27,6 +24,9 @@ class SpanStudyActivity : BaseActivity() {
27
24
const val TITLE_2 =
28
25
" ---> 2、影响度量的Span,实现UpdateLayout接口(UpdateLayout->UpdateAppearance),继承MetricAffectingSpan(MetricAffectingSpan->CharacterStyle)\n "
29
26
const val TITLE_3 = " ---> 3、影响段落的Span \n "
27
+ // const val TITLE_1 = ""
28
+ // const val TITLE_2 = ""
29
+ // const val TITLE_3 = ""
30
30
31
31
private const val SPAN_STR : String = TITLE_1 +
32
32
" 北国风光,千里冰封,万里雪飘。\n\n " +
@@ -35,7 +35,8 @@ class SpanStudyActivity : BaseActivity() {
35
35
" 须晴日,看红装素裹,_ 分外妖娆。\n\n 江山如此多娇,引无数英雄竞折腰。\n\n " +
36
36
" 惜秦皇汉武,略输文采;唐宗宋祖,稍逊风骚。\n\n " +
37
37
TITLE_3 +
38
- " 一代天骄,成吉思汗,只识弯弓射大雕。\n\n " + " 俱往矣,数风流人物,还看今朝。"
38
+ " 一代天骄,成吉思汗,只识弯弓射大雕。\n\n " + " 俱往矣,数风流人物,还看今朝。"
39
+ private const val SPAN_STR2 = " 锄禾日当午,\n\t 汗滴禾下土。\n 谁知盘中餐,\n\t 粒粒皆辛苦。"
39
40
const val SEG_1 = " 北国风光"
40
41
const val SEG_2 = " 千里冰封"
41
42
const val SEG_3 = " 万里雪飘"
@@ -60,10 +61,10 @@ class SpanStudyActivity : BaseActivity() {
60
61
const val SEG_22 = " 只识弯弓射大雕"
61
62
const val SEG_23 = " 俱往矣"
62
63
const val SEG_24 = " 数风流人物"
63
- const val SEG_25 = " 还看今朝"
64
+ const val SEG_25 = " 还看今朝。 "
64
65
const val ORIGIN_FLAGS = " 01234"
65
66
66
- val finalStr = SPAN_STR .replace(SEG_3 , " 万里雪飘 " )
67
+ val finalStr = SPAN_STR .replace(SEG_3 , " 万里雪飘" )
67
68
val index1 = finalStr.indexOf(SEG_1 )
68
69
val index2 = finalStr.indexOf(SEG_2 )
69
70
val index3 = finalStr.indexOf(SEG_3 )
@@ -118,14 +119,13 @@ class SpanStudyActivity : BaseActivity() {
118
119
processAppearance(spanBuilder)
119
120
// 2、影响度量的Span,实现UpdateLayout接口(UpdateLayout->UpdateAppearance),
120
121
// 继承MetricAffectingSpan(MetricAffectingSpan->CharacterStyle)
121
- processMetrics(spanBuilder)
122
+ // processMetrics(spanBuilder)
122
123
// 3、影响段落的Span
123
- processParagraph(spanBuilder)
124
+ // processParagraph(spanBuilder)
124
125
125
- tvSpan.highlightColor = Color .TRANSPARENT
126
126
tvSpan.movementMethod = LinkMovementMethod .getInstance()
127
127
tvSpan.text = spanBuilder
128
- tvSpan.setText(spanBuilder, TextView .BufferType .SPANNABLE )
128
+ // tvSpan.setText(spanBuilder, TextView.BufferType.SPANNABLE)
129
129
tvSpan.setOnClickListener {
130
130
// 避免ClickSpan与TextView本身同时相应点击事件
131
131
(it as ? TextView )?.let { tv ->
@@ -250,6 +250,7 @@ class SpanStudyActivity : BaseActivity() {
250
250
index12, index12 + SEG_12 .length, Spanned .SPAN_EXCLUSIVE_EXCLUSIVE
251
251
)
252
252
253
+ // ImageSpan
253
254
val imgDrawable =
254
255
ResourcesCompat .getDrawable(resources, R .drawable.icon_flower, null )
255
256
imgDrawable?.let {
@@ -259,13 +260,18 @@ class SpanStudyActivity : BaseActivity() {
259
260
index13, index13 + 1 , Spanned .SPAN_EXCLUSIVE_EXCLUSIVE
260
261
)
261
262
}
263
+
262
264
// 自定义RelativeSizeSpan
263
265
spanBuilder.setSpan(
264
266
RelativeSizeColorSpan (0.8f , Color .RED ),
265
267
index14, index14 + SEG_14 .length, Spanned .SPAN_EXCLUSIVE_EXCLUSIVE
266
268
)
267
269
268
270
spanBuilder.setSpan(
271
+ /* *
272
+ * @param size 文本的绝对值大小,单位是像素px
273
+ * @param dip 如果为true,则size变以为dp为单位;否则还是以像素px为单位。
274
+ */
269
275
AbsoluteSizeSpan (20 , true ),
270
276
index15, index15 + SEG_15 .length, Spanned .SPAN_EXCLUSIVE_EXCLUSIVE
271
277
)
@@ -296,64 +302,105 @@ class SpanStudyActivity : BaseActivity() {
296
302
private fun processParagraph (spanBuilder : SpannableStringBuilder ) {
297
303
spanBuilder.setSpan(
298
304
/* *
299
- * first: 每一个段落的首行缩进
300
- * mRest: 每一个段落的其他行缩进
305
+ * first: 每个段落的首行缩进
306
+ * mRest: 每个段落的其他行缩进
301
307
*/
302
308
LeadingMarginSpan .Standard (20 .dp2px(), 5 .dp2px()),
303
309
0 , SPAN_STR .length, Spanned .SPAN_EXCLUSIVE_EXCLUSIVE
304
310
)
311
+
305
312
// 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
+
312
320
// 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
+ // }
320
330
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)
326
333
// 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
+ // ),
328
337
// //DrawableMarginSpan(imgDrawable!!, 10.sp2px()),
329
- // index22, index22 + SEG_22 .length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
338
+ // 0, SPAN_STR .length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
330
339
// )
331
340
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
+ // )
338
356
339
- // 给文本添加项目符号样式 TODO
340
- spanBuilder.setSpan(
341
- BulletSpan (20 , 0xCE6454A ),
342
- index24, index24 + SEG_24 .length, Spanned .SPAN_EXCLUSIVE_EXCLUSIVE
343
- )
344
357
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
+ // )
350
381
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
+ }
356
391
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
+ }
357
404
}
358
405
359
406
private fun getSpanFlagStr (
0 commit comments