HarmonyOS鸿蒙Next中如何实现自定义弹窗(openCustomDialog)的跟手效果?

HarmonyOS鸿蒙Next中如何实现自定义弹窗(openCustomDialog)的跟手效果? 如何实现自定义弹窗(openCustomDialog)的跟手效果,即在一个区域内,手指在哪里长按,哪里就可以弹出窗口

2 回复

场景是在长按事件中触发跟手,长按使用的是event:GestureEvent。所以通过组合手势来实现,示例代码如下:

Index.ets:

// Index.ets
import {ComponentContent} from '@kit.ArkUI';
import {PromptActionClass} from './PromptActionClass';

class Params {
  text: string = "";

  constructor(text: string) {
    this.text = text;
  }
}

@Builder
function buildText(params: Params) {
  Column() {
    Text(params.text)
      .fontSize(50)
      .fontWeight(FontWeight.Bold)
      .margin({bottom: 36})
    Button('Close')
      .onClick(() => {
        PromptActionClass.closeDialog();
      })
  }.backgroundColor('#FFF0F0F0')
}

@Entry
@Component
struct Index {
  @State count: number = 0;
  @State positionX: number = 0;
  @State positionY: number = 0;
  @State gestureEventInfo: string = '';
  @State message: string = 'hello'
  private ctx: UIContext = this.getUIContext();
  private contentNode : ComponentContent<Object> =
    new ComponentContent(this.ctx, wrapBuilder(buildText), new Params(this.message));

  aboutToAppear(): void {
    PromptActionClass.setContext(this.ctx);
    PromptActionClass.setContentNode(this.contentNode);
    PromptActionClass.setOptions({alignment: DialogAlignment.Top, offset:{dx:0, dy: 50}});
  }

  build() {
    Column() {
      Row() {
        Column() {
          Text('这是一句话')
            .fontSize(28)
        }
        .height(200)
        .width('100%')
        .backgroundColor('#F1F3F5')
        .gesture(
          // 以下组合手势为顺序识别, 当长按手势事件未正常触发时则不会触发拖动手势事件
          GestureGroup(GestureMode.Sequence,
            LongPressGesture()
              .onAction((event: GestureEvent) => {
                for (let i=0;i< event.fingerList.length; i++) {
                  this.positionX = event.fingerList[i].globalX;
                  this.positionY = event.fingerList[i].globalY;
                }
                console.info(`positionX:${this.positionX}, positionY:${this.positionY}`)
                PromptActionClass.openDialog()
                PromptActionClass.updateDialog({
                  alignment: DialogAlignment.TopStart,
                  offset:{dx: this.positionX, dy: this.positionY}
                })
              })
              .onActionEnd(() => {
                console.info('LongPress end');
              })
          )
        )
      }
      .padding(12)
      .borderRadius(24)
      .backgroundColor(Color.White)

      Text(this.gestureEventInfo)
        .fontSize(18)
        .width('100%')
        .textAlign(TextAlign.Start)
        .padding({left: 18, top:30})
    }
    .height('100%')
    .width('100%')
    .backgroundColor('#F1F3F5')
  }
}

PromptActionClass.ets:

// PromptActionClass.ets
import { UIContext } from "@ohos.arkui.UIContext";
import { promptAction, ComponentContent } from "@kit.ArkUI";
import { BusinessError } from "@kit.BasicServicesKit";

export class PromptActionClass {
  static ctx: UIContext;
  static contentNode: ComponentContent<Object>;
  static options: promptAction.BaseDialogOptions;

  static setContext(context: UIContext) {
    PromptActionClass.ctx = context;
  }

  static setContentNode(node: ComponentContent<Object>) {
    PromptActionClass.contentNode = node;
  }

  static setOptions(options: promptAction.BaseDialogOptions) {
    PromptActionClass.options = options;
  }

  static openDialog() {
    if (PromptActionClass.contentNode !== null) {
      PromptActionClass.ctx.getPromptAction().openCustomDialog(PromptActionClass.contentNode, PromptActionClass.options)
        .then(() => {
          console.info("OpenCustomDialog complete.");
        })
        .catch((error: BusinessError) => {
          let message = (error as BusinessError).message;
          let code = (error as BusinessError).code;
          console.error(`OpenCustomDialog  args error code is ${code}, message is ${message}`);
        })
    }
  }

  static closeDialog() {
    if (PromptActionClass.contentNode !== null) {
      PromptActionClass.ctx.getPromptAction().closeCustomDialog(PromptActionClass.contentNode)
        .then(() => {
          console.info("CloseCustomDialog complete.");
        })
        .catch((error: BusinessError) => {
          let message = (error as BusinessError).message;
          let code = (error as BusinessError).code;
          console.error(`CloseCustomDialog  args error code is ${code}, message is ${message}`);
        })
    }
  }

  static updateDialog(options: promptAction.BaseDialogOptions) {
    if (PromptActionClass.contentNode !== null) {
      PromptActionClass.ctx.getPromptAction().updateCustomDialog(PromptActionClass.contentNode, options)
        .then(() => {
          console.info("UpdateCustomDialog complete.");
        })
        .catch((error: BusinessError) => {
          let message = (error as BusinessError).message;
          let code = (error as BusinessError).code;
          console.error(`UpdateCustomDialog  args error code is ${code}, message is ${message}`);
        })
    }
  }
}

更多关于HarmonyOS鸿蒙Next中如何实现自定义弹窗(openCustomDialog)的跟手效果?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS鸿蒙Next中,实现自定义弹窗的跟手效果可以通过以下步骤:

  1. 创建自定义弹窗:使用CustomDialogController创建自定义弹窗布局。
  2. 设置触摸事件:在弹窗的根布局上设置onTouchEvent监听器,捕获用户的触摸事件。
  3. 计算偏移量:根据触摸事件的坐标变化,计算弹窗的偏移量。
  4. 更新弹窗位置:通过setTranslationXsetTranslationY方法动态更新弹窗的位置,实现跟手效果。
  5. 处理释放事件:在用户释放触摸时,根据当前偏移量决定是否关闭弹窗或回到原位。

通过这些步骤,可以实现自定义弹窗的跟手效果,提升用户体验。

回到顶部