针对harmonyos是安卓系统吗详情和harmonyos是不是安卓这两个问题,本篇文章进行了详细的解答,同时本文还将给你拓展#HarmonyOS体验官【挑战赛第一期】用HarmonyOSArkUI来
针对harmonyos是安卓系统吗详情和harmonyos是不是安卓这两个问题,本篇文章进行了详细的解答,同时本文还将给你拓展#HarmonyOS 体验官【挑战赛第一期】用 HarmonyOS ArkUI 来开发一个购物应用程序、#HarmonyOS体验官#OpenHarmony和HarmonyOS的差异、#HarmonyOS小课堂# 速览
- harmonyos是安卓系统吗详情(harmonyos是不是安卓)
- #HarmonyOS 体验官【挑战赛第一期】用 HarmonyOS ArkUI 来开发一个购物应用程序
- #HarmonyOS体验官#OpenHarmony和HarmonyOS的差异
- #HarmonyOS小课堂# 速览
课程精华第一期:运行Hello World - #HarmonyOS小课堂# 速览
课程精华第三期:ArkTS基础知识
harmonyos是安卓系统吗详情(harmonyos是不是安卓)
华为自己研发了harmonyos系统,很多的用户就将它和安卓联系在了一起,那么harmonyos是安卓系统吗?相信这个问题已经让很多的手机用户疑惑了吧,下面就看看介绍来了解一下吧。
harmonyos是安卓系统吗:
答:harmonyos不是安卓系统。
harmonyos也叫鸿蒙,是华为研发的新一代智能终端操作系统。
可以为不同的设备实现智能化,为大家提供了统一的语言,
带来了更加便捷流畅以及安全性,能够全场景交互体验。
harmonyos更多介绍:
1、harmonyos的最大优势就是可以万物互联,是面向多种全场景智能设备的系统。
2、不仅可以适配手机,还能够去支持电脑平板和电视,以及无人驾驶和车机设备等。
3、相反安卓系统却有着很大的局限性,因此鸿蒙可以给用户带来一个更大的生态圈。
相关文章:体验感受 | ui界面展示
#HarmonyOS 体验官【挑战赛第一期】用 HarmonyOS ArkUI 来开发一个购物应用程序
本文演示如果用 HarmonyOS 的 ArkUI 来开发一个购物应用程序。体验 HarmonyOS 3 最新的 API 9,欢迎大家一起参与构建这个万物互联的时代!
活动主页
HarmonyOS 线上 Codelabs 挑战赛已经开启,该系列挑战赛将围绕 HarmonyOS 的基础组件和容器组件、三方库和数据库等技术特性展开,开发者们可以通过体验基于 HarmonyOS 特性和能力的应用开发,快速构建有趣、有用的应用程序。
有兴趣的朋友一起参与吧。
活动主页:
https://developer.huawei.com/consumer/cn/forum/topic/0204102597850175203?fid=0101587866109860105
获取 HarmonyOS 应用源码
HarmonyOS 的 ArkUI 来开发的购物应用程序 “ArkUIShopping”,全部代码可以在《跟老卫学 HarmonyOS 开发》项目中找到(链接见文末 “参考引用”)。有兴趣的网友可以 clone 该代码到本地进行运行、测试、修改。
接下来将介绍该购物应用程序 “ArkUIShopping” 是如何实现的。
通过 DevEco Studio 3 创建应用
有关 DevEco Studio 3 的安装配置,可以参考前文《・玩转 HarmonyOS 3 必装 DevEco Studio 3,注意避弹》这里就不在赘述。
首选是打开 DevEco Studio 3,可以看到如下界面。
点击 “Create Project” 来创建 ArkUI 程序 “ArkUIShopping”。
选择模板
选择空模板 Empty Ability,点击 “Next” 执行下一步。
配置项目
配置项目信息,重要是以下圈中部分。其他配置按照默认配置即可。点击 “Finish” 执行下一步。
程序初始化完成之后,就能在该程序基础上进行代码开发、运行。
运行 HarmonyOS 应用
打开 Device Manager
登入华为账号
点击 “Sign In” 登入个人注册的华为账号。如果没有,则参考本文最后的链接进行注册。
启动远程模拟器
运行应用
点击下命的三角形按钮以启动应用
应用运行效果图如下。
完善代码
在空模板的基础上,我们初步添加业务代码,来最终实现购物应用。
实现商品列表页签
主界面商品列表页签主要由下面三个部分组成:
- 顶部的 Tabs 组件。
- 中间 TabContent 组件内包含 List 组件。其中 List 组件的 item 是一个水平布局,由一个垂直布局和一个 Image 组件组成;item 中的垂直布局由 3 个 Text 组件组成。
- 底部的页签导航。
下面来一起创建第一个页面。
在 pages 目录下面新建一个 Page.。
该 Page 命名为 HomePage。
创建完成之后,会在 pages 目录下面生产一个 HomePage.ets 文件,HomePage.ets 文件默认的代码如下。
@Entry
@Component
struct HomePage {
@State message: string = ''Hello World''
build() {
Row() {
Column() {
Text(this.message)
.fontSize(50)
.fontWeight(FontWeight.Bold)
}
.width(''100%'')
}
.height(''100%'')
}
}
新建与 pages 文件夹同级的 model 文件夹,并在 model 目录下新建 ArsData.ets、GoodsData.ets、Menu.ets 和 GoodsDataModels.ets 文件,其中 ArsData.ets、GoodsData.ets、Menu.ets 是数据实体类,GoodsDataModels.ets 是存放这三种实体数据集合,并定义了获取各种数据集合的方法。数据实体包含实体的属性和构造方法,可通过 new ArsData (string,string) 来获取 ArsData 对象。
ArsData.ets 内容如下:
let NextId = 0;
export class ArsData {
id: string;
title: string;
content: string;
constructor(title: string, content: string) {
this.id = `${NextId++}`;
this.title = title;
this.content = content;
}
}
GoodsData.ets 内容如下:
let NextId = 0;
export class GoodsData {
id: string;
title: string;
content: string;
price: number;
imgSrc: Resource;
constructor(title: string, content: string, price: number, imgSrc: Resource) {
this.id = `${NextId++}`;
this.title = title;
this.content = content;
this.price = price;
this.imgSrc = imgSrc;
}
}
Menu.ets 内容如下:
let NextId = 0;
export class Menu {
id: string;
title: string;
num: number;
constructor(title: string, num: number) {
this.id = `${NextId++}`;
this.title = title;
this.num = num;
}
}
export class ImageItem {
id: string;
title: string;
imageSrc: Resource;
constructor(title: string, imageSrc: Resource) {
this.id = `${NextId++}`;
this.title = title;
this.imageSrc = imageSrc;
}
}
GoodsDataModels.ets 内容如下:
import { GoodsData} from ''./GoodsData''
import {Menu, ImageItem} from ''./Menu''
import {ArsData} from ''./ArsData''
export function initializeOnStartup(): Array<GoodsData> {
let GoodsDataArray: Array<GoodsData> = []
GoodsComposition.forEach(item => {
console.log(item.title);
GoodsDataArray.push(new GoodsData(item.title, item.content, item.price, item.imgSrc));
})
return GoodsDataArray;
}
export function getIconPath(): Array<string> {
let IconPath: Array<string> = [''nav/icon-buy.png'',''nav/icon-shopping-cart.png'',''nav/icon-my.png'']
return IconPath;
}
export function getIconPathSelect(): Array<string> {
let IconPathSelect: Array<string> = [''nav/icon-home.png'',''nav/icon-shopping-cart-select.png'',''nav/icon-my-select.png'']
return IconPathSelect;
}
export function getDetailImages(): Array<string> {
let detailImages: Array<string> = [''computer/computer1.png'',''computer/computer2.png'',''computer/computer3.png'',''computer/computer4.png'',''computer/computer5.png'',''computer/computer6.png'']
return detailImages;
}
export function getMenu(): Array<Menu> {
let MenuArray: Array<Menu> = []
MyMenu.forEach(item => {
MenuArray.push(new Menu(item.title,item.num));
})
return MenuArray;
}
export function getTrans(): Array<ImageItem> {
let ImageItemArray: Array<ImageItem> = []
MyTrans.forEach(item => {
ImageItemArray.push(new ImageItem(item.title,item.imageSrc));
})
return ImageItemArray;
}
export function getMore(): Array<ImageItem> {
let ImageItemArray: Array<ImageItem> = []
MyMore.forEach(item => {
ImageItemArray.push(new ImageItem(item.title,item.imageSrc));
})
return ImageItemArray;
}
export function getArs(): Array<ArsData> {
let ArsItemArray: Array<ArsData> = []
ArsList.forEach(item => {
ArsItemArray.push(new ArsData(item.title,item.content));
})
return ArsItemArray;
}
const GoodsComposition: any[] = [
{
"title": ''HUAWEI nova 8 Pro '',
"content": ''Goes on sale: 10:08'',
"price": ''3999'',
"imgSrc": $rawfile(''picture/HW (1).png'')
},
{
"title": ''HUAWEI Mate 30E Pro 5G'',
"content": ''3 interest-free payments '',
"price": ''5299'',
"imgSrc": $rawfile(''picture/HW (2).png'')
},
{
"title": ''HUAWEI MatePad Pro'',
"content": ''Flagship '',
"price": ''3799'',
"imgSrc": $rawfile(''picture/HW (3).png'')
},
{
"title": ''HUAWEI Nova 8 Pro'',
"content": ''New arrival '',
"price": ''3999'',
"imgSrc": $rawfile(''picture/HW (4).png'')
},
{
"title": ''HUAWEI WATCH FIT'',
"content": ''Versatile'',
"price": ''769'',
"imgSrc": $rawfile(''picture/HW (5).png'')
},
{
"title": ''HUAWEI nova 8 Pro '',
"content": ''Goes on sale: 10:08'',
"price": ''3999'',
"imgSrc": $rawfile(''picture/HW (6).png'')
},
{
"title": ''HUAWEI Mate 30E Pro 5G'',
"content": ''3 interest-free payments '',
"price": ''5299'',
"imgSrc": $rawfile(''picture/HW (7).png'')
},
{
"title": ''HUAWEI MatePad Pro'',
"content": ''Flagship '',
"price": ''3799'',
"imgSrc": $rawfile(''picture/HW (8).png'')
},
{
"title": ''HUAWEI Nova 8 Pro'',
"content": ''New arrival '',
"price": ''3999'',
"imgSrc": $rawfile(''picture/HW (9).png'')
},
{
"title": ''HUAWEI WATCH FIT'',
"content": ''Versatile'',
"price": ''769'',
"imgSrc": $rawfile(''picture/HW (10).png'')
},
]
const MyMenu: any[] = [
{
''title'': ''Favorites'',
''num'': ''10''
},
{
''title'': ''Searched'',
''num'': ''1000''
},
{
''title'': ''Following'',
''num'': ''100''
},
{
''title'': ''Followers'',
''num'': ''10000''
}
]
const MyTrans: any[] = [
{
''title'': ''Post: 520'',
''imageSrc'': $rawfile(''nav/icon-menu-release.png'')
},
{
''title'': ''Sold: 520'',
''imageSrc'': $rawfile(''nav/icon-menu-sell.png'')
},
{
''title'': ''Bought: 10'',
''imageSrc'': $rawfile(''nav/icon-menu-buy.png'')
}
]
const MyMore: any[] = [
{
''title'': ''Guide'',
''imageSrc'': $rawfile(''nav/icon-menu-buy.png'')
},
{
''title'': ''Create'',
''imageSrc'': $rawfile(''nav/icon-menu-buy.png'')
},
{
''title'': ''Poster'',
''imageSrc'': $rawfile(''nav/icon-menu-buy.png'')
},
{
''title'': ''Games'',
''imageSrc'': $rawfile(''nav/icon-menu-buy.png'')
},
{
''title'': ''Jobber'',
''imageSrc'': $rawfile(''nav/icon-menu-buy.png'')
},
{
''title'': ''Myself'',
''imageSrc'': $rawfile(''nav/icon-menu-buy.png'')
},
{
''title'': ''About'',
''imageSrc'': $rawfile(''nav/icon-menu-buy.png'')
},
{
''title'': ''Rental'',
''imageSrc'': $rawfile(''nav/icon-menu-buy.png'')
},
{
''title'': ''Author'',
''imageSrc'': $rawfile(''nav/icon-menu-buy.png'')
},
]
const ArsList: any[] =[
{
''title'': ''Display Size'',
''content'': ''13.9 inches'',
},
{
''title'': ''Memory'',
''content'': ''16 GB'',
},
{
''title'': ''Marketing Name'',
''content'': ''HUAWEI MateBook X Pro'',
},
{
''title'': ''Color Gamut'',
''content'': ''100% sRGB color gamut (Typical)'',
},
{
''title'': ''Battery'',
''content'': ''56 Wh (rated capacity)'',
},
{
''title'': ''Storage'',
''content'': ''512 GB'',
},
{
''title'': ''Resolution'',
''content'': ''3000x2000'',
},
{
''title'': ''Processor'',
''content'': ''11th Gen Intel® Core™ i7-1165G7 Processor'',
},
{
''title'': ''CPU Cores'',
''content'': ''4'',
},
{
''title'': ''Launch Time'',
''content'': ''January 2021'',
}
]
在 HomePage.ets 文件中创建商品列表页签相关的组件,添加 GoodsHome 代码如下:
@Component
struct GoodsHome {
private goodsItems: GoodsData[]
build() {
Column() {
Tabs() {
TabContent() {
GoodsList({ goodsItems: this.goodsItems });
}
.tabBar("Top Sellers")
.backgroundColor(Color.White)
TabContent() {
GoodsList({ goodsItems: this.goodsItems });
}
.tabBar("Recommended")
.backgroundColor(Color.White)
TabContent() {
GoodsList({ goodsItems: this.goodsItems });
}
.tabBar("Lifestyle")
.backgroundColor(Color.White)
TabContent() {
GoodsList({ goodsItems: this.goodsItems });
}
.tabBar("Deals")
.backgroundColor(Color.White)
}
.barWidth(500)
.barHeight(25)
.scrollable(true)
.barMode(BarMode.Scrollable)
.backgroundColor(''#007DFF'')
.height(700)
}
.alignItems(HorizontalAlign.Start)
.width(''100%'')
}
}
在 GoodsHome 中使用 Tabs 组件,在 Tabs 组件中设置 4 个 TabContent,给每个 TabContent 设置 tabBar 属性,并设置 TabContent 容器中的内容 GoodsList 组件,GoodsList 组件代码如下:
@Component
struct GoodsList {
private goodsItems: GoodsData[]
build() {
Column() {
List() {
ForEach(this.goodsItems, item => {
ListItem() {
GoodsListItem({ goodsItem: item })
}
}, item => item.id.toString())
}
.height(''100%'')
.width(''100%'')
.align(Alignment.Top)
.margin({top: 5})
}
}
}
在 GoodsList 组件中遍历商品数据集合,ListItem 组件中设置组件内容,并使用 Navigator 组件给每个 Item 设置顶级跳转路由,GoodsListItem 组件代码如下:
@Component
struct GoodsListItem {
private goodsItem: GoodsData
build() {
Navigator({ target: ''pages/ShoppingDetail'' }) {
Row() {
Column(){
Text(this.goodsItem.title)
.fontSize(14)
Text(this.goodsItem.content )
.fontSize(10)
Text(''¥'' + this.goodsItem.price)
.fontSize(14)
.fontColor(Color.Red)
}
.height(100)
.width(''50%'')
.margin({left: 20})
.alignItems(HorizontalAlign.Start)
Image(this.goodsItem.imgSrc)
.objectFit(ImageFit.ScaleDown)
.height(100)
.width(''40%'')
.renderMode(ImageRenderMode.Original)
.margin({right: 10,left:10})
}
.backgroundColor(Color.White)
}
.params({ goodsData: this.goodsItem })
.margin({ right: 5})
}
在 HomePage.ets 中创建文件入口组件(Index)以及底部页签导航组件(HomeBottom),导入需要使用到的数据实体类以及需要使用的方法和组件,每个 page 文件都必须包含一个入口组件,使用 @Entry 修饰,HomePage 文件中的入口组件(Index)代码如下:
import {GoodsData} from ''../model/GoodsData''
import {initializeOnStartup,getIconPath,getIconPathSelect} from ''../model/GoodsDataModels''
import {ShoppingCart} from ''./ShoppingCart''
import {MyInfo} from ''./MyPage''
@Entry
@Component
struct Index {
@Provide currentPage: number = 1
private goodsItems: GoodsData[] = initializeOnStartup()
build() {
Column() {
Scroll() {
Column() {
if (this.currentPage == 1) {
GoodsHome({ goodsItems: this.goodsItems })
} else if (this.currentPage == 2) {
//购物车列表
ShoppingCart()
} else {
//我的
MyInfo()
}
}
.height(700)
}
.flexGrow(1)
HomeBottom()
}
.backgroundColor("white")
}
}
从入口组件的代码中可以看出,我们定义了一个全局变量 currentPage ,并且使用 @provide 修饰,在其子组件 (HomeBottom) 中使用 @Consume 修饰。当子组件 currentPage 发生变化的时候,父组件 currentPage 也会发生变化,会重新加载页面,显示不同的页签。在入口组件中,通过 initializeOnStartup 获取商品列表数据(goodsItems)并传入 GoodsHome 组件中,HomeBottom 组件代码如下:
@Component
struct HomeBottom {
@Consume currentPage: number
private iconPathTmp: string[] = getIconPath()
private iconPathSelectsTmp: string[] = getIconPathSelect()
@State iconPath: string[] = getIconPath()
build() {
Row(){
List() {
ForEach(this.iconPath, item => {
ListItem() {
Image($rawfile(item))
.objectFit(ImageFit.Cover)
.height(30)
.width(30)
.renderMode(ImageRenderMode.Original)
.onClick(()=>{
if(item==this.iconPath[0]){
this.iconPath[0]=this.iconPathTmp[0]
this.iconPath[1]=this.iconPathTmp[1]
this.iconPath[2]=this.iconPathTmp[2]
this.currentPage=1
}
if(item==this.iconPath[1]){
this.iconPath[0]=this.iconPathSelectsTmp[0]
this.iconPath[1]=this.iconPathSelectsTmp[1]
this.iconPath[2]=this.iconPathTmp[2]
this.currentPage=2
}
if(item==this.iconPath[2]){
this.iconPath[0]=this.iconPathSelectsTmp[0]
this.iconPath[1]=this.iconPathTmp[1]
this.iconPath[2]=this.iconPathSelectsTmp[2]
this.currentPage=3
}
})
}
.width(120)
.height(40)
}, item => item)
}
.margin({left:10})
.align(Alignment.BottomStart)
.listDirection(Axis.Horizontal)
}
.alignItems(VerticalAlign.Bottom)
.height(30)
.margin({top:10 ,bottom:10})
}
}
底部组件是由一个横向的图片列表组成,iconPath 是底部初始状态下的 3 张图片路径数组。遍历 iconPath 数组,使用 Image 组件设置图片路径并添加到 List 中,给每个 Image 组件设置点击事件,点击更换底部 3 张图片。在 HomeBottom 中,iconPath 使用的是 @State 修饰,当 iconPath 数组内容变化时,页面组件有使用到的地方都会随之发生变化。
在 MyPage.ets 文件中新建 MyTransList 组件和 MoreGrid 组件,MyTransList 组件代码如下:
@Component
struct MyTransList {
private imageItems: ImageItem[] = getTrans()
build() {
Column() {
Text(''My Transaction'')
.fontSize(20)
.margin({ left: 10 })
.width(''100%'')
.height(30)
Row() {
List() {
ForEach(this.imageItems, item => {
ListItem() {
DataItem({ imageItem: item })
}
}, item => item.id.toString())
}
.height(70)
.width(''100%'')
.align(Alignment.Top)
.margin({ top: 5})
.listDirection(Axis.Horizontal)
}
}
.height(120)
}
}
MoreGrid 组件代码如下:
@Component
struct MoreGrid {
private gridRowTemplate: string = ''''
private imageItems: ImageItem[] = getMore()
private heightValue: number
aboutToAppear() {
var rows = Math.round(this.imageItems.length / 3);
this.gridRowTemplate = ''1fr ''.repeat(rows);
this.heightValue = rows * 75 ;
}
build() {
Column() {
Text(''More'')
.fontSize(20)
.margin({ left: 10 })
.width(''100%'')
.height(30)
Scroll() {
Grid() {
ForEach(this.imageItems, (item: ImageItem) => {
GridItem() {
DataItem({ imageItem: item })
}
}, (item: ImageItem) => item.id.toString())
}
.rowsTemplate(this.gridRowTemplate)
.columnsTemplate(''1fr 1fr 1fr'')
.columnsGap(8)
.rowsGap(8)
.height(this.heightValue)
}
.padding({ left: 16, right: 16 })
}
.height(400)
}
}
在 MyTransList 和 MoreGrid 组件中都包含子组件 DataItem,为避免的重复代码,可以把多次要用到的结构体组件化,这里的结构体就是图片加上文本的上下结构体,DataItem 组件内容如下:
@Component
struct MenuItem {
private menu: Menu
build() {
Column() {
Text(this.menu.title)
.fontSize(15)
Text(this.menu.num+'''')
.fontSize(13)
}
.height(50)
.width(80)
.margin({left: 8,right:8})
.alignItems(HorizontalAlign.Start)
.backgroundColor(Color.White)
}
}
实现购物车页签
主界面购物车页签主要由下面三部分组成:
- 顶部的 Text 组件。
- 中间的 List 组件,其中 List 组件的 item 是一个水平的布局内包含一个 toggle 组件,一个 Image 组件和一个垂直布局,其 item 中的垂直布局是由 2 个 Text 组件组成。
- 底部一个水平布局包含两个 Text 组件。
构建一个购物车页签,给商品列表的每个商品设置一个单选框,可以选中与取消选中,底部 Total 值也会随之增加或减少,点击 Check Out 时会触发弹窗。下面我们来完成 ShoppingCart 页签。
在 pages 目录下面新建一个 Page ,命名为 ShoppingCart.。在 ShoppingCart.ets 文件中添加入口组件 (ShoppingCart),并导入需要使用到的数据实体类、方法和组件。ShoppingCart 组件代码如下:
@Entry
@Component
export struct ShoppingCart {
@Provide totalPrice : number =0
private goodsItems: GoodsData[] = initializeOnStartup()
build() {
Column() {
Column() {
Text(''ShoppingCart'')
.fontColor(Color.Black)
.fontSize(25)
.margin({ left: 60,right:60 })
.align(Alignment.Center)
}
.backgroundColor(''#FF00BFFF'')
.width(''100%'')
.height(30)
ShopCartList({ goodsItems: this.goodsItems });
ShopCartBottom()
}
.alignItems(HorizontalAlign.Start)
}
}
新建 ShopCartList 组件用于存放购物车商品列表,ShopCartList 组件代码如下
@Component
struct ShopCartList {
private goodsItems: GoodsData[]
build() {
Column() {
List() {
ForEach(this.goodsItems, item => {
ListItem() {
ShopCartListItem({ goodsItem: item })
}
}, item => item.id.toString())
}
.height(''100%'')
.width(''100%'')
.align(Alignment.Top)
.margin({top: 5})
}
.height(570)
}
}
ShopCartListItem 组件代码如下:
@Component
struct ShopCartListItem {
@Consume totalPrice: number
private goodsItem: GoodsData
build() {
Row() {
Toggle({type: ToggleType.Checkbox})
.width(10)
.height(10)
.onChange((isOn:boolean) => {
if(isOn){
this.totalPrice +=parseInt(this.goodsItem.price+'''',0)
}else{
this.totalPrice -= parseInt(this.goodsItem.price+'''',0)
}
})
Image(this.goodsItem.imgSrc)
.objectFit(ImageFit.ScaleDown)
.height(100)
.width(100)
.renderMode(ImageRenderMode.Original)
Column() {
Text(this.goodsItem.title)
.fontSize(14)
Text(''¥'' + this.goodsItem.price)
.fontSize(14)
.fontColor(Color.Red)
}
}
.height(100)
.width(180)
.margin({left: 20})
.alignItems(VerticalAlign.Center)
.backgroundColor(Color.White)
}
}
在 ShopCartListItem 中使用 Toggle 的单选框类型来实现每个 item 的选择和取消选择,在 Toggle 的 onChage 事件中来改变 totalPrice 的数值。
新建 ShopCartBottom 组件,ShopCartBottom 组件代码如下:
@Component
struct ShopCartBottom {
@Consume totalPrice: number
build() {
Row() {
Text(''Total: ¥''+this.totalPrice)
.fontColor(Color.Red)
.fontSize(18)
.margin({left:20})
.width(150)
Text(''Check Out'')
.fontColor(Color.Black)
.fontSize(18)
.margin({right:20,left:100})
.onClick(()=>{
prompt.showToast({
message: ''Checking Out'',
duration: 10,
bottom:100
})
})
}
.height(30)
.width(''100%'')
.backgroundColor(''#FF7FFFD4'')
.alignItems(VerticalAlign.Bottom)
}
}
实现我的页签
我的页签主要由下面四部分组成:
- 顶部的水平布局。
- 顶部下面的文本加数字的水平 List。
- My Transactio 模块,图片加文本的水平 List。
- More 模块,图片加文本的 Grid。
构建主页我的页签,主要可以划分成下面几步:
- 在 pages 目录下面新建一个 Page 命名为 MyPage
- 在 MyPage.ets 文件中添加入口组件(MyInfo)
MyInfo 组件内容如下:
import {getMenu,getTrans,getMore} from ''../model/GoodsDataModels''
import {Menu, ImageItem} from ''../model/Menu''
@Entry
@Component
export struct MyInfo {
build() {
Column() {
Row(){
Image($rawfile(''nav/icon-user.png''))
.margin({left:20})
.objectFit(ImageFit.Cover)
.height(50)
.width(50)
.renderMode(ImageRenderMode.Original)
.margin({left:40,right:40})
Column(){
Text(''John Doe'')
.fontSize(15)
Text(''Member Name : John Doe >'')
}
.height(60)
.margin({left:40,top:10})
.alignItems(HorizontalAlign.Start)
}
TopList()
MyTransList()
MoreGrid()
}
.alignItems(HorizontalAlign.Start)
.width(''100%'')
.flexGrow(1)
}
}
入口组件中还包含 TopList,MyTransList 和 MoreGrid 三个子组件。代码如下:
@Component
struct TopList {
private menus: Menu[] = getMenu()
build() {
Row() {
List() {
ForEach(this.menus, item => {
ListItem() {
MenuItem({ menu: item })
}
}, item => item.id.toString())
}
.height(''100%'')
.width(''100%'')
.margin({top: 5})
.edgeEffect(EdgeEffect.None)
.listDirection(Axis.Horizontal)
}
.width(''100%'')
.height(50)
}
}
@Component
struct MyTransList {
private imageItems: ImageItem[] = getTrans()
build() {
Column() {
Text(''My Transaction'')
.fontSize(20)
.margin({ left: 10 })
.width(''100%'')
.height(30)
Row() {
List() {
ForEach(this.imageItems, item => {
ListItem() {
DataItem({ imageItem: item })
}
}, item => item.id.toString())
}
.height(70)
.width(''100%'')
.align(Alignment.Top)
.margin({ top: 5})
.listDirection(Axis.Horizontal)
}
}
.height(120)
}
}
@Component
struct MoreGrid {
private gridRowTemplate: string = ''''
private imageItems: ImageItem[] = getMore()
private heightValue: number
aboutToAppear() {
var rows = Math.round(this.imageItems.length / 3);
this.gridRowTemplate = ''1fr ''.repeat(rows);
this.heightValue = rows * 75 ;
}
build() {
Column() {
Text(''More'')
.fontSize(20)
.margin({ left: 10 })
.width(''100%'')
.height(30)
Scroll() {
Grid() {
ForEach(this.imageItems, (item: ImageItem) => {
GridItem() {
DataItem({ imageItem: item })
}
}, (item: ImageItem) => item.id.toString())
}
.rowsTemplate(this.gridRowTemplate)
.columnsTemplate(''1fr 1fr 1fr'')
.columnsGap(8)
.rowsGap(8)
.height(this.heightValue)
}
.padding({ left: 16, right: 16 })
}
.height(400)
}
}
实现商品详情页面
商品详情页面主要由下面五部分组成:
- 顶部的返回栏。
- Swiper 组件。
- 中间多个 Text 组件组成的布局。
- 参数列表。
- 底部的 Buy。
把上面每一部分都封装成一个组件,然后再放到入口组件内,当点击顶部返回图标时返回到主页面的商品列表页签,点击底部 Buy 时,会触发进度条弹窗。
在 pages 目录下面新建一个 Page, 命名为 ShoppingDetail。在 ShoppingDetail.ets 文件中创建入口组件,组件内容如下:
import router from ''@system.router'';
import {ArsData} from ''../model/ArsData''
import {getArs,getDetailImages} from ''../model/GoodsDataModels''
import prompt from ''@system.prompt'';
@Entry
@Component
struct ShoppingDetail {
private arsItems: ArsData[] = getArs()
private detailImages: string[] = getDetailImages()
build() {
Column() {
DetailTop()
Scroll() {
Column() {
SwiperTop()
DetailText()
DetailArsList({ arsItems: this.arsItems })
Image($rawfile(''computer/computer1.png''))
.height(220)
.width(''100%'')
.margin({top:30})
Image($rawfile(''computer/computer2.png''))
.height(220)
.width(''100%'')
.margin({top:30})
Image($rawfile(''computer/computer3.png''))
.height(220)
.width(''100%'')
.margin({top:30})
Image($rawfile(''computer/computer4.png''))
.height(220)
.width(''100%'')
.margin({top:30})
Image($rawfile(''computer/computer5.png''))
.height(220)
.width(''100%'')
.margin({top:30})
Image($rawfile(''computer/computer6.png''))
.height(220)
.width(''100%'')
.margin({top:30})
}
.width(''100%'')
.flexGrow(1)
}
.scrollable(ScrollDirection.Vertical)
DetailBottom()
}
.height(630)
}
}
顶部 DetailTop 组件代码如下:
@Component
struct DetailTop{
build(){
Column(){
Row(){
Image($rawfile(''detail/icon-return.png''))
.height(20)
.width(20)
.margin({ left: 20, right: 250 })
.onClick(() => {
router.push({
uri: "pages/HomePage"
})
})
}
.width(''100%'')
.height(25)
.backgroundColor(''#FF87CEEB'')
}
.width(''100%'')
.height(30)
}
}
SwiperTop 组件代码如下:
@Component
struct SwiperTop{
build() {
Column() {
Swiper() {
Image($rawfile(''computer/computer1.png''))
.height(220)
.width(''100%'')
Image($rawfile(''computer/computer2.png''))
.height(220)
.width(''100%'')
Image($rawfile(''computer/computer3.png''))
.height(220)
.width(''100%'')
Image($rawfile(''computer/computer4.png''))
.height(220)
.width(''100%'')
Image($rawfile(''computer/computer5.png''))
.height(220)
.width(''100%'')
Image($rawfile(''computer/computer6.png''))
.height(220)
.width(''100%'')
}
.index(0)
.autoPlay(true)
.interval(3000)
.indicator(true)
.loop(true)
.height(250)
.width(''100%'')
}
.height(250)
.width(''100%'')
}
}
DetailText 组件代码如下:
@Component
struct DetailText{
build() {
Column() {
Row(){
Image($rawfile(''computer/icon-promotion.png''))
.height(30)
.width(30)
.margin({left:10})
Text(''Special Offer: ¥9999'')
.fontColor(Color.White)
.fontSize(20)
.margin({left:10})
}
.width(''100%'')
.height(35)
.backgroundColor(Color.Red)
Column(){
Text(''New Arrival: HUAWEI MateBook X Pro 2021'')
.fontSize(15)
.margin({left:10})
.alignSelf(ItemAlign.Start)
Text(''13.9-Inch, 11th Gen Intel® Core™ i7, 16 GB of Memory, 512 GB of Storage, Ultra-slim Business Laptop, 3K FullView Display, Multi-screen Collaboration, Emerald Green'')
.fontSize(10)
.margin({left:10})
Row(){
Image($rawfile(''nav/icon-buy.png''))
.height(15)
.width(15)
.margin({left:10})
//TODO 暂不支持跑马灯组件,用Text代替
Text(''Limited offer'')
.fontSize(10)
.fontColor(Color.Red)
.margin({left:100})
}
.backgroundColor(Color.Pink)
.width(''100%'')
.height(25)
.margin({top:10})
Text('' Shipment: 2-day shipping'')
.fontSize(13)
.fontColor(Color.Red)
.margin({left:10,top:5})
.alignSelf(ItemAlign.Start)
Text('' Ship To: Hubei,Wuhan,China'')
.fontSize(13)
.fontColor(Color.Red)
.margin({left:10,top:5})
.alignSelf(ItemAlign.Start)
.onClick(()=>{
prompt.showDialog({title:''select address'',})
})
Text(''Guarantee: Genuine guaranteed'')
.fontSize(13)
.margin({left:10,top:5})
.alignSelf(ItemAlign.Start)
}
.height(150)
.width(''100%'')
}
.height(160)
.width(''100%'')
}
}
DetailArsList 组件代码如下:
@Component
struct DetailArsList{
private arsItems: ArsData[]
build() {
Scroll() {
Column() {
List() {
ForEach(this.arsItems, item => {
ListItem() {
ArsListItem({ arsItem: item })
}
}, item => item.id.toString())
}
.height(''100%'')
.width(''100%'')
.margin({ top: 5 })
.listDirection(Axis.Vertical)
}
.height(200)
}
}
}
ArsListItem 组件代码如下:
@Component
struct ArsListItem {
private arsItem: ArsData
build() {
Row() {
Text(this.arsItem.title+" :")
.fontSize(11)
.margin({left:20})
.flexGrow(1)
Text( this.arsItem.content)
.fontSize(11)
.margin({right:20})
}
.height(14)
.width(''100%'')
.backgroundColor(Color.White)
}
}
DetailBottom 组件代码如下:
@Component
struct DetailBottom{
@Provide
private value : number=1
dialogController : CustomDialogController = new CustomDialogController({
builder: DialogExample({action: this.onAccept}),
cancel: this.existApp,
autoCancel: true
});
onAccept() {
}
existApp() {
}
build(){
Column(){
Text(''Buy'')
.width(40)
.height(25)
.fontSize(20)
.fontColor(Color.White)
.onClick(()=>{
this.value=1
this.dialogController.open()
})
}
.alignItems(HorizontalAlign.Center)
.backgroundColor(Color.Red)
.width(''100%'')
.height(40)
}
}
DialogExample 自定义弹窗组件代码如下:
@CustomDialog
struct DialogExample {
@Consume
private value : number
controller: CustomDialogController;
action: () => void;
build() {
Column() {
Progress({value: this.value++ >=100?100:this.value, total: 100, style: ProgressStyle.Eclipse})
.height(50)
.width(100)
.margin({top:5})
}
.height(60)
.width(100)
}
}
添加资源文件
程序中所用到的资源文件都放置到 resources\rawfile 目录下。
删除 index.ets
因为程序的入口文件已经改为了 HomePage.ets 文件,因此需要删除 Index.ets 文件。
HomePage.ets 文件重新命名
把 HomePage.ets 文件重新命名为 Index.ets 文件。
程序运行效果
完整演示视频见 B 站:https://www.bilibili.com/video/BV1NG4y1o7rv/
源码
见 https://github.com/waylau/harmonyos-tutorial 中的 “ArkUIShopping”
参考引用
- 《跟老卫学 HarmonyOS 开发》 开源免费教程,https://github.com/waylau/harmonyos-tutorial
- 《鸿蒙 HarmonyOS 应用开发从入门到精通战》(柳伟卫著,北京大学出版社)https://item.jd.com/13696724.html、http://product.dangdang.com/29386650.html
- 玩转 HarmonyOS 3 必装 DevEco Studio 3,注意避弹 https://developer.huawei.com/consumer/cn/forum/topic/0202103558349879153?fid=0101610563345550409
- https://developer.huawei.com/consumer/cn/codelabsPortal/carddetails/HarmonyOS-ShoppingEts
#HarmonyOS体验官#OpenHarmony和HarmonyOS的差异
OpenHarmony和HarmonyOS的差异
OpenHarmony
OpenHarmony是由开放原子开源基金会(OpenAtom Foundation)孵化及运营的开源项目,目标是面向全场景、全连接、全智能时代,基于开源的方式,搭建一个智能终端设备操作系统的框架和平台,促进万物互联产业的繁荣发展。
- 从Open就可以看出,他是一个开源项目,这点区别于HarmonyOS。
- OpenHarmony是由开放原子开源基金会孵化及运营的。
- OpenHarmony相当于Android的AOSP(Android Open Source Project),所以使用者只要遵循开源协议和法律就可以
- OpenHarmony用户应用程序基于全新设计的OpenHarmony API/SDK开发,可以运行在基于 OpenHarmony开源项目开发的系统上,并可以在多终端之间无缝流转。
- OpenHarmony程序框架仅支持OpenHarmony用户应用程序运行,不支持安卓/IOS等基于其他OS API/SDK开发的用户应用程序运行。
可以说OpenHarmony是“鸿蒙操作系统”的底座。是一座毛胚房。 HarmonyOS就是经过装修的精装房。
HarmonyOS
HarmonyOS作为新一代的智能终端操作系统,为不同设备的智能化、互联与协同提供了统一的语言,带来简洁、流畅、连续、安全可靠的全场景交互体验。
- HarmonyOS 是华为基于开源项目OpenHarmony 开发的面向多种全场景智能设备的商用版本。
- 为保护华为现有手机和平板用户的数字资产,在遵循AOSP的开源许可的基础上HarmonyOS 2实现了现有Android生态应用在部分搭载该系统设备上的运行。
这里需要注意:
- 一是HarmonyOS不是开源项目,而是商用版本。
- 二是HarmonyOS手机和平板之所以能运行Android,是因为HarmonyOS 实现了现有Android生态应用(即AOSP)的运行。
OpenHarmony与 HarmonyOS的差异(开发角度)
1.语言支持
OpenHarmony推荐使用JS,ArkTS语言开发应用不支持 Java 来开发应用,
2.SDK 的不同
应用开发工具都是统一使用华为的 DevEco Studio,但是使用的 sdk 不同。
3.运行调测方式不同
HarmonyOS 支持 previewer 预览、模拟器运行、真机运行三种方式;OpenHarmony 支持 previewer 预览、真机运行。
4.签名方式不同
OpenHarmony 的签名方式:
https://gitee.com/openharmony/docs/tree/master/zh-cn/application-dev/quick-start
HarmonyOS 的签名方式:
使用真机进行调试-调试HarmonyOS应用/服务-应用/服务调试-HUAWEI DevEco Studio使用指南-工具-HarmonyOS应用开发
#HarmonyOS小课堂# 速览 课程精华第一期:运行Hello World
#HarmonyOS小课堂# 从“0”开始走进HarmonyOS应用开发
了解3.1版本 #HarmonyOS第一课# 第一期精彩内容
下载配置DevEco Studio,运行您的第一个HarmonyOS应用!
继续了解3.1版本 #HarmonyOS第一课# 第二期精彩内容
继续了解3.1版本 #HarmonyOS第一课# 第三期精彩内容
点击学习#HarmonyOS第一课# 完整版课程
与华为开发者联盟学堂携手筑建鸿蒙世界,从“0”开始走进HarmonyOS应用开发
#HarmonyOS小课堂# 速览 课程精华第三期:ArkTS基础知识
#HarmonyOS小课堂# 从“0”开始走进HarmonyOS应用开发
了解3.1版本 #HarmonyOS第一课# 第三期精彩内容
一图速解HarmonyOS应用开发语言ArkTS
回顾了解3.1版本 #HarmonyOS第一课# 第一期精彩内容
回顾了解3.1版本 #HarmonyOS第一课# 第二期精彩内容
继续了解3.1版本 #HarmonyOS第一课# 第四期上精彩内容
点击学习#HarmonyOS第一课# 完整版课程
与华为开发者联盟学堂携手筑建鸿蒙世界,从“0”开始走进HarmonyOS应用开发
今天关于harmonyos是安卓系统吗详情和harmonyos是不是安卓的分享就到这里,希望大家有所收获,若想了解更多关于#HarmonyOS 体验官【挑战赛第一期】用 HarmonyOS ArkUI 来开发一个购物应用程序、#HarmonyOS体验官#OpenHarmony和HarmonyOS的差异、#HarmonyOS小课堂# 速览
本文标签: