写点什么

【HarmonyOS】鸿蒙高仿华为阅读翻页

作者:zhongcx
  • 2024-10-11
    广东
  • 本文字数:5738 字

    阅读完需:约 19 分钟

【HarmonyOS】高仿华为阅读 app 翻页 demo

src/main/ets/entryability/EntryAbility.ets

import { window } from '@kit.ArkUI';import { UIAbility } from '@kit.AbilityKit';
export default class EntryAbility extends UIAbility { onWindowStageCreate(windowStage: window.WindowStage): void { let windowClass = windowStage.getMainWindowSync() let statusBarHeight = windowClass.getWindowAvoidArea(window.AvoidAreaType.TYPE_SYSTEM).topRect.height let navigationIndicatorHeight = windowClass.getWindowAvoidArea(window.AvoidAreaType.TYPE_NAVIGATION_INDICATOR).bottomRect.height AppStorage.setOrCreate('statusBarHeight', statusBarHeight) //保存状态栏高度,单位px AppStorage.setOrCreate('navigationIndicatorHeight', navigationIndicatorHeight) //保存底部导航条的高度,单位px windowClass.setWindowSystemBarEnable([]); //'status' | 'navigation' windowStage.loadContent('pages/Page40'); }}
复制代码

src/main/ets/pages/Page40.ets

import { promptAction } from '@kit.ArkUI'import { batteryInfo, systemDateTime } from '@kit.BasicServicesKit'
@Entry@Componentstruct Page40 { // 页面信息 @Provide info: string = '设计理念\n在万物互联的时代,我们每天都会接触到很多不同形态的设备,每种设备在特定的场景下能够为我们解决一些特定的问题,表面看起来我们能够做到的事情更多了,但每种设备在使用时都是孤立的,提供的服务也都局限于特定的设备,我们的生活并没有变得更好更便捷,反而变得非常复杂。HarmonyOS 的诞生旨在解决这些问题,在纷繁复杂的世界中回归本源,建立平衡,连接万物。\n混沌初开,一生二、二生三、三生万物,我们希望通过 HarmonyOS 为用户打造一个和谐的数字世界——One Harmonious Universe。\nOne\n万物归一,回归本源。我们强调以人为本的设计,通过严谨的实验探究体验背后的人因,并将其结论融入到我们的设计当中。\nHarmonyOS 系统的表现应该符合人的本质需求。结合充分的人因研究,为保障全场景多设备的舒适体验,在整个系统中,各种大小的文字都清晰易读,图标精确而清晰、色彩舒适而协调、动效流畅而生动。同时,界面元素层次清晰,能巧妙地突出界面的重要内容,并能传达元素可交互的感觉。另外,系统的表现应该是直觉的,用户在使用过程中无需思考。因此系统的操作需要符合人的本能,并且使用智能化的技术能力主动适应用户的习惯。\nHarmonious\n一生为二,平衡共生。万物皆有两面,虚与实、阴与阳、正与反... 二者有所不同却可以很好地融合,达至平衡。\n在 HarmonyOS 中,我们希望给用户带来和谐的视觉体验。我们在物理世界中找到在数字世界中的映射,通过光影、材质等设计转化到界面设计中,给用户带来高品质的视觉享受。同时,物理世界中的体验记忆转化到虚拟世界中,熟悉的印象有助于帮助用户快速理解界面元素并完成相应的操作。\nUniverse\n三生万物,演化自如。HarmonyOS 是面向多设备体验的操作系统,因此,给用户提供舒适便捷的多设备操作体验是 HarmonyOS 区别于其他操作系统的核心要点。\n一方面,界面设计/组件设计需要拥有良好的自适应能力,可快速进行不同尺寸屏幕的开发。\n另一方面,我们希望多设备的体验能在一致性与差异性中取得良好的平衡。\n● 一致性:界面中的元素设计以及交互方式尽量保持一致,以便减少用户的学习成本。\n● 差异性:不同类型的设备在屏幕尺寸、交互方式、使用场景、用户人群等方面都会存在一定的差异性,为了给用户提供合适的操作体验,我们需要针对不同类型的设备进行差异化的设计。\n同时,HarmonyOS 作为面向全球用户的操作系统,为了让更多的用户享受便利的科技与愉悦的体验,我们将在数字健康、全球化、无障碍等方面进行积极的探索与思考。' @Provide lineHeight: number = 0 // 单行文本的高度 @Provide pageHeight: number = 0 // 每页的最大高度 @Provide totalContentHeight: number = 0 // 整个文本内容的高度 @Provide textContent: string = " " // 文本内容,默认一个空格是为了计算单行文本的高度 @Provide @Watch('totalPagesChanged') totalPages: number = 1 // 总页数 //=====页面切换动画===== @State currentPage: number = 0 // 当前页数 private DISPLAY_COUNT: number = 1 private MIN_SCALE: number = 0.75 @State pages: string[] = [] @State opacityList: number[] = [] @State scaleList: number[] = [] @State translateList: number[] = [] @State zIndexList: number[] = [] //=====定时器===== timeIntervalId: number = 0 @Provide timeStr: string = "" @Provide batterySOC: string = "" //======左右滑动判断====== @State screenStartX: number = 0
totalPagesChanged() { // 总页数变化时更新 this.pages = new Array(this.totalPages).fill(''); }
aboutToDisappear(): void { clearInterval(this.timeIntervalId) }
aboutToAppear(): void { this.timeIntervalId = setInterval(() => { let timestamp = systemDateTime.getTime(true) / 1000000 //因为获取的是纳秒 所以要 / 1000000 // console.info(`timestamp:${timestamp}`) const date = new Date(timestamp); const hours = ('0' + date.getHours()).slice(-2); const minutes = ('0' + date.getMinutes()).slice(-2);
this.timeStr = `${hours}:${minutes}` this.batterySOC = `电量${batteryInfo.batterySOC}%` }, 1000, 0)

for (let i = 0; i < this.pages.length; i++) { this.opacityList.push(1.0) this.scaleList.push(1.0) this.translateList.push(0.0) this.zIndexList.push(0) } }
build() { Stack() { Page40Child()// 自定义动画变化透明度、缩放页面、抵消系统默认位移、渲染层级等 .width('100%').height('100%').visibility(Visibility.Hidden)
Swiper() { ForEach(this.pages, (item: string, index: number) => { Page40Child({ index: index })// 自定义动画变化透明度、缩放页面、抵消系统默认位移、渲染层级等 .opacity(this.opacityList[index]) .scale({ x: this.scaleList[index], y: this.scaleList[index] }) .translate({ x: this.translateList[index] }) .zIndex(this.zIndexList[index]) }) } .onTouch((e) => { if (e.type === TouchType.Down && e.touches.length > 0) { // 触摸开始,记录初始位置 this.screenStartX = e.touches[0].x; } else if (e.type === TouchType.Up && e.changedTouches.length > 0) { // 当手指抬起时,更新最后的位置 let lastScreenX = e.changedTouches[0].x; if (this.screenStartX < lastScreenX && this.currentPage === 0) { promptAction.showToast({ message: "没有上一页了" }); } else if (this.screenStartX > lastScreenX && this.currentPage === this.totalPages - 1) { promptAction.showToast({ message: "没有下一页了" }); } } }) .onChange((index: number) => { console.info(index.toString()) this.currentPage = index }) .loop(false) // .height(300) .layoutWeight(1) .indicator(false) .displayCount(this.DISPLAY_COUNT, true) .customContentTransition({ // 页面移除视窗时超时1000ms下渲染树 // timeout: 1000, // 对视窗内所有页面逐帧回调transition,在回调中修改opacity、scale、translate、zIndex等属性值,实现自定义动画 transition: (proxy: SwiperContentTransitionProxy) => { if (proxy.position <= proxy.index % this.DISPLAY_COUNT || proxy.position >= this.DISPLAY_COUNT + proxy.index % this.DISPLAY_COUNT) { // 同组页面往左滑或往右完全滑出视窗外时,重置属性值 this.opacityList[proxy.index] = 1.0 this.scaleList[proxy.index] = 1.0 this.translateList[proxy.index] = 0.0 this.zIndexList[proxy.index] = 0 } else { // 同组页面往右滑且未滑出视窗外时,对同组中左右两个页面,逐帧根据position修改属性值,实现两个页面往Swiper中间靠拢并透明缩放的自定义切换动画 if (proxy.index % this.DISPLAY_COUNT === 0) { this.opacityList[proxy.index] = 1 - proxy.position / this.DISPLAY_COUNT this.scaleList[proxy.index] = this.MIN_SCALE + (1 - this.MIN_SCALE) * (1 - proxy.position / this.DISPLAY_COUNT) this.translateList[proxy.index] = -proxy.position * proxy.mainAxisLength + (1 - this.scaleList[proxy.index]) * proxy.mainAxisLength / 2.0 } else { this.opacityList[proxy.index] = 1 - (proxy.position - 1) / this.DISPLAY_COUNT this.scaleList[proxy.index] = this.MIN_SCALE + (1 - this.MIN_SCALE) * (1 - (proxy.position - 1) / this.DISPLAY_COUNT) this.translateList[proxy.index] = -(proxy.position - 1) * proxy.mainAxisLength - (1 - this.scaleList[proxy.index]) * proxy.mainAxisLength / 2.0 } this.zIndexList[proxy.index] = -1 } } }) .width('100%') .height('100%') }.width('100%').height('100%') }}
@Componentstruct Page40Child { @Consume info: string @Consume lineHeight: number // 单行文本的高度 @Consume pageHeight: number // 每页的最大高度 @Consume totalContentHeight: number // 整个文本内容的高度 @Consume textContent: string // 文本内容,默认一个空格是为了计算单行文本的高度 @Consume totalPages: number // 总页数 @Consume timeStr: string @Consume batterySOC: string @State scrollOffset: number = 0 // 当前滚动偏移量 @Prop index: number = 0 scroller: Scroller = new Scroller() // 滚动条实例
resetMaxLineHeight() { if (this.lineHeight > 0 && this.pageHeight > 0 && this.totalContentHeight > 0) { this.pageHeight = (Math.floor(this.pageHeight / this.lineHeight)) * this.lineHeight this.totalPages = Math.ceil(this.totalContentHeight / this.pageHeight) //向上取整得到总页数 } }
aboutToAppear(): void { this.scrollOffset = -(this.pageHeight * this.index) }
build() { Column() { Text().width('100%').height(`${AppStorage.get('statusBarHeight')}px`) //顶部状态栏高度 Text('通用设计基础') .fontColor("#7a7a7a") .fontSize(10) .padding({ left: 30, top: 10, bottom: 10 }) .width('100%') Column() { Scroll(this.scroller) { Column() { Text(this.textContent) .fontSize(18) .lineHeight(36) .fontColor(Color.Black) .margin({ top: this.scrollOffset }) .onAreaChange((oldArea: Area, newArea: Area) => { if (this.lineHeight == 0 && newArea.height > 0) { this.lineHeight = newArea.height as number this.resetMaxLineHeight() //添加数据测试 this.textContent = this.info return } if (this.totalContentHeight != newArea.height) { console.info(`newArea.height:${newArea.height}`) this.totalContentHeight = newArea.height as number this.resetMaxLineHeight() } }) } .padding({ left: 25, right: 25 }) }.scrollBar(BarState.Off) .constraintSize({ maxHeight: this.pageHeight == 0 ? 1000 : this.pageHeight }) } .width('100%') .layoutWeight(1)
.onAreaChange((oldArea: Area, newArea: Area) => { if (this.pageHeight == 0 && newArea.height > 0) { this.pageHeight = newArea.height as number this.resetMaxLineHeight() } })
Row() { Row() { Text(this.timeStr) .fontColor("#7a7a7a") .fontSize(10) Text(this.batterySOC) .fontColor("#7a7a7a") .fontSize(10) .margin({ left: 5 }) }
Text(`${this.index + 1}/${this.totalPages}`) .fontColor("#7a7a7a") .fontSize(10) }.width('100%').padding({ left: 30, right: 30, top: 30 }).justifyContent(FlexAlign.SpaceBetween)
Text().width('100%').height(`${AppStorage.get('navigationIndicatorHeight')}px`) //底部导航栏高度
} .width('100%') .height('100%') .backgroundColor("#CFE6D6") }}

复制代码


用户头像

zhongcx

关注

还未添加个人签名 2024-09-27 加入

还未添加个人简介

评论

发布
暂无评论
【HarmonyOS】鸿蒙高仿华为阅读翻页_zhongcx_InfoQ写作社区