react-native-highlight-text-view 0.1.16 → 0.1.18

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) {
@@ -308,8 +315,41 @@ class HighlightTextView : AppCompatEditText {
308
315
  Typeface.create(baseTypeface, style)
309
316
  }
310
317
 
318
+ // Save current text to force complete rebuild
319
+ val currentText = text?.toString() ?: ""
320
+ val currentSelection = selectionStart
321
+
311
322
  this.typeface = typeface
312
- applyCharacterBackgrounds()
323
+
324
+ // Force complete text rebuild with new font metrics
325
+ // This is crucial for fonts with different ascender/descender values like Eczar
326
+ post {
327
+ // Clear text first to force layout recalculation
328
+ isUpdatingText = true
329
+ setText("")
330
+
331
+ // Force measure and layout with empty text
332
+ measure(
333
+ MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
334
+ MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)
335
+ )
336
+
337
+ // Restore text - this triggers complete rebuild with new font metrics
338
+ setText(currentText)
339
+
340
+ // Reapply all character backgrounds with new font metrics
341
+ applyCharacterBackgrounds()
342
+
343
+ // Restore cursor position
344
+ val safePosition = currentSelection.coerceIn(0, currentText.length)
345
+ setSelection(safePosition)
346
+
347
+ isUpdatingText = false
348
+
349
+ // Force complete layout recalculation
350
+ requestLayout()
351
+ invalidate()
352
+ }
313
353
  }
314
354
 
315
355
  fun setVerticalAlign(align: String?) {
@@ -367,6 +407,8 @@ class HighlightTextView : AppCompatEditText {
367
407
  if (autoFocus && isFocusable && isFocusableInTouchMode) {
368
408
  post {
369
409
  requestFocus()
410
+ // Set cursor at the end of text
411
+ text?.length?.let { setSelection(it) }
370
412
  val imm = context.getSystemService(android.content.Context.INPUT_METHOD_SERVICE) as? android.view.inputmethod.InputMethodManager
371
413
  imm?.showSoftInput(this, android.view.inputmethod.InputMethodManager.SHOW_IMPLICIT)
372
414
  }
@@ -377,6 +419,9 @@ class HighlightTextView : AppCompatEditText {
377
419
  val text = text?.toString() ?: return
378
420
  if (text.isEmpty()) return
379
421
 
422
+ // Save current cursor position
423
+ val currentSelection = selectionStart
424
+
380
425
  val spannable = SpannableString(text)
381
426
 
382
427
  // Apply line height if specified
@@ -430,7 +475,9 @@ class HighlightTextView : AppCompatEditText {
430
475
 
431
476
  isUpdatingText = true
432
477
  setText(spannable)
433
- setSelection(text.length) // Keep cursor at end
478
+ // Restore cursor position, or set to end if position is invalid
479
+ val safePosition = currentSelection.coerceIn(0, text.length)
480
+ setSelection(safePosition)
434
481
  isUpdatingText = false
435
482
 
436
483
  // Detect line wraps after layout is ready
@@ -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,32 @@ Class<RCTComponentViewProtocol> HighlightTextViewCls(void)
519
529
  }
520
530
 
521
531
  _textView.font = newFont;
532
+
533
+ // Save current text to force complete rebuild
534
+ NSString *currentText = [_textView.text copy];
535
+
536
+ // Clear text storage to force complete recalculation
537
+ [_textView.textStorage beginEditing];
538
+ [_textView.textStorage replaceCharactersInRange:NSMakeRange(0, _textView.textStorage.length) withString:@""];
539
+ [_textView.textStorage endEditing];
540
+
541
+ // Force layout manager to invalidate everything
542
+ [_layoutManager invalidateLayoutForCharacterRange:NSMakeRange(0, 0) actualCharacterRange:NULL];
543
+ [_layoutManager invalidateDisplayForCharacterRange:NSMakeRange(0, 0)];
544
+
545
+ // Restore text and rebuild with new font
546
+ _textView.text = currentText;
547
+
548
+ // Reapply character backgrounds with new font metrics - this rebuilds attributed text
522
549
  [self applyCharacterBackgrounds];
550
+
551
+ // Force complete layout recalculation
552
+ [_textView.layoutManager ensureLayoutForTextContainer:_textView.textContainer];
553
+
554
+ // Force the text view to redraw
555
+ [_textView setNeedsDisplay];
556
+ [_textView setNeedsLayout];
557
+ [_textView layoutIfNeeded];
523
558
  }
524
559
 
525
560
  - (void)applyCharacterBackgrounds
@@ -529,6 +564,9 @@ Class<RCTComponentViewProtocol> HighlightTextViewCls(void)
529
564
  return;
530
565
  }
531
566
 
567
+ // Save current cursor position
568
+ NSRange currentSelection = _textView.selectedRange;
569
+
532
570
  NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:text];
533
571
  UIColor *bgColor = [self hexStringToColor:_characterBackgroundColor];
534
572
 
@@ -577,6 +615,12 @@ Class<RCTComponentViewProtocol> HighlightTextViewCls(void)
577
615
  }
578
616
 
579
617
  _textView.attributedText = attributedString;
618
+
619
+ // Restore cursor position if valid
620
+ if (currentSelection.location <= text.length) {
621
+ _textView.selectedRange = currentSelection;
622
+ }
623
+
580
624
  [_textView setNeedsDisplay];
581
625
  }
582
626
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-highlight-text-view",
3
- "version": "0.1.16",
3
+ "version": "0.1.18",
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",