评论

收藏

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

移动开发 移动开发 发布于:2021-06-28 16:22 | 阅读数:551 | 评论:0

  目录:
  1、引言
  2、功能介绍
  3、BGABadgeView 使用指南
  4、BGABadgeView 开发指南
  5、《HarmonyOS三方件开发指南》系列文章合集
  引言
  现在很多的APP会有新消息/未接来电/未读消息/新通知圆球红点提示,典型的以微信、QQ新消息提示为例,当微信朋友圈有新的朋友更新/发布朋友圈消息后,在微信的底部切换卡上会有一个红色的小圆球红点,表示有新消息,提示用户查看。在消息通讯类的app中十分实用。
  功能介绍
  鸿蒙BGABadgeView 徽章组件,主要功能包括:传入图片生成徽章,设置文本生成文本徽章,并且每个徽章都具有拖拽超范围即可消除,范围内即可回到原位置。模拟机效果图如下
  1.图片徽章:
DSC0000.png DSC0001.png

  2.文字徽章:
DSC0002.png

  3.拖动徽章爆炸: DSC0003.png
  使用时候,直接将其下载,作为一个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,如图:
   DSC0004.png 新建一个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包。
DSC0005.png

  更多原创,请关注:软通动力HarmonyOS学院https://harmonyos.51cto.com/column/30
  作者:软通田可辉
  想了解更多内容,请访问51CTO和华为合作共建的鸿蒙社区:https://harmonyos.51cto.com

关注下面的标签,发现更多相似文章