From 95f3772e77bdfcc6c78ad7365a6c376bdbe01482 Mon Sep 17 00:00:00 2001 From: Dimitris-Rafail Katsampas Date: Thu, 23 Mar 2023 00:13:46 +0200 Subject: [PATCH] fix(ios): support for a11y font scale (#10207) --- .../ui/styling/style-properties-tests.ios.ts | 17 ++++++++++++ .../accessibility/accessibility-properties.ts | 19 ++++---------- packages/core/ui/styling/font.ios.ts | 3 ++- packages/core/ui/styling/style-properties.ts | 15 +---------- packages/core/ui/styling/style/index.ts | 3 +++ packages/core/ui/text-base/index.ios.ts | 26 ++++++++++++++++--- 6 files changed, 50 insertions(+), 33 deletions(-) create mode 100644 apps/automated/src/ui/styling/style-properties-tests.ios.ts diff --git a/apps/automated/src/ui/styling/style-properties-tests.ios.ts b/apps/automated/src/ui/styling/style-properties-tests.ios.ts new file mode 100644 index 000000000..76d8aeabf --- /dev/null +++ b/apps/automated/src/ui/styling/style-properties-tests.ios.ts @@ -0,0 +1,17 @@ +import * as TKUnit from '../../tk-unit'; +import * as helper from '../../ui-helper'; +import { Label } from '@nativescript/core'; + +export function test_native_font_size_with_a11y_font_scale() { + const page = helper.getCurrentPage(); + const testView = new Label(); + const deviceFontScaleMock = 4.0; + + page.content = testView; + + testView.style._fontScale = deviceFontScaleMock; + + const nativeFontSize = testView.nativeTextViewProtected.font.pointSize; + const expectedNativeFontSize = testView.style.fontInternal.fontSize * deviceFontScaleMock; + TKUnit.assertEqual(nativeFontSize, expectedNativeFontSize, 'View font size does not respect a11y font scaling'); +} diff --git a/packages/core/accessibility/accessibility-properties.ts b/packages/core/accessibility/accessibility-properties.ts index 6f2ec7c25..9d899e15c 100644 --- a/packages/core/accessibility/accessibility-properties.ts +++ b/packages/core/accessibility/accessibility-properties.ts @@ -31,20 +31,11 @@ export const accessibilityEnabledProperty = new CssProperty({ }); accessibilityEnabledProperty.register(Style); -const accessibilityHiddenPropertyName = 'accessibilityHidden'; -const accessibilityHiddenCssName = 'a11y-hidden'; - -export const accessibilityHiddenProperty = global.isIOS - ? new InheritedCssProperty({ - name: accessibilityHiddenPropertyName, - cssName: accessibilityHiddenCssName, - valueConverter: booleanConverter, - }) - : new CssProperty({ - name: accessibilityHiddenPropertyName, - cssName: accessibilityHiddenCssName, - valueConverter: booleanConverter, - }); +export const accessibilityHiddenProperty = new (global.isIOS ? InheritedCssProperty : CssProperty)({ + name: 'accessibilityHidden', + cssName: 'a11y-hidden', + valueConverter: booleanConverter, +}); accessibilityHiddenProperty.register(Style); export const accessibilityIdentifierProperty = new Property({ diff --git a/packages/core/ui/styling/font.ios.ts b/packages/core/ui/styling/font.ios.ts index f1f861318..3201efdac 100644 --- a/packages/core/ui/styling/font.ios.ts +++ b/packages/core/ui/styling/font.ios.ts @@ -91,7 +91,8 @@ export class Font extends FontBase { getUIFont(defaultFont: UIFont): UIFont { return getUIFontCached({ fontFamily: parseFontFamily(this.fontFamily), - fontSize: this.fontSize || defaultFont.pointSize, + // Apply a11y scale and calculate proper font size (avoid applying multiplier to native point size as it's messing calculations) + fontSize: this.fontSize ? this.fontSize * this.fontScale : defaultFont.pointSize, fontWeight: getNativeFontWeight(this.fontWeight), fontVariationSettings: this.fontVariationSettings, isBold: this.isBold, diff --git a/packages/core/ui/styling/style-properties.ts b/packages/core/ui/styling/style-properties.ts index 54857c7e6..7e9038fae 100644 --- a/packages/core/ui/styling/style-properties.ts +++ b/packages/core/ui/styling/style-properties.ts @@ -1329,20 +1329,7 @@ fontFamilyProperty.register(Style); export const fontScaleProperty = new InheritedCssProperty({ name: '_fontScale', cssName: '_fontScale', - affectsLayout: global.isIOS, - valueChanged: (target, oldValue, newValue) => { - if (global.isIOS) { - if (target.viewRef['handleFontSize'] === true) { - return; - } - - const currentFont = target.fontInternal || Font.default; - if (currentFont.fontScale !== newValue) { - const newFont = currentFont.withFontScale(newValue); - target.fontInternal = Font.equals(Font.default, newFont) ? unsetValue : newFont; - } - } - }, + defaultValue: 1.0, valueConverter: (v) => parseFloat(v), }); fontScaleProperty.register(Style); diff --git a/packages/core/ui/styling/style/index.ts b/packages/core/ui/styling/style/index.ts index dfeae2ea5..4fa4d0673 100644 --- a/packages/core/ui/styling/style/index.ts +++ b/packages/core/ui/styling/style/index.ts @@ -105,6 +105,9 @@ export class Style extends Observable implements StyleDefinition { } public fontInternal: Font; + /** + * This property ensures inheritance of a11y scale among views. + */ public _fontScale: number; public backgroundInternal: Background; diff --git a/packages/core/ui/text-base/index.ios.ts b/packages/core/ui/text-base/index.ios.ts index b8a80c5a7..30644e5be 100644 --- a/packages/core/ui/text-base/index.ios.ts +++ b/packages/core/ui/text-base/index.ios.ts @@ -4,16 +4,15 @@ import { CSSShadow } from '../styling/css-shadow'; // Requires import { Font } from '../styling/font'; -import { TextBaseCommon, textProperty, formattedTextProperty, textAlignmentProperty, textDecorationProperty, textTransformProperty, textShadowProperty, letterSpacingProperty, lineHeightProperty, resetSymbol } from './text-base-common'; +import { TextBaseCommon, textProperty, formattedTextProperty, textAlignmentProperty, textDecorationProperty, textTransformProperty, textShadowProperty, letterSpacingProperty, lineHeightProperty, maxLinesProperty, resetSymbol } from './text-base-common'; import { Color } from '../../color'; import { FormattedString } from './formatted-string'; import { Span } from './span'; -import { colorProperty, fontInternalProperty, Length } from '../styling/style-properties'; +import { colorProperty, fontInternalProperty, fontScaleProperty, Length } from '../styling/style-properties'; import { isString, isNullOrUndefined } from '../../utils/types'; import { iOSNativeHelper } from '../../utils'; import { Trace } from '../../trace'; import { CoreTypes } from '../../core-types'; -import { maxLinesProperty } from './text-base-common'; export * from './text-base-common'; @@ -188,7 +187,26 @@ export class TextBase extends TextBaseCommon { if (!(value instanceof Font) || !this.formattedText) { let nativeView = this.nativeTextViewProtected; nativeView = nativeView instanceof UIButton ? nativeView.titleLabel : nativeView; - nativeView.font = value instanceof Font ? value.getUIFont(nativeView.font) : value; + + if (value instanceof Font) { + // Apply a11y font scale if not set + if (value.fontScale !== this.style._fontScale) { + value.fontScale = this.style._fontScale; + } + nativeView.font = value.getUIFont(nativeView.font); + } else { + nativeView.font = value; + } + } + } + + [fontScaleProperty.setNative](value: number) { + const nativeView = this.nativeTextViewProtected instanceof UIButton ? this.nativeTextViewProtected.titleLabel : this.nativeTextViewProtected; + const currentFont = this.style.fontInternal || Font.default.withFontSize(nativeView.font.pointSize); + if (currentFont.fontScale !== value) { + const newFont = currentFont.withFontScale(value); + this.style.fontInternal = newFont; + this.requestLayout(); } }