Skip to content

Commit 770c31a

Browse files
committed
Add touch event handling in AztecText when field is disabled
1 parent 329c368 commit 770c31a

File tree

2 files changed

+76
-0
lines changed

2 files changed

+76
-0
lines changed

aztec/src/main/kotlin/org/wordpress/aztec/AztecText.kt

+6
Original file line numberDiff line numberDiff line change
@@ -756,6 +756,12 @@ open class AztecText : AppCompatEditText, TextWatcher, UnknownHtmlSpan.OnUnknown
756756
}
757757
}
758758

759+
// We need to handle touch events to links if they are disabled.
760+
if (!isEnabled &&
761+
EnhancedMovementMethod.handleLinkTouchEvent(widget = this, text = text, event = event).handled) {
762+
return false
763+
}
764+
759765
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P
760766
&& event.action == MotionEvent.ACTION_DOWN) {
761767
// we'll use these values in OnLongClickListener

aztec/src/main/kotlin/org/wordpress/aztec/EnhancedMovementMethod.kt

+70
Original file line numberDiff line numberDiff line change
@@ -100,4 +100,74 @@ object EnhancedMovementMethod : ArrowKeyMovementMethod() {
100100

101101
return super.onTouchEvent(widget, text, event)
102102
}
103+
104+
fun handleLinkTouchEvent(widget: TextView, text: Spannable, event: MotionEvent): LinkTouchEventResult {
105+
var x = event.x.toInt()
106+
var y = event.y.toInt()
107+
108+
x -= widget.totalPaddingLeft
109+
y -= widget.totalPaddingTop
110+
111+
x += widget.scrollX
112+
y += widget.scrollY
113+
114+
val layout = widget.layout
115+
val line = layout.getLineForVertical(y)
116+
val off = layout.getOffsetForHorizontal(line, x.toFloat())
117+
118+
// get the character's position. This may be the left or the right edge of the character so, find the
119+
// other edge by inspecting nearby characters (if they exist)
120+
val charX = layout.getPrimaryHorizontal(off)
121+
val charPrevX = if (off > 0) layout.getPrimaryHorizontal(off - 1) else charX
122+
val charNextX = if (off < text.length) layout.getPrimaryHorizontal(off + 1) else charX
123+
124+
val lineRect = Rect()
125+
layout.getLineBounds(line, lineRect)
126+
127+
val clickedWithinLineHeight = y >= lineRect.top && y <= lineRect.bottom
128+
val clickedOnSpanToTheLeftOfCursor = x.toFloat() in charPrevX..charX
129+
val clickedOnSpanToTheRightOfCursor = x.toFloat() in charX..charNextX
130+
131+
val clickedOnSpan = clickedWithinLineHeight &&
132+
(clickedOnSpanToTheLeftOfCursor || clickedOnSpanToTheRightOfCursor)
133+
134+
val clickedSpanBordersAnotherOne = (text.getSpans(off, off, ClickableSpan::class.java).size == 1 &&
135+
text.getSpans(off + 1, off + 1, ClickableSpan::class.java).isNotEmpty())
136+
137+
val isClickedSpanAmbiguous = text.getSpans(off, off, ClickableSpan::class.java).size > 1
138+
139+
val failedToPinpointClickedSpan = (isClickedSpanAmbiguous || clickedSpanBordersAnotherOne)
140+
&& !clickedOnSpanToTheLeftOfCursor && !clickedOnSpanToTheRightOfCursor
141+
142+
var link: ClickableSpan? = null
143+
144+
if (clickedOnSpan) {
145+
link = if (isClickedSpanAmbiguous) {
146+
if (clickedOnSpanToTheLeftOfCursor) {
147+
text.getSpans(off, off, ClickableSpan::class.java)[0]
148+
} else {
149+
text.getSpans(off, off, ClickableSpan::class.java)[1]
150+
}
151+
} else {
152+
text.getSpans(off, off, ClickableSpan::class.java).firstOrNull()
153+
}
154+
} else if (failedToPinpointClickedSpan) {
155+
link = text.getSpans(off, off, ClickableSpan::class.java).firstOrNull { text.getSpanStart(it) == off }
156+
}
157+
158+
if (link != null) {
159+
if (link is AztecMediaClickableSpan || link is UnknownClickableSpan) {
160+
link.onClick(widget)
161+
return LinkTouchEventResult(true)
162+
} else if (link is AztecURLSpan && isLinkTapEnabled) {
163+
linkTappedListenerRef.get()?.onLinkTapped(widget, link.url) ?: link.onClick(widget)
164+
return LinkTouchEventResult(true)
165+
}
166+
}
167+
168+
return LinkTouchEventResult(false)
169+
}
103170
}
171+
172+
@JvmInline
173+
value class LinkTouchEventResult(val handled: Boolean)

0 commit comments

Comments
 (0)