Skip to content

Commit d260add

Browse files
authored
Merge pull request #415 from wordpress-mobile/issue/396-improving-image-click-detection
Improving hit detection of clickable span.
2 parents 6b4a9d7 + 5861f8d commit d260add

File tree

1 file changed

+37
-14
lines changed

1 file changed

+37
-14
lines changed

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

Lines changed: 37 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ object EnhancedMovementMethod : ArrowKeyMovementMethod() {
1616
override fun onTouchEvent(widget: TextView, text: Spannable, event: MotionEvent): Boolean {
1717
val action = event.action
1818

19-
if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_DOWN) {
19+
if (action == MotionEvent.ACTION_UP) {
2020
var x = event.x.toInt()
2121
var y = event.y.toInt()
2222

@@ -26,13 +26,11 @@ object EnhancedMovementMethod : ArrowKeyMovementMethod() {
2626
x += widget.scrollX
2727
y += widget.scrollY
2828

29+
if(x < 0) return true
30+
2931
val layout = widget.layout
3032
val line = layout.getLineForVertical(y)
31-
var off = layout.getOffsetForHorizontal(line, x.toFloat())
32-
33-
if (text.length > off) {
34-
off++
35-
}
33+
val off = layout.getOffsetForHorizontal(line, x.toFloat())
3634

3735
// get the character's position. This may be the left or the right edge of the character so, find the
3836
// other edge by inspecting nearby characters (if they exist)
@@ -43,17 +41,42 @@ object EnhancedMovementMethod : ArrowKeyMovementMethod() {
4341
val lineRect = Rect()
4442
layout.getLineBounds(line, lineRect)
4543

46-
if (((x in charPrevX..charX) || (x in charX..charNextX))
47-
&& y >= lineRect.top && y <= lineRect.bottom) {
48-
val link = text.getSpans(off, off, ClickableSpan::class.java).firstOrNull()
44+
val clickedWithinLineHeight = y >= lineRect.top && y <= lineRect.bottom
45+
val clickedOnSpanToTheLeftOfCursor = x in charPrevX..charX
46+
val clickedOnSpanToTheRightOfCursor = x in charX..charNextX
47+
48+
val clickedOnSpan = clickedWithinLineHeight &&
49+
(clickedOnSpanToTheLeftOfCursor || clickedOnSpanToTheRightOfCursor)
50+
51+
val clickedSpanBordersAnotherOne = (text.getSpans(off, off, ClickableSpan::class.java).size == 1 &&
52+
text.getSpans(off + 1, off + 1, ClickableSpan::class.java).isNotEmpty())
53+
54+
val isClickedSpanAmbiguous = text.getSpans(off, off, ClickableSpan::class.java).size > 1
4955

50-
// Only react to AztecMediaClickableSpan and UnknownClickableSpan; not to regular links.
51-
if (link != null && (link is AztecMediaClickableSpan || link is UnknownClickableSpan)) {
52-
if (action == MotionEvent.ACTION_UP) {
53-
link.onClick(widget)
56+
val failedToPinpointClickedSpan = (isClickedSpanAmbiguous || clickedSpanBordersAnotherOne)
57+
&& !clickedOnSpanToTheLeftOfCursor && !clickedOnSpanToTheRightOfCursor
58+
59+
var link: ClickableSpan? = null
60+
61+
if (clickedOnSpan) {
62+
if (isClickedSpanAmbiguous) {
63+
if (clickedOnSpanToTheLeftOfCursor) {
64+
link = text.getSpans(off, off, ClickableSpan::class.java)[0]
65+
} else if (clickedOnSpanToTheRightOfCursor) {
66+
link = text.getSpans(off, off, ClickableSpan::class.java)[1]
5467
}
55-
return true
68+
} else {
69+
link = text.getSpans(off, off, ClickableSpan::class.java).firstOrNull()
70+
}
71+
} else if (failedToPinpointClickedSpan) {
72+
link = text.getSpans(off, off, ClickableSpan::class.java).firstOrNull { text.getSpanStart(it) == off }
73+
}
74+
75+
if (link != null && (link is AztecMediaClickableSpan || link is UnknownClickableSpan)) {
76+
if (action == MotionEvent.ACTION_UP) {
77+
link.onClick(widget)
5678
}
79+
return true
5780
}
5881
}
5982

0 commit comments

Comments
 (0)