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)
}
}
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)
}
}
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)
}
}
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
- Attribute Restrictions
No support for CustomBuilder or lambda properties
Cannot modify private properties (e.g., TextPicker.visibleItems)
- State Management Requirements
Manual handling of property override precedence
Complex components need multi-modifier synchronization
- 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)
}
}
2. State Management Optimization
abstract class BaseModifier<T> implements AttributeModifier<T> {
protected themeColor: ResourceColor = Color.Blue
updateTheme(color: ResourceColor) {
this.themeColor = color
}
}
Top comments (0)