<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: flylu</title>
    <description>The latest articles on DEV Community by flylu (@flylu).</description>
    <link>https://dev.to/flylu</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3302129%2F8766910b-150e-4e4d-a8fc-6100ac7c78ed.png</url>
      <title>DEV Community: flylu</title>
      <link>https://dev.to/flylu</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/flylu"/>
    <language>en</language>
    <item>
      <title>HarmonyOS Development Enters Polymorphic Styles stateStyles</title>
      <dc:creator>flylu</dc:creator>
      <pubDate>Sat, 28 Jun 2025 05:33:55 +0000</pubDate>
      <link>https://dev.to/flylu/harmonyos-development-enters-polymorphic-styles-statestyles-3i54</link>
      <guid>https://dev.to/flylu/harmonyos-development-enters-polymorphic-styles-statestyles-3i54</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This article is based on HarmonyOSApi14 &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;in the development, there is a case where there is an entry. The default is a background color in the no-Operation State. After clicking the finger, it changes to another background color. When the finger is released, it reverts to the default background color. How should we implement it? &lt;/p&gt;

&lt;p&gt;Some students may say, this is not a pinch in hand, it can be easily done by using onTouch event. Press the finger to change the background, and lift the finger to restore the background. The code is as follows:&lt;br&gt;
&lt;br&gt;
 &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Column() {
        Text("我是一个普通的条目")
          .fontColor(Color.White)
      }
      .width("100%")
      .height(100)
      .borderRadius(10)
      .justifyContent(FlexAlign.Center)
      .backgroundColor(this.itemBgColor)
      .onTouch((event) =&amp;gt; {
        if (event.type == TouchType.Down) {
          this.itemBgColor = Color.Pink
        } else if (event.type == TouchType.Up) {
          this.itemBgColor = Color.Gray
        }
      })
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ah, let alone, this effect has really been achieved. If it is not only the background color, there may be many attribute changes in actual development, such as width, height, margin, etc., then we need many attributes to assign values. In this writing method, in addition to implementing onTouch method, we also need to define changeable variables to switch our state, which is slightly redundant in code, is there a simple way to change attributes directly? Of course, there are stateStyles. &lt;/p&gt;

&lt;p&gt;Let's use stateStyles to implement the above code. The code is as follows:&lt;br&gt;
&lt;br&gt;
 &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Column() {
        Text("test")
          .fontColor(Color.White)
      }
      .width("100%")
      .height(100)
      .borderRadius(10)
      .justifyContent(FlexAlign.Center)
      .stateStyles({
        pressed: { 
          .backgroundColor(Color.Pink)
        },
        normal: { 
          .backgroundColor(Color.Gray)
        }
      })
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;after running the above code, you can find that the effect is exactly the same as the onTouch above. &lt;/p&gt;

&lt;h2&gt;
  
  
  What are stateStyles? 
&lt;/h2&gt;

&lt;p&gt;stateStyles is a polymorphic style. The official interpretation is that different styles can be quickly set according to the internal state of the component, such as the width, height, background, margin, etc. of the component, supporting all the attributes of the component itself. Currently, there are five supported states, namely: focused: focused state, normal: normal state, pressed: pressed state, disabled: unavailable state, selected: selected state.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjndvmh644s092a21rabx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjndvmh644s092a21rabx.png" alt="Image description" width="800" height="293"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The specific usage scenario mainly involves multi-state switching scenarios, such as the case of background switching in the front. What we need to know is that it supports all the attributes of the component itself. For example, we add other attributes:&lt;br&gt;
&lt;br&gt;
 &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.stateStyles({
        pressed: { 
          .backgroundColor(Color.Pink)
          .width("100%")
        },
        normal: { 
          .backgroundColor(Color.Gray)
          .width("80%")
        }
      })
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;if there are more Styles to modify, stateStyles can be used in combination with the @ Styles Decorator. For example, in the above case, let's modify it:&lt;br&gt;
&lt;br&gt;
 &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  @Styles
  normalStyle() {
    .backgroundColor(Color.Gray)
    .width("80%")
  }

  @Styles
  pressedStyle() {
    .backgroundColor(Color.Pink)
    .width("100%")
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;specific use is as follows:&lt;br&gt;
&lt;br&gt;
 &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; .stateStyles({
        pressed: this.pressedStyle,
        normal: this.normalStyle
      })
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;the disabled state is displayed only when the component is disabled. For example, in the following case, the component is disabled:&lt;br&gt;
&lt;br&gt;
 &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.enabled(false)
      .stateStyles({
        disabled: {
          .backgroundColor(Color.Blue)
        }
      })
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;after running, the background color of the display is blue. &lt;/p&gt;

&lt;p&gt;In addition to the above three states, we introduce another state selected, which is generally applicable to selectable components, such as Checkbox and Radio. Currently, the supported components are as follows: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2t1hb2oukmtj32t5wbkh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2t1hb2oukmtj32t5wbkh.png" alt="Image description" width="800" height="344"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;we simply cite an example:&lt;br&gt;
&lt;br&gt;
 &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Radio({ value: 'radio', group: 'radioGroup' })
        .checked(this.isChecked)
        .height(50)
        .width(50)
        .borderWidth(0)
        .borderRadius(30)
        .onClick(() =&amp;gt; {
          this.isChecked = !this.isChecked
        })
        .radioStyle({ checkedBackgroundColor: Color.Pink })
        .stateStyles({
          normal: {
            .backgroundColor(Color.Gray)
          },
          selected: {
            .backgroundColor(Color.Pink)
          }
        })
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffancsnh9zgy45fx9di6p.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffancsnh9zgy45fx9di6p.gif" alt="Image description" width="604" height="1300"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  simple summary 
&lt;/h2&gt;

&lt;p&gt;when using the polymorphic style stateStyles, it is important to note that when clicked and pressed are used on a component at the same time, only the post-registered state will take effect. &lt;/p&gt;

&lt;p&gt;Article tags: HarmonyOS language, ArkUI&lt;/p&gt;

</description>
      <category>harmonyos</category>
    </item>
    <item>
      <title>Component Style Reuse in HarmonyOS Development</title>
      <dc:creator>flylu</dc:creator>
      <pubDate>Sat, 28 Jun 2025 05:28:10 +0000</pubDate>
      <link>https://dev.to/flylu/component-style-reuse-in-harmonyos-development-103a</link>
      <guid>https://dev.to/flylu/component-style-reuse-in-harmonyos-development-103a</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This article is based on harmonyosapi14. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In a project, it can be said that the number of pages is usually relatively large, and each page is usually composed of many components. Each component sometimes involves a lot of attribute settings, such as width, height, background style, etc. Whether it is a single page or between multiple pages, the same components and style attributes will inevitably appear. &lt;/p&gt;

&lt;p&gt;For these recurring components, we can implement component reuse by individual customization to improve development efficiency and reduce duplicate code. For those same style attributes, it is also necessary to reuse them in order to make the code more concise and easy to maintain. &lt;/p&gt;

&lt;p&gt;For example the following code:&lt;br&gt;
&lt;br&gt;
 &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Column() {
      Column() {
        Text("test 1")
          .fontColor(Color.White)
          .fontSize(16)
          .fontWeight(FontWeight.Bold)
      }
      .width("100%")
      .height(100)
      .backgroundColor(Color.Pink)
      .justifyContent(FlexAlign.Center)
      .margin({ top: 10 })

      Column() {
        Text("test 2")
          .fontColor(Color.White)
          .fontSize(16)
          .fontWeight(FontWeight.Bold)
      }
      .width("100%")
      .height(100)
      .backgroundColor(Color.Pink)
      .justifyContent(FlexAlign.Center)
      .margin({ top: 10 })

      Column() {
        Text("test 3")
          .fontColor(Color.White)
          .fontSize(16)
          .fontWeight(FontWeight.Bold)
      }
      .width("100%")
      .height(100)
      .backgroundColor(Color.Pink)
      .justifyContent(FlexAlign.Center)
      .margin({ top: 10 })

      Column() {
        Text("test 4")
          .fontColor(Color.White)
          .fontSize(16)
          .fontWeight(FontWeight.Bold)
      }
      .width("100%")
      .height(100)
      .backgroundColor(Color.Pink)
      .justifyContent(FlexAlign.Center)
      .margin({ top: 10 })
    }
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;as can be seen from the above code, four sub-Column components are nested inside the Column component, and the style attributes of these sub-Column components are exactly the same. At the same time, each sub-Column component contains the same Text component, and the styles of these Text components are also the same. &lt;/p&gt;

&lt;p&gt;It can be said that in actual development, such a large number of repeated style code is not uncommon, the result is that code redundancy not only makes the code structure becomes bloated, but also brings a lot of inconvenience to the subsequent code maintenance work, greatly increasing the maintenance cost. &lt;/p&gt;

&lt;p&gt;In order to solve the above problems, we can adopt the method of style Reuse. At present, there are mainly two extraction methods to choose from. One is component extraction. We can directly use ForEach loop to traverse and render repeated components, so as to avoid repeatedly writing the same component structure in the code. The other is style extraction, which is centralized management by extracting repeated style attributes, then make references where needed, which can effectively reduce the duplication of style definitions in the code, making the code more concise, clear, and easy to maintain. &lt;/p&gt;

&lt;h2&gt;
  
  
  Generic Attribute Style Extraction
&lt;/h2&gt;

&lt;p&gt;The so-called common attribute extraction is the common attributes of all components, such as the width and height of the components, the background, the inner and outer margins, etc. However, one thing needs to be known is that the components do not support their own attributes, such as the color size of the text component, the bitmap of the picture, etc. All their own component attributes and common Styles are not supported. Common attribute extraction can be done through @ Styles decorator. &lt;/p&gt;

&lt;p&gt;In the above case, we use the @ Styles decorator to extract it.&lt;br&gt;
&lt;br&gt;
 &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Entry
@Component
struct Index {
  @Styles
  columnStyle() {
    .width("100%")
    .height(100)
    .backgroundColor(Color.Pink)
    .margin({ top: 10 })
  }

  build() {
    Column() {
      Column() {
        Text("test 1")
          .fontColor(Color.White)
          .fontSize(16)
          .fontWeight(FontWeight.Bold)
      }
      .columnStyle()
      .justifyContent(FlexAlign.Center)

      Column() {
        Text("test 2")
          .fontColor(Color.White)
          .fontSize(16)
          .fontWeight(FontWeight.Bold)
      }
      .columnStyle()
      .justifyContent(FlexAlign.Center)

      Column() {
        Text("test 3")
          .fontColor(Color.White)
          .fontSize(16)
          .fontWeight(FontWeight.Bold)
      }
      .columnStyle()
      .justifyContent(FlexAlign.Center)

      Column() {
        Text("test 4")
          .fontColor(Color.White)
          .fontSize(16)
          .fontWeight(FontWeight.Bold)
      }
      .columnStyle()
      .justifyContent(FlexAlign.Center)

    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It can be seen that the Column component is still very concise after extraction, but everyone has also seen the problem mentioned earlier, that is, the @ Styles decorator only supports common attributes. Since the justifyContent attribute is the attribute of the Column component itself, it cannot be set, and the attributes in the Text component also belong to the attribute of the Text component and cannot be used here. &lt;/p&gt;

&lt;p&gt;The above method is extracted within the component. Of course, the @ Styles decorator also supports global extraction. You can extract it into a page separately for reuse by all the same component Styles.&lt;br&gt;
&lt;br&gt;
 &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Styles
function columnStyle() {
  .width("100%")
    .height(100)
    .backgroundColor(Color.Pink)
    .margin({ top: 10 })
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Component Style Extraction 
&lt;/h2&gt;

&lt;p&gt;although the use of @ Styles decorator solves some code redundancy, it is still not thorough enough. After all, many of its own attributes are not supported. In order to solve the above problems, we can use @ Extend decorator. &lt;/p&gt;

&lt;p&gt;It's still the above case, let's take a look.&lt;br&gt;
&lt;br&gt;
 &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Extend(Column)
function columnStyle() {
  .width("100%")
  .height(100)
  .backgroundColor(Color.Pink)
  .margin({ top: 10 })
  .justifyContent(FlexAlign.Center)
}

@Extend(Text)
function textStyle() {
  .fontColor(Color.White)
  .fontSize(16)
  .fontWeight(FontWeight.Bold)
}

@Entry
@Component
struct Index {
  build() {
    Column() {
      Column() {
        Text("test 1").textStyle()
      }.columnStyle()

      Column() {
        Text("test 2").textStyle()
      }.columnStyle()

      Column() {
        Text("test 3").textStyle()
      }.columnStyle()

      Column() {
        Text("test 4").textStyle()
      }.columnStyle()

    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Can you see that using the @ Extend decorator is obviously much simpler than the @ Styles decorator. &lt;/p&gt;

&lt;h2&gt;
  
  
  Simple summary
&lt;/h2&gt;

&lt;p&gt;The @ Styles decorator and the @ Extend decorator can both solve the problem of redundancy of our style attributes in actual development, but their uses are really different. For example, if the Styles of the same components are reused, we can use the @ Extend decorator, and if the Styles of different components are common, we can use the @ Styles decorator. &lt;/p&gt;

&lt;p&gt;Although the above two decorators can solve the problem of redundancy of our styles, I want to judge whether to set an attribute style according to a certain condition, that is, the setting of dynamic attributes, which is not supported. In order to solve the problem of dynamic setting of attributes, I have to mention another way in Hongmeng that can extract attribute styles and use AttributeModifier, which we will introduce in future articles. &lt;/p&gt;

&lt;p&gt;Article tags: HarmonyOS language, ArkUI&lt;/p&gt;

</description>
      <category>harmonyos</category>
    </item>
  </channel>
</rss>
