• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# 动态属性设置
2<!--Kit: ArkUI-->
3<!--Subsystem: ArkUI-->
4<!--Owner: @jiangtao92-->
5<!--Designer: @piggyguy-->
6<!--Tester: @songyanhong-->
7<!--Adviser: @HelloCrease-->
8
9动态设置组件的属性,支持开发者在属性设置时使用if/else语法,且根据需要使用多态样式设置属性。
10
11> **说明:**
12>
13> 从API version 11开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。
14>
15> 在attributeModifier中设置的属性尽量不要与其他方法设置的属性相同,避免在页面刷新时attributeModifier不生效。
16>
17> 对于仅需根据条件设置组件单一属性的简单场景,可以使用[三目表达式](../../../ui/state-management/arkts-declarative-ui-description.md#配置属性)(如.width(isFullScreen ? 200 : 100))。
18>
19> 从API version 20开始,attributeModifier支持自定义组件。
20
21## attributeModifier
22
23attributeModifier(modifier: AttributeModifier\<T>): T
24
25动态设置组件的属性方法。
26
27**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。
28
29**系统能力:** SystemCapability.ArkUI.ArkUI.Full
30
31**参数:**
32
33| 参数名   | 类型                                         | 必填 | 说明                                                                                                                             |
34| -------- | -------------------------------------------- | ---- | -------------------------------------------------------------------------------------------------------------------------------- |
35| modifier | [AttributeModifier\<T>](#attributemodifiert) | 是   | 在当前组件上,动态设置属性方法,支持使用if/else语法。<br/>modifier:属性修改器,开发者需要自定义class实现AttributeModifier接口。 |
36
37**返回值:**
38
39| 类型 | 说明 |
40| --- | --- |
41| T | 返回当前组件。 |
42
43## AttributeModifier\<T>
44
45开发者需要自定义class实现AttributeModifier接口。
46
47**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。
48
49**系统能力:** SystemCapability.ArkUI.ArkUI.Full
50
51>  **说明:**
52>
53>  在以下回调函数中,当对instance对象的同一个属性重复设置相同的值或对象时,不会触发该属性的更新。
54
55### applyNormalAttribute
56applyNormalAttribute?(instance: T) : void
57
58组件普通状态时的样式。
59
60**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。
61
62**系统能力:** SystemCapability.ArkUI.ArkUI.Full
63
64**参数:**
65
66| 参数名    | 类型   | 必填   | 说明                                                                                                         |
67| -------- | ------- | ------ | ------------------------------------------------------------------------------------------------------------ |
68| instance | T       | 是     | 组件的属性类,用来标识进行属性设置的组件的类型,比如Button组件的ButtonAttribute,Text组件的TextAttribute等。 |
69
70### applyPressedAttribute
71applyPressedAttribute?(instance: T) : void
72
73组件按压状态的样式。
74
75**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。
76
77**系统能力:** SystemCapability.ArkUI.ArkUI.Full
78
79**参数:**
80
81| 参数名    | 类型   | 必填   | 说明                                                                                                         |
82| -------- | ------- | ------ | ------------------------------------------------------------------------------------------------------------ |
83| instance | T       | 是     | 组件的属性类,用来标识进行属性设置的组件的类型,比如Button组件的ButtonAttribute,Text组件的TextAttribute等。 |
84
85### applyFocusedAttribute
86applyFocusedAttribute?(instance: T) : void
87
88组件获焦状态的样式。
89
90**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。
91
92**系统能力:** SystemCapability.ArkUI.ArkUI.Full
93
94**参数:**
95
96| 参数名    | 类型   | 必填   | 说明                                                                                                         |
97| -------- | ------- | ------ | ------------------------------------------------------------------------------------------------------------ |
98| instance | T       | 是     | 组件的属性类,用来标识进行属性设置的组件的类型,比如Button组件的ButtonAttribute,Text组件的TextAttribute等。 |
99
100### applyDisabledAttribute
101applyDisabledAttribute?(instance: T) : void
102
103组件禁用状态的样式。
104
105**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。
106
107**系统能力:** SystemCapability.ArkUI.ArkUI.Full
108
109**参数:**
110
111| 参数名    | 类型   | 必填   | 说明                                                                                                         |
112| -------- | ------- | ------ | ------------------------------------------------------------------------------------------------------------ |
113| instance | T       | 是     | 组件的属性类,用来标识进行属性设置的组件的类型,比如Button组件的ButtonAttribute,Text组件的TextAttribute等。 |
114
115### applySelectedAttribute
116applySelectedAttribute?(instance: T) : void
117
118组件选中状态的样式。
119
120开发者可根据需要自定义实现这些方法,通过传入的参数识别组件类型,对instance设置属性,支持使用if/else语法进行动态设置。
121
122**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。
123
124**系统能力:** SystemCapability.ArkUI.ArkUI.Full
125
126**参数:**
127
128| 参数名    | 类型   | 必填   | 说明                                                                                                         |
129| -------- | ------- | ------ | ------------------------------------------------------------------------------------------------------------ |
130| instance | T       | 是     | 组件的属性类,用来标识进行属性设置的组件的类型,比如Button组件的ButtonAttribute,Text组件的TextAttribute等。 |
131
132**instance参数支持范围:**
133
134AlphabetIndexerAttribute、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、IndicatorComponentAttribute、ImageAttribute、ImageAnimatorAttribute、ImageSpanAttribute、LineAttribute、LinearIndicatorAttribute、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-->。
135
136**属性支持范围:**
137
1381. 不支持入参或者返回值为[CustomBuilder](ts-types.md#custombuilder8)的属性。
1392. 不支持入参为[modifier](../../../ui/arkts-user-defined-modifier.md)类型的属性,具体为以下属性方法:[attributeModifier](#attributemodifier),[drawModifier](./ts-universal-attributes-draw-modifier.md)和[gestureModifier](./ts-universal-attributes-gesture-modifier.md)。
1403. 不支持[animation](./ts-animatorproperty.md)属性。
1414. 不支持[gesture](../../../ui/arkts-gesture-events-binding.md)类型的属性。
1425. 不支持[stateStyles](./ts-universal-attributes-polymorphic-style.md)属性。
1436. 不支持已废弃属性。
144<!--Del-->
1457. 不支持系统组件属性。<!--DelEnd-->
146
147不支持或者未实现的属性在使用时会抛出"Method not implemented."、"is not callable"、"Builder is not supported."等异常信息。具体Modifier支持范围同基类属性接口的支持范围,详见表格[Attribute支持范围](#attribute支持范围)。
148
149## 自定义Modifier
150从API version 12开始,开发者可使用自定义Modifier构建组件并配置属性,通过此自定义的Modifier可调用所封装组件的属性和样式接口。
151
152**自定义Modifier支持范围:**
153
154CommonModifier、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。
155未暴露的组件Modifier可以使用CommonModifier。
156
157**注意事项**
1581. 设置自定义Modifier给一个组件,该组件对应属性生效。
1592. 自定义Modifier属性值变化,组件对应属性也会变化。自定义Modifier类型为基类,构造的对象为子类对象,使用时要通过as进行类型断言为子类。
1603. 一个自定义Modifier设置给两个组件,Modifier属性变化的时候对两个组件同时生效。
1614. 一个Modifier设置了属性A和属性B,再设置属性C和属性D,4个属性同时在组件上生效。
1625. 自定义Modifier不支持@State标注的状态数据的变化感知,见[示例3(自定义Modifier不支持感知@State装饰的状态数据变化)](#示例3自定义modifier不支持感知state装饰的状态数据变化)。
1636. 多次通过attributeModifier设置属性时,生效的属性为所有属性的并集,相同属性按照设置顺序生效。
164
165## 示例
166### 示例1(组件绑定Modifier切换背景颜色)
167
168该示例通过Button绑定Modifier实现了点击切换背景颜色的效果。
169
170```ts
171// xxx.ets
172class MyButtonModifier implements AttributeModifier<ButtonAttribute> {
173  public isDark: boolean = false;
174
175  applyNormalAttribute(instance: ButtonAttribute): void {
176    if (this.isDark) {
177      instance.backgroundColor(Color.Black);
178    } else {
179      instance.backgroundColor(Color.Red);
180    }
181  }
182}
183
184@Entry
185@Component
186struct attributeDemo {
187  @State modifier: MyButtonModifier = new MyButtonModifier();
188
189  build() {
190    Row() {
191      Column() {
192        Button("Button")
193          .attributeModifier(this.modifier)
194          .onClick(() => {
195            this.modifier.isDark = !this.modifier.isDark;
196          })
197      }
198      .width('100%')
199    }
200    .height('100%')
201  }
202}
203```
204![attributeModifier_ifelse](figures/attributeModifier_ifelse.gif)
205
206### 示例2(组件绑定Modifier实现按压态效果)
207
208该示例通过Button绑定Modifier实现了按压态的效果。如果配合状态管理V2使用,详情见:[Modifier与makeObserved](../../../ui/state-management/arkts-v1-v2-migration-application-and-others.md#modifier)。
209
210```ts
211// xxx.ets
212class MyButtonModifier implements AttributeModifier<ButtonAttribute> {
213  applyNormalAttribute(instance: ButtonAttribute): void {
214    instance.backgroundColor(Color.Black);
215  }
216
217  applyPressedAttribute(instance: ButtonAttribute): void {
218    instance.backgroundColor(Color.Red);
219  }
220}
221
222@Entry
223@Component
224struct attributePressedDemo {
225  @State modifier: MyButtonModifier = new MyButtonModifier();
226
227  build() {
228    Row() {
229      Column() {
230        Button("Button")
231          .attributeModifier(this.modifier)
232      }
233      .width('100%')
234    }
235    .height('100%')
236  }
237}
238```
239![attributeModifier_ifelse](figures/attributeModifier_ifelse.gif)
240
241### 示例3(自定义Modifier不支持感知@State装饰的状态数据变化)
242
243该示例通过状态数据设置自定义Modifier的宽度,自定义Modifier不支持感知@State装饰的状态数据变化,点击按钮后宽度不发生改变。
244
245```ts
246import { CommonModifier } from "@kit.ArkUI";
247
248const TEST_TAG : string = "AttributeModifier";
249class MyModifier extends CommonModifier {
250  applyNormalAttribute(instance: CommonAttribute): void {
251    super.applyNormalAttribute?.(instance);
252  }
253}
254
255@Component
256struct MyImage1 {
257  @Link modifier: CommonModifier;
258
259  build() {
260    Image($r("app.media.startIcon")).attributeModifier(this.modifier as MyModifier)
261  }
262}
263
264@Entry
265@Component
266struct Index {
267  index: number = 0;
268  @State width1: number = 100;
269  @State height1: number = 100;
270  @State myModifier: CommonModifier = new MyModifier().width(this.width1).height(this.height1).margin(10);
271
272  build() {
273    Column() {
274      Button($r("app.string.EntryAbility_label"))
275        .margin(10)
276        .onClick(() => {
277          console.log(TEST_TAG, "onClick");
278          this.index++;
279          if (this.index % 2 === 1) {
280            this.width1 = 10;
281            console.log(TEST_TAG, "setGroup1");
282          } else {
283            this.height1 = 10;
284            console.log(TEST_TAG, "setGroup2");
285          }
286        })
287      MyImage1({ modifier: this.myModifier })
288    }
289    .width('100%')
290  }
291}
292```
293![attributeModifier2](figures/attributeModifier2.gif)
294
295### 示例4(Modifier和自定义Modifier的属性同时生效)
296
297该示例通过自定义Modifier设置了width和height,点击按钮时设置borderStyle和borderWidth,点击后4个属性同时生效。
298
299```ts
300import { CommonModifier } from "@kit.ArkUI";
301
302const TEST_TAG: string = "AttributeModifier";
303
304class MyModifier extends CommonModifier {
305  applyNormalAttribute(instance: CommonAttribute): void {
306    super.applyNormalAttribute?.(instance);
307  }
308
309  public setGroup1(): void {
310    this.borderStyle(BorderStyle.Dotted);
311    this.borderWidth(8);
312  }
313
314  public setGroup2(): void {
315    this.borderStyle(BorderStyle.Dashed);
316    this.borderWidth(8);
317  }
318}
319
320@Component
321struct MyImage1 {
322  @Link modifier: CommonModifier;
323
324  build() {
325    Image($r("app.media.startIcon")).attributeModifier(this.modifier as MyModifier)
326  }
327}
328
329@Entry
330@Component
331struct Index {
332  @State myModifier: CommonModifier = new MyModifier().width(100).height(100).margin(10);
333  index: number = 0;
334
335  build() {
336    Column() {
337      Button($r("app.string.EntryAbility_label"))
338        .margin(10)
339        .onClick(() => {
340          console.log(TEST_TAG, "onClick");
341          this.index++;
342          if (this.index % 2 === 1) {
343            (this.myModifier as MyModifier).setGroup1();
344            console.log(TEST_TAG, "setGroup1");
345          } else {
346            (this.myModifier as MyModifier).setGroup2();
347            console.log(TEST_TAG, "setGroup2");
348          }
349        })
350      MyImage1({ modifier: this.myModifier })
351    }
352    .width('100%')
353  }
354}
355```
356![attributeModifier](figures/attributeModifier.gif)
357
358### 示例5(组件绑定Modifier获焦样式)
359
360该示例通过Button绑定Modifier实现了组件在获得焦点时的样式效果。点击Button2后,Button会显示获得焦点后的样式。
361
362```ts
363class MyButtonModifier implements AttributeModifier<ButtonAttribute> {
364
365  applyNormalAttribute(instance: ButtonAttribute): void {
366    instance.backgroundColor(Color.Blue);
367  }
368  applyFocusedAttribute(instance: ButtonAttribute): void {
369    instance.backgroundColor(Color.Green);
370  }
371}
372
373@Entry
374@Component
375struct attributeDemo {
376  @State modifier: MyButtonModifier = new MyButtonModifier();
377  @State isDisable: boolean = true;
378
379  build() {
380    Row() {
381      Column() {
382        Button("Button")
383          .attributeModifier(this.modifier)
384          .enabled(this.isDisable)
385          .id("app")
386        Divider().vertical(false).strokeWidth(15).color(Color.Transparent)
387        Button("Button2")
388          .onClick(() => {
389            this.getUIContext().getFocusController().activate(true);
390            this.getUIContext().getFocusController().requestFocus("app");
391          })
392      }
393      .width('100%')
394    }
395    .height('100%')
396  }
397}
398```
399![applyFocusedAttribute](figures/applyFocusedAttribute.gif)
400
401### 示例6(组件绑定Modifier禁用状态的样式)
402
403该示例通过Button绑定Modifier实现了组件禁用时的样式效果。点击Button2后,Button会显示禁用状态的样式。
404
405```ts
406class MyButtonModifier implements AttributeModifier<ButtonAttribute> {
407  applyDisabledAttribute(instance: ButtonAttribute): void {
408    instance.width(200);
409  }
410}
411
412@Entry
413@Component
414struct attributeDemo {
415  @State modifier: MyButtonModifier = new MyButtonModifier();
416  @State isDisable: boolean = true;
417
418  build() {
419    Row() {
420      Column() {
421        Button("Button")
422          .attributeModifier(this.modifier)
423          .enabled(this.isDisable)
424        Divider().vertical(false).strokeWidth(15).color(Color.Transparent)
425        Button("Button2")
426          .onClick(() => {
427            this.isDisable = !this.isDisable;
428          })
429      }
430      .width('100%')
431    }
432    .height('100%')
433  }
434}
435```
436![applyDisabledAttribute](figures/applyDisabledAttribute.gif)
437
438### 示例7(组件绑定Modifier选中状态样式)
439
440该示例通过Radio绑定Modifier实现了展示组件选中时样式的效果。
441
442```ts
443class MyRadioModifier implements AttributeModifier<RadioAttribute> {
444  applyNormalAttribute(instance: RadioAttribute): void {
445    instance.backgroundColor(Color.Blue);
446  }
447  applySelectedAttribute(instance: RadioAttribute): void {
448    instance.backgroundColor(Color.Red);
449    instance.borderWidth(2);
450  }
451}
452
453@Entry
454@Component
455struct attributeDemo {
456  @State modifier: MyRadioModifier = new MyRadioModifier();
457  @State value: boolean = false;
458  @State value2: boolean = false;
459
460  build() {
461    Row() {
462      Column() {
463        Radio({ value: 'Radio1', group: 'radioGroup1' })
464          .checked(this.value)
465          .height(50)
466          .width(50)
467          .borderWidth(0)
468          .borderRadius(30)
469          .onClick(() => {
470            this.value = !this.value;
471          })
472          .attributeModifier(this.modifier)
473      }
474      .width('100%')
475    }
476    .height('100%')
477  }
478}
479```
480![applySelectedAttribute](figures/applySelectedAttribute.gif)
481
482### 示例8(自定义组件绑定Modifier实现按压态效果)
483
484该示例通过Common(自定义)绑定Modifier实现了按压态的效果。
485
486```ts
487// xxx.ets
488class CustomModifier implements AttributeModifier<CommonAttribute> {
489  applyNormalAttribute(instance: CommonAttribute): void {
490    instance.backgroundColor(Color.Blue)
491  }
492
493  applyPressedAttribute(instance: CommonAttribute): void {
494    instance.backgroundColor(Color.Red)
495  }
496}
497
498@Entry
499@Component
500struct attributePressedDemo {
501  @State  modifier: CustomModifier = new CustomModifier()
502
503  build() {
504    Row() {
505      Column() {
506        ChildComponent()
507          .attributeModifier(this.modifier)
508      }
509      .width('100%')
510    }
511    .height('100%')
512  }
513}
514
515@Component
516struct ChildComponent {
517  build() {
518    Text("common").fontColor(Color.Green).fontSize(28).textAlign(TextAlign.Center)
519      .width('35%')
520      .height('10%')
521  }
522}
523```
524![attributeModifier_common](figures/attributeModifier_common.gif)
525
526## Attribute支持范围
527
528未在表格中列举的属性默认为支持。
529
530**表1** CommonAttribute属性接口支持例外范围
531
532| 属性                     | 支持情况 | 告警信息                  | 备注                                      |
533| ------------------------ | -------- | ------------------------- | ----------------------------------------- |
534| accessibilityChecked     | 不支持   | is not callable           | -                                         |
535| accessibilitySelected    | 不支持   | is not callable           | -                                         |
536| accessibilityTextHint    | 不支持   | is not callable           | -                                         |
537| accessibilityVirtualNode | 不支持   | is not callable           | 不支持入参为CustomBuilder。               |
538| animation                | 不支持   | Method not implemented.   | 不支持animation相关属性。                 |
539| attributeModifier        | 不支持   | -                         | attributeModifier不支持嵌套使用,不生效。 |
540| background               | 不支持   | Method not implemented.   | 不支持入参为CustomBuilder。               |
541| backgroundFilter         | 不支持   | is not callable           | -                                         |
542| bindContentCover         | 不支持   | Method not implemented.   | 不支持入参为CustomBuilder。               |
543| bindContextMenu          | 不支持   | Method not implemented.   | 不支持入参为CustomBuilder。               |
544| bindPopup                | 不支持   | Method not implemented.   | 不支持入参为CustomBuilder。               |
545| bindSheet                | 不支持   | Method not implemented.   | 不支持入参为CustomBuilder。               |
546| chainWeight              | 不支持   | is not callable           | -                                         |
547| compositingFilter        | 不支持   | is not callable           | -                                         |
548| drawModifier             | 不支持   | is not callable           | 不支持modifier相关的属性。                |
549| foregroundFilter         | 不支持   | is not callable           | -                                         |
550| freeze                   | 不支持   | is not callable           | -                                         |
551| gesture                  | 不支持   | Method not implemented.   | 不支持gesture相关的属性。                 |
552| gestureModifier          | 不支持   | is not callable           | 不支持modifier相关的属性。                |
553| onAccessibilityHover     | 不支持   | is not callable           | -                                         |
554| onDigitalCrown           | 不支持   | is not callable.          | -                                       |
555| onDragStart              | 不支持   | Method not implemented.   | 不支持返回值为CustomBuilder。             |
556| parallelGesture          | 不支持   | Method not implemented.   | 不支持gesture相关的属性。                 |
557| priorityGesture          | 不支持   | Method not implemented.   | 不支持gesture相关的属性。                 |
558| reuseId                  | 不支持   | Method not implemented.   | -                                         |
559| stateStyles              | 不支持   | Method not implemented.   | 不支持stateStyles相关的属性。             |
560| useSizeType              | 不支持   | Method not implemented.   | 不支持已废弃属性。                        |
561| visualEffect             | 不支持   | is not callable           | -                                         |
562| bindMenu                 | 部分支持 | -                         | 不支持入参为CustomBuilder。               |
563| dragPreview              | 部分支持 | Builder is not supported. | 不支持入参为CustomBuilder。               |
564