当前位置: 首页 > news >正文

快速入门HarmonyOS应用开发(三)

目录

前言

1、应用沉浸式

2、主页框架搭建

3、实现效果

前言

本系列案例完整代码已上传GitHub:HarmonyDemos 

------觉得还行的麻烦动动发财的小手点个小星星啦^_^

今天咱们接着上一篇中的功能来继续实现案例Demo,做完闪屏页之后肯定是要到主页了,那今天咱们就来搭建一下APP的主页框架,实现底部的Tab和对应页面的切换,话不多说,开干!

1、应用沉浸式

首先来给咱们的应用实现沉浸式效果,参考官网中的实现方式:

开发应用沉浸式效果

我们选择的方案是窗口全屏布局方案,整体上分为以下几个步骤:

①、调用setWindowLayoutFullScreen()接口设置窗口全屏

②、使用getWindowAvoidArea()接口获取当前布局遮挡区域

③、注册监听函数,动态获取避让区域的实时数据

④、布局中的UI元素需要避让状态栏和导航区域

实现代码:在EntryAbility的onWindowStageCreate()的loadContent()回调中添加代码

// 使用同步方式获取应用主窗口let windowClass: window.Window = windowStage.getMainWindowSync()// 设置状态栏字体颜色windowClass.setWindowSystemBarProperties({statusBarContentColor: '#FFFFFF'})// 设置窗口全屏windowClass.setWindowLayoutFullScreen(true)// 获取布局避让遮挡的区域let topType = window.AvoidAreaType.TYPE_SYSTEMlet topArea = windowClass.getWindowAvoidArea(topType)let topRectHeight = topArea.topRect.heightAppStorage.setOrCreate('topRectHeight', topRectHeight)let bottomType = window.AvoidAreaType.TYPE_NAVIGATION_INDICATORlet bottomArea = windowClass.getWindowAvoidArea(bottomType)let bottomRectHeight = bottomArea.bottomRect.heightAppStorage.setOrCreate('bottomRectHeight', bottomRectHeight)// 注册监听函数,动态获取避让区域的实时数据windowClass.on('avoidAreaChange', (data) => {if (data.type === window.AvoidAreaType.TYPE_SYSTEM) {let topRectHeight = data.area.topRect.heightAppStorage.setOrCreate('topRectHeight', topRectHeight)} else if (data.type == window.AvoidAreaType.TYPE_NAVIGATION_INDICATOR) {let bottomRectHeight = data.area.bottomRect.heightAppStorage.setOrCreate('bottomRectHeight', bottomRectHeight)}})

关于第4步需要在实际的页面中设置布局的底部Padding:

NavDestination() {
}.hideTitleBar(true).padding({bottom:DisplayUtil.getBottomRectHeight(this.getUIContext())})

这里用到了一个工具方法,其实就是对之前存储的数据进行获取之后封装的一个方法,代码如下:

export class DisplayUtil {static getTopRectHeight(context: UIContext): number {return context.px2vp(AppStorage.get<number>('topRectHeight') as number)}static getBottomRectHeight(context: UIContext): number {return context.px2vp(AppStorage.get<number>('bottomRectHeight') as number)}
}

从上面的代码中可以看到咱们有使用AppStorage进行存储和获取数据,关于AppStorage的使用,大家可以参考:

AppStorage:应用全局的UI状态存储

它是HarmonyOS中提供的用于全局内存缓存的机制,与应用进程绑定,需要注意的是它并不是持久化的存储,是内存缓存。

2、主页框架搭建

想要实现底部Tab之间的切换效果,我们需要使用到一个新的系统提供的组件Tabs组件,参考:

选项卡 (Tabs)

打开MainPage页面,我们需要的整体结构是上下结构,上面是每个Tab的页面,下面是Tab按钮。

首先,我们来自定义底部的Tab按钮,这里放置5个按钮,先来定义每个按钮的样式:

@State currentTabIndex: number = CommonConstant.TAB_INDEX
@BuilderTabItem(tabInfo: TabInfo) {Column() {Image(this.currentTabIndex === tabInfo.index ? tabInfo.selectImg : tabInfo.img).objectFit(ImageFit.Contain).width($r('app.float.vp_24')).height($r('app.float.vp_24')).margin({ bottom: $r('app.float.vp_5') })Text(tabInfo.title).width(CommonConstant.FULL_PERCENT).height($r('app.float.vp_16')).fontSize($r('app.float.fp_12')).textAlign(TextAlign.Center).fontColor(this.currentTabIndex === tabInfo.index ? $r("app.color.color_primary") :$r('app.color.color_unselect'))}.width(CommonConstant.FULL_PERCENT).height(CommonConstant.FULL_PERCENT).justifyContent(FlexAlign.Center).width(CommonConstant.PERCENT_20).onClick(() => {this.currentTabIndex = tabInfo.index})}

这里我们用到了@Builder这个装饰器,它是自定义的构建函数,关于它的使用,大家可以参考:

@Builder装饰器:自定义构建函数

在点击这个按钮的时候,通过对上面定义的currentTabIndex变量值的改变来切换不同的下标。

接着,通过循环来实现5个Tab按钮的创建:

@BuilderBottomTabView() {Column() {Divider().width(CommonConstant.FULL_PERCENT).color(Color.Black).opacity(CommonConstant.OPACITY_01).strokeWidth(CommonConstant.WEIGHT_1)Row() {ForEach(tabInfos, (button: TabInfo) => {this.TabItem(button)})}.width(CommonConstant.FULL_PERCENT).height($r('app.float.vp_50')).alignItems(VerticalAlign.Center).backgroundColor(Color.White)}.width(CommonConstant.FULL_PERCENT)}

这里我们使用了ForEach来进行循环渲染,关于ForEach的详细使用,大家可以参考:

ForEach:循环渲染

这里ForEach的第一个参数是我们提前准备好的Tabs的数据,我们把它放在了src/main/ets/model下面:

export class TabInfo {index: number = 0img: Resource = $r('app.media.tab_index')selectImg: Resource = $r('app.media.tab_indexed')title: Resource = $r('app.string.tab_index')
}const tabInfos: TabInfo[] = [{index: 0,img: $r('app.media.tab_index'),selectImg: $r('app.media.tab_indexed'),title: $r('app.string.tab_index')},{index: 1,img: $r('app.media.tab_financial'),selectImg: $r('app.media.tab_financialed'),title: $r('app.string.tab_financial')},{index: 2,img: $r('app.media.tab_video'),selectImg: $r('app.media.tab_videoed'),title: $r('app.string.tab_video')},{index: 3,img: $r('app.media.tab_message'),selectImg: $r('app.media.tab_messaged'),title: $r('app.string.tab_msg')},{index: 4,img: $r('app.media.tab_mine'),selectImg: $r('app.media.tab_mined'),title: $r('app.string.tab_mine')}
]export { tabInfos }

做完上面这些之后,我们就可以来实现整个页面的结构了,在MainPage的NavDestination中通过Column组件来完成上下结构的布局,上面使用Tabs组件,下面使用自定义的BottomTabView():

build() {NavDestination() {Column() {Tabs({ index: this.currentTabIndex }) {TabContent() {HomePage()}TabContent() {FinancialPage()}TabContent() {VideoPage()}TabContent() {MessagePage()}TabContent() {MinePage()}}.barHeight(CommonConstant.TAB_BAR_HEIGHT).scrollable(false).layoutWeight(CommonConstant.WEIGHT_1).onChange((index) => {this.currentTabIndex = index})this.BottomTabView()}}.hideTitleBar(true).padding({bottom:DisplayUtil.getBottomRectHeight(this.getUIContext())})}

可以看到我们一共创建了5个TabContent(),每个里面就是对应Tab承载的内容区域了,简单理解可以称它为页面,实际上它们都是自定义组件,比如,这里第一个TabContent()里面我们创建了HomePage()组件,依此类推我们又创建了余下的四个页面。

下面来看一下HomePage()里面都有些什么吧?由于目前我们只是为了实现页面的整体结构,所以这里咱们就简单放置了一个文本进行展示,代码如下:

@Component
export struct HomePage {build() {Column() {StatusBarComponent()Column() {Text($r('app.string.tab_index')).fontSize($r('app.float.fp_20')).fontColor($r('app.color.color_primary')).fontWeight(FontWeight.Bold)}.layoutWeight(CommonConstant.WEIGHT_1).justifyContent(FlexAlign.Center)}.width(CommonConstant.FULL_PERCENT).height(CommonConstant.FULL_PERCENT)}
}

细心的大家会发现这不是还有一个StatusBarComponent()吗?它是我们自定义的一个状态栏横条,里面也很简单,只有一个跟顶部状态栏高度一致的View,代码如下:

@Component
export struct StatusBarComponent {build() {Blank().height(DisplayUtil.getTopRectHeight(this.getUIContext())).backgroundColor($r('app.color.color_primary'))}
}

通过上面的步骤我们已经完成了首页整体结构的搭建。

3、实现效果

下面,让我们一起来看一下最终的实现效果吧:

主页面结构录屏

OK,今天的内容就这么多啦,下期再会!

祝:工作顺利,生活愉快!

http://www.dtcms.com/a/403037.html

相关文章:

  • Easysearch 国产替代 Elasticsearch:8 大核心问题解读
  • 【机器学习】搭建对抗神经网络模型来实现 MNIST 手写数字生成
  • 做推广的网站那个好中国机房建设公司排名
  • odoo18应用、队列服务器分离(SSHFS)
  • 老年健康管理小工具抖音快手微信小程序看广告流量主开源
  • c#vb.net动态创建二维数组
  • php做网站完整视频动漫制作和动漫设计哪个好
  • 云原生微服务中间件选型
  • Python/JS/Go/Java同步学习(第二十四篇)四语言“元组概念“对照表: 雷影“老板“发飙要求员工下班留校培训风暴(附源码/截图/参数表/避坑指南)
  • vue3在 script 中定义组件
  • 【CSRF】防御
  • vue从template模板到真实渲染在页面上发生了什么
  • 从构建工具到状态管理:React项目全栈技术选型指南
  • 做彩票网站电话多少钱湛江网站网站建设
  • 云手机性能会受到哪些因素的影响?
  • app网站维护网站开发众包平台
  • [iOS] OC高级编程 - 引用计数 (1)
  • MyBatis-Plus实用指南:玩转自动化与高效CRUD
  • 揭开AI神秘面纱:大语言模型原理与Python极简开发
  • cmake详解
  • RabbitMQ-高可用机制
  • 云手机对网络游戏的重要性
  • 莱州做网站设计院一般年薪
  • Java 将 PDF 转换为 HTML:高效解决方案与实践
  • 从Prompt到Answer:详解AI Agent架构中的ReAct模式与工具调用
  • 六、OpenCV中的图像读写
  • 设计案例的网站pc开奖网站建设
  • 10月底实习准备-Mysql(按面试频率准备)
  • Flink Watermark机制解析
  • Windows系统Web UI自动化测试学习系列2--环境搭建--Python-PyCharm-Selenium