目录

平板弹窗被遮挡

问题现象

在横屏模式下打开应用,点击“已有账号登录”后,登录弹窗从底部弹出,未居中显示,且无法点击弹窗中的内容。切换为竖屏模式后,同样点击“已有账号登录”,弹窗底部内容被截断,信息显示不完整。

背景知识

关于弹窗,根据用户交互操作场景,可分为模态弹窗和非模态弹窗两种类型,其区别在于用户是否必须对其做出响应。

问题定位

分析结论

修改建议

由于CustomDialog在使用上存在较多限制,不支持动态创建和动态刷新,在相对较复杂的应用场景中推荐使用UIContext中获取到的PromptAction对象提供的openCustomDialog接口来实现自定义弹出框。以下是基于PromptAction封装的自定义弹窗实现横竖屏居中显示不遮挡的示例,具体实现步骤如下:

完整示例如下:

import { BusinessError } from '@kit.BasicServicesKit';
import { ComponentContent, promptAction, UIContext } from '@kit.ArkUI';


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}`);
        });
    }
  }
}
// Index.ets
import { ComponentContent } from '@kit.ArkUI';
import { PromptActionClass } from './PromptActionView';

@Builder
function buildText() {
  Column() {
    Flex({ justifyContent: FlexAlign.SpaceBetween }) {
      Text('账号登录').fontSize(24).fontWeight(FontWeight.Bold);
      Image($r('app.media.close'))
        .width(32)
        .height(32)
        .onClick(() => {
          PromptActionClass.closeDialog();
        });
    }.padding({ bottom: 24 });

    Column() {
      TextInput({ placeholder: '邮箱' })
        .width('100%')
        .showUnderline(true);
      TextInput({ placeholder: '验证码' })
        .width('100%')
        .showUnderline(true);

      Row() {
        Checkbox({ name: 'checkbox2', group: 'checkboxGroup' })
          .select(false)
          .selectedColor(0x39a2db)
          .shape(CheckBoxShape.ROUNDED_SQUARE)
          .onChange((value: boolean) => {
            console.info('Checkbox2 change is' + value);
          });
        Text('我已阅读并同意《隐私政策》');
      }.padding({ top: 12, bottom: 12 });
    };

    Button('登录')
      .width('100%')
      .onClick(() => {
        PromptActionClass.closeDialog();
      });

    Column() {
      Text('其他账号登录').padding({ bottom: 12 });
      Row() {
        Image($r('app.media.huawei')).width(32).height(32).margin({ right: 12 });
      };
    }
    .padding({ top: 24 });
  }.backgroundColor('#FFF0F0F0')
  .padding(24)
  .width(480)
  .border({ radius: '10%' });
}


@Entry
@Component
struct Index {
  private ctx: UIContext = this.getUIContext();
  private contentNode: ComponentContent<Object> =
    new ComponentContent(this.ctx, wrapBuilder(buildText));


  aboutToAppear(): void {
    PromptActionClass.setContext(this.ctx);
    PromptActionClass.setContentNode(this.contentNode);
    PromptActionClass.setOptions({ alignment: DialogAlignment.Center });
  }


  build() {
    Column() {
      Button('已有账号登录')
        .margin({ bottom: 24 })
        .onClick(() => {
          PromptActionClass.openDialog();
        });
    }
    .justifyContent(FlexAlign.End)
    .width('100%')
    .height('100%');
  }
}