1# Supporting Aging-Friendly Design 2 3## Basic Concepts 4 5Aging-friendly design offers a method to enlarge selected areas or components through a long-press action with a mouse or finger. Specifically, when the system font is larger than 1x, this action on a component with aging-friendly features extracts data from the component within the selected area and presents it in a dialog box. This way, both the component and its internal data (child components) are enlarged, and the entire component is centered on the screen for better visibility. 6 7## Constraints 8 9* Aging-friendly rules 10 11 Since components do not automatically enlarge when the system font size is greater than 1x, the aging-friendly feature is necessary to magnify the components. 12 13* Aging-friendly operations 14 15 Long-pressing a component that supports aging-friendly capabilities triggers a dialog box. The aging-friendly operation ends when the user releases the press. When the system font size is set to be greater than 1x, the component automatically enlarges, and when the system font size returns to 1x, the component returns to its normal state. 16 17* Aging-friendly objects 18 19 The components that trigger the aging-friendly operation and provide the data. 20 21* Aging-friendly dialog box targets 22 23 The components capable of receiving and processing the aging-friendly data. 24 25* Dialog box restrictions 26 27 When users set the system font to more than 2x, the dialog box content, including icons and text, is magnified at a fixed 2x scale. 28 29* Combination with other capabilities 30 31 Aging-friendly capabilities can be integrated with other features (such as swipe and drag). When the bottom tab bar (**tabBar**) component is activated for aging-friendly features, users can swipe their fingers or use a mouse to trigger aging-friendly features for other child components within the tab bar. 32 33## Aging-Friendly Component Adaptation and Activation Methods 34 35| Activation Method | Component | 36| -------------------- | ------------------------------------------------------------ | 37| Long press on the component | [SideBarContainer](../reference/apis-arkui/arkui-ts/ts-container-sidebarcontainer.md), [Bottom Tab Bar (tabBar)](../reference/apis-arkui/arkui-ts/ts-container-tabcontent.md#tabbar9), [Navigation](../reference/apis-arkui/arkui-ts/ts-basic-components-navigation.md), [NavDestination](../reference/apis-arkui/arkui-ts/ts-basic-components-navigation.md#navdestination10), [Tabs](../reference/apis-arkui/arkui-ts/ts-container-tabs.md)| 38| Default system font enlargement| [Picker](../reference/apis-arkui/arkui-ts/ts-basic-components-datepicker.md), [Button](../reference/apis-arkui/arkui-ts/ts-basic-components-button.md), [Menu](../reference/apis-arkui/arkui-ts/ts-basic-components-menu.md), [Stepper](../reference/apis-arkui/arkui-ts/ts-basic-components-stepper.md), [BindSheet](../reference/apis-arkui/arkui-ts/ts-universal-attributes-sheet-transition.md#bindsheet), [TextInput](../reference/apis-arkui/arkui-ts/ts-basic-components-textinput.md)/[TextArea](../reference/apis-arkui/arkui-ts/ts-basic-components-textarea.md)/[Search](../reference/apis-arkui/arkui-ts/ts-basic-components-search.md)/[SelectionMenu](../reference/apis-arkui/arkui-ts/ohos-arkui-advanced-SelectionMenu.md), [Chip](../reference/apis-arkui/arkui-ts/ohos-arkui-advanced-Chip.md#chip), [Dialog](../reference/apis-arkui/arkui-ts/ohos-arkui-advanced-Dialog.md), [Slider](../reference/apis-arkui/arkui-ts/ts-basic-components-slider.md), [Progress](../reference/apis-arkui/arkui-ts/ts-basic-components-progress.md), [Badge](../reference/apis-arkui/arkui-ts/ts-container-badge.md)| 39 40## Example 41 42This example involves the **SideBarContainer** component, which triggers an aging-friendly dialog box when the control button is long-pressed. The dialog box does not appear if the system font size is at the default 1x setting; it appears only when the system font size is set to greater than 1x. 43 44```ts 45import { abilityManager, Configuration } from '@kit.AbilityKit'; 46import { BusinessError } from '@kit.BasicServicesKit'; 47 48@Entry 49@Component 50struct SideBarContainerExample { 51 @State currentFontSizeScale: number = 1 52 normalIcon: Resource = $r("app.media.icon") 53 selectedIcon: Resource = $r("app.media.icon") 54 @State arr: number[] = [1, 2, 3] 55 @State current: number = 1 56 @State title: string = 'Index01'; 57 // Set the font scale. 58 async setFontScale(scale: number): Promise<void> { 59 let configInit: Configuration = { 60 language: 'zh-Ch', 61 fontSizeScale: scale, 62 }; 63 // Update the font size. 64 abilityManager.updateConfiguration(configInit, (err: BusinessError) => { 65 if (err) { 66 console.error(`updateConfiguration fail, err: ${JSON.stringify(err)}`); 67 } else { 68 this.currentFontSizeScale = scale; 69 console.log('updateConfiguration success.'); 70 } 71 }); 72 } 73 74 build() { 75 SideBarContainer(SideBarContainerType.Embed) { 76 Column() { 77 ForEach(this.arr, (item: number) => { 78 Column({ space: 5 }) { 79 Image(this.current === item ? this.selectedIcon : this.normalIcon).width(64).height(64) 80 Text("0" + item) 81 .fontSize(25) 82 .fontColor(this.current === item ? '#0A59F7' : '#999') 83 .fontFamily('source-sans-pro,cursive,sans-serif') 84 } 85 .onClick(() => { 86 this.current = item; 87 this.title = "Index0" + item; 88 }) 89 }, (item: string) => item) 90 }.width('100%') 91 .justifyContent(FlexAlign.SpaceEvenly) 92 .backgroundColor($r('sys.color.mask_fifth')) 93 94 Column() { 95 Text(this.title) 96 Button('1x').onClick(() => { 97 this.setFontScale(1) 98 }).margin(10) 99 Button('1.75x').onClick(() => { 100 this.setFontScale(1.75) 101 }).margin(10) 102 Button('2x').onClick(() => { 103 this.setFontScale(2) 104 }).margin(10) 105 Button('3.2x').onClick(() => { 106 this.setFontScale(3.2) 107 }).margin(10) 108 } 109 .margin({ top: 50, left: 20, right: 30 }) 110 } 111 .controlButton({ 112 icons: { 113 hidden: $r('sys.media.ohos_ic_public_drawer_open_filled'), 114 shown: $r('sys.media.ohos_ic_public_drawer_close') 115 } 116 }) 117 .sideBarWidth(150) 118 .minSideBarWidth(50) 119 .maxSideBarWidth(300) 120 .minContentWidth(0) 121 .onChange((value: boolean) => { 122 console.info('status:' + value) 123 }) 124 .divider({ strokeWidth: '1vp', color: Color.Gray, startMargin: '4vp', endMargin: '4vp' }) 125 } 126} 127``` 128 129Switching system font sizes and long-pressing components with aging-friendly capabilities yields the effects as follows. 130 131| System Font at 1x (Before Aging-Friendly Features Are Enabled)| System Font at 1.75x (After Aging-Friendly Features Are Enabled)| 132| ---------------------------------- | ------------------------------------ | 133|  |  | 134 135The **TextPickerDialog** component triggers an aging-friendly dialog box when the system font is set to greater than 1x, which does not occur at the default 1x setting. 136 137```ts 138import { abilityManager, Configuration } from '@kit.AbilityKit'; 139import { BusinessError } from '@kit.BasicServicesKit'; 140 141@Entry 142@Component 143struct TextPickerExample { 144 private select: number | number[] = 0; 145 private cascade: TextCascadePickerRangeContent[] = [ 146 { 147 text: 'Category 1', 148 children: [{ text: 'Subcategory 1', children: [{ text: 'Subcategory 2' }, { text: 'Subcategory 3' }, { text: 'Subcategory 4' }] }, 149 { text: 'Item 1', children: [{ text: 'Item 2' }, { text: 'Item 3' }, { text: 'Item 4' }] }] 150 }, 151 { 152 text: 'Category 2', 153 children: [{ text: 'Subcategory 1', children: [{ text: 'Subcategory 2' }, { text: 'Subcategory 3' }, { text: 'Subcategory 4' }] }, 154 { text: 'Item 1', children: [{ text: 'Item 2' }, { text: 'Item 3' }, { text: 'Item 4' }] }] 155 }, 156 { 157 text: 'Category 3', 158 children: [{ text: 'Subcategory 1', children: [{ text: 'Subcategory 2' }, { text: 'Subcategory 3' }, { text: 'Subcategory 4' }] }, 159 { text: 'Item 1', children: [{ text: 'Item 2' }, { text: 'Item 3' }, { text: 'Item 4' }] }] 160 } 161 ] 162 @State v: string = ''; 163 @State showTriggered: string = ''; 164 private triggered: string = ''; 165 private maxLines: number = 3; 166 // Set the font scale. 167 async setFontScale(scale: number): Promise<void> { 168 let configInit: Configuration = { 169 fontSizeScale: scale, 170 }; 171 172 abilityManager.updateConfiguration(configInit, (err: BusinessError) => { 173 if (err) { 174 console.error(`updateConfiguration fail, err: ${JSON.stringify(err)}`); 175 } else { 176 console.log('updateConfiguration success.'); 177 } 178 }); 179 } 180 181 linesNum(max: number): void { 182 let items: string[] = this.triggered.split('\n').filter(item => item != ''); 183 if (items.length > max) { 184 this.showTriggered = items.slice(-this.maxLines).join('\n'); 185 } else { 186 this.showTriggered = this.triggered; 187 } 188 } 189 190 build() { 191 Column() { 192 Button("TextPickerDialog.show:" + this.v) 193 .onClick(() => { 194 this.getUIContext().showTextPickerDialog({ 195 range: this.cascade, 196 selected: this.select, 197 onAccept: (value: TextPickerResult) => { 198 this.select = value.index 199 console.log(this.select + '') 200 this.v = value.value as string 201 console.info("TextPickerDialog:onAccept()" + JSON.stringify(value)) 202 if (this.triggered != '') { 203 this.triggered += `\nonAccept(${JSON.stringify(value)})`; 204 } else { 205 this.triggered = `onAccept(${JSON.stringify(value)})`; 206 } 207 this.linesNum(this.maxLines); 208 }, 209 onCancel: () => { 210 console.info("TextPickerDialog:onCancel()") 211 if (this.triggered != '') { 212 this.triggered += `\nonCancel()`; 213 } else { 214 this.triggered = `onCancel()`; 215 } 216 this.linesNum(this.maxLines); 217 }, 218 onChange: (value: TextPickerResult) => { 219 console.info("TextPickerDialog:onChange()" + JSON.stringify(value)) 220 if (this.triggered != '') { 221 this.triggered += `\nonChange(${JSON.stringify(value)})`; 222 } else { 223 this.triggered = `onChange(${JSON.stringify(value)})`; 224 } 225 this.linesNum(this.maxLines); 226 }, 227 }) 228 }) 229 .margin({ top: 60 }) 230 231 Row() { 232 Button('1x').onClick(() => { 233 this.setFontScale(1) 234 }).margin(10) 235 Button('1.75x').onClick(() => { 236 this.setFontScale(1.75) 237 }).margin(10) 238 239 Button('2x').onClick(() => { 240 this.setFontScale(2) 241 }).margin(10) 242 Button('3.2x').onClick(() => { 243 this.setFontScale(3.2) 244 }).margin(10) 245 }.margin({ top: 50 }) 246 } 247 248 } 249} 250``` 251 252| System Font at 1x (Before Aging-Friendly Features Are Enabled)| System Font at 1.75x (After Aging-Friendly Features Are Enabled)| 253| ---------------------------------- | ------------------------------------ | 254|  |  | 255