<?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: 程序员一鸣</title>
    <description>The latest articles on DEV Community by 程序员一鸣 (@abnerming888).</description>
    <link>https://dev.to/abnerming888</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%2F2912844%2F743da117-d041-446c-9d1f-56d2f5f0dbb4.jpeg</url>
      <title>DEV Community: 程序员一鸣</title>
      <link>https://dev.to/abnerming888</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/abnerming888"/>
    <language>en</language>
    <item>
      <title>HarmonyOS Development: Realizing Key-Value Database Storage</title>
      <dc:creator>程序员一鸣</dc:creator>
      <pubDate>Mon, 30 Jun 2025 05:03:54 +0000</pubDate>
      <link>https://dev.to/abnerming888/harmonyos-development-realizing-key-value-database-storage-10pm</link>
      <guid>https://dev.to/abnerming888/harmonyos-development-realizing-key-value-database-storage-10pm</guid>
      <description>&lt;h2&gt;
  
  
  Foreword 
&lt;/h2&gt;

&lt;p&gt;this article is based on Api12 &lt;/p&gt;

&lt;p&gt;the persistent storage of data in Hongmeng provides us with a variety of implementations, such as user preferences, relational databases, key-value database mode, file storage mode, etc., for relatively small data volume, we can directly choose lightweight user preference mode, while for relatively large data volume, we can directly use the database, while for relatively large data, we can use key-value database mode, which is a data storage mode between user preference and relational database. &lt;/p&gt;

&lt;p&gt;The Key-Value database is very simple to use. From the literal meaning, it can be known that it stores and acquires data in the form of Key-Value pairs, which is similar to user preferences. However, the Key-Value database has its own restrictive factors. The first is that for each record, the length of Key ≤ 896 Byte, and the length of Value &amp;lt;4MB, for a single-version database, the length of each record is less than or equal to 1KB, and the length of Value is less than 4MB. Each application supports opening up to 16 Key-Value distributed databases at the same time. The last one is that blocking operations are not allowed in the Key-Value database event callback method, such as modifying UI components. &lt;/p&gt;

&lt;p&gt;Common objects in key-value databases are 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;KVManager: A distributed key value database management instance used to retrieve relevant information from the database.
KVStoreResultSet: Provides methods for obtaining database result sets, including querying and moving data read locations.
Query: Use predicates to represent database queries, providing methods for creating Query instances, querying data in the database, and adding predicates.
SingleKVStore: A single version distributed key value database that does not distinguish the devices to which the data belongs, providing methods for querying and synchronizing data.
DeviceKVStore: Device collaborative database, inherited from SingleKVStore, distinguishes data based on device dimensions, and provides methods for querying and synchronizing data.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;the specific data storage is not introduced here, you can directly view the official documents, here is to introduce the specific usage of the key-value database after encapsulation. &lt;/p&gt;
&lt;h2&gt;
  
  
  Rapid dependence 
&lt;/h2&gt;

&lt;p&gt;method 1: in the Terminal window, run the following command to install the third-party package. DevEco Studio automatically adds the third-party package dependency to the project oh-package.json5.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Suggestion: Execute the command under the module path used.&lt;/strong&gt;&lt;/p&gt;




&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ohpm install @abner/datastore
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Method 2: Set the three-party package dependency in the project oh-package.json5. The configuration example 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;"dependencies": { "@abner/datastore": "^1.0.3"}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  code call 
&lt;/h2&gt;
&lt;h3&gt;
  
  
  1. Initialization 
&lt;/h3&gt;

&lt;p&gt;it is recommended to initialize in the AbilityStage. If you want to use multiple file instances for storage, you can pass the second parameter.&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;DataKvUtil.getInstance().init(this.context, "com.abner.tool")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h4&gt;
  
  
  Related Property Introduction 
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;property&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;type&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;overview&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;context &lt;/td&gt;
&lt;td&gt;Context &lt;/td&gt;
&lt;td&gt;context &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;bundleName &lt;/td&gt;
&lt;td&gt;string &lt;/td&gt;
&lt;td&gt;caller's package name &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;option &lt;/td&gt;
&lt;td&gt;distributedKVStore.Options &lt;/td&gt;
&lt;td&gt;(Optional) Database configuration information &lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h5&gt;
  
  
  option related parameters 
&lt;/h5&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;property&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;type&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;required&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;description&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;createIfMissing &lt;/td&gt;
&lt;td&gt;boolean &lt;/td&gt;
&lt;td&gt;no &lt;/td&gt;
&lt;td&gt;whether to create a database when the database file does not exist. The default value is true.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;encrypt &lt;/td&gt;
&lt;td&gt;boolean &lt;/td&gt;
&lt;td&gt;no &lt;/td&gt;
&lt;td&gt;set whether the database file is encrypted. Encapsulation defaults to true, that is, it is not encrypted. &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;backup &lt;/td&gt;
&lt;td&gt;boolean &lt;/td&gt;
&lt;td&gt;no &lt;/td&gt;
&lt;td&gt;set whether the database file is backed up. Encapsulation defaults to true, that is, backup. &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;autoSync &lt;/td&gt;
&lt;td&gt;boolean &lt;/td&gt;
&lt;td&gt;no &lt;/td&gt;
&lt;td&gt;sets whether the database files are automatically synchronized. Encapsulation defaults to true, that is, Manual synchronization. &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;kvStoreType &lt;/td&gt;
&lt;td&gt;KVStoreType &lt;/td&gt;
&lt;td&gt;no &lt;/td&gt;
&lt;td&gt;set the type of the database to be created. The default value is DEVICE_COLLABORATION, which is a multi-device collaboration database. &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;securityLevel &lt;/td&gt;
&lt;td&gt;SecurityLevel &lt;/td&gt;
&lt;td&gt;yes &lt;/td&gt;
&lt;td&gt;set the database security level. &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;schema &lt;/td&gt;
&lt;td&gt;Schema &lt;/td&gt;
&lt;td&gt;no &lt;/td&gt;
&lt;td&gt;sets the value of the definition stored in the database. The default value is undefined, that is, no Schema is used. &lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h5&gt;
  
  
  KVStoreType
&lt;/h5&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;KVStoreType Distributed Key Value Database Type Enumeration.

DEVICE_COLLABORATION

Represents a multi device collaborative database.

Database features: Data is managed in the dimension of devices, without conflicts; Support querying data based on device dimensions.

SINGLE_VERSION

Represents a single version database.

Database characteristics: Data is not device specific, and modifying the same key between devices will overwrite it.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h5&gt;
  
  
  SecurityLevel
&lt;/h5&gt;

&lt;p&gt;&lt;br&gt;
 &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Enumeration of database security levels.

S1

The security level of the database is low, and data leakage, tampering, destruction, and destruction may have limited adverse effects on individuals or organizations.

For example, gender, nationality, user application records, etc.

S2

The security level of the database is considered medium, and data leakage, tampering, destruction, and destruction may cause serious adverse effects on individuals or organizations.

For example, personal detailed mailing address, name nickname, etc.

S3

The security level of the database is high, and data leakage, tampering, destruction, and destruction may have serious adverse effects on individuals or organizations.

For example, personal real-time precise positioning information, motion trajectories, etc.

S4

The security level of the database is considered critical, which is a special type of data defined in industry laws and regulations. It involves information in the most private areas of individuals or data that may cause significant adverse effects to individuals or organizations if leaked, tampered with, destroyed, or destroyed.

For example, political views, religious and philosophical beliefs, union membership, genetic data, biological information, health and sexual status, sexual orientation, or device authentication, personal credit card and other financial information.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  2. Data storage
&lt;/h3&gt;

&lt;p&gt;&lt;br&gt;
 &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DataKvUtil.getInstance().put("key", "value")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;p&gt;&lt;strong&gt;whether listening is successfully stored&lt;/strong&gt;&lt;/p&gt;




&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DataKvUtil.getInstance().put("key", "value", (isSuccess:boolean) =&amp;gt; {

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

&lt;/div&gt;




&lt;p&gt;&lt;strong&gt;listens for storage success and failure&lt;/strong&gt;&lt;/p&gt;




&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DataKvUtil.getInstance().put("key", "value", (isSuccess:boolean, err:BusinessError) =&amp;gt; {
  //When isSuccess is false, err is the error message
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;p&gt;&lt;strong&gt;using Promise asynchronous callbacks&lt;/strong&gt;&lt;/p&gt;




&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let pPromise = DataKvUtil.getInstance().putPromise("key", "value")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  3 Obtaining data
&lt;/h3&gt;

&lt;p&gt;&lt;br&gt;
 &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DataKvUtil.getInstance().get("key", (data) =&amp;gt; {

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

&lt;/div&gt;




&lt;p&gt;&lt;strong&gt;monitoring failed&lt;/strong&gt;&lt;/p&gt;




&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DataKvUtil.getInstance().get("key", (data) =&amp;gt; {

}, (err:BusinessError) =&amp;gt; {

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

&lt;/div&gt;




&lt;p&gt;&lt;strong&gt;using Promise asynchronous callbacks&lt;/strong&gt;&lt;/p&gt;




&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let pPromise = DataKvUtil.getInstance().getPromise("key")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  4. Delete data
&lt;/h3&gt;

&lt;p&gt;&lt;br&gt;
 &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DataKvUtil.getInstance().delete("key")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;p&gt;&lt;strong&gt;whether the listener is deleted successfully&lt;/strong&gt;&lt;/p&gt;




&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DataKvUtil.getInstance().delete("key", (isSuccess: boolean) =&amp;gt; {

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

&lt;/div&gt;




&lt;p&gt;&lt;strong&gt;whether the monitor fails to be deleted&lt;/strong&gt;&lt;/p&gt;




&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DataKvUtil.getInstance().delete("key", (isSuccess: boolean, err?: BusinessError) =&amp;gt; {

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

&lt;/div&gt;




&lt;p&gt;&lt;strong&gt;using Promise asynchronous callbacks&lt;/strong&gt;&lt;/p&gt;




&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let pPromise = DataKvUtil.getInstance().deletePromise("key")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  5. Modify data 
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;the modification is consistent with the addition, and the data will overwrite the original key.&lt;/strong&gt;&lt;/p&gt;


&lt;h3&gt;
  
  
  6. Get the default StoreId
&lt;/h3&gt;

&lt;p&gt;&lt;br&gt;
 &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DataKvUtil.getInstance().getStoreId()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  7. Delete the specified distributed key-value database
&lt;/h3&gt;

&lt;p&gt;&lt;br&gt;
 &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DataKvUtil.getInstance().deleteKVStore("storeId")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;p&gt;&lt;strong&gt;whether the listener is deleted successfully&lt;/strong&gt;&lt;/p&gt;




&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DataKvUtil.getInstance().deleteKVStore("storeId", (isSuccess: boolean) =&amp;gt; {

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

&lt;/div&gt;




&lt;p&gt;&lt;strong&gt;whether the monitor fails to be deleted&lt;/strong&gt;&lt;/p&gt;




&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DataKvUtil.getInstance().deleteKVStore("storeId", (isSuccess: boolean, err?: BusinessError) =&amp;gt; {

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

&lt;/div&gt;

&lt;h3&gt;
  
  
  8. Create a new and get the distributed key-value database. 
&lt;/h3&gt;

&lt;p&gt;There will be one by default, if you plan to create a new one, you can call this method!&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;DataKvUtil.getInstance().createKVStore("storeId")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  9. The new database is added, deleted, changed and checked 
&lt;/h3&gt;

&lt;p&gt;first set up your own database, that is, storeId in section 7.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DataKvUtil.getInstance().setKVStore("storeId") 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>harmonyos</category>
    </item>
    <item>
      <title>HarmonyOS Development: Customize an English Keyboard</title>
      <dc:creator>程序员一鸣</dc:creator>
      <pubDate>Mon, 30 Jun 2025 05:03:16 +0000</pubDate>
      <link>https://dev.to/abnerming888/harmonyos-development-customize-an-english-keyboard-16e2</link>
      <guid>https://dev.to/abnerming888/harmonyos-development-customize-an-english-keyboard-16e2</guid>
      <description>&lt;h2&gt;
  
  
  Foreword 
&lt;/h2&gt;

&lt;p&gt;this article is based on Api12 &lt;/p&gt;

&lt;p&gt;the series of custom keyboards has been completed one after another. The license plate provinces are referred to as keyboards, the license plate letter selection keyboard and the stock code keyboard are all common keyboards in some special industries. In this article, we will customize an English keyboard for the general public. Like other keyboard definitions, the implementation methods are different due to the different spacing between each line. &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%2F378t707svid51pdrj1os.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%2F378t707svid51pdrj1os.png" alt="Image description" width="692" height="1478"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Code implementation 
&lt;/h2&gt;

&lt;p&gt;in order to better realize the UI effect, a multi-component implementation is also adopted here. After all, the margins of each Row are different. It is divided into four rows for implementation. You can use grid layout or List components for implementation. The Row component I use here uses ForEach to traverse subcomponents in the Row component. Of course, after all, the amount of data is small, which method to use depends on everyone's choice. &lt;/p&gt;

&lt;p&gt;Let's just say that one line of code is implemented, because they are all repeated, except that the data sources and margins displayed are different, and the important thing for each sub-element is its weight.&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;Row() {
        ForEach(["Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P"], (item: string) =&amp;gt; {
          Text(item)
            .layoutWeight(1)
            .height(this.rectHeight)
            .fontSize(this.rectTextSize)
            .fontColor(this.rectTextColor)
            .backgroundColor(this.englishBgColor)
            .textAlign(TextAlign.Center)
            .margin({ left: 5, right: 5 })
            .borderRadius(this.rectBorderRadius)
            .onClick(() =&amp;gt; {
              if (this.onItemClick != undefined) {
                this.onItemClick(item)
              }
            })
        })
      }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  All codes 
&lt;/h2&gt;

&lt;p&gt;the code is very simple to implement, just look at it yourself.&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;@Component
export struct EnglishKeyboardView {
BgColor: ResourceColor="# f5f5f5"//Background color
English BgColor: ResourceColor="# ffffff"//English background color
OtherBgColor: ResourceColor="# e8e8e8"//Non English background color
RectBorderWidth: Length=1//Grid border width
RectBorderRadius: Length=2//Grid border rounded corners
RectTextCize: Length=16//The text size of the grid
RectTextColor: ResourceColor="# 333333"//Default color for grid text
DeleteIconWidth: Length=30//Delete image width
deleteIconSrc: PixelMap | ResourceStr | DrawableDescriptor = $r("app.media.view_ic_key_delete")
RectHeight: Length=60//Each grid height
MarginTop: Length=10//Distance wise
MarginBottom: Length=10//Below distance
onItemClick? : (item: string)=&amp;gt;void//Click on the item
onDelete? : ()=&amp;gt;void//Click to delete
onComplete? : ()=&amp;gt;void//Click to complete
onChinese? : ()=&amp;gt;void//Chinese
onSpace? : ()=&amp;gt;void//Space
onNumber? : ()=&amp;gt;void//number

build() {
Column() {
Row() {
ForEach(["Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P"], (item: string) =&amp;gt; {
Text(item)
.layoutWeight(1)
.height(this.rectHeight)
.fontSize(this.rectTextSize)
.fontColor(this.rectTextColor)
.backgroundColor(this.englishBgColor)
.textAlign(TextAlign.Center)
.margin({ left: 5, right: 5 })
.borderRadius(this.rectBorderRadius)
.onClick(() =&amp;gt; {
if (this.onItemClick != undefined) {
this.onItemClick(item)
}
})
})
}

Row() {
ForEach(["A", "S", "D", "F", "G", "H", "J", "K", "L"], (item: string) =&amp;gt; {
Text(item)
.layoutWeight(1)
.height(this.rectHeight)
.fontSize(this.rectTextSize)
.fontColor(this.rectTextColor)
.backgroundColor(this.englishBgColor)
.textAlign(TextAlign.Center)
.margin({ left: 5, right: 5 })
.borderRadius(this.rectBorderRadius)
.onClick(() =&amp;gt; {
if (this.onItemClick != undefined) {
this.onItemClick(item)
}
})
})
}.margin({ top: 10, left: 20, right: 20 })

Row() {
ForEach (["middle", "Z", "X", "C", "V", "B", "N", "M", "delete"], (item: string, index: number)=&amp;gt;{
if (index == 8) {
Column() {
Image(this.deleteIconSrc)
.width(this.deleteIconWidth)
}
.layoutWeight(1.5)
.justifyContent(FlexAlign.Center)
.backgroundColor(this.otherBgColor)
.height(this.rectHeight)
.onClick(() =&amp;gt; {
//Delete
if (this.onDelete != undefined) {
this.onDelete()
}
})
} else {
Text(item)
.layoutWeight(index == 0 ? 1.5 : 1)
.height(this.rectHeight)
.fontSize(this.rectTextSize)
.fontColor(this.rectTextColor)
.backgroundColor((index == 0) ?  this.otherBgColor : this.englishBgColor)
.textAlign(TextAlign.Center)
.margin({ left: 5, right: 5 })
.borderRadius(this.rectBorderRadius)
.onClick(() =&amp;gt; {
if (index == 0) {
Chinese
if (this.onChinese != undefined) {
this.onChinese()
}

} else {
if (this.onItemClick != undefined) {
this.onItemClick(item)
}
}
})
}

})
}.margin({ top: 10 })

Row() {
ForEach (["123", "space", "OK"], (item: string, index: number)=&amp;gt;{
Text(item)
.layoutWeight((index == 1) ?  2 : 1)
.height(60)
.backgroundColor(this.otherBgColor)
.textAlign(TextAlign.Center)
.margin({ left: 5, right: 5 })
.borderRadius(this.rectBorderRadius)
.onClick(() =&amp;gt; {
if (index == 0) {
//Number
if (this.onNumber != undefined) {
this.onNumber()
}
} else if (index == 1) {
//Space
if (this.onSpace != undefined) {
this.onSpace()
}
} else if (index == 2) {
//Confirm
if (this.onComplete != undefined) {
this.onComplete()
}
}
})
})
}.margin({ top: 10 })
}.backgroundColor(this.bgColor)
.padding({ top: this.marginTop, bottom: this.marginBottom })
}
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Encapsulation Use 
&lt;/h2&gt;

&lt;p&gt;like the abbreviation of the license plate province, the license plate letters are also packaged for everyone to use. &lt;/p&gt;

&lt;p&gt;Method 1: in the Terminal window, run the following command to install the third-party package. DevEco Studio automatically adds the third-party package dependency to the project oh-package.json5. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Suggestion: Execute the command under the module path used.&lt;/strong&gt;&lt;/p&gt;




&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ohpm install @abner/keyboard
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Method 2: Set the three-party package dependency in the project oh-package.json5. The configuration example is as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"dependencies": { "@abner/keyboard": "^1.0.0"}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Code call
&lt;/h3&gt;

&lt;p&gt;&lt;br&gt;
 &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;EnglishKeyboardView({
onItemClick: (item: string) =&amp;gt; {
//Click on the event
Console.log ("====Click on content:"+item)
},
onDelete: () =&amp;gt; {
//Click to delete
Console.log ("====Click to delete")
},
onComplete: () =&amp;gt; {
//Click OK
Console.log ("====Click OK")
},
onChinese: () =&amp;gt; {
//Click on Chinese to switch
Console.log ("====Click on Chinese to switch")
},
onSpace: () =&amp;gt; {
//Click on the space
Console.log ("====Click on Space")
},
onNumber: () =&amp;gt; {
//Click on the number
Console.log ("====Click on number")
}
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;property Introduction&lt;/strong&gt;&lt;/p&gt;




&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;property&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;type&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;overview&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;onItemClick &lt;/td&gt;
&lt;td&gt;(item: string) =&amp;gt; void &lt;/td&gt;
&lt;td&gt;click entry callback &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;onDelete &lt;/td&gt;
&lt;td&gt;() =&amp;gt; void &lt;/td&gt;
&lt;td&gt;click Delete Callback &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;onComplete &lt;/td&gt;
&lt;td&gt;() =&amp;gt; void &lt;/td&gt;
&lt;td&gt;click Finish Callback &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;onChinese &lt;/td&gt;
&lt;td&gt;() =&amp;gt; void &lt;/td&gt;
&lt;td&gt;click Chinese callback &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;onSpace &lt;/td&gt;
&lt;td&gt;() =&amp;gt; void &lt;/td&gt;
&lt;td&gt;click Space Callback &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;onNumber &lt;/td&gt;
&lt;td&gt;() =&amp;gt; void &lt;/td&gt;
&lt;td&gt;click Digital Callback &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;bgColor &lt;/td&gt;
&lt;td&gt;ResourceColor &lt;/td&gt;
&lt;td&gt;background Color &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;englishBgColor &lt;/td&gt;
&lt;td&gt;ResourceColor &lt;/td&gt;
&lt;td&gt;english background color&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;otherBgColor &lt;/td&gt;
&lt;td&gt;ResourceColor &lt;/td&gt;
&lt;td&gt;non-English background color &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;rectBorderWidth &lt;/td&gt;
&lt;td&gt;Length &lt;/td&gt;
&lt;td&gt;grid Border Width &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;rectBorderRadius &lt;/td&gt;
&lt;td&gt;Length &lt;/td&gt;
&lt;td&gt;check Border Fillet &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;rectTextSize &lt;/td&gt;
&lt;td&gt;Length &lt;/td&gt;
&lt;td&gt;text size of grid &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;rectTextColor &lt;/td&gt;
&lt;td&gt;ResourceColor &lt;/td&gt;
&lt;td&gt;default color for check text &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;deleteIconWidth &lt;/td&gt;
&lt;td&gt;Length &lt;/td&gt;
&lt;td&gt;delete icon width &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;deleteIconSrc &lt;/td&gt;
&lt;td&gt;PixelMap /ResourceStr /DrawableDescriptor &lt;/td&gt;
&lt;td&gt;delete icon resources &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;rectHeight &lt;/td&gt;
&lt;td&gt;Length &lt;/td&gt;
&lt;td&gt;height of each grid &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;marginTop &lt;/td&gt;
&lt;td&gt;Length &lt;/td&gt;
&lt;td&gt;distance from top&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;marginBottom &lt;/td&gt;
&lt;td&gt;Length &lt;/td&gt;
&lt;td&gt;distance from below &lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  related Summary 
&lt;/h2&gt;

&lt;p&gt;there are many ways to implement it. At present, a relatively simple one is adopted. If you adopt the Grid Grid component implementation method, it is also possible, but you need to consider the margin and data of each row, as well as the Grid Occupancy problem of the last two rows.&lt;/p&gt;

</description>
      <category>harmonyos</category>
    </item>
    <item>
      <title>HarmonyOS Development: Customize a Stock Code Selection Keyboard</title>
      <dc:creator>程序员一鸣</dc:creator>
      <pubDate>Mon, 30 Jun 2025 05:02:20 +0000</pubDate>
      <link>https://dev.to/abnerming888/harmonyos-development-customize-a-stock-code-selection-keyboard-2o7f</link>
      <guid>https://dev.to/abnerming888/harmonyos-development-customize-a-stock-code-selection-keyboard-2o7f</guid>
      <description>&lt;h2&gt;
  
  
  Foreword 
&lt;/h2&gt;

&lt;p&gt;this article is based on Api12 &lt;/p&gt;

&lt;p&gt;financial software, especially stock fund applications, will have a keyboard that is different from the normal keyboard when searching for stocks, that is, the stock code keyboard. The difference from the ordinary keyboard is that in addition to common numbers, there are also some common stock code prefix buttons, which are more convenient to search when searching for stocks. &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%2F6ge2vzrblmd9ys30ymf3.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%2F6ge2vzrblmd9ys30ymf3.png" alt="Image description" width="690" height="1480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For such a keyboard, it can be said that it is very easy to implement. We can handle a Grid component. Only the background color setting other than the array should be noted. Of course, you can set it in the form of data source or according to the index position. &lt;/p&gt;

&lt;h2&gt;
  
  
  Code implementation 
&lt;/h2&gt;

&lt;h3&gt;
  
  
  defining Data Sources 
&lt;/h3&gt;

&lt;p&gt;data source definition can be defined by single data, that is, only the required string is defined, but the background switching needs to be set according to the index, or it can be defined directly in the form of object array. The required content and background color can be defined in the object. Both methods can be implemented. Currently, the first method is adopted.&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;private mCodeList = ["600", "1", "2", "3", "", "601", "4", "5", "6", "隐藏",
    "000", "7", "8", "9", "empty", "300", "002", "603", "0", "确定"]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Set Components 
&lt;/h3&gt;

&lt;p&gt;since the data is set in the form of a string array, when setting the background color, it is necessary to set it dynamically according to the index position.&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;Grid() {
ForEach(this.mCodeList, (item: string, index: number) =&amp;gt; {
GridItem() {
Column() {
if (index == 4) {
Image(this.deleteIconSrc)
.width(this.deleteIconWidth)
} else {
Text(item)
.fontSize(this.rectTextSize)
.fontColor(this.rectTextColor)
}
}
.width("100%")
.height(this.rectHeight)
.border({ radius: this.rectBorderRadius })
.backgroundColor((index == 1 || index == 2 || index == 3 ||
index == 6 || index == 7 || index == 8 ||
index == 11 || index == 12 || index == 13 || index == 18) ?  this.numberColor : this.notNumberColor)
.justifyContent(FlexAlign.Center)
.onClick(() =&amp;gt; {
//Click on the event
if (index == 4) {
//Delete
if (this.onDelete != undefined) {
this.onDelete()
}
} else if (index == 9) {
//Hide
if (this.onHide != undefined) {
this.onHide()
}
} else if (index == 14) {
//Clear out
if (this.onClear != undefined) {
this.onClear()
}
} else if (index == this.mCodeList.length - 1) {
//Confirm
if (this.onConfirm != undefined) {
this.onConfirm()
}
} else {
if (this.onItemClick != undefined) {
this.onItemClick(item, index)
}
}
})
}
})
}
.columnsTemplate("1fr ".repeat(this.columnSize).trimEnd())
.columnsGap(this.columnsGap)
.rowsGap(this.rowsGap)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  All codes: 
&lt;/h2&gt;

&lt;p&gt;the code is very simple, just a pure Grid component is implemented, so I won't repeat it here.&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;@Component
export struct StockCodeView {
Private mCodeList=["600", "1", "2", "3", "", "601", "4", "5", "6", "hidden",
000 "," 7 "," 8 "," 9 "," Clear "," 300 "," 002 "," 603 "," 0 "," OK "]
BgColor: ResourceColor="# e8e8e8"//Background color
CodeBgColor: ResourceColor="# e8e8e8"//code background color
Number Color: ResourceColor=Color. White//Number background color
NotNumberColor: ResourceColor="# 999999"//Not a numerical background color
RootHeight: number=0//The overall height of the keyboard
RectHeight: Length=60//Each grid height
RowsGap: Length=10//Line spacing
ColumnsMap: Length=10//Column spacing
GridMarkinTop: Length=10//Grid distance from top
GridMarkinBottom: Length=10//Grid distance from bottom
RectBorderRadius: Length=2//Grid border rounded corners
onItemClick? : (item: string, index: number)=&amp;gt;void//Click on the item
onDelete? : ()=&amp;gt;void//Click to delete
onHide? : ()=&amp;gt;void//Click to hide
onClear? : ()=&amp;gt;void//Click to clear
onConfirm? : ()=&amp;gt;void//Click confirm
ColumnSize: number=5//Display how many columns, default is 5 columns
MarginLeft: Length=10//Distance to the left
MarginRight: Length=10//Distance to the right
DeleteIconWidth: Length=30//Delete image width
deleteIconSrc: PixelMap | ResourceStr | DrawableDescriptor = $r("app.media.view_ic_key_delete")
RectTextCize: Length=16//The text size of the grid
RectTextColor: ResourceColor="# 333333"//Default color for grid text

aboutToAppear(): void {
this.rootHeight = (Number(this.rectHeight) * 4) + Number(this.rowsGap) * 3
+ Number(this.gridMarginTop) + Number(this.gridMarginBottom)
}

build() {
Grid() {
ForEach(this.mCodeList, (item: string, index: number) =&amp;gt; {
GridItem() {
Column() {
if (index == 4) {
Image(this.deleteIconSrc)
.width(this.deleteIconWidth)
} else {
Text(item)
.fontSize(this.rectTextSize)
.fontColor(this.rectTextColor)
}
}
.width("100%")
.height(this.rectHeight)
.border({ radius: this.rectBorderRadius })
.backgroundColor((index == 1 || index == 2 || index == 3 ||
index == 6 || index == 7 || index == 8 ||
index == 11 || index == 12 || index == 13 || index == 18) ?  this.numberColor : this.notNumberColor)
.justifyContent(FlexAlign.Center)
.onClick(() =&amp;gt; {
//Click on the event
if (index == 4) {
//Delete
if (this.onDelete != undefined) {
this.onDelete()
}
} else if (index == 9) {
//Hide
if (this.onHide != undefined) {
this.onHide()
}
} else if (index == 14) {
//Clear out
if (this.onClear != undefined) {
this.onClear()
}
} else if (index == this.mCodeList.length - 1) {
//Confirm
if (this.onConfirm != undefined) {
this.onConfirm()
}
} else {
if (this.onItemClick != undefined) {
this.onItemClick(item, index)
}
}
})
}
})
}
.columnsTemplate("1fr ".repeat(this.columnSize).trimEnd())
.columnsGap(this.columnsGap)
.rowsGap(this.rowsGap)
.padding({ left: this.marginLeft, right: this.marginRight, top: this.gridMarginTop })
.backgroundColor(this.bgColor)
.height(this.rootHeight)
}
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Encapsulation Use 
&lt;/h2&gt;

&lt;p&gt;like the abbreviation of the license plate province, the license plate letters are also packaged for everyone to use.&lt;/p&gt;

&lt;p&gt;Method 1: in the Terminal window, run the following command to install the third-party package. DevEco Studio automatically adds the third-party package dependency to the project oh-package.json5. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Suggestion: Execute the command under the module path used.&lt;/strong&gt;&lt;/p&gt;






&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ohpm install @abner/keyboard
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Method 2: Set the three-party package dependency in the project oh-package.json5. The configuration example 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;"dependencies": { "@abner/keyboard": "^1.0.0"}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  code call
&lt;/h3&gt;

&lt;p&gt;&lt;br&gt;
 &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;StockCodeView({
onItemClick: (item: string, index: number) =&amp;gt; {
//Click on the event
Console.log ("===Click on content:"+item+"==Click on index:"+index)
},
onDelete: () =&amp;gt; {
//Click to delete
Console.log ("====Click to delete")
},
onHide: () =&amp;gt; {
//Click to hide
Console.log ("====Click to hide")
},
onClear: () =&amp;gt; {
//Click to clear
Console.log ("====Click to clear")
},
onConfirm: () =&amp;gt; {
//Click confirm
Console.log ("====Click to confirm")
}
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;property Introduction&lt;/strong&gt;&lt;/p&gt;




&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;property&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;type&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;overview&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;onItemClick &lt;/td&gt;
&lt;td&gt;(item: string, index: number) =&amp;gt; void &lt;/td&gt;
&lt;td&gt;click entry callback &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;onDelete &lt;/td&gt;
&lt;td&gt;() =&amp;gt; void &lt;/td&gt;
&lt;td&gt;click Delete Callback &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;onHide &lt;/td&gt;
&lt;td&gt;() =&amp;gt; void &lt;/td&gt;
&lt;td&gt;click to hide the callback &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;onClear &lt;/td&gt;
&lt;td&gt;() =&amp;gt; void &lt;/td&gt;
&lt;td&gt;click Clear Callback &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;onConfirm &lt;/td&gt;
&lt;td&gt;() =&amp;gt; void &lt;/td&gt;
&lt;td&gt;click to confirm callback &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;bgColor &lt;/td&gt;
&lt;td&gt;ResourceColor&lt;/td&gt;
&lt;td&gt;Background Color &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;codeBgColor &lt;/td&gt;
&lt;td&gt;ResourceColor &lt;/td&gt;
&lt;td&gt;code Background Color &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;numberColor &lt;/td&gt;
&lt;td&gt;ResourceColor &lt;/td&gt;
&lt;td&gt;digital background color &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;notNumberColor &lt;/td&gt;
&lt;td&gt;ResourceColor &lt;/td&gt;
&lt;td&gt;not a digital background color &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;rootHeight &lt;/td&gt;
&lt;td&gt;number &lt;/td&gt;
&lt;td&gt;overall height of the keyboard &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;rectHeight &lt;/td&gt;
&lt;td&gt;Length &lt;/td&gt;
&lt;td&gt;height of each grid &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;rowsGap &lt;/td&gt;
&lt;td&gt;Length &lt;/td&gt;
&lt;td&gt;line Spacing &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;columnsGap &lt;/td&gt;
&lt;td&gt;Length &lt;/td&gt;
&lt;td&gt;column Spacing &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;gridMarginTop &lt;/td&gt;
&lt;td&gt;Length &lt;/td&gt;
&lt;td&gt;grid Distance Top &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;gridMarginBottom &lt;/td&gt;
&lt;td&gt;Length &lt;/td&gt;
&lt;td&gt;grid Distance Bottom &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;rectBorderRadius&lt;/td&gt;
&lt;td&gt;Length &lt;/td&gt;
&lt;td&gt;check Border Fillet &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;marginLeft &lt;/td&gt;
&lt;td&gt;Length &lt;/td&gt;
&lt;td&gt;distance to the left &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;marginRight &lt;/td&gt;
&lt;td&gt;Length &lt;/td&gt;
&lt;td&gt;distance to the right &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;deleteIconWidth &lt;/td&gt;
&lt;td&gt;Length &lt;/td&gt;
&lt;td&gt;delete icon width &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;deleteIconSrc &lt;/td&gt;
&lt;td&gt;PixelMap / ResourceStr / DrawableDescriptor &lt;/td&gt;
&lt;td&gt;delete icon resources &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;rectTextSize &lt;/td&gt;
&lt;td&gt;Length &lt;/td&gt;
&lt;td&gt;checker text size &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;rectTextColor &lt;/td&gt;
&lt;td&gt;ResourceColor &lt;/td&gt;
&lt;td&gt;default color for check text&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

</description>
      <category>harmonyos</category>
    </item>
    <item>
      <title>HarmonyOS Development: Customize a License Plate Letter Keyboard</title>
      <dc:creator>程序员一鸣</dc:creator>
      <pubDate>Mon, 30 Jun 2025 05:01:28 +0000</pubDate>
      <link>https://dev.to/abnerming888/harmonyos-development-customize-a-license-plate-letter-keyboard-c0c</link>
      <guid>https://dev.to/abnerming888/harmonyos-development-customize-a-license-plate-letter-keyboard-c0c</guid>
      <description>&lt;h2&gt;
  
  
  Foreword 
&lt;/h2&gt;

&lt;p&gt;this article is based on Api12 &lt;/p&gt;

&lt;p&gt;before, I customized the keyboard for the short name of a license plate province. In fact, it is not enough to have the short name of a province. After all, a normal license plate is composed of the short name of a province + letters + numbers. Just customize a license plate letter selection keyboard, which can be used in combination with the short name keyboard of the previous province. &lt;/p&gt;

&lt;p&gt;Let's look at the final effect. &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%2Fwfdz3cmjdlctdh0lg9zo.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%2Fwfdz3cmjdlctdh0lg9zo.png" alt="Image description" width="686" height="1476"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Analysis of implementation 
&lt;/h2&gt;

&lt;p&gt;for such a letter and number keyboard, it can be said that there are many ways to implement it. We can roughly divide it into three parts. The top part is the finish button, the bottom part is a row of number buttons, and the bottom part is the letter area. The reason why numbers and letters are separated is that the margins of the main two parts are different and it is easier to separate them. When drawing letters, one thing needs attention, that is, the final delete button is going to occupy two squares. &lt;/p&gt;

&lt;h3&gt;
  
  
  Number Button 
&lt;/h3&gt;

&lt;p&gt;there is nothing to say about a row of numbers. Grid is used here to implement it. 10 columns are set. Of course, you can also use other methods to implement it. &lt;/p&gt;

&lt;p&gt;Defining Data Sources&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;mNumberList = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "0"]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;code implementation&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;Grid() {
        ForEach(this.mNumberList, (item: string, index: number) =&amp;gt; {
          GridItem() {
            Text(item)
              .fontSize(this.rectTextSize)
              .fontColor(this.numProhibit ? this.numProhibitColor :
                (this.itemSelectedArray[index] ? this.rectSelectTextColor : this.rectTextColor))
          }.GridItemAttribute(this, index, item)
        })
      }
      .height(this.rectHeight)
      .columnsTemplate("1fr ".repeat(10).trimEnd())
      .columnsGap(this.columnsGap)
      .rowsGap(this.rowsGap)
      .margin({ top: this.gridMarginTop })
      .scrollBar(BarState.Off)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  letter button 
&lt;/h3&gt;

&lt;p&gt;the letter button is similar to the number implementation and is also a Grid component. One difference is that the final delete button needs to occupy two squares. How to occupy two squares? The second parameter layoutOptions of the Grid component is mainly used. We use it to implement the final delete button placement.&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; (scroller?: Scroller, layoutOptions?: GridLayoutOptions): GridAttribute;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Set the last delete button to occupy two spaces.&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; layoutOptions: GridLayoutOptions = {
    regularSize: [1, 1],
    irregularIndexes: [this.mEnglishList.length - 1],
    onGetIrregularSizeByIndex: (_: number) =&amp;gt; {
      return [1, 2]
    }
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Data Source&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;mEnglishList = [
    "Q", "W", "E", "R", "T", "Y", "U", "O", "P",
    "A", "S", "D", "F", "G", "H", "J", "K", "L",
    "Z", "X", "C", "V", "B", "N", "M", ""]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;code implementation&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;Grid(undefined, this.layoutOptions) {
        ForEach(this.mEnglishList, (item: string, index: number) =&amp;gt; {
          GridItem() {
            if (index == this.mEnglishList.length - 1) {
              Row() {
                Column() {
                  Image(this.deleteIconSrc)
                    .width(this.deleteIconWidth)
                }
                .width("100%")
                .height("100%")
                .backgroundColor(Color.White)
                .borderRadius(2)
                .justifyContent(FlexAlign.Center)
              }
              .width("100%")
              .height("100%")
              .justifyContent(FlexAlign.End)
            } else {
              Text(item)
                .fontSize(this.rectTextSize)
                .fontColor(this.itemSelectedArray[index+this.mNumberList.length] ? this.rectSelectTextColor :
                this.rectTextColor)
            }
          }.GridItemAttribute(this, index + this.mNumberList.length, item)

        }, (item: string, index: number) =&amp;gt; JSON.stringify(item) + "_" + index)
      }
      .columnsTemplate("1fr ".repeat(this.columnSize).trimEnd())
      .columnsGap(this.columnsGap)
      .rowsGap(this.rowsGap)
      .margin({ top: Number(this.gridMarginTop) + 10, left: 15, right: 15 })
      .scrollBar(BarState.Off)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  encapsulation Use
&lt;/h2&gt;

&lt;p&gt;Like the abbreviation of the license plate province, the license plate letters are also packaged for everyone to use. &lt;/p&gt;

&lt;p&gt;Method 1: in the Terminal window, run the following command to install the third-party package. DevEco Studio automatically adds the third-party package dependency to the project oh-package.json5. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Suggestion: Execute the command under the module path used.&lt;/strong&gt;&lt;/p&gt;






&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ohpm install @abner/keyboard
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Method 2: Set the three-party package dependency in the project oh-package.json5. The configuration example 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;"dependencies": { "@abner/keyboard": "^1.0.0"}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  code call
&lt;/h3&gt;

&lt;p&gt;&lt;br&gt;
 &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;LicensePlateLetterView({
onItemClick: (item: string, index: number) =&amp;gt; {
//Click on the event
Console.log ("===Click on content:"+item+"==Click on index:"+index)
},
onDelete: () =&amp;gt; {
//Click to delete
Console.log ("====Click to delete")
}
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  related Properties 
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;property&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;type&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;overview&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;onItemClick &lt;/td&gt;
&lt;td&gt;(item: string, index: number) =&amp;gt; void &lt;/td&gt;
&lt;td&gt;click entry callback &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;onDelete &lt;/td&gt;
&lt;td&gt;() =&amp;gt; void &lt;/td&gt;
&lt;td&gt;click Delete Callback &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;onComplete &lt;/td&gt;
&lt;td&gt;(item: string) =&amp;gt; void &lt;/td&gt;
&lt;td&gt;click Finish Callback &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;rowsGap &lt;/td&gt;
&lt;td&gt;Length &lt;/td&gt;
&lt;td&gt;line Spacing &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;columnsGap &lt;/td&gt;
&lt;td&gt;Length &lt;/td&gt;
&lt;td&gt;column Spacing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;columnSize &lt;/td&gt;
&lt;td&gt;number &lt;/td&gt;
&lt;td&gt;show several columns, the default is 10 columns &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;bgColor &lt;/td&gt;
&lt;td&gt;ResourceColor &lt;/td&gt;
&lt;td&gt;background Color &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;marginLeft &lt;/td&gt;
&lt;td&gt;Length &lt;/td&gt;
&lt;td&gt;distance to the left &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;marginRight &lt;/td&gt;
&lt;td&gt;Length &lt;/td&gt;
&lt;td&gt;distance to the right &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;rectHeight &lt;/td&gt;
&lt;td&gt;Length &lt;/td&gt;
&lt;td&gt;height of each grid &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;titleHeight &lt;/td&gt;
&lt;td&gt;Length &lt;/td&gt;
&lt;td&gt;title Bar Height &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;rootHeight &lt;/td&gt;
&lt;td&gt;Length &lt;/td&gt;
&lt;td&gt;overall height of the keyboard &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;gridMarginTop &lt;/td&gt;
&lt;td&gt;Length &lt;/td&gt;
&lt;td&gt;grid Distance Top &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;gridMarginBottom &lt;/td&gt;
&lt;td&gt;Length &lt;/td&gt;
&lt;td&gt;grid Distance Bottom &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;completeTextColor &lt;/td&gt;
&lt;td&gt;ResourceColor&lt;/td&gt;
&lt;td&gt;The color of the finish button &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;completeFontSize &lt;/td&gt;
&lt;td&gt;number/string/ Resource &lt;/td&gt;
&lt;td&gt;finish text size &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;isShowComplete &lt;/td&gt;
&lt;td&gt;boolean &lt;/td&gt;
&lt;td&gt;show Finish button &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;rectBgColor &lt;/td&gt;
&lt;td&gt;ResourceColor &lt;/td&gt;
&lt;td&gt;lattice Background &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;rectSelectBgColor &lt;/td&gt;
&lt;td&gt;ResourceColor &lt;/td&gt;
&lt;td&gt;check background &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;rectBorderWidth &lt;/td&gt;
&lt;td&gt;Length &lt;/td&gt;
&lt;td&gt;grid Border Width &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;rectBorderRadius &lt;/td&gt;
&lt;td&gt;Length &lt;/td&gt;
&lt;td&gt;check Fillet &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;rectBorderColor &lt;/td&gt;
&lt;td&gt;ResourceColor &lt;/td&gt;
&lt;td&gt;check Border Color &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;rectBorderSelectColor &lt;/td&gt;
&lt;td&gt;ResourceColor &lt;/td&gt;
&lt;td&gt;check Border Color &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;rectTextSize&lt;/td&gt;
&lt;td&gt;Length &lt;/td&gt;
&lt;td&gt;text size of grid &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;rectTextColor &lt;/td&gt;
&lt;td&gt;Length &lt;/td&gt;
&lt;td&gt;default color for check text &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;rectSelectTextColor &lt;/td&gt;
&lt;td&gt;ResourceColor &lt;/td&gt;
&lt;td&gt;checked color for check text &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;numProhibit &lt;/td&gt;
&lt;td&gt;boolean &lt;/td&gt;
&lt;td&gt;whether to ban numbers &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;numProhibitColor &lt;/td&gt;
&lt;td&gt;ResourceColor &lt;/td&gt;
&lt;td&gt;prohibit Text Color &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;deleteIconWidth &lt;/td&gt;
&lt;td&gt;Length &lt;/td&gt;
&lt;td&gt;delete image width &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;deleteIconSrc &lt;/td&gt;
&lt;td&gt;PixelMap/ResourceStr/ DrawableDescriptor &lt;/td&gt;
&lt;td&gt;delete icon resources &lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  related Summary 
&lt;/h2&gt;

&lt;p&gt;there is a big difference between the license plate letter keyboard and the general keyboard. You can find that there is one letter missing on the keyboard. Because the I letter is confusing, this letter is not in the license plate keyboard.&lt;/p&gt;

</description>
      <category>harmonyos</category>
    </item>
    <item>
      <title>HarmonyOS Yuan service project actual combat: the end of the memo search function to achieve.</title>
      <dc:creator>程序员一鸣</dc:creator>
      <pubDate>Mon, 30 Jun 2025 05:00:31 +0000</pubDate>
      <link>https://dev.to/abnerming888/harmonyos-yuan-service-project-actual-combat-the-end-of-the-memo-search-function-to-achieve-3i7c</link>
      <guid>https://dev.to/abnerming888/harmonyos-yuan-service-project-actual-combat-the-end-of-the-memo-search-function-to-achieve-3i7c</guid>
      <description>&lt;h2&gt;
  
  
  Foreword 
&lt;/h2&gt;

&lt;p&gt;this article is based on Api12 &lt;/p&gt;

&lt;p&gt;in fact, in the first three articles, we have already realized all the functions to be realized. Whether it is list display, data editing, style modification, skin changing, etc., we have reached a deliverable state. Of course, the current small project has also been put on the application store of Hongmeng System. The name is "Follow Your Heart". Everyone can experience it while doing the project. This article, I will realize the search function of the last point, and summarize the knowledge points used in this small project. &lt;/p&gt;

&lt;p&gt;We can simply look at the results that have been completed so far. &lt;/p&gt;

&lt;p&gt;On the first page of the memo, the color of the item is linked with the skin. &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%2Fqz99n2pwtxjpzz4p54cn.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%2Fqz99n2pwtxjpzz4p54cn.png" alt="Image description" width="688" height="1480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Content editing page, you can set the style and skin. &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%2F481zji5qjmtjj0drs4b5.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%2F481zji5qjmtjj0drs4b5.png" alt="Image description" width="688" height="1480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Search function implementation 
&lt;/h2&gt;

&lt;p&gt;at present, the search function is bound to the list page. First, it shares components to reduce pages and codes. Second, its function is not complicated and it is more intuitive to merge into one page. &lt;/p&gt;

&lt;p&gt;Click the search box, enter the content to search, filter out the data matching the search content for display, click the cross on the right side of the search box, and restore all the data. &lt;/p&gt;

&lt;p&gt;For the previous list data loading, we only need to modify it, add key search terms, pass them during search, and do not pass them during other calls, and use the filter function to filter and search for matching data.&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;doData(keyWord?: string) {
    try {
      this.doContentEmpty()
      this.mListContentBean = []
      DataPreferences.getInstance().getAllSync().allKeys?.forEach((key) =&amp;gt; {
        let content = DataPreferences.getInstance().getSync&amp;lt;string&amp;gt;(key)
        let bean = JSON.parse(content) as ListContentBean
        this.mListContentBean.push(bean)
        if (DataPreferences.getInstance().getAllSync().allKeys?.length == this.mListContentBean.length) {

          this.mListContentBean.sort((a, b) =&amp;gt; b.timeValue! - a.timeValue!)

          if (keyWord != undefined) {
            this.mListContentBean = this.mListContentBean.filter(item =&amp;gt; item.title?.indexOf(keyWord) != -1);
          }
        }
      })
    } catch (e) {
    }
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;UI components&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Search({ placeholder: "search……" })
        .margin({ left: 10, right: 10, top: 10 })
        .onSubmit((value) =&amp;gt; {
          //search
          this.doData(value)
        })
        .onChange((value: string, _?: PreviewText) =&amp;gt; {
          if (value == "") {
            //clear
            this.doData()
          }
        })
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  memorandum of Knowledge
&lt;/h2&gt;

&lt;p&gt;This memo project does not contain many knowledge points. There are two aspects of knowledge points that can be practiced. The first aspect is UI component-related, such as the use of List component, Search component, and rich text component RichEditor. In addition to these typical components, there are also many basic components. &lt;/p&gt;

&lt;p&gt;The second aspect is the function. We can practice the addition, deletion, modification and check of user preference DataPreferences data, the avoidance between input box and soft keyboard, and the saving of page data and the echo of page data. &lt;/p&gt;

&lt;h2&gt;
  
  
  Related Summary 
&lt;/h2&gt;

&lt;p&gt;there are many restrictive factors in the development of meta-services, such as package size restrictions and related API restrictions. Therefore, when we actually develop, we still need to check whether the specific Api can be used in official website. At present, we have summarized several minor problems for the current small project, which can be used as a reference in the development process. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to realize the bottom button, after the soft keyboard pops up, it is displayed on the soft keyboard?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Answer: Get the height of the soft keyboard, and dynamically set the components that need to be changed according to the pop-up and hiding of the soft keyboard. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Meta-service, using user preferences DataPreferences for data storage, how to store in the form of a list?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Answer: You only need to set different keys. When obtaining, you can traverse all keys and obtain the corresponding data with keys. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How should RichEditor echo data correctly?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A: After RichEditor initialization is complete  &lt;strong&gt;,&lt;/strong&gt; for example, in the onReady method.&lt;/p&gt;

</description>
      <category>harmonyos</category>
    </item>
    <item>
      <title>HarmonyOS Yuan Service Project Actual Combat: Memorandum Implementation List Display</title>
      <dc:creator>程序员一鸣</dc:creator>
      <pubDate>Mon, 30 Jun 2025 04:59:25 +0000</pubDate>
      <link>https://dev.to/abnerming888/harmonyos-yuan-service-project-actual-combat-memorandum-implementation-list-display-l2b</link>
      <guid>https://dev.to/abnerming888/harmonyos-yuan-service-project-actual-combat-memorandum-implementation-list-display-l2b</guid>
      <description>&lt;h2&gt;
  
  
  Foreword 
&lt;/h2&gt;

&lt;p&gt;this article is based on Api12 &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%2F9k9gdvn1gsgga98z3puq.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%2F9k9gdvn1gsgga98z3puq.png" alt="Image description" width="684" height="1474"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;in the first two chapters, we have already realized all the logic of UI and editing pages. In this article, we will focus on the following list Display. After all, there are data. How to disaggregate and display them in a friendly way is the most important. After all, each memo needs a designated entrance. &lt;/p&gt;

&lt;p&gt;Display list, one is to display by default, and the other is to update list data after editing the editing page. Both situations need to be considered in actual development. Since the database is not used to store data at present, paging is slightly complicated to implement, and general memos will not have a large amount of data, except for special circumstances, of course, here we will discard paging first and directly obtain all of it, in actual APP projects or networking operations, for the sake of performance, try to make paging loading. &lt;/p&gt;

&lt;p&gt;Another point to note is that the edited or modified memo content, the user preference DataPreferences used when saving, is not sorted by time, so when we display the list, we need to sort according to the timestamp of the content, so that the latest edited content is displayed at the front.&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; this.mListContentBean.sort((a, b) =&amp;gt; b.timeValue! - a.timeValue!)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Data presentation 
&lt;/h2&gt;

&lt;p&gt;at present, all the data is taken from the user's preferences, that is, the data saved in the editing page. Here, all the keys are directly traversed, all the data are obtained, and then converted into the objects we need, which is convenient for us to render the data. One thing needs to be noted, that is, the sorting mentioned above is currently carried out according to the timestamp.&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;doData() {
    try {
      this.doContentEmpty()
      this.mListContentBean = []
      DataPreferences.getInstance().getAllSync().allKeys?.forEach((key) =&amp;gt; {
        let content = DataPreferences.getInstance().getSync&amp;lt;string&amp;gt;(key)
        let bean = JSON.parse(content) as ListContentBean
        this.mListContentBean.push(bean)
        if (DataPreferences.getInstance().getAllSync().allKeys?.length == this.mListContentBean.length) {
          //sort
          this.mListContentBean.sort((a, b) =&amp;gt; b.timeValue! - a.timeValue!)
        }
      })
    } catch (e) {
    }
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Data Echo 
&lt;/h2&gt;

&lt;p&gt;with the data, when we click on the entry to view, there are many ways to deal with it, one is to view it directly, and the other is to echo it to the edit page, that is, to view and modify it together. Here we choose the second one. After clicking on the entry, it will echo to the edit page.&lt;/p&gt;

&lt;p&gt;Click, data transfer.&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;router.pushUrl({
              url: "pages/EditPage", params: {
                "data": JSON.stringify(item)
              }
            })
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To edit the page, we need to wait for RichEditor initialization before rendering data. We can set it in the onReady method.&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;RichEditor(this.options)
          .onReady(() =&amp;gt; {
            if (router.getParams() != undefined) {
              let params = JSON.stringify(router.getParams())
              let bean = JSON.parse(JSON.parse(params)["data"]) as ListContentBean
              this.title = bean.title!
              this.nowTime = bean.time!
              this.clickSkinColorValue = bean.bgColor!
              this.tempContentItemId = bean.id!

              if (bean.content != undefined) {
                let array = JSON.parse(bean.content) as Array&amp;lt;RichEditorTextSpanResult&amp;gt;
                array.forEach((item) =&amp;gt; {
                  this.controller.addTextSpan(item.value, {
                    style: {
                      fontColor: item.textStyle.fontColor,
                      fontSize: item.textStyle.fontSize,
                      fontStyle: item.textStyle.fontStyle,
                      fontFamily: item.textStyle.fontFamily,
                      fontFeature: item.textStyle.fontFeature,
                      fontWeight: item.textStyle.fontWeight &amp;gt; 10 ? FontWeight.Bold : FontWeight.Normal
                    }
                  })
                })
              }

            } else {
              //time
              this.nowTime = this.getDateTime()
              this.nowInterval = setInterval(() =&amp;gt; {
                this.nowTime = this.getDateTime()
              }, 1000)
            }

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Data deletion 
&lt;/h2&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%2F121dxoc5q1hr534we21d.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%2F121dxoc5q1hr534we21d.png" alt="Image description" width="800" height="526"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;for data deletion, the sideslip method we use here can directly use the swipeAction attribute in the List component. &lt;/p&gt;

&lt;p&gt;Delete, delete list array data, delete data in user preferences, and determine the default page display if there is no data currently.&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;DataPreferences.getInstance().delete("abner" + id, (isSuccess: boolean) =&amp;gt; {
          if (isSuccess) {
            _this.mListContentBean.splice(index, 1)
            this.doContentEmpty()
          }
        })
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Related Summary 
&lt;/h2&gt;

&lt;p&gt;counting this article, the memo project has already output 90%, basically covering the editing, display, Echo, storage and so on of the data. A small note-taking project has been completed. Of course, there is still one search to go. We put it in the last article. &lt;/p&gt;

&lt;p&gt;At present, it is only the storage of text. In the actual memo, there are many functions, such as pictures, such as drawing, such as tables, etc. Of course, we need to implement them step by step.&lt;/p&gt;

</description>
      <category>harmonyos</category>
    </item>
    <item>
      <title>HarmonyOS Yuan Service Project Actual Combat: Memorandum Content Editing and Development</title>
      <dc:creator>程序员一鸣</dc:creator>
      <pubDate>Mon, 30 Jun 2025 04:58:14 +0000</pubDate>
      <link>https://dev.to/abnerming888/harmonyos-yuan-service-project-actual-combat-memorandum-content-editing-and-development-55j8</link>
      <guid>https://dev.to/abnerming888/harmonyos-yuan-service-project-actual-combat-memorandum-content-editing-and-development-55j8</guid>
      <description>&lt;h2&gt;
  
  
  Foreword 
&lt;/h2&gt;

&lt;p&gt;this article is based on Api12 &lt;/p&gt;

&lt;p&gt;in the previous article, we have completed the main UI. In this article, we have completed the main function editing page. The so-called memo is to record the content. Of course, the content is not limited to text, pictures, styles, etc. The first version can only realize the text, and then continue to expand. &lt;/p&gt;

&lt;p&gt;There are three key points to realize the development of editing pages. The first is to write rich text content, the second is to modify the style of content, and the third is to store content. &lt;/p&gt;

&lt;p&gt;By the way, the current article corresponds &lt;strong&gt;remember&lt;/strong&gt; meta-service items have been put on the shelves and can be searched in the application store. &lt;strong&gt;Remember&lt;/strong&gt; can experience. &lt;/p&gt;

&lt;h2&gt;
  
  
  Rich Text Content Writing 
&lt;/h2&gt;

&lt;p&gt;Rich text content editing we can directly use the RichEditor component, the most important is the parameter, value: RichEditorOptions, through which we can set the style, and get the final rich text content, this is very important. &lt;/p&gt;

&lt;h3&gt;
  
  
  Defining Initialization Parameters
&lt;/h3&gt;

&lt;p&gt;&lt;br&gt;
 &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;controller: RichEditorController = new RichEditorController();
options: RichEditorOptions = { controller: this.controller };
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  set Initialization Parameters
&lt;/h3&gt;

&lt;p&gt;&lt;br&gt;
 &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;RichEditor(this.options)
          .onReady(() =&amp;gt; {
            //time
            this.nowTime = this.getDateTime()
            this.nowInterval = setInterval(() =&amp;gt; {
              this.nowTime = this.getDateTime()
            }, 1000)

          })
          .placeholder("Take notes at will, record every little bit", {
            fontColor: "#666666"
          })
          .caretColor(Color.Red)
          .padding(10)
          .margin({ top: 10 })
          .onSelect((value: RichEditorSelection) =&amp;gt; {
            this.start = value.selection[0];
            this.end = value.selection[1];
          })
      }
      .alignRules({
        top: { anchor: "bar", align: VerticalAlign.Bottom },
        bottom: { anchor: "bottom_bar", align: VerticalAlign.Top }
      }).margin({ bottom: 80 })
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  content Style Modification 
&lt;/h2&gt;

&lt;p&gt;all content style modifications are made using the initialization parameters of there are two situations for the rich text controller to set, the first is to directly click on the style and then write the content, and the other is to set the style after long pressing on the original content. &lt;/p&gt;

&lt;p&gt;For example, if I click the bold style first and then enter the text, then the entered text is bold and will return to normal only after the bold is canceled.&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%2Futpro1koi5mdp5mfifwg.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%2Futpro1koi5mdp5mfifwg.png" alt="Image description" width="688" height="1466"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The second is to adjust the style after long-pressing the selected text in the original text. The following bold style requires attention, because the specified text style needs to be set and the starting position of the current long-pressed text needs to be obtained, that is, the onSelect method in the above code. &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%2Fesjwzs6l6phpo8hoqvgx.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%2Fesjwzs6l6phpo8hoqvgx.png" alt="Image description" width="690" height="1484"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Of course, it's not just bolding, any style is basically these two situations. In addition, it's also very important to keep the previous style before modifying the style, for example, if the text becomes larger, bolding, and changing the color, then you modify the current style, only the current style, and cannot overwrite or discard the previous style. &lt;/p&gt;

&lt;p&gt;As shown below, change the font size and color of the selected content, then the original bold is still retained. &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%2Fi01rylgyd5s588asbi14.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%2Fi01rylgyd5s588asbi14.png" alt="Image description" width="682" height="1470"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Bold Text
&lt;/h3&gt;

&lt;p&gt;&lt;br&gt;
 &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;private setBold() {
    if (this.start != -1 &amp;amp;&amp;amp; this.end != -1) {
      this.controller.updateSpanStyle({
        start: this.start,
        end: this.end,
        textStyle: {
          fontWeight: FontWeight.Bolder
        }
      })
    }
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  text size
&lt;/h3&gt;

&lt;p&gt;&lt;br&gt;
 &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;private setFontSize() {
    if (this.start != -1 &amp;amp;&amp;amp; this.end != -1) {
      this.controller.updateSpanStyle({
        start: this.start,
        end: this.end,
        textStyle: {
          fontSize: this.clickStyleSizeValue
        }
      })
    }
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  text skew
&lt;/h3&gt;

&lt;p&gt;&lt;br&gt;
 &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;private setStyle() {
    if (this.start != -1 &amp;amp;&amp;amp; this.end != -1) {
      this.controller.updateSpanStyle({
        start: this.start,
        end: this.end,
        textStyle: {
          fontStyle: FontStyle.Italic
        }
      })
    }
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  text color
&lt;/h3&gt;

&lt;p&gt;&lt;br&gt;
 &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;private setFontColor() {
    if (this.start != -1 &amp;amp;&amp;amp; this.end != -1) {
      this.controller.updateSpanStyle({
        start: this.start,
        end: this.end,
        textStyle: {
          fontColor: this.clickStyleColorValue
        }
      })
    }
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;before changing the specified style, we need to set the previously set style so that each style can be consistent.&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;  private changeStyle() {
    this.controller.setTypingStyle({
      fontWeight: this.isClickStyleB ? FontWeight.Bold : FontWeight.Normal,
      fontStyle: this.isClickStyleI ? FontStyle.Italic : FontStyle.Normal,
      fontColor: this.clickStyleColorValue,
      fontSize: this.clickStyleSizeValue
    })
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Content Storage 
&lt;/h2&gt;

&lt;p&gt;after editing the content, what we need to do is to store the content. After all, we are a stand-alone application and do not involve the network, so we can only choose the local storage method. &lt;/p&gt;

&lt;p&gt;There are many ways to store data, such as databases, files, memory storage, etc. In the development of meta-services, it is not to use whichever you want, but to use whichever you support. At present, check official website and find that ohos.data.preferences (user preferences) are supported. We can use it to simply store our data. Of course, there is no support for meta-services on the official website of the database. There is no verification at present. If it is supported in the future, try to use the database. &lt;/p&gt;

&lt;p&gt;UseFor user preferences, it should be noted that the dynamic setting of key can use the current timestamp as the key, while the corresponding value value is a json string, which contains attributes such as title, time, content, background color, etc. &lt;/p&gt;

&lt;p&gt;User preferences currently encapsulate the tool class, you can go to the source code to view 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;            let title = this.title //标题
            let rootBgColorValue = this.clickSkinColorValue //背景颜色
            let id = this.tempContentItemId != undefined ? this.tempContentItemId : new Date().getTime() //id
            let span = JSON.stringify(this.controller.getSpans())
            let bean = new ListContentBean()
            if (title != undefined &amp;amp;&amp;amp; title != "" &amp;amp;&amp;amp; span != undefined &amp;amp;&amp;amp; span != "") {
              bean.title = title
              bean.time = this.getDateTime()
              bean.timeValue = new Date().getTime()
              bean.id = id
              bean.bgColor = rootBgColorValue
              bean.content = span

              let spans = this.controller.getSpans() as Array&amp;lt;RichEditorTextSpanResult&amp;gt;
              let desc = ""
              spans.forEach((span) =&amp;gt; {
                if (desc.length &amp;lt; 30) {
                  desc = desc + span.value.trim()
                }
              })
              bean.desc = desc
              let json = JSON.stringify(bean)
              DataPreferences.getInstance().putSync("abner" + id, json)
            }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Related Summary 
&lt;/h2&gt;

&lt;p&gt;regarding the time that should change in real time, it is impossible for me to enter the editing page 10:10, edit for 30 minutes, or 10:10, which is obviously unreasonable, so the time here must be real-time, this must be paid attention. &lt;/p&gt;

&lt;p&gt;There are some other matters needing attention in editing the page, such as skin changing function, style setting at the bottom, etc., which are relatively simple and will not be repeated.&lt;/p&gt;

</description>
      <category>harmonyos</category>
    </item>
    <item>
      <title>HarmonyOS Yuan Service Project Actual Combat: Memorandum UI Page Development</title>
      <dc:creator>程序员一鸣</dc:creator>
      <pubDate>Mon, 30 Jun 2025 04:56:55 +0000</pubDate>
      <link>https://dev.to/abnerming888/harmonyos-yuan-service-project-actual-combat-memorandum-ui-page-development-5e69</link>
      <guid>https://dev.to/abnerming888/harmonyos-yuan-service-project-actual-combat-memorandum-ui-page-development-5e69</guid>
      <description>&lt;h2&gt;
  
  
  Foreword 
&lt;/h2&gt;

&lt;p&gt;this article is based on Api12 &lt;/p&gt;

&lt;p&gt;before, I wrote an article about the shelf process of meta-service projects. In order to better understand and develop meta-service, I am going to develop a small project from 0 to 1. I also hope to help students who have just stepped into Hongmeng's development. The specific project is also very simple. It is a small memo project that can edit the content and display the edited content list. The development is very fast, usually half a day to a day can be done. &lt;/p&gt;

&lt;p&gt;The biggest reason for choosing such a project is that there is no need for networking operations, and the data is stored locally, which is convenient for individual developers to develop and subsequently put on shelves. &lt;/p&gt;

&lt;p&gt;Right, at present &lt;strong&gt;remember&lt;/strong&gt; meta-service items have been put on the shelves and can be searched in the application store. &lt;strong&gt;Remember&lt;/strong&gt; can experience. &lt;/p&gt;

&lt;p&gt;Let's look at the final effect: &lt;/p&gt;

&lt;h3&gt;
  
  
  home page, no data status 
&lt;/h3&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%2Fz1rereqyucsp6sug5ope.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%2Fz1rereqyucsp6sug5ope.png" alt="Image description" width="688" height="1476"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  home page, with data status 
&lt;/h3&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%2F2kx597zf80jczzia5d7w.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%2F2kx597zf80jczzia5d7w.png" alt="Image description" width="682" height="1470"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  edit Page 
&lt;/h3&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%2Fsuosurjehnv7um81hp2q.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%2Fsuosurjehnv7um81hp2q.png" alt="Image description" width="692" height="1476"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;since it is the first article before the project is developed, this article will take everyone to draw the basic UI. &lt;/p&gt;

&lt;h2&gt;
  
  
  Home page UI 
&lt;/h2&gt;

&lt;p&gt;the UI on the first page is very simple. The structure from top to bottom is the title bar, search box and Memo List. In page UI layout, we can select the Column component as the root layout, and then arrange it from top to bottom, because there are edit buttons and the default page when there is empty data. It is recommended to use the RelativeContainer component directly here. Of course, this is not the only layout method.&lt;/p&gt;

&lt;p&gt;Title bar, you can use the Text component settings, Search using the Search component, List, directly use the List component, as for the default component, need to be dynamically displayed according to whether there is memo data. &lt;/p&gt;

&lt;p&gt;The complete 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;RelativeContainer() {
  Column() {
    ActionBar({ title: "suixinji" })

    Search({ placeholder: "search……" })
      .margin({ left: 10, right: 10, top: 10 })

    List({ space: 10 }) {
      ForEach(this.mListContentBean, (item: ListContentBean, index: number) =&amp;gt; {
        ListItem() {
          Column() {
            Text(item.time)
              .width("100%")
              .textAlign(TextAlign.End)
              .margin({ top: 5, right: 5 })

            Text(item.title)
              .fontWeight(FontWeight.Bold)
              .width("100%")

            Text(item.desc)
              .width("100%")
              .margin({ top: 10, bottom: 10 })
          }
          .width("100%")
            .height(100)
            .padding({
              top: 5,
              bottom: 5,
              left: 10,
              right: 10
            })
            .backgroundColor(item.bgColor == undefined ? "#e8e8e8" : item.bgColor)
            .borderRadius(10)
        }.swipeAction({
        end: {
          builder: () =&amp;gt; {
            this.swipeDelete(this, item.bgColor == undefined ? "#e8e8e8" : item.bgColor,
                             item.id?.toString(), index)
          },
          actionAreaDistance: 80,
        }
      })
              .onClick(() =&amp;gt; {

              })
              })
    }
    .width("100%")
      .layoutWeight(1)
      .padding({ left: 10, right: 10 })
      .margin({ top: 10 })
  }


  Text("＋")
    .width(60)
    .height(60)
    .backgroundColor("#FB553C")
    .borderRadius(50)
    .fontColor(Color.White)
    .fontSize(45)
    .textAlign(TextAlign.Center)
    .margin({ right: 20, bottom: 20 })
    .alignRules({
      bottom: { anchor: "__container__", align: VerticalAlign.Bottom },
      right: { anchor: "__container__", align: HorizontalAlign.End }
    })
    .onClick(() =&amp;gt; {


    })


  Text("NORMAL")
    .fontWeight(FontWeight.Bold)
    .visibility(this.isContentEmpty ? Visibility.Visible : Visibility.None)
    .alignRules({
      center: { anchor: "__container__", align: VerticalAlign.Center },
      middle: { anchor: "__container__", align: HorizontalAlign.Center }
    })


}.height('100%')
  .width('100%')
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  edit Page UI 
&lt;/h2&gt;

&lt;p&gt;the editing page is relatively more complicated. In addition to the content editing component, a skin change at the top and a row of style settings at the bottom are added. The same root layout is also the RelativeContainer component. &lt;/p&gt;

&lt;p&gt;There are two points to pay attention to when drawing the editing page UI. One is a row of style buttons at the bottom, which need to be dynamically set according to the height of the soft keyboard. Of course, this article is only UI drawing, and we will talk about it in the following chapters. The other is the style list, such as text color, text size, skin list, etc., which needs to be hidden by dynamic display boxes. &lt;/p&gt;

&lt;p&gt;How to dynamically display the style effect? It's very simple. You can write the style effect first, then hide it first. When you click on it, you can display it. For example, the skin change at the top. You can write the skin change UI first.&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() {
        List() {
          ForEach(this.skinColors, (item: string, index: number) =&amp;gt; {
            ListItem() {
              Column() {
                Image($r("app.media.complete"))
                  .width(20)
                  .height(20)
                  .visibility(this.clickSkinPosition == index ? Visibility.Visible : Visibility.None)
                  .border({ width: 1, color: "#666666", radius: 20 })
                  .margin({ bottom: 20 })
              }
              .width(100)
              .height(160)
              .backgroundColor(item)
              .justifyContent(FlexAlign.End)
              .borderRadius(5)
              .margin({ left: 10 })
              .onClick(() =&amp;gt; {
                this.clickSkinPosition = index
                this.clickSkinColorValue = item
                this.isClickSkin = !this.isClickSkin
              })
            }
          })
        }
        .width("100%")
        .height(180)
        .backgroundColor("#e8e8e8")
        .listDirection(Axis.Horizontal)
        .padding({ top: 10 })
        .scrollBar(BarState.Off)
      }
      .backgroundColor(Color.Transparent)
      .width("100%")
      .height("100%")
      .onClick(() =&amp;gt; {
        this.isClickSkin = !this.isClickSkin
      })
      .visibility(this.isClickSkin ? Visibility.Visible : Visibility.None)
      .alignRules({
        top: { anchor: "bar", align: VerticalAlign.Bottom },
      })
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you click the Skin Resurfacing button, a skin resurfacing list is displayed.&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;
 this.isClickSkin = !this.isClickSkin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Basic effect &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%2Fbw1tocm9vs246tbtdoqz.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%2Fbw1tocm9vs246tbtdoqz.png" alt="Image description" width="800" height="1718"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  edit all UI codes on the page
&lt;/h3&gt;

&lt;p&gt;&lt;br&gt;
 &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;RelativeContainer() {
      ActionBar({
        title: "EDIT",
        leftIcon: $r("app.media.complete"),
        left2Icon: $r("app.media.skin"),
        leftMenuAttribute: {
          imageWidth: 22,
          imageHeight: 22
        },
        leftMenu2Attribute: {
          imageWidth: 22,
          imageHeight: 22,
          imageMargin: { left: 20 }
        },
        onLeftImageClick: (position) =&amp;gt; {
          if (position == 0) {

            router.back()
          } else {

            this.isClickSkin = !this.isClickSkin
          }
        }
      }).id("bar")

      Column() {
        TextInput({ placeholder: "Please enter a note title", text: $$this.title })
          .backgroundColor(Color.Transparent)
          .placeholderFont({ weight: FontWeight.Bold, size: 15 })
          .placeholderColor("#666666")
          .fontSize(18)
          .maxLength(50)
          .fontColor("#222222")
          .fontWeight(FontWeight.Bold)
          .caretColor(Color.Red)//光标的颜色
          .padding(10)
          .borderRadius(0)
          .margin({ top: 10 })

        Text() {
          Span(this.nowTime)
        }
        .width("100%")
        .fontSize(13)
        .fontColor("#666666")
        .padding({ left: 10 })
        .margin({ top: 10 })

        RichEditor(this.options)
          .onReady(() =&amp;gt; {

            //获取当前的时间
            this.nowTime = this.getDateTime()
            this.nowInterval = setInterval(() =&amp;gt; {
              this.nowTime = this.getDateTime()
            }, 1000)

          })
          .placeholder("Take notes at will, record every little bit", {
            fontColor: "#666666"
          })
          .caretColor(Color.Red)
          .padding(10)
          .margin({ top: 10 })
          .onSelect((value: RichEditorSelection) =&amp;gt; {
            this.start = value.selection[0];
            this.end = value.selection[1];
          })
      }
      .alignRules({
        top: { anchor: "bar", align: VerticalAlign.Bottom },
        bottom: { anchor: "bottom_bar", align: VerticalAlign.Top }
      }).margin({ bottom: 80 })

      Column() {
        List({ space: 10 }) {
          ForEach(this.fontColors, (item: ResourceColor) =&amp;gt; {
            ListItem() {
              Text()
                .width(20)
                .height(20)
                .backgroundColor(item)
                .borderRadius(20)
                .border({ width: 1, color: "#e8e8e8" })
                .onClick(() =&amp;gt; {
                  this.clickStyleColorValue = item
                  this.changeStyle()
                  this.setFontColor()
                })
            }
          })
        }
        .width("100%")
        .height(30)
        .listDirection(Axis.Horizontal)
        .padding({ left: 10, right: 10 })
        .scrollBar(BarState.Off)
        .visibility(this.isClickStyleColor ? Visibility.Visible : Visibility.None)

        List({ space: 10 }) {
          ForEach(this.fontSizes, (item: string, index: number) =&amp;gt; {
            ListItem() {
              Text(item)
                .height(20)
                .borderRadius(20)
                .fontColor(Color.Black)
                .fontWeight(FontWeight.Bold)
                .onClick(() =&amp;gt; {
                  let fontSize = 15
                  if (index == 0) {
                    fontSize = 21
                  } else if (index == 1) {
                    fontSize = 20
                  } else if (index == 2) {
                    fontSize = 19
                  } else if (index == 3) {
                    fontSize = 18
                  } else if (index == 4) {
                    fontSize = 17
                  } else if (index == 5) {
                    fontSize = 16
                  } else if (index == 6) {
                    fontSize = 15
                  } else {
                    fontSize = Number(item)
                  }
                  this.clickStyleSizeValue = fontSize

                  this.changeStyle()
                  //设置文字大小
                  this.setFontSize()
                })
            }
          })
        }
        .width("100%")
        .height(30)
        .listDirection(Axis.Horizontal)
        .padding({ left: 10, right: 10 })
        .scrollBar(BarState.Off)
        .visibility(this.isClickStyleSize ? Visibility.Visible : Visibility.None)

        Row() {
          Image($r("app.media.font_size"))
            .onClick(() =&amp;gt; {
              this.isClickStyleSize = !this.isClickStyleSize
              this.setBold()
            })
            .backgroundColor(this.isClickStyleSize ? "#e8e8e8" : Color.Transparent)
            .width(20)
            .height(20)

          Text("B")
            .onClick(() =&amp;gt; {
              this.isClickStyleB = !this.isClickStyleB
              this.changeStyle()
              this.setBold()
            })
            .fontWeight(FontWeight.Bold)
            .fontSize(20)
            .backgroundColor(this.isClickStyleB ? "#e8e8e8" : Color.Transparent)
            .width(30)
            .height(30)
            .textAlign(TextAlign.Center)
            .margin({ left: 20 })
          Text("I")
            .onClick(() =&amp;gt; {
              this.isClickStyleI = !this.isClickStyleI
              this.changeStyle()
              this.setStyle()
            })
            .fontWeight(FontWeight.Bold)
            .fontStyle(FontStyle.Italic)
            .backgroundColor(this.isClickStyleI ? "#e8e8e8" : Color.Transparent)
            .fontSize(20)
            .margin({ left: 20 })
            .width(30)
            .height(30)
            .textAlign(TextAlign.Center)

          Image($r("app.media.color_bg"))
            .onClick(() =&amp;gt; {
              this.isClickStyleColor = !this.isClickStyleColor
            })
            .backgroundColor(this.isClickStyleColor ? "#e8e8e8" : Color.Transparent)
            .margin({ left: 20 })
            .width(20)
            .height(20)
        }
        .width("100%")
        .height(50)
        .backgroundColor(this.clickSkinColorValue)
        .border({ width: { top: 1 }, color: "#e8e8e8" })
        .padding({ left: 20, right: 20 })

      }.id("bottom_bar")
      .alignRules({
        bottom: { anchor: "__container__", align: VerticalAlign.Bottom }
      })


      Column() {
        List() {
          ForEach(this.skinColors, (item: string, index: number) =&amp;gt; {
            ListItem() {
              Column() {
                Image($r("app.media.complete"))
                  .width(20)
                  .height(20)
                  .visibility(this.clickSkinPosition == index ? Visibility.Visible : Visibility.None)
                  .border({ width: 1, color: "#666666", radius: 20 })
                  .margin({ bottom: 20 })
              }
              .width(100)
              .height(160)
              .backgroundColor(item)
              .justifyContent(FlexAlign.End)
              .borderRadius(5)
              .margin({ left: 10 })
              .onClick(() =&amp;gt; {
                this.clickSkinPosition = index
                this.clickSkinColorValue = item
                this.isClickSkin = !this.isClickSkin
              })
            }
          })
        }
        .width("100%")
        .height(180)
        .backgroundColor("#e8e8e8")
        .listDirection(Axis.Horizontal)
        .padding({ top: 10 })
        .scrollBar(BarState.Off)
      }
      .backgroundColor(Color.Transparent)
      .width("100%")
      .height("100%")
      .onClick(() =&amp;gt; {
        this.isClickSkin = !this.isClickSkin
      })
      .visibility(this.isClickSkin ? Visibility.Visible : Visibility.None)
      .alignRules({
        top: { anchor: "bar", align: VerticalAlign.Bottom },
      })
    }
    .height('100%')
    .width('100%')
    .height(this.screenHeight) 
    .backgroundColor(this.clickSkinColorValue)
    .expandSafeArea([SafeAreaType.SYSTEM, SafeAreaType.KEYBOARD], [SafeAreaEdge.TOP, SafeAreaEdge.BOTTOM])
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  related Summary 
&lt;/h2&gt;

&lt;p&gt;there is nothing to say about UI page drawing, that is, the placement of components and the display logic of components. There are many attributes that are not recorded in the article. You can check them in the warehouse. One of my title bar components is used in the article. If you don't want to use them, you can use what you wrote.&lt;/p&gt;

</description>
      <category>harmonyos</category>
    </item>
    <item>
      <title>HarmonyOS Development: Encryption Algorithm Encapsulation</title>
      <dc:creator>程序员一鸣</dc:creator>
      <pubDate>Mon, 30 Jun 2025 04:55:21 +0000</pubDate>
      <link>https://dev.to/abnerming888/harmonyos-development-encryption-algorithm-encapsulation-32a</link>
      <guid>https://dev.to/abnerming888/harmonyos-development-encryption-algorithm-encapsulation-32a</guid>
      <description>&lt;h2&gt;
  
  
  Foreword 
&lt;/h2&gt;

&lt;p&gt;this article is based on Api12 &lt;/p&gt;

&lt;p&gt;encryption algorithm is a common business in development. For the sake of security, the client and the server transmit data through encryption, which can ensure the confidentiality of data and prevent sensitive data leakage. In Hongmeng system, encryption algorithm is relatively easy to implement. After all, ArkTs is based on TypeScript, so some algorithms are basically common. &lt;/p&gt;

&lt;p&gt;There are many encryption methods, such as symmetric encryption, asymmetric encryption, and Common message digest algorithm MD5,SHA and so on, this article mainly outlines several common algorithms, and simple package after use. &lt;/p&gt;

&lt;h2&gt;
  
  
  Message Digest Algorithm 
&lt;/h2&gt;

&lt;p&gt;message digest algorithm, that is, hash algorithm or one-way hash algorithm, through any length of message, Operation to generate fixed-length summary algorithm, Hongmeng is mainly through. Cryptoframe.createmd method to implement each algorithm. &lt;/p&gt;

&lt;p&gt;Currently, the supported algorithms and specifications are as follows: &lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;summary algorithm&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;types of Support&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;API version&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;HASH &lt;/td&gt;
&lt;td&gt;SHA1 &lt;/td&gt;
&lt;td&gt;9 + &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HASH &lt;/td&gt;
&lt;td&gt;SHA224 &lt;/td&gt;
&lt;td&gt;9 + &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HASH &lt;/td&gt;
&lt;td&gt;SHA256 &lt;/td&gt;
&lt;td&gt;9 + &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HASH&lt;/td&gt;
&lt;td&gt;SHA384 &lt;/td&gt;
&lt;td&gt;9 + &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HASH &lt;/td&gt;
&lt;td&gt;SHA512 &lt;/td&gt;
&lt;td&gt;9 + &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HASH &lt;/td&gt;
&lt;td&gt;MD5 &lt;/td&gt;
&lt;td&gt;9 + &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HASH &lt;/td&gt;
&lt;td&gt;SM3 &lt;/td&gt;
&lt;td&gt;10 + &lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;take a very simple SHA256 algorithm, other specifications, only need to change the type.&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;let md = cryptoFramework.createMd("SHA256")
Await md. update ({data: new Uint8Array (buffer. rom, 'utf-8'. buffer)})
let mdResult = await md.digest()
Console.info ('===encrypted result: '+mdResult.data)
let sha256Result = this.uint8ArrayToString(mdResult.data)
Console.info ('===converted to string result:'+sha256Result)
let mdLen = md.getMdLength()
Console.info ("===encrypted length:"+mdLen)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;For example, MD5:&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;let md = cryptoFramework.createMd("MD5")
Await md. update ({data: new Uint8Array (buffer. rom, 'utf-8'. buffer)})
let mdResult = await md.digest()
Console.info ('===encrypted result: '+mdResult.data)
let sha256Result = this.uint8ArrayToString(mdResult.data)
Console.info ('===converted to string result:'+sha256Result)
let mdLen = md.getMdLength()
Console.info ("===encrypted length:"+mdLen)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;as can be seen from the above code, the Api provided by the system is basically concise enough. &lt;/p&gt;
&lt;h2&gt;
  
  
  Base64 
&lt;/h2&gt;

&lt;p&gt;in fact, strictly speaking, base64 is not an encryption algorithm, but the corresponding the encoding format is used to represent binary data in the text protocol. By using Base64 encoding, binary data can be converted into printable ACSII characters, that is, Base64 encoding is the process from binary to character, so as to ensure that data is not lost during transmission. &lt;/p&gt;

&lt;p&gt;The encoding and decryption of Base64 are also provided in Hongmeng, which is also very simple to use.&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;
  // Base64
  public base64Encode(str: string): string {
    let blob: cryptoFramework.DataBlob = { data: new Uint8Array(buffer.from(str, 'utf-8').buffer) }
    let base64Helper = new util.Base64Helper()
    return base64Helper.encodeToStringSync(blob.data)
  }

  // Base64
  public base64Decode(input: string): string {
    let base64Helper = new util.Base64Helper()
    let uint8Array = base64Helper.decodeSync(input)
    return buffer.from(uint8Array).toString("utf-8")
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  AES symmetric encryption 
&lt;/h2&gt;

&lt;p&gt;symmetric encryption has a remarkable feature, that is, the encryptor and The Decryptor use the same key. This method has a faster encryption and decryption speed and is suitable for long-term use of data. However, the process of key transmission is not safe and easy to crack. Key management is also troublesome. Common symmetric encryption includes AES,DES, and AES is the most commonly used.&lt;/p&gt;

&lt;p&gt;Symmetric encryption AES provides seven encryption modes: ECB, CBC, OFB, CFB, CTR, GCM, and CCM. Different encryption modes apply different encryption and decryption parameters. &lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Grouping Mode&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;key length (bit)&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;fill mode&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;API version&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;ECB &lt;/td&gt;
&lt;td&gt;[128&lt;/td&gt;
&lt;td&gt;192&lt;/td&gt;
&lt;td&gt;256] &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CBC &lt;/td&gt;
&lt;td&gt;[128&lt;/td&gt;
&lt;td&gt;192&lt;/td&gt;
&lt;td&gt;256] &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CTR &lt;/td&gt;
&lt;td&gt;[128&lt;/td&gt;
&lt;td&gt;192&lt;/td&gt;
&lt;td&gt;256] &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OFB &lt;/td&gt;
&lt;td&gt;[128&lt;/td&gt;
&lt;td&gt;192&lt;/td&gt;
&lt;td&gt;256] &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CFB &lt;/td&gt;
&lt;td&gt;[128&lt;/td&gt;
&lt;td&gt;192&lt;/td&gt;
&lt;td&gt;256] &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GCM &lt;/td&gt;
&lt;td&gt;[128&lt;/td&gt;
&lt;td&gt;192&lt;/td&gt;
&lt;td&gt;256] &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CCM &lt;/td&gt;
&lt;td&gt;[128&lt;/td&gt;
&lt;td&gt;192&lt;/td&gt;
&lt;td&gt;256] &lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A simple example of several modes of actual code execution, no matter which way, is to need the secret key and encryption and decryption content, generally we AES development, first to determine the secret key, and then determine the encrypted content and decryption content. &lt;/p&gt;
&lt;h3&gt;
  
  
  ECB mode, encryption and decryption
&lt;/h3&gt;

&lt;p&gt;&lt;br&gt;
 &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
  async encryptMessagePromise(symKey: cryptoFramework.SymKey, plainText: cryptoFramework.DataBlob) {
    let cipher = cryptoFramework.createCipher('AES128|ECB|PKCS7');
    await cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, symKey, null);
    let cipherData = await cipher.doFinal(plainText);
    return cipherData;
  }


  async decryptMessagePromise(symKey: cryptoFramework.SymKey, cipherText: cryptoFramework.DataBlob) {
    let decoder = cryptoFramework.createCipher('AES128|ECB|PKCS7');
    await decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, symKey, null);
    let decryptData = await decoder.doFinal(cipherText);
    re
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  GCM mode, encryption and decryption
&lt;/h3&gt;

&lt;p&gt;&lt;br&gt;
 &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;genGcmParamsSpec() {
let ivBlob = this.generateRandom(12);
let arr = [1, 2, 3, 4, 5, 6, 7, 8];  // 8 bytes
let dataAad = new Uint8Array(arr);
let aadBlob: cryptoFramework.DataBlob = { data: dataAad };
arr = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];  // 16 bytes
let dataTag = new Uint8Array(arr);
let tagBlob: cryptoFramework.DataBlob = {
data: dataTag
};
//The authTag of GCM is obtained from the doFinal result during encryption and filled into the params parameter of the init function during decryption
let gcmParamsSpec: cryptoFramework.GcmParamsSpec = {
iv: ivBlob,
aad: aadBlob,
authTag: tagBlob,
algName: "GcmParamsSpec"
};
return gcmParamsSpec;
}

gcmParams = this.genGcmParamsSpec();

//Encrypt messages
async encryptMessagePromise(symKey: cryptoFramework.SymKey, plainText: cryptoFramework.DataBlob) {
let cipher = cryptoFramework.createCipher('AES128|GCM|PKCS7');
await cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, symKey, this.gcmParams);
let encryptUpdate = await cipher.update(plainText);
//When encrypting doFinal in gcm mode, pass in empty space, obtain tag data, and update it to the gcmParams object.
this.gcmParams.authTag = await cipher.doFinal(null);
return encryptUpdate;
}

//Decrypt message
async decryptMessagePromise(symKey: cryptoFramework.SymKey, cipherText: cryptoFramework.DataBlob) {
let decoder = cryptoFramework.createCipher('AES128|GCM|PKCS7');
await decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, symKey, this.gcmParams);
let decryptUpdate = await decoder.update(cipherText);
//When decrypting doFinal in gcm mode, empty data is passed in. When verifying init, tag data is passed in. If verification fails, an exception will be thrown.
let decryptData = await decoder.doFinal(null);
if (decryptData == null) {
console.info('GCM decrypt success, decryptData is null');
}
return decryptUpdate;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  CCM mode, encryption and decryption
&lt;/h3&gt;

&lt;p&gt;&lt;br&gt;
 &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;genCcmParamsSpec() {
let rand: cryptoFramework.Random = cryptoFramework.createRandom();
let ivBlob: cryptoFramework.DataBlob = rand.generateRandomSync(7);
let aadBlob: cryptoFramework.DataBlob = rand.generateRandomSync(8);
let arr = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];  // 12 bytes
let dataTag = new Uint8Array(arr);
let tagBlob: cryptoFramework.DataBlob = {
data: dataTag
};
//CCM's authTag is obtained from the doFinal result during encryption and filled into the params parameter of the init function during decryption
let ccmParamsSpec: cryptoFramework.CcmParamsSpec = {
iv: ivBlob,
aad: aadBlob,
authTag: tagBlob,
algName: "CcmParamsSpec"
};
return ccmParamsSpec;
}

ccmParams = this.genCcmParamsSpec();

//Encrypt messages
async encryptMessagePromise(symKey: cryptoFramework.SymKey, plainText: cryptoFramework.DataBlob) {
let cipher = cryptoFramework.createCipher('AES128|CCM');
await cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, symKey, this.ccmParams);
let encryptUpdate = await cipher.update(plainText);
//When encrypting doFinal in CCM mode, pass in empty space, obtain tag data, and update it to the ccmParams object.
this.ccmParams.authTag = await cipher.doFinal(null);
return encryptUpdate;
}

//Decrypt message
async decryptMessagePromise(symKey: cryptoFramework.SymKey, cipherText: cryptoFramework.DataBlob) {
let decoder = cryptoFramework.createCipher('AES128|CCM');
await decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, symKey, this.ccmParams);
let decryptUpdate = await decoder.doFinal(cipherText);
return decryptUpdate;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;in actual development, we can generate our secret key according to the provided string or other specific characters, generally in the form of a string key after Base64 encoding, and then decode it when encrypting and decrypting. &lt;/p&gt;
&lt;h2&gt;
  
  
  RSA asymmetric encryption 
&lt;/h2&gt;

&lt;p&gt;the difference between asymmetric encryption and symmetric encryption is that it has two secret keys, a public key and a private key. The public key is used for encryption and the private key is used for decryption. Compared with symmetric encryption, the security factor is on a higher level, but there is also the risk of man-in-the-middle attack. Common asymmetric encryption includes RSA,DSA,ECC, etc. Generally, the most commonly used is RSA. &lt;/p&gt;

&lt;p&gt;RSA also provides a variety of encryption methods, such as PKCS1 mode PKCS1_OAEP mode, and NoPadding. &lt;/p&gt;
&lt;h3&gt;
  
  
  PKCS1 mode
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
  async encryptMessagePromise(publicKey: cryptoFramework.PubKey, plainText: cryptoFramework.DataBlob) {
    let cipher = cryptoFramework.createCipher('RSA1024|PKCS1');
    await cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, publicKey, null);
    let encryptData = await cipher.doFinal(plainText);
    return encryptData;
  }


  async decryptMessagePromise(privateKey: cryptoFramework.PriKey, cipherText: cryptoFramework.DataBlob) {
    let decoder = cryptoFramework.createCipher('RSA1024|PKCS1');
    await decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, privateKey, null);
    let decryptData = await decoder.doFinal(cipherText);
    return decryptData;
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Other modes, no longer examples, you can go to the official website to check. &lt;/p&gt;
&lt;h2&gt;
  
  
  Encapsulation Use 
&lt;/h2&gt;

&lt;p&gt;you can use the above methods to encrypt and decrypt the data. Of course, you can also package it yourself or use someone else's package. For the above, I also simply packaged it, and friends who need it can use it. &lt;/p&gt;
&lt;h3&gt;
  
  
  Simple Feature List 
&lt;/h3&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%2Fplziowtt3a5tuc5khwhd.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%2Fplziowtt3a5tuc5khwhd.png" alt="Image description" width="800" height="582"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  quick Use 
&lt;/h3&gt;

&lt;p&gt;method 1: in the Terminal window, run the following command to install the third-party package. DevEco Studio automatically adds the third-party package dependency to the project oh-package.json5. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Suggestion: Execute the command under the module path used.&lt;/strong&gt;&lt;/p&gt;




&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ohpm install @abner/security
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Method 2: Set the three-party package dependency in the project oh-package.json5. The configuration example 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;"dependencies": { "@abner/security": "^1.0.0"}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  code Use 
&lt;/h3&gt;
&lt;h4&gt;
  
  
  1, MD5 
&lt;/h4&gt;

&lt;p&gt;synchronization&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;Let encryptContent=md5EncryptSync ("encrypted data")
Console.log ("===encrypted:"+encryptContent)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;asynchronous&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;Md5Encrypt ("encrypted data"). then ((content)=&amp;gt;{
Console.log ("===encrypted:"+content)
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h4&gt;
  
  
  2, BASE64 
&lt;/h4&gt;

&lt;p&gt;code synchronization&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;Let encryptContent=base64EncodeSync ("I am test data")
this.mBase64EncodeString = encryptContent
Console.log ("===encoded:"+encryptContent)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;coding asynchronous&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;Base64Encode ("I am test data"). then ((encryptContent)=&amp;gt;{
this.mBase64EncodeString = encryptContent
Console.log ("===encoded:"+encryptContent)
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;decode synchronization&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;base64Decode(this.mBase64EncodeString).then((decode) =&amp;gt; {
Console.log ("===decoded:"+decode)
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h4&gt;
  
  
  3, SHA 
&lt;/h4&gt;

&lt;p&gt;the default sha is SHA256, which can be modified as needed. Just pass in the second parameter. &lt;/p&gt;

&lt;p&gt;Synchronization&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;let encryptContent = shaEncryptSync("1")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;asynchronous&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;shaEncrypt("1").then((content) =&amp;gt; {

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

&lt;/div&gt;


&lt;p&gt;modify the algName&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;let encryptContent = shaEncryptSync("1","SHA256")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h4&gt;
  
  
  4. SM3 
&lt;/h4&gt;

&lt;p&gt;synchronization&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;Let encryptContent=sM3EncryptSync ("encrypted data")
Console.log ("===encrypted:"+encryptContent)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;asynchronous&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SM3Encrypt ("encrypted data"). then ((content)=&amp;gt;{
Console.log ("===encrypted:"+content)
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  5, AES 
&lt;/h4&gt;

&lt;p&gt;randomly generate SymKey [asynchronous]]&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;aesGenerateSymKey().then((symKey) =&amp;gt; {
this.mSymKey = symKey
Console.log (===Key:+symKey)
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;randomly generate SymKey key [synchronization]]&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;let symKey = aesGenerateSymKeySync()
this.mSymKey = symKey
Console.log (===Key:+symKey)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;string Generation Key [Asynchronous]]&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;aesGenerateSymKey("1234").then((symKey) =&amp;gt; {
  this.mSymKey = symKey

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

&lt;/div&gt;


&lt;p&gt;string Generation Key [Sync]]&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;let symKeyString = aesGenerateSymKeySync("1234")
this.mSymKey = symKeyString
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;encrypted data [asynchronous] [ECB mode]]&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;aesEncryptString("123", this.mSymKey).then((result) =&amp;gt; {
  this.encryptString = result

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

&lt;/div&gt;


&lt;p&gt;decryption data [asynchronous] [ECB mode]]&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;aesDecryptString(this.encryptString, this.mSymKey).then((result) =&amp;gt; {

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

&lt;/div&gt;


&lt;p&gt;encrypted data [synchronization] [ECB mode]]&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;let result = aesEncryptStringSync("123", this.mSymKey)
this.encryptString = result
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;decryption data [synchronization] [ECB mode]]&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;let decryptString = aesDecryptStringSync(this.encryptString!, this.mSymKey!)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h4&gt;
  
  
  6. RSA 
&lt;/h4&gt;

&lt;p&gt;randomly generate KeyPair [asynchronous]]&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;rsaGenerateAsyKey().then((keyPair) =&amp;gt; {
  let pubKey = keyPair.pubKey 
  let priKey = keyPair.priKey 
  this.priKey = priKey
  this.pubKey = pubKey
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;randomly generate KeyPair [synchronization]]&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;let keyPair = rsaGenerateAsyKeySync()
let pubKey1 = keyPair.pubKey 
let priKey1 = keyPair.priKey 
this.priKey = priKey1
this.pubKey = pubKey1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;randomly Generate String Key Pair [Asynchronous]]&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;rsaGenerateAsyKeyPem().then((keyPairPem) =&amp;gt; {
  let pubKey = keyPairPem.pubKey 
  let priKey = keyPairPem.priKey 
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;randomly Generate String Key Pair [Synchronization]]&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;let keyPairPem = generateAsyKeyPemSync()
let pubKeyPem = keyPairPem.pubKey 
let priKeyPem = keyPairPem.priKey
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;randomly generated key pair binary [asynchronous]]&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;rsaGenerateAsyKeyDataBlob().then((dataBlobArray) =&amp;gt; {
  let pubKey: cryptoFramework.DataBlob = dataBlobArray[0]
  let priKey: cryptoFramework.DataBlob = dataBlobArray[1]

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

&lt;/div&gt;


&lt;p&gt;randomly Generated Binary Key Pair [Synchronization]]&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;let dataBlobArray = rsaGenerateAsyKeyDataBlobSync()
let pubKey: cryptoFramework.DataBlob = dataBlobArray[0]
let priKey: cryptoFramework.DataBlob = dataBlobArray[1]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;generate KeyPair key pair by specifying binary data [asynchronous]]&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;rsaGenKeyPairByData(this.pkData, this.skData).then((keyPair) =&amp;gt; {
  let pubKey = keyPair.pubKey 
  let priKey = keyPair.priKey 
  this.priKey = priKey
  this.pubKey = pubKey
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;generate KeyPair key pair by specifying binary data [synchronization]]&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;let keyPairByDataSync = rsaGenKeyPairByDataSync(this.pkData, this.skData)
let pubKeyPairByData = keyPairByDataSync.pubKey 
let priKeyPairByData = keyPairByDataSync.priKey 
this.priKey = priKeyPairByData
this.pubKey = pubKeyPairByData
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;generating String Key Pairs from Binary Data [Asynchronous]]&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;rsaGenKeyPairByDataPem(this.pkData, this.skData).then((keyPairPem) =&amp;gt; {
  let pubKeyPem = keyPairPem.pubKey 
  let priKeyPem = keyPairPem.priKey 
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;generate String Key Pair from Binary Data [Synchronization]]&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;let keyPairByDataPemSync = rsaGenKeyPairByDataPemSync(this.pkData, this.skData)
let pubKeyPairByDataPem = keyPairByDataPemSync.pubKey 
let priKeyPairByDataPem = keyPairByDataPemSync.priKey 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;string data generation KeyPair [asynchronous]]&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;rsaGenKeyPairString(this.appRsaPublicKey, this.appRsaPrivateKey).then((keyPair) =&amp;gt; {
  let pubKey = keyPair.pubKey
  let priKey = keyPair.priKey
  this.priKey = priKey
  this.pubKey = pubKey
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;string data generation KeyPair [synchronization]]&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;let keyPair2 = rsaGenKeyPairStringSync(this.publicPkcs1Str1024, this.priKeyPkcs1Str1024)
let pubKey3 = keyPair2.pubKey
let priKey3 = keyPair2.priKey
this.priKey = priKey3
this.pubKey = pubKey3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;string data generation string key pair [asynchronous]]&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rsaGenKeyPairStringPem(this.appRsaPublicKey, this.appRsaPrivateKey).then((keyPair) =&amp;gt; {
          let pubKeyPem = keyPair.pubKey
          let priKeyPem = keyPair.priKey 
        })
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;String data generation string key pair [synchronization]]&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;let keyPairStringPemSync = rsaGenKeyPairStringPemSync(this.publicPkcs1Str1024, this.priKeyPkcs1Str1024)
        let pubKeyPairStringPemSync = keyPairStringPemSync.pubKey 
        let priKeyPairStringPemSync = keyPairStringPemSync.priKey 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;string key encryption [asynchronous]]&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;Let message="I am a piece of data that needs to be encrypted"
Console.log ("===Data before encryption:"+message)
rsaEncryptString(message, this.publicKey).then((data) =&amp;gt; {
this.encryptString = data
Console.log ("===encrypted data:"+data)
}).catch((e: BusinessError) =&amp;gt; {
Console.log ("===Encryption Error:"+JSON. stringify (e.message))
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;string Key Mode Decryption [Asynchronous]]&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;//There must be a private key and the data to be decrypted
rsaDecryptString(this.encryptString, this.privateKey).then((data) =&amp;gt; {
Console.log ("==decrypted data:"+data)
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;string key encryption [synchronization]]&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;Let message1="I am a piece of data that needs to be encrypted"
Console.log ("===Data before encryption:"+message1)
this.encryptString = rsaEncryptStringSync(message1, this.publicKey)
Console.log ("===encrypted data:"+this. encryptString)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;string Key Mode Decryption [Synchronization]]&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;//There must be a private key and the data to be decrypted
let data = rsaDecryptStringSync(this.encryptString, this.privateKey)
Console.log ("==decrypted data:"+data)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;encryption KeyPair key method [asynchronous] requires cryptoFramework.PubKey&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;if (this.pubKey != undefined) {
Let message="I am a piece of data that needs to be encrypted"
Console.log ("===Data before encryption:"+message)
rsaEncryptDataBlob(message, this.pubKey!).then((data) =&amp;gt; {
this.encryptDataBlob = data
Console.log ("===encrypted data:"+JSON. stringify (data))
}).catch((e: BusinessError) =&amp;gt; {
Console.log ("===Encryption Error:"+JSON. stringify (e.message))
})
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;decrypt KeyPair key method [asynchronous]]&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;if (this.priKey != undefined &amp;amp;&amp;amp; this.encryptDataBlob != undefined) {
//There must be a private key and the data to be decrypted
rsaDecryptDataBlob(this.encryptDataBlob, this.priKey).then((data) =&amp;gt; {
Console.log ("==decrypted data:"+data)
})
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;encryption KeyPair key mode [synchronization]]&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;if (this.pubKey != undefined) {
Let message1="I am a piece of data that needs to be encrypted"
Console.log ("===Data before encryption:"+message1)
this.encryptDataBlob = rsaEncryptDataBlobSync(message1, this.pubKey!)
Console.log ("===encrypted data:"+JSON. stringify (this. encryptDataBlob))
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;decrypt KeyPair key mode [synchronization]]&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;if (this.priKey != undefined &amp;amp;&amp;amp; this.encryptDataBlob != undefined) {
//There must be a private key and the data to be decrypted
let data = rsaDecryptDataBlobSync(this.encryptDataBlob, this.priKey)
Console.log ("==decrypted data:"+data)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;private key signature synchronization&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;let sign = rsaEncryptPriKeyContentSync("123", this.privateKey)
Console.log ("======Signature:"+sign)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;public Key Signature Verification Synchronization&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;//This. signData is the signature content
let signResult = rsaDecryptPubKeyContentSync("123",this.signData, this.publicKey)
Console.log ("=====signature verification:"+signResult)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;private key signing asynchronous&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;rsaEncryptPriKeyContent("123", this.privateKey).then((sign) =&amp;gt; {
Console.log ("======Signature:"+sign)
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;public Key Signature Verification Asynchronous&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rsaEncryptPriKeyContent("123", this.privateKey).then((sign) =&amp;gt; {
Console.log ("======Signature:"+sign)
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>harmonyos</category>
    </item>
    <item>
      <title>HarmonyOS Development: Customize a Dialog that pops up anywhere</title>
      <dc:creator>程序员一鸣</dc:creator>
      <pubDate>Mon, 30 Jun 2025 04:54:03 +0000</pubDate>
      <link>https://dev.to/abnerming888/harmonyos-development-customize-a-dialog-that-pops-up-anywhere-39fn</link>
      <guid>https://dev.to/abnerming888/harmonyos-development-customize-a-dialog-that-pops-up-anywhere-39fn</guid>
      <description>&lt;h2&gt;
  
  
  Foreword 
&lt;/h2&gt;

&lt;p&gt;this article is based on Api12 &lt;/p&gt;

&lt;p&gt;in the development of Hongmeng, there has always been a problem bothering him, and presumably most developers, that is, the dialog custom pop-up window provided by the system cannot be popped up at any position, which is limited the member variables of @ CustomDialog and @ Component struct, which leads to, I want to pop up in the encapsulated tool class or ViewModel, or other places, can only be executed by triggering the UI layer through events or callbacks, which is very inconvenient. In addition, although we can share UI, CustomDialogController needs to be defined everywhere, which is also very redundant. Of course, the dialog itself should pop up at the UI layer. There is no problem with Hongmeng's design, but in order to take into account the ease of use, it should pop up at any position, which is probably very necessary for many people. &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%2Focyyw4483o05fozlr8r6.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%2Focyyw4483o05fozlr8r6.png" alt="Image description" width="800" height="61"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  System custom pop-up window
&lt;/h3&gt;

&lt;p&gt;&lt;br&gt;
 &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dialogController = new CustomDialogController({
builder: this.customDialog,
autoCancel: true,
})

/*
* Author:AbnerMing
*Description: Custom Dialog
*/
@Builder
customDialog() {
Text ("I am a custom dialog")
.width("100%")
.height(100)
}


This. dialogController. open()//Pop up
This. dialogController. close()//Close
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;at present, there are two ways to get rid of UI restrictions and pop up at any position. The first is to use window to create a window. This form requires initialization. Whether it depends on window.WindowStage or an ordinary page, it is a front dependency. Of course, there is another point, that is, the pop-up method is slightly stiff, but it can meet the normal needs. The second is through &lt;strong&gt;openCustomDialog in promptAction&lt;/strong&gt; however, this method needs to be in Api11 and above. For the current use requirements, if you want to pop up at any position, it is still recommended to use it. &lt;strong&gt;The openCustomDialog method.&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  openCustomDialog simple to use
&lt;/h3&gt;

&lt;p&gt;The pop-up window is popped up by openCustomDialog and closed by closeCustomDialog.&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;private customDialogComponentId: number = 0

build() {
Column() {
Button ("Simple Demo")
.onClick(() =&amp;gt; {
promptAction.openCustomDialog({
builder: () =&amp;gt; {
this.customDialogComponent()
}
}).then((dialogId: number) =&amp;gt; {
this.customDialogComponentId = dialogId
})
})
}
.width("100%")
.height("100%")
.justifyContent(FlexAlign.Center)
}

@Builder
customDialogComponent() {
Column() {
Text ('spop up '). fontSize (30)
Row({ space: 50 }) {
Button ("Confirm"). onClick()=&amp;gt;{
promptAction.closeCustomDialog(this.customDialogComponentId)
})
Button ("Cancel"). onClick()=&amp;gt;{
promptAction.closeCustomDialog(this.customDialogComponentId)
})
}
}.height(200).padding(5).justifyContent(FlexAlign.SpaceBetween)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;At present, based on the openCustomDialog method, it has also encapsulated a layer and has supported most common functions in the market, such as information pop-up window, confirmation cancellation form pop-up window, bottom pop-up window, time, city and other styles. Of course, it also supports custom component forms, covering almost all scenarios and can be directly used by friends who need them. &lt;/p&gt;

&lt;p&gt;Central Warehouse Address: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://ohpm.openharmony.cn/#/cn/detail/@abner%2Fdialog" rel="noopener noreferrer"&gt;https://ohpm.openharmony.cn/#/cn/detail/@abner%2Fdialog &lt;/a&gt;&lt;/p&gt;

&lt;p&gt;at present, various functions are also listed so that everyone can use them in a targeted way. &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%2F31sgh2yalx1nkuo1f9nf.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%2F31sgh2yalx1nkuo1f9nf.png" alt="Image description" width="684" height="1468"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Quick Use 
&lt;/h2&gt;

&lt;p&gt;method 1: in the Terminal window, run the following command to install the third-party package. DevEco Studio automatically adds the third-party package dependency to the project oh-package.json5. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Suggestion: Execute the command under the module path used.&lt;/strong&gt;&lt;/p&gt;




&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ohpm install @abner/dialog
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Method 2: Set the three-party package dependency in the project oh-package.json5. The configuration example 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;"dependencies": { "@abner/dialog": "^1.1.1"}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  initialization 
&lt;/h2&gt;

&lt;p&gt;initialization can change the unified configuration, such as width and height, such as size, such as background, etc., of course, if necessary, if the default style meets the requirements, &lt;strong&gt;global initialization can be omitted&lt;/strong&gt; , you can also modify the style when you call it separately.&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;initDialog(attribute)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Property Introduction 
&lt;/h2&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;property&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Type&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;overview&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;attribute &lt;/td&gt;
&lt;td&gt;FusionAttribute &lt;/td&gt;
&lt;td&gt;optional parameter, dialog attribute global configuration, used to modify the pop-up window style, can be configured here according to UI &lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h3&gt;
  
  
  FusionAttribute attribute 
&lt;/h3&gt;

&lt;p&gt;FusionAttribute is a global dialog attribute configuration. If the default dialog style is different from the style in your project, you can use this parameter to set it. If you configure the global dialog attribute once, it will take effect in all places on the page, which is convenient for you to use later. &lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Property&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;type&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;overview&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;infoOrConfirmAttribute &lt;/td&gt;
&lt;td&gt;ContentAttribute &lt;/td&gt;
&lt;td&gt;optional parameters, information or confirmation form pop-up window attribute configuration &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;bottomListAttribute &lt;/td&gt;
&lt;td&gt;BottomListAttribute &lt;/td&gt;
&lt;td&gt;optional parameters, the bottom list pop-up window attribute configuration &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;bottomGridAttribute &lt;/td&gt;
&lt;td&gt;BottomGridAttribute &lt;/td&gt;
&lt;td&gt;optional parameters, bottom grid list pop-up window attribute configuration &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;bottomListScrollAttribute&lt;/td&gt;
&lt;td&gt;BottomListScrollAttribute &lt;/td&gt;
&lt;td&gt;optional parameters, sliding list properties at the bottom &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;toastAttribute &lt;/td&gt;
&lt;td&gt;ToastAttribute &lt;/td&gt;
&lt;td&gt;optional parameter, Toast attribute configuration &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;loadingAttribute &lt;/td&gt;
&lt;td&gt;LoadingAttribute &lt;/td&gt;
&lt;td&gt;optional parameters, loading hint &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;isUseMainWindow &lt;/td&gt;
&lt;td&gt;boolean &lt;/td&gt;
&lt;td&gt;whether to use the main window or the child window, the default is the child window. &lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h3&gt;
  
  
  ContentAttribute attribute 
&lt;/h3&gt;

&lt;p&gt;ContentAttribute is a pop-up attribute configuration in the form of information or confirmation. &lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Property&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;type&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;overview&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;title &lt;/td&gt;
&lt;td&gt;string / Resource &lt;/td&gt;
&lt;td&gt;optional parameters, headers, no configuration required in global initialization &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;message &lt;/td&gt;
&lt;td&gt;string / Resource &lt;/td&gt;
&lt;td&gt;optional parameter, description information, no configuration required in global initialization &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;cancelText &lt;/td&gt;
&lt;td&gt;string / Resource&lt;/td&gt;
&lt;td&gt;Optional parameters, canceling text &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;confirmText &lt;/td&gt;
&lt;td&gt;string / Resource &lt;/td&gt;
&lt;td&gt;optional parameters, confirmation text &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;clickCancelHide &lt;/td&gt;
&lt;td&gt;boolean &lt;/td&gt;
&lt;td&gt;optional parameters, click to unhide by default &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;isHideTitle &lt;/td&gt;
&lt;td&gt;boolean &lt;/td&gt;
&lt;td&gt;optional parameter, whether to hide the title, default not to hide &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;clickCancel &lt;/td&gt;
&lt;td&gt;callback &lt;/td&gt;
&lt;td&gt;optional parameter, click to cancel callback event &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;clickConfirm &lt;/td&gt;
&lt;td&gt;callback &lt;/td&gt;
&lt;td&gt;optional parameters, click to confirm the callback event &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;bottomMenuHeight &lt;/td&gt;
&lt;td&gt;Length &lt;/td&gt;
&lt;td&gt;optional parameter, bottom button height &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;backgroundColor &lt;/td&gt;
&lt;td&gt;ResourceColor &lt;/td&gt;
&lt;td&gt;optional parameters, background color &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;radius &lt;/td&gt;
&lt;td&gt;BorderRadiuses / Length &lt;/td&gt;
&lt;td&gt;optional parameter, angle &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;titleAttribute&lt;/td&gt;
&lt;td&gt;TitleAttribute &lt;/td&gt;
&lt;td&gt;optional Parameters, Title Style Properties &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;messageAttribute &lt;/td&gt;
&lt;td&gt;MessageAttribute &lt;/td&gt;
&lt;td&gt;optional parameters, describing style properties &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;dividerHAttribute &lt;/td&gt;
&lt;td&gt;DividerHAttribute &lt;/td&gt;
&lt;td&gt;optional parameter, Horizontal Split Line Style attribute &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;dividerVAttribute &lt;/td&gt;
&lt;td&gt;DividerVAttribute &lt;/td&gt;
&lt;td&gt;optional Parameter, Vertical Split Line Style Property &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;confirmAttribute &lt;/td&gt;
&lt;td&gt;ConfirmAttribute &lt;/td&gt;
&lt;td&gt;optional Parameters, Confirm Style Properties &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;cancelAttribute &lt;/td&gt;
&lt;td&gt;CancelAttribute &lt;/td&gt;
&lt;td&gt;optional parameters, canceling style attributes &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;dialogAttribute &lt;/td&gt;
&lt;td&gt;DialogAttribute &lt;/td&gt;
&lt;td&gt;optional parameters, popup overall properties &lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h3&gt;
  
  
  BottomListAttribute attribute attribute 
&lt;/h3&gt;

&lt;p&gt;BottomListAttribute is the bottom list popup attribute configuration. &lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Property&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Type&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;overview&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;backgroundColor &lt;/td&gt;
&lt;td&gt;ResourceColor &lt;/td&gt;
&lt;td&gt;background Color &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;items &lt;/td&gt;
&lt;td&gt;string[] &lt;/td&gt;
&lt;td&gt;list Entry &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;itemClick &lt;/td&gt;
&lt;td&gt;(position: number) &lt;/td&gt;
&lt;td&gt;entry Click Callback &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;cancelClick &lt;/td&gt;
&lt;td&gt;() &lt;/td&gt;
&lt;td&gt;cancel Click Callback &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;isHideCancel &lt;/td&gt;
&lt;td&gt;boolean &lt;/td&gt;
&lt;td&gt;whether to hide the cancel button &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;isTransparent &lt;/td&gt;
&lt;td&gt;boolean &lt;/td&gt;
&lt;td&gt;transparent display &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;itemRadius &lt;/td&gt;
&lt;td&gt;Length / BorderRadiuses &lt;/td&gt;
&lt;td&gt;the overall angle of the entry after transparency &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;cancelRadius &lt;/td&gt;
&lt;td&gt;Length / BorderRadiuses &lt;/td&gt;
&lt;td&gt;transparent Post Cancel Button Angle &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;topLeftRadius &lt;/td&gt;
&lt;td&gt;Length&lt;/td&gt;
&lt;td&gt;dialog左上角角度&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;topRightRadius&lt;/td&gt;
&lt;td&gt;Length&lt;/td&gt;
&lt;td&gt;dialog右上角角度&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;itemAttr&lt;/td&gt;
&lt;td&gt;BottomListItem&lt;/td&gt;
&lt;td&gt;条目属性&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;itemDivider&lt;/td&gt;
&lt;td&gt;ListItemDivider&lt;/td&gt;
&lt;td&gt;分割线属性&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;cancelAttr&lt;/td&gt;
&lt;td&gt;BottomListCancel&lt;/td&gt;
&lt;td&gt;底部取消属性&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;dialogAttribute&lt;/td&gt;
&lt;td&gt;DialogAttribute&lt;/td&gt;
&lt;td&gt;弹窗总体属性&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h3&gt;
  
  
  BottomGridAttribute
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;属性&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;类型&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;概述&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;items&lt;/td&gt;
&lt;td&gt;BottomGridModel[]&lt;/td&gt;
&lt;td&gt;条目数据，用于网格&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;itemLineArray&lt;/td&gt;
&lt;td&gt;Array&lt;/td&gt;
&lt;td&gt;条目数据，用户每行展示几个，每行几个就几个数据&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;columnSize &lt;/td&gt;
&lt;td&gt;number &lt;/td&gt;
&lt;td&gt;number of columns, 2 columns by default &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;barTitleAttr &lt;/td&gt;
&lt;td&gt;BarTitleGridAttribute &lt;/td&gt;
&lt;td&gt;titlebar property of the edge on the grid &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;barHeight &lt;/td&gt;
&lt;td&gt;number &lt;/td&gt;
&lt;td&gt;the height of the titleBar on the upper edge of the grid &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;barCancelTextAttr &lt;/td&gt;
&lt;td&gt;BarCancelTextGridAttribute &lt;/td&gt;
&lt;td&gt;cancel attribute in titleBar &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;barCancelImageAttr &lt;/td&gt;
&lt;td&gt;BarCancelImageGridAttribute &lt;/td&gt;
&lt;td&gt;cancel the picture attribute in titleBar, and choose one from the text. &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;isBarCancelImage &lt;/td&gt;
&lt;td&gt;boolean &lt;/td&gt;
&lt;td&gt;whether the cancellation in titleBar is the image method, the default is false. &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;itemMarginTop &lt;/td&gt;
&lt;td&gt;number &lt;/td&gt;
&lt;td&gt;item Each row from top &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;backgroundColor &lt;/td&gt;
&lt;td&gt;ResourceColor &lt;/td&gt;
&lt;td&gt;background Color&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;topLeftRadius &lt;/td&gt;
&lt;td&gt;Length &lt;/td&gt;
&lt;td&gt;dialog Top Left Angle &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;topRightRadius &lt;/td&gt;
&lt;td&gt;Length &lt;/td&gt;
&lt;td&gt;dialog upper right corner angle &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;isHideBar &lt;/td&gt;
&lt;td&gt;boolean &lt;/td&gt;
&lt;td&gt;whether to hide titlebar &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;dialogAttribute &lt;/td&gt;
&lt;td&gt;DialogAttribute &lt;/td&gt;
&lt;td&gt;global dialog attribute &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;isItemAttrGlobal &lt;/td&gt;
&lt;td&gt;boolean &lt;/td&gt;
&lt;td&gt;whether the entry property is global, the default is &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;itemAttr &lt;/td&gt;
&lt;td&gt;ItemGridAttribute &lt;/td&gt;
&lt;td&gt;item Properties &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;itemClick &lt;/td&gt;
&lt;td&gt;(position: number) &lt;/td&gt;
&lt;td&gt;entry Click Callback &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;cancelClick &lt;/td&gt;
&lt;td&gt;() &lt;/td&gt;
&lt;td&gt;cancel Click Callback &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;dividerColor &lt;/td&gt;
&lt;td&gt;ResourceColor &lt;/td&gt;
&lt;td&gt;split line color&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;dividerHeight &lt;/td&gt;
&lt;td&gt;number &lt;/td&gt;
&lt;td&gt;split line height &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;isLastDividerShow &lt;/td&gt;
&lt;td&gt;boolean &lt;/td&gt;
&lt;td&gt;whether to display the last one. Default display &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;dividerMarginTop &lt;/td&gt;
&lt;td&gt;Margin / Length &lt;/td&gt;
&lt;td&gt;height of dividing line from upper edge &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;isShowBottomCancel &lt;/td&gt;
&lt;td&gt;boolean &lt;/td&gt;
&lt;td&gt;whether to display the bottom cancel button. By default, it is not displayed. &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;bottomCancelTextAttr &lt;/td&gt;
&lt;td&gt;CancelTextGridAttribute &lt;/td&gt;
&lt;td&gt;cancel button properties at the bottom &lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h3&gt;
  
  
  ToastAttribute attribute 
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;property&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;type&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;overview&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;msg &lt;/td&gt;
&lt;td&gt;string / Resource &lt;/td&gt;
&lt;td&gt;prompt information, no need for initialization &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;duration &lt;/td&gt;
&lt;td&gt;number &lt;/td&gt;
&lt;td&gt;pop-up time, default 2000 &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;backgroundColor&lt;/td&gt;
&lt;td&gt;ResourceColor&lt;/td&gt;
&lt;td&gt;背景颜色&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;fontColor&lt;/td&gt;
&lt;td&gt;ResourceColor&lt;/td&gt;
&lt;td&gt;字体颜色 ，默认ffffff&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;fontWeight&lt;/td&gt;
&lt;td&gt;number / FontWeight / string&lt;/td&gt;
&lt;td&gt;字体粗细设置，默认400&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;fontSize&lt;/td&gt;
&lt;td&gt;number / string / Resource&lt;/td&gt;
&lt;td&gt;字体大小，默认16&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;fontFamily&lt;/td&gt;
&lt;td&gt;string / Resource&lt;/td&gt;
&lt;td&gt;字体样式&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;borderRadius&lt;/td&gt;
&lt;td&gt;Length / BorderRadiuses&lt;/td&gt;
&lt;td&gt;角度&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;padding&lt;/td&gt;
&lt;td&gt;Padding / Length&lt;/td&gt;
&lt;td&gt;内边距&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;flexAlign&lt;/td&gt;
&lt;td&gt;FlexAlign&lt;/td&gt;
&lt;td&gt;位置方向&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;leftSrc&lt;/td&gt;
&lt;td&gt;PixelMap / ResourceStr/ DrawableDescriptor&lt;/td&gt;
&lt;td&gt;Picture on the left &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;rightSrc &lt;/td&gt;
&lt;td&gt;PixelMap / ResourceStr/ DrawableDescriptor &lt;/td&gt;
&lt;td&gt;picture on the right &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;topSrc &lt;/td&gt;
&lt;td&gt;PixelMap / ResourceStr/ DrawableDescriptor &lt;/td&gt;
&lt;td&gt;picture above &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;bottomSrc &lt;/td&gt;
&lt;td&gt;PixelMap / ResourceStr/ DrawableDescriptor &lt;/td&gt;
&lt;td&gt;picture below &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;imageMargin &lt;/td&gt;
&lt;td&gt;Length &lt;/td&gt;
&lt;td&gt;picture Distance Text Distance &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;imageWidth &lt;/td&gt;
&lt;td&gt;Length &lt;/td&gt;
&lt;td&gt;picture Width &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;imageHeight &lt;/td&gt;
&lt;td&gt;Length &lt;/td&gt;
&lt;td&gt;picture height &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;imageAlt &lt;/td&gt;
&lt;td&gt;string /Resource &lt;/td&gt;
&lt;td&gt;the percentage bitmap displayed when loading &lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h3&gt;
  
  
  DialogAttribute attribute 
&lt;/h3&gt;

&lt;p&gt;each pop-up window has a dialogAttribute attribute to control the overall pop-up window style. &lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Property&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Type&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;overview&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;windowAlignment &lt;/td&gt;
&lt;td&gt;DialogAlignment &lt;/td&gt;
&lt;td&gt;pop-up window position &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;dialogDismiss &lt;/td&gt;
&lt;td&gt;(action? :DismissDialogAction) =&amp;gt; void &lt;/td&gt;
&lt;td&gt;dialog hidden state callback &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;dialogAppear &lt;/td&gt;
&lt;td&gt;() =&amp;gt; void &lt;/td&gt;
&lt;td&gt;dialog display callback &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;windowBottomAnimation &lt;/td&gt;
&lt;td&gt;boolean &lt;/td&gt;
&lt;td&gt;whether to turn on bottom animation &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;isPrivacyMode &lt;/td&gt;
&lt;td&gt;boolean &lt;/td&gt;
&lt;td&gt;whether to prevent screenshots, the default is not &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;isSystemAnimation &lt;/td&gt;
&lt;td&gt;boolean &lt;/td&gt;
&lt;td&gt;whether the system is animated or not, the default is both &lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h2&gt;
  
  
  code Case 
&lt;/h2&gt;
&lt;h3&gt;
  
  
  1. Information pop-up window
&lt;/h3&gt;

&lt;p&gt;&lt;br&gt;
 &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;showDialogInfo({
Title: "I am the title",
Message: "I am a description",
clickConfirm: () =&amp;gt; {
//Confirm
Console.log (===Confirm)
//Hide()//Hide
}
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  2. Confirm/cancel pop-up window
&lt;/h3&gt;

&lt;p&gt;&lt;br&gt;
 &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;showDialogConfirm({
Title: "I am a title",
Message: "I am a description",
clickCancel: () =&amp;gt; {
//Cancel
Console.log ("===Cancel")
//Hide()//Hide
},
clickConfirm: () =&amp;gt; {
//Confirm
Console.log (===Confirm)
//Hide()//Hide
}
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  3. Bottom List
&lt;/h3&gt;

&lt;p&gt;&lt;br&gt;
 &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;showDialogBottomList({
Items: ["I am item one", "I am item two"],
itemClick: (position: number) =&amp;gt; {
console.log("==========:" + position)
}
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  4. Confirm the prompt information pop-up window
&lt;/h3&gt;

&lt;p&gt;&lt;br&gt;
 &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;showDialogConfirm({
Title: "I am a title",
Message: "I am a description",
isShowInformation: true, //Display Information
informationAttribute: {
checkboxSelect: true, //Is it selected by default
iconAttribute: {
srcSelect: $r("app.media.startIcon"), //Select
srcUnselected: $r("app.media.loading001"), //Not selected
},
onChange: (isChange) =&amp;gt; {
//Clicking changed the status
console.log("===" + isChange)
}
},
clickCancel: () =&amp;gt; {
//Cancel
//hide()
Console.log ("===Cancel")
},
clickConfirm: () =&amp;gt; {
//Confirm
Console.log (===Confirm)
}
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  5. Bottom List
&lt;/h3&gt;

&lt;p&gt;&lt;br&gt;
 &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;showDialogBottomList({
Items: ["I am item one", "I am item two"],
itemClick: (position: number) =&amp;gt; {
console.log("==========:" + position)
}
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  6. The bottom list is transparent
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;showDialogBottomList({
Items: ["I am item one", "I am item two"],
itemClick: (position: number) =&amp;gt; {
console.log("==========:" + position)
},
isTransparent: true,
dialogAttribute: {
dialogMarginLeft: 20,
dialogMarginRight: 20
}
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  7. Bottom List Multi-style
&lt;/h3&gt;

&lt;p&gt;&lt;br&gt;
 &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;showDialogBottomList({
ItemModels: [new BottomListModel ("Item 1", {fontColor: Color. Red}), new BottomListModel ("Item 2")],
itemClick: (position: number) =&amp;gt; {
hide()
}
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  8. Bottom Grid List
&lt;/h3&gt;

&lt;p&gt;&lt;br&gt;
 &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;showDialogBottomGrid({
columnSize: 4,
Items: [new BottomGridModel ("WeChat", $r ("app. media. app_icon")),
New BottomGridModel ("Moments", $r ("app. media. app_icon"),
new BottomGridModel("QQ", $r("app.media.app_icon")),
New BottomGridModel ("QQ Space", $r ("app. media. app_icon"),
New BottomGridModel (Weibo, $r (app. media. app_icon)),
New BottomGridModel (Weibo, $r (app. media. app_icon)),
New BottomGridModel (Weibo, $r (app. media. app_icon)),
New BottomGridModel ("Weibo", $r ("app. media. app_icon")
],
itemClick: (position) =&amp;gt; {
console.log("==============:" + position)
}
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  9. The bottom grid is distinguished by rows
&lt;/h3&gt;

&lt;p&gt;&lt;br&gt;
 &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;showDialogBottomGrid({
columnSize: 4,
isShowBottomCancel: true,
isHideBar: true,
itemLineArray: [
[new BottomGridModel ("Test", $r ("app. media. app_icon")),
New BottomGridModel ("Test", $r ("app. media. app_icon")),
[new BottomGridModel ("Test", $r ("app. media. app_icon")),
New BottomGridModel ("Test", $r ("app. media. app_icon"),
New BottomGridModel ("Test", $r ("app. media. app_icon"))
],
itemClick: (position) =&amp;gt; {
console.log("==============" + position)
}
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  10. Custom Component Pop-up Window 
&lt;/h3&gt;

&lt;p&gt;the first thing to do is to customize a &lt;strong&gt;global Components&lt;/strong&gt; , you can pass in custom components, or write the layout directly.&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;/*
* Author:AbnerMing
*Description: Custom pop ups, self defined layout
*/
@Builder
function BuilderDialog() {
Column() {
Text ("I am a custom pop-up")
.margin({ top: 30 })
Row() {
Button ("Cancel"). onClick()=&amp;gt;{
//Hide dialog
hide()
})
Button ("OK")
.margin({ left: 30 })
}.margin({ top: 20 })
.margin({ top: 30 })
}.backgroundColor(Color.White)
.width("60%")
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Code call&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;showDialog(wrapBuilder(BuilderDialog))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  11. Custom Component Pop-up Parameters 
&lt;/h3&gt;

&lt;p&gt;the first thing to do is to customize a &lt;strong&gt;global Components&lt;/strong&gt; , you can pass in custom components, or write the layout directly.&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;class DialogParams {
title? : string
}

@Builder
function BuilderDialogParams(params: DialogParams) {
Column() {
Text(params.title)
.margin({ top: 30 })
Row() {
Button ("Cancel"). onClick()=&amp;gt;{
//Hide dialog
hide()
})
Button ("OK")
.margin({ left: 30 })
}.margin({ top: 20 })
.margin({ top: 30 })
}.backgroundColor(Color.White)
.width("60%")
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Code call&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;let params = new DialogParams()
Params. title="I am the passed parameter"
showDialogParams(wrapBuilder(BuilderDialogParams), params)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  12. toast Tips
&lt;/h3&gt;

&lt;p&gt;&lt;br&gt;
 &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Toast ("I am an ordinary toast")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  13. toast changes the background
&lt;/h3&gt;

&lt;p&gt;&lt;br&gt;
 &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Toast ("I am a background changing Toast", {backgroundColor: Color. Red})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  14. toast changes position
&lt;/h3&gt;

&lt;p&gt;&lt;br&gt;
 &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Toast ("I am a relocated Toast", {alignment: DialogAlignment. Center})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  15. toast picture setting
&lt;/h3&gt;

&lt;p&gt;&lt;br&gt;
 &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Toast ("Toast Set Icon", {leftSrc: $r ("app. media. app_icon")})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  16. Bottom List
&lt;/h3&gt;

&lt;p&gt;&lt;br&gt;
 &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;showDialogBottomListScroll({
Items: ["Male", "Female"],
titleBarAttribute: {
Title Text: "Choose Gender"
},
confirmClick: (value, index) =&amp;gt; {
console.log(value + "=========" + index)
}
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  17. The bottom double list is not linked
&lt;/h3&gt;

&lt;p&gt;&lt;br&gt;
 &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;showDialogBottomListScroll({
selected: [1, 2],
Items: [["First Column 1", "First Column 2"], ["Second Column 1", "Second Column 2", "Second Column 3"],
titleBarAttribute: {
Title Text: "Bottom dual list not linked"
},
confirmClick: (value, index) =&amp;gt; {
console.log(value + "=========" + index)
}
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  18. Bottom double list linkage
&lt;/h3&gt;

&lt;p&gt;&lt;br&gt;
 &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;showDialogBottomListScroll({
items: this.doubleList,
titleBarAttribute: {
Title Text: "Bottom Double List Linkage"
},
confirmClick: (value, index) =&amp;gt; {
console.log(value + "=========" + index)
}
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  19, the bottom three list linkage
&lt;/h3&gt;

&lt;p&gt;&lt;br&gt;
 &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;showDialogBottomListScroll({
items: this.thirdList,
titleBarAttribute: {
Title Text: "Bottom Three List Linkage",
},
confirmClick: (value, index) =&amp;gt; {
console.log(value + "=========" + index)
}
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  20, year, month, day, hour, minute and second time pop-up window
&lt;/h3&gt;

&lt;p&gt;&lt;br&gt;
 &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;showDialogTime({
titleBarAttribute: {
Title Text: "Year Month Day Hour Minute Second Pop up",
},
timeAttribute: {
timeType: TimeDialogType.YMDHMS,
},
timeConfirmClick: (date) =&amp;gt; {
//Time callback
Console.log (===time result:+date)
},
confirmClick: (value, index) =&amp;gt; {
//Content and index callbacks
Console.log ("===Content result:"+value+"===Index result:"+index)
}
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  21, year, month, day, pop-up window
&lt;/h3&gt;

&lt;p&gt;&lt;br&gt;
 &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;showDialogTime({
titleBarAttribute: {
Title Text: "Month Day Hour Time Pop up",
},
timeAttribute: {
timeType: TimeDialogType.YMDHM
},
timeConfirmClick: (date) =&amp;gt; {
//Time callback
Console.log (===time result:+date)
},
confirmClick: (value, index) =&amp;gt; {
//Content and index callbacks
Console.log ("===Content result:"+value+"===Index result:"+index)
}
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  22, year, month, pop-up window
&lt;/h3&gt;

&lt;p&gt;&lt;br&gt;
 &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;showDialogTime({
titleBarAttribute: {
Title Text: "Year Month Day Pop up",
},
timeAttribute: {
startTime: "2022-6-12",
endTime: "2025-8-20",
},
timeConfirmClick: (date) =&amp;gt; {
//Time callback
},
confirmClick: (value, index) =&amp;gt; {
//Content and index callbacks
}
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  23, month and day pop-up window
&lt;/h3&gt;

&lt;p&gt;&lt;br&gt;
 &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;showDialogTime({
titleBarAttribute: {
Title Text: "Month Day Pop up",
},
timeAttribute: {
timeType: TimeDialogType.MD
},
timeConfirmClick: (date) =&amp;gt; {
//Time callback
},
confirmClick: (value, index) =&amp;gt; {
//Content and index callbacks
}
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  24, minutes and seconds pop-up window
&lt;/h3&gt;

&lt;p&gt;&lt;br&gt;
 &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;showDialogTime({
titleBarAttribute: {
Title Text: "Hours, minutes, seconds - Pop up",
},
timeAttribute: {
timeType: TimeDialogType.HMS,
},
timeConfirmClick: (date) =&amp;gt; {
//Time callback
},
confirmClick: (value, index) =&amp;gt; {
//Content and index callbacks
}
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  25, city address pop-up window
&lt;/h3&gt;

&lt;p&gt;&lt;br&gt;
 &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;showDialogAddress({
titleBarAttribute: {
Title Text: "City Address Pop up",
},
confirmClick: (value, index) =&amp;gt; {
}
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  26. PopupWindow pops up
&lt;/h3&gt;

&lt;p&gt;First of all, to define the pop-up components, custom can be, support custom component form, pass in can be&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;/**
* AUTHOR:AbnerMing
*INTRODUCE: Popup pop-up box, customizable, any component
* */
@Builder
function BuilderWindowView() {
Text ("I am any component")
.backgroundColor(Color.Pink)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h4&gt;
  
  
  arbitrary position
&lt;/h4&gt;

&lt;p&gt;&lt;br&gt;
 &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;showPopupWindow({
  view: wrapBuilder(BuilderWindowView),
  x: 60,
  y: 300
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h4&gt;
  
  
  top
&lt;/h4&gt;

&lt;p&gt;&lt;br&gt;
 &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;showPopupWindow({
  id: "popupTop",
  view: wrapBuilder(BuilderWindowView)
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h4&gt;
  
  
  down
&lt;/h4&gt;

&lt;p&gt;&lt;br&gt;
 &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;showPopupWindow({
  id: "popupBottom",
  view: wrapBuilder(BuilderWindowView),
  direction: PopupDirection.BOTTOM
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h4&gt;
  
  
  left
&lt;/h4&gt;

&lt;p&gt;&lt;br&gt;
 &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;showPopupWindow({
  id: "popupLeft",
  view: wrapBuilder(BuilderWindowView),
  direction: PopupDirection.LEFT
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h4&gt;
  
  
  right
&lt;/h4&gt;

&lt;p&gt;&lt;br&gt;
 &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;showPopupWindow({
  id: "popupRight",
  view: wrapBuilder(BuilderWindowView),
  direction: PopupDirection.RIGHT
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h4&gt;
  
  
  top Left
&lt;/h4&gt;

&lt;p&gt;&lt;br&gt;
 &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;showPopupWindow({
  id: "popupTopLeft",
  view: wrapBuilder(BuilderWindowView),
  direction: PopupDirection.TOP_LEFT
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h4&gt;
  
  
  top Right
&lt;/h4&gt;

&lt;p&gt;&lt;br&gt;
 &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;showPopupWindow({
  id: "popupTopRight",
  view: wrapBuilder(BuilderWindowView),
  direction: PopupDirection.TOP_RIGHT
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h4&gt;
  
  
  lower left
&lt;/h4&gt;

&lt;p&gt;&lt;br&gt;
 &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;showPopupWindow({
  id: "popupBottomLeft",
  view: wrapBuilder(BuilderWindowView),
  direction: PopupDirection.BOTTOM_LEFT
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h4&gt;
  
  
  lower right
&lt;/h4&gt;

&lt;p&gt;&lt;br&gt;
 &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;showPopupWindow({
  id: "popupBottomRight",
  view: wrapBuilder(BuilderWindowView),
  direction: PopupDirection.BOTTOM_RIGHT
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h4&gt;
  
  
  carry parameters
&lt;/h4&gt;

&lt;p&gt;&lt;br&gt;
 &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class WindowParams {
  title?: string
}

@Builder
  function BuilderWindowParams(params: WindowParams) {
    Text(params.title)
      .backgroundColor(Color.Pink)
  }


let params = new WindowParams()
params.title = "params"
showPopupWindow({
  id: "popupParams",
  params: params,
  viewParams: wrapBuilder(BuilderWindowParams),
  direction: PopupDirection.BOTTOM
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  use summary 
&lt;/h2&gt;

&lt;p&gt;each pop-up window has a unified hiding, just call the hide method directly. If you want the animation effect of the bottom pop-up window, there are currently two ways, one is the system's own, the other is custom, the system's own, animation is, the whole background slides together, the custom is that the background does not move, only the pop-up components move, the specific effect to use, mainly depends on your own needs, in addition, the pop-up animation at the bottom also encapsulates an animation component. BottomAnimationView can easily realize animation. You can also use it if you need it. There are also cases in related Demo. &lt;/p&gt;

&lt;p&gt;It should be noted that if there is a floating window in your project, it may appear that the pop-up pop-up window is in the window of the floating window. In order to solve this problem, you can choose whether to pop up the main window or the sub-window.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;initDialog({
      isUseMainWindow:true
    })
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>harmonyos</category>
    </item>
    <item>
      <title>HarmonyOS Development: How components implement dynamic setting of properties</title>
      <dc:creator>程序员一鸣</dc:creator>
      <pubDate>Mon, 30 Jun 2025 04:52:23 +0000</pubDate>
      <link>https://dev.to/abnerming888/harmonyos-development-how-components-implement-dynamic-setting-of-properties-3fa5</link>
      <guid>https://dev.to/abnerming888/harmonyos-development-how-components-implement-dynamic-setting-of-properties-3fa5</guid>
      <description>&lt;h2&gt;
  
  
  Foreword 
&lt;/h2&gt;

&lt;p&gt;this article is based on Api12 &lt;/p&gt;

&lt;p&gt;in many scenes, we need to dynamically choose whether to use the attributes of components, such as the display and hiding of components, such as the setting of background color change, the setting of height change, the setting of font size change, etc. In many scenes, we need different states to render our UI view. In non-declarative UI language, we can make logical judgment, that is if/else syntax to control the property settings of components, for example, in Android, to control the display and hiding of a component, we can do the following, pseudo-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;If (condition){
display
}else{
hide
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;for declarative languages, how can we dynamically control the setting of certain properties in ArkUI? &lt;/p&gt;

&lt;p&gt;For the setting of dynamic attributes, three usage methods are summarized, which can meet different business scenarios and hope to help you. &lt;/p&gt;
&lt;h2&gt;
  
  
  Way one, ternary operator, direct dynamic setting properties. 
&lt;/h2&gt;

&lt;p&gt;For example, if we want to dynamically display and hide a certain component according to the judgment of a state, we can do the following.&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;.visibility(this.isVisibility ? Visibility.Visible : Visibility.None)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;In the above code, we only need to control the variable isVisibility. For other attribute settings, such as color, size, background, etc. All attributes are basically used in the same way, not for example. &lt;/p&gt;
&lt;h2&gt;
  
  
  Method two, dynamic attribute attributeModifier control
&lt;/h2&gt;

&lt;p&gt;For Mode 1, there is a drawback. Although we theoretically control the state switching of the attribute, no matter what state it is, we must set this attribute, but the value is different. Is there any way to really control the setting of a certain attribute? After searching for official documents, there is indeed, that is, to use it the attribute modifier attribute is used to dynamically set an attribute. &lt;/p&gt;

&lt;p&gt;Of course, if it is only a simple attribute switch, such as background, color, text size, etc., the first method can be used, and the second method is more inclined to whether this attribute needs to be set instead of changing the value of its attribute, which we need to pay attention. &lt;/p&gt;

&lt;p&gt;For example, in a certain state, the height needs to be set to a fixed value, otherwise it is adaptive. For example, in a certain state, the side slip attribute is required, and in other states, it is not required. For example, in a certain state, the border attribute is required, and in other states, it is not required. Wait, there are many application scenarios, &lt;strong&gt;whenever a property needs to be set dynamically, we can use it.&lt;/strong&gt; &lt;strong&gt;attributeModifier&lt;/strong&gt; let's take a simple case. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The first step is to declare the required dynamic attributes, and the custom class implements the AttributeModifier interface to support most component attributes.&lt;/strong&gt;&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%2Fugjj2gbjbehahwfjowun.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%2Fugjj2gbjbehahwfjowun.png" alt="Image description" width="800" height="475"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At present, there are many methods to meet different business scenarios:&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;ApplyNormalAttribute (instance: T): void//The style of the component in its normal state.
Apply Pressed Attribute (instance: T): void//The style of the component's pressing state.
ApplyFocusedAttribute (instance: T): void//The style of the focused state of the component.
ApplyDisabled Attribute (instance: T): The style of the void//component's disabled state.
ApplySelectedAttribute (instance: T): void//Style of the selected state of the component
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class MyTextModifier implements AttributeModifier&amp;lt;TextAttribute&amp;gt; {
  textHeight?: Length


  applyNormalAttribute(instance: TextAttribute): void {
    if (this.textHeight != undefined) {

      instance.height(this.textHeight)
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;the second step, can be used directly:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
@State modifier: MyTextModifier = new MyTextModifier()


Text("text")
  .attributeModifier(this.modifier)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;the above is just a very simple case. The actual business scenario can be implemented by everyone according to their needs. &lt;/p&gt;

&lt;h2&gt;
  
  
  Way three, multi-component form
&lt;/h2&gt;

&lt;p&gt;Declarative UI supports Conditional rendering. For Mode 3, it can satisfy Mode 1 and Mode 2 at the same time. However, it is not recommended because the code is too redundant. For example, we need to implement the color setting of a component:&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;if(this.isColor){
  Text("text").fontColor(Color.Red)
}else {
  Text("text").fontColor(Color.Black)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;method 3 is not the switching of attributes or values, but the overall replacement of components. Although we can achieve the desired effect, dynamic control of attributes is not advocated. However, Method 3 is more friendly in dynamic switching of components, such as multi-item display. &lt;/p&gt;

&lt;h2&gt;
  
  
  Summary 
&lt;/h2&gt;

&lt;p&gt;if it is dynamic switching of attribute values, use mode one can meet the requirements, if it is dynamic setting of attributes, use mode two can be.&lt;/p&gt;

</description>
      <category>harmonyos</category>
    </item>
    <item>
      <title>HarmonyOS development: addition, deletion, modification and inspection of relational database encapsulation</title>
      <dc:creator>程序员一鸣</dc:creator>
      <pubDate>Mon, 30 Jun 2025 04:51:16 +0000</pubDate>
      <link>https://dev.to/abnerming888/harmonyos-development-addition-deletion-modification-and-inspection-of-relational-database-4jh5</link>
      <guid>https://dev.to/abnerming888/harmonyos-development-addition-deletion-modification-and-inspection-of-relational-database-4jh5</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;Foreword&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;this article is based on Api12 &lt;/p&gt;

&lt;p&gt;for persistent storage with less amount of data, we can choose user preferences or distributed key-value databases to operate. If the first two cannot be met, Hongmeng also provides us &lt;strong&gt;relational database&lt;/strong&gt; similar to Android, relational database is based on SQLite component and provides a complete mechanism for managing local database. It also provides a series of interfaces for adding, deleting, modifying and checking data. It is very convenient. In order to operate data more conveniently, a simple package is currently provided for the Api of the system. &lt;/p&gt;

&lt;p&gt;The content of this article is roughly as follows: &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Remote address dependency&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Database creation and table creation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Add, delete, change and check the database&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Use summary&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;i. Remote Address Dependency&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;set the three-party package dependency in the oh-package.json5 of the project. The configuration example 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;"dependencies": { "@abner/datastore": "^1.0.0"}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;OpenHarmony Tripartite Library Central Warehouse Address:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ohpm.openharmony.cn/#/cn/detail/@abner%2Fdatastore" rel="noopener noreferrer"&gt;https://ohpm.openharmony.cn/#/cn/detail/@abner%2Fdatastore &lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;second, database creation and table creation.&lt;/strong&gt;
&lt;/h2&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;1. Database creation&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;when the database is created, it will be created by default during initialization and can be initialized in the AbilityStage.&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;DbUtil.getInstance().init(this.context)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Property Introduction&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Property &lt;/th&gt;
&lt;th&gt;type &lt;/th&gt;
&lt;th&gt;overview &lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;context &lt;/td&gt;
&lt;td&gt;Context &lt;/td&gt;
&lt;td&gt;context &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;storeConfig &lt;/td&gt;
&lt;td&gt;relationalStore.StoreConfig &lt;/td&gt;
&lt;td&gt;database-related configuration, which can be not transmitted by default, will create a default abner_data.db database, securityLevel is S3,encrypt is true. &lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;storeConfig &lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;property &lt;/th&gt;
&lt;th&gt;type &lt;/th&gt;
&lt;th&gt;overview &lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;name &lt;/td&gt;
&lt;td&gt;string &lt;/td&gt;
&lt;td&gt;the database file name, which is also the database unique identifier. &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;securityLevel &lt;/td&gt;
&lt;td&gt;SecurityLevel &lt;/td&gt;
&lt;td&gt;set the database security level. &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;encrypt &lt;/td&gt;
&lt;td&gt;boolean &lt;/td&gt;
&lt;td&gt;specifies whether the database is encrypted. By default, the database is not encrypted. true: Encryption. false: Not encrypted. &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;dataGroupId &lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;The application Group ID, which needs to be obtained from the application market. Model Constraint: This property is only available under the Stage model. Starting with API version 10, this optional parameter is supported. Specifies to create an RdbStore instance in the sandbox path corresponding to this dataGroupId. If this parameter is not specified, the RdbStore instance is created in the application Sandbox Directory by default. &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;customDir &lt;/td&gt;
&lt;td&gt;string &lt;/td&gt;
&lt;td&gt;the database custom path. Usage constraint: The database path size is limited to 128 bytes. If it exceeds this size, the library will fail to open and an error will be returned. &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;autoCleanDirtyData &lt;/td&gt;
&lt;td&gt;boolean &lt;/td&gt;
&lt;td&gt;specifies whether to automatically clean up the data that is synchronized to the local after being deleted from the cloud. true indicates that the data is automatically cleaned up. false indicates that the data is manually cleaned up. By default, the data is automatically cleaned up. &lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;2. Data table creation&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;there are two ways to create data tables, one is to execute SQL statements and the other is to execute objects. &lt;/p&gt;

&lt;p&gt;SQL statement execution&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;DbUtil.getInstance()
  .executeSql("CREATE TABLE table_name(id INTEGER PRIMARY KEY AUTOINCREMENT,name VARCHAR(50),age INT)")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;object Form Execution [recommend]] &lt;/p&gt;

&lt;p&gt;the object form weakens the SQL statement, but it still creates the data table in the form of SQL. It is only the operation of the business layer. Without SQL operation, the execution is very simple and intuitive. The first parameter is the name of the data table, that is, table_name, and the second parameter is an object, that is, the field of the data table. For each field, necessary parameters such as primary key, self-increment, length, etc.&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;DbUtil.getInstance().createTable("table_name", {
  "id": { type: DbTableFieldType.INTEGER, isPrimaryKey: true, isAutoIncrement: true },
  "name": { type: DbTableFieldType.VARCHAR, length: 120 },
  "age": { type: DbTableFieldType.INT, length: 30 }
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Three, database addition, deletion, modification and inspection&lt;/strong&gt;
&lt;/h2&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;1, increase&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;normal storage&lt;/p&gt;

&lt;p&gt;You need to define a ValuesBucket object to pass.&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;const valueBucket1: ValuesBucket = {
  'name': "AbnerMing",
  'age': 18,
}
DbUtil.getInstance().insert("table_name", valueBucket1)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Object Storage&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;let bean = new DbDataBean()
bean.name = "AbnerMing"
bean.age = 18
DbUtil.getInstance().insertBean("table_name", bean)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;2, delete&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;normal Delete &lt;/p&gt;

&lt;p&gt;you need to use the RdbPredicates object to set filtering conditions. You can directly view the official website Api.&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;let deleteRdbPredicates = new relationalStore.RdbPredicates("table_name");
deleteRdbPredicates.equalTo("id", 1);

DbUtil.getInstance().delete(deleteRdbPredicates)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Object Delete &lt;/p&gt;

&lt;p&gt;this is similar to normal deletion, except that the RdbPredicates object is simply encapsulated and you need to call the filterRdbPredicates method to set the filter conditions.&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;DbUtil.getInstance()
  .filterRdbPredicates({ equalTo: { "id": 2 } })
  .deleteBean("table_name")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;3, change.&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Ordinary Modification&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;const valueBucket: ValuesBucket = {
  'name': "ming",
  'age': 28,
}

let upDataRdbPredicates = new relationalStore.RdbPredicates("table_name");
upDataRdbPredicates.equalTo("id", 1)

DbUtil.getInstance().update(upDataRdbPredicates, valueBucket)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;object Modification &lt;/p&gt;

&lt;p&gt;the filterRdbPredicates method is the filter condition, that is, which piece of data you want to change.&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;let uBean = new DbDataBean()
uBean.name = "Ming"
uBean.age = 20
DbUtil.getInstance()
  .filterRdbPredicates({ equalTo: { "id": 2 } })
  .updateBean("table_name", uBean)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;4, check&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;common Query&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;let predicates = new relationalStore.RdbPredicates("table_name");

DbUtil.getInstance().query(predicates, (resultSet: relationalStore.ResultSet) =&amp;gt; {
 while (resultSet.goToNextRow()) {
    const id = resultSet.getLong(resultSet.getColumnIndex("id"));
    const name = resultSet.getString(resultSet.getColumnIndex("name"));
    const age = resultSet.getLong(resultSet.getColumnIndex("age"));
  }
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;object Query &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;get All&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DbUtil.getInstance()
  .queryAllBean&amp;lt;DbDataBean&amp;gt;("table_name", (data) =&amp;gt; {

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;get single&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DbUtil.getInstance()
  .filterRdbPredicates({ equalTo: { "id": 1 } })
  .queryBean&amp;lt;DbDataBean&amp;gt;("table_name", (data) =&amp;gt; {

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;5. filterRdbPredicates&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;in the addition, deletion, modification and inspection of object operations, this method cannot be ignored, and the executable attributes are as follows: &lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;property &lt;/th&gt;
&lt;th&gt;type &lt;/th&gt;
&lt;th&gt;overview &lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;orderByDesc &lt;/td&gt;
&lt;td&gt;string &lt;/td&gt;
&lt;td&gt;configures the predicate to match the values in the field column of the data table to the column sorted in descending order.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;orderByAsc &lt;/td&gt;
&lt;td&gt;string &lt;/td&gt;
&lt;td&gt;configure the predicate to match the values in the field column of the data table in ascending order. &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;limitAs &lt;/td&gt;
&lt;td&gt;number &lt;/td&gt;
&lt;td&gt;predicate to set the maximum number of data records &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;offsetAs &lt;/td&gt;
&lt;td&gt;number &lt;/td&gt;
&lt;td&gt;configure the predicate to specify the starting position of the returned result &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;equalTo &lt;/td&gt;
&lt;td&gt;{} &lt;/td&gt;
&lt;td&gt;configure the predicate to match the field in the field column of the data table with the value value value. &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;notEqualTo &lt;/td&gt;
&lt;td&gt;{} &lt;/td&gt;
&lt;td&gt;configure the predicate to match a field whose value is not value in the field column of the data table &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;contains &lt;/td&gt;
&lt;td&gt;{} &lt;/td&gt;
&lt;td&gt;configure the predicate to match a field with value in the field column of the data table &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;between &lt;/td&gt;
&lt;td&gt;{} &lt;/td&gt;
&lt;td&gt;configure the predicate to match the fields in the field column of the data table with values in the given range (including range boundaries), for example: low = high, with the equal sign. &lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;IV. Use Summary&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Each method is reserved for multiple calling methods, such as using callback asynchronous callback or Promise asynchronous callback, or synchronous execution. In the process of using, you can selectively call according to your own business needs, and also expose the successful and failed methods respectively, which can be targeted to determine whether the execution is successful in the process of execution. &lt;/p&gt;

&lt;p&gt;The following cases:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DbUtil.getInstance().delete(deleteRdbPredicates,
                            (rows: number)=&amp;gt;{

                            },
                            (err: BusinessError)=&amp;gt;{

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

&lt;/div&gt;



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