mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-08-14 18:12:09 +08:00
fix(ios): FormattedString and Span a11y font scale (#10281)
This commit is contained in:

committed by
GitHub

parent
b8a548f009
commit
a14becdc6a
@ -227,6 +227,9 @@ allTests['LISTVIEW'] = listViewTests;
|
||||
import * as activityIndicatorTests from './ui/activity-indicator/activity-indicator-tests';
|
||||
allTests['ACTIVITY-INDICATOR'] = activityIndicatorTests;
|
||||
|
||||
import * as textBaseTests from './ui/text-base/text-base-tests';
|
||||
allTests['TEXT-BASE'] = textBaseTests;
|
||||
|
||||
import * as textFieldTests from './ui/text-field/text-field-tests';
|
||||
allTests['TEXT-FIELD'] = textFieldTests;
|
||||
|
||||
|
@ -580,26 +580,6 @@ export function test_setting_font_properties_sets_native_font() {
|
||||
test_native_font('italic', 'bold');
|
||||
}
|
||||
|
||||
export function test_native_font_size_with_a11y_font_scale() {
|
||||
if (isIOS) {
|
||||
const deviceFontScaleMock = 4.0;
|
||||
|
||||
const page = helper.getCurrentPage();
|
||||
const testView = new Label();
|
||||
const layout = new StackLayout();
|
||||
layout.addChild(testView);
|
||||
|
||||
page.content = layout;
|
||||
|
||||
layout.style.iosAccessibilityAdjustsFontSize = true;
|
||||
layout.style.fontScaleInternal = 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');
|
||||
}
|
||||
}
|
||||
|
||||
function test_native_font(style: 'normal' | 'italic', weight: '100' | '200' | '300' | 'normal' | '400' | '500' | '600' | 'bold' | '700' | '800' | '900') {
|
||||
const testView = new Button();
|
||||
|
||||
|
23
apps/automated/src/ui/text-base/text-base-tests.ts
Normal file
23
apps/automated/src/ui/text-base/text-base-tests.ts
Normal file
@ -0,0 +1,23 @@
|
||||
import * as TKUnit from '../../tk-unit';
|
||||
import * as helper from '../../ui-helper';
|
||||
import { FormattedString, isIOS, Label, Span, StackLayout } from '@nativescript/core';
|
||||
|
||||
export function test_native_font_size_with_a11y_font_scale() {
|
||||
if (isIOS) {
|
||||
const deviceFontScaleMock = 4.0;
|
||||
|
||||
const page = helper.getCurrentPage();
|
||||
const testView = new Label();
|
||||
const layout = new StackLayout();
|
||||
layout.addChild(testView);
|
||||
|
||||
page.content = layout;
|
||||
|
||||
layout.style.iosAccessibilityAdjustsFontSize = true;
|
||||
layout.style.fontScaleInternal = 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');
|
||||
}
|
||||
}
|
21
packages/core/ui/text-base/formatted-string.d.ts
vendored
21
packages/core/ui/text-base/formatted-string.d.ts
vendored
@ -6,7 +6,7 @@ import { Span } from './span';
|
||||
import { ObservableArray } from '../../data/observable-array';
|
||||
import { ViewBase } from '../core/view-base';
|
||||
import { Color } from '../../color';
|
||||
import { FontStyle, FontWeight } from '../styling/font';
|
||||
import { FontStyleType, FontWeightType } from '../styling/font';
|
||||
import { CoreTypes } from '../../core-types';
|
||||
|
||||
/**
|
||||
@ -36,12 +36,12 @@ export class FormattedString extends ViewBase {
|
||||
/**
|
||||
* Gets or sets the font style which will be used for all spans that doesn't have a specific value.
|
||||
*/
|
||||
public fontStyle: FontStyle;
|
||||
public fontStyle: FontStyleType;
|
||||
|
||||
/**
|
||||
* Gets or sets the font weight which will be used for all spans that doesn't have a specific value.
|
||||
*/
|
||||
public fontWeight: FontWeight;
|
||||
public fontWeight: FontWeightType;
|
||||
|
||||
/**
|
||||
* Gets or sets text decorations which will be used for all spans that doesn't have a specific value.
|
||||
@ -57,4 +57,19 @@ export class FormattedString extends ViewBase {
|
||||
* Gets or sets the font background color which will be used for all spans that doesn't have a specific value.
|
||||
*/
|
||||
public backgroundColor: Color;
|
||||
|
||||
/**
|
||||
* Defines whether accessibility font scale should affect font size.
|
||||
*/
|
||||
iosAccessibilityAdjustsFontSize: boolean;
|
||||
|
||||
/**
|
||||
* Gets or sets the minimum accessibility font scale.
|
||||
*/
|
||||
iosAccessibilityMinFontScale: number;
|
||||
|
||||
/**
|
||||
* Gets or sets the maximum accessibility font scale.
|
||||
*/
|
||||
iosAccessibilityMaxFontScale: number;
|
||||
}
|
||||
|
@ -66,6 +66,27 @@ export class FormattedString extends ViewBase implements FormattedStringDefiniti
|
||||
this.style.backgroundColor = value;
|
||||
}
|
||||
|
||||
get iosAccessibilityAdjustsFontSize(): boolean {
|
||||
return this.style.iosAccessibilityAdjustsFontSize;
|
||||
}
|
||||
set iosAccessibilityAdjustsFontSize(value: boolean) {
|
||||
this.style.iosAccessibilityAdjustsFontSize = value;
|
||||
}
|
||||
|
||||
get iosAccessibilityMinFontScale(): number {
|
||||
return this.style.iosAccessibilityMinFontScale;
|
||||
}
|
||||
set iosAccessibilityMinFontScale(value: number) {
|
||||
this.style.iosAccessibilityMinFontScale = value;
|
||||
}
|
||||
|
||||
get iosAccessibilityMaxFontScale(): number {
|
||||
return this.style.iosAccessibilityMaxFontScale;
|
||||
}
|
||||
set iosAccessibilityMaxFontScale(value: number) {
|
||||
this.style.iosAccessibilityMaxFontScale = value;
|
||||
}
|
||||
|
||||
get spans(): ObservableArray<Span> {
|
||||
if (!this._spans) {
|
||||
this._spans = new ObservableArray<Span>();
|
||||
@ -135,6 +156,12 @@ export class FormattedString extends ViewBase implements FormattedStringDefiniti
|
||||
style.on('textDecorationChange', this.onPropertyChange, this);
|
||||
style.on('colorChange', this.onPropertyChange, this);
|
||||
style.on('backgroundColorChange', this.onPropertyChange, this);
|
||||
|
||||
// These handlers will trigger font scale update
|
||||
style.on('iosAccessibilityAdjustsFontSizeChange', this.onPropertyChange, this);
|
||||
style.on('iosAccessibilityMinFontScaleChange', this.onPropertyChange, this);
|
||||
style.on('iosAccessibilityMaxFontScaleChange', this.onPropertyChange, this);
|
||||
style.on('fontScaleInternalChange', this.onPropertyChange, this);
|
||||
}
|
||||
|
||||
private removePropertyChangeHandler(span: Span) {
|
||||
@ -147,6 +174,11 @@ export class FormattedString extends ViewBase implements FormattedStringDefiniti
|
||||
style.off('textDecorationChange', this.onPropertyChange, this);
|
||||
style.off('colorChange', this.onPropertyChange, this);
|
||||
style.off('backgroundColorChange', this.onPropertyChange, this);
|
||||
|
||||
style.off('iosAccessibilityAdjustsFontSizeChange', this.onPropertyChange, this);
|
||||
style.off('iosAccessibilityMinFontScaleChange', this.onPropertyChange, this);
|
||||
style.off('iosAccessibilityMaxFontScaleChange', this.onPropertyChange, this);
|
||||
style.off('fontScaleInternalChange', this.onPropertyChange, this);
|
||||
}
|
||||
|
||||
private onPropertyChange(data: PropertyChangeData) {
|
||||
|
@ -194,28 +194,17 @@ export class TextBase extends TextBaseCommon {
|
||||
|
||||
[fontScaleInternalProperty.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);
|
||||
|
||||
let finalValue;
|
||||
if (this.iosAccessibilityAdjustsFontSize) {
|
||||
finalValue = value;
|
||||
|
||||
if (this.iosAccessibilityMinFontScale && this.iosAccessibilityMinFontScale > value) {
|
||||
finalValue = this.iosAccessibilityMinFontScale;
|
||||
}
|
||||
if (this.iosAccessibilityMaxFontScale && this.iosAccessibilityMaxFontScale < value) {
|
||||
finalValue = this.iosAccessibilityMaxFontScale;
|
||||
}
|
||||
} else {
|
||||
finalValue = 1.0;
|
||||
}
|
||||
|
||||
const newFont = currentFont.withFontScale(finalValue);
|
||||
this.style.fontInternal = newFont;
|
||||
const font = this.style.fontInternal || Font.default.withFontSize(nativeView.font.pointSize);
|
||||
const finalValue = adjustMinMaxFontScale(value, this);
|
||||
|
||||
// Request layout on font scale as it's not done automatically
|
||||
if (currentFont.fontScale !== finalValue) {
|
||||
if (font.fontScale !== finalValue) {
|
||||
this.style.fontInternal = font.withFontScale(finalValue);
|
||||
this.requestLayout();
|
||||
} else {
|
||||
if (!this.style.fontInternal) {
|
||||
this.style.fontInternal = font;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -360,7 +349,8 @@ export class TextBase extends TextBaseCommon {
|
||||
}
|
||||
|
||||
createMutableStringDetails(span: Span, text: string, index?: number): any {
|
||||
const font = new Font(span.style.fontFamily, span.style.fontSize, span.style.fontStyle, span.style.fontWeight);
|
||||
const fontScale = adjustMinMaxFontScale(span.style.fontScaleInternal, span);
|
||||
const font = new Font(span.style.fontFamily, span.style.fontSize, span.style.fontStyle, span.style.fontWeight, fontScale);
|
||||
const iosFont = font.getUIFont(this.nativeTextViewProtected.font);
|
||||
|
||||
const backgroundColor = <Color>(span.style.backgroundColor || (<FormattedString>span.parent).backgroundColor || (<TextBase>span.parent.parent).backgroundColor);
|
||||
@ -485,3 +475,20 @@ function isStringTappable(formattedString: FormattedString) {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function adjustMinMaxFontScale(value: number, view: TextBase | Span) {
|
||||
let finalValue;
|
||||
if (view.iosAccessibilityAdjustsFontSize) {
|
||||
finalValue = value;
|
||||
|
||||
if (view.iosAccessibilityMinFontScale && view.iosAccessibilityMinFontScale > value) {
|
||||
finalValue = view.iosAccessibilityMinFontScale;
|
||||
}
|
||||
if (view.iosAccessibilityMaxFontScale && view.iosAccessibilityMaxFontScale < value) {
|
||||
finalValue = view.iosAccessibilityMaxFontScale;
|
||||
}
|
||||
} else {
|
||||
finalValue = 1.0;
|
||||
}
|
||||
return finalValue;
|
||||
}
|
||||
|
21
packages/core/ui/text-base/span.d.ts
vendored
21
packages/core/ui/text-base/span.d.ts
vendored
@ -1,6 +1,6 @@
|
||||
import { Color } from '../../color';
|
||||
import { ViewBase } from '../core/view-base';
|
||||
import { FontStyle, FontWeight } from '../styling/font';
|
||||
import { FontStyleType, FontWeightType } from '../styling/font';
|
||||
import { CoreTypes } from '../../core-types';
|
||||
|
||||
/**
|
||||
@ -20,12 +20,12 @@ export class Span extends ViewBase {
|
||||
/**
|
||||
* Gets or sets the font style of the span.
|
||||
*/
|
||||
public fontStyle: FontStyle;
|
||||
public fontStyle: FontStyleType;
|
||||
|
||||
/**
|
||||
* Gets or sets the font weight of the span.
|
||||
*/
|
||||
public fontWeight: FontWeight;
|
||||
public fontWeight: FontWeightType;
|
||||
|
||||
/**
|
||||
* Gets or sets text decorations for the span.
|
||||
@ -42,6 +42,21 @@ export class Span extends ViewBase {
|
||||
*/
|
||||
public backgroundColor: Color;
|
||||
|
||||
/**
|
||||
* Defines whether accessibility font scale should affect font size.
|
||||
*/
|
||||
iosAccessibilityAdjustsFontSize: boolean;
|
||||
|
||||
/**
|
||||
* Gets or sets the minimum accessibility font scale.
|
||||
*/
|
||||
iosAccessibilityMinFontScale: number;
|
||||
|
||||
/**
|
||||
* Gets or sets the maximum accessibility font scale.
|
||||
*/
|
||||
iosAccessibilityMaxFontScale: number;
|
||||
|
||||
/**
|
||||
* Gets or sets the text for the span.
|
||||
*/
|
||||
|
@ -62,6 +62,27 @@ export class Span extends ViewBase implements SpanDefinition {
|
||||
this.style.backgroundColor = value;
|
||||
}
|
||||
|
||||
get iosAccessibilityAdjustsFontSize(): boolean {
|
||||
return this.style.iosAccessibilityAdjustsFontSize;
|
||||
}
|
||||
set iosAccessibilityAdjustsFontSize(value: boolean) {
|
||||
this.style.iosAccessibilityAdjustsFontSize = value;
|
||||
}
|
||||
|
||||
get iosAccessibilityMinFontScale(): number {
|
||||
return this.style.iosAccessibilityMinFontScale;
|
||||
}
|
||||
set iosAccessibilityMinFontScale(value: number) {
|
||||
this.style.iosAccessibilityMinFontScale = value;
|
||||
}
|
||||
|
||||
get iosAccessibilityMaxFontScale(): number {
|
||||
return this.style.iosAccessibilityMaxFontScale;
|
||||
}
|
||||
set iosAccessibilityMaxFontScale(value: number) {
|
||||
this.style.iosAccessibilityMaxFontScale = value;
|
||||
}
|
||||
|
||||
get text(): string {
|
||||
return this._text;
|
||||
}
|
||||
|
Reference in New Issue
Block a user