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
|
|
321
|
-
//
|
|
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
|
-
|
|
324
|
-
|
|
325
|
-
|
|
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
|
|
package/ios/HighlightTextView.mm
CHANGED
|
@@ -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
|
|
534
|
-
|
|
535
|
-
|
|
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
|
-
//
|
|
538
|
-
[
|
|
543
|
+
// Remove text container from layout manager
|
|
544
|
+
[_layoutManager removeTextContainerAtIndex:0];
|
|
539
545
|
|
|
540
|
-
//
|
|
541
|
-
[
|
|
542
|
-
[
|
|
543
|
-
|
|
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.
|
|
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",
|