androidで長いTextViewがあって、一部だけハイパーリンクにするのめちゃくちゃめんどくさいですよね。
ハイパーリンクというか、クリックイベントをとりたかったのですがだいぶめんどくさかったです。
なのでコピペでできるようにしました。
ついでにHTMLタグにも対応できるカスタムtextviewを作りました。
まずはそれを表示するクラスから
HtmlTextActivity.kt
class HtmlTextActivity: AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_html_text)
setHtmlTextView()
}
private fun setHtmlTextView() {
// クリックを検知したいワードをセット
val targets = mutableListOf("ここ", "こっち")
html_textview.setPartialStringClickListener(targets, object: HtmlTextView.Callback {
override fun onClick(tappedText: String) {
when (tappedText) {
"ここ" -> finish()
"こっち" -> {
AlertDialog.Builder(this@HtmlTextActivity)
.setTitle("tapされました")
.setMessage("")
.setPositiveButton("OK"){ _, _ -> }
.show()
}
}
}
})
}
}
setHtmlTextView()くらいしか特筆すべき点はないです。
クリックイベントをとりたいtargetの文字列を指定して、mutableListに入れて、タップされた文字列がコールバックされるように組みました。
次に、肝心なHtmlに対応したTextViewです(今回は改行くらいしかタグを使っていませんがwww)
HtmlTextView.kt
class HtmlTextView: TextView {
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {}
constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle) {}
private var listener: Callback? = null
init {
// htmlに対応させてます。プレビューでもhtmlが有効になるのでとても見やすいです。
this.text = HtmlCompat.fromHtml(this.text.toString(), FROM_HTML_MODE_COMPACT)
}
fun setPartialStringClickListener(targets: MutableList<String>, listener: Callback) {
this.listener = listener
val ss = SpannableString(this.text)
for (target in targets) {
var start = 0
var end = 0
// リンク化対象の文字列の start, end を算出する
val pattern = Pattern.compile(target)
val matcher = pattern.matcher(this.text)
while (matcher.find()) {
start = matcher.start()
end = matcher.end()
break
}
ss.setSpan(object: ClickableSpan() {
override fun onClick(textView: View) {
listener.onClick(target)
}
}, start, end, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
}
this.text = ss
this.movementMethod = LinkMovementMethod.getInstance()
this.highlightColor = Color.TRANSPARENT
}
interface Callback {
fun onClick(clickedStr: String)
}
}
コメントにも書いていますが、プレビューでもhtmlが有効になるのでとても見やすいです(gifはめちゃくちゃめんどくさいのでもう載せませんがww)
一応、HtmlTextViewを使ったときのxmlも載せておきます。
activity_html_text.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.free.myapplication.extension.HtmlTextView
android:id="@+id/html_textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="32dp"
android:layout_centerInParent="true"
android:textColorLink="@android:color/holo_orange_light"
android:text="@string/test_html"/>
</RelativeLayout>
android:textColorLinkってところで色を指定しないとわけわからん色をつけられちゃうので注意です。