@@ -2,79 +2,117 @@ package com.alonew0lfxx.itm
22
33import android.annotation.SuppressLint
44import android.content.Context
5+ import android.graphics.Canvas
6+ import android.graphics.Typeface
57import android.util.AttributeSet
8+ import android.util.Log
69import android.util.TypedValue
710import androidx.appcompat.widget.AppCompatTextView
811import androidx.core.content.res.ResourcesCompat
912import androidx.core.content.withStyledAttributes
1013
11- class InteractiveTextView : AppCompatTextView {
14+ class InteractiveTextView (
15+ context : Context ,
16+ attrs : AttributeSet ?
17+ ) : AppCompatTextView(context, attrs) {
1218
1319 private val listeners = mutableListOf< (index: Int ) -> Unit > ()
14- private var attrs: AttributeSet ? = null
1520
16- constructor (context: Context ) : super (context)
17- constructor (context: Context , attrs: AttributeSet ) : super (context, attrs) {
18- this .attrs = attrs
19- }
21+ // Attributes.
22+ private var colorPrimary: Int? = 0
23+ private var specialTextColor: Int? = 0
24+ private var specialTextHighlightColor: Int? = 0
25+ private var specialTextUnderlined: Boolean? = false
26+ private var allTextUnderlined: Boolean? = false
27+ private var specialTextSize: Float? = 0f
28+ private var specialTextFontFamily: Typeface ? = null
29+ private var specialTextSeparator: String? = null
30+ private lateinit var previousString: String
2031
21- constructor (context: Context , attrs: AttributeSet , defStyle: Int ) : super (
22- context,
23- attrs,
24- defStyle
25- ) {
26- this .attrs = attrs
27- }
2832
29- @SuppressLint( " SetTextI18n " )
30- fun initialize ( context : Context , attrs : AttributeSet ? ) {
33+ init {
34+ Log .d( TAG , " null() called " )
3135 context.withStyledAttributes(attrs, R .styleable.InteractiveTextView ) {
32- val colorPrimary = TypedValue ().let {
36+ colorPrimary = TypedValue ().let {
3337 getContext().theme.resolveAttribute(android.R .attr.colorPrimary, it, true )
3438 it.data
3539 }
36- val specialTextColor =
37- getColor(R .styleable.InteractiveTextView_specialTextColor , colorPrimary)
38- val specialTextHighlightColor =
40+ specialTextSeparator =
41+ getString(R .styleable.InteractiveTextView_specialTextSeparator ) ? : " __"
42+ specialTextColor =
43+ getColor(R .styleable.InteractiveTextView_specialTextColor , colorPrimary!! )
44+ specialTextHighlightColor =
3945 getColor(R .styleable.InteractiveTextView_specialTextHighlightColor , - 1 )
40- val specialTextUnderlined =
46+ specialTextUnderlined =
4147 getBoolean(R .styleable.InteractiveTextView_specialTextUnderlined , false )
42- val allTextUnderlined =
48+ allTextUnderlined =
4349 getBoolean(R .styleable.InteractiveTextView_allTextUnderlined , false )
44- val specialTextSize = getDimension(
50+ specialTextSize = getDimension(
4551 R .styleable.InteractiveTextView_specialTextSize ,
4652 this @InteractiveTextView.textSize
4753 )
48- val specialTextFontFamily = try {
54+ specialTextFontFamily = try {
4955 val fontId =
5056 getResourceId(R .styleable.InteractiveTextView_specialTextFontFamily , - 1 )
51- ResourcesCompat .getFont(context, fontId)
57+ ResourcesCompat .getFont(context, fontId)!!
5258 } catch (e: Exception ) {
5359 this @InteractiveTextView.typeface!!
5460 }
55- val specialTextSeparator =
56- getString(R .styleable.InteractiveTextView_specialTextSeparator ) ? : " __"
57- if (allTextUnderlined) text = " $specialTextSeparator${text}$specialTextSeparator "
58- InteractiveTextMaker .of(this @InteractiveTextView)
59- .also {
60- it.setSpecialTextColor(specialTextColor)
61- it.setSpecialTextSeparator(specialTextSeparator)
62- it.setSpecialTextUnderLined(specialTextUnderlined)
63- it.setSpecialTextSize(specialTextSize)
64- it.setSpecialTextFontFamily(specialTextFontFamily!! )
65- if (specialTextHighlightColor != - 1 )
66- it.setSpecialTextHighlightColor(specialTextHighlightColor)
67- }
68- .setOnTextClickListener { index -> listeners.forEach { it(index) } }
69- .initialize()
61+ Log .d(TAG , " specialTextSeparator: $specialTextSeparator " )
7062 }
63+ initialize(context)
7164 }
7265
66+
67+ /*
68+ * I don't how that's happening but I managed to fix the
69+ * ```
70+ * Parameter specified as non-null is null: method kotlin.jvm.internal.Intrinsics.checkNotNullParameter, parameter separator
71+ * ```
72+ * crash with null controls at initialize function. In somehow the variables like "specialTextSeparator" become null after
73+ * the setText() method runs.
74+ *
75+ */
76+ @SuppressLint(" SetTextI18n" )
77+ fun initialize (context : Context ) {
78+ Log .d(TAG , " initialize() called with: $specialTextSeparator " )
79+ if (allTextUnderlined == null ) return
80+ if (specialTextColor == null ) return
81+ if (specialTextSeparator == null ) return
82+ if (specialTextUnderlined == null ) return
83+ if (specialTextSize == null ) return
84+ if (specialTextFontFamily == null ) return
85+ if (specialTextHighlightColor == null ) return
86+ if (allTextUnderlined!! ) text = " $specialTextSeparator${text}$specialTextSeparator "
87+ InteractiveTextMaker .of(this @InteractiveTextView)
88+ .also {
89+ it.setSpecialTextColor(specialTextColor!! )
90+ it.setSpecialTextSeparator(specialTextSeparator!! )
91+ it.setSpecialTextUnderLined(specialTextUnderlined!! )
92+ it.setSpecialTextSize(specialTextSize!! )
93+ it.setSpecialTextFontFamily(specialTextFontFamily!! )
94+ if (specialTextHighlightColor != - 1 )
95+ it.setSpecialTextHighlightColor(specialTextHighlightColor!! )
96+ }
97+ .setOnTextClickListener { index -> listeners.forEach { it(index) } }
98+ .initialize()
99+ }
100+
101+ /*
102+ * InteractiveTextMaker uses .setText method to work. It'll gonna create a [setText] loop.
103+ * to block that I'm gonna use previousString variable to capture every string. and compare with
104+ * previous one.
105+ *
106+ * If anyone knows how to make this in right way please contact me :)
107+ */
73108 override fun setText (text : CharSequence? , type : BufferType ? ) {
109+ if (this ::previousString.isInitialized && previousString == text) return
110+ previousString = text.toString()
74111 super .setText(text, type)
75- initialize(context, attrs )
112+ initialize(context)
76113 }
77114
115+
78116 /* *
79117 * Whenever a special word has been clicked this [function] will be run with index
80118 * of the word.
@@ -83,4 +121,8 @@ class InteractiveTextView : AppCompatTextView {
83121 listeners.add(function)
84122 }
85123
124+ companion object {
125+ private const val TAG = " InteractiveTextView"
126+ }
127+
86128}
0 commit comments