react-native-highlight-text-view 0.1.16 → 0.1.17
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.
|
@@ -206,6 +206,13 @@ class HighlightTextView : AppCompatEditText {
|
|
|
206
206
|
}
|
|
207
207
|
}
|
|
208
208
|
})
|
|
209
|
+
|
|
210
|
+
// Set cursor at end when view gains focus
|
|
211
|
+
setOnFocusChangeListener { _, hasFocus ->
|
|
212
|
+
if (hasFocus) {
|
|
213
|
+
text?.length?.let { setSelection(it) }
|
|
214
|
+
}
|
|
215
|
+
}
|
|
209
216
|
}
|
|
210
217
|
|
|
211
218
|
fun setCharacterBackgroundColor(color: Int) {
|
|
@@ -309,7 +316,14 @@ class HighlightTextView : AppCompatEditText {
|
|
|
309
316
|
}
|
|
310
317
|
|
|
311
318
|
this.typeface = typeface
|
|
312
|
-
|
|
319
|
+
|
|
320
|
+
// Force complete layout recalculation with new font metrics
|
|
321
|
+
// This ensures background highlights recalculate with new ascender/descender values
|
|
322
|
+
post {
|
|
323
|
+
applyCharacterBackgrounds()
|
|
324
|
+
requestLayout()
|
|
325
|
+
invalidate()
|
|
326
|
+
}
|
|
313
327
|
}
|
|
314
328
|
|
|
315
329
|
fun setVerticalAlign(align: String?) {
|
|
@@ -367,6 +381,8 @@ class HighlightTextView : AppCompatEditText {
|
|
|
367
381
|
if (autoFocus && isFocusable && isFocusableInTouchMode) {
|
|
368
382
|
post {
|
|
369
383
|
requestFocus()
|
|
384
|
+
// Set cursor at the end of text
|
|
385
|
+
text?.length?.let { setSelection(it) }
|
|
370
386
|
val imm = context.getSystemService(android.content.Context.INPUT_METHOD_SERVICE) as? android.view.inputmethod.InputMethodManager
|
|
371
387
|
imm?.showSoftInput(this, android.view.inputmethod.InputMethodManager.SHOW_IMPLICIT)
|
|
372
388
|
}
|
|
@@ -377,6 +393,9 @@ class HighlightTextView : AppCompatEditText {
|
|
|
377
393
|
val text = text?.toString() ?: return
|
|
378
394
|
if (text.isEmpty()) return
|
|
379
395
|
|
|
396
|
+
// Save current cursor position
|
|
397
|
+
val currentSelection = selectionStart
|
|
398
|
+
|
|
380
399
|
val spannable = SpannableString(text)
|
|
381
400
|
|
|
382
401
|
// Apply line height if specified
|
|
@@ -430,7 +449,9 @@ class HighlightTextView : AppCompatEditText {
|
|
|
430
449
|
|
|
431
450
|
isUpdatingText = true
|
|
432
451
|
setText(spannable)
|
|
433
|
-
|
|
452
|
+
// Restore cursor position, or set to end if position is invalid
|
|
453
|
+
val safePosition = currentSelection.coerceIn(0, text.length)
|
|
454
|
+
setSelection(safePosition)
|
|
434
455
|
isUpdatingText = false
|
|
435
456
|
|
|
436
457
|
// Detect line wraps after layout is ready
|
package/ios/HighlightTextView.mm
CHANGED
|
@@ -430,6 +430,9 @@ using namespace facebook::react;
|
|
|
430
430
|
if (newViewProps.autoFocus && _textView.isEditable) {
|
|
431
431
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
432
432
|
[self->_textView becomeFirstResponder];
|
|
433
|
+
// Set cursor at the end of text
|
|
434
|
+
NSUInteger textLength = self->_textView.text.length;
|
|
435
|
+
self->_textView.selectedRange = NSMakeRange(textLength, 0);
|
|
433
436
|
});
|
|
434
437
|
}
|
|
435
438
|
}
|
|
@@ -468,6 +471,13 @@ Class<RCTComponentViewProtocol> HighlightTextViewCls(void)
|
|
|
468
471
|
}
|
|
469
472
|
}
|
|
470
473
|
|
|
474
|
+
- (void)textViewDidBeginEditing:(UITextView *)textView
|
|
475
|
+
{
|
|
476
|
+
// Set cursor at the end when editing begins
|
|
477
|
+
NSUInteger textLength = textView.text.length;
|
|
478
|
+
textView.selectedRange = NSMakeRange(textLength, 0);
|
|
479
|
+
}
|
|
480
|
+
|
|
471
481
|
- (void)updateFont
|
|
472
482
|
{
|
|
473
483
|
CGFloat fontSize = _fontSize > 0 ? _fontSize : 32.0;
|
|
@@ -519,7 +529,18 @@ Class<RCTComponentViewProtocol> HighlightTextViewCls(void)
|
|
|
519
529
|
}
|
|
520
530
|
|
|
521
531
|
_textView.font = newFont;
|
|
532
|
+
|
|
533
|
+
// Force layout manager to invalidate and recalculate layout
|
|
534
|
+
[_layoutManager invalidateLayoutForCharacterRange:NSMakeRange(0, _textView.textStorage.length) actualCharacterRange:NULL];
|
|
535
|
+
[_layoutManager invalidateDisplayForCharacterRange:NSMakeRange(0, _textView.textStorage.length)];
|
|
536
|
+
|
|
537
|
+
// Reapply character backgrounds with new font metrics
|
|
522
538
|
[self applyCharacterBackgrounds];
|
|
539
|
+
|
|
540
|
+
// Force the text view to redraw
|
|
541
|
+
[_textView setNeedsDisplay];
|
|
542
|
+
[_textView setNeedsLayout];
|
|
543
|
+
[_textView layoutIfNeeded];
|
|
523
544
|
}
|
|
524
545
|
|
|
525
546
|
- (void)applyCharacterBackgrounds
|
|
@@ -529,6 +550,9 @@ Class<RCTComponentViewProtocol> HighlightTextViewCls(void)
|
|
|
529
550
|
return;
|
|
530
551
|
}
|
|
531
552
|
|
|
553
|
+
// Save current cursor position
|
|
554
|
+
NSRange currentSelection = _textView.selectedRange;
|
|
555
|
+
|
|
532
556
|
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:text];
|
|
533
557
|
UIColor *bgColor = [self hexStringToColor:_characterBackgroundColor];
|
|
534
558
|
|
|
@@ -577,6 +601,12 @@ Class<RCTComponentViewProtocol> HighlightTextViewCls(void)
|
|
|
577
601
|
}
|
|
578
602
|
|
|
579
603
|
_textView.attributedText = attributedString;
|
|
604
|
+
|
|
605
|
+
// Restore cursor position if valid
|
|
606
|
+
if (currentSelection.location <= text.length) {
|
|
607
|
+
_textView.selectedRange = currentSelection;
|
|
608
|
+
}
|
|
609
|
+
|
|
580
610
|
[_textView setNeedsDisplay];
|
|
581
611
|
}
|
|
582
612
|
|
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.17",
|
|
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",
|