HarmonyOS三方件开发指南(19)-BGABadgeView徽章组件

想了解更多内容,开件请访问:

和华为官方合作共建的章组鸿蒙技术社区

https://harmonyos.51cto.com

引言

现在很多的APP会有新消息/未接来电/未读消息/新通知圆球红点提示,典型的开件以微信、QQ新消息提示为例,章组当微信朋友圈有新的开件朋友更新/发布朋友圈消息后,在微信的章组底部切换卡上会有一个红色的小圆球红点,表示有新消息,开件提示用户查看。章组在消息通讯类的开件app中十分实用。

功能介绍

鸿蒙BGABadgeView 徽章组件,章组主要功能包括:传入图片生成徽章,开件设置文本生成文本徽章,章组并且每个徽章都具有拖拽超范围即可消除,网站模板开件范围内即可回到原位置。章组模拟机效果图如下

1.图片徽章:

2.文字徽章:

3.拖动徽章爆炸:

使用时候,开件直接将其下载,作为一个har包导入到自己的项目中即可。下面则详细介绍BGABadgeView 的使用以及开发指南。

BGABadgeView 使用指南

Ø 新建工程, 添加组件Har包依赖

在应用模块中添加HAR,只需要将verificationcodeview-debug.har复制到entry\libs目录下即可

Ø 修改配置文件

1. 修改主页面的布局文件:

<?xml version="1.0" encoding="utf-8"?> <DependentLayout     xmlns:ohos="http://schemas.huawei.com/res/ohos"     ohos:height="match_parent"     ohos:width="match_parent"     ohos:id="$+id:layout1"     ohos:orientation="vertical">     <DependentLayout         ohos:id="$+id:dependent1"         ohos:height="200vp"         ohos:width="match_parent">          <com.example.bgabadgecomp_library.BAGDragBadgeImage             ohos:top_margin="15vp"             ohos:right_margin="10vp"             ohos:bottom_margin="10vp"             ohos:height="80vp"             ohos:width="80vp"             ohos:scale_mode="zoom_center"             ohos:image_src="$media:avator"             ohos:id="$+id:image1"             ohos:below="$id:title"             ohos:left_margin="30vp"/>         <Image             ohos:top_margin="15vp"             ohos:right_margin="10vp"             ohos:bottom_margin="10vp"             ohos:height="80vp"             ohos:width="80vp"             ohos:scale_mode="zoom_center"             ohos:image_src="$media:avator"             ohos:id="$+id:image2"             ohos:end_of="$id:image1"             ohos:below="$id:title"             ohos:left_margin="10vp"/>            </DependentLayout>         <Text             ohos:left_margin="30vp"             ohos:id="$+id:text1"             ohos:top_margin="10vp"             ohos:right_margin="15vp"             ohos:bottom_margin="10vp"             ohos:height="40vp"             ohos:width="match_parent"             ohos:text="测试1"             ohos:below="$id:dependent1"             ohos:text_size="20vp"/> </DependentLayout> 

 2.修改MainAbilitySlice中的UI加载代码

在MainAbilitySlince类的onStart函数中,增加如下代码:

@Override public void onStart(Intent intent) {      super.onStart(intent);     super.setUIContent(ResourceTable.Layout_ability_main);      BAGDragBadgeImage bagDragBadgeImage = (BAGDragBadgeImage) findComponentById(ResourceTable.Id_image1);     bagDragBadgeImage.setCornerRadius(bagDragBadgeImage.getWidth() / 2); // 圆形边框     DependentLayout stackLayout = (DependentLayout) findComponentById(ResourceTable.Id_layout1);      Image image2 = (Image) findComponentById(ResourceTable.Id_image2);     image2.setCornerRadius(20);      DependentLayout.LayoutConfig config = new DependentLayout.LayoutConfig(DependentLayout.LayoutConfig.MATCH_PARENT, DependentLayout.LayoutConfig.MATCH_PARENT);      RoundRectImage roundRectImage = RoundRectImage.attach2Window(this, stackLayout, image2, config, BGABadgeViewHelper.getPixelMap(this, ResourceTable.Media_avatar_vip));      RoundRectText roundRectText = RoundRectText.attach2Window(this, stackLayout, image3, config);      Text text1  = (Text) findComponentById(ResourceTable.Id_text1);     RoundRectText roundText1 = RoundRectText.attach2Window(this, stackLayout, text1, config);     roundText1.setBadgeText("qqqqqqqq");     List<Component> componentList = new ArrayList<>();     componentList.add(roundRectText);     componentList.add(roundText1);      stackLayout.setTouchEventListener(new Component.TouchEventListener() {          @Override         public boolean onTouchEvent(Component component, TouchEvent event) {               switch (event.getAction()) {                  case TouchEvent.PRIMARY_POINT_DOWN:// 手指第一次触摸到屏幕                     int startX = (int) event.getPointerPosition(event.getIndex()).getX();                     int startY = (int) event.getPointerPosition(event.getIndex()).getY();                    if (startX < roundRectImage.getCircleLeft() + 2 * roundRectImage.getCircleRadius()                            && startX > roundRectImage.getCircleLeft()                            && startY < roundRectImage.getCircleTop() + 2 * roundRectImage.getCircleRadius()                            && startY > roundRectImage.getCircleTop()) {                         roundRectImage.setDraggedListener(DRAG_HORIZONTAL_VERTICAL, roundRectImage );                         for (Component component1 : componentList) {                             component1.setDraggedListener(DRAG_HORIZONTAL_VERTICAL,null);                        }                    } else {                         roundRectImage.setDraggedListener(DRAG_HORIZONTAL_VERTICAL, null );                         for (Component component1 : componentList) {                             RoundRectText rectText = (RoundRectText) component1;                            if (startX < rectText.getCircleLeft() + 2 * rectText.getRadius()                                    && startX > rectText.getCircleLeft()                                    && startY < rectText.getCircleTop() + 2 * rectText.getRadius()                                    && startY > rectText.getCircleTop()) {                                 component1.setDraggedListener(DRAG_HORIZONTAL_VERTICAL, (Component.DraggedListener) component1);                            } else {                                 component1.setDraggedListener(DRAG_HORIZONTAL_VERTICAL,null);                            }                        }                    }                      break;                 case TouchEvent.PRIMARY_POINT_UP:                 case TouchEvent.POINT_MOVE:                 default:                     break;             }             return true;         }     }); } 

 复制通过以上两个步骤,就实现了简单的徽章组件,接下来在一起看下徽章组件是如何实现的。源码库

BGABadgeView 开发指南

新建一个Module

新建一个Module,类型选择HarmonyOS Library,模块名为VerificationCodeView,如图:

新建一个RoundRectText类

1.实现自定义RoundRectText绘制

@Override public void onDraw(Component component, Canvas canvas){      length = mBadgeText.length();     Paint mTextPain = new Paint();     mTextPain.setColor(Color.WHITE);     mTextPain.setStyle(Paint.Style.FILL_STYLE);     mTextPain.setTextSize(30);     mTextPain.setFont(Font.DEFAULT);     Rect textBounds = mTextPain.getTextBounds(mBadgeText);      Paint mBadgePaint = new Paint();     mBadgePaint.setColor(Color.RED);     mBadgePaint.setStyle(Paint.Style.FILL_STYLE);     mBadgePaint.setStrokeWidth(5);     if (mBadgeRectF == null) {          switch (mBadgeGravity) {              case RightTop:                 int left = mComponent.getLeft();                 int top = mComponent.getTop();                 circleLeft = mComponent.getWidth() + left - 2 * radius - 15 * (length - 2);                 circleTop = top;                 mBadgeRectF = new RectFloat( circleLeft, circleTop, circleLeft + 2 * radius + 15 * (length - 2)  , circleTop + 2 * radius);                 break;             case RightCenter:                 left = mComponent.getLeft();                 top = mComponent.getTop();                 circleLeft = mComponent.getWidth() + left - 2 * radius - 15 * (length - 2);                 circleTop = top + (float)mComponent.getHeight() / 2 - radius;                 mBadgeRectF = new RectFloat( circleLeft, circleTop, circleLeft + 2 * radius + 15 * (length - 2) , circleTop + 2 * radius);                  break;             case RightBottom:                 mBadgeRectF = new RectFloat();                 left = mComponent.getLeft();                 top = mComponent.getTop();                 circleLeft = mComponent.getWidth() + left - 2 * radius - 15 * (length - 2) ;                 circleTop = top + mComponent.getHeight() - 2 * radius;                 mBadgeRectF = new RectFloat( circleLeft, circleTop, circleLeft + 2 * radius + 15 * (length - 2) , circleTop + 2 * radius);                  break;             default:                 break;         }     }     path = (float) Math.sqrt((mBadgeRectF.left - circleLeft) * (mBadgeRectF.left - circleLeft) + (mBadgeRectF.top - circleTop) * (mBadgeRectF.top - circleTop));     isOverPath = path > overPath;     float offSet = (float) (textBounds.top + textBounds.bottom) / 2;     float boundsX = 0 ;     if( 15 * length < (mBadgeRectF.right - mBadgeRectF.left)){         float temp =  mBadgeRectF.right - mBadgeRectF.left - 15 * length;         boundsX = temp / 2;     }    float roundNum = 2 * radius / (mBadgeRectF.right - mBadgeRectF.left) ;     canvas.drawRoundRect(mBadgeRectF,roundNum * radius ,roundNum * radius, mBadgePaint);     canvas.drawText(mTextPain, mBadgeText, mBadgeRectF.left + boundsX, mBadgeRectF.top + radius - offSet); } 

 2.生成拖拽事件

@Override public void onDragDown(Component component, DragInfo dragInfo) {       pointX = dragInfo.downPoint.getPointX();      pointY = dragInfo.downPoint.getPointY();     if (pointX <= circleLeft || pointX >= circleLeft + 2 * radius + 15 * (length - 2)             || pointY <= circleTop || pointY >= circleTop + 2 * radius) {          onDragCancel(component, dragInfo);     } }  @Override public void onDragStart(Component component, DragInfo dragInfo) {  } @Override public void onDragUpdate(Component component, DragInfo dragInfo) {       float left = mBadgeRectF.left;     float right = mBadgeRectF.right;     float top = mBadgeRectF.top;     float bottom = mBadgeRectF.bottom;      if (pointX <= circleLeft || pointX >= circleLeft + 2 * radius + 15 * (length - 2)             || pointY <= circleTop || pointY >= circleTop + 2 * radius) {          onDragCancel(component, dragInfo);     } else {          mBadgeRectF.left = (float) (left + dragInfo.xOffset);         mBadgeRectF.right = (float) (right + dragInfo.xOffset);         mBadgeRectF.top = (float) (top + dragInfo.yOffset);         mBadgeRectF.bottom = (float) (bottom + dragInfo.yOffset);         invalidate();     }  } @Override public void onDragEnd(Component component, DragInfo dragInfo) {      if (isOverPath) {          explosionField.explode(component, mBadgeRectF, explosionFieldColor);     } else {          mBadgeRectF = new RectFloat(circleLeft, circleTop , circleLeft + 2 * radius + 15 * (length - 2), circleTop + 2 * radius);         invalidate();     } } @Override public void onDragCancel(Component component, DragInfo dragInfo) {      mBadgeRectF = new RectFloat(circleLeft, circleTop , circleLeft + 2 * radius + 15 * (length - 2), circleTop + 2 * radius);     invalidate(); } 

 具体代码请下载项目查看。

编译HAR包

利用Gradle可以将HarmonyOS Library库模块构建为HAR包,构建HAR包的方法如下:

在Gradle构建任务中,双击PackageDebugHar或PackageReleaseHar任务,构建Debug类型或Release类型的HAR。

待构建任务完成后,可以在工程目录中的VerificationCodeView> bulid > outputs > har目录中,获取生成的HAR包。

想了解更多内容,请访问:

和华为官方合作共建的鸿蒙技术社区

https://harmonyos.51cto.com

-->
IT科技
上一篇:vivo 短视频用户访问体验优化实践
下一篇:苹果 M3 Ultra 芯片规格曝光:最高 32 核 CPU、80 核 GPU