【HarmonyOS】鸿蒙系统在租房项目中的项目实战(二)

        从今天开始,博主将开设一门新的专栏用来讲解市面上比较热门的技术 “鸿蒙开发”,对于刚接触这项技术的小伙伴在学习鸿蒙开发之前,有必要先了解一下鸿蒙,从你的角度来讲,你认为什么是鸿蒙呢?它出现的意义又是什么?鸿蒙仅仅是一个手机操作系统吗?它的出现能够和Android和IOS三分天下吗?它未来的潜力能否制霸整个手机市场呢?

今天实现一个简单的小案例,从零开始讲解如何通过鸿蒙开发实现一个租房平台的案例。

目录

房源推荐搭建

封装滚动组件

状态功能适配

想看模块搭建


房源推荐搭建

接下来我们开始编写房源推荐的相关内容,首先我们先把接口写好,这里我们先根据后端返回的接口类型的数据将接口类型编写一遍:

// 公共类型
interface BaseResponse {code: number;message: string;
}
interface BaseID { id: number }
interface BaseName { name: string }
interface BaseTitle { title: string }
interface BaseSubTitle { sub_title: string }
interface BaseImageURL { imageURL: string }// 房源推荐数据
interface BaseRecommendData extends BaseResponse {data: RecommendData[]
}
interface RecommendData extends BaseID {housePicture: stringtags: BaseName[]houseTitle: stringaddress: stringrentPriceUnit: stringrentPriceListing: stringrentArea: string
}export {BaseRecommendData,RecommendData
}

然后我们根据后端的路径开始编写接口函数,将上面的类型赋值的接口的返回值当中:

import http from "../../utils/http"
import type { HomeData, BaseRecommendData } from './type'// 统一管理接口
enum API {HOME_INFO = '/home/info',ROOM_RECOMMEND = '/house/nearbyHouses'
}// 获取首页数据
export const reqHomeData = () =>http.get<any, HomeData>(API.HOME_INFO)// 获取房源推荐数据
export const reqRecommendData = () =>http.get<any, BaseRecommendData>(API.ROOM_RECOMMEND)

因为房源组件的数据仅仅是该组件要使用而已,所以我们的接口数据就只需要在该组件进行调用即可,代码如下所示:

@State roomRecommentList: RecommendData[] = []
// 获取房源数据
getRoomRecommendData = async () => {const res: BaseRecommendData = await reqRecommendData()this.roomRecommentList = res.data
}aboutToAppear(): void {this.getRoomRecommendData()
}

后面就是借助Grid布局调整调整样式即可,最终呈现的效果如下所示:

封装滚动组件

接下来我们开始封装滚动组件,因为搜索栏的组件可能多个页面都会用到,并且会随着页面的滚动的时候出现在顶部并渐变显示,这里我们也是需要对其颜色样式进行一个动态的渲染,这里我们都将其放置在公共组件当中去,这里也是用到了插槽的内容,具体如下:

如下代码我们封装了一个插槽,一个是用于放置滚动的主体内容,另一个是放置搜索栏:

interface IColor {bgColor: stringfontColor: string
}@Component
export default struct ScrollContainer {@Builder customBuilder() {}@BuilderParam navBuilderParam: ($$: IColor) => void = this.customBuilder@BuilderParam contentBuilderParam: () => void = this.customBuilder@State scrollY: number = 0 // 存储滚动条位置(y轴滚动距离)@State bgColor: string = 'rgba(0, 0, 0, 0)' // 背景颜色@State fontColor: string = 'rgba(255, 255, 255, 1)' // 字体颜色// 处理滚动事件handleScroll = (xOffset: number, yOffset: number) => {this.scrollY += yOffset // 存储滚动条位置(y轴滚动距离)this.calcColor() // 监听文字颜色变化范围}// 监听文字颜色变化范围calcColor = () => {if (this.scrollY < 10) {// 到达顶部,渐变开始this.bgColor = 'rgba(255, 255, 255, 0)'this.fontColor = 'rgba(255, 255, 255, 1)'} else if (this.scrollY <= 100) {// 渐变中(透明度 0 -> 1)const  colorOpacity = (this.scrollY - 10) / (100 - 10)this.bgColor = `rgba(255, 255, 255, ${colorOpacity})`this.fontColor = `rgba(0, 0, 0, ${colorOpacity})`} else {// 渐变结束this.bgColor = 'rgba(255, 255, 255, 1)'this.fontColor = 'rgba(0, 0, 0, 1)'}}build() {Stack() {Scroll() {Column() {this.contentBuilderParam()}.width('100%')}.width('100%').height('100%').scrollBar(BarState.Off).align(Alignment.TopStart).onDidScroll(this.handleScroll)// 搜索栏组件, 按引用传递this.navBuilderParam({ bgColor: this.bgColor, fontColor: this.fontColor })}.width('100%').alignContent(Alignment.TopStart)}
}

接下来我们需要对首页的内容进行改造一下,将原本的代码直接删掉,采用插槽的方式进行书写,因为使用@Builder会导致this指向的问题,所以我们在调用的时候,包一层箭头函数即可:

import { reqHomeData } from '../api/home'
import type { HomeData, bannerList, navList, tileList, planList } from '../api/home/type'
import { PADDING, SHADOW_RADIUS } from '../contants/size'
import SwiperLayout from '../components/Home/SwiperLayout'
import SearchBar from '../components/Home/SearchBar'
import NavList from '../components/Home/NavList'
import TitleList from  '../components/Home/TitleList'
import PlanList from '../components/Home/PlanList'
import RoomRecommend from '../components/Home/RoomRecommend'
import ScrollContainer from '../components/Container/ScrollContainer'interface IColor {bgColor: stringfontColor: string
}@Component
export default struct Home {@State bannerList: bannerList[] = []@State navList: navList[] = []@State titleList: tileList[] = []@State planList: planList[] = []@State adPicture: string = ''// 获取首页数据getHomeData = async () => {const res: HomeData = await reqHomeData()this.bannerList = res.data.bannerListthis.navList = res.data.navListthis.titleList = res.data.tileListthis.planList = res.data.planListthis.adPicture = res.data.adPicture}// 初始化页面调用aboutToAppear(): void {this.getHomeData()}@BuildernavBuilder($$: IColor) {// 搜索栏组件SearchBar({ bgColor: $$.bgColor, fontColor: $$.fontColor })}@BuildercontentBuilder() {SwiperLayout({ bannerList: this.bannerList }) // 轮播图组件使用props通信Column() {NavList({ navList: this.navList }) // 导航栏组件使用props通信TitleList({ titleList: this.titleList }) // 标题栏组件使用props通信PlanList({ planList: this.planList }) // 列表组件Image(this.adPicture) // 广告图.width('100%').height(60).objectFit(ImageFit.Fill).margin({ top: 10 }).shadow({ offsetX: 0, offsetY: 0, radius: SHADOW_RADIUS, color: 'rgba(0, 0, 0, 0.14)' })}.width('100%').padding({ left: PADDING, right: PADDING })RoomRecommend() // 推荐房源组件}build() {ScrollContainer({navBuilderParam: this.navBuilder,contentBuilderParam: () => {// 使用Builder函数,需要使用箭头函数指向this实例this.contentBuilder()},})}
}

最终呈现的效果如下所示,依然实现了原本的效果:

状态功能适配

        因为我们上面都是按照UI设计稿来设置的宽高度,也就是说我们把样式给写死了,当用户用其他不同的比例的显示器去查看我们设计的页面的时候,就会出现适配问题,为此我们需要对一些功能的状态适配问题进行相应的处理。

我们来到进入应用窗口的函数当中进行编写,将获取到的相关状态高度颜色等进行持久化存储:

然后我们可以在滚动容器当中拿到对应的对象:

windowStyle?: window.WindowgetWindowStyle = async  () => {this.windowStyle = await window.getLastWindow(getContext(this))
}

在设定颜色的内容处根据滚动距离设置不同的颜色内容:

然后我们可以根据适配器的内容设置一下适配函数,在所有的定义宽高距离的内容当中调用一下该函数进行适配:

/** 计算元素真正的大小:元素在设计稿的大小 / 设计稿总宽度 = x / 真机宽度(保证元素在不同设备占比相同)x = 元素在设计稿的大小 / 设计稿总宽度 * 真机宽度* */const DRAFT_WIDTH = 360
// 预览器获取不到宽度,给预览器默认值360
const windowWidth = AppStorage.get('windowWidth') as number || 360
const rvp = (val: number) => {return val / DRAFT_WIDTH * windowWidth
}export default rvp

然后我们给设置的每一个距离的内容都调用该函数即可:

想看模块搭建

接下来我们开始搭建想看的模块内容,首先我们先处理一下导航栏的样式内容,如下所示:

import { PADDING } from "../../contants/size"
import rvp from "../../utils/responsive"@Component
export default struct NavBar {@StorageProp('topHeight') topHeight: number = 0build() {Row() {Row({ space: rvp(6) }) {Image($r('app.media.bag')).width(rvp(16)).height(rvp(16))Text('请写通勤地址').fontSize(rvp(12)).fontColor($r('app.color.black'))}Row({ space: rvp(28) }) {Column({ space: rvp(1) }) {Image($r('app.media.message')).width(rvp(20)).height(rvp(20)).fillColor($r('app.color.black'))Text('消息').fontSize(rvp(10)).fontColor($r('app.color.black'))}Column({ space: rvp(1) }) {Image($r('app.media.journey')).width(rvp(20)).height(rvp(20))Text('行程').fontSize(rvp(10)).fontColor($r('app.color.black'))}}}.width('100%').height(rvp(44)).justifyContent(FlexAlign.SpaceBetween).padding({ left: rvp(PADDING), right: rvp(PADDING) }).margin({ top: this.topHeight })}
}

接着处理一下找房的一些图片文字资源的显示:

import { PADDING } from "../../contants/size"
import rvp from "../../utils/responsive"@Component
export default struct NavBar {@StorageProp('topHeight') topHeight: number = 0build() {Column() {Image($r('app.media.find_room')).width(rvp(60)).height(rvp(23)).margin({ left: rvp(4) })Text('发现你想看的房子').margin({ left: rvp(4), top: rvp(20) }).fontSize(rvp(12)).fontColor($r('app.color.black'))Image($r('app.media.blank')).width(rvp(234)).height(rvp(221)).alignSelf(ItemAlign.Center).margin({ top: rvp(7) })Text("暂无想看房源,试试如下找房方式").width('100%').textAlign(TextAlign.Center).margin({ top: rvp(10) }).fontSize(rvp(16)).fontColor($r('app.color.black')).fontWeight(600)Row({ space: rvp(10) }) {Row({ space: rvp(5) }) {Image($r('app.media.bus')).width(rvp(40)).height(rvp(40))Column({ space: rvp(3) }) {Text('通勤找房').fontSize(rvp(16)).fontColor($r('app.color.black'))Text('找公交车站附件房源').fontSize(rvp(12)).fontColor($r('app.color.gray'))}.alignItems(HorizontalAlign.Start)}Row({ space: rvp(5) }) {Image($r('app.media.map')).width(rvp(40)).height(rvp(40))Column({ space: rvp(3) }) {Text('地图找房').fontSize(rvp(16)).fontColor($r('app.color.black'))Text('找地图附件房源').fontSize(rvp(12)).fontColor($r('app.color.gray'))}.alignItems(HorizontalAlign.Start)}}.width('100%').height(rvp(70)).border({ width: 1, color: $r('app.color.shadow') }).margin({ top: rvp(10) }).justifyContent(FlexAlign.SpaceAround)}.width('100%').alignItems(HorizontalAlign.Start).padding({ top: rvp(54), left: rvp(PADDING), right: rvp(PADDING) })}
}

然后我们将两个封装的组件在See的想看模块中进行调用,如下所示:

import NavBar from '../components/See/NavBar'
import FindRoom from '../components/See/FindRoom'@Component
export default struct See {build() {Column() {NavBar()FindRoom()}.width('100%').height('100%').linearGradient({direction: GradientDirection.Bottom,colors: [['#DEFBE5', 0], ['#FFFFFF', 0.3]]})}
}

最终呈现的效果如下所示:

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

深度学习神经网络创新点方向

一、引言 深度学习神经网络在过去几十年里取得了令人瞩目的成就&#xff0c;从图像识别、语音处理到自然语言理解等众多领域都有广泛应用。然而&#xff0c;随着数据量的不断增长和应用场景的日益复杂&#xff0c;对神经网络的创新需求也愈发迫切。本文将探讨深度学习神经网络…

C++析构函数详解

C析构函数详解&#xff1a;对象销毁与资源清理 在 C 中&#xff0c;析构函数是与构造函数相对应的特殊成员函数&#xff0c;它在对象生命周期结束时被自动调用&#xff0c;用于执行对象销毁之前的清理操作。析构函数主要用于释放对象占用的资源&#xff0c;如动态分配的内存、打…

Minikube 上安装 Argo Workflow

文章目录 步骤 1&#xff1a;启动 Minikube 集群步骤 2&#xff1a;安装Argo Workflow步骤 3&#xff1a;访问UI创建流水线任务参考 前提条件&#xff1a; Minikube&#xff1a;确保你已经安装并启动了 Minikube。 kubectl&#xff1a;确保你已经安装并配置了 kubectl&#xff…

计算机编程中的设计模式及其在简化复杂系统设计中的应用

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 计算机编程中的设计模式及其在简化复杂系统设计中的应用 计算机编程中的设计模式及其在简化复杂系统设计中的应用 计算机编程中的…

基于 CentOS7.6 的 Docker 下载常用的容器(MySQLRedisMongoDB),解决拉取容器镜像失败问题

安装MySQL&Redis&MongoDB mysql选择是8版本&#xff0c;redis是选择4版本、mongoDB选择最新版&#xff0c;也可以根据自己的需要进行下载对应的版本&#xff0c;无非就是容器名:版本号 这样去拉去相关的容器镜像。如果你还不会在服务器中安装 docker&#xff0c;可以查…

【分布式】万字图文解析——深入七大分布式事务解决方案

分布式事务 分布式事务是指跨多个独立服务或系统的事务管理&#xff0c;以确保这些服务中的数据变更要么全部成功&#xff0c;要么全部回滚&#xff0c;从而保证数据的一致性。在微服务架构和分布式系统中&#xff0c;由于业务逻辑往往会跨多个服务&#xff0c;传统的单体事务…

SystemVerilog学习笔记(十一):接口

在Verilog中&#xff0c;模块之间的通信是使用模块端口指定的。 Verilog模块连接的缺点 声明必须在多个模块中重复。存在声明不匹配的风险。设计规格的更改可能需要修改多个模块。 接口 SystemVerilog引入了 interface 结构&#xff0c;它封装了模块之间的通信。一个 inter…

ARM 汇编指令

blr指令的基本概念和用途 在 ARM64 汇编中&#xff0c;blr是 “Branch with Link to Register” 的缩写。它是一种分支指令&#xff0c;主要用于跳转到一个由寄存器指定的地址&#xff0c;并将返回地址保存到链接寄存器&#xff08;Link Register&#xff0c;LR&#xff09;中。…

pycharm分支提交操作

一、Pycharm拉取Git远程仓库代码 1、点击VCS > Get from Version Control 2、输入git的url&#xff0c;选择自己的项目路径 3、点击Clone&#xff0c;就拉取成功了 默认签出分支为main 选择develop签出即可进行开发工作 二、创建分支&#xff08;非必要可以不使用&#xf…

【MySQL】优化方向+表连接

目录 数据库表连接 表的关系与外键 数据库设计 规范化 反规范化 事务一致性 表优化 索引优化 表结构优化 查询优化 数据库表连接 表的关系与外键 表之间的关系 常见表关系总结 一对一关系&#xff1a;每一条记录在表A中对应表B的唯一一条记录&#xff0c;反之也是&a…

【数据库】mysql数据库迁移前应如何备份数据?

MySQL 数据库的备份是确保数据安全的重要措施之一。在进行数据库迁移之前&#xff0c;备份现有数据可以防止数据丢失或损坏。以下是一套详细的 MySQL 数据库备份步骤&#xff0c;适用于大多数情况。请注意&#xff0c;具体的命令和工具可能因 MySQL 版本的不同而有所差异。整个…

mybatis 动态SQL语句

10. 动态SQL 10.1. 介绍 什么是动态SQL&#xff1a;动态SQL指的是根据不同的查询条件 , 生成不同的Sql语句. 官网描述&#xff1a;MyBatis 的强大特性之一便是它的动态 SQL。如果你有使用 JDBC 或其它类似框架的经验&#xff0c;你就能体会到根据不同条件拼接 SQL 语句的痛苦…

shell脚本_永久环境变量和字符串操作

一、永久环境变量 1. 常见的环境变量 2. 设置永久环境变量 3.1.将脚本加进PATH变量的目录中 3.2.添加进环境变量里 3.2.修改用户的 shell 配置文件 二、字符串操作 1. 字符串拼接 2. 字符串切片 3. 字符串查找 4. 字符串替换 5. 字符串大小写转换 6. 字符串分割 7…

【Go】-bufio库解读

目录 Reader和Writer接口 bufio.Reader/Writer 小结 其他函数-Peek、fill Reader小结 Writer Scanner结构体 缓冲区对于网络数据读写的重要性 Reader和Writer接口 在net/http包生成的Conn 接口的实例中有两个方法叫做Read和Write接口 type Conn interface {Read(b []b…

场景营销在企业定制开发 AI 智能名片 S2B2C 商城小程序中的应用与价值

摘要&#xff1a;本文深入剖析了品牌广告效果不佳与场景营销缺失之间的内在联系&#xff0c;阐述了场景营销对于品牌落地和转化的关键意义。同时&#xff0c;详细探讨了如何将场景营销理念与实践应用于企业定制开发的 AI 智能名片 S2B2C 商城小程序中&#xff0c;借助移动时代的…

uniapp 实现tabbar分类导航及滚动联动效果

思路&#xff1a;使用两个scroll-view&#xff0c;tabbar分类导航使用scrollleft移动&#xff0c;内容联动使用页面滚动onPageScroll监听滚动高度 效果图 <template><view class"content" ><view :class"[isSticky ? tab-sticky: ]">…

Flutter中的Material Theme完全指南:从入门到实战

Flutter作为一款热门的跨平台开发框架&#xff0c;其UI组件库Material Design深受开发者喜爱。本文将深入探讨Flutter Material Theme的使用&#xff0c;包括如何借助Material Theme Builder创建符合产品需求的主题风格。通过多个场景和代码实例&#xff0c;让你轻松掌握这一工…

aws中AcmClient.describeCertificate返回值中没有ResourceRecord

我有一个需求&#xff0c;就是让用户自己把自己的域名绑定我们的提供的AWS服务器。 AWS需要验证证书 上一篇文章中我用php的AcmClient中的requestCertificate方法申请到了证书。 $acmClient new AcmClient([region > us-east-1,version > 2015-12-08,credentials>[/…

Oracle 19c PDB克隆后出现Warning: PDB altered with errors受限模式处理

在进行一次19c PDB克隆过程中&#xff0c;发现克隆结束&#xff0c;在打开后出现了报错&#xff0c;PDB变成受限模式&#xff0c;以下是分析处理过程 09:25:48 SQL> alter pluggable database test1113 open instancesall; Warning: PDB altered with errors. Elapsed: 0…

【3D Slicer】的小白入门使用指南九

定量医学影像临床研究与实践 任务 定量成像教程 定量成像是从医学影像中提取定量测量的过程。 本教程基于两个定量成像的例子构建: - 形态学:缓慢生长肿瘤中的小体积变化 - 功能:鳞状细胞癌中的代谢活动 第1部分:使用变化跟踪模块测量脑膜瘤的小体积变化第2部分:使用PET标…