Foreword
this article is based on Api12
grid drag and drop, this function is very common, generally used for channel editing or item sequence arrangement. In the development of Hongmeng, the system also gives relevant Api for grid editing, which can be easily implemented through itemdragstart and itemdrop. Itemdragstart is used to set the display during drag and drop, and itemdrop is used for data exchange logic processing.
According to the official provision, we casually implemented a simple drag and drop effect:
@Entry
@Component
struct Index {
@State numbers: number[] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
@Builder
itemLayout(text: string) {
Text(text)
.fontSize(16)
.backgroundColor(Color.Pink)
.width(80)
.height(80)
.textAlign(TextAlign.Center)
}
changeIndex(index1: number, index2: number) {
let temp = this.numbers[index1];
this.numbers[index1] = this.numbers[index2];
this.numbers[index2] = temp;
}
build() {
Column() {
Grid() {
ForEach(this.numbers, (n: number) => {
GridItem() {
this.itemLayout(n.toString())
}
})
}
.columnsTemplate('1fr 1fr 1fr')
.columnsGap(10)
.rowsGap(10)
.editMode(true)
.onItemDragStart((event: ItemDragInfo, itemIndex: number) => { //第一次拖拽此事件绑定的组件时,触发回调。
return this.itemLayout(this.numbers[itemIndex].toString()) //设置拖拽过程中显示
})
.onItemDrop((event: ItemDragInfo, itemIndex: number, insertIndex: number,
isSuccess: boolean) => {
if (!isSuccess || insertIndex >= this.numbers.length) {
return
}
this.changeIndex(itemIndex, insertIndex)
})
}.width('100%')
.height("100%")
}
}
in the above code, we simply implemented a grid drag and drop. After the actual operation, the long press did drag and drop, and the corresponding item was also exchanged, but there was no process of mobile exchange, because there was no setting. Drag animation method, if you want to drag the process of moving animation, just need to set supportAnimation is set to true. In addition, there is another very important attribute, that is editMode, true is edit mode, false is not editable.
The drag-and-drop code is very simple. After all, the government has also given relevant cases. Two of them are not given, that is, the prohibition of drag-and-drop and the prohibition of exchange with them.
For example, the first and second entries cannot be dragged and dropped. How do you set them? For example, no entry can be exchanged with the first one. How should it be set?
Drag and Drop Prohibited
It is also the above code. For example, it is very simple to prohibit the first entry from being dragged. In the onItemDragStart method, if the specified index is touched, it is not allowed to be executed.
.onItemDragStart((event: ItemDragInfo, itemIndex: number) => {
if (itemIndex == 0) {
return
}
return this.itemLayout(this.numbers[itemIndex].toString()) //设置拖拽过程中显示
})
It should be noted that the above code only prohibits dragging. However, there is a potential problem that other entries can be exchanged with it. After Exchange, due to the change of its index, it becomes draggable. If you want to realize real, you cannot drag even after being exchanged, then you cannot judge the index and can judge by the unique value, for example, item data is replaced with an object, and a unique value is defined in the object.
Prohibition of Exchange
in actual development, in addition to the prohibition of dragging and dropping of an entry, there is also logic that cannot be exchanged with it. For example, the first entry is fixed, which not only prohibits dragging and dropping, but also cannot be exchanged with it. How can this be implemented?
onItemDrop((event: ItemDragInfo, itemIndex: number, insertIndex: number,
isSuccess: boolean) => {
if (insertIndex <= 0) {
return
}
if (!isSuccess || insertIndex >= this.numbers.length) {
return
}
this.changeIndex(itemIndex, insertIndex)
})
It is very simple. If it is the first one, it is enough not to execute it directly. Although the above code implements the prohibition of exchange, there is a problem, that is, the actual animation has been executed, but the final exchange has not been executed. There are still big visual problems.
The effect we want is to keep the animation of moving and dragging, but when dragging to the first one, the animation will not be executed, and the others will be executed as they are executed.
Then, when setting supportAnimation animation animation, it cannot be set to true directly, but after moving to the position of item one, it is set to fasle, and the others are set to true.
How to get the coordinates of the first item? In fact, each component has a method, onAreaChange. Through this attribute, we can get the width and height of any component and the coordinates of xy. Of course, you can also calculate. After all, you know the width and height of the screen and the width and height of the entry.
The coordinates of the gesture movement can be obtained by the onTouch method, and judged in the Move Event. If the movement is within the range of item one, the animation is canceled, otherwise the animation is executed.
Simple implementation
at present, the grid drag-and-drop function has been encapsulated and put into the refresh Library. If you want to use it directly, you can rely on this library:
"dependencies": { "@abner/refresh": "^1.3.6"}
the simple case is as follows:
import { GridDropView } from '@abner/refresh'
@Entry
@Component
struct Index {
@State numbers: number[] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
@Builder
itemLayout(item: Object, _: number) {
Text(item.toString())
.fontSize(16)
.backgroundColor(Color.Pink)
.width(80)
.height(80)
.textAlign(TextAlign.Center)
}
build() {
Column() {
GridDropView({
columnsTemplate:"1fr 1fr 1fr",
items: this.numbers,
itemLayout: this.itemLayout,
dropLayout: this.itemLayout,
rowsGap: 10,
columnsGap: 10,
isEditMode: true,
prohibitDrop: [0, 1],
prohibitMaxSwap: 0,
onDropData: (items) => {
console.log("END:" + JSON.stringify(items))
}
})
}.width('100%')
.height("100%")
}
}
precautions
the three most important ways to implement drag and drop are to open the editing State editMode, implement the onItemDragStart and onItemDrop, set the drag and drop Movement animation and exchange data, and if you want to open the complementary animation, you still need to implement it. The supportAnimation method.
Top comments (0)