HarmonyOS 鸿蒙Next开发案例 | 在网格Grid中拖拽交换子组件位置
HarmonyOS 鸿蒙Next开发案例 | 在网格Grid中拖拽交换子组件位置
场景说明
在使用网格Grid的应用中,可以通过拖拽子组件GridItem的方式,交换子组件的显示位置。
效果呈现
本示例的最终效果如下:
运行环境
本例基于以下环境开发,开发者也可以基于其他适配的版本进行开发:
- IDE:DevEco Studio 3.1.1 Release
- SDK:3.1.0(API 9)
实现原理
-
设置Grid的editMode属性为true,使Grid进入编辑模式,从而可以拖拽Grid组件内部GridItem。
-
在Grid的相关拖拽事件中进行拖拽逻辑处理:
- 在onItemDragStart事件中显示拖拽过程中的图片,即被拖拽的GridItem。
- 在onItemDrop事件中根据拖拽前后的位置,完成两个GridItem位置交换的逻辑。
开发步骤
- 构建Grid组件及子组件GridItem,开启Grid组件的editMode属性。
@Entry
@Component
struct Index {
@State numbers: String[] = []
scroller: Scroller = new Scroller()
@State text: string = 'drag'
// 拖拽过程中展示的样式
@Builder pixelMapBuilder() {
Column() {
Text(this.text)
.fontSize(16)
.backgroundColor(0xF9CF93)
.width(80)
.height(80)
.textAlign(TextAlign.Center)
}
}
aboutToAppear() {
for (let i = 1;i <= 15; i++) {
this.numbers.push(i + '')
}
}
// 交换数组中元素位置
changeIndex(index1: number, index2: number) {
[this.numbers[index1], this.numbers[index2]] = [this.numbers[index2], this.numbers[index1]];
}
build() {
Column({ space: 5 }) {
Grid(this.scroller) {
ForEach(this.numbers, (day: string) => {
GridItem() {
Text(day)
.fontSize(16)
.backgroundColor(0xF9CF93)
.width(80)
.height(80)
.textAlign(TextAlign.Center)
.onTouch((event: TouchEvent) => {
if (event.type === TouchType.Down) {
this.text = day
}
})
}
})
}
.columnsTemplate('1fr 1fr 1fr')
.columnsGap(10)
.rowsGap(10)
.onScrollIndex((first: number) => {
console.info(first.toString())
})
.width('90%')
.backgroundColor(0xFAEEE0)
.height('100%')
// 设置Grid是否进入编辑模式,进入编辑模式可以拖拽Grid组件内部GridItem
.editMode(true)
// 第一次拖拽此事件绑定的组件时,触发回调
.onItemDragStart((event: ItemDragInfo, itemIndex: number) => {
// 设置拖拽过程中显示的图片
return this.pixelMapBuilder()
})
// 绑定此事件的组件可作为拖拽释放目标,当在本组件范围内停止拖拽行为时,触发回调
// itemIndex为拖拽起始位置,insertIndex为拖拽插入位置
.onItemDrop((event: ItemDragInfo, itemIndex: number, insertIndex: number, isSuccess: boolean) => {
// 不支持拖拽到已有内容以外的位置
if(insertIndex < this.numbers.length){
this.changeIndex(itemIndex, insertIndex)
}
})
}.width('100%').margin({ top: 5 })
}
}
-
当长按GridItem时触发onItemDragStart事件,在该事件中提供被拖拽GridItem的显示逻辑。
-
停止拖拽时触发onItemDrop事件,在该事件中完成两个GridItem位置交换的逻辑。
更多关于HarmonyOS 鸿蒙Next开发案例 | 在网格Grid中拖拽交换子组件位置的实战教程也可以访问 https://www.itying.com/category-93-b0.html
拖拽太生硬了,怎么添加动画效果?类似于下图会自动回填。
更多关于HarmonyOS 鸿蒙Next开发案例 | 在网格Grid中拖拽交换子组件位置的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
这种移位动效和抖动动效如何实现?试了属性动画貌似没移位效果,
有要学HarmonyOS AI的同学吗,联系我:https://www.itying.com/goods-1206.html
您好,这个有实现方案吗?
华为开发提供demo,测试可以。开发者您好,请参考以下demo:
import curves from '@ohos.curves';
@Entry
@Component
struct Index {
@State numbers: String[] = ["娱乐", "关注", "热榜", "航天", "动漫", "宠物", "保险", "NBA", "汽车", "财经", "体育", "女性", "搞笑", "军事", "有料", "北京", "深度", "5G"]
scroller: Scroller = new Scroller()
@State text: string = 'drag'
@State isShowDelete: boolean = false
@State isEdit: boolean = false
@State rotateZ: number = 0;
private stopJump() {
animateTo({
delay: 0,
tempo: 5,
duration: 0,
curve: Curve.Smooth,
playMode: PlayMode.Normal,
iterations: 1
},
() => {
this.rotateZ = 0;
})
}
//抖动的动画
private jumpWithSpeed(speed: number) {
if (this.isEdit) {
this.rotateZ = -1;
animateTo({
delay: 0, //延时播放
tempo: speed, //动画的播放速度,值越大动画播放越快
duration: 1000, //动画持续的时间
curve: Curve.Smooth, //动画曲线
playMode: PlayMode.Normal, //动画播放模式
iterations: -1
},
() => {
this.rotateZ = 1;
})
} else {
this.stopJump()
}
}
//拖拽过程中展示的样式
@Builder
pixelMapBuilder() {
Column() {
Text(this.text)
.fontSize(16)
.backgroundColor(0xF9CF93)
.width(80)
.height(40)
.textAlign(TextAlign.Center)
.borderRadius(20)
.borderWidth(2)
.borderColor(Color.Orange)
}
//改变数组中元素位置
changeIndex(index1: number, index2: number) {
this.numbers.splice(index2, 0, this.numbers.splice(index1, 1)[0])
}
build() {
Column({ space: 5 }) {
Row({ space: 30 }) {
Text("我的频道")
.fontSize(20)
Text(this.isEdit ? "长按拖动调整顺序" : "点击编辑按钮进入编辑")
.fontColor(Color.Gray)
Button() {
Text(this.isEdit ? "完成" : "编辑")
.fontColor(this.isEdit ? Color.Black : 0xF9CF93)
}.width(80)
.height(30)
.backgroundColor(Color.White)
.onClick(() => {
this.isEdit = !this.isEdit
this.jumpWithSpeed(5)
})
}.padding({ left: 15 })
Grid(this.scroller) {
ForEach(this.numbers, (day: string, index: number) => {
GridItem() {
Stack({ alignContent: Alignment.TopEnd }) {
Text(day)
.borderRadius(20)
.borderWidth(2)
.borderColor(Color.Orange)
.fontSize(16)
.backgroundColor(0xF9CF93)
.width(80)
.height(40)
.textAlign(TextAlign.Center)
.onTouch((event: TouchEvent) => {
if (event.type === TouchType.Down) {
this.text = day
}
})
if (this.isEdit) {
Image($r('app.media.close'))
.width(20)
.height(20)
.onClick(() => {
animateTo({ duration: 300 }, () => {
this.numbers.splice(index, 1)
})
this.stopJump()
this.jumpWithSpeed(5)
})
}
}
.rotate({ z: this.rotateZ,
angle: 0.4,
centerX: 0.5,
centerY: 0.5
})
}
.transition({ type: TransitionType.All, translate: { x: 100 }, scale: { x: 1, y: 1 } })
.padding({ top: 15 })
})
}
.columnsTemplate('1fr 1fr 1fr')
.columnsGap(10)
.rowsGap(10)
.onScrollIndex((first: number) => {
console.info(first.toString())
})
.margin({ top: 5 })
.width('100%')
.backgroundColor(0xFAEEE0)
.height('100%')
.supportAnimation(true) //是否支持动画
//设置Grid是否进入编辑模式,进入编辑模式可以拖拽Grid组件内部GridItem
.editMode(this.isEdit)
//第一次拖拽此事件绑定的组件时,触发回调
.onItemDragStart((event: ItemDragInfo, itemIndex: number) => {
//设置拖拽过程中显示的图片
return this.pixelMapBuilder()
})
//绑定此事件的组件可作为拖拽释放目标,当在本组件范围内停止拖拽行为时,触发回调
//itemIndex为拖拽起始位置,insertIndex为拖拽插入位置
.onItemDrop((event: ItemDragInfo, itemIndex: number, insertIndex: number, isSuccess: boolean) => {
//不支持拖拽到已有内容以外的位置
if (insertIndex < this.numbers.length) {
this.changeIndex(itemIndex, insertIndex)
this.stopJump()
this.jumpWithSpeed(5)
}
})
}.width('100%')
.margin({ top: 5 })
.alignItems(HorizontalAlign.End)
}
}
有图片的拖动 demo 嘛
图片拖动解决了吗?貌似图片不能拖动,
在HarmonyOS鸿蒙Next开发框架中,若要在网格(Grid)布局中实现拖拽交换子组件位置的功能,可以通过以下方式实现:
首先,需要利用鸿蒙提供的触摸事件监听机制。为每个子组件添加触摸监听器,监听用户的拖拽动作。这通常包括按下(ACTION_DOWN)、移动(ACTION_MOVE)和抬起(ACTION_UP)事件。
在按下事件中,记录拖拽开始的位置,并设置一个标志位表示拖拽开始。在移动事件中,根据触摸点的变化,实时更新拖拽组件的位置。同时,需要检测拖拽组件是否与其他组件重叠,若重叠,则准备交换它们的位置。
在抬起事件中,根据拖拽路径和最终位置,完成组件位置的交换,并清除拖拽标志位。
此外,为了实现平滑的拖拽效果,可能需要对拖拽组件进行视觉上的反馈,如改变透明度或添加阴影。同时,在拖拽过程中,其他组件可能需要暂时禁用点击事件,以避免冲突。
需要注意的是,拖拽交换功能可能涉及复杂的布局计算和事件处理,开发者需确保逻辑的正确性和性能的优化。
如果问题依旧没法解决请联系官网客服,官网地址是 https://www.itying.com/category-93-b0.html,