Location>code7788 >text

Hongmeng NEXT Development Case: Face Character Finder

Popularity:672 ℃/2024-12-14 21:57:52

 

【引言】

本文将介绍一个名为“颜文字搜索器”的开发案例,该应用是基于鸿蒙NEXT平台构建的,旨在帮助用户快速查找和使用各种风格的表情符号。通过本案例的学习,读者可以了解如何在鸿蒙平台上进行数据处理、UI设计以及交互逻辑的实现。

【环境准备】

• 操作系统:Windows 10

• 开发工具:DevEco Studio NEXT Beta1 Build Version: 5.0.3.806

• 目标设备:华为Mate60 Pro

• 开发语言:ArkTS

• 框架:ArkUI

• API版本:API 12

【Development Ideas】

1. Data model design

In order to represent information about a single emoticon, we define an EmoticonBean class that contains the style, type, the emoticon itself and its meaning. In addition, a boolean property isShown is added to keep track of whether an emoticon should be shown to the user, which helps to dynamically update the list during searches.

2. UI components and layout

The main interface of the application consists of an Index component, which is responsible for the overall layout. The upper part of the interface is a search box that allows the user to enter keywords to filter the list of emoticons. The bottom part is a table that shows all the eligible emoji, with each row consisting of four parts: style, type, emoji and meaning. To enhance the user experience, when the user clicks on an emoji or the highlighted text in its meaning, a corresponding click event is triggered and a log message is output.

3. Data loading and processing

The data for the emoticons comes from a local JSON file () that is read and parsed into an array of EmoticonBean objects before the component is first rendered. Each time the user modifies the content of the search box, the splitAndHighlight method is called to split the meaning of each emoticon and check if there is a matching keyword. If there is, the isShown property is set to true, otherwise it is false, which controls whether the emoticon is displayed in the interface.

4. Searching and highlighting

The splitAndHighlight function is used to split the meaning of an emoticon into multiple segments according to the keyword and return an array of these segments. Segments that contain keywords are highlighted in a different color in the interface to visually point out the matches. Additionally, this function determines whether an emoji is visible or not based on whether or not there is a match, ensuring that only relevant emoji are shown to the user.

5. User interaction

In order to let the user have a better operation experience, we implement the touch event listener on the interface to automatically close the keyboard when the user clicks on a non-input area. This not only ensures a neat interface, but also simplifies the user's operation process.

[complete code]

Data source: src/main/resources/rawfile/

/download/zhongcongxu01/90126325

coding

// Introduce the necessary tool libraries util for text decoding etc.
import { util } from '@'
// Introduce the BusinessError class for handling business logic errors.
import { BusinessError } from '@'
// Introduce the inputMethod module to manage input method behavior.
import { inputMethod } from '@'
 
// Define a data model that can be observed EmoticonBean represents information about a single emoticon
@ObservedV2
class EmoticonBean {
  // Define the style attribute and initialize it to the empty string
  style: string = ""
  // Define the type attribute and initialize to the empty string
  type: string = ""
  // Define the emoji itself and initialize it to the empty string
  emoticon: string = ""
  // Define the meaning attribute and initialize it to the empty string
  meaning: string = ""
 
  // Constructor that allows the above properties to be set when the object is created
  constructor(style: string, type: string, emoticon: string, meaning: string) {
     = style
     = type
     = emoticon
     = meaning
  }
 
  // Define the emoji status tag to be shown or not, defaults to true, use @Trace decorator to make it traceable to changes
  @Trace isShown: boolean = true
}
 
// Use the @Entry and @Component decorators to define the Index component as the application entry point.
@Entry
@Component
struct Index {
  // Define a state variable, textInput, to store the text content of the search box, which defaults to an empty string.
  @State private textInput: string = ''
  // Define a state variable emoticonList to store the list of emoticons, defaults to an empty array.
  @State private emoticonList: EmoticonBean[] = []
 
  // Define the line color property
  private lineColor: string = "#e6e6e6"
  // Define the header background color property
  private titleBackground: string = "#f8f8f8"
  // Define the text color attribute
  private textColor: string = "#333333"
  // Define the base fill size
  private basePadding: number = 4
  // Define the line width
  private lineWidth: number = 2
  // Define the cell height
  private cellHeight: number = 50
  // Define column weight ratios
  private weightRatio: number[] = [1, 1, 5, 4]
  // Define the base font size
  private baseFontSize: number = 14
 
  // Define a method splitAndHighlight to split and highlight keywords in an emoji's meaning.
  private splitAndHighlight(item: EmoticonBean, keyword: string): string[] {
    let text =  // Get the text of the meaning of the emoticon
    if (!keyword) { // If there is no keyword, the entire text is returned directly and the emoji is displayed
       = true
      return [text]
    }
    let segments: string[] = []; // Used to store split text fragments
    let lastMatchEnd: number = 0; // Record where the last match ended
    while (true) { // Loop over keywords to find their position in the text
      const matchIndex = (keyword, lastMatchEnd); // Find where keywords appear
      if (matchIndex === -1) { // If no keywords are found, add the remaining text to the segments and exit the loop
        ((lastMatchEnd));
        break;
      } else { // If keywords are found, add the non-keyword and keyword sections to the segments separately
        ((lastMatchEnd, matchIndex)); // Non-keyworded section
        ((matchIndex, matchIndex + )); // Keyword section
        lastMatchEnd = matchIndex + ;
      }
    }
    // Set emoji to display if a keyword is present
     = ((keyword) != -1)
    return segments;
  }
 
  // This method is called when the component is about to appear on the screen and is used to load the emoji data
  aboutToAppear() {
    // Read the contents of a local file from Explorer.
    getContext().("", (err: BusinessError, data) => {
      if (err) { // If the read fails, print an error message
        ('getRawFileContent error: ' + (err))
        return
      }
      // Create a text decoder to convert binary data to strings
      let textDecoder = ('utf-8', { ignoreBOM: true })
      let jsonString = (data, { stream: false })
      let jsonObjectArray: object[] = (jsonString) // Parsing a JSON string into an array of objects
      for (let i = 0; i < ; i++) { // Iterate through the array of objects to fill the emoticonList.
        let item = jsonObjectArray[i]
        (new EmoticonBean(item['s'], item['t'], item['e'], item['m']))
      }
      try {
        // Print the emoticonList to the console for debugging.
        (`:${(, null, '\u00a0\u00a0')}`)
      } catch (err) {
        ('parse error: ' + (err))
      }
    })
  }
 
  // Define the build method to build the component's UI structure.
  build() {
    Column({ space: 0 }) { // Create a column container with no spacing between internal elements
      // The search box component, bound to the textInput state variable.
      Search({ value: $$ })
        .margin() // Setting the outer margin
        .fontFeature("\"ss01\" on") // Setting font characteristics
      // Create a column container for table headers
      Column() {
        Row() { // Create a row for the table header
          // Header text: Style
          Text('Style')
            .height('100%') // Set the height to 100% of the parent container
            .layoutWeight([0]) // Assigning widths based on weights
            .textAlign() // Center-align text
            .fontSize() // Setting the font size
            .fontWeight(600) // Set the font thickness
            .fontColor() // Set the text color
          // Split Line
          Line().height('100%').width().backgroundColor()
          // Header text: type
          Text('Type')
            .height('100%')
            .layoutWeight([1])
            .textAlign()
            .fontSize()
            .fontWeight(600)
            .fontColor()
          // Split Line
          Line().height('100%').width().backgroundColor()
          // Header text: Emoji
          Text('Expressions')
            .height('100%')
            .layoutWeight([2])
            .textAlign()
            .fontSize()
            .fontWeight(600)
            .fontColor()
          // Split Line
          Line().height('100%').width().backgroundColor()
          // Header text: meaning
          Text('Meaning')
            .height('100%')
            .layoutWeight([3])
            .textAlign()
            .fontSize()
            .fontWeight(600)
            .fontColor()
        }.height().borderWidth().borderColor()
        .backgroundColor() // Set the background color
      }.width(`100%`).padding({ left: , right:  })
 
      // Create a scroll container Scroll containing a list of emoji.
      Scroll() {
        Column() {
          // ForEach loop through the emoticonList array, creating one emoticon entry per row.
          ForEach(, (item: EmoticonBean) => {
            Row() {
              // Style of displaying emoticons
              Text()
                .height('100%')
                .layoutWeight([0])
                .textAlign()
                .fontSize()
                .fontColor()
              // Split Line
              Line().height('100%').width().backgroundColor()
              // Display the type of emoticon
              Text()
                .height('100%')
                .layoutWeight([1])
                .textAlign()
                .fontSize()
                .fontColor()
              // Split Line
              Line().height('100%').width().backgroundColor()
              // Show emoticons
              Text()
                .height('100%')
                .layoutWeight([2])
                .textAlign()
                .fontSize()
                .fontColor()
                .copyOption() // Allow copying to clipboard
              // Split Line
              Line().height('100%').width().backgroundColor()
              // Display the meaning of emoticons, with support for keyword highlighting
              Text() {
                ForEach((item, ), (segment: string, index: number) => {
                  ContainerSpan() {
                    Span(segment)
                      .fontColor(segment ===  ?  : ) // Set font color based on whether it's a keyword or not
                      .onClick(() => { // Setting up the click event listener
                        (`Highlighted text clicked: ${segment}`); // Print the text message of the click
                        (`Click index: ${index}`); // Print the index information of the click
                      });
                  }.textBackgroundStyle({
                    color: segment ===  ?  :  // Set background color based on whether it's a keyword or not
                  });
                });
              }
              .height('100%')
              .layoutWeight([3])
              .textAlign()
              .fontSize()
              .fontColor()
              .padding({ left: , right:  })
            }
            .height()
            .borderWidth({ left: , right: , bottom:  })
            .borderColor()
            // Visibility of emoticons is determined by their state (whether they are displayed or not)
            .visibility( ?  : )
          })
        }.width(`100%`).padding({ left: , right:  })
      }.width('100%').layoutWeight(1).align()
      // Touch event handling to disable keyboard input when the user clicks on a blank area
      .onTouch((event) => {
        if ( == ) { // If it's a press event
          ().stopInputSession() // Stop the current input session
        }
      })
    }.width('100%').height('100%').backgroundColor(); // Set the container's width, height and background color
  }
}