• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# 动态属性设置
2
3动态设置组件的属性,支持开发者在属性设置时使用if/else语法,且根据需要使用多态样式设置属性。
4
5>  **说明:**
6>
7>  从API Version 11开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。
8>
9> 在attributeModifier中设置的属性尽量不要与其他方法设置的属性相同,避免在页面刷新时attributeModifier不生效。
10>
11> attributeModifier不支持自定义组件。
12
13## attributeModifier
14
15attributeModifier(modifier:&nbsp;AttributeModifier\<T>)
16
17动态设置组件的属性方法。
18
19**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。
20
21**系统能力:** SystemCapability.ArkUI.ArkUI.Full
22
23**参数:**
24
25| 参数名   | 类型                                         | 必填 | 说明                                                                                                                             |
26| -------- | -------------------------------------------- | ---- | -------------------------------------------------------------------------------------------------------------------------------- |
27| modifier | [AttributeModifier\<T>](#attributemodifiert) | 是   | 在当前组件上,动态设置属性方法,支持使用if/else语法。<br/>modifier: 属性修改器,开发者需要自定义class实现AttributeModifier接口。 |
28
29## AttributeModifier\<T>
30
31开发者需要自定义class实现AttributeModifier接口。
32
33**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。
34
35**系统能力:** SystemCapability.ArkUI.ArkUI.Full
36
37>  **说明:**
38>
39>  在以下回调函数中,当对instance对象的同一个属性重复设置相同的值或对象时,不会触发该属性的更新。
40
41### applyNormalAttribute
42applyNormalAttribute(instance: T) : void
43
44组件普通状态时的样式。
45
46**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。
47
48**系统能力:** SystemCapability.ArkUI.ArkUI.Full
49
50### applyPressedAttribute
51applyPressedAttribute(instance: T) : void
52
53组件按压状态的样式。
54
55**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。
56
57**系统能力:** SystemCapability.ArkUI.ArkUI.Full
58
59### applyFocusedAttribute
60applyFocusedAttribute(instance: T) : void
61
62组件获焦状态的样式。
63
64**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。
65
66**系统能力:** SystemCapability.ArkUI.ArkUI.Full
67
68### applyDisabledAttribute
69applyDisabledAttribute(instance: T) : void
70
71组件禁用状态的样式。
72
73**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。
74
75**系统能力:** SystemCapability.ArkUI.ArkUI.Full
76
77### applySelectedAttribute
78applySelectedAttribute(instance: T) : void
79
80组件选中状态的样式。
81
82开发者可根据需要自定义实现这些方法,通过传入的参数识别组件类型,对instance设置属性,支持使用if/else语法进行动态设置。
83
84**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。
85
86**系统能力:** SystemCapability.ArkUI.ArkUI.Full
87
88**参数**:
89
90| 参数     | 描述                                                                                                         |
91| -------- | ------------------------------------------------------------------------------------------------------------ |
92| instance | 组件的属性类,用来标识进行属性设置的组件的类型,比如Button组件的ButtonAttribute,Text组件的TextAttribute等。 |
93
94**instance参数支持范围:**
95
96AlphabetIndexerAttribute、BadgeAttribute、BlankAttribute、ButtonAttribute、CalendarPickerAttribute、CanvasAttribute、CheckboxAttribute、CheckboxGroupAttribute、CircleAttribute、ColumnAttribute、ColumnSplitAttribute、ShapeAttribute、CommonAttribute、CounterAttribute、DataPanelAttribute、DatePickerAttribute、DividerAttribute、EllipseAttribute、FlexAttribute、FlowItemAttribute、FormLinkAttribute、GaugeAttribute、GridAttribute、GridColAttribute、ColumnAttribute、GridItemAttribute、GridRowAttribute、HyperlinkAttribute、ImageAttribute、ImageAnimatorAttribute、ImageSpanAttribute、LineAttribute、ListAttribute、ListItemAttribute、ListItemGroupAttribute、LoadingProgressAttribute、MarqueeAttribute、MenuAttribute、MenuItemAttribute、MenuItemGroupAttribute、NavDestinationAttribute、NavigationAttribute、NavigatorAttribute、NavRouterAttribute、PanelAttribute、PathAttribute、PatternLockAttribute、PolygonAttribute、PolylineAttribute、ProgressAttribute、QRCodeAttribute、RadioAttribute、RatingAttribute、RectAttribute、RefreshAttribute、RelativeContainerAttribute、RichEditorAttribute、RichTextAttribute、RowAttribute、RowSplitAttribute、ScrollAttribute、ScrollBarAttribute、SearchAttribute、SelectAttribute、ShapeAttribute、SideBarContainerAttribute、SliderAttribute、SpanAttribute、StackAttribute、StepperAttribute、StepperItemAttribute、SwiperAttribute、SymbolGlyphAttribute、TabContentAttribute、TabsAttribute、TextAttribute、TextAreaAttribute、TextClockAttribute、TextInputAttribute、TextPickerAttribute、TextTimerAttribute、TimePickerAttribute、ToggleAttribute、VideoAttribute、WaterFlowAttribute、XComponentAttribute、ParticleAttribute<!--Del-->、EffectComponentAttribute、FormComponentAttribute、PluginComponentAttribute、RemoteWindowAttribute、UIExtensionComponentAttribute<!--DelEnd-->。
97
98**属性支持范围:**
99
1001. 不支持入参或者返回值为[CustomBuilder](ts-types.md#custombuilder8)的属性。
1012. 不支持入参为[modifier](../../../ui/arkts-user-defined-modifier.md)类型的属性,具体为以下属性方法:[attributeModifier](#attributemodifier),[drawModifier](./ts-universal-attributes-draw-modifier.md)和[gestureModifier](./ts-universal-attributes-gesture-modifier.md)。
1023. 不支持[animation](./ts-animatorproperty.md)属性。
1034. 不支持[gesture](../../../ui/arkts-gesture-events-binding.md)类型的属性。
1045. 不支持[stateStyles](./ts-universal-attributes-polymorphic-style.md)属性。
1056. 不支持已废弃属性。
106<!--Del-->
1077. 不支持系统组件属性。<!--DelEnd-->
108
109不支持或者未实现的属性在使用时会抛出"Method not implemented."、"is not callable"、"Builder is not supported."等异常信息。具体Modifier支持范围同基类属性接口的支持范围,详见表格[Attribute支持范围](#attribute支持范围)。
110
111## 自定义Modifier
112从API version 12开始,开发者可使用自定义Modifier构建组件并配置属性,通过此自定义的Modifier可调用所封装组件的属性和样式接口。
113
114**自定义Modifier支持范围:**
115
116CommonModifier、ColumnModifier、ColumnSplitModifier、RowModifier、RowSplitModifier、SideBarContainerModifier、BlankModifier、DividerModifier、GridColModifier、GridRowModifier、NavDestinationModifier、NavigatorModifier、StackModifier、NavigationModifier、NavRouterModifier、StepperItemModifier、TabsModifier、GridModifier、GridItemModifier、ListModifier、ListItemModifier、ListItemGroupModifier、ScrollModifier、SwiperModifier、WaterFlowModifier、ButtonModifier、CounterModifier、TextPickerModifier、TimePickerModifier、ToggleModifier、CalendarPickerModifier、CheckboxModifier、CheckboxGroupModifier、DatePickerModifier、RadioModifier、RatingModifier、SelectModifier、SliderModifier、PatternLockModifier、SpanModifier、RichEditorModifier、RefreshModifier、SearchModifier、TextAreaModifier、TextModifier、TextInputModifier、ImageSpanModifier、ImageAnimatorModifier、ImageModifier、VideoModifier、DataPanelModifier、GaugeModifier、LoadingProgressModifier、MarqueeModifier、ProgressModifier、QRCodeModifier、TextClockModifier、TextTimerModifier、LineModifier、PathModifier、PolygonModifier、PolylineModifier、RectModifier、ShapeModifier、AlphabetIndexerModifier、FormComponentModifier、HyperlinkModifier、MenuModifier、MenuItemModifier、PanelModifier、SymbolGlyphModifier、ParticleModifier。
117未暴露的组件Modifier可以使用CommonModifier。
118
119**注意事项**
1201. 设置自定义Modifier给一个组件,该组件对应属性生效。
1212. 自定义Modifier属性值变化,组件对应属性也会变化。自定义Modifier类型为基类,构造的对象为子类对象,使用时要通过as进行类型断言为子类。
1223. 一个自定义Modifier设置给两个组件,Modifier属性变化的时候对两个组件同时生效。
1234. 一个Modifier设置了属性A和属性B,再设置属性C和属性D,4个属性同时在组件上生效。
1245. 自定义Modifier不支持@State标注的状态数据的变化感知,见示例2。
1256. 多次通过attributeModifier设置属性时,生效的属性为所有属性的并集,相同属性按照设置顺序生效。
126
127## 示例
128### 示例1(组件绑定Modifier切换背景颜色)
129
130该示例通过Button绑定Modifier实现了点击切换背景颜色的效果。
131
132```ts
133// xxx.ets
134class MyButtonModifier implements AttributeModifier<ButtonAttribute> {
135  isDark: boolean = false
136
137  applyNormalAttribute(instance: ButtonAttribute): void {
138    if (this.isDark) {
139      instance.backgroundColor(Color.Black)
140    } else {
141      instance.backgroundColor(Color.Red)
142    }
143  }
144}
145
146@Entry
147@Component
148struct attributeDemo {
149  @State modifier: MyButtonModifier = new MyButtonModifier()
150
151  build() {
152    Row() {
153      Column() {
154        Button("Button")
155          .attributeModifier(this.modifier)
156          .onClick(() => {
157            this.modifier.isDark = !this.modifier.isDark
158          })
159      }
160      .width('100%')
161    }
162    .height('100%')
163  }
164}
165```
166![attributeModifier_ifelse](figures/attributeModifier_ifelse.gif)
167
168### 示例2(组件绑定Modifier实现按压态效果)
169
170该示例通过Button绑定Modifier实现了按压态的效果。如果配合状态管理V2使用,详情见:[Modifier与makeObserved](../../../ui/state-management/arkts-v1-v2-migration.md#modifier)。
171
172```ts
173// xxx.ets
174class MyButtonModifier implements AttributeModifier<ButtonAttribute> {
175  applyNormalAttribute(instance: ButtonAttribute): void {
176    instance.backgroundColor(Color.Black)
177  }
178
179  applyPressedAttribute(instance: ButtonAttribute): void {
180    instance.backgroundColor(Color.Red)
181  }
182}
183
184@Entry
185@Component
186struct attributePressedDemo {
187  @State modifier: MyButtonModifier = new MyButtonModifier()
188
189  build() {
190    Row() {
191      Column() {
192        Button("Button")
193          .attributeModifier(this.modifier)
194      }
195      .width('100%')
196    }
197    .height('100%')
198  }
199}
200```
201![attributeModifier_ifelse](figures/attributeModifier_ifelse.gif)
202
203### 示例3(自定义Modifier不支持感知@State装饰的状态数据变化)
204
205该示例通过状态数据设置自定义Modifier的宽度,自定义Modifier不支持感知@State装饰的状态数据变化,点击按钮后宽度不发生改变。
206
207```ts
208import { CommonModifier } from "@kit.ArkUI"
209
210const TEST_TAG : string = "AttributeModifier";
211class MyModifier extends CommonModifier {
212  applyNormalAttribute(instance: CommonAttribute): void {
213    super.applyNormalAttribute?.(instance);
214  }
215}
216
217@Component
218struct MyImage1 {
219  @Link modifier: CommonModifier
220
221  build() {
222    Image($r("app.media.startIcon")).attributeModifier(this.modifier as MyModifier)
223  }
224}
225
226@Entry
227@Component
228struct Index {
229  index: number = 0;
230  @State width1: number = 100;
231  @State height1: number = 100;
232  @State myModifier: CommonModifier = new MyModifier().width(this.width1).height(this.height1).margin(10)
233
234  build() {
235    Column() {
236      Button($r("app.string.EntryAbility_label"))
237        .margin(10)
238        .onClick(() => {
239          console.log(TEST_TAG, "onClick")
240          this.index++;
241          if (this.index % 2 === 1) {
242            this.width1 = 10;
243            console.log(TEST_TAG, "setGroup1")
244          } else {
245            this.width1 = 10;
246            console.log(TEST_TAG, "setGroup2")
247          }
248        })
249      MyImage1({ modifier: this.myModifier })
250    }
251    .width('100%')
252  }
253}
254```
255![attributeModifier2](figures/attributeModifier2.gif)
256
257### 示例4(Modifier和自定义Modifier的属性同时生效)
258
259该示例通过自定义Modifier设置了width和height,点击按钮时设置borderStyle和borderWidth,点击后4个属性同时生效。
260
261```ts
262import { CommonModifier } from "@kit.ArkUI"
263
264const TEST_TAG: string = "AttributeModifier";
265
266class MyModifier extends CommonModifier {
267  applyNormalAttribute(instance: CommonAttribute): void {
268    super.applyNormalAttribute?.(instance);
269  }
270
271  public setGroup1(): void {
272    this.borderStyle(BorderStyle.Dotted)
273    this.borderWidth(8)
274  }
275
276  public setGroup2(): void {
277    this.borderStyle(BorderStyle.Dashed)
278    this.borderWidth(8)
279  }
280}
281
282@Component
283struct MyImage1 {
284  @Link modifier: CommonModifier
285
286  build() {
287    Image($r("app.media.startIcon")).attributeModifier(this.modifier as MyModifier)
288  }
289}
290
291@Entry
292@Component
293struct Index {
294  @State myModifier: CommonModifier = new MyModifier().width(100).height(100).margin(10)
295  index: number = 0;
296
297  build() {
298    Column() {
299      Button($r("app.string.EntryAbility_label"))
300        .margin(10)
301        .onClick(() => {
302          console.log(TEST_TAG, "onClick")
303          this.index++;
304          if (this.index % 2 === 1) {
305            (this.myModifier as MyModifier).setGroup1()
306            console.log(TEST_TAG, "setGroup1")
307          } else {
308            (this.myModifier as MyModifier).setGroup2()
309            console.log(TEST_TAG, "setGroup2")
310          }
311        })
312      MyImage1({ modifier: this.myModifier })
313    }
314    .width('100%')
315  }
316}
317```
318![attributeModifier](figures/attributeModifier.gif)
319
320### 示例5(组件绑定Modifier获焦样式)
321
322该示例通过 Button 绑定 Modifier 实现了组件在获得焦点时的样式效果。点击 Button2 后,Button 会显示获得焦点后的样式。
323
324```ts
325class MyButtonModifier implements AttributeModifier<ButtonAttribute> {
326
327  applyNormalAttribute(instance: ButtonAttribute): void {
328    instance.backgroundColor(Color.Blue)
329  }
330  applyFocusedAttribute(instance: ButtonAttribute): void {
331    instance.backgroundColor(Color.Green)
332  }
333}
334
335@Entry
336@Component
337struct attributeDemo {
338  @State modifier: MyButtonModifier = new MyButtonModifier()
339  @State isDisable: boolean = true;
340
341  build() {
342    Row() {
343      Column() {
344        Button("Button")
345          .attributeModifier(this.modifier)
346          .enabled(this.isDisable)
347          .id("app")
348        Divider().vertical(false).strokeWidth(15).color(Color.Transparent)
349        Button("Button2")
350          .onClick(() => {
351            this.getUIContext().getFocusController().activate(true)
352            this.getUIContext().getFocusController().requestFocus("app")
353          })
354      }
355      .width('100%')
356    }
357    .height('100%')
358  }
359}
360```
361![applyFocusedAttribute](figures/applyFocusedAttribute.gif)
362
363### 示例6(组件绑定Modifier禁用状态的样式)
364
365该示例通过 Button 绑定 Modifier 实现了组件禁用时的样式效果。点击 Button2 后,Button 会显示禁用状态的样式。
366
367```ts
368class MyButtonModifier implements AttributeModifier<ButtonAttribute> {
369  applyDisabledAttribute(instance: ButtonAttribute): void {
370    instance.width(200)
371  }
372}
373
374@Entry
375@Component
376struct attributeDemo {
377  @State modifier: MyButtonModifier = new MyButtonModifier()
378  @State isDisable: boolean = true
379
380  build() {
381    Row() {
382      Column() {
383        Button("Button")
384          .attributeModifier(this.modifier)
385          .enabled(this.isDisable)
386        Divider().vertical(false).strokeWidth(15).color(Color.Transparent)
387        Button("Button2")
388          .onClick(() => {
389            this.isDisable = !this.isDisable
390          })
391      }
392      .width('100%')
393    }
394    .height('100%')
395  }
396}
397```
398![applyDisabledAttribute](figures/applyDisabledAttribute.gif)
399
400### 示例7(组件绑定Modifier选中状态样式)
401
402该示例通过Radio绑定Modifier实现了展示组件选中时样式的效果。
403
404```ts
405class MyRadioModifier implements AttributeModifier<RadioAttribute> {
406  applyNormalAttribute(instance: RadioAttribute): void {
407    instance.backgroundColor(Color.Blue)
408  }
409  applySelectedAttribute(instance: RadioAttribute): void {
410    instance.backgroundColor(Color.Red)
411    instance.borderWidth(2)
412  }
413}
414
415@Entry
416@Component
417struct attributeDemo {
418  @State modifier: MyRadioModifier = new MyRadioModifier()
419  @State value: boolean = false
420  @State value2: boolean = false
421
422  build() {
423    Row() {
424      Column() {
425        Radio({ value: 'Radio1', group: 'radioGroup1' })
426          .checked(this.value)
427          .height(50)
428          .width(50)
429          .borderWidth(0)
430          .borderRadius(30)
431          .onClick(() => {
432            this.value = !this.value
433          })
434          .attributeModifier(this.modifier)
435      }
436      .width('100%')
437    }
438    .height('100%')
439  }
440}
441```
442![applySelectedAttribute](figures/applySelectedAttribute.gif)
443
444## Attribute支持范围
445
446未在表格中列举的属性默认为支持。
447
448**表1** CommonAttribute属性接口支持例外范围
449
450| 属性                     | 支持情况 | 告警信息                  | 备注                                      |
451| ------------------------ | -------- | ------------------------- | ----------------------------------------- |
452| accessibilityChecked     | 不支持   | is not callable           | -                                         |
453| accessibilitySelected    | 不支持   | is not callable           | -                                         |
454| accessibilityTextHint    | 不支持   | is not callable           | -                                         |
455| accessibilityVirtualNode | 不支持   | is not callable           | 不支持入参为CustomBuilder。               |
456| animation                | 不支持   | Method not implemented.   | 不支持animation相关属性。                 |
457| attributeModifier        | 不支持   | -                         | attributeModifier不支持嵌套使用,不生效。 |
458| background               | 不支持   | Method not implemented.   | 不支持入参为CustomBuilder。               |
459| backgroundFilter         | 不支持   | is not callable           | -                                         |
460| bindContentCover         | 不支持   | Method not implemented.   | 不支持入参为CustomBuilder。               |
461| bindContextMenu          | 不支持   | Method not implemented.   | 不支持入参为CustomBuilder。               |
462| bindPopup                | 不支持   | Method not implemented.   | 不支持入参为CustomBuilder。               |
463| bindSheet                | 不支持   | Method not implemented.   | 不支持入参为CustomBuilder。               |
464| chainWeight              | 不支持   | is not callable           | -                                         |
465| compositingFilter        | 不支持   | is not callable           | -                                         |
466| drawModifier             | 不支持   | is not callable           | 不支持modifier相关的属性。                |
467| foregroundFilter         | 不支持   | is not callable           | -                                         |
468| freeze                   | 不支持   | is not callable           | -                                         |
469| gesture                  | 不支持   | Method not implemented.   | 不支持gesture相关的属性。                 |
470| gestureModifier          | 不支持   | is not callable           | 不支持modifier相关的属性。                |
471| onAccessibilityHover     | 不支持   | is not callable           | -                                         |
472| onChildTouchTest         | 不支持   | is not callable           | -                                         |
473| onDragStart              | 不支持   | Method not implemented.   | 不支持返回值为CustomBuilder。             |
474| onPreDrag                | 不支持   | Method not implemented.   | -                                         |
475| onTouchIntercept         | 不支持   | is not callable           | -                                         |
476| onVisibleAreaChange      | 不支持   | Method not implemented.   | -                                         |
477| parallelGesture          | 不支持   | Method not implemented.   | 不支持gesture相关的属性。                 |
478| priorityGesture          | 不支持   | Method not implemented.   | 不支持gesture相关的属性。                 |
479| reuseId                  | 不支持   | Method not implemented.   | -                                         |
480| stateStyles              | 不支持   | Method not implemented.   | 不支持stateStyles相关的属性。             |
481| useSizeType              | 不支持   | Method not implemented.   | 不支持已废弃属性。                        |
482| visualEffect             | 不支持   | is not callable           | -                                         |
483| bindMenu                 | 部分支持 | -                         | 不支持入参为CustomBuilder。               |
484| dragPreview              | 部分支持 | Builder is not supported. | 不支持入参为CustomBuilder。               |
485