HarmonyOS--合理使用页面间转场

news2024/11/6 3:05:55

一、概述

        页面间转场是用户从一个页面切换到另一个页面时的过程,一个无缝流畅的转场动效可以提升用户的交互体验。从主页到详情页、从列表页到结果页都需要去设置一些转场动效使得用户体验更加流畅。基于用户行为和应用设计模式,我们总结出了一些常见的转场场景,包括层级转场、搜索转场、新建转场、编辑转场、通用转场、跨应用转场。

二、视角转换步骤

         

  1. 了解系统能力:首先,开发者需要深入了解HarmonyOS系统提供的转场能力和动画功能。这包括了解页面转场的机制、转场动画的类型和特性,以及如何在HarmonyOS应用中使用相关API。
  2. 分析UX设计视角:仔细分析UX设计所提供的转场场景和动效。理解设计师的意图,包括页面之间的过渡效果、元素的动画行为,以及何时触发和结束转场动效。
  3. 设计转场方案:基于分析的结果,设计出合理的转场方案。确定页面切换的触发时机、转场动画的类型和参数等。
  4. 使用转场能力:利用HarmonyOS提供的转场能力,如UIAbility转场、页面路由转场、组件转场,来实现页面之间的转场效果。
  5. 使用动画能力:利用HarmonyOS提供的动画能力,如属性动画、出现/消失转场动画等来实现元素的平移、缩放、旋转、透明度等动画行为。
  6. (可选)使用高级模板化转场:HarmonyOS已经为我们提供了一些基于场景化封装的相关高级模板化转场,如导航转场、模态转场、共享元素转场。
  7. 调试和优化:在实施转场和动效的过程中,进行调试和优化。确保转场效果流畅,动效符合预期,且满足性能要求。

三、转场场景

        1、 层级转场

        层级转场是指在用户界面中,从一个层级结构的界面状态转换到另一个层级结构的界面状态的过程,它通常用于在应用中进行页面间的导航和视图层级的变化。层级转场的场景可以划分为卡片、图标展开和列表展开:

  • 列表展开:通常是完整的页面替换,开发者可以使用左右位移遮罩动效完成这类变化
  • 卡片/图表展开:单体独立卡片展开推荐使用一镜到底动效;相对复杂的组合卡片样式则需要由开发者以更为符合用户视觉流畅感为标准,根据实际情况选择左右位移遮罩动效或一镜到底动效。

        2、搜索转场

        搜索转场是指在用户执行搜索操作,如在搜索栏中输入关键词并按下搜索按钮、或者直接触摸搜索图标时,应用改变应用页面以显示搜索结果的过程。它包含了固定搜索区域和非固定搜索区域两种情况:

  • 固定搜索区域:在固定搜索区域中,大部分空间是不需要变化的,只是在上面增加了一层蒙版。主要变化区域集中在页眉,即搜索框和返回按键。当用户触发搜索操作时,页面可以使用淡入淡出动效来优化搜索体验,搜索框和返回按键通过渐变的方式进入视图,从而吸引用户的注意力。
  • 非固定搜索区域:在非固定搜索区域中,页面的变化更加复杂。为了保持用户的注意力和流畅的体验,可以使用一镜到底的动效,让搜索框始终保持在用户视线焦点中,相对忽视页面中其余变动较大的部分。

         3、新建转场

        新建转场是指用户创建新内容或实体时,应用页面发生的过渡效果,它可以让用户感知到新的事物的添加或创建,并提供一种连贯和引人注目的视觉切换。由于新建页面中需要完成整个页面的替换,推荐开发者使用左右位移遮罩作为转场动效。

        对于新建转场,推荐使用系统转场,页面转场采用左右位移的运动方式,不应单帧直接切换或上下位移切换,曲线优先使用弹簧曲线。

        4、编辑转场

        用户对现有内容或实体进行编辑时,例如点击“编辑”按钮、选择要编辑的项目或内容,或者执行其他与编辑相关的动作,应用应提供动效引导用户进入一个用于编辑现有内容的页面,修改所需的信息。在这个场景下,开发者需要达成的视觉效果是从编辑按键处弹出编辑页面,类似于单体卡片展开的效果。但由于一般的编辑按键并没有分明的外框,并不适用一镜到底的动效,此时淡入淡出能够提供类似于一镜到底的效果。

        5、通用转场

        通用转场是一种广泛适用于不同情境和应用类型的页面过渡效果,目的是提供一种通用的、可重复使用的方式,以改善用户页面之间的切换,增强用户体验。其关键点在于要适用各种应用情境,包括不同类型的应用(例如社交媒体、电子商务、新闻等)和不同操作(例如导航、搜索、编辑等)。这就需要一种通用的、不需要复杂操作的动效来完成跳转任务,而缩放能够满足绝大多数用户的需求和视觉体验感受。

        6、跨应用转场

        跨应用转场是指用户从一个应用程序切换到另一个应用程序,用户能够无缝地从一个应用切换到另一个应用,而不会感到中断或不适。和以上几类转场都不同的是,用户点击应用内的链接、按钮或执行其他与外部应用交互的动作后,页面的跳转已经不仅仅存在于页面与页面之间,而是应用与应用之间,为此,推荐开发者使用专为此设计的左右间隔位移动效。

        7、场景解构

        转场是由交互行为引起的界面变化,分析界面元素在过程中的意义,定义其在转场中所在的类型,并将它们进行分类,元素所属的类别会影响它们使用怎样的转场能力,同时也将决定用什么类型的曲线和时长。

  • 进场元素:转场中新出现的元素,一般是结果界面上的构成元素。
  • 出场元素:转场中消失的元素,一般是上一界面中的构成元素。
  • 持续元素:转场中持续存在的元素,可以是元素在布局上的变化,也可以是某种连续性的动画效果,整个过程无中断。
  • 静止元素:转场中无任何变化的元素。

 四、转场场景开发

        1、转场能力

        HarmonyOS为开发者提供了UIAbility转场、页面路由和组件转场三种方式,在选择转场方式时,开发者需要考虑用户体验、界面一致性和业务需求,确保所选导航组件能够提供直观、易用的导航方式,帮助应用实现更好的转场效果。

  • UIAbility组件间交互:UIAbility是系统调度的最小单元。通过调用startAbility()方法启动UIAbility实现在设备内的功能模块之间的跳转。该UIAbility可以是应用内的其他UIAbility,也可以是其他应用的UIAbility(例如启动三方支付UIAbility)。
  • 页面路由(@ohos.router):页面路由指在应用程序中实现不同页面之间的跳转和数据传递。HarmonyOS提供了Router模块,通过不同的url地址,可以方便地进行页面路由,轻松地访问不同的页面。
  • 组件转场:组件转场是指通过HarmonyOS提供的各类组件来实现转场效果,以便更加便捷地展示不同的内容或功能模块。在组件转场中,可以使用诸如页面切换动画、过渡效果、布局变化等方式来实现页面之间的平滑切换

        2、动画能力

        转场动画是指对将要出现或消失的组件做动画,对始终出现的组件做动画应使用属性动画。转场动画主要为了让开发者从繁重的消失节点管理中解放出来,如果用属性动画做组件转场,开发者需要在动画结束回调中删除组件节点。同时,由于动画结束前已经删除的组件节点可能会重新出现,还需要在结束回调中增加对节点状态的判断。

        转场动画分为基础转场和高级模板化转场,出现/消失转场是一种基础转场,是对新增、消失的控件实现动画效果的能力。为了简化开发者工作,HarmonyOS提供了以下高级模板,将属性动画和出现消失动画封装,开发者只需调用接口,可以轻松的完成页面转场:

  • 导航转场:页面的路由转场方式,对应一个界面消失,另外一个界面出现的动画效果,如设置应用一级菜单切换到二级界面。
  • 模态转场:新的界面覆盖在旧的界面之上的动画,旧的界面不消失,新的界面出现,如弹框就是典型的模态转场动画。
  • 共享元素转场:共享元素转场是一种界面切换时对相同或者相似的元素做的一种位置和大小匹配的过渡动画效果。

 五、案例实践

转场场景

动效

推荐使用的转场能力

层级转场

卡片/图标展开

组合卡片样式

左右遮罩位移(可考虑一镜到底)

页面路由转场、导航转场模板

单体卡片样式

一镜到底

模态转场模板、共享元素转场模板

列表展开

列表样式(非卡片)

左右遮罩位移

页面路由转场、导航转场模板

混合样式(卡片+列表+图标)

左右遮罩位移

页面路由转场、导航转场模板

搜索转场

固定搜索区域

淡入淡出

组件转场、模态转场模板

非固定搜索区域

一镜到底

共享元素转场模板、模态转场模板

新建转场

左右遮罩位移

组件转场、模态转场模板

编辑转场

淡入淡出

组件转场

通用转场

缩放

组件转场、模态转场模板

跨应用转场

左右间隔位移

组件转场

         1、导航转场模板实现层级转场

        实现效果:在本场景中,需要在地图上显示6个具体的坐标位置,点击对应的坐标icon后,能跳转到对应的详情介绍页面中去

        

build() {
  Stack() {
    // Navigation组件一般可以用来实现标题栏、工具栏、导航栏等。
    Navigation() {
      //分别对每一个地图上的导航mapElements进行渲染和链接
      ForEach(this.mapElements,
        (item: MapElement) => {
          Column() {
            // NavRouter导航组件,默认提供点击响应处理,不需要开发者自定义点击事件逻辑。NavRouter必须包含两个子组件,其中第二个子组件必须为NavDestination。
            NavRouter() {
              //地图上对应导航位置图标资源的渲染
              AnimIcon({ item: item })
              ......
              // 作为NavRouter组件的子组件,用于显示导航内容区。其中IntroductionPage即为即将跳转的对应页面
              NavDestination() {
                IntroductionPage({currentZoneId: item.id})
              }
            }
            // 指定点击NavRouter跳转到NavDestination页面时使用的路由模式。此处不需要保存原页面,选择replace方式,跳转后页面销毁,且该页面信息从路由栈中清除。
            .mode(NavRouteMode.REPLACE)
          }
        ......
        },
        (item: MapElement) => JSON.stringify(item)
      )
    }
    // 将mode属性设置为NavigationMode.Stack,Navigation组件即可设置为单页面显示模式。
    .mode(NavigationMode.Stack)
    .hideNavBar(true)
    .hideTitleBar(true)
    .hideBackButton(true)
    .hideToolBar(true)
  }
}

        2、Tabs组件实现层级转场

        实现效果:在本场景中,需要完成是效果是在用户主页切换显示收藏、浏览、成就三个页面

        

build() {
  ......
  ListItem() {
    // Tabs组件的页面组成包含两个部分,分别是TabContent和TabBar。
    Tabs() {
      // TabContent仅在Tabs中使用,对应一个切换页签的内容视图
      TabContent() {
        // 收藏列表页面
        CollectedResourceView({ innerScroller: this.innerScroller, outerScroller: this.outScroller })
      }
      // tabBar设置TabBar上显示内容。每一个TabContent对应的内容需要有一个页签,可以通过TabContent的tabBar属性进行配置。
      .tabBar(this.MineTabs(TabInfo.COLLECTED, $r('app.string.my_collected')))
      .backgroundColor($r('app.color.hmos_background_color_white'))

      TabContent() {
        // 浏览列表页面
        ViewedResourceView({ innerScroller: this.innerScroller, outerScroller: this.outScroller })
      }
      .tabBar(this.MineTabs(TabInfo.VIEWED, $r('app.string.my_viewed')))
      .backgroundColor($r('app.color.hmos_background_color_white'))

      TabContent() {
        // 成就展示页面
        AchievesView()
      }
      .tabBar(this.MineTabs(TabInfo.ACHIEVEMENT, $r('app.string.my_achieve')))
      .backgroundColor($r('app.color.hmos_background_color_white'))
    }
    .onChange((index: number) => {
      this.currentIndex = index;
    })
    ......
  }
  ......
}

        3、模态转场模板实现通用转场

        实现效果:在本场景中,当用户点击介绍详情页中的图片时,图片会放大展示,覆盖在原有界面上,并且点击空白处完成返回操作

        

build() {
    Stack() {
      ForEach(this.introductionData.imageList, (item: ResourceStr, index?: number) => {
        if (index !== undefined) {
          Row() {
            Image(item)
              .objectFit(ImageFit.ScaleDown)
              // geometryTransition绑定id
              .geometryTransition(index === this.currentIndex ? 'share_' + this.currentIndex : '')
              ......
          }
          .onClick(() => {
            // 设置动画参数,curves.springMotion构造弹性动画对象
            animateTo({ curve: curves.springMotion(Const.SPRING_RESPONSE, Const.DAMPING_FRACTION) }, () => {
              this.isPresent = !this.isPresent;
            });
          })
        }
      }, (item: ResourceStr) => JSON.stringify(item))
    }
    .width(Const.FULL_PERCENT)
    .height($r('app.float.swiper_height'))
    .alignContent(Alignment.Center)
    // 通过bindContentCover属性为组件绑定全屏模态页面,在组件插入和删除时,可通过设置转场参数ModalTransition显示过渡动效。
    .bindContentCover($$this.isPresent, this.PhotoBuilder, {modalTransition: ModalTransition.ALPHA, onAppear: () => {}, onDisappear: () => {}})
  }

  @Builder
  PhotoBuilder() {
    ImageViewDialog({ isPresent: $isPresent, currentIndex: $currentIndex })
      .width(Const.FULL_PERCENT)
      .height(Const.FULL_PERCENT)
      .transition(TransitionEffect.opacity(1))
      .backgroundBlurStyle(this.isPresent ? BlurStyle.Regular : BlurStyle.NONE, { colorMode: ThemeColorMode.DARK })
  }


build() {
  Stack() {
    Swiper() {
      ForEach(this.introductionData.imageList, (item: Resource, index?: number) => {
        Column() {
          ......
          Image(item)
            .width(Const.FULL_PERCENT)
            .syncLoad(true)
            .objectFit(ImageFit.Contain)
            .gesture(
              PinchGesture()
                .onActionStart(() => {
                  this.isGesture = true;
                })
                .onActionUpdate((event?: GestureEvent) => {
                  if (event) {
                    this.imgScale = this.curScale * event.scale;
                  }
                })
                .onActionEnd(() => {
                  this.limitScale(false);
                })
            )
             // geometryTransition绑定id
            .geometryTransition(index === this.currentIndex && !this.isGesture ? 'share_' + index : '')
            ......
        }
        .width(Const.FULL_PERCENT)
        .height(Const.FULL_PERCENT)
        .justifyContent(FlexAlign.Center)
      })
    }
    ......
  }
}

六、总结

  • 符合界面设计需求:动效应该与应用的整体设计风格和用户期望相匹配,不应过于炫目或过于简单。动效的设计应该与应用的功能和交互逻辑相符,能够提供有意义的反馈和引导。
  • 提高用户体验:动效可以增强用户对界面操作的反馈感知,使用户能够更直观地理解应用的状态和变化。例如,在页面切换时使用渐变效果或位移动画,可以使用户感到界面的流畅性和连贯性,提高用户的满意度和使用体验。
  • 控制动效的频率和时长:动效的过度使用可能会让用户感到疲劳或干扰用户的操作。因此,在设计动效时需要注意控制动效的频率和时长,避免过多的动效干扰用户的操作和阅读。
  • 考虑性能和流畅度:在使用动效时,需要考虑应用的性能和流畅度。过多或复杂的动效可能会导致应用的性能下降,影响用户的体验。因此,在设计动效时需要合理权衡动效的效果和应用的性能,确保动效的运行流畅和稳定。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2087357.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C#/.net core “hello”.IndexOf(“\0”,2)中的坑

先想想看,你认为下面代码返回值是多少? "hello".IndexOf("", 2); "hello".IndexOf("\0", 2); "hello".IndexOf(\0, 2); 今天和大家分享关于.net core中与字符相关的一些奇怪问题。 首先我们先以.N…

Golang | Leetcode Golang题解之第383题赎金信

题目&#xff1a; 题解&#xff1a; func canConstruct(ransomNote, magazine string) bool {if len(ransomNote) > len(magazine) {return false}cnt : [26]int{}for _, ch : range magazine {cnt[ch-a]}for _, ch : range ransomNote {cnt[ch-a]--if cnt[ch-a] < 0 {r…

大模型知识检索RAG业务实践实践(初级篇)

大模型知识检索RAG业务实践实践(初级篇) 1.知识检索大图 大模型是现在一个非常热门的话题,大模型表现出的生成能力也是非常惊艳。但是强如 GPT4 这样的大模型,它在知识更新和幻觉上也会存在问题。比如说我们问互联网行业有什么大事,GPT4 的回答是三年前的内容。主要是说疫…

机械学习—零基础学习日志(如何理解概率论12)

假设检验 假设检验是有一些参数&#xff0c;已知条件&#xff0c;让你检验某种假设是否成立。 我们通过具体的题目来说明&#xff1a; 这里我们需要确认使用什么公式&#xff1a; 使用下面的公式如下图&#xff1a; 题目中&#xff0c;以21作为分界线&#xff0c;所以我们将是…

用manim证明函数的左右极限

http://t.csdnimg.cn/2pVdFhttp://t.csdnimg.cn/2pVdF在上一节的最后两个示例中&#xff0c;我们看到了两个不存在的限制。然而&#xff0c;对于每个例子来说&#xff0c;每个限制不存在的原因是不同的。 我们看一下下面的例子&#xff1a; 极限不存在&#xff0c;因为函数没有…

Redis基本全局命令

文章目录 get和setkeysexistsdelexpirettltype redis全局命令&#xff1a; redis支持很多种数据结构&#xff0c;整体上来说。redis是键值对结构&#xff0c;key固定就是字符串&#xff0c;value实际上就会有很多种&#xff0c;比如说&#xff1a; 字符串哈希表列表有序集合 …

linux系统编程-网络-tcp(29)

C/S B/S P2p模型 在Linux系统编程中&#xff0c;C/S&#xff08;Client/Server&#xff0c;客户端/服务器&#xff09;和B/S&#xff08;Browser/Server&#xff0c;浏览器/服务器&#xff09;模型是两种常见的架构模式&#xff0c;用于构建分布式应用程序。它们在设计和实现上…

C语言 | Leetcode C语言题解之第384题打乱数组

题目&#xff1a; 题解&#xff1a; typedef struct {int* num;int* src;int numsize; } Solution;Solution *obj NULL;Solution* solutionCreate(int* nums, int numsSize) {if (obj ! NULL) {return obj;}Solution *obj (Solution*)malloc(sizeof(Solution));obj->nums…

#C++ 笔记二

四、运算符重载 1.友元 1.1 概念 类实现了数据的隐藏和封装&#xff0c;类的数据成员一般定义为私有成员&#xff0c;仅能通过类的公有成员函数才能进行读写。 如果数据成员定义成公共的&#xff0c;则又破坏了封装性。但是在某些情况下&#xff0c;需要频繁的读写数据成员…

Java 7.3 - 分布式 id

分布式 ID 介绍 什么是 ID&#xff1f; ID 就是 数据的唯一标识。 什么是分布式 ID&#xff1f; 分布式 ID 是 分布式系统中的 ID&#xff0c;它不存在于现实生活&#xff0c;只存在于分布式系统中。 分库分表&#xff1a; 一个项目&#xff0c;在上线初期使用的是单机 My…

2-80 基于matlab-GUI,实现kalman滤波对目标物的位置进行检测跟踪

基于matlab-GUI,实现kalman滤波对目标物的位置进行检测跟踪。检测汽车中心和最大半径&#xff0c;与背景差分选择较大差异的区域进行形态学处理&#xff0c;用冒泡法对目标面积从大到小排序。程序已调通&#xff0c;可直接运行。 2-80 kalman视频跟踪滤波 - 小红书 (xiaohongsh…

光学涡旋Talbot阵列照明器的matlab模拟与仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 5.完整程序 1.程序功能描述 光学涡旋 Talbot 阵列照明器是一种利用光学涡旋&#xff08;Optical Vortex&#xff09;和 Talbot 效应&#xff08;Talbot Effect&#xff09;相结合的技术&…

【HTML源码】上传即可使用的在线叫号系统源码

这个叫号系统的过程是这样的 接了一个任务&#xff0c;某学校要对学生进行逐个面试&#xff0c;希望能有类似医院门诊那种叫号系统。 条件&#xff1a;首先说硬件&#xff0c;就是教室里边一台笔记本电脑&#xff0c;同屏到教室外面的电视机。 需求&#xff1a;软件需求是可…

汉诺塔递归解决思路图解分析,python代码实现

目录 4.假设四层汉诺塔&#xff0c;n4&#xff0c;利用整体思想分解为两层的情况 3.分解到n3 3.1 分解上面n4时第一个步骤&#xff1a; 3.2 分解上面n4时第三个步骤&#xff1a; 2.继续分解到n2 &#xff08;同理略&#xff09; 1.当分解到n1 python代码 问题&#xff1…

【Linux】升级OpenSSH版本规避远程代码执行漏洞

本文首发于 ❄️慕雪的寒舍 升级OpenSSH版本规避远程代码执行漏洞。 说明 今天早上逛别人的博客的时候看到了这个重磅消息。OpenSSH爆出能远程通过root身份执行任意代码的漏洞&#xff0c;影响版本是 8.5p1 < OpenSSH < 9.8p1&#xff0c;奇安信的报告可以点我查看。 上…

计算机三级网络第4套练习记背

计算机三级网络第4套练习记背

全志/RK安卓屏一体机:医疗自助服务终端,支持鸿蒙国产化

医疗自助服务终端 为了解决传统医疗模式下的“看病难、看病慢”等问题&#xff0c;提高医疗品质、效率与效益&#xff0c;自助服务业务的推广成为智慧医疗领域实现信息化建设、高效运作的重要环节。 医疗自助服务终端是智慧医疗应用场景中最常见的智能设备之一&#xff0c;它通…

Linux学习笔记(4)----Debian压力测试方法

使用命令行终端压力测试需要两个实用工具&#xff1a;s-tui和stress sudo apt install s-tui stress 安装完成后&#xff0c;在终端中启动 s-tui实用工具&#xff1a; s-tui 执行后如下图&#xff1a; 你可以使用鼠标或键盘箭头键浏览菜单&#xff0c;然后点击“压力选项(Str…

day44.动态规划

718.最长重复子数组 给两个整数数组 nums1 和 nums2 &#xff0c;返回 两个数组中 公共的 、长度最长的子数组的长度 。 思路:1.确定dp数组&#xff08;dp table&#xff09;以及下标的含义: dp[i][j] &#xff1a;以下标i - 1为结尾的A&#xff0c;和以下标j - 1为结尾的B&…

【论文速读】|RO-SVD:一种用于 AIGC 应用的可重构硬件版权保护框架

本次分享论文&#xff1a;RO-SVD: A Reconfigurable Hardware Copyright Protection Framework for AIGC Applications 基本信息 原文作者&#xff1a;Zhuoheng Ran, Muhammad A.A. Abdelgawad, Zekai Zhang, Ray C.C. Cheung, Hong Yan 作者单位&#xff1a;香港城市大学电…