From 7b5533266ec6b33346a4bc2c41b71d9ee3e43d7d Mon Sep 17 00:00:00 2001 From: Dimitris - Rafail Katsampas Date: Sat, 9 Nov 2024 00:58:26 +0200 Subject: [PATCH 01/13] feat(core): Typography improvements --- .../platforms/ios/src/UIView+NativeScript.m | 22 +++++++-- packages/core/ui/html-view/index.android.ts | 13 +++--- packages/core/ui/search-bar/index.android.ts | 14 +++--- .../core/ui/segmented-bar/index.android.ts | 12 ++--- packages/core/ui/tab-view/index.android.ts | 24 ++++------ packages/core/ui/tab-view/index.ios.ts | 2 +- packages/core/ui/text-base/index.android.ts | 45 ++++++++++++++----- 7 files changed, 76 insertions(+), 56 deletions(-) diff --git a/packages/core/platforms/ios/src/UIView+NativeScript.m b/packages/core/platforms/ios/src/UIView+NativeScript.m index f288aeaa55..a4c74a0bbe 100644 --- a/packages/core/platforms/ios/src/UIView+NativeScript.m +++ b/packages/core/platforms/ios/src/UIView+NativeScript.m @@ -15,8 +15,8 @@ - (void)nativeScriptSetTextDecorationAndTransform:(NSString*)text textDecoration } BOOL isTextType = [self isKindOfClass:[UITextField class]] || [self isKindOfClass:[UITextView class]] | [self isKindOfClass:[UILabel class]] | [self isKindOfClass:[UIButton class]]; - if (letterSpacing != 0 && isTextType && ((UITextView*)self).font != nil) { - NSNumber *kern = [NSNumber numberWithDouble:letterSpacing * ((UITextView*)self).font.pointSize]; + if (letterSpacing != 0 && isTextType) { + NSNumber *kern = [NSNumber numberWithDouble:letterSpacing]; attrDict[NSKernAttributeName] = kern; if ([self isKindOfClass:[UITextField class]]) { [((UITextField*)self).defaultTextAttributes setValue:kern forKey:NSKernAttributeName]; @@ -30,8 +30,16 @@ - (void)nativeScriptSetTextDecorationAndTransform:(NSString*)text textDecoration // make sure a possible previously set text alignment setting is not lost when line height is specified if ([self isKindOfClass:[UIButton class]]) { paragraphStyle.alignment = ((UIButton*)self).titleLabel.textAlignment; + + if (((UIButton*)self).titleLabel.font) { + paragraphStyle.lineSpacing = lineHeight - ((UIButton*)self).titleLabel.font.lineHeight; + } } else { paragraphStyle.alignment = ((UILabel*)self).textAlignment; + + if (((UILabel*)self).font) { + paragraphStyle.lineSpacing = lineHeight - ((UILabel*)self).font.lineHeight; + } } if ([self isKindOfClass:[UILabel class]]) { @@ -78,7 +86,7 @@ - (void)nativeScriptSetTextDecorationAndTransform:(NSString*)text textDecoration -(void)nativeScriptSetFormattedTextDecorationAndTransform:(NSDictionary*)details letterSpacing:(CGFloat)letterSpacing lineHeight:(CGFloat)lineHeight { NSMutableAttributedString *attrText = [NativeScriptUtils createMutableStringWithDetails:details]; if (letterSpacing != 0) { - NSNumber *kern = [NSNumber numberWithDouble:letterSpacing * ((UITextView*)self).font.pointSize]; + NSNumber *kern = [NSNumber numberWithDouble:letterSpacing]; [attrText addAttribute:NSKernAttributeName value:kern range:(NSRange){ 0, attrText.length @@ -92,9 +100,17 @@ -(void)nativeScriptSetFormattedTextDecorationAndTransform:(NSDictionary*)details // make sure a possible previously set text alignment setting is not lost when line height is specified if ([self isKindOfClass:[UIButton class]]) { paragraphStyle.alignment = ((UIButton*)self).titleLabel.textAlignment; + + if (((UIButton*)self).titleLabel.font) { + paragraphStyle.lineSpacing = lineHeight - ((UIButton*)self).titleLabel.font.lineHeight; + } } else { // Paragraph alignment is also important for tappable spans as NSTextContainer takes it into account paragraphStyle.alignment = ((UILabel*)self).textAlignment; + + if (((UILabel*)self).font) { + paragraphStyle.lineSpacing = lineHeight - ((UILabel*)self).font.lineHeight; + } } if (isLabel) { diff --git a/packages/core/ui/html-view/index.android.ts b/packages/core/ui/html-view/index.android.ts index 3865cb594c..93caa23c60 100644 --- a/packages/core/ui/html-view/index.android.ts +++ b/packages/core/ui/html-view/index.android.ts @@ -1,4 +1,5 @@ import { Color } from '../../color'; +import { layout } from '../../utils'; import { SDK_VERSION } from '../../utils/constants'; import { Font } from '../styling/font'; import { colorProperty, fontSizeProperty, fontInternalProperty } from '../styling/style-properties'; @@ -86,14 +87,10 @@ export class HtmlView extends HtmlViewBase { this.nativeViewProtected.setTypeface(font); } - [fontSizeProperty.getDefault](): { nativeSize: number } { - return { nativeSize: this.nativeViewProtected.getTextSize() }; + [fontSizeProperty.getDefault](): number { + return this.nativeViewProtected.getTextSize() / layout.getDisplayDensity(); } - [fontSizeProperty.setNative](value: number | { nativeSize: number }) { - if (typeof value === 'number') { - this.nativeViewProtected.setTextSize(value); - } else { - this.nativeViewProtected.setTextSize(android.util.TypedValue.COMPLEX_UNIT_PX, value.nativeSize); - } + [fontSizeProperty.setNative](value: number) { + this.nativeViewProtected.setTextSize(value); } } diff --git a/packages/core/ui/search-bar/index.android.ts b/packages/core/ui/search-bar/index.android.ts index dead0caf69..1c4a4b7ff6 100644 --- a/packages/core/ui/search-bar/index.android.ts +++ b/packages/core/ui/search-bar/index.android.ts @@ -1,7 +1,7 @@ import { Font } from '../styling/font'; import { SearchBarBase, textProperty, hintProperty, textFieldHintColorProperty, textFieldBackgroundColorProperty } from './search-bar-common'; import { isUserInteractionEnabledProperty, isEnabledProperty } from '../core/view'; -import { ad } from '../../utils'; +import { ad, layout } from '../../utils'; import { Color } from '../../color'; import { colorProperty, backgroundColorProperty, backgroundInternalProperty, fontInternalProperty, fontSizeProperty } from '../styling/style-properties'; @@ -199,15 +199,11 @@ export class SearchBar extends SearchBarBase { textView.setTextColor(color); } - [fontSizeProperty.getDefault](): { nativeSize: number } { - return { nativeSize: this._getTextView().getTextSize() }; + [fontSizeProperty.getDefault](): number { + return this._getTextView().getTextSize() / layout.getDisplayDensity(); } - [fontSizeProperty.setNative](value: number | { nativeSize: number }) { - if (typeof value === 'number') { - this._getTextView().setTextSize(value); - } else { - this._getTextView().setTextSize(android.util.TypedValue.COMPLEX_UNIT_PX, value.nativeSize); - } + [fontSizeProperty.setNative](value: number) { + this._getTextView().setTextSize(value); } [fontInternalProperty.getDefault](): android.graphics.Typeface { diff --git a/packages/core/ui/segmented-bar/index.android.ts b/packages/core/ui/segmented-bar/index.android.ts index 99448baf56..d84d864726 100644 --- a/packages/core/ui/segmented-bar/index.android.ts +++ b/packages/core/ui/segmented-bar/index.android.ts @@ -140,15 +140,11 @@ export class SegmentedBarItem extends SegmentedBarItemBase { this.nativeViewProtected.setTextColor(color); } - [fontSizeProperty.getDefault](): { nativeSize: number } { - return { nativeSize: this.nativeViewProtected.getTextSize() }; + [fontSizeProperty.getDefault](): number { + return this.nativeViewProtected.getTextSize() / layout.getDisplayDensity(); } - [fontSizeProperty.setNative](value: number | { nativeSize: number }) { - if (typeof value === 'number') { - this.nativeViewProtected.setTextSize(value); - } else { - this.nativeViewProtected.setTextSize(android.util.TypedValue.COMPLEX_UNIT_PX, value.nativeSize); - } + [fontSizeProperty.setNative](value: number) { + this.nativeViewProtected.setTextSize(value); } [fontInternalProperty.getDefault](): android.graphics.Typeface { diff --git a/packages/core/ui/tab-view/index.android.ts b/packages/core/ui/tab-view/index.android.ts index cc8405311a..f66e33b643 100644 --- a/packages/core/ui/tab-view/index.android.ts +++ b/packages/core/ui/tab-view/index.android.ts @@ -392,15 +392,11 @@ export class TabViewItem extends TabViewItemBase { return tabFragment.getChildFragmentManager(); } - [fontSizeProperty.getDefault](): { nativeSize: number } { - return { nativeSize: this.nativeViewProtected.getTextSize() }; + [fontSizeProperty.getDefault](): number { + return this.nativeViewProtected.getTextSize() / layout.getDisplayDensity(); } - [fontSizeProperty.setNative](value: number | { nativeSize: number }) { - if (typeof value === 'number') { - this.nativeViewProtected.setTextSize(value); - } else { - this.nativeViewProtected.setTextSize(android.util.TypedValue.COMPLEX_UNIT_PX, value.nativeSize); - } + [fontSizeProperty.setNative](value: number) { + this.nativeViewProtected.setTextSize(value); } [fontInternalProperty.getDefault](): android.graphics.Typeface { @@ -494,7 +490,7 @@ export class TabView extends TabViewBase { JSON.stringify([ { value: 1, type: 0 /* org.nativescript.widgets.GridUnitType.auto */ }, { value: 1, type: 2 /* org.nativescript.widgets.GridUnitType.star */ }, - ]) + ]), ); viewPager.setLayoutParams(lp); @@ -506,7 +502,7 @@ export class TabView extends TabViewBase { JSON.stringify([ { value: 1, type: 2 /* org.nativescript.widgets.GridUnitType.star */ }, { value: 1, type: 0 /* org.nativescript.widgets.GridUnitType.auto */ }, - ]) + ]), ); tabLayout.setLayoutParams(lp); viewPager.setSwipePageEnabled(false); @@ -771,12 +767,8 @@ export class TabView extends TabViewBase { [tabTextFontSizeProperty.getDefault](): number { return this._tabLayout.getTabTextFontSize(); } - [tabTextFontSizeProperty.setNative](value: number | { nativeSize: number }) { - if (typeof value === 'number') { - this._tabLayout.setTabTextFontSize(value); - } else { - this._tabLayout.setTabTextFontSize(value.nativeSize); - } + [tabTextFontSizeProperty.setNative](value: number) { + this._tabLayout.setTabTextFontSize(value); } [tabTextColorProperty.getDefault](): number { diff --git a/packages/core/ui/tab-view/index.ios.ts b/packages/core/ui/tab-view/index.ios.ts index ece8ae0963..5262a624d1 100644 --- a/packages/core/ui/tab-view/index.ios.ts +++ b/packages/core/ui/tab-view/index.ios.ts @@ -580,7 +580,7 @@ export class TabView extends TabViewBase { [tabTextFontSizeProperty.getDefault](): number { return null; } - [tabTextFontSizeProperty.setNative](value: number | { nativeSize: number }) { + [tabTextFontSizeProperty.setNative](value: number) { this._updateIOSTabBarColorsAndFonts(); } diff --git a/packages/core/ui/text-base/index.android.ts b/packages/core/ui/text-base/index.android.ts index cb538617bd..580a2e3400 100644 --- a/packages/core/ui/text-base/index.android.ts +++ b/packages/core/ui/text-base/index.android.ts @@ -360,15 +360,24 @@ export class TextBase extends TextBaseCommon { } } - [fontSizeProperty.getDefault](): { nativeSize: number } { - return { nativeSize: this.nativeTextViewProtected.getTextSize() }; - } - [fontSizeProperty.setNative](value: number | { nativeSize: number }) { - if (!this.formattedText || typeof value !== 'number') { - if (typeof value === 'number') { - this.nativeTextViewProtected.setTextSize(value); - } else { - this.nativeTextViewProtected.setTextSize(android.util.TypedValue.COMPLEX_UNIT_PX, value.nativeSize); + [fontSizeProperty.getDefault](): number { + return this.nativeTextViewProtected.getTextSize() / layout.getDisplayDensity(); + } + [fontSizeProperty.setNative](value: number) { + if (!this.formattedText) { + this.nativeTextViewProtected.setTextSize(value); + + // Re-calculate line-height + if (this.lineHeight != 0) { + // It's done automatically for API 28+ + if (SDK_VERSION < 28) { + this._setLineHeightLegacy(this.lineHeight); + } + } + + // Re-calculate letter-spacing + if (this.letterSpacing != 0) { + this._updateLetterSpacing(this.letterSpacing); } } } @@ -433,10 +442,10 @@ export class TextBase extends TextBaseCommon { } [letterSpacingProperty.getDefault](): number { - return org.nativescript.widgets.ViewHelper.getLetterspacing(this.nativeTextViewProtected); + return org.nativescript.widgets.ViewHelper.getLetterspacing(this.nativeTextViewProtected) * this.fontSize; } [letterSpacingProperty.setNative](value: number) { - org.nativescript.widgets.ViewHelper.setLetterspacing(this.nativeTextViewProtected, value); + this._updateLetterSpacing(value); } [paddingTopProperty.getDefault](): CoreTypes.LengthType { @@ -485,6 +494,20 @@ export class TextBase extends TextBaseCommon { } } + _setLineHeightLegacy(value: number): void { + const dpValue = value * layout.getDisplayDensity(); + const fontHeight = this.nativeTextViewProtected.getPaint().getFontMetricsInt(null); + // Actual line spacing is the diff of line height and font height + const lineSpacing = Math.max(dpValue - fontHeight, 0); + + this.nativeTextViewProtected.setLineSpacing(lineSpacing, 1); + } + + _updateLetterSpacing(value: number): void { + const emValue = value / this.fontSize; + org.nativescript.widgets.ViewHelper.setLetterspacing(this.nativeTextViewProtected, emValue); + } + _setNativeText(reset = false): void { if (reset) { this.nativeTextViewProtected.setText(null); From 65048f606f38327fc43e1d35bf8f48c3b2cd7239 Mon Sep 17 00:00:00 2001 From: Dimitris - Rafail Katsampas Date: Tue, 19 Nov 2024 00:31:36 +0200 Subject: [PATCH 02/13] chore: Reverted line-height changes --- .../platforms/ios/src/UIView+NativeScript.m | 16 ---------------- packages/core/ui/text-base/index.android.ts | 17 ----------------- 2 files changed, 33 deletions(-) diff --git a/packages/core/platforms/ios/src/UIView+NativeScript.m b/packages/core/platforms/ios/src/UIView+NativeScript.m index a4c74a0bbe..aeb2a80d68 100644 --- a/packages/core/platforms/ios/src/UIView+NativeScript.m +++ b/packages/core/platforms/ios/src/UIView+NativeScript.m @@ -30,16 +30,8 @@ - (void)nativeScriptSetTextDecorationAndTransform:(NSString*)text textDecoration // make sure a possible previously set text alignment setting is not lost when line height is specified if ([self isKindOfClass:[UIButton class]]) { paragraphStyle.alignment = ((UIButton*)self).titleLabel.textAlignment; - - if (((UIButton*)self).titleLabel.font) { - paragraphStyle.lineSpacing = lineHeight - ((UIButton*)self).titleLabel.font.lineHeight; - } } else { paragraphStyle.alignment = ((UILabel*)self).textAlignment; - - if (((UILabel*)self).font) { - paragraphStyle.lineSpacing = lineHeight - ((UILabel*)self).font.lineHeight; - } } if ([self isKindOfClass:[UILabel class]]) { @@ -100,17 +92,9 @@ -(void)nativeScriptSetFormattedTextDecorationAndTransform:(NSDictionary*)details // make sure a possible previously set text alignment setting is not lost when line height is specified if ([self isKindOfClass:[UIButton class]]) { paragraphStyle.alignment = ((UIButton*)self).titleLabel.textAlignment; - - if (((UIButton*)self).titleLabel.font) { - paragraphStyle.lineSpacing = lineHeight - ((UIButton*)self).titleLabel.font.lineHeight; - } } else { // Paragraph alignment is also important for tappable spans as NSTextContainer takes it into account paragraphStyle.alignment = ((UILabel*)self).textAlignment; - - if (((UILabel*)self).font) { - paragraphStyle.lineSpacing = lineHeight - ((UILabel*)self).font.lineHeight; - } } if (isLabel) { diff --git a/packages/core/ui/text-base/index.android.ts b/packages/core/ui/text-base/index.android.ts index 580a2e3400..db85e242a3 100644 --- a/packages/core/ui/text-base/index.android.ts +++ b/packages/core/ui/text-base/index.android.ts @@ -367,14 +367,6 @@ export class TextBase extends TextBaseCommon { if (!this.formattedText) { this.nativeTextViewProtected.setTextSize(value); - // Re-calculate line-height - if (this.lineHeight != 0) { - // It's done automatically for API 28+ - if (SDK_VERSION < 28) { - this._setLineHeightLegacy(this.lineHeight); - } - } - // Re-calculate letter-spacing if (this.letterSpacing != 0) { this._updateLetterSpacing(this.letterSpacing); @@ -494,15 +486,6 @@ export class TextBase extends TextBaseCommon { } } - _setLineHeightLegacy(value: number): void { - const dpValue = value * layout.getDisplayDensity(); - const fontHeight = this.nativeTextViewProtected.getPaint().getFontMetricsInt(null); - // Actual line spacing is the diff of line height and font height - const lineSpacing = Math.max(dpValue - fontHeight, 0); - - this.nativeTextViewProtected.setLineSpacing(lineSpacing, 1); - } - _updateLetterSpacing(value: number): void { const emValue = value / this.fontSize; org.nativescript.widgets.ViewHelper.setLetterspacing(this.nativeTextViewProtected, emValue); From 68218b0e0b776ceabc3729975b11c3e3fe73047c Mon Sep 17 00:00:00 2001 From: Dimitris - Rafail Katsampas Date: Wed, 20 Nov 2024 22:53:03 +0200 Subject: [PATCH 03/13] feat: Line height corrections and percent unit --- .../platforms/ios/src/UIView+NativeScript.m | 20 +++++++++++-- .../core/ui/styling/style-properties.d.ts | 1 - packages/core/ui/styling/style/index.ts | 2 +- packages/core/ui/text-base/index.android.ts | 29 +++++++++++++++---- packages/core/ui/text-base/index.d.ts | 4 +-- packages/core/ui/text-base/index.ios.ts | 23 +++++++++++++-- .../core/ui/text-base/text-base-common.ts | 10 ++++--- 7 files changed, 71 insertions(+), 18 deletions(-) diff --git a/packages/core/platforms/ios/src/UIView+NativeScript.m b/packages/core/platforms/ios/src/UIView+NativeScript.m index aeb2a80d68..378efc069e 100644 --- a/packages/core/platforms/ios/src/UIView+NativeScript.m +++ b/packages/core/platforms/ios/src/UIView+NativeScript.m @@ -26,12 +26,20 @@ - (void)nativeScriptSetTextDecorationAndTransform:(NSString*)text textDecoration BOOL isTextView = [self isKindOfClass:[UITextView class]]; if (lineHeight > 0) { NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init]; - paragraphStyle.lineSpacing = lineHeight; + // make sure a possible previously set text alignment setting is not lost when line height is specified if ([self isKindOfClass:[UIButton class]]) { paragraphStyle.alignment = ((UIButton*)self).titleLabel.textAlignment; + + if (((UIButton*)self).titleLabel.font) { + paragraphStyle.lineSpacing = fmax(lineHeight - ((UIButton*)self).titleLabel.font.lineHeight, 0); + } } else { paragraphStyle.alignment = ((UILabel*)self).textAlignment; + + if (((UILabel*)self).font) { + paragraphStyle.lineSpacing = fmax(lineHeight - ((UILabel*)self).font.lineHeight, 0); + } } if ([self isKindOfClass:[UILabel class]]) { @@ -88,13 +96,21 @@ -(void)nativeScriptSetFormattedTextDecorationAndTransform:(NSDictionary*)details BOOL isLabel = [self isKindOfClass:[UILabel class]]; if (lineHeight > 0) { NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init]; - paragraphStyle.lineSpacing = lineHeight; + // make sure a possible previously set text alignment setting is not lost when line height is specified if ([self isKindOfClass:[UIButton class]]) { paragraphStyle.alignment = ((UIButton*)self).titleLabel.textAlignment; + + if (((UIButton*)self).titleLabel.font) { + paragraphStyle.lineSpacing = fmax(lineHeight - ((UIButton*)self).titleLabel.font.lineHeight, 0); + } } else { // Paragraph alignment is also important for tappable spans as NSTextContainer takes it into account paragraphStyle.alignment = ((UILabel*)self).textAlignment; + + if (((UILabel*)self).font) { + paragraphStyle.lineSpacing = fmax(lineHeight - ((UILabel*)self).font.lineHeight, 0); + } } if (isLabel) { diff --git a/packages/core/ui/styling/style-properties.d.ts b/packages/core/ui/styling/style-properties.d.ts index 61f99e3d0a..ab19aac513 100644 --- a/packages/core/ui/styling/style-properties.d.ts +++ b/packages/core/ui/styling/style-properties.d.ts @@ -77,7 +77,6 @@ export const minWidthProperty: CssProperty; export const widthProperty: CssAnimationProperty; export const heightProperty: CssAnimationProperty; -export const lineHeightProperty: CssProperty; export const marginProperty: ShorthandProperty; export const marginLeftProperty: CssProperty; export const marginRightProperty: CssProperty; diff --git a/packages/core/ui/styling/style/index.ts b/packages/core/ui/styling/style/index.ts index 30839455a6..8030d289d9 100644 --- a/packages/core/ui/styling/style/index.ts +++ b/packages/core/ui/styling/style/index.ts @@ -168,7 +168,7 @@ export class Style extends Observable implements StyleDefinition { public visibility: CoreTypes.VisibilityType; public letterSpacing: number; - public lineHeight: number; + public lineHeight: CoreTypes.PercentLengthType; public textAlignment: CoreTypes.TextAlignmentType; public textDecoration: CoreTypes.TextDecorationType; public textTransform: CoreTypes.TextTransformType; diff --git a/packages/core/ui/text-base/index.android.ts b/packages/core/ui/text-base/index.android.ts index db85e242a3..7dbe6a4cee 100644 --- a/packages/core/ui/text-base/index.android.ts +++ b/packages/core/ui/text-base/index.android.ts @@ -4,10 +4,9 @@ import { ShadowCSSValues } from '../styling/css-shadow'; // Requires import { Font } from '../styling/font'; -import { backgroundColorProperty } from '../styling/style-properties'; import { TextBaseCommon, formattedTextProperty, textAlignmentProperty, textDecorationProperty, textProperty, textTransformProperty, textShadowProperty, textStrokeProperty, letterSpacingProperty, whiteSpaceProperty, lineHeightProperty, isBold, resetSymbol } from './text-base-common'; import { Color } from '../../color'; -import { colorProperty, fontSizeProperty, fontInternalProperty, paddingLeftProperty, paddingTopProperty, paddingRightProperty, paddingBottomProperty, Length } from '../styling/style-properties'; +import { backgroundColorProperty, colorProperty, fontSizeProperty, fontInternalProperty, paddingLeftProperty, paddingTopProperty, paddingRightProperty, paddingBottomProperty, Length } from '../styling/style-properties'; import { StrokeCSSValues } from '../styling/css-stroke'; import { FormattedString } from './formatted-string'; import { Span } from './span'; @@ -374,11 +373,29 @@ export class TextBase extends TextBaseCommon { } } - [lineHeightProperty.getDefault](): number { - return this.nativeTextViewProtected.getLineSpacingExtra() / layout.getDisplayDensity(); + [lineHeightProperty.getDefault](): CoreTypes.PercentLengthType { + return { value: this.nativeTextViewProtected.getLineHeight(), unit: 'px' }; } - [lineHeightProperty.setNative](value: number) { - this.nativeTextViewProtected.setLineSpacing(value * layout.getDisplayDensity(), 1); + [lineHeightProperty.setNative](value: CoreTypes.PercentLengthType) { + const lengthType = value; + + if (!lengthType) { + this.nativeTextViewProtected.setLineSpacing(0, 1); + } else if (typeof lengthType !== 'number' && lengthType !== 'auto' && lengthType.unit === '%') { + this.nativeTextViewProtected.setLineSpacing(0, lengthType.value); + } else { + const dpValue = Length.toDevicePixels(lengthType, 0); + + if (SDK_VERSION >= 28) { + this.nativeTextViewProtected.setLineHeight(dpValue); + } else { + const fontHeight = this.nativeTextViewProtected.getPaint().getFontMetricsInt(null); + // Actual line spacing is the diff of line height and font height + const lineSpacing = Math.max(dpValue - fontHeight, 0); + + this.nativeTextViewProtected.setLineSpacing(lineSpacing, 1); + } + } } [fontInternalProperty.getDefault](): android.graphics.Typeface { diff --git a/packages/core/ui/text-base/index.d.ts b/packages/core/ui/text-base/index.d.ts index 8dde2ad28b..57ed3435c8 100644 --- a/packages/core/ui/text-base/index.d.ts +++ b/packages/core/ui/text-base/index.d.ts @@ -50,7 +50,7 @@ export class TextBase extends View implements AddChildFromBuilder { * * @nsProperty */ - lineHeight: number; + lineHeight: CoreTypes.PercentLengthType; /** * Gets or sets text-alignment style property. @@ -200,7 +200,7 @@ export const textStrokeProperty: CssProperty; export const whiteSpaceProperty: CssProperty; export const textOverflowProperty: CssProperty; export const letterSpacingProperty: CssProperty; -export const lineHeightProperty: CssProperty; +export const lineHeightProperty: CssProperty; //Used by tab view export function getTransformedText(text: string, textTransform: CoreTypes.TextTransformType): string; diff --git a/packages/core/ui/text-base/index.ios.ts b/packages/core/ui/text-base/index.ios.ts index fd0d42dd74..0d7aff0015 100644 --- a/packages/core/ui/text-base/index.ios.ts +++ b/packages/core/ui/text-base/index.ios.ts @@ -256,7 +256,7 @@ export class TextBase extends TextBaseCommon { this._setNativeText(); } - [lineHeightProperty.setNative](value: number) { + [lineHeightProperty.setNative](value: CoreTypes.PercentLengthType) { this._setNativeText(); } @@ -318,7 +318,8 @@ export class TextBase extends TextBaseCommon { } const letterSpacing = this.style.letterSpacing ? this.style.letterSpacing : 0; - const lineHeight = this.style.lineHeight ? this.style.lineHeight : 0; + const lineHeight = this._calculateLineHeight(); + if (this.formattedText) { this.nativeTextViewProtected.nativeScriptSetFormattedTextDecorationAndTransformLetterSpacingLineHeight(this.getFormattedStringDetails(this.formattedText) as any, letterSpacing, lineHeight); } else { @@ -330,6 +331,7 @@ export class TextBase extends TextBaseCommon { this._setColor(UIColor.labelColor); } } + if (this.style?.textStroke) { this.nativeTextViewProtected.nativeScriptSetFormattedTextStrokeColor(Length.toDevicePixels(this.style.textStroke.width, 0), this.style.textStroke.color.ios); } @@ -422,6 +424,23 @@ export class TextBase extends TextBaseCommon { } } + private _calculateLineHeight(): number { + const lengthType = this.style.lineHeight; + const fontHeight = this.nativeTextViewProtected.font?.lineHeight || 0; + + let lineHeight: number; + + if (!lengthType) { + lineHeight = 0; + } else if (typeof lengthType !== 'number' && lengthType !== 'auto' && lengthType.unit === '%') { + lineHeight = lengthType.value * fontHeight; + } else { + lineHeight = layout.toDeviceIndependentPixels(Length.toDevicePixels(lengthType, 0)); + } + + return lineHeight; + } + _setShadow(value: ShadowCSSValues): void { const layer: CALayer = this.nativeTextViewProtected.layer; diff --git a/packages/core/ui/text-base/text-base-common.ts b/packages/core/ui/text-base/text-base-common.ts index ab192d37ec..16b7b2fb7b 100644 --- a/packages/core/ui/text-base/text-base-common.ts +++ b/packages/core/ui/text-base/text-base-common.ts @@ -15,6 +15,7 @@ import { TextBase as TextBaseDefinition } from '.'; import { Color } from '../../color'; import { ShadowCSSValues, parseCSSShadow } from '../styling/css-shadow'; import { StrokeCSSValues, parseCSSStroke } from '../styling/css-stroke'; +import { Length, PercentLength } from '../styling/style-properties'; const CHILD_SPAN = 'Span'; const CHILD_FORMATTED_TEXT = 'formattedText'; @@ -86,10 +87,10 @@ export abstract class TextBaseCommon extends View implements TextBaseDefinition this.style.letterSpacing = value; } - get lineHeight(): number { + get lineHeight(): CoreTypes.PercentLengthType { return this.style.lineHeight; } - set lineHeight(value: number) { + set lineHeight(value: CoreTypes.PercentLengthType) { this.style.lineHeight = value; } @@ -361,11 +362,12 @@ export const letterSpacingProperty = new InheritedCssProperty({ }); letterSpacingProperty.register(Style); -export const lineHeightProperty = new InheritedCssProperty({ +export const lineHeightProperty = new InheritedCssProperty({ name: 'lineHeight', cssName: 'line-height', affectsLayout: __APPLE__, - valueConverter: (v) => parseFloat(v), + equalityComparer: Length.equals, + valueConverter: PercentLength.parse, }); lineHeightProperty.register(Style); From 666f26178c03d546f560977179ab2d743b8a9068 Mon Sep 17 00:00:00 2001 From: Dimitris - Rafail Katsampas Date: Thu, 2 Jan 2025 19:16:26 +0200 Subject: [PATCH 04/13] chore: Removed letter spacing calculations --- .../core/platforms/ios/src/UIView+NativeScript.m | 14 +++++++------- packages/core/ui/text-base/index.android.ts | 14 ++------------ 2 files changed, 9 insertions(+), 19 deletions(-) diff --git a/packages/core/platforms/ios/src/UIView+NativeScript.m b/packages/core/platforms/ios/src/UIView+NativeScript.m index 378efc069e..929ff9f650 100644 --- a/packages/core/platforms/ios/src/UIView+NativeScript.m +++ b/packages/core/platforms/ios/src/UIView+NativeScript.m @@ -15,8 +15,8 @@ - (void)nativeScriptSetTextDecorationAndTransform:(NSString*)text textDecoration } BOOL isTextType = [self isKindOfClass:[UITextField class]] || [self isKindOfClass:[UITextView class]] | [self isKindOfClass:[UILabel class]] | [self isKindOfClass:[UIButton class]]; - if (letterSpacing != 0 && isTextType) { - NSNumber *kern = [NSNumber numberWithDouble:letterSpacing]; + if (letterSpacing != 0 && isTextType && ((UITextView*)self).font != nil) { + NSNumber *kern = [NSNumber numberWithDouble:letterSpacing * ((UITextView*)self).font.pointSize]; attrDict[NSKernAttributeName] = kern; if ([self isKindOfClass:[UITextField class]]) { [((UITextField*)self).defaultTextAttributes setValue:kern forKey:NSKernAttributeName]; @@ -31,13 +31,13 @@ - (void)nativeScriptSetTextDecorationAndTransform:(NSString*)text textDecoration if ([self isKindOfClass:[UIButton class]]) { paragraphStyle.alignment = ((UIButton*)self).titleLabel.textAlignment; - if (((UIButton*)self).titleLabel.font) { + if (((UIButton*)self).titleLabel.font != nil) { paragraphStyle.lineSpacing = fmax(lineHeight - ((UIButton*)self).titleLabel.font.lineHeight, 0); } } else { paragraphStyle.alignment = ((UILabel*)self).textAlignment; - if (((UILabel*)self).font) { + if (((UILabel*)self).font != nil) { paragraphStyle.lineSpacing = fmax(lineHeight - ((UILabel*)self).font.lineHeight, 0); } } @@ -86,7 +86,7 @@ - (void)nativeScriptSetTextDecorationAndTransform:(NSString*)text textDecoration -(void)nativeScriptSetFormattedTextDecorationAndTransform:(NSDictionary*)details letterSpacing:(CGFloat)letterSpacing lineHeight:(CGFloat)lineHeight { NSMutableAttributedString *attrText = [NativeScriptUtils createMutableStringWithDetails:details]; if (letterSpacing != 0) { - NSNumber *kern = [NSNumber numberWithDouble:letterSpacing]; + NSNumber *kern = [NSNumber numberWithDouble:letterSpacing * ((UITextView*)self).font.pointSize]; [attrText addAttribute:NSKernAttributeName value:kern range:(NSRange){ 0, attrText.length @@ -101,14 +101,14 @@ -(void)nativeScriptSetFormattedTextDecorationAndTransform:(NSDictionary*)details if ([self isKindOfClass:[UIButton class]]) { paragraphStyle.alignment = ((UIButton*)self).titleLabel.textAlignment; - if (((UIButton*)self).titleLabel.font) { + if (((UIButton*)self).titleLabel.font != nil) { paragraphStyle.lineSpacing = fmax(lineHeight - ((UIButton*)self).titleLabel.font.lineHeight, 0); } } else { // Paragraph alignment is also important for tappable spans as NSTextContainer takes it into account paragraphStyle.alignment = ((UILabel*)self).textAlignment; - if (((UILabel*)self).font) { + if (((UILabel*)self).font != nil) { paragraphStyle.lineSpacing = fmax(lineHeight - ((UILabel*)self).font.lineHeight, 0); } } diff --git a/packages/core/ui/text-base/index.android.ts b/packages/core/ui/text-base/index.android.ts index 7dbe6a4cee..a8f835265c 100644 --- a/packages/core/ui/text-base/index.android.ts +++ b/packages/core/ui/text-base/index.android.ts @@ -365,11 +365,6 @@ export class TextBase extends TextBaseCommon { [fontSizeProperty.setNative](value: number) { if (!this.formattedText) { this.nativeTextViewProtected.setTextSize(value); - - // Re-calculate letter-spacing - if (this.letterSpacing != 0) { - this._updateLetterSpacing(this.letterSpacing); - } } } @@ -451,10 +446,10 @@ export class TextBase extends TextBaseCommon { } [letterSpacingProperty.getDefault](): number { - return org.nativescript.widgets.ViewHelper.getLetterspacing(this.nativeTextViewProtected) * this.fontSize; + return org.nativescript.widgets.ViewHelper.getLetterspacing(this.nativeTextViewProtected); } [letterSpacingProperty.setNative](value: number) { - this._updateLetterSpacing(value); + org.nativescript.widgets.ViewHelper.setLetterspacing(this.nativeTextViewProtected, value); } [paddingTopProperty.getDefault](): CoreTypes.LengthType { @@ -503,11 +498,6 @@ export class TextBase extends TextBaseCommon { } } - _updateLetterSpacing(value: number): void { - const emValue = value / this.fontSize; - org.nativescript.widgets.ViewHelper.setLetterspacing(this.nativeTextViewProtected, emValue); - } - _setNativeText(reset = false): void { if (reset) { this.nativeTextViewProtected.setText(null); From efd34355264df4d43969ed41d33adf596d705671 Mon Sep 17 00:00:00 2001 From: Dimitris - Rafail Katsampas Date: Sat, 25 Jan 2025 16:14:00 +0200 Subject: [PATCH 05/13] fix: Get UIButton font height from title label --- packages/core/ui/text-base/index.ios.ts | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/packages/core/ui/text-base/index.ios.ts b/packages/core/ui/text-base/index.ios.ts index 0d7aff0015..90f1e95269 100644 --- a/packages/core/ui/text-base/index.ios.ts +++ b/packages/core/ui/text-base/index.ios.ts @@ -256,6 +256,13 @@ export class TextBase extends TextBaseCommon { this._setNativeText(); } + [lineHeightProperty.getDefault](): CoreTypes.PercentLengthType { + const nativeTextView = this.nativeTextViewProtected; + const nativeFont = nativeTextView instanceof UIButton ? nativeTextView.titleLabel.font : nativeTextView.font; + + return nativeFont?.lineHeight ?? 0; + } + [lineHeightProperty.setNative](value: CoreTypes.PercentLengthType) { this._setNativeText(); } @@ -426,13 +433,21 @@ export class TextBase extends TextBaseCommon { private _calculateLineHeight(): number { const lengthType = this.style.lineHeight; - const fontHeight = this.nativeTextViewProtected.font?.lineHeight || 0; + const nativeTextView = this.nativeTextViewProtected; + const nativeFont = nativeTextView instanceof UIButton ? nativeTextView.titleLabel.font : nativeTextView.font; + // Get font lineHeight value to simulate what android does with getFontMetricsInt + const fontHeight = nativeFont?.lineHeight || 0; let lineHeight: number; if (!lengthType) { lineHeight = 0; - } else if (typeof lengthType !== 'number' && lengthType !== 'auto' && lengthType.unit === '%') { + } else if (typeof lengthType === 'number') { + lineHeight = lengthType; + } else if (typeof lengthType === 'string') { + // e.g. normal + lineHeight = fontHeight; + } else if (lengthType.unit === '%') { lineHeight = lengthType.value * fontHeight; } else { lineHeight = layout.toDeviceIndependentPixels(Length.toDevicePixels(lengthType, 0)); From 58a1154d4fc607f4c4e4d64cd8eadb071fa5657b Mon Sep 17 00:00:00 2001 From: Dimitris - Rafail Katsampas Date: Sat, 25 Jan 2025 17:43:51 +0200 Subject: [PATCH 06/13] fix: Corrected zero and percentage line-height --- packages/core/ui/text-base/index.android.ts | 23 +++++++++++++++------ packages/core/ui/text-base/index.ios.ts | 7 ++----- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/packages/core/ui/text-base/index.android.ts b/packages/core/ui/text-base/index.android.ts index a8f835265c..ae58e98d86 100644 --- a/packages/core/ui/text-base/index.android.ts +++ b/packages/core/ui/text-base/index.android.ts @@ -374,19 +374,30 @@ export class TextBase extends TextBaseCommon { [lineHeightProperty.setNative](value: CoreTypes.PercentLengthType) { const lengthType = value; - if (!lengthType) { + if (lengthType == null || typeof lengthType === 'string') { + // Method setLineHeight calls this one internally so it's enough to do the cleanup this.nativeTextViewProtected.setLineSpacing(0, 1); - } else if (typeof lengthType !== 'number' && lengthType !== 'auto' && lengthType.unit === '%') { - this.nativeTextViewProtected.setLineSpacing(0, lengthType.value); } else { - const dpValue = Length.toDevicePixels(lengthType, 0); + let finalValue: number; + + if (typeof lengthType === 'number') { + finalValue = Length.toDevicePixels(lengthType, 0); + } else if (lengthType.unit === '%') { + const fontHeight = this.nativeTextViewProtected.getPaint().getFontMetricsInt(null); + finalValue = lengthType.value * fontHeight; + } else { + finalValue = Length.toDevicePixels(lengthType, 0); + } + + // Method setLineHeight throws in case of a negative value + finalValue = Math.max(finalValue, 0); if (SDK_VERSION >= 28) { - this.nativeTextViewProtected.setLineHeight(dpValue); + this.nativeTextViewProtected.setLineHeight(finalValue); } else { const fontHeight = this.nativeTextViewProtected.getPaint().getFontMetricsInt(null); // Actual line spacing is the diff of line height and font height - const lineSpacing = Math.max(dpValue - fontHeight, 0); + const lineSpacing = finalValue - fontHeight; this.nativeTextViewProtected.setLineSpacing(lineSpacing, 1); } diff --git a/packages/core/ui/text-base/index.ios.ts b/packages/core/ui/text-base/index.ios.ts index 90f1e95269..483d28b756 100644 --- a/packages/core/ui/text-base/index.ios.ts +++ b/packages/core/ui/text-base/index.ios.ts @@ -440,13 +440,10 @@ export class TextBase extends TextBaseCommon { let lineHeight: number; - if (!lengthType) { - lineHeight = 0; + if (lengthType == null || typeof lengthType === 'string') { + lineHeight = fontHeight; } else if (typeof lengthType === 'number') { lineHeight = lengthType; - } else if (typeof lengthType === 'string') { - // e.g. normal - lineHeight = fontHeight; } else if (lengthType.unit === '%') { lineHeight = lengthType.value * fontHeight; } else { From a99f1d1e5ce4a670a3b42ae5fd03052130563531 Mon Sep 17 00:00:00 2001 From: Dimitris - Rafail Katsampas Date: Sat, 25 Jan 2025 18:51:41 +0200 Subject: [PATCH 07/13] chore: Get UIButton point size from title label font --- .../platforms/ios/src/UIView+NativeScript.m | 32 +++++++++++++++---- 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/packages/core/platforms/ios/src/UIView+NativeScript.m b/packages/core/platforms/ios/src/UIView+NativeScript.m index 929ff9f650..9990f2fde5 100644 --- a/packages/core/platforms/ios/src/UIView+NativeScript.m +++ b/packages/core/platforms/ios/src/UIView+NativeScript.m @@ -15,11 +15,24 @@ - (void)nativeScriptSetTextDecorationAndTransform:(NSString*)text textDecoration } BOOL isTextType = [self isKindOfClass:[UITextField class]] || [self isKindOfClass:[UITextView class]] | [self isKindOfClass:[UILabel class]] | [self isKindOfClass:[UIButton class]]; - if (letterSpacing != 0 && isTextType && ((UITextView*)self).font != nil) { - NSNumber *kern = [NSNumber numberWithDouble:letterSpacing * ((UITextView*)self).font.pointSize]; - attrDict[NSKernAttributeName] = kern; - if ([self isKindOfClass:[UITextField class]]) { - [((UITextField*)self).defaultTextAttributes setValue:kern forKey:NSKernAttributeName]; + if (letterSpacing != 0 && isTextType) { + NSNumber *kern = nil; + + if ([self isKindOfClass:[UIButton class]]) { + if (((UIButton*)self).titleLabel.font != nil) { + kern = [NSNumber numberWithDouble:letterSpacing * ((UIButton*)self).titleLabel.font.pointSize]; + } + } else { + if (((UITextView*)self).font != nil) { + kern = [NSNumber numberWithDouble:letterSpacing * ((UITextView*)self).font.pointSize]; + } + } + + if (kern != nil) { + attrDict[NSKernAttributeName] = kern; + if ([self isKindOfClass:[UITextField class]]) { + [((UITextField*)self).defaultTextAttributes setValue:kern forKey:NSKernAttributeName]; + } } } @@ -86,7 +99,14 @@ - (void)nativeScriptSetTextDecorationAndTransform:(NSString*)text textDecoration -(void)nativeScriptSetFormattedTextDecorationAndTransform:(NSDictionary*)details letterSpacing:(CGFloat)letterSpacing lineHeight:(CGFloat)lineHeight { NSMutableAttributedString *attrText = [NativeScriptUtils createMutableStringWithDetails:details]; if (letterSpacing != 0) { - NSNumber *kern = [NSNumber numberWithDouble:letterSpacing * ((UITextView*)self).font.pointSize]; + NSNumber *kern = nil; + + if ([self isKindOfClass:[UIButton class]]) { + kern = [NSNumber numberWithDouble:letterSpacing * ((UIButton*)self).titleLabel.font.pointSize]; + } else { + kern = [NSNumber numberWithDouble:letterSpacing * ((UITextView*)self).font.pointSize]; + } + [attrText addAttribute:NSKernAttributeName value:kern range:(NSRange){ 0, attrText.length From a58503cc3534d04695d3f2391d7aff496285e266 Mon Sep 17 00:00:00 2001 From: Dimitris - Rafail Katsampas Date: Sat, 25 Jan 2025 18:52:39 +0200 Subject: [PATCH 08/13] fix: Formatted iOS button incorrect default text color --- packages/core/ui/text-base/index.ios.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/core/ui/text-base/index.ios.ts b/packages/core/ui/text-base/index.ios.ts index 483d28b756..ff1179eaf0 100644 --- a/packages/core/ui/text-base/index.ios.ts +++ b/packages/core/ui/text-base/index.ios.ts @@ -330,13 +330,13 @@ export class TextBase extends TextBaseCommon { if (this.formattedText) { this.nativeTextViewProtected.nativeScriptSetFormattedTextDecorationAndTransformLetterSpacingLineHeight(this.getFormattedStringDetails(this.formattedText) as any, letterSpacing, lineHeight); } else { - // console.log('setTextDecorationAndTransform...') const text = getTransformedText(isNullOrUndefined(this.text) ? '' : `${this.text}`, this.textTransform); this.nativeTextViewProtected.nativeScriptSetTextDecorationAndTransformTextDecorationLetterSpacingLineHeight(text, this.style.textDecoration || '', letterSpacing, lineHeight); + } - if (!this.style?.color && majorVersion >= 13 && UIColor.labelColor) { - this._setColor(UIColor.labelColor); - } + // Apply this default to both regular and formatted text, otherwise UIButton will use its own default + if (!this.style?.color && majorVersion >= 13 && UIColor.labelColor) { + this._setColor(UIColor.labelColor); } if (this.style?.textStroke) { From 28d911942353969f8c72efb1b8b973e7d16164ee Mon Sep 17 00:00:00 2001 From: Dimitris - Rafail Katsampas Date: Sat, 25 Jan 2025 19:11:03 +0200 Subject: [PATCH 09/13] chore: Small type correction --- packages/core/ui/index.ts | 2 +- packages/core/ui/text-base/index.d.ts | 2 +- packages/core/ui/text-base/index.ios.ts | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/core/ui/index.ts b/packages/core/ui/index.ts index 039b7d038a..42f9a478ef 100644 --- a/packages/core/ui/index.ts +++ b/packages/core/ui/index.ts @@ -71,7 +71,7 @@ export { CSSHelper } from './styling/css-selector'; export { Switch } from './switch'; export { TabView, TabViewItem } from './tab-view'; -export { TextBase, getTransformedText, letterSpacingProperty, textAlignmentProperty, textDecorationProperty, textTransformProperty, textShadowProperty, textStrokeProperty, whiteSpaceProperty, textOverflowProperty, lineHeightProperty } from './text-base'; +export { TextBase, getTransformedText, letterSpacingProperty, textAlignmentProperty, textDecorationProperty, textTransformProperty, textShadowProperty, textStrokeProperty, whiteSpaceProperty, textOverflowProperty } from './text-base'; export { FormattedString } from './text-base/formatted-string'; export { Span } from './text-base/span'; export { TextField } from './text-field'; diff --git a/packages/core/ui/text-base/index.d.ts b/packages/core/ui/text-base/index.d.ts index 57ed3435c8..71c7945916 100644 --- a/packages/core/ui/text-base/index.d.ts +++ b/packages/core/ui/text-base/index.d.ts @@ -200,7 +200,7 @@ export const textStrokeProperty: CssProperty; export const whiteSpaceProperty: CssProperty; export const textOverflowProperty: CssProperty; export const letterSpacingProperty: CssProperty; -export const lineHeightProperty: CssProperty; +export const lineHeightProperty: InheritedCssProperty; //Used by tab view export function getTransformedText(text: string, textTransform: CoreTypes.TextTransformType): string; diff --git a/packages/core/ui/text-base/index.ios.ts b/packages/core/ui/text-base/index.ios.ts index ff1179eaf0..8b950756a1 100644 --- a/packages/core/ui/text-base/index.ios.ts +++ b/packages/core/ui/text-base/index.ios.ts @@ -259,7 +259,6 @@ export class TextBase extends TextBaseCommon { [lineHeightProperty.getDefault](): CoreTypes.PercentLengthType { const nativeTextView = this.nativeTextViewProtected; const nativeFont = nativeTextView instanceof UIButton ? nativeTextView.titleLabel.font : nativeTextView.font; - return nativeFont?.lineHeight ?? 0; } From b84effb023d8657bd306739561ce35bc2569cf76 Mon Sep 17 00:00:00 2001 From: Dimitris - Rafail Katsampas Date: Sat, 25 Jan 2025 19:41:26 +0200 Subject: [PATCH 10/13] fix: Avoid setting text paragraph style when line height is not set --- packages/core/platforms/ios/src/UIView+NativeScript.m | 6 ++++-- packages/core/ui/text-base/index.ios.ts | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/core/platforms/ios/src/UIView+NativeScript.m b/packages/core/platforms/ios/src/UIView+NativeScript.m index 9990f2fde5..75c9260c4b 100644 --- a/packages/core/platforms/ios/src/UIView+NativeScript.m +++ b/packages/core/platforms/ios/src/UIView+NativeScript.m @@ -37,7 +37,8 @@ - (void)nativeScriptSetTextDecorationAndTransform:(NSString*)text textDecoration } BOOL isTextView = [self isKindOfClass:[UITextView class]]; - if (lineHeight > 0) { + // TODO: Find a good alternative of lineSpacing that works well with layout as it doesn't accept values less than the standard height + if (lineHeight >= 0) { NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init]; // make sure a possible previously set text alignment setting is not lost when line height is specified @@ -114,7 +115,8 @@ -(void)nativeScriptSetFormattedTextDecorationAndTransform:(NSDictionary*)details } BOOL isLabel = [self isKindOfClass:[UILabel class]]; - if (lineHeight > 0) { + // TODO: Find a good alternative of lineSpacing that works well with layout as it doesn't accept values less than the standard height + if (lineHeight >= 0) { NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init]; // make sure a possible previously set text alignment setting is not lost when line height is specified diff --git a/packages/core/ui/text-base/index.ios.ts b/packages/core/ui/text-base/index.ios.ts index 8b950756a1..0bfef11a85 100644 --- a/packages/core/ui/text-base/index.ios.ts +++ b/packages/core/ui/text-base/index.ios.ts @@ -440,7 +440,7 @@ export class TextBase extends TextBaseCommon { let lineHeight: number; if (lengthType == null || typeof lengthType === 'string') { - lineHeight = fontHeight; + lineHeight = -1; // This indicates that line-height is normal } else if (typeof lengthType === 'number') { lineHeight = lengthType; } else if (lengthType.unit === '%') { From a5b2994198544d7836c063ca566f947e08f57537 Mon Sep 17 00:00:00 2001 From: Dimitris - Rafail Katsampas Date: Sat, 25 Jan 2025 19:56:32 +0200 Subject: [PATCH 11/13] chore: Corrected defaults for 'auto' --- packages/core/ui/text-base/index.android.ts | 4 ++-- packages/core/ui/text-base/index.ios.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/core/ui/text-base/index.android.ts b/packages/core/ui/text-base/index.android.ts index ae58e98d86..2114784862 100644 --- a/packages/core/ui/text-base/index.android.ts +++ b/packages/core/ui/text-base/index.android.ts @@ -381,12 +381,12 @@ export class TextBase extends TextBaseCommon { let finalValue: number; if (typeof lengthType === 'number') { - finalValue = Length.toDevicePixels(lengthType, 0); + finalValue = Length.toDevicePixels(lengthType, -1); } else if (lengthType.unit === '%') { const fontHeight = this.nativeTextViewProtected.getPaint().getFontMetricsInt(null); finalValue = lengthType.value * fontHeight; } else { - finalValue = Length.toDevicePixels(lengthType, 0); + finalValue = Length.toDevicePixels(lengthType, -1); } // Method setLineHeight throws in case of a negative value diff --git a/packages/core/ui/text-base/index.ios.ts b/packages/core/ui/text-base/index.ios.ts index 0bfef11a85..7c2a5c44d0 100644 --- a/packages/core/ui/text-base/index.ios.ts +++ b/packages/core/ui/text-base/index.ios.ts @@ -446,7 +446,7 @@ export class TextBase extends TextBaseCommon { } else if (lengthType.unit === '%') { lineHeight = lengthType.value * fontHeight; } else { - lineHeight = layout.toDeviceIndependentPixels(Length.toDevicePixels(lengthType, 0)); + lineHeight = layout.toDeviceIndependentPixels(Length.toDevicePixels(lengthType, -1)); } return lineHeight; From 5741703d3eed2774391748745e9ac881536a6c2a Mon Sep 17 00:00:00 2001 From: Dimitris - Rafail Katsampas Date: Sat, 25 Jan 2025 20:14:39 +0200 Subject: [PATCH 12/13] chore: Adding back a removed export --- packages/core/ui/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/ui/index.ts b/packages/core/ui/index.ts index 42f9a478ef..039b7d038a 100644 --- a/packages/core/ui/index.ts +++ b/packages/core/ui/index.ts @@ -71,7 +71,7 @@ export { CSSHelper } from './styling/css-selector'; export { Switch } from './switch'; export { TabView, TabViewItem } from './tab-view'; -export { TextBase, getTransformedText, letterSpacingProperty, textAlignmentProperty, textDecorationProperty, textTransformProperty, textShadowProperty, textStrokeProperty, whiteSpaceProperty, textOverflowProperty } from './text-base'; +export { TextBase, getTransformedText, letterSpacingProperty, textAlignmentProperty, textDecorationProperty, textTransformProperty, textShadowProperty, textStrokeProperty, whiteSpaceProperty, textOverflowProperty, lineHeightProperty } from './text-base'; export { FormattedString } from './text-base/formatted-string'; export { Span } from './text-base/span'; export { TextField } from './text-field'; From 06f1dd8a95c862ad1c1ad47ddc6aa94b8b292e31 Mon Sep 17 00:00:00 2001 From: Dimitris - Rafail Katsampas Date: Sat, 25 Jan 2025 20:16:25 +0200 Subject: [PATCH 13/13] chore: Minor check improvement --- packages/core/ui/text-base/index.ios.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/ui/text-base/index.ios.ts b/packages/core/ui/text-base/index.ios.ts index 7c2a5c44d0..b847143b1f 100644 --- a/packages/core/ui/text-base/index.ios.ts +++ b/packages/core/ui/text-base/index.ios.ts @@ -435,7 +435,7 @@ export class TextBase extends TextBaseCommon { const nativeTextView = this.nativeTextViewProtected; const nativeFont = nativeTextView instanceof UIButton ? nativeTextView.titleLabel.font : nativeTextView.font; // Get font lineHeight value to simulate what android does with getFontMetricsInt - const fontHeight = nativeFont?.lineHeight || 0; + const fontHeight = nativeFont?.lineHeight ?? 0; let lineHeight: number;