diff --git a/UI/CustomComponent/README.md b/UI/CustomComponent/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..70cd5653279e14f1b65f2b4c664826889262b041
--- /dev/null
+++ b/UI/CustomComponent/README.md
@@ -0,0 +1,22 @@
+# CustomComponent
+
+- [Introduction](#section9327887216)
+- [Usage](#section3453161502117)
+- [Constraints](#section1565727162211)
+
+## Introduction
+
+You can use the Java UI framework to customize components, add custom draw tasks, and define component attributes and event responses. This example shows how to use custom components.
+
+## Usage
+
+The procedure for using this example is as follows:
+
+On the application home screen, click **annulus**. A yellow circle is displayed. You can click the circle to change its color.
+
+Click **controllers**. A circular progress control is displayed. You can click the circle to change the progress.
+
+## Constraints
+
+This example can be run only on a standard system.
+
diff --git a/UI/CustomComponent/README_zh.md b/UI/CustomComponent/README_zh.md
new file mode 100644
index 0000000000000000000000000000000000000000..eb2e2f683694a3d532749f8873ac2c2b3b8cac3c
--- /dev/null
+++ b/UI/CustomComponent/README_zh.md
@@ -0,0 +1,16 @@
+# 自定义组件
+
+
+
+### 简介
+
+本示例展示了自定义组件的使用方法,当JAVA UI框架提供的组件无法满足需求时,可以自定义组件,添加自定义绘制任务,并定义组件的属性和事件响应。
+
+### 使用说明
+
+本事例使用步骤:进入应用主界面后,点击annulus,跳转页面,出现黄色圆环,点击圆环改变其颜色;点击controllers,跳转页面,出现环形进度控制器,点击环形可改变其进度。
+
+### 约束和限制
+
+本示例支持在标准系统上运行
+
diff --git a/UI/CustomComponent/build.gradle b/UI/CustomComponent/build.gradle
new file mode 100644
index 0000000000000000000000000000000000000000..f2c4805ecb88f4a659a10a42bb9f4d12928b0b5d
--- /dev/null
+++ b/UI/CustomComponent/build.gradle
@@ -0,0 +1,34 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+apply plugin: 'com.huawei.ohos.app'
+
+ohos {
+ compileSdkVersion 5
+ defaultConfig {
+ compatibleSdkVersion 4
+ }
+}
+buildscript {
+ repositories {
+ maven {
+ url 'https://mirrors.huaweicloud.com/repository/maven/'
+ }
+ maven {
+ url 'https://developer.huawei.com/repo/'
+ }
+ jcenter()
+ }
+ dependencies {
+ classpath 'com.huawei.ohos:hap:2.4.4.2'
+ }
+}
+allprojects {
+ repositories {
+ maven {
+ url 'https://mirrors.huaweicloud.com/repository/maven/'
+ }
+ maven {
+ url 'https://developer.huawei.com/repo/'
+ }
+ jcenter()
+ }
+}
\ No newline at end of file
diff --git a/UI/CustomComponent/entry/build.gradle b/UI/CustomComponent/entry/build.gradle
new file mode 100644
index 0000000000000000000000000000000000000000..67dd713bacdf1e94c64521ff59265cf56ad0dfde
--- /dev/null
+++ b/UI/CustomComponent/entry/build.gradle
@@ -0,0 +1,10 @@
+apply plugin: 'com.huawei.ohos.hap'
+ohos {
+ compileSdkVersion 5
+ defaultConfig {
+ compatibleSdkVersion 4
+ }
+}
+dependencies {
+ implementation fileTree(dir: 'libs', include: ['*.jar'])
+}
diff --git a/UI/CustomComponent/entry/src/main/config.json b/UI/CustomComponent/entry/src/main/config.json
new file mode 100644
index 0000000000000000000000000000000000000000..a63d46be8309c581901413c14da8248ca85b3890
--- /dev/null
+++ b/UI/CustomComponent/entry/src/main/config.json
@@ -0,0 +1,44 @@
+{
+ "app": {
+ "bundleName": "ohos.samples.customcomponent",
+ "version": {
+ "code": 1000000,
+ "name": "1.0"
+ }
+ },
+ "deviceConfig": {},
+ "module": {
+ "package": "ohos.samples.customcomponent",
+ "name": ".MainAbility",
+ "deviceType": [
+ "phone"
+ ],
+ "distro": {
+ "deliveryWithInstall": true,
+ "moduleName": "entry",
+ "moduleType": "entry",
+ "installationFree":false
+ },
+ "abilities": [
+ {
+ "skills": [
+ {
+ "entities": [
+ "entity.system.home"
+ ],
+ "actions": [
+ "action.system.home"
+ ]
+ }
+ ],
+ "orientation": "portrait",
+ "name": "ohos.samples.customcomponent.MainAbility",
+ "icon": "$media:icon",
+ "description": "$string:mainability_description",
+ "label": "$string:app_name",
+ "type": "page",
+ "launchType": "standard"
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/UI/CustomComponent/entry/src/main/java/ohos/samples/customcomponent/MainAbility.java b/UI/CustomComponent/entry/src/main/java/ohos/samples/customcomponent/MainAbility.java
new file mode 100644
index 0000000000000000000000000000000000000000..670c9db5dc0c028bfd52ad91430306342485d2f6
--- /dev/null
+++ b/UI/CustomComponent/entry/src/main/java/ohos/samples/customcomponent/MainAbility.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ohos.samples.customcomponent;
+
+import ohos.aafwk.ability.Ability;
+import ohos.aafwk.content.Intent;
+import ohos.samples.customcomponent.slice.MainAbilitySlice;
+
+/**
+ * MainAbility
+ *
+ * @since 2021-05-08
+ */
+public class MainAbility extends Ability {
+ @Override
+ public void onStart(Intent intent) {
+ super.onStart(intent);
+ super.setMainRoute(MainAbilitySlice.class.getName());
+ }
+}
diff --git a/UI/CustomComponent/entry/src/main/java/ohos/samples/customcomponent/modle/CustomComponent.java b/UI/CustomComponent/entry/src/main/java/ohos/samples/customcomponent/modle/CustomComponent.java
new file mode 100644
index 0000000000000000000000000000000000000000..a5624469eed4b44300687f10ccd16e6074d1976e
--- /dev/null
+++ b/UI/CustomComponent/entry/src/main/java/ohos/samples/customcomponent/modle/CustomComponent.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2021 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ohos.samples.customcomponent.modle;
+
+import ohos.agp.components.AttrSet;
+import ohos.agp.components.Component;
+import ohos.agp.render.Canvas;
+import ohos.agp.render.Paint;
+import ohos.agp.utils.Color;
+import ohos.app.Context;
+import ohos.hiviewdfx.HiLog;
+import ohos.hiviewdfx.HiLogLabel;
+import ohos.multimodalinput.event.TouchEvent;
+
+/**
+ * CustomComponent
+ *
+ * @since 2021-05-08
+ */
+public class CustomComponent extends Component implements Component.EstimateSizeListener, Component.DrawTask,
+ Component.TouchEventListener {
+ private static final String TAG = CustomComponent.class.getSimpleName();
+
+ private static final HiLogLabel LABEL_LOG = new HiLogLabel(3, 0xD000F00, TAG);
+
+ private static final float CIRCLE_STROKE_WIDTH = 100f;
+
+ private static final float Y = 500;
+
+ private static final float RADIUS = 300;
+
+ private float X;
+
+ private Paint circlePaint;
+
+ private boolean isColor = false;
+
+ /**
+ * customcomponent
+ *
+ * @param context Indicates the Context
+ * @param attrSet attrset
+ */
+ public CustomComponent(Context context, AttrSet attrSet) {
+ super(context, attrSet);
+ setEstimateSizeListener(this);
+ setTouchEventListener(this);
+ initPaint();
+ addDrawTask(this);
+ }
+
+ @Override
+ public boolean onEstimateSize(int widthEstimateConfig, int heightEstimateConfig) {
+ int width = Component.EstimateSpec.getSize(widthEstimateConfig);
+ int height = Component.EstimateSpec.getSize(heightEstimateConfig);
+ setEstimatedSize(Component.EstimateSpec.getChildSizeWithMode(width, height, EstimateSpec.NOT_EXCEED),
+ Component.EstimateSpec.getChildSizeWithMode(width, height, EstimateSpec.NOT_EXCEED));
+ X = width;
+ return true;
+ }
+
+ private void initPaint() {
+ circlePaint = new Paint();
+ circlePaint.setColor(Color.YELLOW);
+ circlePaint.setStrokeWidth(CIRCLE_STROKE_WIDTH);
+ circlePaint.setStyle(Paint.Style.STROKE_STYLE);
+ }
+
+ @Override
+ public void onDraw(Component component, Canvas canvas) {
+ canvas.drawCircle(X / 2, Y, RADIUS, circlePaint);
+ }
+
+ @Override
+ public boolean onTouchEvent(Component component, TouchEvent touchEvent) {
+ HiLog.info(LABEL_LOG, "onTouchEvent");
+ if (touchEvent.getAction() == TouchEvent.PRIMARY_POINT_DOWN) {
+ if (!isColor) {
+ circlePaint.setColor(Color.GREEN);
+ } else {
+ circlePaint.setColor(Color.YELLOW);
+ }
+ invalidate();
+ isColor = !isColor;
+ }
+ return false;
+ }
+}
diff --git a/UI/CustomComponent/entry/src/main/java/ohos/samples/customcomponent/modle/CustomControlBar.java b/UI/CustomComponent/entry/src/main/java/ohos/samples/customcomponent/modle/CustomControlBar.java
new file mode 100644
index 0000000000000000000000000000000000000000..ba6f161a771e946385b63e2d5c3d474989600c1c
--- /dev/null
+++ b/UI/CustomComponent/entry/src/main/java/ohos/samples/customcomponent/modle/CustomControlBar.java
@@ -0,0 +1,211 @@
+/*
+ * Copyright (c) 2021 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ohos.samples.customcomponent.modle;
+
+import ohos.agp.components.AttrSet;
+import ohos.agp.components.Component;
+import ohos.agp.render.Arc;
+import ohos.agp.render.Canvas;
+import ohos.agp.render.Paint;
+import ohos.agp.render.PixelMapHolder;
+import ohos.agp.utils.Color;
+import ohos.agp.utils.Point;
+import ohos.agp.utils.RectFloat;
+import ohos.app.Context;
+import ohos.hiviewdfx.HiLog;
+import ohos.hiviewdfx.HiLogLabel;
+import ohos.media.image.PixelMap;
+import ohos.media.image.common.Size;
+import ohos.multimodalinput.event.MmiPoint;
+import ohos.multimodalinput.event.TouchEvent;
+import ohos.samples.customcomponent.ResourceTable;
+import ohos.samples.customcomponent.utils.Util;
+
+/**
+ * CustomControlBar
+ *
+ * @since 2021-05-08
+ */
+public class CustomControlBar extends Component implements Component.DrawTask, Component.EstimateSizeListener,
+ Component.TouchEventListener {
+ private static final String TAG = CustomComponent.class.getSimpleName();
+
+ private static final HiLogLabel LABEL_LOG = new HiLogLabel(3, 0xD000F00, TAG);
+
+ private static final float CIRCLE_ANGLE = 360.0f;
+
+ private static final int DEF_UNFILL_COLOR = 0xFF808080;
+
+ private static final int DEF_FILL_COLOR = 0xFF1E90FF;
+
+ private static final int COUNT = 10;
+
+ private static final int SPLIT_SIZE = 15;
+
+ private static final int CIRCLE_WIDTH = 60;
+
+ private static final int MARGIN = 50;
+
+ private static final int TWO = 2;
+
+ private static final int ANGLE = 90;
+
+ private static final double POOR = 0.4;
+
+ private static final double NUM_TWO = 2.0;
+
+ private static final float NUM_ONE = 1.0f;
+
+ private Color unFillColor;
+
+ private Color fillColor;
+
+ private final Paint paint;
+
+ private int currentCount;
+
+ private RectFloat centerRectFloat;
+
+ private PixelMap image;
+
+ private Point centerPoint;
+
+ /**
+ * customcontrolbar
+ *
+ * @param context Indicates the Context
+ * @param attrSet attrset
+ */
+ public CustomControlBar(Context context, AttrSet attrSet) {
+ super(context, attrSet);
+ paint = new Paint();
+ initData();
+ setEstimateSizeListener(this);
+ setTouchEventListener(this);
+ addDrawTask(this);
+ }
+
+ private void initData() {
+ unFillColor = new Color(DEF_UNFILL_COLOR);
+ fillColor = new Color(DEF_FILL_COLOR);
+ currentCount = TWO;
+ centerRectFloat = new RectFloat();
+ image = Util.createPixelMapByResId(ResourceTable.Media_icon, getContext()).get();
+ }
+
+ @Override
+ public void onDraw(Component component, Canvas canvas) {
+ HiLog.info(LABEL_LOG, "onDraw");
+ paint.setAntiAlias(true);
+ paint.setStrokeWidth(CIRCLE_WIDTH);
+ paint.setStrokeCap(Paint.StrokeCap.ROUND_CAP);
+ paint.setStyle(Paint.Style.STROKE_STYLE);
+
+ int width = getWidth();
+ int center = width / TWO;
+ centerPoint = new Point(center, center);
+ int radius = center - CIRCLE_WIDTH / TWO - MARGIN;
+ drawCount(canvas, center, radius);
+
+ int inRadius = center - CIRCLE_WIDTH;
+ double length = inRadius - Math.sqrt(TWO) * NUM_ONE / TWO * inRadius;
+ centerRectFloat.left = (float) (length + CIRCLE_WIDTH);
+ centerRectFloat.top = (float) (length + CIRCLE_WIDTH);
+ centerRectFloat.bottom = (float) (centerRectFloat.left + Math.sqrt(TWO) * inRadius);
+ centerRectFloat.right = (float) (centerRectFloat.left + Math.sqrt(TWO) * inRadius);
+
+ Size imageSize = image.getImageInfo().size;
+ if (imageSize.width < Math.sqrt(TWO) * inRadius) {
+ centerRectFloat.left =
+ (float) (centerRectFloat.left + Math.sqrt(TWO) * inRadius * NUM_ONE / TWO
+ - imageSize.width * NUM_ONE / TWO);
+ centerRectFloat.top =
+ (float) (centerRectFloat.top + Math.sqrt(TWO) * inRadius * NUM_ONE / TWO
+ - imageSize.height * NUM_ONE / TWO);
+ centerRectFloat.right = centerRectFloat.left + imageSize.width;
+ centerRectFloat.bottom = centerRectFloat.top + imageSize.height;
+ }
+ canvas.drawPixelMapHolderRect(new PixelMapHolder(image), centerRectFloat, paint);
+ }
+
+ private void drawCount(Canvas canvas, int center, int radius) {
+ float itemSize = (CIRCLE_ANGLE - COUNT * SPLIT_SIZE) / COUNT;
+
+ RectFloat oval = new RectFloat(center - radius, center - radius, center + radius,
+ center + radius);
+
+ paint.setColor(unFillColor);
+ for (int i = 0; i < COUNT; i++) {
+ Arc arc = new Arc((i * (itemSize + SPLIT_SIZE)) - ANGLE, itemSize, false);
+ canvas.drawArc(oval, arc, paint);
+ }
+
+ paint.setColor(fillColor);
+ for (int i = 0; i < currentCount; i++) {
+ Arc arc = new Arc((i * (itemSize + SPLIT_SIZE)) - ANGLE, itemSize, false);
+ canvas.drawArc(oval, arc, paint);
+ }
+ }
+
+ @Override
+ public boolean onEstimateSize(int widthEstimateConfig, int heightEstimateConfig) {
+ int width = Component.EstimateSpec.getSize(widthEstimateConfig);
+ int height = Component.EstimateSpec.getSize(heightEstimateConfig);
+ setEstimatedSize(
+ Component.EstimateSpec.getChildSizeWithMode(width, height, Component.EstimateSpec.PRECISE),
+ Component.EstimateSpec.getChildSizeWithMode(width, height, Component.EstimateSpec.PRECISE)
+ );
+ return true;
+ }
+
+ @Override
+ public boolean onTouchEvent(Component component, TouchEvent touchEvent) {
+ switch (touchEvent.getAction()) {
+ case TouchEvent.PRIMARY_POINT_DOWN:
+ case TouchEvent.POINT_MOVE: {
+ MmiPoint absPoint = touchEvent.getPointerPosition(touchEvent.getIndex());
+ Point point =
+ new Point(absPoint.getX() - getContentPositionX(), absPoint.getY() - getContentPositionY());
+ double angle = calcRotationAngleInDegrees(centerPoint, point) * TWO;
+ if (angle > CIRCLE_ANGLE) {
+ angle -= CIRCLE_ANGLE;
+ }
+ double multiple = angle / (CIRCLE_ANGLE / COUNT);
+ if ((multiple - (int) multiple) > POOR) {
+ currentCount = (int) multiple + 1;
+ } else {
+ currentCount = (int) multiple;
+ }
+ invalidate();
+ break;
+ }
+ default:
+ break;
+ }
+ return false;
+ }
+
+ private double calcRotationAngleInDegrees(Point centerPt, Point targetPt) {
+ double theta = Math.atan2(targetPt.getPointYToInt()
+ - centerPt.getPointYToInt(), targetPt.getPointXToInt() - centerPt.getPointXToInt());
+ theta += Math.PI / NUM_TWO;
+ double angle = Math.toDegrees(theta);
+ if (angle < 0) {
+ angle += CIRCLE_ANGLE;
+ }
+ return angle;
+ }
+}
diff --git a/UI/CustomComponent/entry/src/main/java/ohos/samples/customcomponent/slice/AnnulusAbilitySlice.java b/UI/CustomComponent/entry/src/main/java/ohos/samples/customcomponent/slice/AnnulusAbilitySlice.java
new file mode 100644
index 0000000000000000000000000000000000000000..b7f9499baeb97658837a2181181f287532663093
--- /dev/null
+++ b/UI/CustomComponent/entry/src/main/java/ohos/samples/customcomponent/slice/AnnulusAbilitySlice.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2021 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ohos.samples.customcomponent.slice;
+
+import ohos.aafwk.ability.AbilitySlice;
+import ohos.aafwk.content.Intent;
+import ohos.samples.customcomponent.ResourceTable;
+import ohos.samples.customcomponent.modle.CustomComponent;
+
+/**
+ * AnnlusAbilitySlice
+ *
+ * @since 2021-05-08
+ */
+public class AnnulusAbilitySlice extends AbilitySlice {
+ private CustomComponent component;
+
+ @Override
+ public void onStart(Intent intent) {
+ super.onStart(intent);
+ setUIContent(ResourceTable.Layout_annulus_main_ability);
+ }
+}
diff --git a/UI/CustomComponent/entry/src/main/java/ohos/samples/customcomponent/slice/ControllerAbilitySlice.java b/UI/CustomComponent/entry/src/main/java/ohos/samples/customcomponent/slice/ControllerAbilitySlice.java
new file mode 100644
index 0000000000000000000000000000000000000000..6be09b2bf0475946b635e6a6ebca9eb42cbf4330
--- /dev/null
+++ b/UI/CustomComponent/entry/src/main/java/ohos/samples/customcomponent/slice/ControllerAbilitySlice.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ohos.samples.customcomponent.slice;
+
+import ohos.aafwk.ability.AbilitySlice;
+import ohos.aafwk.content.Intent;
+import ohos.samples.customcomponent.ResourceTable;
+
+/**
+ * ControllerAbilitySlice
+ *
+ * @since 2021-05-08
+ */
+public class ControllerAbilitySlice extends AbilitySlice {
+ @Override
+ public void onStart(Intent intent) {
+ super.onStart(intent);
+ setUIContent(ResourceTable.Layout_controller_main_ability);
+ }
+}
diff --git a/UI/CustomComponent/entry/src/main/java/ohos/samples/customcomponent/slice/MainAbilitySlice.java b/UI/CustomComponent/entry/src/main/java/ohos/samples/customcomponent/slice/MainAbilitySlice.java
new file mode 100644
index 0000000000000000000000000000000000000000..15a728f38af60effb06587d6be54389dca8ed234
--- /dev/null
+++ b/UI/CustomComponent/entry/src/main/java/ohos/samples/customcomponent/slice/MainAbilitySlice.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2021 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ohos.samples.customcomponent.slice;
+
+import ohos.aafwk.ability.AbilitySlice;
+import ohos.aafwk.content.Intent;
+import ohos.agp.components.Component;
+import ohos.samples.customcomponent.ResourceTable;
+
+/**
+ * MainAbilitySlice
+ *
+ * @since 2021-05-08
+ */
+public class MainAbilitySlice extends AbilitySlice {
+ @Override
+ public void onStart(Intent intent) {
+ super.onStart(intent);
+ super.setUIContent(ResourceTable.Layout_main_ability_slice);
+ Component annulusButton = findComponentById(ResourceTable.Id_annulus_button);
+ Component controllersButton = findComponentById(ResourceTable.Id_controllers_button);
+ annulusButton.setClickedListener(listener -> present(new AnnulusAbilitySlice(), new Intent()));
+ controllersButton.setClickedListener(listener -> present(new ControllerAbilitySlice(), new Intent()));
+ }
+
+ @Override
+ public void onActive() {
+ super.onActive();
+ }
+
+ @Override
+ public void onForeground(Intent intent) {
+ super.onForeground(intent);
+ }
+}
diff --git a/UI/CustomComponent/entry/src/main/java/ohos/samples/customcomponent/utils/Util.java b/UI/CustomComponent/entry/src/main/java/ohos/samples/customcomponent/utils/Util.java
new file mode 100644
index 0000000000000000000000000000000000000000..337cc23ec0f0eac30ca78799de05a8dbcf73eb2d
--- /dev/null
+++ b/UI/CustomComponent/entry/src/main/java/ohos/samples/customcomponent/utils/Util.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2021 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ohos.samples.customcomponent.utils;
+
+import ohos.app.Context;
+import ohos.global.resource.NotExistException;
+import ohos.global.resource.Resource;
+import ohos.global.resource.ResourceManager;
+import ohos.hiviewdfx.HiLog;
+import ohos.hiviewdfx.HiLogLabel;
+import ohos.media.image.ImageSource;
+import ohos.media.image.PixelMap;
+import ohos.media.image.common.PixelFormat;
+import ohos.media.image.common.Rect;
+import ohos.media.image.common.Size;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Optional;
+
+/**
+ * Util Tools
+ *
+ * @since 2021-05-08
+ */
+public class Util {
+ private static final HiLogLabel TAG = new HiLogLabel(3, 0xD001100, "Utils");
+
+ private Util() {
+ }
+
+ private static byte[] readResource(Resource resource) {
+ final int bufferSize = 1024;
+ final int ioEnd = -1;
+ byte[] byteArray;
+ byte[] buffer = new byte[bufferSize];
+ try (ByteArrayOutputStream output = new ByteArrayOutputStream()) {
+ while (true) {
+ int readLen = resource.read(buffer, 0, bufferSize);
+ if (readLen == ioEnd) {
+ HiLog.error(TAG, "readResource finish");
+ byteArray = output.toByteArray();
+ break;
+ }
+ output.write(buffer, 0, readLen);
+ }
+ } catch (IOException e) {
+ HiLog.debug(TAG, "readResource failed" + e.getLocalizedMessage());
+ return new byte[0];
+ }
+ return byteArray;
+ }
+
+ /**
+ * Creates is {@code PixelMap} object based on the image resource ID.
+ * This method only loads local image resources. If the image file does not exist or the loading fails,
+ * {@code null} is returned.
+ *
+ * @param resouceId Indicates the image resource ID.
+ * @param slice Indicates the Context.
+ * @return Returns the image.
+ */
+ public static Optional createPixelMapByResId(int resouceId, Context slice) {
+ ResourceManager manager = slice.getResourceManager();
+ if (manager == null) {
+ return Optional.empty();
+ }
+ try {
+ try (Resource resource = manager.getResource(resouceId)) {
+ if (resource == null) {
+ return Optional.empty();
+ }
+ ImageSource.SourceOptions srcOpts = new ImageSource.SourceOptions();
+ srcOpts.formatHint = "image/png";
+ ImageSource imageSource = ImageSource.create(readResource(resource), srcOpts);
+ if (imageSource == null) {
+ return Optional.empty();
+ }
+ ImageSource.DecodingOptions decodingOptions = new ImageSource.DecodingOptions();
+ decodingOptions.desiredSize = new Size(0, 0);
+ decodingOptions.desiredRegion = new Rect(0, 0, 0, 0);
+ decodingOptions.desiredPixelFormat = PixelFormat.ARGB_8888;
+
+ return Optional.of(imageSource.createPixelmap(decodingOptions));
+ }
+ } catch (IOException | NotExistException e) {
+ return Optional.empty();
+ }
+ }
+}
diff --git a/UI/CustomComponent/entry/src/main/resources/base/element/pattern.json b/UI/CustomComponent/entry/src/main/resources/base/element/pattern.json
new file mode 100644
index 0000000000000000000000000000000000000000..fa93f5b559f558056b436b82258e4190d3464d6a
--- /dev/null
+++ b/UI/CustomComponent/entry/src/main/resources/base/element/pattern.json
@@ -0,0 +1,25 @@
+{
+ "pattern": [
+ {
+ "name": "base",
+ "value": [
+ {
+ "name": "left_padding",
+ "value": "24vp"
+ },
+ {
+ "name": "padding",
+ "value": "10vp"
+ },
+ {
+ "name": "top_margin",
+ "value": "10vp"
+ },
+ {
+ "name": "text_size",
+ "value": "18fp"
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/UI/CustomComponent/entry/src/main/resources/base/element/string.json b/UI/CustomComponent/entry/src/main/resources/base/element/string.json
new file mode 100644
index 0000000000000000000000000000000000000000..209b0d08706dbcb8dde53ac893adfddcd3880b39
--- /dev/null
+++ b/UI/CustomComponent/entry/src/main/resources/base/element/string.json
@@ -0,0 +1,24 @@
+{
+ "string": [
+ {
+ "name": "app_name",
+ "value": "CustomComponent"
+ },
+ {
+ "name": "mainability_description",
+ "value": "Java_Phone_Empty Feature Ability"
+ },
+ {
+ "name": "HelloWorld",
+ "value": "Hello World"
+ },
+ {
+ "name": "annulus_button",
+ "value": "annulus"
+ },
+ {
+ "name": "controllers_button",
+ "value": "controllers"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/UI/CustomComponent/entry/src/main/resources/base/graphic/background_ability_main.xml b/UI/CustomComponent/entry/src/main/resources/base/graphic/background_ability_main.xml
new file mode 100644
index 0000000000000000000000000000000000000000..43fe1d48fec2453ff1cde2170b50a546c70f16e4
--- /dev/null
+++ b/UI/CustomComponent/entry/src/main/resources/base/graphic/background_ability_main.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/UI/CustomComponent/entry/src/main/resources/base/graphic/color_blue_element.xml b/UI/CustomComponent/entry/src/main/resources/base/graphic/color_blue_element.xml
new file mode 100644
index 0000000000000000000000000000000000000000..8e65e066ac87b5872e83e57008efd2b3f521119a
--- /dev/null
+++ b/UI/CustomComponent/entry/src/main/resources/base/graphic/color_blue_element.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/UI/CustomComponent/entry/src/main/resources/base/layout/annulus_main_ability.xml b/UI/CustomComponent/entry/src/main/resources/base/layout/annulus_main_ability.xml
new file mode 100644
index 0000000000000000000000000000000000000000..47752f128db7a9304a229a80c5255b1c2862c488
--- /dev/null
+++ b/UI/CustomComponent/entry/src/main/resources/base/layout/annulus_main_ability.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/UI/CustomComponent/entry/src/main/resources/base/layout/controller_main_ability.xml b/UI/CustomComponent/entry/src/main/resources/base/layout/controller_main_ability.xml
new file mode 100644
index 0000000000000000000000000000000000000000..661d6c3be2fe9ad3b6c2b14ebbe12a4ae6f43177
--- /dev/null
+++ b/UI/CustomComponent/entry/src/main/resources/base/layout/controller_main_ability.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/UI/CustomComponent/entry/src/main/resources/base/layout/main_ability_slice.xml b/UI/CustomComponent/entry/src/main/resources/base/layout/main_ability_slice.xml
new file mode 100644
index 0000000000000000000000000000000000000000..b82fb793072f867e0c88ec0ddefeac206cfac20d
--- /dev/null
+++ b/UI/CustomComponent/entry/src/main/resources/base/layout/main_ability_slice.xml
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/UI/CustomComponent/entry/src/main/resources/base/media/icon.png b/UI/CustomComponent/entry/src/main/resources/base/media/icon.png
new file mode 100644
index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c
Binary files /dev/null and b/UI/CustomComponent/entry/src/main/resources/base/media/icon.png differ
diff --git a/UI/CustomComponent/screenshots/phone/components.png b/UI/CustomComponent/screenshots/phone/components.png
new file mode 100644
index 0000000000000000000000000000000000000000..18f1edc0e25fc8dac5a3327c0c2642c4528f82b7
Binary files /dev/null and b/UI/CustomComponent/screenshots/phone/components.png differ
diff --git a/UI/CustomComponent/screenshots/phone/controlbar.png b/UI/CustomComponent/screenshots/phone/controlbar.png
new file mode 100644
index 0000000000000000000000000000000000000000..e305894489da2f07252833b6349991f5df0d06dd
Binary files /dev/null and b/UI/CustomComponent/screenshots/phone/controlbar.png differ
diff --git a/UI/CustomComponent/screenshots/phone/customcomponent.png b/UI/CustomComponent/screenshots/phone/customcomponent.png
new file mode 100644
index 0000000000000000000000000000000000000000..717e0a338e83f52599a895de3697f65b360e0fad
Binary files /dev/null and b/UI/CustomComponent/screenshots/phone/customcomponent.png differ
diff --git a/UI/CustomComponent/settings.gradle b/UI/CustomComponent/settings.gradle
new file mode 100644
index 0000000000000000000000000000000000000000..3fb34a2efe19092eee2757302500a06e080542a0
--- /dev/null
+++ b/UI/CustomComponent/settings.gradle
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2021 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+include ':entry'
\ No newline at end of file