我們可以使用 TextView
做些什么呢陵吸?
一般的文本控件可以使用 TextView
來(lái)實(shí)現(xiàn),
那么介牙,還有沒(méi)有一些其他的場(chǎng)景壮虫,可以使用 TextView
實(shí)現(xiàn)呢?
本文想記錄一些利用 TextView
實(shí)現(xiàn)的場(chǎng)景环础。
涉及到以下內(nèi)容:
- 使用
drawableStart|End
實(shí)現(xiàn)文字 + 圖標(biāo) - 使用
Span
實(shí)現(xiàn)「文字+圖標(biāo)混排」效果 - 實(shí)現(xiàn)帶背景的文字效果
- 部分點(diǎn)擊事件實(shí)現(xiàn)
- 添加原角背景 + 背景透明度設(shè)置
1. 實(shí)現(xiàn)文字 + 圖標(biāo)實(shí)現(xiàn)
想要實(shí)現(xiàn)類(lèi)似這樣的效果囚似,文字 + 圖標(biāo)。
其實(shí)實(shí)現(xiàn)起來(lái)特別簡(jiǎn)單线得,使用一個(gè) TextView
+ ImageView
即可饶唤。
但是,如果我們可以使用一個(gè) View
搞定贯钩,為什么要使用兩個(gè)呢搬素?
在 TextView
中,有個(gè)屬性叫做魏保, drawableXXX
熬尺, 在 xml
中為:
// 在文字的右邊放置圖片
android:drawableEnd="@drawable/ic_action_like"
// 在文字的左邊放置圖片
android:drawableStart="@drawable/ic_action_like"
// 在文字的上邊放置圖片
android:drawableTop="@drawable/ic_action_like"
// 在文字的下邊放置圖片
android:drawableBottom="@drawable/ic_action_like"
所以,當(dāng)我們想要實(shí)現(xiàn)上述的效果時(shí)谓罗,可以這么使用:
<TextView
android:id="@+id/like"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="40dp"
android:drawableEnd="@drawable/ic_action_like"
android:drawablePadding="4dp"
android:gravity="center"
android:paddingBottom="4dp"
android:text="123"
android:textColor="#0084FF"
android:textSize="12sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
上述代碼即可實(shí)現(xiàn)粱哼,文字 + 圖標(biāo)效果 。
android:drawablePadding
是設(shè)置該圖標(biāo)與文字的padding
2. 對(duì) TextView
設(shè)置 Span
實(shí)現(xiàn)「文字+圖標(biāo)混排」效果
上述的實(shí)現(xiàn)檩咱,只能把圖標(biāo)固定的放在文字的「前揭措、后胯舷、上、下」 這四種效果绊含。
對(duì)于復(fù)雜的文字圖標(biāo)混排桑嘶,就無(wú)能為力了。
那么如何實(shí)現(xiàn)「文字+圖標(biāo)混排」效果呢躬充?
我們可以使用 ImageSpan
實(shí)現(xiàn)該效果逃顶。
例如,我們想要這樣的效果:
在 哈哈哈123充甚,你說(shuō)不說(shuō)以政,那我開(kāi)始 balabala 了,嘿嘿嘿
中添加愛(ài)心圖標(biāo)伴找,
實(shí)現(xiàn)代碼如下:
contentView.text = "哈哈哈123盈蛮,你說(shuō)不說(shuō),那我開(kāi)始 balabala 了技矮,嘿嘿嘿"
val stringBuilder = SpannableString(contentView.text)
val drawable = getDrawable(R.drawable.ic_action_like)
val imageSpan = ImageSpan(drawable)
// 設(shè)置 drawable 大小抖誉,這里簡(jiǎn)單處理下
drawable!!.setBounds(0, 0, 64, 64)
stringBuilder.setSpan(imageSpan, 10, 12, Spannable.SPAN_INCLUSIVE_EXCLUSIVE)
contentView.text = stringBuilder
常見(jiàn)的消息中的小表情,就是利用 ImageSpan
實(shí)現(xiàn)的
小表情的實(shí)現(xiàn)衰倦,通常是利用特定的字符標(biāo)志寸五,例如
[笑臉]
,當(dāng)檢測(cè)到有類(lèi)似這種格式[]
耿币,會(huì)通過(guò)一套解析工具梳杏,把[笑臉]
替換成一個(gè)ImageSpan
, 從而實(shí)現(xiàn)小表情的效果淹接。
3. 實(shí)現(xiàn)帶背景的文字效果
我們想要實(shí)現(xiàn)的效果如下:
TextView.getText()
的返回值是 CharSequence
而 SpannableStringBuilder
實(shí)現(xiàn)了 CharSequence
接口 ,
表明 TextView
是可以設(shè)置 SpannableStringBuilder
的十性,而我們可以利用 SpannableStringBuilder
設(shè)置 span
樣式,完成很多不一樣的樣式實(shí)現(xiàn)塑悼。
3.1 給部分字體添加背景
實(shí)現(xiàn)代碼:
private fun setupLikeTextView() {
likeTextView.text = "你說(shuō)是不是熬⑹省?是不是這樣的厢蒜,你猜一下霞势,猜不到吧?在猜一下斑鸦,哈哈哈哈愕贡,就不告訴你"
val stringBuilder = SpannableStringBuilder(likeTextView.text)
val backgroundSpan = BackgroundColorSpan(getColor(R.color.colorAccent))
val start = 3
val end = content.length
stringBuilder.setSpan(backgroundSpan, start, end, Spannable.SPAN_INCLUSIVE_EXCLUSIVE)
likeTextView.text = stringBuilder
}
即可實(shí)現(xiàn),likeTextView.text
從 第 3
個(gè) 字符到結(jié)尾都會(huì)添加一個(gè)帶顏色的背景巷屿。
主要代碼是 stringBuilder
的構(gòu)建以及 likeTextView.text
的賦值固以。
3.2 給部分文字使用不同的顏色
實(shí)現(xiàn)效果如下:
hahhaah
這個(gè)文案部分, 其中的第 3 ~ 4
個(gè)字符使用不同的顏色
我們可以使用 ForegroundColorSpan
來(lái)實(shí)現(xiàn)不同顏色的 TextView
文本, 代碼如下:
contentView.text = "hahhaah, 123, 456, 789"
val foregroundColorSpan = ForegroundColorSpan(context.resources.getColor(R.color.colorAccent))
val sb = SpannableStringBuilder(contentView.text)
sb.setSpan(foregroundColorSpan, 3, 5, SpannableStringBuilder.SPAN_INCLUSIVE_EXCLUSIVE)
contentView.text = sb
在 Android
系統(tǒng)中,還有 StrikethroughSpan
, UnderlineSpan
等很多可以實(shí)現(xiàn)特定樣式的 Span
可以供我們使用憨琳。
4. 給 TextView
設(shè)置部分文本可點(diǎn)擊
通常在 TextView
中诫钓,如果有鏈接,我們需要實(shí)現(xiàn)點(diǎn)擊該部分文案時(shí)會(huì)跳轉(zhuǎn)到該鏈接的效果篙螟。
代碼實(shí)現(xiàn):
contentView.movementMethod = LinkMovementMethod.getInstance()
contentView.text = "哈哈哈123菌湃,后面是一個(gè)鏈接,可部分點(diǎn)擊: http://www.reibang.com/u/9d38eab6ce45"
contentView.setLinkTextColor(context.resources.getColor(R.color.blue))
val contentString = contentView.text
val start = contentString.indexOfFirst { it == ':' }
val end = contentView.text.length
val stringBuilder = SpannableString(contentView.text)
val clickableSpan = TLClickableSpan()
stringBuilder.setSpan(clickableSpan, start, end, Spannable.SPAN_EXCLUSIVE_INCLUSIVE)
contentView.text = stringBuilder
其中 TLClickableSpan
簡(jiǎn)單的繼承了 ClickableSpan
:
class TLClickableSpan : ClickableSpan() {
override fun onClick(widget: View) {
Log.i("zc_test", "TLClickableSpan is onClick and view is $widget")
}
}
實(shí)現(xiàn)的效果為:
點(diǎn)擊后的效果遍略, log
提示為 :
2020-05-29 16:50:07.136 5602-5602/com.chendroid.learning I/zc_test: TLClickableSpan is onClick and view is com.google.android.material.textview.MaterialTextView{5773c57 VFED..CL. ...P.... 72,117-1096,223 #7f0800b7 app:id/item_content}
注意事項(xiàng)
代碼中:contentView.movementMethod = LinkMovementMethod.getInstance() 是必須的惧所, 如果不設(shè)置不會(huì)響應(yīng)
ClickableSpan
的點(diǎn)擊。
同時(shí)墅冷,1. 當(dāng)ClickableSpan
生效時(shí),會(huì)觸發(fā)TextView
的監(jiān)聽(tīng)事件或油,消費(fèi)該事件寞忿;
- 當(dāng)點(diǎn)擊
TextView
非點(diǎn)擊部分時(shí),TextView
也會(huì)消費(fèi)該事件顶岸,會(huì)導(dǎo)致本來(lái)應(yīng)該傳遞給ViewGroup
的事件被TextView
攔截腔彰。
為了解決 當(dāng)點(diǎn)擊 TextView
非點(diǎn)擊部分時(shí), TextView
也會(huì)消費(fèi)該事件辖佣, 這個(gè)問(wèn)題霹抛,我們可以設(shè)置:
contentView.movementMethod = LinkMovementMethod.getInstance()
// 不可點(diǎn)擊
contentView.isClickable = false
// 不可長(zhǎng)按
contentView.isLongClickable = false
// 不聚焦
contentView.isFocusable = false
5. 添加原角背景 + 背景透明度設(shè)置
如果我們想要實(shí)現(xiàn)類(lèi)似這樣的效果:
實(shí)現(xiàn)圖中自帶透明度和圓角的「
默認(rèn)
」圖標(biāo)。
代碼如下:
//xml 中的代碼
<TextView
android:id="@+id/todo_type"
android:layout_width="64dp"
android:layout_height="30dp"
android:layout_marginTop="16dp"
android:layout_marginBottom="16dp"
android:background="@drawable/bg_blue_8"
android:gravity="center"
android:text="默認(rèn)"
android:textColor="#0084FF"
android:textSize="15sp"
/>
其中 @drawable/bg_blue_8
為圓角背景, 源碼如下:
// bg_blue_8.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="8dp" />
<solid android:color="#0084FF" />
</shape>
那么如何實(shí)現(xiàn)背景的透明度呢卷谈?
我們不能直接對(duì) TextView
直接設(shè)置 TextView.setAlpha(xxx)
. 因?yàn)檫@樣會(huì)影響到整個(gè) TextView
的透明度杯拐,也會(huì)給字體添加上透明度。
TextView
中有單獨(dú)對(duì) background
設(shè)置的方法世蔗,我們需要這樣設(shè)置:
type = view.todo_type_1
type.apply {
background.alpha = (0.08 * 255).toInt()
...
}
上述代碼即可實(shí)現(xiàn)我們想要的效果端逼。
注:該
UI
設(shè)計(jì)實(shí)現(xiàn)方案有很多種,這里只討論如何只用一個(gè)TextView
實(shí)現(xiàn)污淋。
這樣實(shí)現(xiàn)的目的:盡可能使界面的渲染高效顶滩。避免不必要的內(nèi)存浪費(fèi)。
6. 總結(jié)
記錄了一下寸爆,日常在代碼中利用 TextView
實(shí)現(xiàn)的一些效果礁鲁,
內(nèi)容不難,簡(jiǎn)單的介紹了代碼實(shí)現(xiàn)方式赁豆。
我們還可以利用 TextView
實(shí)現(xiàn)很多樣式的混排效果仅醇, 使用 Html
解析或者設(shè)置 Span
可以解決我們遇到的大部分問(wèn)題。
這篇文章魔种,如有錯(cuò)誤着憨,還請(qǐng)見(jiàn)諒,指出务嫡。
2020.5.30 by chendroid