• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# 支持适老化
2<!--Kit: ArkUI-->
3<!--Subsystem: ArkUI-->
4<!--Owner: @liyi0309-->
5<!--Designer: @liyi0309-->
6<!--Tester: @fredyuan912-->
7<!--Adviser: @HelloCrease-->
8
9<!--RP1-->
10
11## 基本概念
12
13适老化提供了一种通过鼠标或手指长按的方法来放大所选区域或组件,即如果系统字体大小大于1倍,当用户使用鼠标或手指长按装配了适老化方法的组件,需要从所选区域的组件中提取数据,并放入另一个弹窗组件中展示。该方法的目的在于使组件和组件内部数据(子组件)放大,同时将整体组件在屏幕中央显示,让用户能够更好的观察该组件。
14
15## 使用约束
16
17* 适老化规则
18
19  由于在系统字体大于1倍时,组件并没有默认放大,需要通过配置[configuration标签](../quick-start/app-configuration-file.md#configuration标签),实现组件放大的适老化功能。
20
21* 适老化操作
22
23  在已经支持适老化能力的组件上长按组件,能够触发弹窗,当用户释放时,适老化操作结束。当设置系统字体大于1倍时,组件自动放大,当系统字体恢复至1倍时组件恢复正常状态。
24
25* 适老化对象
26
27  触发适老化操作并提供数据的组件。
28
29* 适老化弹窗目标
30
31  可接收并处理适老化数据的组件。
32
33* 弹窗限制
34
35  当用户将系统字体设置为2倍以上时,弹窗内容包括icon和文字的放大倍数固定为2倍。
36
37* 联合其他能力
38
39  适老化能力可以适配其他能力(如:滑动拖拽)。底部页签(tabBar)组件在触发适老化时,如果用户滑动手指或鼠标可以触发底部页签其他子组件的适老化功能。
40
41## 适配适老化的组件及触发方式
42
43| 触发方式             | 组件名称                                                     |
44| -------------------- | ------------------------------------------------------------ |
45| 长按组件触发         | [SideBarContainer](../reference/apis-arkui/arkui-ts/ts-container-sidebarcontainer.md), [底部页签(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-navdestination.md), [Tabs](../reference/apis-arkui/arkui-ts/ts-container-tabs.md) |
46| 设置系统字体默认放大 | [PickerDialog](arkts-fixes-style-dialog.md#选择器弹窗-pickerdialog), [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) |
47
48## 示例
49
50SideBarContainer组件通过长按控制按钮触发适老化弹窗。在系统字体为1倍的情况下,长按控制按钮不能弹窗。在系统字体大于1倍的情况下,长按控制按钮可以弹窗。
51
52```ts
53import { abilityManager, Configuration } from '@kit.AbilityKit';
54import { BusinessError } from '@kit.BasicServicesKit';
55
56@Entry
57@Component
58struct SideBarContainerExample {
59  @State currentFontSizeScale: number = 1
60  normalIcon: Resource = $r("app.media.icon") // icon仅作示例,请替换为实际使用的图片。
61  selectedIcon: Resource = $r("app.media.icon") // icon仅作示例,请替换为实际使用的图片。
62  @State arr: number[] = [1, 2, 3]
63  @State current: number = 1
64  @State title: string = 'Index01';
65  // 设置字体大小
66  async setFontScale(scale: number): Promise<void> {
67    let configInit: Configuration = {
68      language: 'zh-Ch',
69      fontSizeScale: scale,
70    };
71    // 更新配置-字体大小
72    abilityManager.updateConfiguration(configInit, (err: BusinessError) => {
73      if (err) {
74        console.error(`updateConfiguration fail, err: ${JSON.stringify(err)}`);
75      } else {
76        this.currentFontSizeScale = scale;
77        console.log('updateConfiguration success.');
78      }
79    });
80  }
81
82  build() {
83    SideBarContainer(SideBarContainerType.Embed) {
84      Column() {
85        ForEach(this.arr, (item: number) => {
86          Column({ space: 5 }) {
87            Image(this.current === item ? this.selectedIcon : this.normalIcon).width(64).height(64)
88            Text("0" + item)
89              .fontSize(25)
90              .fontColor(this.current === item ? '#0A59F7' : '#999')
91              .fontFamily('source-sans-pro,cursive,sans-serif')
92          }
93          .onClick(() => {
94            this.current = item;
95            this.title = "Index0" + item;
96          })
97        }, (item: string) => item)
98      }.width('100%')
99      .justifyContent(FlexAlign.SpaceEvenly)
100      .backgroundColor($r('sys.color.mask_fifth'))
101
102      Column() {
103        Text(this.title)
104        Button('1倍').onClick(() => {
105          this.setFontScale(1)
106        }).margin(10)
107        Button('1.75倍').onClick(() => {
108          this.setFontScale(1.75)
109        }).margin(10)
110        Button('2倍').onClick(() => {
111          this.setFontScale(2)
112        }).margin(10)
113        Button('3.2倍').onClick(() => {
114          this.setFontScale(3.2)
115        }).margin(10)
116      }
117      .margin({ top: 50, left: 20, right: 30 })
118    }
119    .controlButton({
120      icons: {
121        hidden: $r('sys.media.ohos_ic_public_drawer_open_filled'),
122        shown: $r('sys.media.ohos_ic_public_drawer_close')
123      }
124    })
125    .sideBarWidth(150)
126    .minSideBarWidth(50)
127    .maxSideBarWidth(300)
128    .minContentWidth(0)
129    .onChange((value: boolean) => {
130      console.info('status:' + value)
131    })
132    .divider({ strokeWidth: '1vp', color: Color.Gray, startMargin: '4vp', endMargin: '4vp' })
133  }
134}
135```
136
137切换系统字体前后长按已经支持适老化能力的组件,有如下效果:
138
139| 系统字体为一倍(适老化能力开启前) | 系统字体为1.75倍(适老化能力开启后) |
140| ---------------------------------- | ------------------------------------ |
141| ![](figures/aging_01.png)          | ![](figures/aging_02.png)            |
142
143[TextPickerDialog](../reference/apis-arkui/arkui-ts/ts-methods-textpicker-dialog.md)组件通过设置系统字体大小触发适老化弹窗。在系统字体为1倍的情况下,适老化不触发;在系统字体大于1倍的情况下,适老化触发。
144
145```ts
146import { abilityManager, Configuration } from '@kit.AbilityKit';
147import { BusinessError } from '@kit.BasicServicesKit';
148
149@Entry
150@Component
151struct TextPickerExample {
152  private select: number | number[] = 0;
153  private cascade: TextCascadePickerRangeContent[] = [
154    {
155      text: '辽宁省',
156      children: [{ text: '沈阳市', children: [{ text: '沈河区' }, { text: '和平区' }, { text: '浑南区' }] },
157        { text: '大连市', children: [{ text: '中山区' }, { text: '金州区' }, { text: '长海县' }] }]
158    },
159    {
160      text: '吉林省',
161      children: [{ text: '长春市', children: [{ text: '南关区' }, { text: '宽城区' }, { text: '朝阳区' }] },
162        { text: '四平市', children: [{ text: '铁西区' }, { text: '铁东区' }, { text: '梨树县' }] }]
163    },
164    {
165      text: '黑龙江省',
166      children: [{ text: '哈尔滨市', children: [{ text: '道里区' }, { text: '道外区' }, { text: '南岗区' }] },
167        { text: '牡丹江市', children: [{ text: '东安区' }, { text: '西安区' }, { text: '爱民区' }] }]
168    }
169  ]
170  @State v: string = '';
171  @State showTriggered: string = '';
172  private triggered: string = '';
173  private maxLines: number = 3;
174  // 设置字体大小
175  async setFontScale(scale: number): Promise<void> {
176    let configInit: Configuration = {
177      fontSizeScale: scale,
178    };
179
180    abilityManager.updateConfiguration(configInit, (err: BusinessError) => {
181      if (err) {
182        console.error(`updateConfiguration fail, err: ${JSON.stringify(err)}`);
183      } else {
184        console.log('updateConfiguration success.');
185      }
186    });
187  }
188
189  linesNum(max: number): void {
190    let items: string[] = this.triggered.split('\n').filter(item => item != '');
191    if (items.length > max) {
192      this.showTriggered = items.slice(-this.maxLines).join('\n');
193    } else {
194      this.showTriggered = this.triggered;
195    }
196  }
197
198  build() {
199    Column() {
200      Button("TextPickerDialog.show:" + this.v)
201        .onClick(() => {
202          this.getUIContext().showTextPickerDialog({
203            range: this.cascade,
204            selected: this.select,
205            onAccept: (value: TextPickerResult) => {
206              this.select = value.index
207              console.log(this.select + '')
208              this.v = value.value as string
209              console.info("TextPickerDialog:onAccept()" + JSON.stringify(value))
210              if (this.triggered != '') {
211                this.triggered += `\nonAccept(${JSON.stringify(value)})`;
212              } else {
213                this.triggered = `onAccept(${JSON.stringify(value)})`;
214              }
215              this.linesNum(this.maxLines);
216            },
217            onCancel: () => {
218              console.info("TextPickerDialog:onCancel()")
219              if (this.triggered != '') {
220                this.triggered += `\nonCancel()`;
221              } else {
222                this.triggered = `onCancel()`;
223              }
224              this.linesNum(this.maxLines);
225            },
226            onChange: (value: TextPickerResult) => {
227              console.info("TextPickerDialog:onChange()" + JSON.stringify(value))
228              if (this.triggered != '') {
229                this.triggered += `\nonChange(${JSON.stringify(value)})`;
230              } else {
231                this.triggered = `onChange(${JSON.stringify(value)})`;
232              }
233              this.linesNum(this.maxLines);
234            },
235          })
236        })
237        .margin({ top: 60 })
238
239      Row() {
240        Button('1倍').onClick(() => {
241          this.setFontScale(1)
242        }).margin(10)
243        Button('1.75倍').onClick(() => {
244          this.setFontScale(1.75)
245        }).margin(10)
246
247        Button('2倍').onClick(() => {
248          this.setFontScale(2)
249        }).margin(10)
250        Button('3.2倍').onClick(() => {
251          this.setFontScale(3.2)
252        }).margin(10)
253      }.margin({ top: 50 })
254    }
255
256  }
257}
258```
259
260| 系统字体为一倍(适老化能力开启前) | 系统字体为1.75倍(适老化能力开启后) |
261| ---------------------------------- | ------------------------------------ |
262| ![](figures/aging_03.png)          | ![](figures/aging_04.png)            |
263<!--RP1End-->