DEV Community

HarmonyOS
HarmonyOS

Posted on

How to Slide the Grid Width to the Last Item and Align It to the Left

Read the original article:How to Slide the Grid Width to the Last Item and Align It to the Left

Requirement Description

In a custom Grid component scenario, the requirement is to make the grid slide horizontally so that the last item aligns neatly to the left edge of the screen. Without handling, the last column may leave extra spacing or misalignment, leading to poor user experience.

Background Knowledge

  • In ArkUI, a Grid can be used with a Scroller for horizontal paging.
  • Each GridItem defines its own width. If the total items cannot fill a complete page width, the last items may leave empty space.
  • By adding an additional filler GridItem with a fixed width, we can ensure alignment to the left when sliding to the last item.
  • Developers often use autoScrollPage logic with scrollTo() to snap the grid to a page boundary.

Implementation Steps

  1. Define the data model (BsAIStoryListInfo, BsAIStoryMusicInfo, etc.).
  2. Populate the list with items and bind them to the Grid.
  3. Define a custom autoScrollPage(scroller) function to control paging by calculating scrollPageWidth.
  4. Insert an extra 90px width GridItem at the end to handle alignment.
  5. Use .onScrollStop() event to trigger auto-alignment when the user stops scrolling.

Code Snippet / Configuration

@Builder
buildGridView(list: BsAIStoryMusicInfo[], scroller: Scroller) {
  Grid(scroller) {
    ForEach(list, (item: BsAIStoryMusicInfo, index) => {
      GridItem() {
        Row() {
          if (item.cover_info?.url && item.title && item.synthetic_tip && item.audio_info?.format_duration) {
            this.builderAudioInfo(
              item.cover_info?.url, 
              item.title, 
              item.synthetic_tip,
              item.audio_info?.format_duration
            )
          }
        }
        .width(387.6923076923077 - 90) // Page width minus filler
      }
      .onClick(() => {
        // this.playIndex(index)
      })
    })

    // Add filler GridItem to align last column
    GridItem() { }
      .width(90)
  }
  .padding({ left: 20 })
  .rowsTemplate('1fr 1fr 1fr')
  .layoutDirection(GridDirection.Column)
  .height(190)
  .width('100%')
  .cachedCount(3)
  .scrollBar(BarState.Off)
  .onScrollStop(() => {
    this.autoScrollPage(scroller)
  })
}

autoScrollPage(scroller: Scroller) {
  let pageIndex = Math.floor(scroller.currentOffset().xOffset / this.scrollPageWidth)
  let toOffsetX = pageIndex * this.scrollPageWidth
  if (scroller.currentOffset().xOffset > toOffsetX + this.scrollPageWidth / 2.0) {
    let toIndex = pageIndex + 1
    toOffsetX = toIndex * this.scrollPageWidth
  }
  scroller.scrollTo({
    xOffset: toOffsetX,
    yOffset: scroller.currentOffset().yOffset,
    animation: true
  })
}
Enter fullscreen mode Exit fullscreen mode

Test Results

  • Tested with multiple lists of different lengths:
    • If the last row had fewer items, the filler ensured left alignment.
    • Scrolling stopped correctly aligned to each "page" without extra blank space.
  • User experience improved by eliminating uneven black spacing on the right edge.

Limitations or Considerations

  • Requires maintaining scrollPageWidth accurately (should equal grid item width × number of items per row).
  • Filler GridItem must match the spacing reserved in the paging calculation (here 90px).
  • If data changes dynamically, ensure to re-run alignment logic via refreshRawDataSource().

Written by Arif Emre Ankara

Top comments (0)