情報系人間のブログ

プログラミング、開発に関することを書いていきます。

特定文字をリンクするTextView

特定の文字をリンクにしたいときに使うTextView

LinkableTextView.kt

class LinkableTextView @JvmOverloads constructor(
        context: Context,
        attrs: AttributeSet? = null
) : TextView(context, attrs) {

    private var target = ""
    private var color = 0
    private var linkBold = false
    var listener: Listener? = null

    init {
        val a = context.theme.obtainStyledAttributes(
                attrs,
                R.styleable.LinkableTextView,
                0, 0)

        try {
            target = a.getString(R.styleable.LinkableTextView_target)
            color = a.getColor(R.styleable.LinkableTextView_link_color, 0)
            linkBold  = a.getBoolean(R.styleable.LinkableTextView_link_bold, false)
        } finally {
            a.recycle()
        }
    }

    override fun setText(text: CharSequence?, type: BufferType?) {
        if (TextUtils.isEmpty(target)) {
            super.setText(text, type)
            return
        }
        val p1 = Pattern.compile(target)
        val m1 = p1.matcher(text)
        val ss = SpannableString(text)

        if (m1.find()) {
            val start = m1.start()
            val end = m1.end()
            movementMethod = LinkMovementMethod.getInstance()
            ss.setSpan(object : ClickableSpan() {
                override fun onClick(widget: View) {
                    listener?.onLinkClick()
                }
            }, start, end, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
            if (color != 0) {
                ss.setSpan(ForegroundColorSpan(color), start, end, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
            }
            if (linkBold) {
                ss.setSpan(StyleSpan(Typeface.BOLD), start, end, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
            }
        }
        super.setText(ss, type)
    }

    interface Listener {
        fun onLinkClick()
    }

}

attr.xmlから要素を取得しその値に応じてリンクさせたい文字列や見た目を設定していきます。 targetはリンクさせたい文字列、colorはリンクさせたい文字列の色、linkBoldリンクさせたい文字列がBoldかどうか を指定します。

attrs.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="LinkableTextView">
        <attr name="link_color" format="color"/>
        <attr name="target" format="string"/>
        <attr name="link_bold" format="boolean"/>
    </declare-styleable>
</resources> 

上記した3つの要素を指定しています。

使い方

xmlで置くときに3つの要素に値を設定します。

     <LinkableTextView
            android:id="@+id/id"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="20sp"
            android:text="text"
            android:textColor="@color/your_color"
            app:target="target"
            app:link_color="@color/your_color"
            />

コードでリンクをクリックした際の動作を書きます。

   binding.linkableTextView.text = "text"
   binding.linkableTextViewlistener = object: LinkableTextView.Listener {
             override fun onLinkClick() {
                //do something
             }
    }