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