一,DevEoc Studio基本内容学习
项目工程目录
entry 默认的项目入口模块
ets 界面相关文件(目前都放入pages文件内即可)
resource资源文件,配置文件
index.est默认文件
’ @ ‘开头的一般为装饰器,修饰功能,来约定后面代码的功能
Entry项目入口
@Component 约定下方代码为组件
(鸿蒙中,界面中能看到的都是组件)
@State约定后面的代码为状态,数据变视图,自动更新(数据驱动视图)
bulid()构建界面,文字等等
系统组件:RelativeContainer Text
@Entry
@Component
struct Index {
@State message: string = 'Hello HM';
build() {
RelativeContainer() {
Text(this.message)
.id('HelloWorld')
.fontSize($r('app.float.page_text_font_size'))
.fontWeight(FontWeight.Bold)
.alignRules({
center: { anchor: '__container__', align: VerticalAlign.Center },
middle: { anchor: '__container__', align: HorizontalAlign.Center }
})
.onClick(() => {
this.message = 'Welcome';
})
}
.height('100%')
.width('100%')
}
}
二,ArkTs学习
1.变量和类型
使用变量存储不同类型的数据:状态信息(布尔类型boolean),文字信息(字符串类型string),数字信息(数字类型number)
any不确定类型(只能在TS中使用,不能在ArkTS中使用)
变量:存储数据的容器
存储方式:【 let 变量名:数据类型 = 值 】
*在日志中输出小括号中的内容
console.log()
测试:在日志中查看输出信息
日志并不会自动清空,右键清空
//注释:crtl+/
//声明变量,保存数据 string字符串类型
let title:string='创意橘子花瓶'
//日志输出
console.log('商品标题是',title)
let count:number=1
console.log('购买数量',count )
let isSelect:boolean=true
console.log('订单选中了吗?',isSelect)
2.数组
数组:一次性保存多个同类型数据
数组也是容器,用来存储多个数据
数组:[数据1,数据2,......]
表示方法: let 数组名 : 类型[] = [数据1,数据2,数据3,.......]
找到对应的数据:数组名[索引] (索引0,1,2,...)
let titles:string[]=['创意','橘子','花瓶']
console.log('数组是',titles)
console.log('产品1',titles[0])
3.对象
对象:可以一次性存多个不同类型的数据
*数组存的是相同类型的数据,对象存的是不同类型的数据
***使用接口来约定对象的结构和类型
【用接口来定义对象中变量的类型,(接口中有什么是哪种类型,对象中也要有对应的内容)】
定义接口【interface 接口名{}】
定义对象【let 对象名:接口名={}】
//定义接口->约定对象的数据类型(接口名Goods)
interface Goods{
title:string
price:number
}
//定义对象【 属性名:属性值->键值对->键值对之间用逗号隔开 】(继承接口,要和接口的数据相对应)
let vase:Goods={
title:'创意句子花瓶',
price:12.99
}
//查找数据 对象名.属性名
console.log('商品标题是',vase.title)
console.log('商品价格是',vase.price)
console.log('对象是',vase)//得到[object Object],隐藏数据的内容
练习
interface People{
name:string
age:number
height:number
listen:boolean
}
let ren:People={
name:'王铁锤',
age:20,
height:180,
listen:true
}
console.log('人名',ren.name)
console.log('年龄',ren.age)
console.log('身高',ren.height)
console.log('成年没',ren.listen)
4.函数
使用函数封装代码,提升代码复用性(一次定义,多次使用)
*定义函数
function calc(){ function 函数名(参数1:类型,参数2:类型,...){
return 返回值(返回到函数调用的位置)
} }
*调用函数
calc() 函数名()
例子:计算圆的周长
//计算任意半径圆的周长 2*3.14*半径
function calc(r:number){
console.log('半径为',r)
return 2*3.14*r;
}
//真实数据->实参
let c1:number=calc(10)
console.log('圆的周长',c1)
let c:number=calc(100)
console.log('圆的周长',c)
没有参数没有返回值
//没有参数没有返回值的函数
function printInfo(){
console.log('函数里面的输出语句')
}
printInfo();
定义函数->function 函数名(参数列表){} 形参
调用函数->函数名(数据列表) 实参
5.箭头函数
使用箭头函数封装代码,提升代码复用性
表示形式: ( ) =>{
}
可以将箭头函数存到一个函数名中
*定义函数
(函数名sum)
let sum = (num1: number,num2:number)=>{
return num1+num2
}
*调用函数
sum(1,2)
//计算任意两个数的和
let sum=(num1:number,num2:number)=>{
console.log('参数的数据是',num1,num2)
return num1+num2
}
console.log('箭头函数的返回值是',sum(1,2))
console.log('箭头函数的返回值是',sum(10,20))
练习:计算圆的周长
let cun=(r:number)=>{
return 2*3.14*r
}
console.log('圆的周长是',cun(2))
三,ArkUI
ArkUI(方舟开发框架):构建鸿蒙应用界面的框架
1.组件基础
组件:界面构建与显示的最小单位
*掌握组件写法,使用组件布局界面
**容器组件:布局
写法:组件名(){}
Colume(){} (内容竖着排)
Row(){} (内容横着排)
**内容组件:内容
写法:组件名()
Text('内容')要求内容都是字符串类型的
*****注意:先布局,再内容 (在bulid()中写代码)
Column换行排列
Row横向排列
@Entry
@Component
struct Index {
build() {
// Column(){
// Text('大壮')
// Text('大壮')
// Text('大壮')
// }
Row(){
Text('大壮')
Text('大壮')
Text('大壮')
}
}
}
***build唯一的容器组件:用嵌套来解决
2.通用属性
使用属性美化组件
写法: 组件
.属性(值)
属性名 | 作用 | 属性值 |
width | 宽度 | 数值(默认单位vp) |
height | 高度 | 数值(默认单位vp) |
backgroundColor | 背景色 | 色值(内置颜色或十六进制色值) |
@Entry
@Component
struct Index {
//build 里面要有唯一的容器和组件
build() {
Column(){
Text('大锤')
//给Text组件添加宽高背景色
//Color E->Enum 枚举
.backgroundColor(Color.Blue)
.width(100)
.height(50)
Row(){}
//满屏尺寸为360vp或者100%
//.width(360)
.width('100%')
.height(100)
.backgroundColor('#ff6600')
}
}
}
3,文本属性
属性名 | 作用 | 属性值 |
fontSize | 字体大小 | 数值(默认单位fp) |
fontColor | 文字颜色 | 色值(内置颜色或十六进制颜色) |
fontWeight | 字体粗细 | 100~900 |
@Entry
@Component
struct Index {
//build 里面要有唯一的容器和组件
build() {
Column(){
Text('大锤')
//this.自定义构建函数名(数据列表1)
//this.自定义构建函数名(数据列表2)
.fontSize(30)
.fontColor(Color.Blue)
.fontWeight(800)
}
}
}
练习:新闻列表
@Entry
@Component
struct Index {
//build 里面要有唯一的容器和组件
build() {
Column(){
Text('在千年')
.fontSize(18)
.width(320)
Text('新华社')
.fontSize(12)
.fontColor('#999999')
.width(320)
Text('扩大开发对象')
.fontSize(18)
.width(320)
Text('央视新闻')
.fontSize(12)
.fontColor('#999999')
.width(320)
}
}
}
4,图像组件
使用图像组件Image为界面添加图像资源
Image(图像资源路径)
支持本地图和网络图
路径写法:本地图 Image($r('app.media.xx'))
网络图 Image('https:xxx')
@Entry
@Component
struct Index {
//build 里面要有唯一的容器和组件
build() {
Column(){
//添加本地图片
Image($r('app.media.startIcon'))
.width(200)
//添加网络图片
Image('https://p5.ssl.qhimgs1.com/sdr/400__/t013c8c9997c4ffb6af.jpg')
.width(200)
}
}
}
5,内外边距
使用内,外边距调整组件及内容的位置
内边距padding 外边距margin
*希望内容和组件之间有间距用padding
*希望两个组件之间有间距用margin
***四个方向间距相同 写法:
组件
.padding(数值)
.margin(数值)
***四个方向间距不同 写法:
组件
.padding({top:10,botton:20,left:30,right:40})
.margin({top:10,botton:20,left:30,right:40})
@Entry
@Component
struct Index {
//build 里面要有唯一的容器和组件
build() {
Column(){
Button('登录')
.width('100%')
.margin({bottom:20})
Button('注册')
.width('100%')
.backgroundColor(Color.Green)
}
.backgroundColor('#DDDDDD')
.padding(10)
.padding({
left:10,
top:20,
right:30,
bottom:30
})
}
}
内边距:拉开内容与组件边缘的距离
外边距:拉开两个组件的距离
单值:四个方向间距相同
对象:四个方向间距不同
6,边框属性border
使用border属性为组件添加边框效果:设置边框,圆角,粗细,等等
写法: 组件
.border({
width:粗细
color:颜色
style:线条样式
radius:圆角
})
@Entry
@Component
struct Index {
//build 里面要有唯一的容器和组件
build() {
Column(){
Text('+状态')
.width(100)
.height(60)
.backgroundColor(Color.Brown)
//文本水平居中
.textAlign(TextAlign.Center)
.border({
width:3,
color:Color.Blue,
style:BorderStyle.Dotted,
radius:10
})
}
.padding(20)
}
}
四,界面布局
1.歌曲列表
使用组件及属性方法布局歌曲列表
***先整体,再布局
***先布局,再内容,后美化
******List容器组件,里面加ListItem
写法:List(){
ListItem(){...}
ListItem(){...}
}
******scrollBar滚动条 BarState滚动条状态
设置不显示滚动条 .scrollBar(BarState.Off)
******扩充组件的安全区expandSafeArea 扩充到顶部SafeAreaEdge.TOP,底部SafeAreEdge.BOTTOM
组件(){}
.expandSafeArea([SafeAreaType.SYSTEM],[SafeAreaEdge.TOP,SafeAreaEdge.BOTTOM])
******.layoutWeight(数字) 将外层组件剩余尺寸分成指定份数,当前组件占用对应的份数
******图片.svg(支持用代码,用属性改变图片颜色) 用 .fillColor('') 改变图片颜色
import { EditableLeftIconType } from '@kit.ArkUI'
@Entry
@Component
struct Index {
build() {
Column(){
Text('猜你喜欢')
.fontColor('#fff')
.width('100%')
.margin({bottom:10})
//容器组件List,支持滑动,加ListItem
List(){
ListItem(){
Row(){
//图
Image($r('app.media.1'))
.width(80)
.height(80)
.border({radius:8})
.margin({right:5,left:5})
//字
Column(){
Text('直到世界镜头')
.fontColor('#F3F3F3')
.width('100%')
.fontWeight(700)
.margin({bottom:15,left:10})
Row(){
Text('VIP')
.fontColor('#9A8E28')
.border({radius:8,color:'#9A8E28',width:1})
.padding({left:5,right:5,top:3,bottom:3})
.margin({right:8,left:8})
.fontSize(10)
Text('凤凰传奇')
.fontColor('#696969')
.fontSize(12)
}
.width('100%')
}
.layoutWeight(1)//占用剩余的所有空间
//图标
//*图片.svg(支持用代码,用属性改变图片颜色)用.fillColor('')
Image($r('app.media.4'))
.width(20)
.margin({right:5})
}
.width('100%')
.height(80)
//.backgroundColor(Color.Pink)
.margin({bottom:10})
}
ListItem(){
Row(){
//图
Image($r('app.media.1'))
.width(80)
.height(80)
.border({radius:8})
.margin({right:5,left:5})
//字
Column(){
Text('直到世界镜头')
.fontColor('#F3F3F3')
.width('100%')
.fontWeight(700)
.margin({bottom:15,left:10})
Row(){
Text('VIP')
.fontColor('#9A8E28')
.border({radius:8,color:'#9A8E28',width:1})
.padding({left:5,right:5,top:3,bottom:3})
.margin({right:8,left:8})
.fontSize(10)
Text('凤凰传奇')
.fontColor('#696969')
.fontSize(12)
}
.width('100%')
}
.layoutWeight(1)//占用剩余的所有空间
//图标
//*图片.svg(支持用代码,用属性改变图片颜色)用.fillColor('')
Image($r('app.media.4'))
.width(20)
.margin({right:5})
}
.width('100%')
.height(80)
//.backgroundColor(Color.Pink)
.margin({bottom:10})
}
}
//折叠滚动条: 滚动条scrollBar 滚动条状态BarState 关闭Off
.scrollBar(BarState.Off)
}
.width('100%')
.height('100%')
.backgroundColor('#131313')
.padding({left:10,right:10})
//扩充组件的安全区,扩充到顶部SafeAreaEdge.TOP,底部SafeAreEdge.BOTTOM
.expandSafeArea([SafeAreaType.SYSTEM],[SafeAreaEdge.TOP,SafeAreaEdge.BOTTOM])
}
}
2,if分支语句
根据逻辑条件结果,执行不同语句
if(逻辑条件){
条件成立执行的代码
}else{
条件不成立执行的代码
}
*if成立时
let age:number=20
if(age>=18){
console.log('成年了')
}
@Entry
@Component
struct Index {
build() {
Column() {
}
}
}
*if不成立,执行else
let age:number=10
if(age>=18){
console.log('成年了')
}else{
console.log('未成年')
}
@Entry
@Component
struct Index {
build() {
Column() {
}
}
}
根据逻辑条件结果,执行不同语句
if(条件1){
条件1成立执行的代码
}else if(条件2){
条件2成立执行的代码
}else{
以上条件都不成立执行的代码
}
let score:number=90
if(score>=80){
console.log('A')
}else if (score>=70){
console.log('B')
}else if(score>=60){
console.log('C')
}else {
console.log('D')
}
3.条件表达式
根据逻辑条件结果,执行不同的表达式,得到不同结果
写法: 条件?条件成立的表达式:条件不成立的表达式
let num1:number=10
let num2:number=20
num1>num2?console.log('num1大'):console.log('num2大')
4.条件渲染
根据逻辑条件结果,渲染不同的UI内容
写法:
if(条件1){
组件1
}else if(条件2){
组件2
}else{
组件 else
}
*** “ === ”严格等号,判断数值+类型
let num1:number=1
@Entry
@Component
struct Index {
build() {
Column() {
if(num1==1){
Text('文本1')
}else if(num1==2){
Text('文本2')
}else{
Text('文本else')
}
}
}
}
五,ArkTS核心
1.循环渲染
根据数组数据重复渲染UI内容
写法: ForEach(数组名字,箭头函数)
ForEach(数组,(item:类型,index:number)=>{
组件
})
*item数组中的数据项 index索引
let names:string[]=['Tom','Kit','Dog']
@Entry
@Component
struct Index {
build() {
Column() {
ForEach(names,(item:string,index:number)=>{
//字符串之间的‘+’,表示拼接
Text(item+index)
})
}
.padding(10)
}
}
2.状态管理(V2)
应用的运行时的状态是参数,当参数改变时,UI渲染刷新
状态变量:使用装饰器装饰,状态变量数据改变会引起UI的渲染刷新
//V2状态管理
@ComponentV2
struct Index{
@Local num:number=1
......
}
*注意:
(1).状态必须设置数据类型
(2).状态必须设置初始值
//.onClick点击事件
组件
.onClick(()=>{
this.num++
this.num--
})
@Entry
//进入V2状态
@ComponentV2
struct Index {
//num状态
@Local num:number=0
build() {
Column() {
Row(){
Text('-')
.width(40)
.height(40)
.textAlign(TextAlign.Center)
.border({width:1,radius:{topLeft:3,bottomLeft:3},color:'#999'})
//添加点击事件,修改状态
.onClick(()=>{
if(this.num>1){
this.num--
}
})
//状态设置进来,将num的类型转换为string
Text(this.num.toString())
.width(40)
.height(40)
.textAlign(TextAlign.Center)
.border({width:{top:1,bottom:1},color:'#999'})
Text('+')
.width(40)
.height(40)
.textAlign(TextAlign.Center)
.border({width:1,radius:{topRight:3,bottomRight:3},color:'#999'})
//添加点击事件,修改状态
.onClick(()=>{
this.num++
})
}
.padding(20)
}
}
}
3.@Builder自定义构建函数
使用@Builder装饰的函数也称为“自定义构建函数”
@Builder装饰的函数作用:封装UI元素,提升复用性
*定义方法:
@Builder
自定义构建函数名(参数列表){
要复用的组件结构
}
*调用方法
this.自定义构建函数名(数据列表1)
this.自定义构建函数名(数据列表2)
*自定义构建函数可以写在组件的里面
@Entry
@Component
struct Index {
//封装自定义构建函数 传入参数
@Builder
titleBuilder(title:string){
Row(){
Text(title)
.fontColor('#fff')
.fontWeight(700)
.layoutWeight(1)
Image($r('app.media.1'))
.width(22)
}
.width('100%')
.height(50)
}
build() {
Column() {
this.titleBuilder('每日推荐')
this.titleBuilder('推荐歌单')
}
.width('100%')
.height('100%')
.expandSafeArea([SafeAreaType.SYSTEM],[SafeAreaEdge.TOP,SafeAreaEdge.BOTTOM])
.backgroundColor('#131313')
.padding({left:10,right:10})
}
}
六,歌单交互效果
1. ForEach循环渲染歌单
数组里面包对象,可以叫做对象数组
interface Music{
image:string
name:string
author:string
}
@Entry
@Component
struct Index {
songs:Music[]=[
{
image:'https://img2.baidu.com/it/u=2614416695,3021245428&fm=253&fmt=auto&app=138&f=JPEG?w=504&h=500',
name:'美美美',
author:'xiao田'
},
{
image:'https://img0.baidu.com/it/u=1717687967,3764228590&fm=253&fmt=auto&app=138&f=JPEG?w=800&h=800',
name:'美美美',
author:'xiao田'
},
{
image:'https://img2.baidu.com/it/u=579662994,16903855&fm=253&fmt=auto&app=138&f=JPEG?w=800&h=800',
name:'美美美',
author:'xiao田'
},
{
image:'https://img0.baidu.com/it/u=2960273897,2797347908&fm=253&fmt=auto&app=138&f=JPEG?w=800&h=800',
name:'美美美',
author:'xiao田'
},
{
image:'https://img1.baidu.com/it/u=3259094038,2675463443&fm=253&fmt=auto&app=120&f=JPEG?w=500&h=500',
name:'美美美',
author:'xiao田'
},
{
image:'https://img1.baidu.com/it/u=3745915620,3856927535&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500',
name:'美美美',
author:'xiao田'
},
{
image:'https://img2.baidu.com/it/u=182231357,1062845046&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500',
name:'美美美',
author:'xiao田'
},
{
image:'https://img1.baidu.com/it/u=2431701095,4189347457&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500',
name:'美美美',
author:'xiao田'
},
{
image:'https://img2.baidu.com/it/u=2894005634,1549621335&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500',
name:'美美美',
author:'xiao田'
},
{
image:'https://img2.baidu.com/it/u=2578316366,3430436350&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500',
name:'美美美',
author:'xiao田'
}
]
build() {
Column() {
Text('猜你喜欢')
.fontColor('#fff')
.width('100%')
.margin({bottom:10})
List(){
ForEach(this.songs,(item:Music,index:number)=>{
ListItem(){
Row(){
//tu
Image(item.image)
.width(80)
.border({radius:5})
.margin({right:5,top:10,bottom:10})
//zi
Column(){
Text(item.name)
.fontColor('#fff')
.fontSize('14')
.margin({left:20,bottom:10})
.width('100%')
Row(){
Text('VIP')
.fontColor('#fff')
.fontSize(12)
.margin(10)
.border({radius:8,width:1,color:'#fff'})
Text(item.author)
.fontColor('#fff')
.fontSize(12)
}
.width('100%')
}
.layoutWeight(1)
//fu
Image($r('app.media.4'))
.width(10)
.margin(5)
}
}
})
}
.scrollBar(BarState.Off)
}
.padding(20)
.width('100%')
.height('100%')
.backgroundColor('#131313')
.expandSafeArea([SafeAreaType.SYSTEM],[SafeAreaEdge.TOP,SafeAreaEdge.BOTTOM])
}
}
2.播放状态
层叠组件Stcak()
interface Music{
image:string
name:string
author:string
}
@Entry
@ComponentV2
struct Index {
@Local playIndex:number=-1
songs:Music[]=[
{
image:'https://img2.baidu.com/it/u=2614416695,3021245428&fm=253&fmt=auto&app=138&f=JPEG?w=504&h=500',
name:'美美美',
author:'xiao田'
},
{
image:'https://img0.baidu.com/it/u=1717687967,3764228590&fm=253&fmt=auto&app=138&f=JPEG?w=800&h=800',
name:'美美美',
author:'xiao田'
},
{
image:'https://img2.baidu.com/it/u=579662994,16903855&fm=253&fmt=auto&app=138&f=JPEG?w=800&h=800',
name:'美美美',
author:'xiao田'
},
{
image:'https://img0.baidu.com/it/u=2960273897,2797347908&fm=253&fmt=auto&app=138&f=JPEG?w=800&h=800',
name:'美美美',
author:'xiao田'
},
{
image:'https://img1.baidu.com/it/u=3259094038,2675463443&fm=253&fmt=auto&app=120&f=JPEG?w=500&h=500',
name:'美美美',
author:'xiao田'
},
{
image:'https://img1.baidu.com/it/u=3745915620,3856927535&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500',
name:'美美美',
author:'xiao田'
},
{
image:'https://img2.baidu.com/it/u=182231357,1062845046&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500',
name:'美美美',
author:'xiao田'
},
{
image:'https://img1.baidu.com/it/u=2431701095,4189347457&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500',
name:'美美美',
author:'xiao田'
},
{
image:'https://img2.baidu.com/it/u=2894005634,1549621335&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500',
name:'美美美',
author:'xiao田'
},
{
image:'https://img2.baidu.com/it/u=2578316366,3430436350&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500',
name:'美美美',
author:'xiao田'
}
]
build() {
Column() {
Text('猜你喜欢')
.fontColor('#fff')
.width('100%')
.margin({bottom:10})
List(){
ForEach(this.songs,(item:Music,index:number)=>{
ListItem(){
Row(){
//tu
Stack(){
Image(item.image)
.width(80)
.border({radius:5})
.margin({right:5,top:10,bottom:10})
if(this.playIndex===index){
Image($r('app.media.1'))
.width(10)
}
}
//zi
Column(){
Text(item.name)
.fontColor('#fff')
.fontSize('14')
.margin({left:20,bottom:10})
.width('100%')
Row(){
Text('VIP')
.fontColor('#fff')
.fontSize(12)
.margin(10)
.border({radius:8,width:1,color:'#fff'})
Text(item.author)
.fontColor('#fff')
.fontSize(12)
}
.width('100%')
}
.layoutWeight(1)
//fu
Image($r('app.media.4'))
.width(10)
.margin(5)
}
.onClick(()=>{
this.playIndex=index
})
}
})
}
.scrollBar(BarState.Off)
}
.padding(20)
.width('100%')
.height('100%')
.backgroundColor('#131313')
.expandSafeArea([SafeAreaType.SYSTEM],[SafeAreaEdge.TOP,SafeAreaEdge.BOTTOM])
}
}
循环渲染数据的思路:
数组数据------>ForEach------>替换数据
控制播放状态的思路:
播放状态组件(层叠)--->状态变量@Local播放索引--->条件渲染,播放状态组件--->点击事件修改状态变量
层叠布局组件:
Stack容器组件
依据:【全网首套鸿蒙5.0零基础入门到项目实战开发全套视频教程,原生鸿蒙正式版项目实战从ArkTS+AI到V2应用状态管理,鸿蒙API16应用开发全掌握】https://www.bilibili.com/video/BV1gSZvYzEdZ?p=25&vd_source=9e0031c99b0b852d596960307c0f094d