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 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 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 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 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 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 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 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 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