目录

应用内浏览文档上滑时不流畅

问题现象

应用内浏览文档上滑时不流畅,下滑正常。

背景知识

问题定位

  1. 通过UIViewer工具获取到发生问题页面的组件结构是Scroll组件中嵌套Web页面,并且Web组件同一层级还有两个Column容器。此时应用可滑动区域是由三个容器组成的。

  2. 使用DevTools工具抓取加载的Web页面,可以看到页面右侧有滚动条,且支持上下滑动。

  3. 通过滚轮将Web页面滑动至顶部,此时再次在手机上尝试滑动,发现无卡顿现象,使用UIViewer根据抓取此时的组件结构。此时应用可滑动区域是由Web组件单独构成的。

  4. 使用DevEco Profiler Frame模板抓取滑动过程的Trace信息,搜索关键字User events、H:WEB_LIST_FLING、H:TRAILING_ANIMATION。结合应用包名泳道中与浏览器内核相关的线程情况,可以看到前六次滑动手势操作的均为Scroll组件,后两次滑动手势才真正滑动了Web页面,此时浏览器内核相关线程才开始处理渲染Web页面。

    在代码中搜索关键字NestedScrollMode,发现设置滚动方式为PARENT_FIRST,父组件优先滚动到边缘后自身滚动。以下是相关代码:

    import webview from "@ohos.web.webview";
    
    @Entry
    @Component
    struct NestedScroll {
      private scrollerForScroll: Scroller = new Scroller();
      private web = new webview.WebviewController();
    
      build() {
        Flex() {
          Scroll(this.scrollerForScroll) {
            Column() {
              Column(){
                Text("Scroll Area1.1")
                  .width("100%")
                  .height("5%")
                  .backgroundColor(0X330000FF)
                  .fontSize(16)
                  .textAlign(TextAlign.Center)
                Text("Scroll Area1.2")
                  .width("100%")
                  .height("5%")
                  .backgroundColor(0X330000FF)
                  .fontSize(16)
                  .textAlign(TextAlign.Center)
                Text("Scroll Area1.3")
                  .width("100%")
                  .height("5%")
                  .backgroundColor(0X330000FF)
                  .fontSize(16)
                  .textAlign(TextAlign.Center)
              }
              Column(){
                Text("Scroll Area2.1")
                  .width("100%")
                  .height("5%")
                  .backgroundColor(0X540000FF)
                  .fontSize(16)
                  .textAlign(TextAlign.Center)
                Text("Scroll Area2.2")
                  .width("100%")
                  .height("5%")
                  .backgroundColor(0X540000FF)
                  .fontSize(16)
                  .textAlign(TextAlign.Center)
              }
    
              Web({
                src: $r('app.string.test_url'), // 测试时请替换成实际地址
                controller: this.web
              })
                .width("100%")
                .height("100%")
                .nestedScroll({
                  scrollForward: NestedScrollMode.PARENT_FIRST,
                  scrollBackward: NestedScrollMode.SELF_FIRST
                })
                .fileAccess(false)
                .geolocationAccess(false)
            }
          }
          .width("100%")
          .height("100%")
        }
        .width('100%')
        .height('100%')
        .backgroundColor(0xDCDCDC)
        .padding({
          left: 20,
          right: 20,
          top: 50,
          bottom: 20
        })
      }
    }

分析结论

Scroll组件嵌套Web时,存在其他与Web组件同一层级的容器,发生手势识别冲突,导致Web页面滑动卡顿。

修改建议

使用触摸测试控制来规避此种情况,给显示在上层的节点设置hitTestBehavior为HitTestMode.BLock。

import webview from "@ohos.web.webview";

@Entry
@Component
struct NestedScroll {
  private scrollerForScroll: Scroller = new Scroller();
  private web = new webview.WebviewController();

  build() {
    Flex() {
      Scroll(this.scrollerForScroll) {
        Column() {
          Column(){
            Text("Scroll Area1.1")
              .width("100%")
              .height("5%")
              .backgroundColor(0X330000FF)
              .fontSize(16)
              .textAlign(TextAlign.Center)
            Text("Scroll Area1.2")
              .width("100%")
              .height("5%")
              .backgroundColor(0X330000FF)
              .fontSize(16)
              .textAlign(TextAlign.Center)
            Text("Scroll Area1.3")
              .width("100%")
              .height("5%")
              .backgroundColor(0X330000FF)
              .fontSize(16)
              .textAlign(TextAlign.Center)
          }
          Column(){
            Text("Scroll Area2.1")
              .width("100%")
              .height("5%")
              .backgroundColor(0X540000FF)
              .fontSize(16)
              .textAlign(TextAlign.Center)
            Text("Scroll Area2.2")
              .width("100%")
              .height("5%")
              .backgroundColor(0X540000FF)
              .fontSize(16)
              .textAlign(TextAlign.Center)
          }

          Web({
            src: $r('app.string.test_url'), // 测试时请替换成实际地址
            controller: this.web
          })
            .width("100%")
            .height("100%")
            .hitTestBehavior(HitTestMode.Block)
            .fileAccess(false)
            .geolocationAccess(false)
        }
      }
      .width("100%")
      .height("100%")
    }
    .width('100%')
    .height('100%')
    .backgroundColor(0xDCDCDC)
    .padding({
      left: 20,
      right: 20,
      top: 50,
      bottom: 20
    })
  }
}