HarmonyOS 鸿蒙Next中共享元素转场返回上一个页面闪白问题

HarmonyOS 鸿蒙Next中共享元素转场返回上一个页面闪白问题 共享元素转场返回上一个页面会产生闪白问题,是系统自带的还是bug,如何解决?期待大佬的恢复!!此致敬礼🫡

//SearchPageOne.ts  第一个页面

import { CommonHeader } from "../../ui_components/CommonHeader";
import { curves } from "@kit.ArkUI";

export const search_id:string = 'SEARCH_ONE_SHOT_DEMO_TRANSITION_ID'

@ComponentV2
struct SearchPageOne {
  @Consumer('pathStack') pathStack:NavPathStack = new NavPathStack();

  onBackPress(): boolean {
    this.pathStack.pop(false);
    return true;
  }

  toPageTwo(){
    this.getUIContext().animateTo({curve:curves.interpolatingSpring(1,2,348,33)},() => {
      this.pathStack.pushPathByName('SearchPageTwo',undefined,false);
    })
  }

  @Builder
  content(){
    Column(){
      Search({placeholder:'please input the content'})
        .width('90%')
        .height(40)
        .borderRadius(20)
        .borderWidth(1)
        .borderColor(Color.Orange)
        .geometryTransition(search_id,{follow:true})
        .onClick(() => {
          this.toPageTwo();
        })

      Image($r('app.media.flower'))
        .width('80%')
        .height(50)
        .borderRadius(10)
        .geometryTransition('iamge_id')
    }
    .width('100%')
    .height('100%')
    .backgroundColor(Color.Green)
    // .transition(TransitionEffect.OPACITY)

  }

  build() {
    NavDestination(){
      this.content();
    }
    .title('搜索一镜到底')
  }
}

@Builder
export function pageBuilder(){
  SearchPageOne();
}
//SearchPageTwo.ts  第二个页面
import { CommonHeader } from "../../ui_components/CommonHeader";
import { curves } from "@kit.ArkUI";
import { search_id } from "./SearchPageOne";

@ComponentV2
struct SearchPageTwo {
  @Consumer('pathStack') pathStack:NavPathStack = new NavPathStack();

  onBackPress(): boolean {
    this.pathStack.pop(false);
    return true;
  }

  aniPop(){
    this.getUIContext().animateTo({curve:curves.interpolatingSpring(0,1,342,38)},() => {
      this.pathStack.pop(false);
    })
  }

  @Builder
  content(){
    Column(){
      Row({space:5}){
        Image($r('app.media.left_arrow'))
          .width(25)
          .height(25)
          .fillColor(Color.Green)
          .backgroundColor(Color.Grey)
          .padding(5)
          .borderRadius(15)
          .onClick(() => {
            this.aniPop()
          })
          .transition(TransitionEffect.asymmetric(
            TransitionEffect.OPACITY
              .animation({ duration: 200, delay: 150, curve: curves.cubicBezierCurve(0.33, 0, 0.67, 1) }),
            TransitionEffect.OPACITY
              .animation({ duration: 200, curve: curves.cubicBezierCurve(0.33, 0, 0.67, 1) })
          ))

        Search({placeholder:'please input the content'})
          .layoutWeight(1)
          .height(40)
          .borderWidth(1)
          .borderColor(Color.Red)
          .borderRadius(20)
          .geometryTransition(search_id,{follow:true})

      }

      .margin(20)
        Image($r('app.media.flower'))
          .width(300)
          .height(300)
          .borderRadius(300)
          .borderWidth(5)
          .borderColor(Color.Orange)
          .shadow({color:Color.Grey,radius:10})
          .geometryTransition('iamge_id')
    }
    .width('100%')
    .height('100%')
    .backgroundColor(Color.Green)

  }

  build() {
    NavDestination(){
      this.content();
    }
    .hideTitleBar(true)
    .onBackPressed(() => {
      this.aniPop()
      return true;
    })
    // .transition(TransitionEffect.OPACITY)


  }
}

@Builder
export function pageBuilder(){
  SearchPageTwo();
}

更多关于HarmonyOS 鸿蒙Next中共享元素转场返回上一个页面闪白问题的实战教程也可以访问 https://www.itying.com/category-93-b0.html

6 回复

共享元素转场返回上一个页面时出现闪白问题,通常与转场动画过程中的背景色渲染或默认转场动画冲突有关。以下是基于鸿蒙文档的准确、完整和清晰的解答:

问题原因分析

闪白问题在转场动画中常见,可能原因包括:

  1. 背景色不匹配或透明:转场过程中,如果页面背景色未设置或不透明,可能会出现视觉衔接问题,导致闪白。
  2. 系统默认转场动画未禁用:共享元素转场(如使用 geometryTransition)需要关闭系统默认的转场动画,否则可能发生动画冲突,造成闪白。
  3. 转场动画配置不协调animateTo 中的动画曲线或时长设置不当,可能导致转场不平滑。

解决方案

根据文档内容,解决闪白问题的关键步骤如下:

1. 设置一致且不透明的背景色

  • 确保两个页面的背景色相同且不透明,以避免转场过程中出现颜色跳变。
  • 在您的代码中,两个页面都已设置 backgroundColor(Color.Green),这是一致的。但建议同时为 NavDestination 设置背景色,确保全覆盖:
// 在 SearchPageOne 和 SearchPageTwo 的 build 方法中
NavDestination() {
  // 内容
}
.backgroundColor(Color.Green) // 添加背景色
  • 参考文档《js-components-common-transition.md》中注意事项:“配置自定义转场时,建议配置页面背景色为不透明颜色,否则在转场过程中可能会出现衔接不自然的现象。”

2. 禁用系统默认转场动画

  • 共享元素转场需显式关闭系统默认转场动画。对于 Navigation 组件,可通过在页面组件中配置 pageTransitionNone 来禁用默认动画:
// 在 SearchPageOne 和 SearchPageTwo 中添加 pageTransition 方法
pageTransition() {
  PageTransitionEnter({ type: RouteType.None }) // 禁用进入动画
  PageTransitionExit({ type: RouteType.None })  // 禁用退出动画
}

3. 启用组件的透明度转场效果

  • 为页面内容容器(如 Column)添加透明度转场效果(TransitionEffect.OPACITY),使页面内容淡入淡出,增强平滑度:
// 在 SearchPageOne 和 SearchPageTwo 的 content Builder 中,取消注释 .transition(TransitionEffect.OPACITY)
Column() {
  // 内容
}
.transition(TransitionEffect.OPACITY) // 启用透明度转场

4. 优化 animateTo 动画参数

  • 确保 animateTo 中的动画曲线和时长设置合理,避免过快或过慢的动画导致视觉不适。您的代码中使用了 interpolatingSpring 曲线,可尝试调整参数或使用标准曲线(如 Curve.Ease)测试:
// 例如,在 aniPop 方法中尝试更平滑的曲线
this.getUIContext().animateTo({
  curve: Curve.Ease, // 或 curves.cubicBezierCurve(0.33, 0, 0.67, 1)
  duration: 300      // 适当时长
}, () => {
  this.pathStack.pop(false);
});

完整代码调整示例

基于您的代码,以下是修改建议(关键部分):

// SearchPageOne.ts
@ComponentV2
struct SearchPageOne {
  // ... 现有代码

  pageTransition() {
    PageTransitionEnter({ type: RouteType.None })
    PageTransitionExit({ type: RouteType.None })
  }

  @Builder
  content() {
    Column() {
      // ... 现有内容
    }
    .width('100%')
    .height('100%')
    .backgroundColor(Color.Green)
    .transition(TransitionEffect.OPACITY) // 启用透明度转场
  }

  build() {
    NavDestination() {
      this.content()
    }
    .backgroundColor(Color.Green) // 为 NavDestination 设置背景色
    .title('搜索一镜到底')
  }
}
// SearchPageTwo.ts
@ComponentV2
struct SearchPageTwo {
  // ... 现有代码

  pageTransition() {
    PageTransitionEnter({ type: RouteType.None })
    PageTransitionExit({ type: RouteType.None })
  }

  @Builder
  content() {
    Column() {
      // ... 现有内容
    }
    .width('100%')
    .height('100%')
    .backgroundColor(Color.Green)
    .transition(TransitionEffect.OPACITY) // 启用透明度转场
  }

  build() {
    NavDestination() {
      this.content()
    }
    .backgroundColor(Color.Green) // 为 NavDestination 设置背景色
    .hideTitleBar(true)
    .onBackPressed(() => {
      this.aniPop()
      return true;
    })
  }
}

注意事项

  • 如果问题仍未解决,请检查是否还有其他全局动画或样式冲突。

如果以上步骤仍无法解决问题,建议提供更多上下文或检查设备日志以进一步调试。

更多关于HarmonyOS 鸿蒙Next中共享元素转场返回上一个页面闪白问题的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


谢谢大佬,

这边使用所给的两个页面进行测试,没有出现返回上一个页面会产生闪白的现象。猜测可能是页面中有变量控制了组件的显示,需要补全复现代码(如最小复现demo),让参与用户更快速复现您的问题;测试代码的子页面为所给页面代码,测试的根页面代码如下:

import { pageABuilder } from './PageA';
import { pageBBuilder } from './PageB';

@Entry
@Component
struct Index {
  @State message: string = 'Hello World';

  @Provide('pathStack') naviStack:NavPathStack = new NavPathStack();
  @Builder
  pathMap(name:string){
    if(name=="PageA"){
      pageABuilder()
    }else if(name =="PageB"){
      pageBBuilder()
    }
  }
  build() {
    Navigation(this.naviStack) {
      Column() {
        Text(this.message)
          .id('HelloWorld')
          .fontSize(50)
          .fontWeight(FontWeight.Bold)
          .alignRules({
            center: { anchor: '__container__', align: VerticalAlign.Center },
            middle: { anchor: '__container__', align: HorizontalAlign.Center }
          })

        Button("A").onClick(()=>{
          this.naviStack.pushPath({name:"PageA"})
        })
        Button("B").onClick(()=>{
          this.naviStack.pushPath({name:"PageB"})
        })
      }
    }.navDestination(this.pathMap)
    .height('100%')
    .width('100%')
  }
}

谢谢大佬,

鸿蒙Next中共享元素转场闪白问题通常由页面渲染机制引起。该现象可能源于共享元素动画执行过程中页面背景未正确初始化或过渡动画未完全同步。建议检查页面生命周期回调,确保共享元素转场前后页面渲染状态一致。可通过调整转场动画参数或使用系统提供的转场优化接口缓解此问题。

共享元素转场返回时出现闪白问题通常与页面渲染时机和动画同步有关。从代码来看,问题可能出在以下方面:

  1. 页面背景色差异:两个页面都使用了Color.Green作为背景,但返回时可能存在短暂的重绘延迟。可以尝试在NavDestination层级设置统一的背景色。

  2. 动画曲线配置:进出页面使用的interpolatingSpring参数不一致(第一个页面是(1,2,348,33),返回时是(0,1,342,38)),可能导致动画结束时出现视觉断层。建议使用相同的曲线参数保持一致性。

  3. 缺少过渡效果:虽然代码中注释了.transition(TransitionEffect.OPACITY),但在共享元素转场中,建议为整个页面容器添加透明度过渡:

NavDestination()
.transition(TransitionEffect.opacity(0.99).animation({ duration: 300 }))
  1. 硬件加速问题:可以尝试为共享元素添加显式的GPU加速:
.geometryTransition(search_id, { follow: true })
.graphicsLayer({ compositing: true })

建议优先调整动画曲线一致性并添加页面级透明度过渡,这能有效缓解闪白现象。

回到顶部