import curves from '@ohos.curves' import { AddFormMenuItem } from '@kit.ArkUI' import { formBindingData } from '@kit.FormKit' import { getCount, IBestToast } from 'basic' @Component export struct MainView { @Prop displayArr: getCount[] = [] columnsTemplate: string = '1fr 1fr' @BuilderParam item: () => void private columnsCount: number = 0 @State private dragItemId: number = -1 @State private scaleItemId: number = -1 @State private offsetX: number = 0 @State private offsetY: number = 0 private dragRefOffsetx: number = 0 private dragRefOffsety: number = 0 private FIX_VP_X: number = 108 private FIX_VP_Y: number = 120 aboutToAppear() { const temArr: number[] = Array.from({ length: 11 }) temArr.forEach((item, index) => { this.displayArr.push({ id: index }) }) this.columnsCount = this.columnsTemplate.split(' ').length } itemMove(index: number, newIndex: number): void { if (!this.isDraggable(newIndex)) { return; } // 创建临时数组 const newNumbers = [...this.displayArr]; const movedItem = newNumbers.splice(index, 1)[0]; // 直接获取数组第一个元素 newNumbers.splice(newIndex, 0, movedItem); this.displayArr = newNumbers; } //向下滑 down(index: number): void { // 指定固定GridItem不响应事件 if (!this.isDraggable(index + this.columnsCount)) { return } this.offsetY -= this.FIX_VP_Y this.dragRefOffsety += this.FIX_VP_Y this.itemMove(index, index + this.columnsCount) } //向下滑(右下角为空) // down2(index: number): void { // if (!this.isDraggable(index + this.columnsCount)) { // return // } // this.offsetY -= this.FIX_VP_Y // this.dragRefOffsety += this.FIX_VP_Y // this.itemMove(index, index + this.columnsCount) // } //向上滑 up(index: number): void { if (!this.isDraggable(index - this.columnsCount)) { return } this.offsetY += this.FIX_VP_Y this.dragRefOffsety -= this.FIX_VP_Y this.itemMove(index, index - this.columnsCount) } //向左滑 left(index: number): void { if (!this.isDraggable(index - 1)) { return } this.offsetX += this.FIX_VP_X this.dragRefOffsetx -= this.FIX_VP_X this.itemMove(index, index - 1) } //向右滑 right(index: number): void { if (!this.isDraggable(index + 1)) { return } this.offsetX -= this.FIX_VP_X this.dragRefOffsetx += this.FIX_VP_X this.itemMove(index, index + 1) } //向右下滑 lowerRight(index: number): void { if (!this.isDraggable(index + this.columnsCount + 1)) { return } this.offsetX -= this.FIX_VP_X this.dragRefOffsetx += this.FIX_VP_X this.offsetY -= this.FIX_VP_Y this.dragRefOffsety += this.FIX_VP_Y this.itemMove(index, index + this.columnsCount + 1) } //向右上滑 upperRight(index: number): void { if (!this.isDraggable(index - this.columnsCount + 1)) { return } this.offsetX -= this.FIX_VP_X this.dragRefOffsetx += this.FIX_VP_X this.offsetY += this.FIX_VP_Y this.dragRefOffsety -= this.FIX_VP_Y this.itemMove(index, index - this.columnsCount + 1) } //向左下滑 lowerLeft(index: number): void { if (!this.isDraggable(index + 2)) { return } this.offsetX += this.FIX_VP_X this.dragRefOffsetx -= this.FIX_VP_X this.offsetY -= this.FIX_VP_Y this.dragRefOffsety += this.FIX_VP_Y this.itemMove(index, index + this.columnsCount - 1) } //向左上滑 upperLeft(index: number): void { if (!this.isDraggable(index - this.columnsCount - 1)) { return } this.offsetX += this.FIX_VP_X this.dragRefOffsetx -= this.FIX_VP_X this.offsetY += this.FIX_VP_Y this.dragRefOffsety -= this.FIX_VP_Y this.itemMove(index, index - this.columnsCount - 1) } isDraggable(index: number): boolean { return index >= 0 && index < this.displayArr.length } build() { Column() { Grid() { ForEach(this.displayArr, (item: getCount, index) => { GridItem() { Text(item + '') .fontSize(16) .width('100%') .height('100%') .bindContextMenu( this.menu_4, ResponseType.LongPress, { placement: Placement.TopLeft, }) .textAlign(TextAlign.Center) .borderRadius(10) .backgroundColor(0xF9CF93) .shadow(this.scaleItemId == item.id ? { radius: 70, color: '#15000000', offsetX: 0, offsetY: 0 } : { radius: 0, color: '#15000000', offsetX: 0, offsetY: 0 }) .animation({ curve: Curve.Sharp, duration: 300 }) // this.item() } .aspectRatio(1) // 指定固定GridItem不响应事件 .hitTestBehavior(this.isDraggable(this.displayArr.indexOf(item)) ? HitTestMode.Default : HitTestMode.None) .scale({ x: this.scaleItemId == item.id ? 1.05 : 1, y: this.scaleItemId == item.id ? 1.05 : 1 }) .zIndex(this.dragItemId === item.id ? 1 : 0) .translate(this.dragItemId === item.id ? { x: this.offsetX, y: this.offsetY } : { x: 0, y: 0 }) .onAreaChange((_, newArea) => { if (index == 0) { this.FIX_VP_X = newArea.width as number this.FIX_VP_Y = newArea.height as number } }) .gesture( // 以下组合手势为顺序识别,当长按手势事件未正常触发时则不会触发拖动手势事件 GestureGroup(GestureMode.Sequence, LongPressGesture({ repeat: true }) .onAction((event?: GestureEvent) => { animateTo({ curve: Curve.Friction, duration: 300 }, () => { this.scaleItemId = item.id }) }) .onActionEnd(() => { animateTo({ curve: Curve.Friction, duration: 300 }, () => { this.scaleItemId = -1 }) }), PanGesture({ fingers: 1, direction: null, distance: 0 }) .onActionStart(() => { this.dragItemId = item.id this.dragRefOffsetx = 0 this.dragRefOffsety = 0 }) .onActionUpdate((event: GestureEvent) => { this.offsetY = event.offsetY - this.dragRefOffsety this.offsetX = event.offsetX - this.dragRefOffsetx let index = this.displayArr.findIndex(item => item.id == this.dragItemId) if (this.offsetY >= this.FIX_VP_Y / 2 && (this.offsetX <= 44 && this.offsetX >= -44) && !this.isLastRow(index)) { //向下滑 this.down(index) } else if (this.offsetY <= -this.FIX_VP_Y / 2 && (this.offsetX <= 44 && this.offsetX >= -44) && !this.isFirstRow(index)) { //向上滑 this.up(index) } else if (this.offsetX >= this.FIX_VP_X / 2 && (this.offsetY <= 50 && this.offsetY >= -50) && !this.isLastColumn(index)) { //向右滑 this.right(index) } else if (this.offsetX <= -this.FIX_VP_X / 2 && (this.offsetY <= 50 && this.offsetY >= -50) && !this.isFirstColumn(index)) { //向左滑 this.left(index) } else if (this.offsetX >= this.FIX_VP_X / 2 && this.offsetY >= this.FIX_VP_Y / 2 && !this.isLastRow(index) && !this.isLastColumn(index)) { //向右下滑 this.lowerRight(index) } else if (this.offsetX >= this.FIX_VP_X / 2 && this.offsetY <= -this.FIX_VP_Y / 2 && !this.isFirstRow(index) && !this.isLastColumn(index)) { //向右上滑 this.upperRight(index) } else if (this.offsetX <= -this.FIX_VP_X / 2 && this.offsetY >= this.FIX_VP_Y / 2 && !this.isLastRow(index) && !this.isFirstColumn(index)) { //向左下滑 this.lowerLeft(index) } else if (this.offsetX <= -this.FIX_VP_X / 2 && this.offsetY <= -this.FIX_VP_Y / 2 && !this.isFirstRow(index) && !this.isFirstColumn(index)) { //向左上滑 this.upperLeft(index) } else if (this.offsetX >= this.FIX_VP_X / 2 && this.offsetY >= this.FIX_VP_Y / 2 && this.isLastRow(index) && this.isFirstColumn(index)) { //右下角为空的情况 this.down(index) } }) .onActionEnd(() => { animateTo({ curve: Curve.Linear, duration: 150 }, () => { // 缩短时间并简化曲线 this.dragItemId = -1; }); }) ) .onCancel(() => { animateTo({ curve: curves.interpolatingSpring(0, 1, 400, 38) }, () => { this.dragItemId = -1; }) animateTo({ curve: curves.interpolatingSpring(14, 1, 170, 17) }, () => { this.scaleItemId = -1 }) }) ) }) } .width('100%') .editMode(true) .columnsGap(20) .rowsGap(20) .scrollBar(BarState.Off) .columnsTemplate(this.columnsTemplate) }.width('100%').height('100%').backgroundColor('#0D182431').padding({ top: 5 }) } @Builder menu_4() { this.basicMenu('card_4', 4, 'fuWidget') } @Builder basicMenu(compId: string, form_dimension: number, form_name: string) { Menu() { AddFormMenuItem( { bundleName: 'com.ytpm.xjlrl', // 包名 abilityName: 'EntryFormAbility', // 模块ability名称 parameters: { 'ohos.extra.param.key.form_dimension': form_dimension, // 卡片尺寸,1代表1*2卡片,2代表2*2卡片,3代表2*4卡片,4代表4*4卡片,7代表6*4卡片,6代表1*1卡片 'ohos.extra.param.key.form_name': form_name, // 卡片名称 'ohos.extra.param.key.module_name': 'entry' // 卡片所属的模块名称 }, }, compId, { formBindingData: formBindingData.createFormBindingData({ data: 'share' }), // formBindingData: formBindingData.createFormBindingData({ data: 'share' }), callback: (error, formId) => { if (!error) { IBestToast.show("添加成功") } }, style: { options: { // startIcon: $r("app.media.icon"), // 菜单图标,可以自己提供。系统默认采用"sys.media.ic_public_add" content: "添加到桌面", // 菜单内容,可以自己提供。默认使用"sys.string.ohos_add_form_to_desktop" // endIcon: $r("app.media.icon") // 菜单图标,可以自己提供 } } } ) } } // 新增辅助方法:检查当前项是否在最后一行 private isLastRow(index: number): boolean { const rowIndex = Math.floor(index / this.columnsCount); const totalRows = Math.ceil(this.displayArr.length / this.columnsCount); return rowIndex === totalRows - 1; } // 检查是否在第一行 private isFirstRow(index: number): boolean { return Math.floor(index / this.columnsCount) === 0; } // 检查是否在最后一列 private isLastColumn(index: number): boolean { return index % this.columnsCount === this.columnsCount - 1; } // 检查是否在第一列 private isFirstColumn(index: number): boolean { return index % this.columnsCount === 0; } }