HarmonyOS 鸿蒙Next List组件中swipeAction显示尺寸问题

发布于 1周前 作者 sinazl 来自 鸿蒙OS

HarmonyOS 鸿蒙Next List组件中swipeAction显示尺寸问题 List组件中删除某个Item后调用DataSource的notifyDataReload,swipeAction自动出现,且尺寸不对

代码如下:

@Entry
@Component
struct CollectListPage {

  @State state: CollectListState = new CollectListState()
  vm: CollectListViewModel | null = null
  @State dataSource: BasicDataSource<NewsModel> = this.state.newsList

  aboutToAppear() {
    this.vm = new CollectListViewModel(this.state)
  }

  build() {
    Column() {
      this.buildTitle()
      Divider().vertical(false).color('#E1E1E1').height(1)
      
      if (this.state.newsList.totalCount() == 0) {
        this.buildEmpty()
      } else {
        this.buildBody()
      }
      this.buildFooter()
    }.width('100%').height('100%')
  }

  @Builder
  private buildTitle() {

    RelativeContainer() {
      Text('我的收藏')
        .fontColor('#222222')
        .fontSize(18)
        .textAlign(TextAlign.Center)
        .fontWeight(500)
        .alignRules(AlignRules.CENTER)
        .id('title')
        .backgroundColor(Color.White)

      Image(ResManager.getBackIcon())
        .width(24)
        .height(24)
        .margin({ left: 14 })
        .onClick(() => {
          router.back()
        })
        .id('back')
        .alignRules(AlignRules.LEFT_CENTER)

      Text(this.state.isEdit ? '取消' : '编辑')
        .fontColor(this.state.isEdit ? '#ee2b2a' : '#3d3d3d')
        .fontSize(16)
        .alignRules(AlignRules.RIGHT_CENTER)
        .id('edit')
        .onClick(() => {
          this.state.isEdit = !this.state.isEdit
          this.vm?.reset()
        })
        .padding({ right: 14 })
    }
    .height(44)
    .width('100%')
    .backgroundColor(Color.White)
  }

  @Builder
  private buildBody() {

    List({space:0}) {
      LazyForEach(this.dataSource, (item: NewsModel, index: number) => {
        ListItem() {
          EditNewsItem({
            isEdit: this.state.isEdit, news: item, onSelectChangeListener: (isSelected) => {
              isSelected ? this.state.selectCount++ : this.state.selectCount--
            }
          })
        }
        .swipeAction({
          end: this.state.isEdit ? null : { builder: () => this.buildSwipeDelete(index) },
          edgeEffect: SwipeEdgeEffect.None
        })
      })

      ListItem() {
        Text('已显示全部收藏')
          .fontSize(16)
          .fontColor('#a4a4a4')
          .width('100%')
          .textAlign(TextAlign.Center)
          .margin({ top: 15, bottom: 40 })
      }
    }.layoutWeight(1).cachedCount(2)
  }

  @Builder
  private buildEmpty() {
    
    if (this.state.loadFinish) {
      Text('您还没有收藏内容哦~')
        .fontSize(16)
        .fontColor('#A4A4A4')
        .width('100$')
        .height('100%')
        .textAlign(TextAlign.Center)
    } else {
      LoadingIndicator()
    }
  }

  @Builder
  private buildSwipeDelete(item: number) {

    if (this.state.isEdit) {
      Row().width(0).height(0)
    } else {
      Column(){
        Text('删除')
          .width(80)
          .textAlign(TextAlign.Center)
          .fontSize(15)
          .fontColor(Color.White)
          .onClick(() => {
            this.vm?.delItem(item)
          }).layoutWeight(1)
      }.backgroundColor(Color.Red)
    }
  }

  @Builder
  private buildFooter() {
    
    if (this.state.isEdit) {
      Row() {
        
        Image(this.state.selectCount == this.state.newsList.totalCount() ? $r('app.media.radio_button_checked') : $r('app.media.radio_button_normal'))
          .width(20)
          .height(20).onClick(() => {
          this.vm?.selectAll()
        }).objectFit(ImageFit.Contain)

        Row().width(10)
        
        Text('全选').fontColor('#3D3D3D').fontSize(15).onClick(() => {
          this.vm?.selectAll()
        })

        Row().layoutWeight(1)

        Text(this.state.selectCount == 0 ? '删除' : `删除(${this.state.selectCount})`)
          .height(26)
          .width(140)
          .textAlign(TextAlign.Center)
          .backgroundColor(this.state.selectCount == 0 ? Color.Gray : '#CC2B2A')
          .borderRadius(5)
          .fontColor(Color.White)
          .fontSize(15)
          .onClick(() => {
            this.vm?.delBatch()
          })
      }
      .height(40)
      .width('100%')
      .padding({ left: 10, right: 10 })
      .borderColor({ top: '#d9d9d9' })
      .borderWidth({ top: 1 })
    }
  }
}

@Component
export struct EditNewsItem {

  @Prop isEdit: boolean
  @ObjectLink news: NewsModel
  onSelectChangeListener: (selected: boolean) => void | null = null

  build() {
    Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center }) {
      if (this.isEdit) {
        Image(this.news.is_selected ? $r('app.media.radio_button_checked') : $r('app.media.radio_button_normal'))
          .width(20)
          .height(20)
          .objectFit(ImageFit.Contain).margin({ left: 14 })
      }

      Row() {
        NewsItem({
          newsModel: this.news,
          isHotChannel: false,
          comeFromHomePage: false,
          comeFromSearchResult: false,
          canCache: false
        })
      }
      .flexShrink(1).width('100%')
    }.onClick(() => {
      console.error(this.news.title)
      if (this.isEdit) {
        this.news.is_selected = !this.news.is_selected
        this.onSelectChangeListener && this.onSelectChangeListener(this.news.is_selected)
      }
    })
  }
}

@Observed
export class CollectListState {
  newsList: BasicDataSource<NewsModel> = new BasicDataSource()
  isEdit: boolean = false
  selectCount: number = 0
  loadFinish: boolean = false
}

export class CollectListViewModel extends BaseViewModel<void, CollectListState> {
  page: number = 1
  onCreate(): void {
    this.page = 1
    this.getCollectList()
  }

  getCollectList() {
    const param = new LightWeightMap<string, string>()
    param.set('device_id', AppStorage.get<string>(CommonConstants.DEVICE_ID))
    param.set('page', this.page + '')
    param.set('os', 'android')
    LoginUtils.addUserInfo(param)
    HttpManager.getInstance().post<Array<NewsModel>>(Api.COLLECT_LIST, param).then((response) => {
      let news = JSONUtils.text2ClsArr<NewsModel, NewsModel>(NewsModel, response.data)
      if (news != null) {
        this.state.newsList.addAll(news)
      }
      this.state.loadFinish = true
    })
  }

  selectAll() {
    if (this.state.selectCount == this.state.newsList.totalCount()) {
      this.state.selectCount = 0
      for (let i = 0; i < this.state.newsList.totalCount(); i++) {
        this.state.newsList.getData(i).is_selected = false
      }
    } else {
      this.state.selectCount = this.state.newsList.totalCount()
      for (let i = 0; i < this.state.newsList.totalCount(); i++) {
        this.state.newsList.getData(i).is_selected = true
      }
    }
  }

  async delItem(index: number) {
    const result = await this.delete(index)
    if (result) {
      this.state.newsList.notifyDataDelete(index)
    }
  }

  private async delete(index: number): Promise<boolean> {
    const param = new LightWeightMap<string, string>()
    const news = this.state.newsList.getData(index)
    param.set('device_id', AppStorage.get<string>(CommonConstants.DEVICE_ID))
    param.set('os', 'android')
    param.set('aid', news.aid)
    param.set('type', news.type.toString())
    LoginUtils.addUserInfo(param)
    let result = false
    await HttpManager.getInstance().post<void>(Api.DEL_COLLECT, param).then(() => {
      this.state.newsList.deleteData(index)
      console.error('del success:' + index)
      result = true
    }).catch((e: NetError) => {
      promptAction.showToast({ message: e.message })
      result = false
    })
    return result
  }

  async delBatch() {
    for (let i = 0; i < this.state.newsList.totalCount(); i++) {
      if (this.state.newsList.getData(i).is_selected) {
        await this.delete(i)
      }
    }
    this.state.isEdit = false
    this.state.newsList.notifyDataReload()
  }

  reset() {
    this.state.selectCount = 0
    for (let i = 0; i < this.state.newsList.totalCount(); i++) {
      this.state.newsList.getData(i).is_selected = false
    }
  }
}

更多关于HarmonyOS 鸿蒙Next List组件中swipeAction显示尺寸问题的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html

2 回复

SwipeActionOptions的start和end对应的@builder函数中顶层必须是单个组件,不能是if/else、ForEach、LazyForEach语句。你使用了if语句也用到了多个组件,可以使用单个组件优化一下代码看看。

参考链接:https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/ts-container-listitem-0000001881250681-V5#ZH-CN_TOPIC_0000001881250681__swipeactionoptions%E5%AF%B9%E8%B1%A1%E8%AF%B4%E6%98%8E

更多关于HarmonyOS 鸿蒙Next List组件中swipeAction显示尺寸问题的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS鸿蒙系统中,Next List组件的swipeAction显示尺寸问题通常与布局配置和组件的样式属性有关。以下是对该问题的直接回答:

  1. 检查布局文件:

    • 确认swipeAction所在列表项的布局文件是否正确设置。特别是宽度(width)和高度(height)属性,以及margin(边距)和padding(内边距)的设置,这些都可能影响swipeAction的显示尺寸。
  2. 调整组件样式:

    • 在组件的样式定义中,检查是否有针对swipeAction的特定样式设置,如背景大小、图标大小等。调整这些样式属性可以改变swipeAction的显示尺寸。
  3. 适配屏幕尺寸:

    • 如果swipeAction在不同屏幕尺寸上显示不一致,考虑使用响应式布局或动态调整组件尺寸以适应不同屏幕尺寸。
  4. 检查约束条件:

    • 确认swipeAction是否受到其他布局约束或父容器的限制,这些约束可能会影响其显示尺寸。

如果以上方法仍未解决swipeAction显示尺寸的问题,可能是由于系统版本或组件库的bug导致的。此时,建议直接联系官网客服获取更专业的帮助。官网地址是:https://www.itying.com/category-93-b0.html

回到顶部