react-native-highlight-text-view 0.1.22 → 0.1.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -33,7 +33,9 @@ class RoundedBackgroundSpan(
|
|
|
33
33
|
internal val backgroundInsetRight: Float,
|
|
34
34
|
internal val cornerRadius: Float,
|
|
35
35
|
internal val isLineStart: Boolean = false,
|
|
36
|
-
internal val isLineEnd: Boolean = false
|
|
36
|
+
internal val isLineEnd: Boolean = false,
|
|
37
|
+
internal val isFirstLine: Boolean = false,
|
|
38
|
+
internal val isLastLine: Boolean = false
|
|
37
39
|
) : ReplacementSpan() {
|
|
38
40
|
|
|
39
41
|
override fun getSize(
|
|
@@ -102,9 +104,9 @@ class RoundedBackgroundSpan(
|
|
|
102
104
|
0f
|
|
103
105
|
}
|
|
104
106
|
|
|
105
|
-
// Vertical overlap to eliminate gaps
|
|
106
|
-
val topExtend =
|
|
107
|
-
val bottomExtend =
|
|
107
|
+
// Vertical overlap to eliminate gaps (reduced to prevent descender clipping)
|
|
108
|
+
val topExtend = 0f
|
|
109
|
+
val bottomExtend = 0f
|
|
108
110
|
|
|
109
111
|
// Calculate background rect
|
|
110
112
|
// NOTE: Since this is a ReplacementSpan, 'x' is the start of the span (including padding).
|
|
@@ -123,37 +125,37 @@ class RoundedBackgroundSpan(
|
|
|
123
125
|
canvas.drawRoundRect(rect, cornerRadius, cornerRadius, bgPaint)
|
|
124
126
|
}
|
|
125
127
|
isLineStart -> {
|
|
126
|
-
// Line START - round LEFT corners
|
|
128
|
+
// Line START - round LEFT corners (top and bottom)
|
|
127
129
|
val path = android.graphics.Path()
|
|
128
130
|
path.addRoundRect(
|
|
129
131
|
rect,
|
|
130
132
|
floatArrayOf(
|
|
131
|
-
cornerRadius, cornerRadius,
|
|
132
|
-
0f, 0f,
|
|
133
|
-
0f, 0f,
|
|
134
|
-
cornerRadius, cornerRadius
|
|
133
|
+
cornerRadius, cornerRadius, // top-left
|
|
134
|
+
0f, 0f, // top-right
|
|
135
|
+
0f, 0f, // bottom-right
|
|
136
|
+
cornerRadius, cornerRadius // bottom-left
|
|
135
137
|
),
|
|
136
138
|
android.graphics.Path.Direction.CW
|
|
137
139
|
)
|
|
138
140
|
canvas.drawPath(path, bgPaint)
|
|
139
141
|
}
|
|
140
142
|
isLineEnd -> {
|
|
141
|
-
// Line END - round RIGHT corners
|
|
143
|
+
// Line END - round RIGHT corners (top and bottom)
|
|
142
144
|
val path = android.graphics.Path()
|
|
143
145
|
path.addRoundRect(
|
|
144
146
|
rect,
|
|
145
147
|
floatArrayOf(
|
|
146
|
-
0f, 0f,
|
|
147
|
-
cornerRadius, cornerRadius,
|
|
148
|
-
cornerRadius, cornerRadius,
|
|
149
|
-
0f, 0f
|
|
148
|
+
0f, 0f, // top-left
|
|
149
|
+
cornerRadius, cornerRadius, // top-right
|
|
150
|
+
cornerRadius, cornerRadius, // bottom-right
|
|
151
|
+
0f, 0f // bottom-left
|
|
150
152
|
),
|
|
151
153
|
android.graphics.Path.Direction.CW
|
|
152
154
|
)
|
|
153
155
|
canvas.drawPath(path, bgPaint)
|
|
154
156
|
}
|
|
155
157
|
else -> {
|
|
156
|
-
// Middle - NO rounded corners (
|
|
158
|
+
// Middle characters - NO rounded corners (square) for smooth edges
|
|
157
159
|
canvas.drawRect(rect, bgPaint)
|
|
158
160
|
}
|
|
159
161
|
}
|
|
@@ -486,12 +488,19 @@ class HighlightTextView : AppCompatEditText {
|
|
|
486
488
|
var isAtLineStart = i == 0 || hasNewlineBefore
|
|
487
489
|
var isAtLineEnd = i == textStr.length - 1 || hasNewlineAfter
|
|
488
490
|
|
|
491
|
+
// Determine if this is the first or last line
|
|
492
|
+
var isOnFirstLine = i == 0 || hasNewlineBefore
|
|
493
|
+
var isOnLastLine = i == textStr.length - 1 || hasNewlineAfter
|
|
494
|
+
|
|
489
495
|
// Only use layout for auto-wrapped lines (not manual newlines)
|
|
490
496
|
if (!hasNewlineBefore && !hasNewlineAfter && layout != null && i < textStr.length) {
|
|
491
497
|
try {
|
|
492
498
|
val line = layout.getLineForOffset(i)
|
|
493
499
|
val lineStart = layout.getLineStart(line)
|
|
494
500
|
val lineEnd = layout.getLineEnd(line)
|
|
501
|
+
// Check if this is the first or last line
|
|
502
|
+
isOnFirstLine = line == 0
|
|
503
|
+
isOnLastLine = line == layout.lineCount - 1
|
|
495
504
|
// Only override if this is an auto-wrapped boundary
|
|
496
505
|
if (i == lineStart && textStr.getOrNull(i - 1) != '\n') {
|
|
497
506
|
isAtLineStart = true
|
|
@@ -517,7 +526,9 @@ class HighlightTextView : AppCompatEditText {
|
|
|
517
526
|
backgroundInsetRight,
|
|
518
527
|
radius,
|
|
519
528
|
isAtLineStart,
|
|
520
|
-
isAtLineEnd
|
|
529
|
+
isAtLineEnd,
|
|
530
|
+
isOnFirstLine,
|
|
531
|
+
isOnLastLine
|
|
521
532
|
)
|
|
522
533
|
editable.setSpan(span, i, i + 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
|
|
523
534
|
}
|
|
@@ -547,10 +558,14 @@ class HighlightTextView : AppCompatEditText {
|
|
|
547
558
|
val textStr = editable.toString()
|
|
548
559
|
if (textStr.isEmpty()) return
|
|
549
560
|
|
|
550
|
-
// Apply line height if specified
|
|
561
|
+
// Apply line height if specified, or add spacing for padding
|
|
551
562
|
if (customLineHeight > 0) {
|
|
552
563
|
val lineSpacingMultiplier = customLineHeight / textSize
|
|
553
564
|
setLineSpacing(0f, lineSpacingMultiplier)
|
|
565
|
+
} else {
|
|
566
|
+
// Add line spacing to accommodate vertical padding and prevent overlap
|
|
567
|
+
val extraSpacing = charPaddingTop + charPaddingBottom
|
|
568
|
+
setLineSpacing(extraSpacing, 1.0f)
|
|
554
569
|
}
|
|
555
570
|
|
|
556
571
|
isUpdatingText = true
|
|
@@ -586,12 +601,19 @@ class HighlightTextView : AppCompatEditText {
|
|
|
586
601
|
var isAtLineStart = i == 0 || hasNewlineBefore
|
|
587
602
|
var isAtLineEnd = i == textStr.length - 1 || hasNewlineAfter
|
|
588
603
|
|
|
604
|
+
// Determine if this is the first or last line
|
|
605
|
+
var isOnFirstLine = i == 0 || hasNewlineBefore
|
|
606
|
+
var isOnLastLine = i == textStr.length - 1 || hasNewlineAfter
|
|
607
|
+
|
|
589
608
|
// Only use layout for auto-wrapped lines (not manual newlines)
|
|
590
609
|
if (!hasNewlineBefore && !hasNewlineAfter && layoutObj != null && i < textStr.length) {
|
|
591
610
|
try {
|
|
592
611
|
val line = layoutObj.getLineForOffset(i)
|
|
593
612
|
val lineStart = layoutObj.getLineStart(line)
|
|
594
613
|
val lineEnd = layoutObj.getLineEnd(line)
|
|
614
|
+
// Check if this is the first or last line
|
|
615
|
+
isOnFirstLine = line == 0
|
|
616
|
+
isOnLastLine = line == layoutObj.lineCount - 1
|
|
595
617
|
// Only override if this is an auto-wrapped boundary
|
|
596
618
|
if (i == lineStart && textStr.getOrNull(i - 1) != '\n') {
|
|
597
619
|
isAtLineStart = true
|
|
@@ -617,13 +639,23 @@ class HighlightTextView : AppCompatEditText {
|
|
|
617
639
|
backgroundInsetRight,
|
|
618
640
|
radius,
|
|
619
641
|
isAtLineStart,
|
|
620
|
-
isAtLineEnd
|
|
642
|
+
isAtLineEnd,
|
|
643
|
+
isOnFirstLine,
|
|
644
|
+
isOnLastLine
|
|
621
645
|
)
|
|
622
646
|
editable.setSpan(span, i, i + 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
|
|
623
647
|
}
|
|
624
648
|
}
|
|
625
649
|
|
|
626
650
|
isUpdatingText = false
|
|
651
|
+
|
|
652
|
+
// Schedule a post-layout update to ensure corner rounding is correct
|
|
653
|
+
// This is needed because layout might not be ready when this method is called
|
|
654
|
+
post {
|
|
655
|
+
if (!isUpdatingText) {
|
|
656
|
+
updateAutoWrappedLineBoundaries()
|
|
657
|
+
}
|
|
658
|
+
}
|
|
627
659
|
}
|
|
628
660
|
|
|
629
661
|
/**
|
|
@@ -664,12 +696,17 @@ class HighlightTextView : AppCompatEditText {
|
|
|
664
696
|
val isAtLineStart = spanStart == lineStart
|
|
665
697
|
val isAtLineEnd = spanEnd == lineEnd
|
|
666
698
|
|
|
699
|
+
// Check if this is the first or last line
|
|
700
|
+
val isOnFirstLine = line == 0
|
|
701
|
+
val isOnLastLine = line == layout.lineCount - 1
|
|
702
|
+
|
|
667
703
|
// Only update if this is an auto-wrapped line boundary (not a newline boundary)
|
|
668
704
|
val isNewlineBoundary = (spanStart > 0 && textStr[spanStart - 1] == '\n') ||
|
|
669
705
|
(spanEnd < textStr.length && textStr[spanEnd] == '\n')
|
|
670
706
|
|
|
671
707
|
// Only recreate span if it's at an auto-wrapped boundary and flags are wrong
|
|
672
|
-
if (!isNewlineBoundary && (isAtLineStart != span.isLineStart || isAtLineEnd != span.isLineEnd
|
|
708
|
+
if (!isNewlineBoundary && (isAtLineStart != span.isLineStart || isAtLineEnd != span.isLineEnd ||
|
|
709
|
+
isOnFirstLine != span.isFirstLine || isOnLastLine != span.isLastLine)) {
|
|
673
710
|
val newSpan = RoundedBackgroundSpan(
|
|
674
711
|
span.backgroundColor,
|
|
675
712
|
span.textColor,
|
|
@@ -683,7 +720,9 @@ class HighlightTextView : AppCompatEditText {
|
|
|
683
720
|
span.backgroundInsetRight,
|
|
684
721
|
span.cornerRadius,
|
|
685
722
|
isAtLineStart,
|
|
686
|
-
isAtLineEnd
|
|
723
|
+
isAtLineEnd,
|
|
724
|
+
isOnFirstLine,
|
|
725
|
+
isOnLastLine
|
|
687
726
|
)
|
|
688
727
|
editable.removeSpan(span)
|
|
689
728
|
editable.setSpan(newSpan, spanStart, spanEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-highlight-text-view",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.24",
|
|
4
4
|
"description": "A native text input for React Native that supports inline text highlighting",
|
|
5
5
|
"main": "./lib/module/index.js",
|
|
6
6
|
"types": "./lib/typescript/src/index.d.ts",
|