DEV Community

HarmonyOS
HarmonyOS

Posted on

How to Implement Chat List Functionality Using the List Component

Read the original article:How to Implement Chat List Functionality Using the List Component

How to Implement Chat List Functionality Using the List Component

Requirement Description

The chat list is an important feature in instant messaging. This example provides several common implementation methods.

Background Knowledge

In HarmonyOS, the List component is used in various scenarios such as product displays, chat pages, and invoice pages. The @Watch decorator is used to monitor state variables. If you need to track changes in a specific state variable, you can use @Watch to set a callback function for it.

Implementation Steps

  • Scenario 1: Display new data starting from the bottom when received.
    Implementation Principle: Use @Watch to monitor changes in the data source. When the data source changes, if the List is not already scrolled to the bottom, automatically scroll the List to the bottom.

  • Scenario 2: Load the message list from the bottom and click a button to return to the latest position.
    Implementation Principle: Setting the stackFromEnd property of the List component to true enables layout loading from the bottom. By binding scrollEdge to the bottom edge of the List, you can achieve a jump back to the latest position.

Note: The property stackFromEnd is supported from API version 19.

Code Snippet / Configuration

  • Scenario 1:
  @Component
  export struct Chat {
    // This list represents the chat content. Each time a message is sent or received, 
    // the chat content is added to this list.
    // When the list changes, the function scrollerBottom is executed to scroll the list to the bottom.
    @Prop @Watch('scrollerBottom') list: string[] = [];
    scroller: Scroller = new Scroller();

    scrollerBottom() {
      this.scroller.scrollEdge(Edge.Bottom);
    }

    build() {
      // initialIndex represents the index from which the list starts displaying when created.
      // Choosing the last index allows the latest messages at the bottom to be shown.
      // scroller binds the scroll event, working with the List watcher to make sure that
      // whenever messages are sent or received, the view scrolls to the bottom.
      List({ initialIndex: this.list.length - 1, scroller: this.scroller }) {
        ForEach(this.list, (item: string) => {
          ListItem() {
            Text(item)
              .fontWeight(FontWeight.Bold);
          };
        });
      }
      .width('100%')
      .height('100%');
    }
  }

  @Entry
  @Component
  struct ListChat {
    @State message: string[] = [];
    count: number = 0;

    build() {
      Column() {
        Chat({ list: this.message })
          .width('50%')
          .backgroundColor('#F1F3F5');
        Button('New message +1')
          .onClick(() => {
            this.message.push('New message' + (this.count++).toString());
          })
          .margin({ top: 20 })
          .backgroundColor('#0A59F7');
      }
      .height('50%')
      .width('100%')
      .justifyContent(FlexAlign.Center)
      .alignItems(HorizontalAlign.Center);
    }
  }
Enter fullscreen mode Exit fullscreen mode
  • Scenario 2:
  @Entry
  @Component
  struct ListBottom {
    @State listContent: Array<string> = ['Old message'];
    listScroller: ListScroller = new ListScroller();

    build() {
      Column() {
        List({ space: 10, scroller: this.listScroller }) {
          ForEach(this.listContent, (value: string) => {
            ListItem() {
              Text(value);
            }
            .width('90%')
            .height(200)
            .border({
              width: 1,
              radius: 20,
              color: Color.Black
            })
            .backgroundColor('#ffdddddd');
          });
        }
        .width('100%')
        .height('90%')
        .stackFromEnd(true) // Set to true to make the list layout start from the bottom
        .alignListItem(ListItemAlign.Center)
        .scrollBar(BarState.Off)
        .border({
          width: 1,
          color: '#ffdddddd'
        });

        Row() {
          Button('Add')
            .onClick(() => {
              this.listContent.push('New message ' + this.listContent.length.toString());
            });

          Button('Scroll to latest position')
            .onClick(() => {
              this.listScroller.scrollEdge(Edge.Bottom); // Scroll the list to the bottom edge
            });
        }
        .width('100%')
        .justifyContent(FlexAlign.SpaceAround);
      }
      .width('100%')
      .height('100%')
      .justifyContent(FlexAlign.SpaceBetween);
    }
  }
Enter fullscreen mode Exit fullscreen mode

Test Results

  • Scenario 1: 1.gif
  • Scenario 2: 2.gif

Limitations or Considerations

This example supports API Version 20 Release and above.
This example supports HarmonyOS 6.0.0 Release SDK and above.
This example requires DevEco Studio 6.0.0 Release and above for compilation and execution.

Written by Bunyamin Akcay

Top comments (0)