react-native-highlight-text-view 0.1.17 → 0.1.19

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.
@@ -315,14 +315,60 @@ class HighlightTextView : AppCompatEditText {
315
315
  Typeface.create(baseTypeface, style)
316
316
  }
317
317
 
318
+ // Save current text and selection
319
+ val currentText = text?.toString() ?: ""
320
+ val currentSelection = selectionStart
321
+
322
+ // Apply new typeface
318
323
  this.typeface = typeface
319
324
 
320
- // Force complete layout recalculation with new font metrics
321
- // This ensures background highlights recalculate with new ascender/descender values
325
+ // CRITICAL: Force complete layout rebuild for fonts with different metrics (like Eczar)
326
+ // Multiple post calls ensure all layout phases complete with new font
322
327
  post {
323
- applyCharacterBackgrounds()
324
- requestLayout()
325
- invalidate()
328
+ isUpdatingText = true
329
+
330
+ // Phase 1: Clear everything
331
+ setText("")
332
+ paint.typeface = typeface // Ensure paint also has new typeface
333
+
334
+ // Force measure with empty text and new font
335
+ measure(
336
+ MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
337
+ MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)
338
+ )
339
+ layout(left, top, right, bottom)
340
+
341
+ // Phase 2: Restore text and rebuild (next frame)
342
+ post {
343
+ setText(currentText)
344
+
345
+ // Force another measure/layout cycle with actual text
346
+ measure(
347
+ MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
348
+ MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)
349
+ )
350
+ layout(left, top, right, bottom)
351
+
352
+ // Phase 3: Apply backgrounds and finalize (next frame)
353
+ post {
354
+ applyCharacterBackgrounds()
355
+
356
+ // Restore cursor position
357
+ val safePosition = currentSelection.coerceIn(0, currentText.length)
358
+ setSelection(safePosition)
359
+
360
+ isUpdatingText = false
361
+
362
+ // Final layout pass
363
+ requestLayout()
364
+ invalidate()
365
+
366
+ // Extra invalidate to ensure rendering
367
+ post {
368
+ invalidate()
369
+ }
370
+ }
371
+ }
326
372
  }
327
373
  }
328
374
 
@@ -528,19 +528,51 @@ Class<RCTComponentViewProtocol> HighlightTextViewCls(void)
528
528
  newFont = [UIFont systemFontOfSize:fontSize weight:fontWeight];
529
529
  }
530
530
 
531
+ // Save current text and selection
532
+ NSString *currentText = [_textView.text copy];
533
+ NSRange currentSelection = _textView.selectedRange;
534
+
535
+ // Update font on text view
531
536
  _textView.font = newFont;
532
537
 
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)];
538
+ // CRITICAL: Force complete rebuild by removing and re-adding the text container
539
+ // This ensures all glyph and layout caches are cleared for the new font metrics
540
+ NSTextContainer *textContainer = _textView.textContainer;
541
+ NSTextStorage *textStorage = _textView.textStorage;
536
542
 
537
- // Reapply character backgrounds with new font metrics
538
- [self applyCharacterBackgrounds];
543
+ // Remove text container from layout manager
544
+ [_layoutManager removeTextContainerAtIndex:0];
539
545
 
540
- // Force the text view to redraw
541
- [_textView setNeedsDisplay];
542
- [_textView setNeedsLayout];
543
- [_textView layoutIfNeeded];
546
+ // Completely invalidate all layout
547
+ [_layoutManager invalidateLayoutForCharacterRange:NSMakeRange(0, textStorage.length) actualCharacterRange:NULL];
548
+ [_layoutManager invalidateDisplayForCharacterRange:NSMakeRange(0, textStorage.length)];
549
+
550
+ // Re-add text container - forces complete layout recalculation
551
+ [_layoutManager addTextContainer:textContainer];
552
+
553
+ // Force immediate layout with new font metrics
554
+ dispatch_async(dispatch_get_main_queue(), ^{
555
+ // Restore text through applyCharacterBackgrounds which rebuilds attributed string
556
+ [self applyCharacterBackgrounds];
557
+
558
+ // Ensure layout is calculated with new font
559
+ [self->_layoutManager ensureLayoutForTextContainer:self->_textView.textContainer];
560
+
561
+ // Restore selection if valid
562
+ if (currentSelection.location <= currentText.length) {
563
+ self->_textView.selectedRange = currentSelection;
564
+ }
565
+
566
+ // Force complete redraw
567
+ [self->_textView setNeedsDisplay];
568
+ [self->_textView setNeedsLayout];
569
+ [self->_textView layoutIfNeeded];
570
+
571
+ // Trigger another display update to ensure rendering
572
+ dispatch_async(dispatch_get_main_queue(), ^{
573
+ [self->_textView setNeedsDisplay];
574
+ });
575
+ });
544
576
  }
545
577
 
546
578
  - (void)applyCharacterBackgrounds
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-highlight-text-view",
3
- "version": "0.1.17",
3
+ "version": "0.1.19",
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",