效果图:
代码:
import display from "@ohos.display"
import { AppUtil } from "@pura/harmony-utils"
/**
* 自定义可拖拽图标组件
*/
@Component
export default struct DraggableImage {
imageResource?: Resource
imageHeight: number = 50 //单位:vp
imageWidth: number = 50 //单位:vp
//图标初始位置,默认在左上角
startLocationX:number = 0
startLocationY:number = 0
marginLeft:number = 0
marginRight:number = 0
marginTop:number = 0
marginBottom:number = 0
@State private offsetX: number = 0
@State private offsetY: number = 0
@State private positionX: number = 0
@State private positionY: number = 0
//屏幕宽
private screenWidth: number = 0
private screenHeight: number = 0
// 定义贴边的阈值(距离边缘多少像素时触发贴边)
private snapThreshold: number = 50; //单位:vp
aboutToAppear(): void {
this.screenWidth = px2vp(display.getDefaultDisplaySync().width)-this.marginRight
this.screenHeight = px2vp(display.getDefaultDisplaySync().height - AppUtil.getStatusBarHeight() - AppUtil.getNavigationIndicatorHeight())-this.marginBottom
this.snapThreshold = this.screenWidth / 2
console.info('DraggableImage aboutToAppear ' + this.screenWidth + " " + this.screenHeight)
this.offsetX= this.startLocationX;
this.offsetY= this.startLocationY;
this.positionX= this.startLocationX;
this.positionY= this.startLocationY;
}
aboutToDisappear(): void {
}
build() {
Image(this.imageResource)
.height(this.imageHeight)
.width(this.imageWidth)
.draggable(false)
.position({
x: this.offsetX,
y: this.offsetY
})//.translate({ x: this.offsetX, y: this.offsetY, z: 0 })// 以组件左上角为坐标原点进行移动
// 左右滑动触发该手势事件
.gesture(
PanGesture()
.onActionStart((event: GestureEvent) => {
console.info('DraggableImage start')
})
.onActionUpdate((event: GestureEvent) => {
if (event) {
// 计算新的位置
let newOffsetX = this.positionX + event.offsetX;
let newOffsetY = this.positionY + event.offsetY;
// 防止图标滑出左边界
if (newOffsetX < this.marginLeft) {
newOffsetX = this.marginLeft;
}
// 防止图标滑出右边界
if (newOffsetX + this.imageWidth > this.screenWidth) { // imageWidth 是图标的宽度
newOffsetX = this.screenWidth - this.imageWidth;
}
// 防止图标滑出上边界
if (newOffsetY < this.marginTop) {
newOffsetY = this.marginTop;
}
// 防止图标滑出下边界
if (newOffsetY + this.imageHeight > this.screenHeight) { // imageHeight 是图标的高度
newOffsetY = this.screenHeight - this.imageHeight;
}
// 更新图标位置
this.offsetX = newOffsetX;
this.offsetY = newOffsetY;
console.info('DraggableImage onActionUpdate ' + this.offsetX + " " + this.offsetY)
}
})
.onActionEnd((event: GestureEvent) => {
let newOffsetX = this.marginLeft
// 检查是否靠近左边缘
if (this.offsetX < this.snapThreshold) {
newOffsetX = this.marginLeft; // 贴到左边缘
} else if (this.offsetX + this.imageWidth > this.screenWidth - this.snapThreshold) { // imageWidth 是图标的宽度
// 检查是否靠近右边缘
newOffsetX = this.screenWidth - this.imageWidth; // 贴到右边缘
} else {
newOffsetX = this.marginLeft
}
// 检查是否靠近上边缘
/* if (this.offsetY < this.snapThreshold) {
this.offsetY = 0; // 贴到上边缘
}
// 检查是否靠近下边缘
else if (this.offsetY + 50 > this.screenHeight - this.snapThreshold) { // 50 是图标的高度
this.offsetY = this.screenHeight - 50; // 贴到下边缘
}*/
animateTo({ duration: 300, curve: Curve.Linear }, () => {
this.offsetX = newOffsetX;
})
this.positionX = this.offsetX
this.positionY = this.offsetY
console.info('DraggableImage end')
})
)
}
}
关键代码处都做了注释,这里也不在过多说明啦。
这里用了一个工具类 harmony-utils 来获取状态栏高度和底部导航栏高度,大家自行下载。
如何使用 DraggablePage.ets:
import DraggableImage from './DraggableImage'
import { display } from '@kit.ArkUI'
import { AppUtil } from '@pura/harmony-utils'
@Entry
@Component
struct DraggablePage {
marginBottom: number = 30
marginRight: number = 10
imageSize: number = 50
build() {
Column() {
Stack({ alignContent: Alignment.Center }) {
Text("我是内容布局")
.fontSize(30)
.fontColor(Color.Black)
DraggableImage({
imageResource: $r('app.media.update'),
imageHeight: this.imageSize,
imageWidth: this.imageSize,
startLocationX: px2vp(display.getDefaultDisplaySync().width) - this.imageSize - this.marginRight,
startLocationY: px2vp(display.getDefaultDisplaySync().height - AppUtil.getStatusBarHeight() - AppUtil.getNavigationIndicatorHeight()) - this.imageSize - this.marginBottom,
marginTop: this.marginBottom,
marginBottom: this.marginBottom,
marginLeft: this.marginRight,
marginRight: this.marginRight,
})
//注意:拖拽图标的边距,不能这样设置
// .margin({ bottom: this.marginBottom, right: this.marginRight })
}
.width('100%')
.layoutWeight(1)
}
.backgroundColor('#ffde7b7b')
.width('100%')
.height('100%')
}
}
如果你不想设置拖拽图标的 margin ,这样写就行:
DraggableImage({
imageResource: $r('app.media.update'),
imageHeight: this.imageSize,
imageWidth: this.imageSize,
})