Encapsulation of hyperlink implementation of Android color text (Application of kotlin extension function)

Posted by taha on Thu, 27 Jan 2022 13:00:48 +0100

1, Foreword

Recently, we encountered such a problem when designing the interface. We can often see such an interface, which tells users the privacy terms and user agreement, and these color words directly point to the corresponding links

At that time, the original idea was to set up multiple textviews to realize it. However, there would be a problem. Such a simple function uses five controls, which is too embarrassing. Moreover, the text alignment needs to be adjusted by itself. It is unnatural. After searching, the implementation method is not difficult, but there is no better encapsulation, So today I'll show you how to encapsulate a colorText method with kotlin's extension function. I have to praise kotlin's extension function, which is really easy to use.

2, Design click event

First, you need to create a container for SpannableStringBuilder to apply click events and so on

val style = SpannableStringBuilder()
val parent = "I have read and agree to the user agreement and privacy policy"
val colorText = "User agreement"
//Find the subscript of the first colorText
val index = indexOf(colorText,0)
style.append(parent)

Then let's set the click event

//It is equivalent to overriding the method of a click event in an anonymous class
val clickableSpan = object : ClickableSpan(){
    override fun onClick(widget: View) {
        //Specific events
    }
}
//The first parameter is the option to set the click event, the second is the position of colorText in the parent, the second is the position of the last text, and the third is a fixed parameter
style.setSpan(clickableSpan, index, index+colorText.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)

So far, the current colorText has the click of events

3, Set no underline

This part is also very important. You added an inexplicable underline without setting your text

First, you need to create a class to make an underline

class NoUnderlineSpan: UnderlineSpan(){
    override fun updateDrawState(ds: TextPaint) {
        super.updateDrawState(ds)
        ds.color = ds.linkColor
        ds.isUnderlineText = false
    }
}

Finally, set it

//The parameters here are similar to those in the previous one. The first one is to set no underline. 2 and 3 are the same as above. The fourth option is replaced
val noUnderlineSpan = NoUnderlineSpan()
style.setSpan(noUnderlineSpan,index , index+colorText.length, Spanned.SPAN_MARK_MARK)

4, Set color

Set the color of the link. This part is similar to the above. Set the foreground color. Other parameters are similar

val foregroundColorSpan = ForegroundColorSpan(Color.parseColor("#118EEA"))
style.setSpan(foregroundColorSpan, index, index+colorText.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)

Finally, you need to apply it to realize the click event of color link

MyTextView.movementMethod = LinkMovementMethod.getInstance()
MyTextView.text = style

5, Encapsulation

After talking about it in parts, the next step is the most wonderful encapsulation, which uses Kotlin's extension function

  • First, analyze that the class to be extended is TextView class. In this way, any control that inherits TextView class can use the function of this extension function
  • Secondly, analyze the required parameters, which should be functional parameters that require complete text, colorText, colorString and click events. Later, think about it wrong. You already have its context in TextView and can directly obtain the complete text. Therefore, finally, you need three parameters, colorText, colorString and functional parameters

The following is the final package. It looks very long, but it is very convenient to use

//The text may not be found here. If an error occurs, remember to check whether the text is correct
class NoUnderlineSpan: UnderlineSpan(){
    override fun updateDrawState(ds: TextPaint) {
        super.updateDrawState(ds)
        ds.color = ds.linkColor
        ds.isUnderlineText = false
    }
}
fun TextView.colorText(colorText:String, color:String, click:()->Unit){
    val style = SpannableStringBuilder()
    val index = text.indexOf(colorText,0)
    style.append(text)
    val clickableSpan = object : ClickableSpan(){
        override fun onClick(widget: View) {
            click()
        }
    }
    style.setSpan(clickableSpan, index, index+colorText.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
    val noUnderlineSpan = NoUnderlineSpan()
    style.setSpan(noUnderlineSpan,index , index+colorText.length, Spanned.SPAN_MARK_MARK)
    val foregroundColorSpan = ForegroundColorSpan(Color.parseColor(color))
    style.setSpan(foregroundColorSpan, index, index+colorText.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
    movementMethod = LinkMovementMethod.getInstance()
    text = style
}

Its use

myTextView.colorText("User agreement","#118EEA"){
   //Own click events
}

6, Summary

The encapsulation is generally good. It simplifies the code and applies Kotlin's knowledge. Welcome to leave a message

Topics: Java Android kotlin TextView