HarmonyOS —常用组件开发指导-CommonDialog

HarmonyOS —常用组件开发指导-CommonDialog

CommonDialog是一种在弹出框消失之前,用户无法操作其他界面内容的对话框。通常用来展示用户当前需要的或用户必须关注的信息或操作。对话框的内容通常是不同组件进行组合布局,如:文本、列表、输入框、网格、图标或图片,常用于选择或确认信息。

接口说明

构造方法

创建对话框

CommonDialog dialog = new CommonDialog(getContext());

在UI线程调用该方法创建一个CommonDialog的实例。getContext()是获取上下文对象的方法,您也可以以其他的方式将其传入使用。

使用对话框

下面显示一个包含标题、内容和按钮的简单对话框。设置按钮时传入的IDialog.BUTTON3表示按钮为按钮区从左至右第三个按钮,当只设置一个按钮时,按钮居中,多个按钮时以相同比例平均分配在按钮区。

CommonDialog dialog = new CommonDialog(getContext());
dialog.setTitleText("Notification");
dialog.setContentText("This is CommonDialog Content area.");
dialog.setButton(IDialog.BUTTON3, "CONFIRM", (iDialog, i) -> iDialog.destroy());
dialog.show();

说明

常用方法的设置需在调用dialog.show()之前进行,否则设置无法生效。

图1 创建显示的CommonDialog对话框效果图

修改窗口尺寸

import static ohos.agp.components.ComponentContainer.LayoutConfig.MATCH_CONTENT; // 注意引入

dialog.setSize(800, MATCH_CONTENT);

该方法输入int类型的参数,或者MATCH_CONTENT和MATCH_PARENT。参数大小代表屏幕所占像素大小。图2 修改CommonDialog对话框窗口尺寸后的效果图

修改位置

用户可以通过设置对话框的对齐属性和偏移量来设置对话框显示的位置。

dialog.setAlignment(LayoutAlignment.BOTTOM);
dialog.setOffset(0, 200);

图3 修改CommonDialog对话框位置后的效果图

销毁监听

如果需要监听对话框的销毁事件,可以通过setDestroyedListener​这个方法来进行相关操作。

dialog.setDestroyedListener(() -> {
    // TODO: 销毁后需要执行的任务。
});

延时关闭

通过设置方法setDuration​来实现对话框显示指定时间后自动关闭的功能,传入值为int类型,单位为毫秒。

dialog.setDuration(5000);

自定义样式

用户也可以通过自定义样式来实现自己想要的对话框效果。调用setTitleCustomComponent​方法和setContentCustomComponent方法来实现标题区域或内容区域的自定义效果。

  1. 在Project窗口,打开“entry > src > main > resources > base > media”,添加所需图片至media文件夹下,本例以“transparent_bg.JPG”为例。
  2. 在Project窗口,点击“entry > src > main > resources > base > layout”,右键选择“New > Layout Resource File”,命名为“layout_custom_dialog”,单击回车键。示例代码如下:
<?xml version="1.0" encoding="utf-8"?>
<DependentLayout
    xmlns:ohos="http://schemas.huawei.com/res/ohos"
    ohos:id="$+id:custom_container"
    ohos:height="match_content"
    ohos:width="300vp"
    ohos:background_element="#F5F5F5">
    
    <Text
        ohos:id="$+id:custom_title"
        ohos:height="match_content"
        ohos:width="match_content"
        ohos:horizontal_center="true"
        ohos:margin="8vp"
        ohos:padding="8vp"
        ohos:text="TITLE"
        ohos:text_size="16fp"/>
    <Image
        ohos:id="$+id:custom_img"
        ohos:height="150vp"
        ohos:width="280vp"
        ohos:below="$id:custom_title"
        ohos:horizontal_center="true"
        ohos:image_src="$media:transparent_bg"
        ohos:clip_alignment="center"/>
    <Button
        ohos:height="match_content"
        ohos:width="match_parent"
        ohos:background_element="#FF9912"
        ohos:below="$id:custom_img"
        ohos:margin="8vp"
        ohos:padding="8vp"
        ohos:text="BUTTON"
        ohos:text_color="#FFFFFF"
        ohos:text_size="18vp"/>
</DependentLayout>

在Java代码中引用自定义界面,示例代码如下:

...
Component container = LayoutScatter.getInstance(getContext()).parse(ResourceTable.Layout_layout_custom_dialog, null, false);
dialog.setContentCustomComponent(container);
dialog.setSize(MATCH_CONTENT, MATCH_CONTENT);

图4 自定义CommonDialog对话框样式的效果图

场景示例

利用CommonDialog的setContentCustomComponent方法设置自定义对话框样式。

开发步骤和源码示例如下:

  1. 声明所需引用的颜色资源:在Project窗口,点击“entry > src > main > resources > base > element”,右键选择“New > File”,新建“color.json”文件。color.json示例如下:
{
  "color": [
    {
      "name": "bg_dialog_light",
      "value": "#E8EAEE"
    },
    {
      "name": "text_color_light",
      "value": "#E5000000"
    },
    {
      "name": "colorAccent",
      "value": "#007DFF"
    },
    {
      "name": "colorAccentPressed",
      "value": "#2e94ff"
    },
    {
      "name": "colorError",
      "value": "#FA2A2D"
    },
    {
      "name": "colorErrorPressed",
      "value": "#FB5053"
    },
    {
      "name": "colorNormal",
      "value": "#FFFFFF"
    },
    {
      "name": "colorNormalPressed",
      "value": "#10000000"
    }
  ]
}

声明所需引用的数值资源:在Project窗口,点击“entry > src > main > resources > base > element”,右键选择“New > File”,新建“float.json”文件。float.json示例如下:

{
  "float": [
    {
      "name": "spacing_mini",
      "value": "8vp"
    },
    {
      "name": "spacing_normal",
      "value": "16vp"
    },
    {
      "name": "spacing_large",
      "value": "32vp"
    },
    {
      "name": "spacing_huge",
      "value": "64vp"
    },
    {
      "name": "text_size_title",
      "value": "20fp"
    },
    {
      "name": "text_size_content",
      "value": "16fp"
    },
    {
      "name": "dialog_corner_radius",
      "value": "24vp"
    },
    {
      "name": "button_height",
      "value": "40vp"
    },
    {
      "name": "button_size",
      "value": "14fp"
    }
  ]
}

创建对话框布局文件:在Project窗口,点击“entry > src > main > resources > base > layout”,右键选择“New > Layout Resource File”,新建“general_dialog”xml文件。general_dialog.xml文件示例如下:

<?xml version="1.0" encoding="utf-8"?>
<DirectionalLayout
    xmlns:ohos="http://schemas.huawei.com/res/ohos"
    ohos:background_element="$color:bg_dialog_light"
    ohos:height="match_content"
    ohos:min_height="$float:spacing_huge"
    ohos:orientation="vertical"
    ohos:width="328vp">

    <StackLayout
        ohos:id="$+id:title_layout"
        ohos:height="match_content"
        ohos:width="match_parent"
        ohos:left_padding="$float:spacing_large"
        ohos:top_padding="$float:spacing_normal"
        ohos:right_padding="$float:spacing_large"
        ohos:bottom_padding="$float:spacing_normal">

        <Text
            ohos:id="$+id:title"
            ohos:layout_alignment="center"
            ohos:height="match_content"
            ohos:width="match_content"
            ohos:min_height="32vp"
            ohos:max_text_lines="2"
            ohos:multiple_lines="true"
            ohos:text_color="$color:text_color_light"
            ohos:text_font="HwChinese-medium"
            ohos:text_size="$float:text_size_title"
            ohos:text_alignment="vertical_center"
            ohos:truncation_mode="ellipsis_at_end"
            ohos:visibility="hide" />
    </StackLayout>

    <DependentLayout
        ohos:id="$+id:content_layout"
        ohos:height="match_content"
        ohos:width="match_parent">

        <Image
            ohos:id="$+id:icon"
            ohos:horizontal_center="true"
            ohos:height="$float:spacing_huge"
            ohos:width="$float:spacing_huge"
            ohos:top_margin="$float:spacing_large"
            ohos:bottom_margin="$float:spacing_normal"
            ohos:scale_mode="stretch"
            ohos:visibility="hide" />

        <Text
            ohos:id="$+id:content"
            ohos:horizontal_center="true"
            ohos:below="$id:icon"
            ohos:height="match_content"
            ohos:width="match_content"
            ohos:left_margin="$float:spacing_large"
            ohos:right_margin="$float:spacing_large"
            ohos:max_height="984"
            ohos:multiple_lines="true"
            ohos:scrollable="true"
            ohos:text_color="$color:text_color_light"
            ohos:text_size="$float:text_size_content"
            ohos:visibility="hide" />
    </DependentLayout>

    <DirectionalLayout
        ohos:id="$+id:bottom_layout"
        ohos:height="match_content"
        ohos:min_height="$float:spacing_large"
        ohos:width="match_parent"
        ohos:visibility="hide">

        <DirectionalLayout
            ohos:id="$+id:operation_layout"
            ohos:height="72vp"
            ohos:width="match_parent"
            ohos:alignment="center"
            ohos:top_margin="$float:spacing_mini"
            ohos:left_margin="$float:spacing_normal"
            ohos:right_margin="$float:spacing_normal"
            ohos:orientation="horizontal"
            ohos:visibility="hide">

        </DirectionalLayout>
    </DirectionalLayout>
</DirectionalLayout>

创建处理资源文件的类ResourceTool.java。示例如下:

//请根据实际工程/包名引入
package com.huawei.myapplication.slice;

import ohos.app.Context;
import ohos.global.resource.NotExistException;
import ohos.global.resource.WrongTypeException;

import java.io.IOException;

public class ResourceTool {
    public static int getColor(Context context, int id, int defaultValue) {
        int color = defaultValue;
        try {
            color = context.getResourceManager().getElement(id).getColor();
        } catch (IOException | NotExistException | WrongTypeException e) {
            e.printStackTrace();
        }
        return color;
    }

    public static float getFloat(Context context, int id, float defaultValue) {
        float value = defaultValue;
        try {
            value = context.getResourceManager().getElement(id).getFloat();
        } catch (IOException | NotExistException | WrongTypeException e) {
            e.printStackTrace();
        }
        return value;
    }
}

创建按钮背景的工具类GeneralButtonElement.java。示例如下:

//请根据实际工程/包名引入
package com.huawei.myapplication.slice;
import com.huawei.myapplication.ResourceTable;

import ohos.agp.colors.RgbColor;
import ohos.agp.components.ComponentState;
import ohos.agp.components.element.ShapeElement;
import ohos.agp.components.element.StateElement;
import ohos.app.Context;

public class GeneralButtonElement extends StateElement{
    private Context mContext;

    private int[] mStateFlagEmpty = new int[] {ComponentState.COMPONENT_STATE_EMPTY};

    private int[] mStateFlagPressed = new int[] {ComponentState.COMPONENT_STATE_PRESSED};

    private int[][] mAllTypeColorIds = {
        {
            ResourceTable.Color_colorNormal, ResourceTable.Color_colorNormalPressed
        },
        {
            ResourceTable.Color_colorAccent, ResourceTable.Color_colorAccentPressed
        },
        {
            ResourceTable.Color_colorError, ResourceTable.Color_colorErrorPressed
        }
    };

    public static final int TYPE_NORMAL = 0;

    public static final int TYPE_ACCENT = 1;

    public static final int TYPE_ERROR = 2;

    public GeneralButtonElement(Context context, int type) {
        super();
        mContext = context;
        initBackground(mAllTypeColorIds[type]);
    }

    private void initBackground(int[] colorIds) {
        this.addState(mStateFlagPressed, new ShapeElement() {
            {
                setRgbColor(RgbColor.fromArgbInt(ResourceTool.getColor(mContext, colorIds[1], 0)));
                setCornerRadius(ResourceTool.getFloat(mContext, ResourceTable.Float_dialog_corner_radius, 0));
            }
        });
        this.addState(mStateFlagEmpty, new ShapeElement() {
            {
                setRgbColor(RgbColor.fromArgbInt(ResourceTool.getColor(mContext, colorIds[0], 0)));
                setCornerRadius(ResourceTool.getFloat(mContext, ResourceTable.Float_dialog_corner_radius, 0));
            }
        });
    }
}

创建自定义对话框类GeneralDialog.java。示例如下:

//请根据实际工程/包名引入
package com.huawei.ohos.dialogdemo.dialog;
import com.huawei.myapplication.ResourceTable;

import java.util.Optional;
import ohos.agp.colors.RgbColor;
import ohos.agp.components.AttrHelper;
import ohos.agp.components.Button;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.DirectionalLayout;
import ohos.agp.components.Image;
import ohos.agp.components.LayoutScatter;
import ohos.agp.components.Text;
import ohos.agp.components.element.ShapeElement;
import ohos.agp.text.Font;
import ohos.agp.utils.Color;
import ohos.agp.utils.LayoutAlignment;
import ohos.agp.window.dialog.CommonDialog;
import ohos.agp.window.service.WindowManager;
import ohos.app.Context;

public class GeneralDialog {
    private static final int MAX_BUTTON_NUMBER = 3;

    private static final int DIALOG_WIDTH_VP = 328;

    private final String[] mButtonTexts = new String[MAX_BUTTON_NUMBER];

    private final int[] mButtonTypes = new int[MAX_BUTTON_NUMBER];

    private final ClickedListener[] mButtonListeners = new ClickedListener[MAX_BUTTON_NUMBER];

    private String mTitle;

    private String mContent;

    private int mIconId;

    private int buttonNum = 0;

    private float dim = -1f;

    private boolean mOutsideTouchClosable = false;

    private CommonDialog mCommonDialog;

    public void show() {
        if (mCommonDialog != null) {
            mCommonDialog.show();
            if (dim >= 0) {
                changeDialogDim(mCommonDialog, dim);
            }
        }
    }

    public void remove(){
        if (mCommonDialog != null) {
            mCommonDialog.destroy();
        }
    }

    private void changeDialogDim(CommonDialog dialog, float dim) {
        Optional<WindowManager.LayoutConfig> configOpt = dialog.getWindow().getLayoutConfig();
        configOpt.ifPresent(config -> {
            config.dim = dim;
            dialog.getWindow().setLayoutConfig(config);
        });
    }

    public interface ClickedListener{
        void onClick(GeneralDialog dialog);
    }

    public static class Builder {
        private final GeneralDialog mGeneralDialog;

        private final Context mContext;

        public Builder(Context context) {
            mContext = context;
            mGeneralDialog = new GeneralDialog();
        }

        public Builder setTitle(String title) {
            mGeneralDialog.mTitle = title;
            return this;
        }

        public Builder setContent(String content) {
            mGeneralDialog.mContent = content;
            return this;
        }

        public Builder setIcon(int id) {
            mGeneralDialog.mIconId = id;
            return this;
        }

        public Builder setDim(float dim){
            if (dim > 1) {
                mGeneralDialog.dim = 1;
            } else if (dim < 0) {
                mGeneralDialog.dim = 0;
            } else {
                mGeneralDialog.dim = dim;
            }
            return this;
        }

        public Builder setOutsideTouchClosable(boolean closable){
            mGeneralDialog.mOutsideTouchClosable = closable;
            return this;
        }

        public Builder addButton(String text, int type, ClickedListener listener) {
            if (mGeneralDialog.buttonNum >= MAX_BUTTON_NUMBER) {
                return this;
            }
            mGeneralDialog.mButtonTexts[mGeneralDialog.buttonNum] = text;
            mGeneralDialog.mButtonTypes[mGeneralDialog.buttonNum] = type;
            mGeneralDialog.mButtonListeners[mGeneralDialog.buttonNum] = listener;
            mGeneralDialog.buttonNum++;
            return this;
        }

        public GeneralDialog create() {
            CommonDialog sDialog = new CommonDialog(mContext);
            sDialog.setSize(AttrHelper.fp2px(DIALOG_WIDTH_VP, mContext), ComponentContainer.LayoutConfig.MATCH_CONTENT);
            sDialog.setAlignment(LayoutAlignment.BOTTOM);
            sDialog.setOffset(0, (int) ResourceTool.getFloat(mContext, ResourceTable.Float_spacing_huge, 0));
            sDialog.setTransparent(true);
            sDialog.setContentCustomComponent(initDialog());
            sDialog.setAutoClosable(mGeneralDialog.mOutsideTouchClosable);
            mGeneralDialog.mCommonDialog = sDialog;
            return mGeneralDialog;
        }

        private Component initDialog() {
            Component dialogLayout = LayoutScatter.getInstance(mContext).parse(ResourceTable.Layout_general_dialog, null, false);
            dialogLayout.setBackground(new ShapeElement(){{
                setRgbColor(RgbColor.fromArgbInt(ResourceTool.getColor(mContext, ResourceTable.Color_bg_dialog_light, 0xffffff)));
                setCornerRadius(ResourceTool.getFloat(mContext, ResourceTable.Float_dialog_corner_radius, 0));
            }});

            Text textTitle = (Text) dialogLayout.findComponentById(ResourceTable.Id_title);
            if (mGeneralDialog.mTitle != null) {
                textTitle.setText(mGeneralDialog.mTitle);
                textTitle.setVisibility(Component.VISIBLE);
            }

            Image imageIcon = (Image) dialogLayout.findComponentById(ResourceTable.Id_icon);
            if (mGeneralDialog.mIconId != 0) {
                imageIcon.setPixelMap(mGeneralDialog.mIconId);
                imageIcon.setVisibility(Component.VISIBLE);
                Component titleLayout = dialogLayout.findComponentById(ResourceTable.Id_title_layout);
                titleLayout.setVisibility(Component.HIDE);
            }

            Text textContent = (Text) dialogLayout.findComponentById(ResourceTable.Id_content);
            Component bottomLayout = dialogLayout.findComponentById(ResourceTable.Id_bottom_layout);
            if (mGeneralDialog.mContent != null) {
                textContent.setText(mGeneralDialog.mContent);
                textContent.setVisibility(Component.VISIBLE);
                bottomLayout.setVisibility(Component.VISIBLE);
            }

            DirectionalLayout operationLayout = (DirectionalLayout) dialogLayout.findComponentById(ResourceTable.Id_operation_layout);
            float totalWeight = 1.25f;
            for (int i = 0; i < mGeneralDialog.buttonNum; i++) {
                if (i == 0) {
                    operationLayout.setVisibility(Component.VISIBLE);
                    bottomLayout.setVisibility(Component.VISIBLE);
                }
                Button button = new Button(mContext);
                operationLayout.addComponent(button);
                DirectionalLayout.LayoutConfig config = new DirectionalLayout.LayoutConfig();
                config.height = (int) ResourceTool.getFloat(mContext, ResourceTable.Float_button_height, 0);
                config.width = DirectionalLayout.LayoutConfig.MATCH_PARENT;
                config.weight = 1;
                int spacingHorizontal = (int) ResourceTool.getFloat(mContext, ResourceTable.Float_spacing_mini, 0);
                config.setMargins(spacingHorizontal, 0, spacingHorizontal, 0);
                button.setLayoutConfig(config);
                if (i != 0) {
                    totalWeight = i + 1.0f;
                }
                button.setBackground(new GeneralButtonElement(mContext, mGeneralDialog.mButtonTypes[i]));
                if (mGeneralDialog.mButtonTypes[i] == GeneralButtonElement.TYPE_NORMAL) {
                    button.setTextColor(new Color(ResourceTool.getColor(mContext, ResourceTable.Color_text_color_light, 0xFFFFFF)));
                } else {
                    button.setTextColor(new Color(ResourceTool.getColor(mContext, ResourceTable.Color_colorNormal, 0xFFFFFF)));
                }
                button.setText(mGeneralDialog.mButtonTexts[i]);
                int currentIndex = i;
                button.setClickedListener(component -> mGeneralDialog.mButtonListeners[currentIndex].onClick(mGeneralDialog));
                button.setFont(Font.DEFAULT_BOLD);
                button.setTextSize((int) ResourceTool.getFloat(mContext, ResourceTable.Float_button_size, 0));
                button.setMultipleLine(false);
                button.setTruncationMode(Text.TruncationMode.ELLIPSIS_AT_END);
                button.setPaddingLeft(spacingHorizontal);
                button.setPaddingRight(spacingHorizontal);
            }
            operationLayout.setTotalWeight(totalWeight);
            return dialogLayout;
        }
    }
}

自定义对话框的使用:在主线程下调用如下方法:

GeneralDialog.Builder builder = new GeneralDialog.Builder(getContext());
builder.setTitle("TITLE")
    .setContent("CONTENT CONTENT CONTENT CONTENT CONTENT CONTENT CONTENT CONTENT CONTENT CONTENT")
    .addButton("CANCEL", GeneralButtonElement.TYPE_NORMAL, GeneralDialog::remove)
    .addButton("OK", GeneralButtonElement.TYPE_ACCENT, GeneralDialog::remove)
    .addButton("ERROR", GeneralButtonElement.TYPE_ERROR, GeneralDialog::remove)
    .create()
    .show();

图5 CommonDialog对话框场景示例的效果图

该示例中,也可设置图标,但注意设置图标后标题会被隐藏。另外,addButton最多只能添加三个按钮,多次调用无效。本示例的GeneralDialog.Builder中还有一些其他的接口,您可以自行调用查看效果。

0 0 投票数
文章评分
订阅评论
提醒
0 评论
内联反馈
查看所有评论
0
希望看到您的想法,请您发表评论x