【HarmonyOS Next 自定义可拖拽image】

发布于:2025-02-11 ⋅ 阅读:(13) ⋅ 点赞:(0)

效果图:
请添加图片描述
代码:

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,
          
        })

网站公告

今日签到

点亮在社区的每一天
去签到