HarmonyOS 鸿蒙Next中关于应用接续长列表的

HarmonyOS 鸿蒙Next中关于应用接续长列表的 目前版本是最新版,我想问一下,长列表接续,就是我手机浏览到一般,接续到平板,平板可以直接从这一半中继续浏览,我想问一下,如果页面有两个滑动容器,外面Scroll,里面是List,然后我按照文档上把OnDidScroll和OnDidBuilde都配置到Scroll了,List我没配置,现在可以监听到Scroll滑动的距离,但是这个距离有最大值,我没搞懂,还有就是,手机看一般,平板并不能跳转到手机的对应位置,这怎么解决啊?

6 回复

【背景知识】

应用接续,指当用户在一个设备上操作某个应用时,可以在另一个设备的同一个应用中快速切换,并无缝衔接上一个设备的应用体验。比如在用户使用过程中,使用情景发生了变化,之前使用的设备不再适合继续当前任务,或者周围有更合适的设备,此时用户可以选择使用新的设备来继续当前的任务。接续完成后,之前设备的应用可退出或保留,用户可以将注意力集中在被拉起的设备上,继续执行任务。

【解决方案】

Scroll嵌套List,浏览进度接续。

// EntryAbility.ets
// 冷启动取出浏览进度
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
  if (launchParam.launchReason === AbilityConstant.LaunchReason.CONTINUATION) {
    // 将上述的保存的数据取出恢复
    if (want.parameters !== undefined) {
      want.parameters.currentOffset && AppStorage.setOrCreate('continueOffset', want.parameters.currentOffset);
      AppStorage.setOrCreate('setCurrentOffset', true);
    }
    // 触发页面恢复
    this.context.restoreWindowStage(this.storage);
  }
}

// EntryAbility.ets
// 热启动取出浏览进度
onNewWant(want: Want, launchParam: AbilityConstant.LaunchParam): void {
  console.info(`EntryAbility onNewWant ${AbilityConstant.LaunchReason.CONTINUATION}`)
  if (launchParam.launchReason === AbilityConstant.LaunchReason.CONTINUATION) {
    // 将上述的保存的数据取出恢复
    if (want.parameters !== undefined) {
      want.parameters.currentOffset && AppStorage.setOrCreate('continueOffset', want.parameters.currentOffset);
      AppStorage.setOrCreate('setCurrentOffset', true);
    }
    this.context.restoreWindowStage(this.storage);
  }
}

// EntryAbility.ets
// 接续生命周期保存
onContinue(wantParam: Record<string, Object>) {
  console.info('Ability onContinue');
  // 迁移数据保存
  let currentOffset = AppStorage.get('continueOffset') as number;
  wantParam.currentOffset = currentOffset;

  return AbilityConstant.OnContinueResult.AGREE;
}

// PageContinue.ets
@StorageLink('continueOffset') continueOffset: number = 0; // 接续偏移量
@StorageLink('setCurrentOffset') setCurrentOffset: boolean = false; // 是否启用设置偏移量

onDidBuild(): void {
  if (this.setCurrentOffset) {
    // 渲染前使用控制器调整滚动位置
    this.scroller.scrollTo({ xOffset: 0, yOffset: this.continueOffset });
    this.setCurrentOffset = false;
  }
}

build() {
  Scroll(this.scroller) {
    List({ space: 20, initialIndex: 0 }) {
      LazyForEach(this.arr, (item: number) => {
        ListItem() {
          Text('' + item)
        }
      }, (item: number) => item.toString())
    }
    .listDirection(Axis.Vertical) // 排列方向
    .scrollBar(BarState.Off)
    .edgeEffect(EdgeEffect.Spring) // 边缘效果设置为Spring
    .width('90%')
  }
  .onDidScroll((scrollOffset: number, scrollState: ScrollState) => {
    if (!this.setCurrentOffset) {
      this.continueOffset = this.scroller.currentOffset()?.yOffset;
    }
  })
  .width('100%')
  .height('100%')
}

更多关于HarmonyOS 鸿蒙Next中关于应用接续长列表的的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


两个设备上的接续都存在list的话楼主可以考虑这个回调来记录已经阅读到的位置,切换设备了过后结合scrollToItemInGroup主动跳转到这个位置:

cke_926.png

找HarmonyOS工作还需要会Flutter的哦,有需要Flutter教程的可以学学大地老师的教程,很不错,B站免费学的哦:https://www.bilibili.com/video/BV1S4411E7LY/?p=17

若仅监听外层Scroll的滚动事件,获取的滚动距离仅代表外层容器自身的滑动范围。当内层List产生独立滚动时,该数值无法覆盖内层滚动偏移量。List组件自带懒加载特性,与外层Scroll的滚动监听存在冲突,会导致位置计算不准确。试试下面的办法?

同时为外层Scroll和内层List配置onScroll事件,将内外层偏移量转换为全局坐标后存储

Scroll(this.outerScroller) {

  List() {

    // List内容

  }

  .onScroll((offset: number) => {

    this.saveInnerOffset(offset)

  })

}

.onScroll((offset: number) => {

  this.saveOuterOffset(offset)

})

在保存滚动位置时需同时记录分页状态:

interface ContinueData {

  scrollOffset: number;  // 总滚动距离

  pageIndex: number;     // 当前页码

  itemIndex: number;     // 首条可见项索引

}

在目标设备恢复时需等待组件渲染完成:

aboutToAppear() {

  setTimeout(() => { // 等待布局完成

    this.outerScroller.scrollTo({

      x: 0,

      y: savedData.scrollOffset

    })

  }, 50)

}

在HarmonyOS Next中,应用接续长列表通过分布式数据管理和流转框架实现。系统利用分布式软总线技术,使应用在不同设备间无缝迁移并保持列表状态。通过统一的跨端数据管理机制,长列表数据可在多设备间同步,确保用户操作连续性。应用需使用ArkUI声明式开发范式,结合分布式数据对象与跨设备组件通信能力,实现列表状态实时同步与高效渲染。

问题可能出在内外滑动容器的联动处理上。Scroll和List都需要配置OnDidScroll和OnDidBuild,否则无法准确同步滚动位置。建议检查List是否遗漏了接续配置,并确保两个容器都正确注册了滑动事件。另外,最大距离限制可能是由于容器高度计算差异导致的,需要确认滚动位置传递逻辑是否一致。

回到顶部