11package com.mindorks.editdrawabletext
22
33import android.content.Context
4+ import android.content.res.TypedArray
45import android.graphics.Rect
56import android.graphics.drawable.Drawable
7+ import android.text.Editable
8+ import android.text.TextWatcher
69import android.util.AttributeSet
710import android.view.MotionEvent
811import android.widget.EditText
912import kotlin.math.abs
1013
11- class EditDrawableText : EditText {
14+ class EditDrawableText ( context : Context , attrs : AttributeSet ) : EditText(context, attrs) {
1215
1316 private var drawableRight: Drawable ? = null
1417 private var drawableLeft: Drawable ? = null
1518 private var drawableTop: Drawable ? = null
1619 private var drawableBottom: Drawable ? = null
1720 private var positionX: Int = 0
1821 private var positionY: Int = 0
19-
22+ private var isDrawableShownWhenTextIsEmpty = true
2023 private var onDrawableClickListener: OnDrawableClickListener ? = null
2124
22- constructor (context: Context , attrs: AttributeSet ) : super (context, attrs)
2325
24- constructor (context: Context , attrs: AttributeSet , defStyle: Int ) : super (context, attrs, defStyle)
26+ init {
27+ parseAttributes(
28+ context.obtainStyledAttributes(
29+ attrs,
30+ R .styleable.EditDrawableText
31+ )
32+ )
33+ }
34+
35+
36+ private fun parseAttributes (obtainStyledAttributes : TypedArray ) {
37+ isDrawableShownWhenTextIsEmpty = obtainStyledAttributes.getBoolean(R .styleable.EditDrawableText_isDrawableShownWhenTextIsEmpty , isDrawableShownWhenTextIsEmpty);
38+ obtainStyledAttributes.recycle()
39+ hasDrawable(isDrawableShownWhenTextIsEmpty)
40+ }
41+
42+ private fun hasDrawable (value : Boolean ) {
43+ isDrawableShownWhenTextIsEmpty = value
44+ if (! isDrawableShownWhenTextIsEmpty) this .setCompoundDrawablesWithIntrinsicBounds(0 , 0 , 0 , 0 )
45+ invalidate()
46+ }
2547
2648 override fun setCompoundDrawables (leftDrawable : Drawable ? ,
2749 topDrawable : Drawable ? ,
@@ -33,106 +55,129 @@ class EditDrawableText : EditText {
3355 if (bottomDrawable != null ) drawableBottom = bottomDrawable
3456 super .setCompoundDrawables(leftDrawable, topDrawable, rightDrawable, bottomDrawable)
3557 }
36-
58+
3759 override fun onTouchEvent (event : MotionEvent ): Boolean {
3860 var bounds: Rect ?
39- if (event.action == MotionEvent .ACTION_DOWN ) {
40- positionX = event.x.toInt()
41- positionY = event.y.toInt()
42-
43-
44- // this works for left since container shares 0,0 origin with bounds
45- if (drawableLeft != null ) {
46- bounds = drawableLeft!! .bounds
47-
48- var xClickPosition: Int
49- var yClickPosition: Int
50- /*
51- * @return pixels into dp
52- */
53- val extraClickArea = (13 * resources.displayMetrics.density + 0.5 ).toInt()
61+ val editText = this
62+ this .addTextChangedListener(object : TextWatcher {
63+ override fun afterTextChanged (p0 : Editable ? ) {
5464
55- xClickPosition = positionX
56- yClickPosition = positionY
65+ }
5766
58- if (! bounds!! .contains(positionX, positionY)) {
59- /* * Gives some extra space for tapping. */
60- xClickPosition = positionX - extraClickArea
61- yClickPosition = positionY - extraClickArea
67+ override fun beforeTextChanged (p0 : CharSequence? , p1 : Int , p2 : Int , p3 : Int ) {
68+ }
6269
63- if (xClickPosition <= 0 ) xClickPosition = positionX
64- if (yClickPosition <= 0 ) yClickPosition = positionY
70+ override fun onTextChanged (char : CharSequence , p1 : Int , p2 : Int , p3 : Int ) {
71+ if (char.isEmpty()) {
72+ if (! isDrawableShownWhenTextIsEmpty) editText.setCompoundDrawablesWithIntrinsicBounds(0 , 0 , 0 , 0 )
73+ } else editText.setCompoundDrawables(drawableLeft, drawableTop, drawableRight, drawableBottom)
74+ }
6575
66- /* * Creates square from the smallest value from x or y*/
67- if (xClickPosition < yClickPosition) yClickPosition = xClickPosition
68- }
6976
70- if (bounds.contains(xClickPosition, yClickPosition) && onDrawableClickListener != null ) {
71- onDrawableClickListener !! .onClick( DrawablePosition . LEFT )
72- event.action = MotionEvent . ACTION_CANCEL
73- return false
77+ })
78+ if (event.action == MotionEvent . ACTION_DOWN ) {
79+ positionX = event.x.toInt()
80+ positionY = event.y.toInt()
7481
75- }
82+ // this works for left since container shares 0,0 origin with bounds
83+ if (drawableLeft != null ) {
84+ bounds = drawableLeft?.bounds
85+ setupDrawableLeftClick(bounds, event)
7686 }
77-
87+
7888 if (drawableRight != null ) {
79- bounds = drawableRight!! .bounds
80- var xClickPosition: Int
81- var yClickPosition: Int
82- val extraClickingArea = 13
83-
84- xClickPosition = positionX + extraClickingArea
85- yClickPosition = positionY - extraClickingArea
86-
87- /* *
88- * It right drawable -> subtract the value of x from the width of view. so that width - tapped area * will result in x co-ordinate in drawable bound.
89- */
90- xClickPosition = width - xClickPosition
91- if (xClickPosition <= 0 ) xClickPosition + = extraClickingArea
92-
93- /* If after calculating for extra clickable area is negative.
94- * assign the original value so that after subtracting
95- * extra clicking area value doesn't go into negative value.
96- */
97-
98- if (yClickPosition <= 0 ) yClickPosition = positionY
99-
100- /* *If drawable bounds contains the x and y points then move ahead. */
101- if (bounds!! .contains(xClickPosition, yClickPosition) && onDrawableClickListener != null ) {
102- onDrawableClickListener!! .onClick(DrawablePosition .RIGHT )
103- event.action = MotionEvent .ACTION_CANCEL
104- return false
105- }
106- return super .onTouchEvent(event)
89+ bounds = drawableRight?.bounds
90+ setupDrawableRightClick(bounds, event)
10791 }
10892
10993 if (drawableTop != null ) {
110- bounds = drawableTop!! .bounds
111- val extraClickingArea = 13
112- if (abs((width - paddingLeft - paddingRight) / 2 + paddingLeft - positionX) <= bounds.width() / 2 + extraClickingArea) {
113- onDrawableClickListener!! .onClick(DrawablePosition .TOP )
114- event.action = MotionEvent .ACTION_CANCEL
115- return false
116- }
94+ bounds = drawableTop?.bounds
95+ setupDrawableTopClick(bounds, event)
11796 }
11897
119- if (drawableBottom!= null )
120- {
121- bounds = drawableBottom!! .bounds
122- val extraClickingArea = 13
123-
124- if (abs((width - paddingLeft - paddingRight) / 2 + paddingLeft - positionX) <= bounds.width() / 2 + extraClickingArea) {
125- onDrawableClickListener!! .onClick(DrawablePosition .BOTTOM )
126- event.action = MotionEvent .ACTION_CANCEL
127- return false
128- }
98+ if (drawableBottom != null ) {
99+ bounds = drawableBottom?.bounds
100+ setupDrawableBottomClick(bounds, event)
129101 }
130102
131103
132104 }
133105 return super .onTouchEvent(event)
134106 }
135107
108+ private fun setupDrawableBottomClick (bounds : Rect ? , event : MotionEvent ) {
109+ val extraClickingArea = 13
110+ if (abs((width - paddingLeft - paddingRight) / 2 + paddingLeft - positionX) <= bounds!! .width() / 2 + extraClickingArea) {
111+ onDrawableClickListener?.onClick(DrawablePosition .BOTTOM )
112+ event.action = MotionEvent .ACTION_CANCEL
113+ }
114+ }
115+
116+ private fun setupDrawableTopClick (bounds : Rect ? , event : MotionEvent ) {
117+ val extraClickingArea = 13
118+ if (abs((width - paddingLeft - paddingRight) / 2 + paddingLeft - positionX) <= bounds!! .width() / 2 + extraClickingArea) {
119+ onDrawableClickListener?.onClick(DrawablePosition .TOP )
120+ event.action = MotionEvent .ACTION_CANCEL
121+ }
122+ }
123+
124+ private fun setupDrawableLeftClick (bounds : Rect ? , event : MotionEvent ) {
125+ var xClickPosition: Int
126+ var yClickPosition: Int
127+ /*
128+ * @return pixels into dp
129+ */
130+ val extraClickArea = (13 * resources.displayMetrics.density + 0.5 ).toInt()
131+
132+ xClickPosition = positionX
133+ yClickPosition = positionY
134+
135+ if (! bounds!! .contains(positionX, positionY)) {
136+ /* * Gives some extra space for tapping. */
137+ xClickPosition = positionX - extraClickArea
138+ yClickPosition = positionY - extraClickArea
139+
140+ if (xClickPosition <= 0 ) xClickPosition = positionX
141+ if (yClickPosition <= 0 ) yClickPosition = positionY
142+
143+ /* * Creates square from the smallest value from x or y*/
144+ if (xClickPosition < yClickPosition) yClickPosition = xClickPosition
145+ }
146+
147+ if (bounds.contains(xClickPosition, yClickPosition) && onDrawableClickListener != null ) {
148+ onDrawableClickListener?.onClick(DrawablePosition .LEFT )
149+ event.action = MotionEvent .ACTION_CANCEL
150+
151+ }
152+ }
153+
154+ private fun setupDrawableRightClick (bounds : Rect ? , event : MotionEvent ) {
155+ var xClickPosition: Int
156+ var yClickPosition: Int
157+ val extraClickingArea = 13
158+
159+ xClickPosition = positionX + extraClickingArea
160+ yClickPosition = positionY - extraClickingArea
161+
162+ /* *
163+ * It right drawable -> subtract the value of x from the width of view. so that width - tapped area * will result in x co-ordinate in drawable bound.
164+ */
165+ xClickPosition = width - xClickPosition
166+ if (xClickPosition <= 0 ) xClickPosition + = extraClickingArea
167+
168+ /* If after calculating for extra clickable area is negative.
169+ * assign the original value so that after subtracting
170+ * extra clicking area value doesn't go into negative value.
171+ */
172+
173+ if (yClickPosition <= 0 ) yClickPosition = positionY
174+
175+ /* *If drawable bounds contains the x and y points then move ahead. */
176+ if (bounds!! .contains(xClickPosition, yClickPosition) && onDrawableClickListener != null ) {
177+ onDrawableClickListener?.onClick(DrawablePosition .RIGHT )
178+ event.action = MotionEvent .ACTION_CANCEL
179+ }
180+ }
136181
137182 fun setDrawableClickListener (OnDrawableClickListener : OnDrawableClickListener ) {
138183 this .onDrawableClickListener = OnDrawableClickListener
0 commit comments