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 To ensure that components enlarge appropriately when the system font size is greater than 1x, you need to configure the [configuration tag](../quick-start/app-configuration-file.md#configuration) for implementing an aging-friendly feature. 12 13<!--RP1--><!--RP1End--> 14 15* Aging-friendly operations 16 17 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. 18 19* Aging-friendly objects 20 21 The components that trigger the aging-friendly operation and provide the data. 22 23* Aging-friendly dialog box targets 24 25 The components capable of receiving and processing the aging-friendly data. 26 27* Dialog box restrictions 28 29 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. 30 31* Combination with other capabilities 32 33 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. 34 35## Aging-Friendly Component Adaptation and Activation Methods 36 37| Activation Method | Component | 38| -------------------- | ------------------------------------------------------------ | 39| 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)| 40| Default system font enlargement| [PickerDialog](../reference/apis-arkui/arkui-ts/ts-methods-calendarpicker-dialog.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)| 41 42## Example 43 44<!--RP2--> 45This example uses the **SideBarContainer** component to trigger an aging-friendly dialog box through a long press of the control button. Note that the dialog box does not appear if the system font size is at the 1x setting. Instead, it appears only when the system font size is set to greater than 1x. 46 47```ts 48import { abilityManager, Configuration } from '@kit.AbilityKit'; 49import { BusinessError } from '@kit.BasicServicesKit'; 50 51@Entry 52@Component 53struct SideBarContainerExample { 54 @State currentFontSizeScale: number = 1 55 normalIcon: Resource = $r("app.media.icon") 56 selectedIcon: Resource = $r("app.media.icon") 57 @State arr: number[] = [1, 2, 3] 58 @State current: number = 1 59 @State title: string = 'Index01'; 60 // Set the font scale. 61 async setFontScale(scale: number): Promise<void> { 62 let configInit: Configuration = { 63 language: 'zh-Ch', 64 fontSizeScale: scale, 65 }; 66 // Update the font size. 67 abilityManager.updateConfiguration(configInit, (err: BusinessError) => { 68 if (err) { 69 console.error(`updateConfiguration fail, err: ${JSON.stringify(err)}`); 70 } else { 71 this.currentFontSizeScale = scale; 72 console.log('updateConfiguration success.'); 73 } 74 }); 75 } 76 77 build() { 78 SideBarContainer(SideBarContainerType.Embed) { 79 Column() { 80 ForEach(this.arr, (item: number) => { 81 Column({ space: 5 }) { 82 Image(this.current === item ? this.selectedIcon : this.normalIcon).width(64).height(64) 83 Text("0" + item) 84 .fontSize(25) 85 .fontColor(this.current === item ? '#0A59F7' : '#999') 86 .fontFamily('source-sans-pro,cursive,sans-serif') 87 } 88 .onClick(() => { 89 this.current = item; 90 this.title = "Index0" + item; 91 }) 92 }, (item: string) => item) 93 }.width('100%') 94 .justifyContent(FlexAlign.SpaceEvenly) 95 .backgroundColor($r('sys.color.mask_fifth')) 96 97 Column() { 98 Text(this.title) 99 Button('1x').onClick(() => { 100 this.setFontScale(1) 101 }).margin(10) 102 Button('1.75x').onClick(() => { 103 this.setFontScale(1.75) 104 }).margin(10) 105 Button('2x').onClick(() => { 106 this.setFontScale(2) 107 }).margin(10) 108 Button('3.2x').onClick(() => { 109 this.setFontScale(3.2) 110 }).margin(10) 111 } 112 .margin({ top: 50, left: 20, right: 30 }) 113 } 114 .controlButton({ 115 icons: { 116 hidden: $r('sys.media.ohos_ic_public_drawer_open_filled'), 117 shown: $r('sys.media.ohos_ic_public_drawer_close') 118 } 119 }) 120 .sideBarWidth(150) 121 .minSideBarWidth(50) 122 .maxSideBarWidth(300) 123 .minContentWidth(0) 124 .onChange((value: boolean) => { 125 console.info('status:' + value) 126 }) 127 .divider({ strokeWidth: '1vp', color: Color.Gray, startMargin: '4vp', endMargin: '4vp' }) 128 } 129} 130``` 131 132Switching system font sizes and long-pressing components with aging-friendly capabilities yields the effects as follows. 133 134| System Font at 1x (Before Aging-Friendly Features Are Enabled)| System Font at 1.75x (After Aging-Friendly Features Are Enabled)| 135| ---------------------------------- | ------------------------------------ | 136|  |  | 137 138The [TextPickerDialog](../reference/apis-arkui/arkui-ts/ts-methods-textpicker-dialog.md) 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. 139 140```ts 141import { abilityManager, Configuration } from '@kit.AbilityKit'; 142import { BusinessError } from '@kit.BasicServicesKit'; 143 144@Entry 145@Component 146struct TextPickerExample { 147 private select: number | number[] = 0; 148 private cascade: TextCascadePickerRangeContent[] = [ 149 { 150 text: 'Category 1', 151 children: [{ text: 'Subcategory 1', children: [{ text: 'Subcategory 2' }, { text: 'Subcategory 3' }, { text: 'Subcategory 4' }] }, 152 { text: 'Item 1', children: [{ text: 'Item 2' }, { text: 'Item 3' }, { text: 'Item 4' }] }] 153 }, 154 { 155 text: 'Category 2', 156 children: [{ text: 'Subcategory 1', children: [{ text: 'Subcategory 2' }, { text: 'Subcategory 3' }, { text: 'Subcategory 4' }] }, 157 { text: 'Item 1', children: [{ text: 'Item 2' }, { text: 'Item 3' }, { text: 'Item 4' }] }] 158 }, 159 { 160 text: 'Category 3', 161 children: [{ text: 'Subcategory 1', children: [{ text: 'Subcategory 2' }, { text: 'Subcategory 3' }, { text: 'Subcategory 4' }] }, 162 { text: 'Item 1', children: [{ text: 'Item 2' }, { text: 'Item 3' }, { text: 'Item 4' }] }] 163 } 164 ] 165 @State v: string = ''; 166 @State showTriggered: string = ''; 167 private triggered: string = ''; 168 private maxLines: number = 3; 169 // Set the font scale. 170 async setFontScale(scale: number): Promise<void> { 171 let configInit: Configuration = { 172 fontSizeScale: scale, 173 }; 174 175 abilityManager.updateConfiguration(configInit, (err: BusinessError) => { 176 if (err) { 177 console.error(`updateConfiguration fail, err: ${JSON.stringify(err)}`); 178 } else { 179 console.log('updateConfiguration success.'); 180 } 181 }); 182 } 183 184 linesNum(max: number): void { 185 let items: string[] = this.triggered.split('\n').filter(item => item != ''); 186 if (items.length > max) { 187 this.showTriggered = items.slice(-this.maxLines).join('\n'); 188 } else { 189 this.showTriggered = this.triggered; 190 } 191 } 192 193 build() { 194 Column() { 195 Button("TextPickerDialog.show:" + this.v) 196 .onClick(() => { 197 this.getUIContext().showTextPickerDialog({ 198 range: this.cascade, 199 selected: this.select, 200 onAccept: (value: TextPickerResult) => { 201 this.select = value.index 202 console.log(this.select + '') 203 this.v = value.value as string 204 console.info("TextPickerDialog:onAccept()" + JSON.stringify(value)) 205 if (this.triggered != '') { 206 this.triggered += `\nonAccept(${JSON.stringify(value)})`; 207 } else { 208 this.triggered = `onAccept(${JSON.stringify(value)})`; 209 } 210 this.linesNum(this.maxLines); 211 }, 212 onCancel: () => { 213 console.info("TextPickerDialog:onCancel()") 214 if (this.triggered != '') { 215 this.triggered += `\nonCancel()`; 216 } else { 217 this.triggered = `onCancel()`; 218 } 219 this.linesNum(this.maxLines); 220 }, 221 onChange: (value: TextPickerResult) => { 222 console.info("TextPickerDialog:onChange()" + JSON.stringify(value)) 223 if (this.triggered != '') { 224 this.triggered += `\nonChange(${JSON.stringify(value)})`; 225 } else { 226 this.triggered = `onChange(${JSON.stringify(value)})`; 227 } 228 this.linesNum(this.maxLines); 229 }, 230 }) 231 }) 232 .margin({ top: 60 }) 233 234 Row() { 235 Button('1x').onClick(() => { 236 this.setFontScale(1) 237 }).margin(10) 238 Button('1.75x').onClick(() => { 239 this.setFontScale(1.75) 240 }).margin(10) 241 242 Button('2x').onClick(() => { 243 this.setFontScale(2) 244 }).margin(10) 245 Button('3.2x').onClick(() => { 246 this.setFontScale(3.2) 247 }).margin(10) 248 }.margin({ top: 50 }) 249 } 250 251 } 252} 253``` 254 255| System Font at 1x (Before Aging-Friendly Features Are Enabled)| System Font at 1.75x (After Aging-Friendly Features Are Enabled)| 256| ---------------------------------- | ------------------------------------ | 257|  |  | 258<!--RP2End--> 259