diff --git a/kotlin-extensions/src/main/java/ru/touchin/extensions/CharSequence.kt b/kotlin-extensions/src/main/java/ru/touchin/extensions/CharSequence.kt new file mode 100644 index 0000000..bd4fe7d --- /dev/null +++ b/kotlin-extensions/src/main/java/ru/touchin/extensions/CharSequence.kt @@ -0,0 +1,3 @@ +package ru.touchin.extensions + +fun CharSequence.indexesOf(substring: String) = Regex(substring).find(this)?.let { it.range.first to it.range.last + 1 } diff --git a/utils/build.gradle b/utils/build.gradle index 2a77fe4..2a490af 100644 --- a/utils/build.gradle +++ b/utils/build.gradle @@ -1,6 +1,7 @@ apply from: "../android-configs/lib-config.gradle" dependencies { + implementation project(':kotlin-extensions') implementation "androidx.core:core" implementation "androidx.annotation:annotation" diff --git a/utils/src/main/java/ru/touchin/roboswag/components/utils/spans/SpanUtils.kt b/utils/src/main/java/ru/touchin/roboswag/components/utils/spans/SpanUtils.kt index 25b6fec..b69a0cd 100644 --- a/utils/src/main/java/ru/touchin/roboswag/components/utils/spans/SpanUtils.kt +++ b/utils/src/main/java/ru/touchin/roboswag/components/utils/spans/SpanUtils.kt @@ -2,9 +2,15 @@ package ru.touchin.roboswag.components.utils.spans import android.text.SpannableString import android.text.Spanned +import android.text.TextPaint +import android.text.style.ClickableSpan +import android.text.style.ForegroundColorSpan import android.text.style.URLSpan import android.text.util.Linkify +import android.view.View +import androidx.annotation.ColorInt import androidx.core.text.HtmlCompat +import ru.touchin.extensions.indexesOf /** * Convert text with 'href' tags and raw links to spanned text with clickable URLSpan. @@ -47,3 +53,28 @@ private fun SpannableString.getUrlSpans() = getSpans(0, length, URLSpan::class.j .map { UrlSpanWithBorders(it, this.getSpanStart(it), this.getSpanEnd(it)) } private data class UrlSpanWithBorders(val span: URLSpan, val start: Int, val end: Int) + +/** + * Find substring inside string (for example in TextView) and fill it with ClickableSpan + */ +fun CharSequence.toClickableSubstringText( + substring: String, + clickAction: () -> Unit, + @ColorInt color: Int? = null, + isUnderlineText: Boolean = false +) = SpannableString(this) + .apply { + indexesOf(substring)?.let { (startSpan, endSpan) -> + setSpan(object : ClickableSpan() { + override fun onClick(widget: View) { + clickAction.invoke() + } + + override fun updateDrawState(ds: TextPaint) { + super.updateDrawState(ds) + ds.isUnderlineText = isUnderlineText + if (color != null) ds.color = color + } + }, startSpan, endSpan, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) + } + } diff --git a/views/src/main/java/ru/touchin/roboswag/views/ActionTextView.kt b/views/src/main/java/ru/touchin/roboswag/views/ActionTextView.kt new file mode 100644 index 0000000..39d3ffd --- /dev/null +++ b/views/src/main/java/ru/touchin/roboswag/views/ActionTextView.kt @@ -0,0 +1,44 @@ +package ru.touchin.roboswag.views + +import android.content.Context +import android.graphics.Color +import android.util.AttributeSet +import androidx.appcompat.widget.AppCompatTextView +import androidx.core.content.withStyledAttributes +import ru.touchin.roboswag.components.utils.movementmethods.ClickableMovementMethod +import ru.touchin.roboswag.components.utils.spans.toClickableSubstringText + +class ActionTextView @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : AppCompatTextView(context, attrs, defStyleAttr) { + + private var onClickAction: () -> Unit = { } + + init { + isClickable = false + isLongClickable = false + highlightColor = Color.TRANSPARENT + + movementMethod = ClickableMovementMethod + + context.withStyledAttributes(attrs, R.styleable.ActionTextView, defStyleAttr, 0) { + val actionText = getString(R.styleable.ActionTextView_actionText).orEmpty() + val actionColor = getColor(R.styleable.ActionTextView_actionColor, currentTextColor) + val isUnderlineText = getBoolean(R.styleable.ActionTextView_isUnderlineText, false) + + text = text.toClickableSubstringText( + substring = actionText, + clickAction = { onClickAction.invoke() }, + color = actionColor, + isUnderlineText = isUnderlineText + ) + } + } + + fun setOnActionClickListener(onClickAction: () -> Unit) { + this.onClickAction = onClickAction + } + +} diff --git a/views/src/main/res/values/attrs.xml b/views/src/main/res/values/attrs.xml index b8dce82..9b154af 100644 --- a/views/src/main/res/values/attrs.xml +++ b/views/src/main/res/values/attrs.xml @@ -50,4 +50,10 @@ + + + + + +