DEV Community

Cover image for HarmonyOS Development: Realizing Popup Bubble Prompt
程序员一鸣
程序员一鸣

Posted on

HarmonyOS Development: Realizing Popup Bubble Prompt

Foreword 

this article is based on Api13 

bubble prompt is used in many scenarios, such as common WeChat conversation chat, long press a message, a bubble prompt will pop up, or click the plus sign in the upper right corner, a bubble selection will also pop up, which can be said to be widely used. 

As follows, when a message is long pressed: 

Image description

when clicking the plus sign in the upper right corner: 

Image description

the above effect can be realized very quickly in Hongmeng development. After all, each component has a common attribute. bindPopup , using bindPopup can quickly implement a bubble, and bind to which component you want to pop up. 

The simple case is as follows:

 

@Entry
@Component
struct Index {
  @State isShowPopup: boolean = false

  build() {
    Column() {
      Button("点击")
        .onClick(() => {
          this.isShowPopup = !this.isShowPopup
        })
        .bindPopup(this.isShowPopup, {
          message: "我是一个简单的气泡",
          onStateChange: (e) => {
            this.isShowPopup = e.isVisible
          }
        })
    }
    .width("100%")
    .height("100%")
    .justifyContent(FlexAlign.Center)
  }
}
Enter fullscreen mode Exit fullscreen mode

the effect is as follows: 

Image description

in this article, we will walk into the use of bindPopup together, and in the end, we will also implement a custom Popup bubble prompt in our own way. 

I. bindPopup General Tips 

the simplest is a common text prompt, that is, the case in the preface. Just set a message directly. The display and hiding of bubbles can be controlled through the first boolean type parameter. In addition to these two parameters, it has many attributes to choose from. Let's briefly summarize some of the more commonly used ones. 

Arrow Control enableArrow 

bubbles have arrows by default. If you want to hide arrows, you can use the attributeEnable Arrow to control, set false.

 

 enableArrow: false, //隐藏箭头
Enter fullscreen mode Exit fullscreen mode

If we look at the effect after setting, we can see that the arrow has been hidden. 

Image description

Fillet radius 

the default fillet radius is 20vp, if you want to change it, you can pass radius property to control, such as setting the fillet radius to 0, the code is as follows:

 

radius:0,//圆角半径
Enter fullscreen mode Exit fullscreen mode

the effect is as follows: you can see that the fillet radius is already 0. 

Image description

Background Color popupColor


 

  /**
     * Set the background color of the popup.
     *
     * @type { ?(Color | string | Resource | number) }
     * @syscap SystemCapability.ArkUI.ArkUI.Full
     * @crossplatform
     * @atomicservice
     * @since 12
     */
    popupColor?: Color | string | Resource | number;
Enter fullscreen mode Exit fullscreen mode

from the above source code, we can see that popupColor supports four types of parameters: Color, string, Resource, and number. 

We can directly select one of the types to pass.

 

 popupColor: Color.Pink,
Enter fullscreen mode Exit fullscreen mode

If you only set this attribute, you will find that the background color flashes by and does not show the color we specified. This is caused by the fuzzy background fill effect backgroundBlurStyle. Just set backgroundBlurStyle to BlurStyle.NONE.

 

 backgroundBlurStyle: BlurStyle.NONE,
Enter fullscreen mode Exit fullscreen mode

Looking at the effect again, we can find that the background has changed. 

Image description

mask color 

the default mask is transparent. If you want to change the color of the mask, you can use it. mask to set.

  /**
     * The mask to block gesture events of popup.
     * When mask is set false, gesture events are not blocked.
     * When mask is set true, gesture events are blocked and mask color is transparent.
     *
     * @type { ?(boolean | { color: ResourceColor }) }
     * @syscap SystemCapability.ArkUI.ArkUI.Full
     * @crossplatform
     * @atomicservice
     * @since 11
     */
    mask?: boolean | {
        color: ResourceColor;
    };
Enter fullscreen mode Exit fullscreen mode

Through the source code, we can see that mask not only supports color, but also supports a boolean type. Its function is to not display the mask layer if set to false. If set to true, a transparent color mask layer will be displayed. 

We can use color directly. For example, I want to set the mask color to 80% transparent color. The code is as follows:

 

mask:{color:"#80000000"}
Enter fullscreen mode Exit fullscreen mode

the effect is as follows: 

Image description

set Spacing targetSpace 

if you need to modify the spacing between the bubble pop-up window and the target component, you can use targetSpace attribute to modify the parameter class the type is Length, for example, I modify the spacing with the target component to 20.

 

targetSpace:20
Enter fullscreen mode Exit fullscreen mode

The effect is as follows. It can be seen that compared with the default, the obvious spacing is larger. 

Image description

Display position placement 

by property placement, we can set the display position of the bubble pop-up window, the default position is the bottom display, which is placement.Bottom, with the following values to choose from: 

name  description 
Left  the bubble tip is located on the left side of the component, aligned with the left center of the component. 
Right  the bubble tip is on the right side of the component, aligned with the right center of the component. 
Top The bubble tip is located on the upper side of the Assembly and aligned with the center of the upper side of the Assembly. 
Bottom  the bubble tip is located on the underside of the Assembly, aligned with the center of the underside of the Assembly. 
TopLeft  the Bubble tip is located on the upper side of the component, starting from API Version 9 and aligned with the left edge of the component. 
TopRight  the bubble prompt is located on the upper side of the component, starting from API Version 9, and aligned with the right edge of the component. 
BottomLeft  the bubble tip is located on the lower side of the component, starting from API Version 9 and aligned with the left edge of the component. 
BottomRight  the bubble tip is located on the lower side of the component, starting from API Version 9 and aligned with the right edge of the component. 
LeftTop 9 +  the bubble tip is located on the left side of the Assembly, aligned with the upper edge of the Assembly. 
LeftBottom 9 +  the bubble tip is located on the left side of the Assembly, aligned with the lower edge of the Assembly. 
RightTop 9 +  the bubble tip is located on the right side of the Assembly, aligned with the upper edge of the Assembly. 
RightBottom 9 + The bubble tip is located on the right side of the Assembly, aligned with the lower edge of the Assembly. 

For example, if I want to set the display on the top, I can set it as follows:

 

placement:Placement.Top
Enter fullscreen mode Exit fullscreen mode

the effect is as follows: 

Image description

in addition to the above common attributes, there are many optional attributes, such as the position of the Arrow, offset, focus, width and bubble state monitoring, etc., which will not be repeated here. If you know, you can go to official website to check. 

Some friends may ask questions. My bubble prompt is not a simple text prompt, but a complex view like WeChat. How to implement it? This implementation is also very simple, through the builder attribute. 

Second, bindPopup custom components. 

In addition to simple text prompts, bindPopup also provides us with an attribute that can be passed on to custom components, that is, builder. Through builder, we can draw views ourselves and achieve various layout effects. 

Simple case:

@Entry
@Component
struct Index {
  @State isShowPopup: boolean = false

  @Builder
  popupBuilder() {
    Column() {
      ForEach([1, 2, 3, 4, 5], (item: number) => {
        Row() {
          Image($r("app.media.app_icon"))
            .width(20)
            .height(20)
          Text("条目" + item)
            .textAlign(TextAlign.Center)
            .margin({ left: 5 })
        }.width(100)
        .height(40)
        .justifyContent(FlexAlign.Center)
        .border({ width: { bottom: 1 }, color: "#e8e8e8" })
      })
    }
  }

  build() {
    Column() {
      Button("点击")
        .onClick(() => {
          this.isShowPopup = !this.isShowPopup
        })
        .bindPopup(this.isShowPopup, {
          builder: this.popupBuilder,
          radius: 5,
          onStateChange: (e) => {
            this.isShowPopup = e.isVisible
          }
        })
    }
    .width("100%")
    .height("100%")
    .justifyContent(FlexAlign.Center)
  }
}
Enter fullscreen mode Exit fullscreen mode

the effect is as follows:

Image description

the above two methods can basically meet the vast majority of our bubble needs, but some friends have also said that it is a bit troublesome to bind a bubble. Is there a way to play as I like without binding? Alas, this is possible, that is, through openCustomDialog. 

Three, dialog library implementation 

through openCustomDialog, we can draw any component pop-up window by ourselves and realize popup bubble prompt in the form of dialog. Only what needs to be determined is the coordinate position of the display component. This is summarized in the next article. In this article, we will only briefly understand the specific usage.

Choose one of the two dependency methods. 

Method 1: in the Terminal window, run the following command to install the third-party package. DevEco Studio automatically adds the third-party package dependency to the project oh-package.json5. 

Suggestion: Execute the command under the module path used.


ohpm install @abner/dialog
Enter fullscreen mode Exit fullscreen mode

Method 2: Set the three-party package dependency in the project oh-package.json5. The configuration example is as follows. The latest version is 1.2.0.

 

"dependencies": { "@abner/dialog": "^1.2.0"}
Enter fullscreen mode Exit fullscreen mode

Simple to use

 

import { showPopupWindow, PopupDirection } from "@abner/dialog"

@Builder
function popupBuilder() {
  Column() {
    ForEach([1, 2, 3, 4, 5], (item: number) => {
      Row() {
        Image($r("app.media.app_icon"))
          .width(20)
          .height(20)
        Text("条目" + item)
          .textAlign(TextAlign.Center)
          .margin({ left: 5 })
          .fontColor(Color.White)
      }.width(100)
      .height(40)
      .justifyContent(FlexAlign.Center)
      .border({ width: { bottom: 1 }, color: "#e8e8e8" })
    })
  }.backgroundColor(Color.Black)
  .margin({ top: 10 })
}

@Entry
@Component
struct Index {
  build() {
    Column() {
      Button("点击")
        .id("popupBottom")
        .onClick(() => {
          showPopupWindow({
            id: "popupBottom",
            view: wrapBuilder(popupBuilder),
            direction: PopupDirection.BOTTOM,
          })
        })
    }
    .width("100%")
    .height("100%")
    .justifyContent(FlexAlign.Center)
  }
}
Enter fullscreen mode Exit fullscreen mode

effect display 

Image description

support many directions, such as upper left and lower right, upper left and lower right, lower left and upper right, which can be controlled by direction. 

Pop up


 

showPopupWindow({
            id: "popupTop",
            view: wrapBuilder(BuilderWindowView)
          })
Enter fullscreen mode Exit fullscreen mode

pop down


 

showPopupWindow({
  id: "popupBottom",
  view: wrapBuilder(BuilderWindowView),
  direction: PopupDirection.BOTTOM
})
Enter fullscreen mode Exit fullscreen mode

carry parameters


 

let params = new WindowParams()
          params.title = "我是携带的参数"
          showPopupWindow({
            id: "popupParams",
            params: params,
            viewParams: wrapBuilder(BuilderWindowParams),
            direction: PopupDirection.BOTTOM
          })
Enter fullscreen mode Exit fullscreen mode

update data


 

let params = new WindowParams()
    params.title = "嘿嘿,我更新了"
    updatePopupData(params)
Enter fullscreen mode Exit fullscreen mode

arbitrary position


 

showPopupWindow({
  view: wrapBuilder(BuilderWindowView),
  x: 60,
  y: 300
})
Enter fullscreen mode Exit fullscreen mode

related Summary 

the native bindPopup attribute not only supports a single text prompt, but also supports the form of custom components. It can already meet the normal requirements for development. If you can use the native, you can use the native. The reason why a popup bubble pop-up window was added to the dialog Library was because the native did not support the form of custom components at the time of packaging. Now it has been supported, and you can safely use the native. 

Of course, if you don't want to implement the binding form and want to pop up freely, you can use the one provided in the dialog library, and an id can be located on the component that needs to be popped up, which is also very simple to use. 

Article tags: HarmonyOSNext/ArkUI

Top comments (0)