diff --git a/packages/core/ui/text-base/index.d.ts b/packages/core/ui/text-base/index.d.ts index e432b153a..4d2ea4f77 100644 --- a/packages/core/ui/text-base/index.d.ts +++ b/packages/core/ui/text-base/index.d.ts @@ -99,6 +99,16 @@ export class TextBase extends View implements AddChildFromBuilder { */ paddingTop: CoreTypes.LengthType; + /** + * Specify wether the native text should be applied with or without animations + */ + iosTextAnimation: 'inherit' | boolean; + + /** + * The value used when the iosTextAnimation is set to 'inherit' + */ + static iosTextAnimationFallback: boolean; + /** * Called for every child element declared in xml. * This method will add a child element (value) to current element. diff --git a/packages/core/ui/text-base/index.ios.ts b/packages/core/ui/text-base/index.ios.ts index 06416d73d..fedad4df0 100644 --- a/packages/core/ui/text-base/index.ios.ts +++ b/packages/core/ui/text-base/index.ios.ts @@ -291,39 +291,49 @@ export class TextBase extends TextBaseCommon { this.nativeTextViewProtected.textColor = color; } } + _animationWrap(fn: () => void) { + const shouldAnimate = this.iosTextAnimation === 'inherit' ? TextBase.iosTextAnimationFallback : this.iosTextAnimation; + if (shouldAnimate) { + fn(); + } else { + UIView.performWithoutAnimation(fn); + } + } _setNativeText(reset = false): void { - if (reset) { - const nativeView = this.nativeTextViewProtected; - if (nativeView instanceof UIButton) { - // Clear attributedText or title won't be affected. - nativeView.setAttributedTitleForState(null, UIControlState.Normal); - nativeView.setTitleForState(null, UIControlState.Normal); + this._animationWrap(() => { + if (reset) { + const nativeView = this.nativeTextViewProtected; + if (nativeView instanceof UIButton) { + // Clear attributedText or title won't be affected. + nativeView.setAttributedTitleForState(null, UIControlState.Normal); + nativeView.setTitleForState(null, UIControlState.Normal); + } else { + // Clear attributedText or text won't be affected. + nativeView.attributedText = null; + nativeView.text = null; + } + + return; + } + + const letterSpacing = this.style.letterSpacing ? this.style.letterSpacing : 0; + const lineHeight = this.style.lineHeight ? this.style.lineHeight : 0; + if (this.formattedText) { + this.nativeTextViewProtected.nativeScriptSetFormattedTextDecorationAndTransformLetterSpacingLineHeight(this.getFormattedStringDetails(this.formattedText) as any, letterSpacing, lineHeight); } else { - // Clear attributedText or text won't be affected. - nativeView.attributedText = null; - nativeView.text = null; + // 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); + } } - - return; - } - - const letterSpacing = this.style.letterSpacing ? this.style.letterSpacing : 0; - const lineHeight = this.style.lineHeight ? this.style.lineHeight : 0; - 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); + if (this.style?.textStroke) { + this.nativeTextViewProtected.nativeScriptSetFormattedTextStrokeColor(Length.toDevicePixels(this.style.textStroke.width, 0), this.style.textStroke.color.ios); } - } - if (this.style?.textStroke) { - this.nativeTextViewProtected.nativeScriptSetFormattedTextStrokeColor(Length.toDevicePixels(this.style.textStroke.width, 0), this.style.textStroke.color.ios); - } + }); } createFormattedTextNative(value: FormattedString) { diff --git a/packages/core/ui/text-base/text-base-common.ts b/packages/core/ui/text-base/text-base-common.ts index 274f4f8da..eb5ad595b 100644 --- a/packages/core/ui/text-base/text-base-common.ts +++ b/packages/core/ui/text-base/text-base-common.ts @@ -1,6 +1,6 @@ // Types import { PropertyChangeData } from '../../data/observable'; -import { ViewBase } from '../core/view-base'; +import { ViewBase, booleanConverter } from '../core/view-base'; import { FontStyleType, FontWeightType } from '../styling/font-interfaces'; // Requires. @@ -24,6 +24,8 @@ export abstract class TextBaseCommon extends View implements TextBaseDefinition public _isSingleLine: boolean; public text: string; public formattedText: FormattedString; + public iosTextAnimation: 'inherit' | boolean; + static iosTextAnimationFallback = true; /*** * In the NativeScript Core; by default the nativeTextViewProtected points to the same value as nativeViewProtected. @@ -236,6 +238,20 @@ export const formattedTextProperty = new Property({ + name: 'iosTextAnimation', + defaultValue: 'inherit', + affectsLayout: false, + valueConverter(value: string) { + try { + return booleanConverter(value); + } catch (e) { + return 'inherit'; + } + }, +}); +iosTextAnimationProperty.register(TextBaseCommon); + function onFormattedTextPropertyChanged(textBase: TextBaseCommon, oldValue: FormattedString, newValue: FormattedString) { if (oldValue) { oldValue.off(Observable.propertyChangeEvent, textBase._onFormattedTextContentsChanged, textBase);