赞
踩
OpenHarmony ArkUI框架提供了丰富的动画组件和接口,开发者可以根据实际场景和开发需求,选用丰富的动画组件和接口来实现不同的动画效果。
本文中,我们会构建一个简易的购物应用。应用包含两级页面,分别是主页(“商品浏览”页签、“购物车”页签、“我的”页签)和商品详情页面。效果如下图所示:
本篇Codelab只对核心代码进行讲解,首先来介绍下整个工程的代码结构:
model:存放封装好的数据实体。
pages:存放页面。
resources :存放工程使用到的资源文件。
config.json:配置文件。
完成本篇Codelab我们首先要完成开发环境的搭建,本示例以Hi3516DV300开发板为例,参照以下步骤进行:
获取OpenHarmony系统版本:标准系统解决方案(二进制)
以3.0版本为例:
搭建烧录环境
搭建开发环境
在本节中,我们将完成商品列表页签的设计,效果图如下:
从效果图可以看出,商品列表页签主要由三个部分组成:
实现步骤如下:
在pages目录下面新建一个ETS Page,命名为HomePage.ets,在config.json文件的pages属性中会自动添加“pages/HomePage”页面路由。
说明:
- 页面文件名不能使用组件名称,比如:Text.ets、Button.ets等。
- 每个页面文件中必须包含入口组件。
新建与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;
- }
- }
一个文件中可以包含多个class ,Menu.ets中就包含了Menu类和ImageItem类,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;
- }
- //获取MyTrans数据列表
- export function getTrans(): Array<ImageItem> {
- let ImageItemArray: Array<ImageItem> = []
- MyTrans.forEach(item => {
- ImageItemArray.push(new ImageItem(item.title,item.imageSrc));
- })
- return ImageItemArray;
- }
- //获取More数据列表
- 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;
- }
- //数据集合部分
- ...
在HomePage.ets文件中创建商品列表页签相关的组件,其中GoodsHome效果图如下:
代码如下:
- @Component
- @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(540)
- .barHeight(50)
- .scrollable(true)
- .barMode(BarMode.Scrollable)
- .backgroundColor('#007DFF')
- .height('100%')
- }
- .alignItems(HorizontalAlign.Start)
- }
- }
在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(18)
- Text(this.goodsItem.content)
- .fontSize(14)
- Text('¥' + this.goodsItem.price)
- .fontSize(18)
- .fontColor(Color.Red)
- }
- .height(130)
- .width('60%')
- .margin({ left: 20 })
- .alignItems(HorizontalAlign.Start)
-
- Image(this.goodsItem.imgSrc)
- .objectFit(ImageFit.ScaleDown)
- .height(130)
- .width('30%')
- .renderMode(ImageRenderMode.Original)
- .margin({ right: 10, left: 10 })
-
- }
- .backgroundColor(Color.White)
-
- }
- .params({ goodsData: this.goodsItem })
- .margin({ right: 5 })
- }
- }
在HomePage.ets中创建文件入口组件(Index)以及底部页签导航组件(Navigation),导入需要使用到的数据实体类以及需要使用的方法和组件,每个page文件都必须包含一个入口组件,使用@Entry修饰,HomePage文件中的入口组件(Index)代码如下:
- import { GoodsData, IconImage } from '../model/GoodsData'
- import { initializeOnStartup, getIconPath, getIconPathSelect } from '../model/GoodsDataModels'
- import { ShoppingCart } from './ShoppingCartPage.ets'
- import { MyInfo } from './MyPage.ets'
- import router from '@system.router';
-
- @Entry
- @Component
- struct Index {
- @Provide currentPage: number = 1
- private goodsItems: GoodsData[] = initializeOnStartup()
- @State Build: Array<Object> = [
- {
- icon: $r('app.media.icon_home'),
- icon_after: $r('app.media.icon_buy1'),
- text: '首页',
- num: 0
- },
- {
- icon: $r('app.media.icon_shopping_cart'),
- icon_after: $r('app.media.icon_shopping_cart_select'),
- text: '购物车',
- num: 1
- },
- {
- icon: $r('app.media.icon_my'),
- icon_after: $r('app.media.icon_my_select'),
- text: '我的',
- num: 2
- }
- ]
-
- @Builder NavigationToolbar() {
- Flex({direction:FlexDirection.Row,wrap:FlexWrap.NoWrap,justifyContent:FlexAlign.SpaceAround}) {
- ForEach(this.Build, item => {
- Column() {
- Image(this.currentPage == item.num ? item.icon_after : item.icon)
- .width(25)
- .height(25)
- Text(item.text)
- .fontColor(this.currentPage == item.num ? "#ff7500" : "#000000")
- }
- .onClick(() => {
- this.currentPage = item.num
- })
- })
- }
- }
-
- build() {
- Column() {
- Navigation() {
- Flex() {
- if (this.currentPage == 0) {
- GoodsHome({ goodsItems: this.goodsItems })
- }
- if (this.currentPage == 1) {
- ShoppingCart() //购物车列表
- }
- if (this.currentPage == 2) {
- MyInfo() //我的
- }
- }
- .width('100%')
- .height('100%')
- }
- .toolBar(this.NavigationToolbar)
- .title("购物车")
- .hideTitleBar(this.currentPage == 1 ? false : true)
- .hideBackButton(true)
- }
- }
- }
从入口组件的代码中可以看出,我们定义了一个全局变量currentPage ,当currentPage发生变化的时候,会显示不同的页签。在入口组件中,通initializeOnStartup获取商品列表数据(goodsItems)并传入GoodsHome组件中。效果图如下:
从上面效果图可以看出,主界面购物车页签主要由下面三部分组成:
在本任务中我们主要是构建一个购物车页签,给商品列表的每个商品设置一个单选框,可以选中与取消选中,底部Total值也会随之增加或减少,点击Check Out时会触发弹窗。下面我们来完成ShoppingCart页签。
在pages目录下面新建一个ETS Page ,命名为ShoppingCart.ets,config.json文件pages属性中也会自动添加“pages/ShoppingCart”页面路由。
在ShoppingCartPage.ets文件中添加入口组件(ShoppingCart),并导入需要使用到的数据实体类、方法和组件。ShoppingCart组件代码如下:
- import {GoodsData} from '../model/GoodsData'
- import {initializeOnStartup} from '../model/GoodsDataModels'
- import prompt from '@system.prompt';
-
- @Entry
- @Component
- export struct ShoppingCart {
- @Provide totalPrice: number = 0
- private goodsItems: GoodsData[] = initializeOnStartup()
-
- build() {
- Column() {
- ShopCartList({ goodsItems: this.goodsItems });
- ShopCartBottom()
- }
- .height('100%')
- .width('100%')
- .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('90%')
- }
- }
在ShopCartListItem中使用Toggle的单选框类型来实现每个item的选择和取消选择,在Toggle的onChage事件中来改变totalPrice的数值。ShopCartListItem组件效果图如下:
代码如下:
- @Component
- struct ShopCartListItem {
- @Consume totalPrice: number
- private goodsItem: GoodsData
-
- build() {
- Row() {
- Toggle({ type: ToggleType.Checkbox })
- .width(13)
- .height(13)
- .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(130)
- .width(100)
- .renderMode(ImageRenderMode.Original)
- Column() {
- Text(this.goodsItem.title)
- .fontSize(18)
- Text('¥' + this.goodsItem.price)
- .fontSize(18)
- .fontColor(Color.Red)
- }
- .margin({left:40})
- }
- .height(100)
- .width('100%')
- .margin({ left: 20 })
- .alignItems(VerticalAlign.Center)
- .backgroundColor(Color.White)
- }
- }
新建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: 180 })
- .onClick(() => {
- prompt.showToast({
- message: 'Checking Out',
- duration: 10,
- bottom: 100
- })
- })
- }
- .height(30)
- .width('100%')
- .backgroundColor('#FF7FFFD4')
- .alignItems(VerticalAlign.Bottom)
- }
- }
从上面效果图可以看出,主界面我的页签主要由下面四部分组成:
在本任务中,我们构建主页我的页签,主要可以划分成下面几步:
在pages目录下面新建一个ETS Page 命名为MyPage.ets,在config.json文件pages属性中也会自动添加“pages/MyPage”页面路由。
在MyPage.ets文件中添加入口组件(MyInfo),组件内容如下:
- import {getMenu,getTrans,getMore} from '../model/GoodsDataModels'
- import {Menu, ImageItem} from '../model/Menu'
- @Entry
- @Component
- export struct MyInfo {
- build() {
- Column() {
- Row() {
- Image($r('app.media.icon_user'))
- .objectFit(ImageFit.Contain)
- .height(50)
- .width(50)
- .margin({left:10})
- .renderMode(ImageRenderMode.Original)
- Column() {
- Text('John Doe')
- .fontSize(15)
- Text('Member Name : John Doe >')
- .fontSize(15)
- }
- .height(60)
- .margin({ left: 20, top: 10 })
- .alignItems(HorizontalAlign.Start)
- }
-
- TopList()
- MyTransList()
- MoreGrid()
-
- }
- .alignItems(HorizontalAlign.Start)
- .width('100%')
- .height('100%')
- .flexGrow(1)
- }
- }
入口组件中还包含TopList,MyTransList和MoreGrid三个子组件。
在MyPage.ets文件中新建TopList组件,效果图如下:
代码如下:
- @Component
- struct TopList {
- private menus: Menu1[] = getMenu()
-
- build() {
- Row() {
- List() {
- ForEach(this.menus, item => {
- ListItem() {
- MenuItem({ menu: item })
- }
- }, item => item.id.toString())
- }
- .height('100%')
- .width('100%')
- .margin({ top: 5,left: 10})
- .edgeEffect(EdgeEffect.None)
- .listDirection(Axis.Horizontal)
- }
- .width('100%')
- .height(50)
- }
- }
getMenu()方法在上文中已有定义,是获取菜单列表的方法,TopList的子组件MenuItem内容如下:
- @Component
- struct MenuItem {
- private menu: Menu1
-
- build() {
- Column() {
- Text(this.menu.title)
- .fontSize(15)
- Text(this.menu.num + '')
- .fontSize(13)
-
- }
- .height(50)
- .width(100)
- .margin({ left: 8, right: 8 })
- .alignItems(HorizontalAlign.Start)
- .backgroundColor(Color.White)
- }
- }
在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%')
- .edgeEffect(EdgeEffect.None)
- .margin({ top: 5 })
- .padding({ left: 16, right: 16 })
- .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 DataItem {
- private imageItem: ImageItem
-
- build() {
- Column() {
- Image(this.imageItem.imageSrc)
- .objectFit(ImageFit.Contain)
- .height(50)
- .width(50)
- .renderMode(ImageRenderMode.Original)
- Text(this.imageItem.title)
- .fontSize(15)
-
- }
- .height(70)
- .width(150)
- .margin({ left: 10, right: 10 })
- .backgroundColor(Color.White)
- }
- }
从上面效果图可以看出,商品详情页面主要由下面五部分组成:
在本任务中,把上面每一部分都封装成一个组件,然后再放到入口组件内,当点击顶部返回图标时返回到主页面的商品列表页签,点击底部Buy时,会触发进度条弹窗
在pages目录下面新建一个ETS Page, 命名为ShoppingDetail.ets,config.json文件pages属性中也会自动添加“pages/ShoppingDetail”页面路由。
在ShoppingDetail.ets文件中创建入口组件,组件内容如下:
- @Entry
- @Component
- struct ShoppingDetail {
- private arsItems: ArsData[] = getArs()
-
- build() {
- Column() {
- DetailTop()
- Scroll() {
- Column() {
- SwiperTop()
- DetailText()
- DetailArsList({ arsItems: this.arsItems })
- Image($r('app.media.computer1'))
- .height(220)
- .width('100%')
- .margin({ top: 30 })
- Image($r('app.media.computer2'))
- .height(220)
- .width('100%')
- .margin({ top: 30 })
- Image($r('app.media.computer3'))
- .height(220)
- .width('100%')
- .margin({ top: 30 })
- Image($r('app.media.computer4'))
- .height(220)
- .width('100%')
- .margin({ top: 30 })
- Image($r('app.media.computer5'))
- .height(220)
- .width('100%')
- .margin({ top: 30 })
- Image($r('app.media.computer6'))
- .height(220)
- .width('100%')
- .margin({ top: 30 })
- }
- .width('100%')
- .flexGrow(1)
- }
- .scrollable(ScrollDirection.Vertical)
-
- DetailBottom()
- }
- .height('90%')
- .width('100%')
- }
- }
其中顶部DetailTop组件效果图如下:
代码如下:
- @Component
- struct DetailTop {
- build() {
- Column() {
- Row() {
- Image($r('app.media.icon_return'))
- .height(40)
- .width(40)
- .margin({left: 20})
- .onClick(() => {
- router.push({
- uri: "pages/HomePage"
- })
- })
-
- }
- .width('100%')
- .height(35)
- .backgroundColor('#FF87CEEB')
- }
- .width('100%')
- .height(40)
- }
- }
SwiperTop组件效果图如下:
代码如下:
- @Component
- struct SwiperTop {
- build() {
- Column() {
- Swiper() {
- Image($r('app.media.computer1'))
- .height(220)
- .width('100%')
- Image($r('app.media.computer2'))
- .height(220)
- .width('100%')
- Image($r('app.media.computer3'))
- .height(220)
- .width('100%')
- Image($r('app.media.computer4'))
- .height(220)
- .width('100%')
- Image($r('app.media.computer5'))
- .height(220)
- .width('100%')
- Image($r('app.media.computer6'))
- .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($r('app.media.icon_promotion'))
- .objectFit(ImageFit.Contain)
- .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(18)
- .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(14)
- .margin({ left: 10 })
- Row() {
- Image($r('app.media.icon_buy'))
- .objectFit(ImageFit.Contain)
- .height(30)
- .width(30)
- .margin({ left: 10 })
- Text('Limited offer')
- .fontSize(15)
- .fontColor(Color.Red)
- .margin({ left: 100 })
-
- }
- .backgroundColor(Color.Pink)
- .width('100%')
- .height(45)
- .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(170)
- .width('100%')
- }
- .height(180)
- .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('10%')
- }
- }
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.Capsule })
- .height(50)
- .width(100)
- .margin({ top: 5 })
-
- }
- .height(60)
- .width(100)
- }
- }
有很多小伙伴不知道学习哪些鸿蒙开发技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?而且学习时频繁踩坑,最终浪费大量时间。所以有一份实用的鸿蒙(HarmonyOS NEXT)资料用来跟着学习是非常有必要的。
这份鸿蒙(HarmonyOS NEXT)资料包含了鸿蒙开发必掌握的核心知识要点,内容包含了(ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、Harmony南向开发、鸿蒙项目实战等等)鸿蒙(HarmonyOS NEXT)技术知识点。
希望这一份鸿蒙学习资料能够给大家带来帮助,有需要的小伙伴自行领取,限时开源,先到先得~无套路领取!!
如果你是一名有经验的资深Android移动开发、Java开发、前端开发、对鸿蒙感兴趣以及转行人员,可以直接领取这份资料
获取这份完整版高清学习路线,请点击→纯血版全套鸿蒙HarmonyOS学习资料
HarmonOS基础技能
有了路线图,怎么能没有学习资料呢,小编也准备了一份联合鸿蒙官方发布笔记整理收纳的一套系统性的鸿蒙(OpenHarmony )学习手册(共计1236页)与鸿蒙(OpenHarmony )开发入门教学视频,内容包含:ArkTS、ArkUI、Web开发、应用模型、资源分类…等知识点。
获取以上完整版高清学习路线,请点击→纯血版全套鸿蒙HarmonyOS学习资料
OpenHarmony北向、南向开发环境搭建
获取以上完整鸿蒙HarmonyOS学习资料,请点击→纯血版全套鸿蒙HarmonyOS学习资料
总的来说,华为鸿蒙不再兼容安卓,对中年程序员来说是一个挑战,也是一个机会。只有积极应对变化,不断学习和提升自己,他们才能在这个变革的时代中立于不败之地。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。