1# 左右翻页 2## 场景介绍 3在众多阅读或者文档应用中,都会涉及到文本翻页、电子书翻页、书籍翻页的场景。本文即为大家介绍左右翻页的开发过程。 4 5## 效果呈现 6效果图如下: 7 8 9 10## 运行环境 11本例基于以下环境开发,开发者也可以基于其他适配的版本进行开发: 12- IDE: DevEco Studio 4.0 Release 13- SDK: Ohos_sdk_public 4.0.10.13 (API Version 10 Release) 14 15## 实现思路 16本例的包含的关键特性及其实现方案如下: 17- 页面左右覆盖:通过NavDestination组件实现。 18- 小说翻页:通过点击事件(点击不同区域产生不同的交互动作)完成,并对小说首页进行处理。 19- 展示文本:通过创建并调用自定义函数novelContent(),最终展示在页面。 20 21## 开发步骤 22本例详细开发步骤如下,开发步骤仅展示关键代码。 231. 构建小说内容:通过创建自定义函数novelContent()。具体代码块如下: 24 ```ts 25 novelContent(){ 26 this.content1 = (this.currentPageNum - 1) + "___小说___" + (this.currentPageNum - 1) 27 this.content2 = (this.currentPageNum) + "___小说___" + (this.currentPageNum) 28 this.content3 = (this.currentPageNum + 1) + "___小说___" + (this.currentPageNum + 1) 29 console.log("oh----->currentPage=" + this.currentPageNum) 30 console.log("oh----->content1=" + this.content1) 31 console.log("oh----->content2=" + this.content2) 32 console.log("oh----->content3=" + this.content3); 33 } 34 ``` 352. 展示小说文本:通过NavDestination作为小说文本页面(子页面)的根容器,最后调用自定义组件ReadPage()将小说内容展示到页面上。 36 ```ts 37 NavDestination(){ 38 Stack(){ 39 ReadPage({content:this.content3}) 40 .backgroundColor(this.bgColor) 41 42 ReadPage({content:this.content2}) 43 .translate({x:this.offsetX >= 0 ? 0:this.offsetX , y:0 , z:0}) 44 .backgroundColor(this.bgColor) 45 .width(this.screenW) 46 47 ReadPage({content:this.content1}) 48 .backgroundColor(this.bgColor) 49 .translate({ 50 x:-this.screenW + this.offsetX 51 }) 52 } 53 } 54 // 自定义组件ReaderPage 55 @Component 56 struct ReadPage{ 57 @Prop content:string= "" 58 59 build(){ 60 Column(){ 61 Text(this.content) 62 .textAlign(TextAlign.Center) 63 .width("100%") 64 .height("100%") 65 .fontSize(50) 66 } 67 .borderColor(Color.Black) 68 .borderWidth(2) 69 .width("100%") 70 .height("100%") 71 } 72 } 73 ``` 743. 通过点击完成翻页以及提示消息完成:首先将点击事件封装clickAnimateTo(),点击不同区域产生不同的交互事件。点击距离屏幕左端1/3(横向)的区域,小说页面跳到上一页(第一页除外);点击距离屏幕右端1/3(横向)的区域,小说页面跳转到下一页;点击剩余区域出现提示语“打开菜单”。具体代码如下: 75 ```ts 76 // 封装点击事件clickAnimateTo() 77 private clickAnimateTo(isLeft: Boolean){ 78 animateTo({ 79 duration:400, 80 curve:Curve.EaseOut, 81 onFinish:()=>{ 82 if (this.offsetX > 100){ 83 this.currentPageNum -= 1 84 }else if (this.offsetX < -100){ 85 this.currentPageNum += 1 86 console.log("oh----->当前页变为" + this.currentPageNum) 87 } 88 this.offsetX = 0 89 this.novelContent() 90 } 91 },()=>{ 92 if (isLeft){ 93 this.offsetX = this.screenW 94 }else{ 95 this.offsetX = -this.screenW 96 } 97 }) 98 } 99 100 // 点击事件产生的交互动作 101 .onClick((event?:ClickEvent)=>{ 102 if (event){ 103 console.log("点击位置:" + event.x) 104 if (event.x > this.screenW / 3 * 2){ 105 this.clickAnimateTo(false) 106 }else if(event.x > this.screenW /3){ 107 promptAction.showToast({ 108 message:"打开菜单", 109 duration:300 110 }) 111 }else{ 112 if (this.currentPageNum == 1){ 113 promptAction.showToast({ 114 message:"没有内容!", 115 duration:300 116 }) 117 }else{ 118 this.clickAnimateTo(true) 119 } 120 } 121 } 122 }) 123 ``` 124## 完整代码 125完整示例代码如下: 126```ts 127import display from '@ohos.display' 128import promptAction from '@ohos.promptAction'; 129import window from '@ohos.window'; 130import common from '@ohos.app.ability.common'; 131 132@Component 133struct ReadPage{ 134 @Prop content:string= "" 135 136 build(){ 137 Column(){ 138 Text(this.content) 139 .textAlign(TextAlign.Center) 140 .width("100%") 141 .height("100%") 142 .fontSize(50) 143 } 144 .borderColor(Color.Black) 145 .borderWidth(2) 146 .width("100%") 147 .height("100%") 148 } 149} 150 151@Entry 152@Component 153export struct Reader{ 154 @State bgColor:string = "#EDA7A7" 155 @State content1:string = "" 156 @State content2:string = "" 157 @State content3:string = "" 158 private currentPageNum:number = 1 159 @State offsetX:number = 0 160 @State curPosition:number = 0 161 private panOption:PanGestureOptions = new PanGestureOptions({direction:PanDirection.Left | PanDirection.Right}) 162 private screenW:number = px2vp(display.getDefaultDisplaySync().width) 163 // 沉浸式窗口 164 context:common.UIAbilityContext = getContext(this) as common.UIAbilityContext 165 async setSystemBar(){ 166 let windowClass:window.Window = await window.getLastWindow(this.context) 167 await windowClass.setWindowSystemBarProperties({ 168 navigationBarColor:"#EDA7A7", 169 statusBarColor:"#EDA7A7", 170 navigationBarContentColor:"#EDA7A7", 171 statusBarContentColor:"#EDA7A7" 172 }) 173 } 174 175 aboutToAppear(){ 176 console.info("oh----->内容宽度:" + this.screenW) 177 this.novelContent() 178 this.setSystemBar() 179 } 180 181 /// 构建小说内容 182 novelContent(){ 183 this.content1 = (this.currentPageNum - 1) + "___小说___" + (this.currentPageNum - 1) 184 this.content2 = (this.currentPageNum) + "___小说___" + (this.currentPageNum) 185 this.content3 = (this.currentPageNum + 1) + "___小说___" + (this.currentPageNum + 1) 186 console.log("oh----->currentPage=" + this.currentPageNum) 187 console.log("oh----->content1=" + this.content1) 188 console.log("oh----->content2=" + this.content2) 189 console.log("oh----->content3=" + this.content3); 190 } 191 192 private clickAnimateTo(isLeft: Boolean){ 193 animateTo({ 194 duration:400, 195 curve:Curve.EaseOut, 196 onFinish:()=>{ 197 if (this.offsetX > 100){ 198 this.currentPageNum -= 1 199 }else if (this.offsetX < -100){ 200 this.currentPageNum += 1 201 console.log("oh----->当前页变为" + this.currentPageNum) 202 } 203 this.offsetX = 0 204 this.novelContent() 205 } 206 },()=>{ 207 if (isLeft){ 208 this.offsetX = this.screenW 209 }else{ 210 this.offsetX = -this.screenW 211 } 212 }) 213 } 214 215 build(){ 216 NavDestination(){ 217 Stack(){ 218 ReadPage({content:this.content3}) 219 .backgroundColor(this.bgColor) 220 221 ReadPage({content:this.content2}) 222 .translate({x:this.offsetX >= 0 ? 0:this.offsetX , y:0 , z:0}) 223 .backgroundColor(this.bgColor) 224 .width(this.screenW) 225 226 ReadPage({content:this.content1}) 227 .backgroundColor(this.bgColor) 228 .translate({ 229 x:-this.screenW + this.offsetX 230 }) 231 } 232 .onClick((event?:ClickEvent)=>{ 233 if (event){ 234 console.log("点击位置:" + event.x) 235 if (event.x > this.screenW / 3 * 2){ 236 this.clickAnimateTo(false) 237 }else if(event.x > this.screenW /3){ 238 promptAction.showToast({ 239 message:"打开菜单", 240 duration:300 241 }) 242 }else{ 243 if (this.currentPageNum == 1){ 244 promptAction.showToast({ 245 message:"没有内容!", 246 duration:300 247 }) 248 }else{ 249 this.clickAnimateTo(true) 250 } 251 } 252 } 253 }) 254 } 255 .hideTitleBar(true) 256 // 可展示标题栏 257 // .title("小说阅读器") 258 } 259} 260``` 261## 参考 262[NavDestination](../application-dev/reference/apis-arkui/arkui-ts/ts-basic-components-navdestination.md) 263 264[管理应用窗口(Stage模型)](../application-dev/windowmanager/application-window-stage.md)