DEV Community

魔眼天王
魔眼天王

Posted on

Deep Dive into HarmonyOS AttributeModifier

Recently working on focus management, I encountered issues with incomplete focus border displays. After extensive investigation, I discovered AttributeModifier - a powerful yet non-invasive solution for dynamic attribute control.

I. Core Concepts & Architecture

AttributeModifier is a dynamic attribute modification interface provided by HarmonyOS ArkUI framework. By implementing method families like applyNormalAttribute() and applyPressedAttribute(), developers can dynamically control component properties across interaction states. Its architecture comprises three key layers:

1. State Perception Layer

Triggers corresponding methods through built-in component states (default/pressed/focused/disabled/selected). Example: Press state activates applyPressedAttribute()

2. Attribute Injection Layer

Injects custom modifier instances via .attributeModifier() during component initialization or state changes, supporting cross-component reuse

3. Dynamic Parameter Layer

Enables runtime style control through class member variables combined with @State

II. Practical Applications

1. Polymorphic Style Management

// Button polymorphic style definition  
export class ThemeButtonModifier implements AttributeModifier<ButtonAttribute> {  
  applyNormalAttribute(instance: ButtonAttribute) {  
    instance.backgroundColor(Color.Blue)  
  }  
  applyPressedAttribute(instance: ButtonAttribute) {  
    instance.backgroundColor(Color.DarkBlue)  
  }  
}  
Enter fullscreen mode Exit fullscreen mode

Unified theming for form controls and button state consistency

2. Dynamic Theme Switching

@State isDarkMode: boolean = false  
build() {  
  Button("Toggle Theme")  
    .attributeModifier(new DynamicThemeModifier(this.isDarkMode))  
    .onClick(() => this.isDarkMode = !this.isDarkMode)  
}  

class DynamicThemeModifier implements AttributeModifier<ButtonAttribute> {  
  private isDark: boolean = false  
  constructor(dark: boolean) { this.isDark = dark }  
  applyNormalAttribute(instance: ButtonAttribute) {  
    instance.backgroundColor(this.isDark ? Color.Black : Color.White)  
    instance.fontColor(this.isDark ? Color.White : Color.Black)  
  }  
}  
Enter fullscreen mode Exit fullscreen mode

Avoids hard-coded colors for global theme responsiveness

3. Business Logic Integration

export class AuthButtonModifier implements AttributeModifier<ButtonAttribute> {  
  private isVIP: boolean = false  
  setVIPStatus(status: boolean) { this.isVIP = status }  
  applyNormalAttribute(instance: ButtonAttribute) {  
    instance.backgroundColor(this.isVIP ? Color.Gold : Color.Gray)  
  }  
}  
Enter fullscreen mode Exit fullscreen mode

Dynamically adjusts component states based on user permissions

III. API Comparison

Feature AttributeModifier @styles @Extend
Cross-file reusability ✔️ Supported ❌ No ❌ No
Dynamic parameters ✔️ Via class vars ❌ Compile-time ❌ Compile-time
Component-specific ✔️ Partial ❌ Generic ✔️ Full
Event handling ✔️ onClick/etc ❌ No ❌ Basic
Full polymorphism ✔️ Complete ❌ Default ❌ Default

IV. Limitations

  1. ​Attribute Restrictions​
  • No support for CustomBuilder or lambda properties

  • Cannot modify private properties (e.g., TextPicker.visibleItems)

  1. ​State Management Requirements​
  • Manual handling of property override precedence

  • Complex components need multi-modifier synchronization

  1. ​Performance Considerations​
  • Frame rate drops 10-15% with >3 modifiers

  • Frequent state changes (>5/s) may cause rendering delays

V. Implementation Best Practices

1. Style Isolation

// Separate color & layout logic  
class ColorModifier implements AttributeModifier<TextAttribute> {  
  applyNormalAttribute(instance: TextAttribute) {  
    instance.fontColor(this.textColor)  
  }  
}  

class LayoutModifier implements AttributeModifier<TextAttribute> {  
  applyNormalAttribute(instance: TextAttribute) {  
    instance.fontSize(16)  
  }  
}  
Enter fullscreen mode Exit fullscreen mode

2. State Management Optimization

abstract class BaseModifier<T> implements AttributeModifier<T> {  
  protected themeColor: ResourceColor = Color.Blue  
  updateTheme(color: ResourceColor) {  
    this.themeColor = color  
  }  
}  
Enter fullscreen mode Exit fullscreen mode

Top comments (0)