引言
现在很多的APP会有新消息/未接来电/未读消息/新通知圆球红点提示,典型的以微信、QQ新消息提示为例,当微信朋友圈有新的朋友更新/发布朋友圈消息后,在微信的底部切换卡上会有一个红色的小圆球红点,表示有新消息,提示用户查看。在消息通讯类的app中十分实用。
功能介绍
鸿蒙BGABadgeView 徽章组件,主要功能包括:传入图片生成徽章,设置文本生成文本徽章,并且每个徽章都具有拖拽超范围即可消除,范围内即可回到原位置。模拟机效果图如下
图片徽章:
文字徽章:
拖动徽章爆炸:
使用时候,直接将其下载,作为一个har包导入到自己的项目中即可。下面则详细介绍BGABadgeView 的使用以及开发指南。
BGABadgeView 使用指南
Ø 新建工程, 添加组件Har包依赖
在应用模块中添加HAR,只需要将verificationcodeview-debug.har复制到entry\libs目录下即可
Ø 修改配置文件
修改主页面的布局文件:
- "1.0" encoding="utf-8"?>
- xmlns:ohos="http://schemas.huawei.com/res/ohos"
- ohos:height="match_parent"
- ohos:width="match_parent"
- ohos:id="$+id:layout1"
- ohos:orientation="vertical">
-
- ohos:id="$+id:dependent1"
- ohos:height="200vp"
- ohos:width="match_parent">
-
-
- 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"/>
-
- 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"/>
-
-
- 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"/>
-
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
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类
实现自定义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包。