admin管理员组

文章数量:1655506

ArkTs基础入门

文章目录

  • 一、 (方舟开发框架)ArkUI介绍
  • 二、自定义组件
      • 自定义公共变量和枚举
  • 三、组件事件及使用
      • 分割线
      • Text文本
      • TextInput文本输入框
      • TextArea文本域
      • Image图片
      • BackgroundImage背景图片
      • Button按钮
      • Radio 单选框
      • Toggle切换按钮
      • CheckBox 复/多选框
      • Select选中框
      • Slider进度滑动组件
      • Progress进度条
      • Router路径跳转
      • 扩展setInterval 与setTimeOut的区别
  • 四、盒子模型和布局
      • Padding内边距
      • Border边框
      • borderRadius圆角
      • Margin外边距
      • Column列
      • Row行
      • 主轴交叉轴
      • Blank自适应拉伸,缩放,延伸 弹簧
      • layoutWeight自适应缩放 内容的占比
      • Scroll滚动条
  • 五、动态元素UI构建
      • 页面声明周期
      • 组件声明周期
      • 页面和组件声明周期顺序
      • @Builder局部自定义构建函数:
      • @Builder全局自定义构建函数:
      • @Builder参数传递
      • @BuilderParam占位符、插槽
      • @Styles组件样式重用的封装
      • @Extend 扩展组件样式
      • stateStyles多态样式
      • Flax弹性布局
      • position()绝对定位
      • offset()偏移
      • Z序控制 : zIndex(数字)
      • ForEache用法、数组
      • LazyForEach(懒加载)用法、数组
      • Stack()堆叠布局
      • Grid()网格布局
  • 六、UI的渲染控制
      • Math对象
      • If(){}else{}判断
      • ForEach()循环判断
  • 七、简单容器组件使用
    • 7.1 通用属性
      • linearGradient()颜色渐变效果 :线性渐变==线性
      • radialGradient()颜色渐变效果 :径向渐变== 圆形
      • shadow()阴影效果
      • animation动画
      • 图形变换
        • translate() 平移
        • scale() 缩放
        • rotate() 旋转
    • 7.2 List列表
      • 基本使用
      • divider分割线属性
      • Badge列表标记
      • scrollBar滚动条
      • ListItemGroup分组列表
      • Scroller滚动位置控制
      • AlphabetIndexer响应滚动控制
      • swipeAction列表事件,左右滑动
    • 7.3 滚动Scroll、Scorrer
      • Scroll组件
      • Scorrer控制器
  • 八、Swiper轮播组件
  • 九、Tabs组件
  • 十、Navigation分栏、标题栏、工具栏,导航栏组件
  • 十一、TextPicker文本选择器
  • 十二、TextPickerDialog弹框
  • 十三、TimePicker选择器
  • 十四、TimePickerDialog弹框
  • 十五、DatePicker选择器
  • 十六、DatePickerDialog弹框
  • 十七、自定义选择器 和 CustomDialog自定义弹框
  • 十八、AlertDialog警告弹框
  • 十九、ActionSheet列表弹框
  • 二十、装饰器传值和监听watch
  • 二十一、状态存储
      • LocalStorage:页面级UI状态存储(局部、全局)
      • AppStorage:应用全局的UI状态存储
      • PersistentStorage:持久化存储UI状态
      • Environment:设备环境查询
  • 二十二、手势
      • Gesture点击手势
      • LongPressGesture长按手势
      • PanGesture拖动手势
      • PinchGesture捏合手势
      • RotationGesture旋转手势
      • SwipeGesture滑动手势
      • GestureGroup组合手势
      • 组合手势案例:(缩放、旋转、拖动)
  • 二十三、绘制组件
      • Circle圆形
      • Ellipse椭圆
      • Line线性
      • PolyLine折线
      • Polygon多边形
      • Path路径绘制
      • Rect矩形
      • Shape父组件
  • 二十四、Canvas画布组件
  • 二十五、动画
      • animation动画
      • animateTo显示动画
      • Navigator转场动画,可以用于路径跳转
      • pageTransition页面转场动画效果
      • animateTo组件内动画
      • sharedTransition共享元素组件
      • motionPath路径动画
  • 二十六、多媒体
      • Video视频
  • 扩展
  • 项目启动注意事项或者检查(**会导致模拟启动不起来等其他情况)
  • 规范项目结构


一、 (方舟开发框架)ArkUI介绍

方舟开发框架(简称:ArkUI),是一套 构建 HarmonyOS 应用 界面 的框架。构建页面的最小单位就
是 "组件"。

二、自定义组件

自定义组件的构成: 
ArkTs通过装饰器:@Component和@Entry装饰struct关键字声明数据结构,构成一个自定义组件。
自定义组件中提供了一个build(){} 函数,须在该函数内进行链式调用的方式进行基本的UI描述

@Entry:@Entry没有页面不会被加载,一个自定义组件只能被一个@Entry进行修饰,也是UI页面的入口
@Component :  表示自定义组件,只能修饰struct关键字声明结构,被修饰后具有组件渲染能力
自定义组件格式: 
	@Entry
	@Component
	struct Index {
		build(){
		}
	}
在同一个文件中:定义一个组件可以被实现调用 
@Component
struct Index2 {
	build(){
	}
}
调用方式:
	@Entry
	@Component
	struct Index {
		build(){
			column(){
				Index2()
			}
		}
	}

自定义公共变量和枚举

:
export const FONT_COLOR: Color = Color.Orange
export const FONT_COLOR_Str: string = "#000"
export const FONT_SIZE: number = 40

export const enum PADDING_SIZE {
  TOP = 10,
  RIGHT = 10,
  BOTTOM= 5,
  LEFT = 20
}

三、组件事件及使用

分割线

Divider()  分割线

Text文本

Text("字符串"或者在element中拿取对应值)
格式:
方式一 Text("字符串")
方式二 Text($r("app.string.json文件名.对应name")  // 目的为了国际化

	Text("值")属性:
		.fontSize()  字体大小
		.fontWeight()  设置字体粗细,值可以设置为字符串或者数字类型数字的取值在[100,900]默认400
		.fontColor() 字体颜色,建议使用十六进制和枚举
		.border()  边框 //如:.border({ width: 2 })
		.TextAlign(TextAlign.___)   文本Center居中  Start左边  End右边
		.decoration({ type: TextDecorationType._____})  设置 Underline下划线、LineThrough中划线、Overline上划线
		.MaxLines(number)  设置最大行数 ,多出的不会显示,若想看是否存在溢出需要结合 textOverflow,但不会显示溢出多少信息只是有个表示。。。
		.textOverflow({overflow:TextOverflow.Ellipsis})   Clip溢出不显示,Ellipsis:超出最大行数才会生效,才体现一处效果,MARQUEE: 滚动效果
		.lineHeight()  行高 :行与行的高度
		.borderRadius(8)  设置圆边框
		.opacity(number | Resource)   设置透明度
		.letterSpacing(number | string) 设置字体之间的间隙
		.width() 宽度
		.height() 高度

	当Text中写Span后,text是不生效的,样式也是一样
	如:
	Text(`sssvfvfv`) {
        Span("米好")  业务span内容会覆盖Text内容,若样式都有则文本样式不生效
      }

TextInput文本输入框

	TextInput({ placeholder: '提示信息',text:'默认值' })
		.width()宽度
		.height() 高度
		// 常用事件
		.onChange((val)=>{})  触发事件:当写箭头函数时val位置,可以获取输入变量,用于改变定义变量信息
		.onSubmit(()=>{}) 当点击回车,触发执行事件
		// 不常用事件
		.onFocus(()=>{}) 当获取文本焦点则就会触发
		.onBlur(()=>{}) 当失去文本输入框焦点,则会触发
		.type(InputType.___)  设置是普通文本、Number数值、Password密码、Email邮箱、PhoneNumber手机号 格式
		

TextArea文本域

// 多行输入框
// 当一行输入到头时,则自动更新换下一行
TextArea() 

Image图片

	图片的引用存在4个方式:
	1.当文件在media下时,调用方式为: Image($r("app.media.图片名"))
	2.当文件在rawfile下时,调用方式为:Image($rawfile("图片名"))
	3.pages内可以任意创建文件 使用相对路径 如:Image("./pages/image.png")
	4.引用网络资源,
		Image("图片访问地址")
	需要在module.json5配置网络权限
		 "module": { // 文件中已经存在
			 // 添加网络请求权限   固定格式
           "requestPermissions": [{"name": "ohos.permission.INTERNET" }] 
         }
格式及相关属性:
	Image("4种方式")
		.width("100")
		  // .height("50")
		  // 宽高比 同时设置宽高不会使用,
		  // 设置一个宽或者高然后再设置宽高比 当存在宽高比为长方形则会显示不全
		.aspectRatio(1)
		.alt("URL路径 4种方式") // 一般是本地,展位图,当引入外来资源,或者加载慢,则会显示展位图
		.fillColor("颜色") // 设置图标颜色  [图标库](https://developer.huawei/consumer/cn/design/harmonyos-icon/)
		.objectFit(ImageFit.__) // 图片缩放 常用: Fill:按照容器尺寸铺满。Cover:截取一部分 Contain:按照比例展示
		.blur() // 模糊度 越大越模糊 10-100
		.opacity() // 越小越透明 0-1
		

BackgroundImage背景图片

例:
Text("背景土")
        .width(300)
        .height(300)
        .backgroundColor(Color.Orange) // 图片背景颜色,一般不用
        .backgroundImage("/pages/image.png") // 背景图片
        .backgroundImageSize(ImageSize.Contain 或者  {width:280,height:280}) // 背景图片大小 {width:280,height:280}或者ImageSize属性   ImageSize属性:Cover:截取一部分 Contain:按照比例展示
        .backgroundImagePosition(Alignment.Center) // 位置坐标位置,但是不是平铺过去 {x:280,y:290} 或者 Alignment属性
        .border({ width: 1,radius:0) }) // 边框,边缘圆角

Button按钮

格式:
	Button(“名称”,{type: ButtonType.____})        //  Circle圆形,Capsule胶囊,Normal矩形
	.onClick(()=>{处理业务})点击事件使用
	.enabled(boolean)  :按钮判断合适禁用启用
	Button("登录") // type,可选见上
		.width("80%")
		.onClick(() => {
		  if (true) {
		    AlertDialog.show({ message: '登录成功' })
		  } else {
		    AlertDialog.show({ message: '登录失败' })
		  }
		})
		.enabled(true) // true启用 false 禁用

Button按钮 还可以存在子组件

Button() {
        Row() {
          Image("/pages/image.png")
            .width(50)
            .aspectRatio(2) // 宽高比
        }
      }

Radio 单选框

Radiod({value:'单选名字',group:'分组'})
	.checked(true) // 是否默认  true:默认
	.onChang((val)=>{ // 当发生点击,触发的事件,并会传递值
		if(val){
		//  业务体
		}
	})
** 当存在多个单选框时,需要弹开,可以使用 Blank() 函数(弹簧),若不生效,看一下width()长度是否设置了

Toggle切换按钮

Toggle:可以设置为多个按钮(Checkbox复选框、Button按钮、Switch开关) **** Button按钮比较特殊和其他不同,如下:
/*
         * Checkbox :复选框
         * Switch 开关
         * Button: 按钮 ,需要在里面设置文本
         * */
     Checkbox :复选框:
     Toggle({ type: ToggleType.Checkbox, isOn: false })// isOn: true:默认 false:非默认。
     Switch 开关:
     Toggle({ type: ToggleType.Switch, isOn: true }) // isOn: true:默认 false:非默认。
     Button: 按钮 ,需要在里面设置文本
     Toggle({type: ToggleType.Button,isOn: true}) {Text("按钮")}

CheckBox 复/多选框

Checkbox({name:'名称',group:'分组'})
	.select(true) // 默认
	.selcectColor("颜色") // 复选框颜色
	.onChange((val)=>{ "业务体" }) // 改变事件

Select选中框

Select选项是个数组的方式[]
icon: 可以为每个选项设置图片
@State opers:[] = [
{value:'一级',icon:"图片路径"},
{value:'二级'} 
]
select(opers)
	.value("请选择选项") // 设置提示
	.selected(1) // 根据下标默认选择
	.selectedOptionFont({size:20}) // 选中的字体大小
	.optionFont({size:20}) // 选项大小
	.onselect((index)=>{ // 选择触发事件 index为数组下标
	}) 
	

Slider进度滑动组件

Slider({
  value: 'number默认值',
  min: 0, // 最小
  max: 60, // 最大
  style: SliderStyle.OutSet, // OutSet:滑块在滑轨上。 InSet:滑块在滑轨内。
  direction: Axis.Vertical // 竖着,默认水平
})
  .showTips(true)  // true:滑动显示%
  .trackColor('#bbb') // 未滑动颜色
  .selectedColor('#bbb') // 已经滑动颜色
  .blockColor('#ff2778f1') // 滑块颜色
  .showSteps(false) // 是否显示刻度值
  .onChange((value: number, mode: SliderChangeMode) => {
    this.intervalMinute = value
  })

Progress进度条

默认横着:可以通过宽度设置宽度, 当高度大于宽度,则会变为竖的进度条
Progress({value:当前进度,total:100(一般是100好计算) ,type:ProgressType.__值__})
ProgressType:
	Linear : 线性 
	Ring:环形
	ScaleRing:刻度进度条
	Eclipse:圆形
	Capsule: 胶囊
	例:
		Progress({value:num , total:100,type:ProgressType.___值___})
			.style({strokeWidth: 30 }) // 当为环形时设置厚度
			.style({scaleCount: 60}) // 当为刻度进度条 可以设置刻度数量

Router路径跳转

Router的使用需要导入包: import router from '@ohos.router'  --当使用时,会自己导入
使用方法:
 1.在需要路由跳转的路径需要在src/main/resources/base/profile/main_pages.json的位置添加路径信息
 若启动模拟器:则查看: src/main/ets/entryability/EntryAbility.ts 下的启动首页路径需要配置为首页的
 2.开始使用 router.pushUrl({url:"跳转到那个文件的路径",params:'参数'})   或者  router.replaceUrl({url:"跳转到那个文件的路径",params:'参数'}) 
 
 3.当退回使用  router.pushUrl({url:"跳转到那个文件的路径",params:'参数'}) 
 或者 
 	router.back() 
 或者  
	 router.back({
	 url: 'pages/Index',
	  params: { msg: "这是上个页面的返回信息" }
	})
 4. 当路由完成可以在声明周期结束时清除路由: router.clear()
**扩展: pushUrl()replaceUrl()的区别:
	pushUrl: 使用跳转可以返回上一级页面。
	replaceUrl: 使用跳转不能跳转上一级页面,比如首页展示
	具体看情况而定

5.接收参数
Arrs:类型 = router.getParams()["msg"] // 接收看传递的是什么类型
router知识点:
1.router的2中实例模式:单例(Single)和多例(Standard)===>默认:多例(Standard)
2.router.pushUrl()区别: 
	多例(Standard):默认为多例,跳转时则会往栈中添加一条路由,栈中只能存32个路由,因此在合适的位置需要使用clear()清除路由
	单例(Single):若栈中没有保存当前路由,则会往栈中添加一条,当存在时则是直接在栈中拿。这种页面会存在一定的页面缓存效果。若是局部刷新的话,则在需要跳转之前先操作。
3.router.pushUrl() 与 router.replaceUrl()的区别:
相同点:都可以使用参数进行传参。
router.pushUrl():当使用跳转时会往栈中添加一条路由,可以使用router.back() 进行返回,可以返回上一级。
router.replaceUrl():进行跳转时,则会将当前的路由进行替换,当返回时直接退出应用系统。

扩展setInterval 与setTimeOut的区别

格式:
let id = setInterval(()=>{},时间) // 每搁多长时间,执行一次 
let id =setTimeOut(()=>{},时间) // 延迟多长时间开始执行,执行完就结束了

当使用完成,需要关闭需要调用各自的.clearInterval(id) 或者 clearTimeOut(id)函数
setInterval():50ms执行一次:
let dingshi = setInterval(()=>{
    if (this.sum ==100) {
      this.is = true
      this.sum = 0
      clearInterval(dingshi)  // 清除,否则页面不变化,但是内部还在执行
    } else {
      this.sum++
    }
  },50)

setTimeout(): 延时50ms执行:
let dingshi =setTimeout(()=>{
	// 业务体
	clearTimeOut(dingshi)
},50)

四、盒子模型和布局

Padding内边距

Border边框

用法:
	Text() // 可以为其他组件
	// 上使用线:Solid 实线、Dashed 虚线(短线)、 	Dotted: 虚线(点)
	.border({width:1,color:Color.Green,style:BorderStyle.Solid}) // 边框宽度,粗细颜色,实线

borderRadius圆角

borderRadius: 生成的样式,为矩形把角磨圆的形状为圆角
		针对四个角设置
		// 格式一
		.borderRadius(10) // 将圆角设置为10, 当为正方形时,设置一半的长度图形为圆形
		// 格式二
		.borderRadius({ // 单独设置每一个角
		topLeft: 40,
		topRight: 10,
		bottomLeft:10,
		bottomRight:40
})
		.clip(true) // 裁剪 当有图片时,可能导致样式不显示,此时可以使用

Margin外边距

Column列

格式:Column(){ }// 在上级为build() 时  每个自定义组件中,统计的只能存在一个 ,因为只能存在一个节点
组件可以设置每个子组件的间距:
Column({space:30}){} // 各间距30vp

Row行

格式:Row(){}  // 在上级为build() 时    每个自定义组件中,统计的只能存在一个 ,因为只能存在一个节点

主轴交叉轴

Column: 
列的主心轴为竖着的  
设置使用.justifyContent(FlexAlign.____)  //Start 主轴起始对齐  Center中间对齐  End:末端对齐  SpaceBetween 之间均分  SpaceAround两边一半均分  SpaceEvenly 包含空格
列的交叉轴为横着的  
设置使用.alignItems(HorizontalAlign.____)   //Start 主轴起始对齐  Center中间对齐  End:末端对齐

Row:
行的主心轴为横着的  
设置使用.justifyContent(FlexAlign.____)  //Start 主轴起始对齐  Center中间对齐  End:末端对齐  SpaceBetween 之间均分  SpaceAround两边一半均分  SpaceEvenly 包含空格
行的交叉轴为竖着的  
设置使用.alignItems(VerticalAlign.____)   //Start 主轴起始对齐  Center中间对齐  End:末端对齐

共用组件属性:
某个条件来设置方向(从左至右,还是从右至左)
.direction(true ? Direction.Rtl : Direction.Ltr) // Rtl :从右至左,否则取反


Blank自适应拉伸,缩放,延伸 弹簧

Blank(): 将两个组件弹开,可以使用在2个按钮之间,如设置里面的数据信息也是可以的

layoutWeight自适应缩放 内容的占比

layoutWeight(number) :根据设置的占比自己调整
例:
@Component
struct AlterInDome {
  build() {
    Row() {
      Column() {

      }
      .width(50)
      .height(30)
      .backgroundColor(Color.Gray)
      .border({ width: 1 })
      // 设置内容的占比 ,也可以设置宽度百分比进行
      .layoutWeight(1)

      Column() {

      }
      .width(50)
      .height(30)
      .backgroundColor(Color.Gray)
      .border({ width: 1 })
      .layoutWeight(1)

      Column() {

      }
      .width(50)
      .height(30)
      .backgroundColor(Color.Gray)
      .border({ width: 1 })
      .layoutWeight(2)

    }
    .width("80%")
    .backgroundColor(Color.Red)
  }
}

Scroll滚动条

格式:
	@Compocnent
	struct 自定义组件名称{
		build(){
			Scroll(){  // 滚动条组件
				Column(){}  //或者其他组件
				} 
				.在这添加属性
			}
		}
属性:
.scrollable(ScrollDirection.___) // Vertical:垂直方向移动 、 Horizontal:水平方向
.scrollBar(BarState.On) // 显示滚动条 on:显示  auto:当滚动出现, off:不显示滚动条
.scrollBarColor("") //滚动条颜色
.edgeEffect(EdgeEffect.Spring) // Spring:到边缘回弹  Fade:边缘滑动效果为“渐隐”效果

五、动态元素UI构建

页面声明周期

onPageSHow(){}:当点击这个页面时,开始这个路由时执行, 在vue中其实就是钩子函数 等于create,在这叫声明周期
onPageHide(){}: 当这个页面被置动至后台。使用的声明周期
onBackPress(){}: 当页面点击退出调用此声明周期

组件声明周期

当单击页面的是由优先加载组件,因为页面就是组件渲染出来的。
aboutToAppear(){}: 组件开始加载时调用,在执行build() 函数之前执行
aboutToDisappear(){}: 关闭组件时调用

页面和组件声明周期顺序

1.aboutToAppear()-->组件声明周期
2.build()
3.onPageSHow() -->页面声明周期,开启页面展示/渲染
4.方式一: 当页面置于后台,调用onPageHisde() -->开启页面隐藏 
	方式二: 当页面退出时执行onPagePress()-->开启页面退出 后执行 	onPageHide()-->开启页面隐藏
5.aboutToDisappear() -->关闭组件

@Builder局部自定义构建函数:

调用需要使用this
格式:
@builder 组件名(str:string,....){} // 可以传多个参数  

调用:
this.组件名("",....) 

@Builder全局自定义构建函数:

调用直接调用,定义则需要使用Function
格式:
@builder function 组件名(str:string,....){} // 可以使用参数

调用:
组件名(str:string,....)

@Builder参数传递

自定义函数支持两种方式传递:
按值传递: 如组件名(str:string,....)  也就是栈中的数据
按引用传递:定义参数需要使用($$:类型) 

定义组件格式: 
@Builder
getCellContent($$: CellParams){}
调用不变
getCellContent({"对象属性""对象属性对应的值"})

@BuilderParam占位符、插槽

可以理解为自定义组件,构建自定义UI页面,此功能只要是定义一个插槽,可以后填充自定义组件。
属于在组件内的某一个位置使用插槽当不使用的时候,则页面不会渲染。

语法: 
@BuilderParam name:()=>void   // ()=>void 无返回值的箭头函数
格式:
1.定义一个UI渲染入口@Entry
2.定义一个自定义构建函数@Builder和自定义组件@component
3.定义一个插槽@BuilderParam


第一步:
@Entry
@Component
struct PageName{

@Builder
 getContentParam(str:string){
    Column(){
      Text(str)
        .backgroundColor(Color.Pink)
    }
  }
  
	build(){
		Column(){
			// 调用子组件
			// 方式一 : 尾随闭包传递 仅适用于定义了一个@BuilderParam 
			Card(){
				this.getContentParam("这里是卡槽传值1") 
        		this.getContentParam("这里是卡槽传值2")
       			this.getContentParam("一个插槽可以调用多个")
			}
		// 方式二: 多个@BuilderParam 插槽传值方式
		  Card({Content:()=>{
		  this.getContentParam("多个BuilderParam需要这么传值") // 不能一次性调用好几个一样的
		  }})
    
		}.width("100%")
   	 	 .height("100%")
	}
}


第二步:
@Component
struct Card{
  // 定义一个变量传值
  label:string= '自定义组件值'
  // 插槽
  @BuilderParam Content:()=>void  // Content 作为插槽函数
  build(){
    Column(){
      Text("卡片组件这里不是插槽")
      Divider()
      if(this.Content){ // 可以不用加判断,为了防止报错,加入判断
        this.Content()
      }
    }
  }
}

@Styles组件样式重用的封装

@Styles:装饰器不支持参数传递
当定义全局的时候需要使用function ,使用时直接点这个组件就可以
格式:
全局:
@styles funcation fun(){
	.width("100%")
	.height("100%")
}
局部
@Component // 需要注册为组件
@styles fun(){
	.width("100%")
	.height("100%")
}

调用方式:
Text()
	.fun()

@Extend 扩展组件样式

仅支持在本文件内使用
格式: UIComponentName 代表:TEXT,Button,...等组件
@Extend(UIComponentName) function functionName(size:number,width:string|number){ // 可以传参数
.fontSize(size)
.width(width??"100%") // ??:当不传值则默认
.fun()  // 可以调用使用@styles装饰器封装的样式
}

调用:
Text()
	.functionName(20) // 有参数需要传值

stateStyles多态样式

stateStyles 是属性方法,可以根据UI内部状态来设置样式,类似于css伪类,但语法不同。ArkUI提供以
下四种状态:
focused:获焦态。
normal:正常态。
pressed:按压态。
disabled:不可用态。

**normal 和 disabled 都存在时 disabled不会好用一般增加变量通过 normal 实现效果

例:
@Entry
@Component
struct StateStylesSample {
build() {
Column() {
Button('Button1')
.stateStyles({
focused: {
.backgroundColor(Color.Pink)
},
pressed: {
.backgroundColor(Color.Black)
},
normal: {
.backgroundColor(Color.Red)
}
})
.margin(20)
Button('Button2')
.stateStyles({
focused: {
.backgroundColor(Color.Pink)
},
pressed: {
.backgroundColor(Color.Black)
},
normal: {
.backgroundColor(Color.Red)
}
})
}.margin('30%')
}
}

Flax弹性布局

语法使用和ROW和Column一致,里面增加包含了方向的排列方式
/**
     * 当超出100%后默认压缩,不会自己换行
     * Wrap:换行
     * NoWrap:不换行
     * WrapReverse: 换行反转
     */
 Flex({wrap: FlexWrap.WrapReverse }) { } // 默认Row
 Flex({ direction: FlexDirection.Column, wrap: FlexWrap.WrapReverse }) { }
也存在:主轴justifyContent,和交叉轴ItemAlign的对齐方式
 Flex({ direction: FlexDirection.Column, wrap: FlexWrap.WrapReverse ,justifyContent:FlexAlign.____,alignItems:ItemAlign.___ }) { }

position()绝对定位

作用:控制组件位置,可以实现层叠效果
特点: 
1. 参照 父组件左上角 进行偏移 
2. 绝对定位后的组件 不再占用自身原有位置
position({x:num,y:num})

offset()偏移

属性:offset()
参数: {x: 水平偏移量, y: 垂直偏移量}
格式:
.offset({
x: 100,
y: -30
})
相对定位特点:
1. 相对自身左上角进行偏移
2. 相对定位后的组件仍然占用自身原有位置

Z序控制 : zIndex(数字)

定位后的组件,默认后定义的组件在最上面显示,可以通过 zIndex 属性调整显示层
级
属性: zIndex(数字)
特点:取值为整数数字,取值越大,显示层级越高

例:
// Z 轴显示顺序,取值越大,显示层级越高
.zIndex(1)

ForEache用法、数组

forEach(arr数组,()=>{
//业务
}) 

扩展特殊用法:
 let mouth: string[] = Array.from(Array(12), (v, i) => { // 定义一个长度的空数组
    return (i + 1).toString() // 根据下标进行返回 若长度不足2位,则使用0填充
  })
  //  当只有数字受限制语法时,可以进行填充
 let mouth: string[] =  new Array(5).fill('') // 填充空字符串

LazyForEach(懒加载)用法、数组

思路: 1.首先创建对象并实现IDataSource 接口
2.创建变量,变为LazyForEach所接受的类型
3.使用LazyForEach组件

举例:
1.首先创建对象并实现IDataSource 接口

// 将数据修改为懒加载
export class MyVideoDataRescuer implements IDataSource {
  private dataArray: VideoItem[]
  constructor(dataArray: VideoItem[]) {
    this.dataArray = dataArray
  }
  totalCount(): number {
    return this.dataArray.length
  }
  getData(index: number): VideoItem {
    return this.dataArray[index]
  }

  // 后面为修改变更使用.参考官网
  registerDataChangeListener(listener: DataChangeListener): void {
  }
  unregisterDataChangeListener(listener: DataChangeListener): void {
  }
}

2.创建变量,变为LazyForEach所接受的类型

  @State tableList: VideoItem[] = allData
  // 创建的对象
  bannerList = new MyVideoDataRescuer(this.tableList)

3.使用LazyForEach组件

LazyForEach(this.bannerList, (item: VideoItem, index: number) => {
              // VideoCom({ item: item }) 组件或者渲染UI
})

Stack()堆叠布局

层叠布局具有较强的页面层叠、位置定位能力,其使用场景有广告、卡片层叠效果等。
并且可以设置对齐方式

例:
Column(){
Stack({alignContent: Alignment.____  }) { // 设置对齐方式
// 可包含多个组件,并可以对某一个组件设置 zIndex() 控制
Column()
Button('button')
}

Grid()网格布局

需要与子组件GridItem(){}连用,GridItem里面只能包含一个组件间,若想有多个则进行Row()或者Column()包装起来,如:计算机的排列
属性:
1. rowsTemplate和columnsTemplate 是设置排列方式的,作用于Grid(){}组件上
属性值是一个由多个空格和 数字 + fr 间隔拼接的字符串,fr 的个数即网格布局的行或列数,fr 前面的数值大小,用于计
算该行或列在网格布局宽度上的占比,最终决定该行或列的宽度。

***特殊:当设置的时候仅设置一个,并且页面展示不够的时候,可以实现滚动效果,组件自带的功能

格式:
Grid() {
...
}
.rowsTemplate('1fr 1fr 1fr')
.columnsTemplate('1fr 2fr 1fr')


2..columnsGap 和rowsGap 行列间距,等同于设置 column({speac:30})类似,各组件之间的间距为多少
格式:
Grid(){}
.columnsGap(10)
.rowsGap(15)

3.子组件网格合并:
	GridItem() {
Text(key)
...
}
.rowStart(5) // 从第几行开始
.rowEnd(6) // 至第几行结束
或者
.ColumnStart(5) // 从第几行开始
.ColumnEnd(6) // 至第几行结束

六、UI的渲染控制

Math对象

Math 是一个内置对象,它拥有一些数学常数属性和数学函数方法, Math 用于
Number 类型数据的处理
	Math.random() // 获取随机数 [0,1) 可以取到0但是取不到1
		例: 
		// 0-10 之间的随机 整数
		console.log('Math对象', Math.floor(Math.random() * 11))
		
	Math.ceil() // 向上取整 也称天花板函数
	Math.floor() // 向下取整 也称地板函数
	// 4-12 之间的随机 整数
	// Math.floor(Math.random() * (差值 + 1) + 最小值)
	console.log('Math对象', Math.floor(Math.random() * 9 + 4))

If(){}else{}判断

一般用在子组件判断显示和状态判断,这个比较熟悉。

ForEach()循环判断

格式:
ForEach(
arr: Array, // 数组
itemGenerator: (item: any, index: number) => void, // 组件生成函数
keyGenerator?: (item: any, index: number) => {return string} // 键值生成函数 ,显示规则生成函数,需要reture string
)

七、简单容器组件使用

7.1 通用属性

linearGradient()颜色渐变效果 :线性渐变==线性

####线性渐变
格式: .lineearGradient({
		angle?: 线性渐变的起始角度,
		direction?: 线性渐变的方向,
		colors: [[颜色1, 颜色1所处位置], [颜色2, 颜色2所处位置],......],
		repeating?: 是否重复着色
		})
例:  
	Text('渐变颜色')
		.width("100%")
        .height(30)
		.linearGradient({ // 渐变颜色效果
		angle:49,  //不常用 :线性渐变的起始角度。0点方向顺时针旋转为正向角度,默认值:180 当使用这个direction属性不生效 
          direction: GradientDirection.___, // 方向 Right:右侧: left:左侧及其他常用方位
          colors: [["颜色", number值颜色所处位置], ["另一个颜色", 颜色所处位置],......] // 从哪个方向渐变为另一个颜色
        })

radialGradient()颜色渐变效果 :径向渐变== 圆形

	格式: radialGradient(
			center: 径向渐变的中心点坐标,
			radius: 径向渐变的半径,
			colors: [[颜色1, 颜色1所处位置], [颜色2, 颜色2所处位置],......],
			repeating?: 是否重复着色
			)
	例:
		Text("径向圆形")
		.width(100)
		.height(100)
		.radialGradient({
			center:[50,50], // 径向渐变的中心点坐标  当前长度的一半(行,列),
			radius: 50 // 半径
         	 colors: [["#f00", 0], ["#ff0", 0.7],......
		})
		.borderRadius(50) // 文本圆角

shadow()阴影效果

格式: shadow(
		{
		radius: 模糊半径,
		color ?: 阴影颜色
		offset?: x轴偏移
		offsetY?: Y轴偏移
		}
		)

例:
	Text("阴影")
        .width(100)
        .height(100)
        .margin(20)
        .show({ // 阴影组件及属性
	         radius: 80, // 圆角
	          color: "#ffd90d0d", // 颜色
	          offsetX: 100, // 左偏移
	          offsetY: 50 // 下偏移
			})

animation动画

可以结合伪类stateStyles 进行结合使用
Text("动画")
        .fontSize(40)
        .backgroundColor(Color.Pink)
        .width("100%")
        .height("100")
		.stateStyles({
			pressed:{.height(150)}
			})
		.animation({
			duration: 3*1000 // 多久执行完
			curve: curves.springMotin(), // 缓和的速度曲线,默认:Curve.Linear
			delay: 1*1000, //延时多长时间执行
			iterations: -1, // 无线动画次数 默认1次,当为-1为无限次,0无动画效果
			onFinish:()=>{
			// 动画完成执行的业务
			}
		})

图形变换

用于对组件进行平移translate、旋转rotate、缩放scale、矩阵变换等操作。
结合着伪类stateStyles使用,主要是变化效果
translate() 平移
格式:
	.translate({x?: X轴移动距离, y?: Y轴移动距离, z?: Z轴移动距离})
例:
	Text("移动动画")
        .width(100)
        .height(100)
        .backgroundColor(Color.Pink)
          .stateStyles({
            normal:{ // 正常
              .translate({x:0})
            },
            pressed:{ // 按压
              .translate({ y: 100, x: 0, z: 300 })
            }
          })
        .animation({ // 动画
          duration:3*100,
          curve: curves.springMotion(), // 缓和的速度曲线
        })
scale() 缩放
	格式: .scale( {x?: X轴缩放比例, y?: Y轴缩放比例, z?: Z轴缩放比例, centerX?: Y轴中心
点坐标, centerY? Y轴中心点坐标}):
	Image($r("app.media.icon"))
        .width(200)
        .animation({
          curve: curves.springMotion()
        })
        .stateStyles({
          normal: {
            .scale({ x: 1, y: 1 })
          },
          pressed: {
            .scale({ x: 0.5, y: 0.5 }) // 原比例缩放
          }
        })
rotate() 旋转
格式: .rotate({angle: 旋转角度, centerX?: Y轴中心点坐标, centerY? Y轴中心点坐标})
Text("旋转文字")
        .fontSize(40)
        .width("100")
        .height(100)
        .backgroundColor(Color.Pink)
        .textAlign(TextAlign.Center)
        .stateStyles({
          normal: {
            .rotate({ angle: 0 }) // 旋转角度
          },
          pressed: {
            .rotate({ angle: 90,x:5,y:5 }) // 旋转角度,默认顺时针
          }
        })

7.2 List列表

基本使用

List 组件主轴默认是垂直方向,即默认情况下不需要手动设置 List方 向,就可以构建
	一个垂直滚动列表。 若设置水平方向如下:
	格式:
	 	// 当使用滚动条时: List({ scroller: this.scroller,initialIndex:0 }) { //初始化滚动
		List(){}
		.listDirection(Axis.Horizontal) // 水平方向 相当于设置主轴, 不设置默认垂直方向
		.alignlistItem(ListItemAligin.Center) // 设置交叉轴
		
	list组件中包含:ListItem 和 ListItemGroup 子组件,其中 使用ListItem 组件中只能存在一个组件

	***List的子组件必须是ListItemGroup或ListItem,ListItem和ListItemGroup必须配合List来使用。


格式: 
 默认垂直:
	List(){
		ListItem() {
			Text("") // 只能有一个组件,若需要存在多个,可以使用colum()或者Row()其他组件进行套起来
		}
	}
	
水平:
	List(){}
		.listDirection(Axis.Horizontal) // 水平方向 相当于设置主轴, 不设置默认垂直方向
		.alignlistItem(ListItemAligin.Center) // 设置交叉轴

divider分割线属性

分割线: 作用域List(){}组件上
例:
	List(){}
	.divider({
		strokwidth:1 ,// 分割线宽度
		startMargin:60, // 开始位置
		endMargin:10, // 结束距离
		color:Color.Pick // 颜色 
	})
	

Badge列表标记

Badge列表添加标记: 作用于List显示的某个组件之上。
例:
	List() {
      ForEach(this.contact, (item: Contact, index: number) => {
        ListItem() {
          Row() {
            // 图片
            if (this.contact.length - 1 == index) {
              Badge({  //** 判断为那个列表添加标记
                count: 1,  // 标记显示数量,只能为number类型,当超过100则显示99+
                position: BadgePosition.RightTop, // 显示位置
                style: { badgeSize: 20, badgeColor: Color.Red } // 标记的大小和颜色
              }) {
                Image(item.icon).width(50)
              }
              .margin(10)
            } else {
              Image(item.icon).width(50).margin(10)
            }
            // 文本
            Text(item.name)
          }.width("100%")

        }
      })
    }

scrollBar滚动条

scrollBar:作用于List()组件之上
格式:
	List(){}
	.scrollBar(Barstate.Auto) // 是否显示滚动条 on 开 off关 auto 自适应滚动显示

ListItemGroup分组列表

如:手机联系人页面,实现分组和快速定位的功能
格式:

数据格式: {title: 'A', data:[]}

build() {
List() {
ListItemGroup({ header: this.itemHead('A') }) {  // 需要自己分组后才会展示正常
// 循环渲染分组A的ListItem 对应data[] 数据
...
}
...
ListItemGroup({ header: this.itemHead('B') }) {
// 循环渲染分组B的ListItem
...
}
}
}

Scroller滚动位置控制

Scroller的使用需要先创建这个对象, 作用于List()组件。
  listScroller: Scroller = new Scroller()
  在使用的时候调用 this.listScroller.scrollToIndex(0) // 数组的下标,用于回到那个位置 0:代表置顶、头部
使用的是否可能会使用到Stack()堆叠布局,可以实现在List列表层级上显示

格式:

提供数据格式: {title: 'A', data:[]}

1.创建Scroller滚动条对象
listScroller:Scroller =new Scroller()

2.渲染UI
build(){
	Stack({alignContent: Alignment.BottomEnd}){ // 堆叠布局,设置对齐方式,这里右下
		List({scroller:this.listScroller,listScroller?: 0}){ // 通过将listScroller用于初始化List组件的scroller参数,完成listScroller与列表的绑定。在需要跳转的位置指定scrollToIndex的参数为0,表示返回列表顶部。
		forEach(ArrArrs,(itemArr)=>{
			ListItemGroup({heard: 这是一个自定义函数,见:itemHeader例子}){
					forEach(itemArr.arr,(item)=>{
						.......
					})	
				}
			})
		}.width("100%")
		.onScrollIndex((start:number,end:number)=>{
			// 可以获取数组的下标, 可以获取控制AlphabetIndexer的响应控制,见:AlphabetIndexer响应滚动控制内容
		})	

		Button("顶部")
		.onClick(()=>{
3.变更控制
				this.listScroller.scrollToIndex(0) // 回到顶部
		})
	}
}


@Builder function itemHeader(msg: string) {
  Text(msg)
    .fontSize(20)
    .backgroundColor(Color.Green)
    .width("100%")
    .padding(5)
}

AlphabetIndexer响应滚动控制

联系人右侧的字母

	需要结合Stack堆叠布局进行使用
	格式:
	listScroller:Scroller = new Scroller()
	build(){
	Stack(){
		List({scroller:this.listScroller,listScroller?: 0}){} // 列表数据 **必须设置属性用于响应
		AlphabetIndexer({arrayValue: arr[]字符串数组数据,selected: 默认值,数组下标}){ //响应滚动控制组件  ,selected 可以根据onScrollIndex属性设置动态默认值
		.itemSize(30) // 数组各之间的间距
		.font({size:20}) // 字体大小
		.selected(动态获取下标数据)// 当设置选中,则组件中使用的	selected不会生效,一般使用组件中的,动态获取就可以
		.selectedColor(Color.____) // 选中的颜色
		.usingPopup(true) // 电锯选中后,当前字体会有一个弹出框,相当于放大
		.onSelect((index:number)=>{
			// 选中后显示的数组下标,可以控制页面列表信息显示对应信息
          	this.listScroller.scrollToIndex(index)
		})
		}
	}	
}
	

swipeAction列表事件,左右滑动

swipeAction属性,作用于ListItem()组件接收的是个自定义函数,用于显示左右滑动显示的功能,比如:删除

格式:
	ListItem(){}
	.swipeAction({end: this.itemEnd(下标:number)})  // 自定义函数格式


@Builder itemEnd(index:number){
    Button({type:ButtonType.Circle}){
      Image($r("app.media.delete"))
        .width(25)
        .height(25)
        .fillColor(Color.Red)
    }
    .onClick(()=>{
      // 相关业务处理
    })

  }

7.3 滚动Scroll、Scorrer

Scroll组件

 Scroll 默认竖着滚动,当数据页面超过设置的高则才会生效
格式: Scroll(){}
.scrollable(ScrollDirection.____)  // Vertical:默认竖着    Horizontal:水平滚动  
.scrollbar(BarState.____) // On  off  auto 按需显示, 滚动条关闭显示不会影响滚动
.scrollBarColor(Color.Green) // 设置滚动条颜色
.scrollBarWidth(20) // 设置滚动条宽度
.onScroll((x,y)=>{}) // 获取实时滚动条位置
.onScrollEdge(()=>{}) // 滚动结束触发
.onScrollStop(()=>{}) // 滚动暂停触发
.onScrollStart(()=>{}) // 滚动开始触发

Scorrer控制器

需要重新创建对象:
	scroller: Scroller = new Scroller()
结合滚动组件的用法格式: 
	Scroll({this.scroller}){}
		
滚动控制属性:
	scroller: Scroller = new Scroller()
	this.scroller.scrollTo({xOffset:0,yOffset:700}) // 滚动到某个位置
	this.scroller.scrollTo({xOffset:0,yOffset:0}) // 顶部
	this.scroll.scrollEdge(Edge.Bottom) //跳转到边界位置 上中下
	this.scroll.scrollPage({next: boolean}) // true:跳转下一页 false:跳转上一页

八、Swiper轮播组件

组件格式: Swiper(){} // 使用和滚动控制类似
SwiperController // 导航控制器

步骤:
1.创建导航控制器:swiperController:SwiperController = new SwiperController()
	属性: 
		.showNext() // 切换下一个图片
		.showPrevious() // 切换上一个图片
2.创建组件: 
	Swiper(this.swiperController) { // 用于后面的其他功能
		forEach(Array,(item:object,index:number)=>{
		 // UI
		})
	} // swiper的属性
	.autoPlay(true) // 是否轮播 true:轮播 false: 不轮播
	.loop(true) // 播完时候回来,等于循环
	.interval(3*1000) // 多久切换一次
	.indicator(true) // 是否显示导航条,默认显示
	.index(1) // 默认显示哪一个数组下标
	.indicatorStyle({ // 导航条属性
		bottom:10,
		color: ,  
		selectColor:  // 选中的颜色 
	})
	.onChange((index: number) => { // 当进行轮播时,获取当前的Index
      // this.curIndex = index
    })

九、Tabs组件

tabs组件中需要使用 TabContent()和tabBar() 子组件。

格式:
tabs({barPostition:BarPosition.Start}){ //若不设置则默认在上面, Start:上面, End:下面。
// 若设置左侧或者右侧需要增加一个 .vertical(true) 结果: Start + true= 左侧  End + true = 右侧
	TextContent(){
		Text("文章内容")
	}
	.tabBar("首页") // 可以是文本也可以是自定义函数或者组件
}
.vertical(true) //设置首页在左侧或者右侧使用  结果: Start + true= 左侧  End + true = 右侧
.barWidth(100) // 标题的宽度
.barHeight(100) //标题的高度
.barMode(BarMode.Scrollable) //默认值:Fixed。  若导航太多时,可以设置为滚动,不设置显示不开,会显示成“.”

十、Navigation分栏、标题栏、工具栏,导航栏组件

Navigation():主页面组件,在内容区可以使用NavRouter()实现导航栏功能,其中子组件导航栏内容需要有NavDestination()进行渲染。
等级:Navigation(主组件) -->NavRouter(主组件内容)-->NavDestination(子组件内容)

格式:
Navigation(){
Text("主组件")
	NavRouter() {
		Text("导航栏")
			NavDestination(){
				Cloum(){Text("点击导航显示的内容")}
			}
			.title("点击的小标题")
	}
}
.title("主标题")
.mode(NavigationMode.Auto) // 不设置默认Stack(覆盖当前的页面), Split:将当前页面进行分栏,主题一半,内容一半
.titleMode(NavigationTitleMode.___) // 看主页面的间距发生变化了
.menus( // 菜单栏,缩略部分不显示图片 显示在上部
[{value: '菜单栏名称',icon: '字符串格式的图片,可以放在page下或者远程',action:()=>{
  // 当点击处理的事件
}}])
.toolBar(
{
item:[{value:'工具栏名称',icon:'图片',action:()=>{
 //当点击处理的事件
 }}]
})

十一、TextPicker文本选择器

格式:
TextPicker({
rang:arr数组,
selected:默认值,写数组下标
value: 默认值,写内容非下标
})
.onchange((val,index)=>{})

十二、TextPickerDialog弹框

TextPickerDialog.show({
range:[“-1”, “0”, “1”, “2”, “3”],
selected:1,
onAccept:(val:TextPickerResult)=>{},
onChange:(res:TextPickerResult)=>{res.value+res.index},
onCancel:()=>{}
})

十三、TimePicker选择器

TimePicker({
selected:new Date(), // 默认
})
.useMilitaryTime(true) // 按照24小时显示
.onchang((val:TimePickerResult)=>{
// 接收的参数是24小时,和useMilitaryTime无关
promptAction.showToast({ message: '' + val.hour + ":" + val.minute })

})

十四、TimePickerDialog弹框

TimePickerDialog.show({
            useMilitaryTime: true, // 是否开启24小时
            selected: new Date(), // 默认选择
            onAccept: (value: TimePickerResult) => {
              promptAction.showToast({ message: "确认" + value.minute })
            },
            onCancel: () => {
              promptAction.showToast({ message: "确认" })
            },
            onChange: (value: TimePickerResult) => {
              promptAction.showToast({ message: "确认" + value.minute })
            }
          })

十五、DatePicker选择器

DatePicker({
start:new Date(), // 开始时间,不设置为1969年
end:new Date(), // 结束时间 ,最大值2100
selected:new Date() // 默认时间
})
.lunar(true) // 是否使用农历
.onchang((value:DatePickResult)=>{
// 打印还是非农历进行输出的
          promptAction.showToast({ message: value.year + "-" + (value.month + 1) + "-" + value.day })
})

十六、DatePickerDialog弹框

	DatePickerDialog.show({
            start: new Date("1997-10-06"), // 设置开始时间
            end: new Date(), // 结束时间
            selected: new Date(), //默认时间
            lunar: true, // 是否开启使用农历日历
            onChange: (val: DatePickerResult) => {
            // 发生变更调用
              promptAction.showToast({ message: "改变" + val.day })
            },
            onAccept: (res: DatePickerResult) => { // 确认调用
              promptAction.showToast({ message: "改变" + res.day })
            },
            onCancel: () => { // 任意点击关闭弹出框调用
            } // 返回
          })

十七、自定义选择器 和 CustomDialog自定义弹框

自定义选择器 还是使用TextPicker实现
自定义弹框:需要创建CustomDialog并自定义构建组件或者函数来完成弹出框内容设计。调用内部的open() 或者close() 进行开启和关闭弹出框
CustomDialog自定义弹框:操作步骤:

	1.创建自定义弹出框对象,并在该对象内传递参数信息,实现弹出框UI的页面:
		dialog: CustomDialogController = new CustomDialogController(
    {
      // 自定义组件 使用@CustomDialog装饰器 和  controller:CustomDialogController
      builder: 'this.组件名称()', //自定义组件或者函数,并可以传入想要的值 
      autoCancel: false, // 是否任意点击取消弹出框
      alignment: DialogAlignment.Center, // 样式
      cancel: () => {
        this.commonDigMessage("点击任意取消")
      },
    }
  )

 	2.创建自定义的组件, ***需要将@Component 替换为 @CustomDialog 并定义一个CustomDialogController属性,才可生效
 
   格式:
   strurt  组件名称{
	 controller: CustomDialogController // 作用可能是关闭弹框使用的
	 build(){}
	}

	3. 在需要用此弹出框是,根据创建的对象进行调用: this.dialog.open()
	4.在关闭时,则在弹出框内调用常见的对象: this.controller.close()

十八、AlertDialog警告弹框

AlertDialog 存在2种重要区分一点击确定框的功能对应的参数不同
扩展: promptAction.showToast({message:'弹出后,会自己消失,短暂停留'})  需要导包
方式1: 仅有一个确定按钮AlertDialogParamWithConfirm

AlertDialog.show({
	message: '你是否喝酒驾车',
	title: '警告提示'
	alignment: DialogAlignment.Top, // 弹框对齐位置
	autoCancel: false, //任意点击自动取消
	autoCancel: false, //任意点击自动取消
	offset: { dx: 0, dy: 100 }, // 位置偏移
	confirm:{
		value: '确定或者取消', // 仅一个
		action:()=>{ 
			// 业务处理
		}
	},
	cencel:()=>{
			// 任意随意点击弹出框消失,执行的业务
	}
})

方式2(建议): 有多个按钮AlertDialogParamWithButtons

AlertDialog.show({
            title: '标题',
            message: "第二种",
            autoCancel: false, // 自动取消
            alignment: DialogAlignment.Bottom,
            offset: { dx: 0, dy: -100 },
            primaryButton: { // 确认按钮
              value: "取消",
              action: () => {
                promptAction.showToast({ message: "取消" })
              }
            },
            secondaryButton: {
              value: "确认",
              action: () => {
                promptAction.showToast({ message: '点击确定' })
              }
            },
            cancel: () => {
              promptAction.showToast({ message: '任意取消' })
            }
          })

十九、ActionSheet列表弹框

ActionSheet.show({
            title: "列表弹出框",
            message: "请选择通知信息",
            alignment: DialogAlignment.Center, // 位置
            autoCancel: true, // 是否任意关闭
            cancel: () => {
              promptAction.showToast({ message: "任意取消" })
            },
            confirm: {
              value: "确定",
              action: () => {
                promptAction.showToast({ message: "确定功能" })
              }
            },
            sheets: [
              { title: "苹果", action: () => {
                promptAction.showToast({ message: "pingguo" })
              } },
              { title: "小脚", action: () => {
                promptAction.showToast({ message: "pingguo" })
              } },

              { title: "apple", action: () => {
                promptAction.showToast({ message: "pingguo" })
              } }
            ]
          })

二十、装饰器传值和监听watch

@State:
只作用于当前组件 使用时需要赋值
@Prop:
父传子,但是子变更不了父 不需要赋值,若赋值则会报错,因为接收父组件值

@Link:
父子互传,但是父值一遍,所有子组件也就变化 不需要赋值,若赋值则会报错,因为接收父组件值
**@Link只能修改被@state修饰的变量。

@privoid  @cusumer :
后代传值 2个装饰器需要结合使用,并且需要定义的变量名和类型保持一致,否则渲染不出来 
// 当时后代传值,不需要在父类种传递参数;当子类,和后代都是用使用,按时按照父子组件对子组件@link进行传值,后代还是使用@Consume,对于提供者需要使用@provide进行装饰

@Observed @ObjectLink :
深层/多层数据监听。其中@Observed作用于对象属性, @ObjectLink作用于封装的多层数据结构。 
使用此注解需要在创建对象时需要new Class() ,否则不生效
//限制: ObjectLink只能在子组件中使用,并且只能传递第二层的数据 如:City不是第一层的User Observed:则就对City类上标记注解

@watch("定义的函数名"):
监听状态管理。//    当初次使用监听不会被调用 @watch("定义的函数") 结合@state使用 如:简单的计算总和

二十一、状态存储

LocalStorage:页面级UI状态存储(局部、全局)

局部:
1.创建对象
export  const res = new LocalStorage({key:{name:"你的名字",id:1} as User}) // 若在其他页面使用需要使用使用 export导出

2.需要在@Entry装饰器添加参数 如:@Entry(res)
3.根据对应的想要获取的参数,使用@LocalStorageProp("key") 或者 @LocalStorageLink("key")进行接收值
如:
@LocalStorageProp("key")
user:User = {} as User // 接收的参数需要默认值
全局: 需要在EntryAbility.ts文件中进行参数传递
1.创建定义的对象:
export  const res = new LocalStorage({key:{name:"你的名字全局",id:1}}) 
2.在onWindowStageCreate()函数中进行传参,找到首页路径位置进行开始传参
windowStage.loadContent('pages/PersistentStoragePage',res(此处定义存储变量名), (err, data) => {})
3.外部使用 LocalStorage.GetShared():
	如:
	// 获取全局
	let res =LocalStorage.GetShared()
	//在注解将变量填入
	@Entry(res)
	//使用注解获取对应的数据,记得赋默认值
	@LocalStorageProp("key") 或者 @LocalStorageLink("key")
  	use:User = {} as User

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

格式:
1.创建AppStorage并赋值:
	AppStorage.SetOrCreate<User>('user', { name: 'appStorage使用', id: 3 }) // key:value格式
	AppStorage.Set<User>("user2",{name:'',id:1})
2.获取key的方法 存在多种方式
	2.1:使用注解 
	@StorageProp("user") 或者 @StorageLink("user")
  	user:User = {name:'',id:0} as User
  	2.2:只能获取无法修改
  	const user: User = AppStorage.Get('user')
  	2.3: 获取后可以赋值
  	const link:SubscribedAbstractProperty<User> = AppStorage.Link('user')
     link.get().id;
     link.get().name;
     link.set({name:'aaa',id:2})
    const prop:SubscribedAbstractProperty<User> = AppStorage.Prop('user')
     prop.get().id;
     prop.get().name;
     prop.set({name:'aa',id:4})

PersistentStorage:持久化存储UI状态

PersistenStorage():可以将状态到磁盘中,每次退出将会记录最终的数据。
底层使用的是AppStorage,用法和AppStorage一致

格式:
1.赋值的全局数据:
	  PersistentStorage.PersistProp("key","保存信息")
2.获取方式:
方式一:
	 @StorageLink("key") 或者 @StorageProp('key')
	 message:string = ''
方式二:
	let key = AppStorage.Get('key')
	使用这种可以结合赋值: AppStorage.SetOrCreate('key',47);

Environment:设备环境查询

应用程序运行的设备的环境参数,以此来作出不同的场景判断,比如多语言,暗黑模式等,需要用到Environment设备环境查询。
如查询系统语言:
Environment.EnvProp('languageCode', 'en'); // 这里面赋值的为初始值
@StorageProp("languageCode") // 一般只会取值,不会修改,赋值的话也是改变系统属性的
lan:string = ''

二十二、手势

使用手势的步骤
	1.绑定手势方法 。 
	存在3钟: 手势方法: 常规:gesture 优先级:priorityGesture 并行:parallelGesture
	2.设置手势类型。
	(TapGesture点触、LongPressGesture长按、PanGesture拖动、PinchGesture捏合、RotationGesture旋转、SwipeGesture滑动  并可以对这些样式进行组合使用使用GestureGroup组件)
	3.绑定对应手势方法 格式:.手势方法(类型,响应方法())

知识点:
一:
	   * 手势方法: 常规:gesture 优先级:priorityGesture 并行:parallelGesture
       * gesture:当父子组件都有绑定,会优先识别子组件手势,各执行各自的,子级优先
       * priorityGesture::当父子组件都有绑定 优先执行父组件,子组件内部的也是使用父组件的手势,父级优先
       * parallelGesture:父子组件同事绑定单击和双击,则只显示单击

二:     
	GestureGroup组合手势的3个类型:
	GestureGroup(GestureMode.______,()=>{//Sequence : 组合顺序识别 ;Parallel:并发识别; Exclusive:互斥只有一个识别,其余的不执行
	
	// 设置手势类型。
	//可以设置的手势:TapGesture点触、LongPressGesture长按、PanGesture拖动、PinchGesture捏合、RotationGesture旋转、SwipeGesture滑动 和GestureGroup组合手势。 其中GestureGroup组合手势可其他的有些区别。
	//使用TapGesture点触的手势进行举例:
	TapGesture((e: GestureEvent)=>{
			// 触发执行的业务,部分需要结合着其他属性来共同实现。如:拖动需要结合、捏合、旋转
	})
	}):
 常用属性:
  		  e.repeat // 是否重复,主要用于longPressGesture手势触发
          e.offsetX // 左右偏移位置
          e.offsetY // 上下偏移位置
          e.angle // 用于RoationGesture: 表示旋转角度
          e.scale // 缩放手势,用于捏合手势PinchGesture ,单位vp
          e.pinchCenterX // 用于捏合手势PinchGesture ,单位vp
          e.pinchCenterY //用于捏合手势PinchGesture ,单位vp
          e.speed //: 滑动手势速度
          e.fingerList // 数组 用于长按和点触的场景
          e.timestamp // 时间戳
          e.target // 对象显示区域的宽高
          e.source // 事件输入设备, unknowm 未知 Mouse: 鼠标 TouchaScreen: 触摸屏
          e.pressure // 按压压力的大小
          e.tiltX // 手写笔夹角
          e.tiltY // 手写笔夹角
          e.sourceTool // 输入事件源

Gesture点击手势

Text("手势")
        .width(100)
        .height(100)
        .backgroundColor(Color.Pink)
        .textAlign(TextAlign.Center)
        .gesture(// 绑定手势
        	// 设置手势类型
          TapGesture({ count: 2,fingers: 2 }) // 默认点击一次 count:次数,repeat:是否重复执行 ,fingers:手指数量。含义:2个手指共点击2次		
          	//响应方法
            .onAction((e: GestureEvent) => {
              // 处理对应的业务
              // promptAction.showToast({ message: e.offsetX + '' })
            })
        )

LongPressGesture长按手势

Text("手势")
        .width(300)
        .height(40)
        .backgroundColor(Color.Pink)
        .textAlign(TextAlign.Center)
        .gesture(
          LongPressGesture({
            duration: 3 * 1000, // duration:按压多长时间执行 3S
            repeat: false, // repeat:是否重复执行事件内容 默认false
            fingers: 1  // 默认一个手指长按 fingers几个手指按压
          })   , 
            .onAction((e: GestureEvent) => {
              promptAction.showToast({ message: e.offsetX + '' })
              console.log(e.offsetX + '')
            })
        )

PanGesture拖动手势

@Component
struct PanGestureDome {
  // 当前位置移动多少
  @State x: number = 0
  @State y: number = 0
  // 改变后的当前位置,每次第二层触发会存在问题,需要记录结束的距离
  @State yx: number = 0
  @State yy: number = 0

  build() {
    Column() {
      Text("拖动")
        .width("100")
        .height("100")
        .backgroundColor(Color.Pink)
        .textAlign(TextAlign.Center)
        .translate({ x: this.x, y: this.y }) // 平移
          // .offset({x:this.x,y:this.y}) // 使用这个有问题
        .gesture(
          PanGesture({ direction: PanDirection.Vertical }) // 设置拖动方向
            .onActionStart((e: GestureEvent) => {
              promptAction.showToast({ message: '开始移动X:' + e.offsetX + ",Y:" + e.offsetY })
            })
            .onActionUpdate((e: GestureEvent) => {
              this.x = e.offsetX + this.yx
              this.y = e.offsetY + this.yy
              promptAction.showToast({ message: '开始移动X:' + e.offsetX + ",Y:" + e.offsetY })
            })
            .onActionEnd((e: GestureEvent) => {
              this.yx = this.x
              this.yy = this.y
              promptAction.showToast({ message: '开始移动X:' + e.offsetX + ",Y:" + e.offsetY })
            })
        )
    }
    .width('100%')
    .height('100%')
  }
}

PinchGesture捏合手势

@Component
struct PinchGestureDome {
  // 当前位置移动多少
  @State x: number = 1
  // 改变后的当前位置,每次第二层触发会存在问题,需要记录结束的距离
  @State yx: number = 1

  build() {
    Column() {
      Text("捏合")
        .width("200")
        .height(200)
        .backgroundColor(Color.Pink)
        .textAlign(TextAlign.Center)
        .border({ width: 2, color: Color.Green })
        .scale({ x: this.x, y: this.x })
        .gesture(
          PinchGesture()
            .onActionStart((e: GestureEvent) => {
              promptAction.showToast({ message: "开始捏合" })
            })
            .onActionUpdate((e: GestureEvent) => {
              promptAction.showToast({ message: e.pinchCenterX + "::" + e.pinchCenterY })
              this.x = e.scale * this.yx
            })
            .onActionEnd(() => {
              this.yx = this.x
            })
        )
    }
    .justifyContent(FlexAlign.Center)
    .alignItems(HorizontalAlign.Center)
    .width('100%')
    .height('100%')
  }
}

RotationGesture旋转手势

@Component
struct RotationGestureDome {
  @State angle: number = 0
  @State Yangle: number = 0

  build() {
    Column() {
      Text("旋转")
        .fontSize(30) // 度数
        .width("100")
        .height("100")
        .backgroundColor(Color.Pink)
        .textAlign(TextAlign.Center)
        .rotate({ angle: this.angle })
        .gesture(
          RotationGesture()
            .onActionUpdate((e: GestureEvent) => {
              this.angle = e.angle + this.Yangle
            })
            .onActionEnd(() => {
              this.Yangle = this.angle
            })
        )
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
    .alignItems(HorizontalAlign.Center)
  }
}

SwipeGesture滑动手势


@Component
struct SwipeGestureDome {
  build() {
    Column() {
      Text("滑动")
        .fontSize(30) // 度数
        .width("100")
        .height("100")
        .backgroundColor(Color.Pink)
        .textAlign(TextAlign.Center)
        .gesture(
          SwipeGesture({ direction: SwipeDirection.All }) //滑动方向
            .onAction((e: GestureEvent) => {

            })
        )
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
    .alignItems(HorizontalAlign.Center)
  }
}

GestureGroup组合手势

@Component
struct GroupDome {
  build() {
    Column() {
      Text("组合")
        .fontSize(30)
        .width("100")
        .height("100")
        .backgroundColor(Color.Pink)
        .textAlign(TextAlign.Center)
        .gesture(
          // GestureGroup 组合手势 ,多个手势使用","分割
          GestureGroup(GestureMode.Exclusive, //Sequence : 组合顺序识别 ;Parallel:并发识别; Exclusive:互斥只有一个识别,其余的不执行
            LongPressGesture() // 长按
              .onAction(() => {
                promptAction.showToast({ message: "组合中的长按" })
              })
            ,
            PanGesture()
              .onActionUpdate(() => {
                promptAction.showToast({ message: "组合中的拖动" })
              })

          )
        )
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
    .alignItems(HorizontalAlign.Center)
  }
}

组合手势案例:(缩放、旋转、拖动)


@Entry
@Component
struct OperatePage {
  // 放大scale
  @State scale1: number = 1
  @State scaleCopy: number = 1

  // 旋转rotate
  @State rotate1: number = 0
  @State rotateCopy: number = 0

  // 拖动translate
  @State x: number = 0
  @State xCopy: number = 0
  @State y: number = 0
  @State yCopy: number = 0

  build() {
    Column() {
      Image($r("app.media.icon"))
        // Text("滑动")
        //   .fontSize(30)
        .width("100")
          // .backgroundColor(Color.Pink)
        .height("100")
        .scale({x:this.scale1})
        .rotate({ angle: this.rotate1 })
        .translate({x:this.x,y:this.y})
        .gesture(
          GestureGroup(GestureMode.Parallel,
            PinchGesture() // 捏合
              .onActionUpdate((e: GestureEvent) => {
                this.scale1 = e.scale * this.scaleCopy
              })
              .onActionEnd(() => {
                this.scaleCopy = this.scale1
              })
            ,
            RotationGesture() // 旋转
              .onActionUpdate((e: GestureEvent) => {
                this.rotate1 = e.angle + this.rotateCopy
              })
              .onActionEnd(() => {
                this.rotateCopy = this.rotate1
              })
            ,
            LongPressGesture() // 长按
              .onAction(() => {
              })
            ,
            PanGesture({ direction: PanDirection.All }) // 拖动
              .onActionUpdate((e:GestureEvent) => {
                this.x = this.xCopy + e.offsetX
                this.y = this.yCopy + e.offsetY
              })
              .onActionEnd(()=>{
                this.xCopy = this.x
                this.yCopy = this.y
              })
          )
        )
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
    .alignItems(HorizontalAlign.Center)
  }
}

二十三、绘制组件

绘制组件包含:Circle圆形、Ellipse椭圆、Line线性、PolyLine折线、Polygon多边形、Path路径绘制、Rect矩形、Shape绘制组件父组件。
其中Shape父组件可以将单一的组件进行结合起来,可以实现类似SVG的效果

Circle圆形

	Stack() {  // 此处使用的堆叠布局
        Text("加载...").zIndex(10) // Z序控制层级,否则此处将会被覆盖
        Circle()
          .width(100)
          .height(100)
          .fill(Color.Red) // 默认黑色 填充颜色
          .fillOpacity(1) // 透明度 0-1
          .stroke(Color.Yellow) // 边框颜色 ,结合边框宽度使用 ,否则没有宽度显示不出来
          .strokeWidth(10) // 边框粗细
          .strokeDashArray([10, 10]) // 齿轮 ,数组里面添加下数值
      }

Ellipse椭圆

Ellipse()
        .width("100")
        .height(80)
        .fill("#fa2") // 填充颜色
        .stroke(Color.Green)// 边框颜色
        .strokeWidth(3)
        .strokeDashArray([10])

Line线性

Line()
        .width(200)
        .height(50)
        .backgroundColor(Color.Green)
        .startPoint([0, 0]) // 开始画线
        .endPoint([45, 45]) // 结束画线
        .stroke(Color.Pink)// 边框颜色
        .strokeWidth(10)
        .strokeLineCap(LineCapStyle.Round) // Round: 和 .borderRadius(25) 一样
        .strokeDashArray([5, 10])//设置边框间隙。
        .strokeDashOffset(20) // 边框绘制起点的偏移量

PolyLine折线

Polyline()
        .width(100)
        .height(100)
        .backgroundColor(Color.Pink)
        .points([[0, 0], [20, 0], [30, 80], [0, 40], [100, 100]]) // [x,y]坐标 可以任意线如圆形
        .stroke(Color.Red) // 边框颜色
        .strokeLineJoin(LineJoinStyle.Round) // 设置边框拐角绘制样式
        .strokeLineCap(LineCapStyle.Round) // 设置边框端点绘制样式

Polygon多边形

Polygon()
        .width(100)
        .height(30)
        .backgroundColor(Color.Yellow)
        .fill(Color.Pink)
        .points([[0, 0], [0, 10], [10, 10], [10, 0]]) // 绘制矩形内的正方形
        .fillOpacity(0.5)
        .stroke(Color.Black)

Path路径绘制

Path()
	.commands() // 属性
	说明:
	/**
	后面跟着的是坐标 数值是像素px,但每个的属性都不一致具体的参考官方文档.
	* M : 在某个位置开始画
    * 小写的字母是基于上一节点的位置进行移动。可以理解为:其中小写的字母代码相对路径,大写字母代表绝对路径
	*/ 
     
    含义及举例: 
			//L : 从那个位置开始画直线
			//mands("M 0 0 L(l) 0 100 (L)l 100 100")
			
		    //垂直线V
		   // mands("M 100 100 H 300 H 300") // H 绝对位置 画水平线
		   // mands("M 00 00 h 300 h 300") // h 相对位置  画水平线

          // 垂直线V
          // mands('M 0 0 V 100 V 300 ')
          // mands('M 0 0 v 100 v 300')

          // 弯曲 C
          // mands('M 0 0 C 200 50 0  300 150 400 C 20 200 10 300 40 300' )  // 每 6个一组
          // mands('M 0 0 c 200 50 0  300 150 400 c 20 200 10 300 40 300' )  // 每 6个一组

          // 平滑弯曲 S
          // mands('M 0 0 S 100 200 0 300 S 200 100  300 300')
          // mands('M 0 0 s 100 200 0 300 s 200 100  300 300')

          // 曲线Q
          // mands('M 0 0 Q 100 200 0 300 Q 200 100  300 300')
          // mands('M 0 0 q 100 200 0 300 q 200 100  300 300')


          // T
          // mands('M 0 0 Q 100 200 0 300 Q 200 100  300 300')
          // mands('M 0 0 q 100 200 0 300 q 200 100  300 300')

          // A 椭圆弧
         //mands('M 0 0  A 100 100  0 0 200 200 ')
         
         // Z 将终点和起点加入闭合
         //mands("M0 300 S100 0 240 300 Z")

Rect矩形

Rect() // 默认黑色
        .width("100")
        .height(100)
        .fill(Color.Blue) // 填充
        .fillOpacity(0.5)// 透明度
        .stroke(Color.Red)
        .strokeWidth(3)
          // .radiusWidth(20)
          // .radiusHeight(50)
        .radius([[50, 50], [50, 50], [10, 10], [10, 10]]) // 对每个角设置圆角
        .strokeDashArray([10, 3, 1]) //设置边框间隙。

Shape父组件

 依验证码生成为例(此处可以拿来即用):
 @Entry
@Component
struct TaskWork {
  /**
   * 1.定义数组 数组和字母
   * 2.定义2个接收数组  验证数组 和 颜色数组
   * 3.使用 Shape: 绘制组件  Rect: 矩形 Text 文本 Path:路径
   * */
  @State data: (string | number)[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
  @State yanZheng: (string | number)[] = []
  @State colors: string[] = []
  @State Lines:string[] = []
  height1: number = 100
  width1: number = 200

  randomNumber(num:number) {
    return Math.floor(Math.random()*num) // 随机数+地板函数
  }

  randomLine() {
    // "M 0 0 L 0 0 "
    return "M "+ this.randomNumber(this.width1)*3+" "+this.randomNumber(this.height1)*3 + "L"+ this.randomNumber(this.width1)*3+" "+this.randomNumber(this.height1)*3
  }

  randomRotate(){
    const  res = this.randomNumber(90)
    if (res>45) {
      return -(res-45)
    } else {
      return res
    }
  }

  randomColor(){
    let color = ''
    for (let index = 0; index < 3; index++) {
      color = color+','+Math.floor(Math.random()*255)
    }
    return "rgb("+color.replace(',','')+")"
  }

  // 初始化数据,组件打开时执行
  aboutToAppear() {
    this.colors= []
    this.yanZheng = []
    this.Lines = []
    for (let index = 0; index < 4; index++) {
      this.yanZheng.push(this.data[this.randomNumber(this.data.length)])
    }
    for (let index = 0; index < 9; index++) {
      this.colors.push(this.randomColor())
      this.Lines.push(this.randomLine())
    }
  }

  build() {
    Column() {
      Shape() {
        Rect() // 矩形
          .width(this.width1)
          .height(this.height1)
        Row({ space: 0 }) {
          ForEach(this.yanZheng, (item: number | string, index: number) => {
            Text(item.toString()) // 文本
              .fontSize(40)
              .rotate({angle:this.randomRotate()})
              .fontColor(this.colors[index])
          })
        }
        .width(this.width1)
        .height(this.height1)
        .justifyContent(FlexAlign.SpaceEvenly)
        .alignItems(VerticalAlign.Center)

        ForEach(this.Lines, (line:string, index: number) => {
          Path() // 路径绘制
            .commands(line)
            .stroke(this.colors[index])
            .strokeWidth(2)
        })
      }
      .width(this.width1)
      .height(this.height1)
      .fill(Color.Pink)
      .opacity(0.5)
      .onClick(() => {
        this.aboutToAppear()
      })
    }
    .width('100%')
    .margin({top:10})
  }
}

二十四、Canvas画布组件

格式:
1.创建对象
 settings: RenderingContextSettings = new RenderingContextSettings(true)
  context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)
2.创建组件并绑定对象
	Canvas(this.context)
        .onReady(()=>{ // 特有属性
3.执行业务方法 调用 this.context中的属性
})

this.context中的属性:
1.this.context.save() :保存: 不加就会导致图片绘制一动全动,根据情况加入
2.this.context.translate()平移
3.this.context.rotate()旋转
4.this.context.drawImage() // 画图 ,接收ImageBitmap 对象 如:new ImageBitmap(src),起始点坐标,大小宽高)
5.this.context.restore() 回复状态

二十五、动画

animation动画

那个位置需要使用在哪位置添加
格式:
.animation({
          duration: 5 * 1000, //多久执行完成
          curve: Curve.Linear, // 不添加默认这个类型
          onFinish: () => {
            //动画完成触发
            promptAction.showToast({ message: '执行完成' })
          },
          iterations: 1 // 默认一次,无限循环使用-1
        })

animateTo显示动画

格式:
Button("按钮")
 .onClick(() => {
animateTo({
// 当页面重新渲染则获执行动画效果
   duration: 2 * 1000,
         curve: Curve.Linear,
         onFinish: () => {
           // 执行完成事件
         }
       }, () => {
         // 变更样式属性 宽高
         this.width1 = 300
         this.height1 = 200
       })

})

Navigator转场动画,可以用于路径跳转

Navigator主要实现2个页面的跳转动画效果
格式:
// 类似于ppt的投影图片效果模式
 Navigator({ target: "pages/index", type: NavigationType.Push }) { // 默认淡入淡出
   Image($r("app.media.icon"))
 }

pageTransition页面转场动画效果

pageTransition结合Navigator使用
在build()外部使用,用于动画进入和退出时的效果
格式:
  pageTransition() {
    PageTransitionEnter({ // 进入动画
      duration: 5 * 1000,
      curve: Curve.Ease
    }).onEnter((type: RouteType, progress: number) => {
      // progress  进度条
      this.op = progress
    })
      .opacity(this.op)
      .slide(SlideEffect.Top)  // 控制进入方向

    PageTransitionExit({ // 退出动画
     duration: 2 * 1000,
      curve: Curve.Linear }).onExit((type: RouteType, progress: number) => {
      // progress  进度条
      this.op = 1 - progress
    })
      .opacity(this.op)
      .slide(SlideEffect.Top)
  }

animateTo组件内动画

格式:当重新渲染时加载动画
  @State isShow: boolean = true
  build() {
    Column({ space: 30 }) {
      Button("组件内动画")
        .onClick(() => {
          animateTo({ duration: 3 * 1000, curve: Curve.Linear }, () => {
            this.isShow = !this.isShow
          })
        })
      if (this.isShow) {
        Image($r("app.media.icon"))
          .width("80%")
          .height("80%")
          .transition({
            type: TransitionType.All,
            scale: { x: 0.1, y: 0.1 }, // 缩放初始化
            rotate: { angle: 180 * 10 } // 旋转角度
          })
      }
    }
    .width('100%')
    .height('100%')
  }

sharedTransition共享元素组件

当页面发生跳转,可以看到动画共用的效果,需要多个组件才可以使用
.sharedTransition(
'path',  // 'path':是需要组件id保持一致
{
      duration:3*1000,
      curve:Curve.Linear
    })

motionPath路径动画

格式:
.motionPath({ path: 'Mstart.x start.y L00 200 L500 500 L 500 0 Lend.x end.y',
          from: 1.0, //从哪到哪,没看出来什么区别
          to: 1.0
        })
 
 例:
 @Component
struct MotionPathDome {

  @State isShow:boolean = false
  build() {
    Column() {
      Button("按钮")
        .onClick(() => {
          animateTo({
            duration: 3 * 1000,
            curve: Curve.Linear
          }, () => {
            this.isShow =!this.isShow
          })
        })
      Image($r("app.media.icon"))
        .width(this.isShow?"30%":"10%")
        .height(this.isShow?"30%":"10%")
        .motionPath({ path: 'Mstart.x start.y L00 200 L500 500 L 500 0 Lend.x end.y',
          from: 1.0, //从哪到哪
          to: 1.0
        })
    }
    .width('100%')
    .height('100%')
  }
}

二十六、多媒体

Video视频

定义控制器:
  private controller: VideoController = new VideoController()

Video({
              src: $rawfile('mda-qdr9m6wqyishnfnr.mp4'), //视频的数据源
              previewUri:'图片的数据源' // 视频未播放时的预览图片路径,默认不显示图片。
              currentProgressRate:PlaybackSpeed.Speed_Forward_1_00_X, // 默认
              controller: this.controller // 设置视频控制器,可以控制视频的播放状态。
            })
            .muted(false) // 是否静音。默认值:false 不静音
            .autoPlay(true) // true 自动播放
            .controls(true) // 是否显示原有的控制栏
            .onPrepared((event) => { // 播放之前执行
                this.max = event.duration // 获取视频总时长
              })
              .onUpdate((event) => { // 获取当前指定的长度
                this.current = event.time
              })
  private controller: VideoController = new VideoController()

控制器常见方法:
播放:this.controller.start()
暂停:this.controller.pause()
结束: this.controller.stop()
重播:reset()
是否全屏播放:requestFullscreen(true/false)
设置当前进度:this.controller.setCurrentTime(this.current)

扩展

number.toString().padStart(2, '0') // 比如:当月份的长度不足2位数时, 校验长度是否够2个,否则前面使用0填充

// 随机生成UUID
import util from '@ohos.util';
let uuid:string = util.generateRandomUUID()

@Preview:当为组件时,可以使用注解进行显示预览功能

项目启动注意事项或者检查(**会导致模拟启动不起来等其他情况)

1.确定首页跳转路径: src/main/ets/entryability/EntryAbility.ts 中的windowStage.loadContent('首页url')
2.查看软件图标和名称是否修改: src/main/module.json5 中的  icon 和 label 值
3.当引入网络资源需要权限添加配置: src/main/module.json5 在module添加
		"requestPermissions": [
	      {
	        "name": "ohos.permission.INTERNET"
	      }
	    ],  

规范项目结构

本文标签: 入门基础系统harmonyos