HarmonyOS 沉浸光感详情页实战:大图头部、吸顶栏与滚动渐变

详情页做沉浸光感,最容易翻车的位置不是正文,而是顶部。大图头部很好看,但返回按钮看不清;吸顶栏出现太晚,用户滚动后不知道当前页面标题;正文卡片上浮过度,又会遮住图片重点。详情页的光感设计必须跟滚动阶段绑定,而不是把一张大图固定在顶部。

请添加图片描述

本文围绕一个具体目标展开:在 HarmonyOS 应用详情页中,把大图头部、透明导航、吸顶栏、正文区域和底部操作拆成可维护链路,让滚动过程自然、可读、可操作。

一、详情页先分三段:首屏、中段、吸顶

详情页不是一个静态页面。用户刚进入时看的是大图和主标题;向下滚动时看的是核心信息;继续滚动后,吸顶栏接管导航和标题。三段状态要分别设计。

阶段 用户关注点 视觉策略
首屏 看大图、标题、关键按钮 透明导航,按钮加底色保护
中段 读摘要和关键指标 导航逐渐变实,正文卡片上浮
吸顶 持续阅读和返回 固定标题栏,背景弱化
底部操作 开始导航、预约、购买 保持稳定,不跟随头图变化

请添加图片描述

如果三段不拆,页面会出现“首屏很好看,滚动后难用”的问题。

二、资料与版本边界:本文写详情页滚动视觉链路

本文示例面向 HarmonyOS NEXT / ArkTS / ArkUI 工程,重点在应用层:大图头部模型、滚动进度计算、吸顶栏可见性、按钮安全区、正文可读性和验收排查。具体背景、模糊、组件和安全区能力,以读者当前 SDK 与华为开发者文档为准。

请添加图片描述

参考资料:

  1. HarmonyOS 新能力一览
    https://developer.huawei.com/consumer/cn/features/6-1
  2. ArkUI 背景设置相关属性
    https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-universal-attributes-background
  3. ArkTS 声明式开发范式
    https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-ui-development
  4. HarmonyOS 应用设计指南
    https://developer.huawei.com/consumer/cn/design/

三、头部模型:大图、标题和按钮要拆开

详情页头部不要只保存一张图片地址。至少要保存图片亮度、标题、安全区按钮和是否允许吸顶。

export interface DetailHeroHeader {
  imageUrl: string;
  title: string;
  subtitle: string;
  imageLuminance: number;
  allowStickyTitle: boolean;
  safeTopVp: number;
}

export function createRouteDetailHeader(): DetailHeroHeader {
  return {
    imageUrl: 'route_sunrise_header.png',
    title: '日出峰顶路线',
    subtitle: '12.6 km · 预计 5-6 h',
    imageLuminance: 0.46,
    allowStickyTitle: true,
    safeTopVp: 44
  };
}

这段模型的边界是详情页头部事实。它不处理滚动,也不直接绘制 UI。这样拆开后,标题栏、按钮保护和正文布局都能复用同一份头部信息。

四、滚动进度:不要用多个魔法数字散落页面

滚动渐变要稳定,核心是把 scrollOffset 转成一个 0 到 1 的进度。页面各层都根据进度变化,而不是各自写阈值。

export interface DetailScrollProgress {
  offset: number;
  progress: number;
  phase: 'hero' | 'blending' | 'sticky';
}

export function calculateDetailScrollProgress(offset: number, heroHeight: number): DetailScrollProgress {
  const triggerStart = heroHeight * 0.28;
  const triggerEnd = heroHeight * 0.72;

  if (offset <= triggerStart) {
    return { offset, progress: 0, phase: 'hero' };
  }
  if (offset >= triggerEnd) {
    return { offset, progress: 1, phase: 'sticky' };
  }

  return {
    offset,
    progress: (offset - triggerStart) / (triggerEnd - triggerStart),
    phase: 'blending'
  };
}

代码解释:

  • hero 阶段保留大图沉浸感。
  • blending 阶段让导航栏、标题、遮罩同步变化。
  • sticky 阶段以阅读为主,导航栏固定可读。

如果不用统一进度,容易出现标题栏已经显示但按钮还看不清,或者正文已经上浮但头图遮罩没退场。

五、透明导航:按钮必须先可见,再谈融合

详情页顶部按钮通常浮在大图上,返回和收藏不能因为背景亮度变化而消失。建议把按钮样式从头图亮度中推导。

export interface DetailTopButtonStyle {
  iconColor: string;
  containerColor: string;
  containerOpacity: number;
  borderVisible: boolean;
}

export function resolveDetailTopButtonStyle(imageLuminance: number): DetailTopButtonStyle {
  if (imageLuminance > 0.58) {
    return { iconColor: '#102033', containerColor: '#FFFFFF', containerOpacity: 0.72, borderVisible: true };
  }
  return { iconColor: '#FFFFFF', containerColor: '#06111F', containerOpacity: 0.46, borderVisible: false };
}

这段代码只负责按钮可见性。它预防的是头图亮度变化后返回按钮不可读。页面可以把它用于返回、收藏、分享三个入口,保证顶部操作一致。

六、吸顶栏:透明到实色要有连续过渡

吸顶栏最怕突然出现。更稳的做法是根据滚动进度逐步调整背景不透明度和标题显示。

export interface StickyBarVisual {
  backgroundOpacity: number;
  titleOpacity: number;
  useSolidBackground: boolean;
}

export function buildStickyBarVisual(progress: DetailScrollProgress): StickyBarVisual {
  if (progress.phase === 'hero') {
    return { backgroundOpacity: 0, titleOpacity: 0, useSolidBackground: false };
  }

  return {
    backgroundOpacity: 0.18 + progress.progress * 0.82,
    titleOpacity: progress.progress,
    useSolidBackground: progress.progress > 0.88
  };
}

这段策略让导航栏在滚动中平滑接管。useSolidBackground 只在接近吸顶时打开,避免首屏一进来就像普通详情页。

七、正文上浮:卡片圆角和头图遮罩要同步

详情正文通常会做成白色或半透明卡片上浮。上浮距离太大,会挡住头图;太小,页面层级不明显。建议用滚动进度控制正文卡片的位置和圆角。

export interface DetailContentLift {
  translateY: number;
  cornerRadius: number;
  topShadowOpacity: number;
}

export function resolveDetailContentLift(progress: DetailScrollProgress): DetailContentLift {
  const lift = Math.min(progress.offset * 0.18, 42);
  return {
    translateY: -lift,
    cornerRadius: progress.phase === 'sticky' ? 18 : 28,
    topShadowOpacity: 0.08 + progress.progress * 0.08
  };
}

这段代码保护的是正文区域的阅读体验。正文卡片可以有层次,但不要为了沉浸感牺牲可读性。

八、底部操作:不要跟着头图一起变

详情页底部的主操作,例如“开始导航”“立即预约”“加入购物车”,应该保持稳定。它可以有光感材质,但不应该随着头图滚动不断变化。

export interface DetailBottomActionState {
  primaryText: string;
  enabled: boolean;
  stickyAtBottom: boolean;
  safeBottomVp: number;
}

export function buildRouteBottomAction(canStart: boolean): DetailBottomActionState {
  return {
    primaryText: canStart ? '开始导航' : '暂不可用',
    enabled: canStart,
    stickyAtBottom: true,
    safeBottomVp: 24
  };
}

底部操作的边界是任务闭环,不是视觉氛围。头图再漂亮,用户最终要能清楚地完成主操作。

九、接入步骤:从静态头图开始,不要一口气做完整动效

旧详情页改沉浸光感时,建议先按四步推进。第一步只替换头图结构,保留原来的正文和底部按钮,确认图片比例、安全区和返回按钮没有问题。第二步接滚动进度,只让吸顶栏透明度变化,不改正文位置。第三步再做正文卡片上浮,观察内容是否遮挡。第四步才接底部操作的光感材质。

步骤 改动范围 验收重点
头图改造 DetailHeader.ets 图片比例、返回按钮、安全区
吸顶过渡 StickyBarPolicy.ets 标题出现时机、背景透明度
正文上浮 DetailContentSection.ets 正文不遮挡、圆角自然
底部操作 DetailActionBar.ets 主按钮稳定、底部安全区

这个顺序能降低风险。详情页通常是核心转化页面,如果一次性重写头图、导航、正文和底部操作,出问题时很难判断是哪一层导致。

十、装配计划:详情页只消费一个视觉计划

页面层不要到处判断滚动状态。可以把头部、进度、导航、正文和底部操作收敛成一个计划。

export interface DetailPageVisualPlan {
  topButton: DetailTopButtonStyle;
  stickyBar: StickyBarVisual;
  contentLift: DetailContentLift;
  bottomAction: DetailBottomActionState;
}

export function buildDetailPageVisualPlan(
  header: DetailHeroHeader,
  scrollOffset: number,
  heroHeight: number,
  canStart: boolean
): DetailPageVisualPlan {
  const progress = calculateDetailScrollProgress(scrollOffset, heroHeight);
  return {
    topButton: resolveDetailTopButtonStyle(header.imageLuminance),
    stickyBar: buildStickyBarVisual(progress),
    contentLift: resolveDetailContentLift(progress),
    bottomAction: buildRouteBottomAction(canStart)
  };
}

这段装配函数是详情页视觉链路入口。页面只要根据 plan 渲染,不需要理解每个阈值为什么存在。

十一、真机复盘:保留三个滚动位置截图

详情页问题很难只靠一张截图说明。建议每次视觉改版后保存三张图:首屏、滚动中段、吸顶完成。三张图能直接看出按钮是否丢失、标题是否重复、正文是否被压住。

export interface DetailScrollSnapshot {
  pageName: string;
  phase: DetailScrollProgress['phase'];
  offset: number;
  screenshotName: string;
  note: string;
}

export function createDetailScrollSnapshot(
  phase: DetailScrollProgress['phase'],
  offset: number,
  note: string
): DetailScrollSnapshot {
  return {
    pageName: 'RouteDetailPage',
    phase,
    offset,
    screenshotName: `route_detail_${phase}_${Date.now()}.png`,
    note
  };
}

这段快照对象不是运行时代码必需品,它用于测试和视觉复盘。出现“某些头图按钮看不清”时,可以直接定位到具体阶段和截图。

十二、常见问题排查

现象 优先查看 处理方式
返回按钮看不清 头图亮度和按钮容器 给按钮加半透明底色
吸顶栏突然出现 滚动进度计算 progress 做连续过渡
正文遮住头图重点 上浮距离过大 限制 translateY 上限
标题重复显示 首屏标题和吸顶标题状态没分开 按阶段控制透明度
底部按钮被遮挡 安全区处理不足 使用安全区和固定底部策略
大图加载慢 没有占位和骨架 提供低清占位或默认背景

十三、上线前验收表

验收项 通过标准
首屏按钮 返回、收藏、分享在不同头图上都清楚
滚动过渡 透明栏到吸顶栏没有突兀跳变
正文阅读 指标、标题、正文不被头图或浮层遮挡
底部操作 主按钮稳定可见,安全区正确
弱网图片 头图未加载时页面仍可用
多设备 手机、平板、折叠屏头图比例可控

十四、把详情页光感做成滚动状态机

详情页沉浸光感的核心不是大图,而是滚动状态机。头图负责氛围,透明导航负责首屏操作,吸顶栏负责持续阅读,正文卡片负责信息承载,底部操作负责任务完成。把这些职责拆开后,详情页既能有高级感,也不会在滚动中丢失可用性。

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐