一闸天、說明
這是一個(gè)關(guān)于介紹 TextClassification API 的系列文章侥钳,總共分三篇呈枉,本文是最后一篇刹勃。上一篇在此:【翻譯】TextClassification介紹(二)
原文作者:Mark Allison
閱讀時(shí)間: 5 分鐘
原文鏈接:https://blog.stylingandroid.com/textclassification-part-3/
二堪侯、正文
在 API 26 (奧利奧)中安卓引入了一個(gè)新的文字功能系統(tǒng): TextClassification 。這個(gè)系統(tǒng)將會(huì)在 API 28 ( π )中進(jìn)一步改進(jìn)完善深夯。在本次簡(jiǎn)短的系列中抖格,我們主要會(huì)探討它是一個(gè)什么樣的系統(tǒng),如何使用它咕晋,以及如何為它添加一些自定義行為。
上一篇文章中我們開始研究自定義 TextClassifier 的實(shí)現(xiàn)收奔,并研究了如何實(shí)現(xiàn)我們自己的“文本選擇建議”掌呜。在本系列的最后一篇文章中,我們將會(huì)實(shí)現(xiàn)相應(yīng)的 classifyText()
方法坪哄,并應(yīng)用到我們自定義的 TextClassifier 文本分類器的實(shí)現(xiàn)中质蕉。
這里的 classifyText()
方法的實(shí)現(xiàn)實(shí)際上非常簡(jiǎn)單直接。我們檢查選擇的文本是否與請(qǐng)求中所選擇的相匹配翩肌,如果相匹配則返回一個(gè) TextClassification 的實(shí)例模暗,這個(gè)我們稍后再詳細(xì)了解。如果選擇的文本與我們的正則表達(dá)式不匹配念祭,那么我們會(huì)將結(jié)果進(jìn)行回滾(也就是 TextClassifier 的默認(rèn)實(shí)現(xiàn)):
override fun classifyText(request: TextClassification.Request): TextClassification {
//line 36
return if (regex.matches(request.subSequence())) {
factory.buildTextClassification(
//line 38
request.subSequence().toString(),
listOf(TextClassifier.TYPE_URL to 1.0f),
listOf(factory.buildRemoteAction(
context,
R.drawable.ic_stylingandroid,
stylingAndroid,
contentDescription,
stylingAndroidUri
))
)
} else {
fallback.classifyText(request)
}
}
private fun TextClassification.Request.subSequence() =
text.subSequence(startIndex, endIndex)
這里有一個(gè) TextClassification.Request
的擴(kuò)展函數(shù)兑宇,它返回文本中已選擇的子文本 subSequence
,我們正是使用它來匹配正則表達(dá)式(第 36 行)粱坤。然后隶糕,我們構(gòu)建一個(gè) TextClassification 對(duì)象瓷产,它需要一些參數(shù),包括匹配到的字符串(第 38 行)枚驻,分類類型與其各自的可信度分?jǐn)?shù)列表(第 39 行)濒旦,以及一列 RemoteAction 實(shí)例對(duì)象,每個(gè) RemoteAction 對(duì)象對(duì)應(yīng)一個(gè)分類類型條目(第 39-45 行)再登。
這里的 buildRemoteAction()
方法返回每個(gè) RemoteAction 實(shí)例:
override fun buildRemoteAction(
context: Context,
drawableId: Int,
title: String,
contentDescription: String,
uri: String
): RemoteAction {
return RemoteAction(
Icon.createWithResource(context, drawableId),
title,
contentDescription,
PendingIntent.getActivity(
context,
0,
Intent(Intent.ACTION_VIEW, Uri.parse(uri)),
0
)
)
}
這里 RemoteAction 的構(gòu)造函數(shù)需要四個(gè)參數(shù):一個(gè) Icon
對(duì)象尔邓,它將顯示為操作按鈕中的一部分;一個(gè)要顯示的文字锉矢;一個(gè)表示可訪問的內(nèi)容描述梯嗽;最后還需一個(gè) PendingIntent 對(duì)象,它表示用戶在點(diǎn)擊操作按鈕時(shí)將會(huì)執(zhí)行的操作沈撞。在我們的示例代碼中慷荔,我們使用了一個(gè) Styling Android 標(biāo)志圖形作為圖標(biāo),使用了 “Styling Android” 作為標(biāo)題缠俺,以及簡(jiǎn)單的一些內(nèi)容描述显晶,再加一個(gè)能登錄瀏覽器打開 URL 鏈接 "https://blog.stylingandroid.com" 的 PendingIntent 對(duì)象。
buildTextClassification()
函數(shù)使用 TextClassification.Builder 實(shí)例來創(chuàng)建 TextClassification 對(duì)象:
override fun buildTextClassification(
text: String,
entityTypes: List<Pair<String, Float>>,
actions: List<RemoteAction>
): TextClassification {
return TextClassification.Builder()
.run {
setText(text)
entityTypes.forEach { setEntityType(it.first, it.second) }
actions.forEach { addAction(it) }
build()
}
}
這里需要傳遞三個(gè)參數(shù):匹配到的文本壹士,一系列以類型及其對(duì)應(yīng)的可信度范圍作為 Pair
的列表磷雇,以及與每個(gè)類型/置信度組合所對(duì)應(yīng)的 RemoteActions 列表。在這里示例中躏救,這些參數(shù)分別是被選定的子字符串唯笙,包含一對(duì) TextClassifier.TYPE_URL
及其可信度為 1.0f 組成的 Pair
的列表,以及一列包含我們剛剛說過的 RemoteAction 類單例的列表盒使。
TextClassifier 已經(jīng)完成了崩掘,剩下的事情就是將它連接到我們的 TextView 文本控件中:
class MainActivity : AppCompatActivity() {
private val emailText = "dummy@email.com"
private val urlText = "https://blog.stylingandroid.com"
private val hybridText = "Email: $emailText"
private lateinit var textClassificationManager: TextClassificationManager
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
textClassificationManager = getSystemService(Context.TEXT_CLASSIFICATION_SERVICE) as TextClassificationManager
classifier()
text1.textClassifier = StylingAndroidTextClassifier(this, textClassificationManager.textClassifier)
}
private fun classifier() = async(CommonPool) {
val textClassifier = textClassificationManager.textClassifier
val emailClassification = textClassifier.classifyText(emailText, 0, emailText.length, LocaleList.getDefault())
println(emailClassification)
val urlClassification = textClassifier.classifyText(urlText, 0, urlText.length, LocaleList.getDefault())
println(urlClassification)
val suggestions = textClassifier.suggestSelection(hybridText, 10, 11, LocaleList.getDefault())
println(suggestions)
}
}
一行代碼就可以實(shí)現(xiàn)我們要做的一切。我們創(chuàng)建了一個(gè)自定義 TextClassifier 對(duì)象少办,并將其作為參數(shù)傳遞給默認(rèn)的 TextClassifier 對(duì)象的構(gòu)造函數(shù)苞慢,并將 TextView 的 textClassifier
屬性設(shè)置為我們的自定義實(shí)例。
我們目前得到的文本處理行為是:如果用戶長(zhǎng)時(shí)間按下的文字是無法識(shí)別的類型英妓,那就只有簡(jiǎn)單的復(fù)制挽放,粘貼和選擇所有的選項(xiàng)功能;如果他們長(zhǎng)時(shí)間按下系統(tǒng)默認(rèn)的文本分類器所支持的任何類型蔓纠,那么他們會(huì)得到我們?cè)诘谝黄恼轮兴吹降乃邢嗤男袨楹蛣?dòng)作辑畦;但是,如果他們長(zhǎng)按 "Styling Android" 字符串(或者與正則表達(dá)式相匹配的類似字符串)腿倚,那么將獲得我們所自定義的“流行廣告”操作纯出,這個(gè)操作將啟動(dòng)瀏覽器并登錄加載鏈接: https://blog.stylingandroid.com :
在 TextClassifier 文本分類器中還有一個(gè)機(jī)制,用來識(shí)別具體的文本類型,然后使用文本生成鏈接潦刃,不過在本系列文章中我們不會(huì)去研究它侮措,因?yàn)槲覀冞@里所看到的技術(shù)已經(jīng)涵蓋了 TextView 和 WebView 內(nèi)置的一些主要功能。如果看到這里有人對(duì)此感興趣乖杠,那么請(qǐng)告訴我分扎,我將會(huì)單獨(dú)寫一篇文章作詳細(xì)說明。
三胧洒、總結(jié)
這篇文章的源代碼可以在這里找到: https://github.com/StylingAndroid/TextClassification/tree/Part3畏吓。
? 2018 , Mark Allison 卫漫。保留所有版權(quán)菲饼。
我的博客地址: http://liuqingwen.me ,歡迎關(guān)注我的微信公眾號(hào):