├── .gitignore
├── AppScope
├── app.json5
└── resources
│ └── base
│ ├── element
│ └── string.json
│ └── media
│ └── app_icon.svg
├── LICENSE
├── README.md
├── build-profile.json5
├── code-linter.json5
├── entry
├── .gitignore
├── build-profile.json5
├── hvigorfile.ts
├── obfuscation-rules.txt
├── oh-package-lock.json5
├── oh-package.json5
└── src
│ ├── main
│ ├── ets
│ │ ├── component
│ │ │ └── CategoryNavigation.ets
│ │ ├── data
│ │ │ ├── CategoryData.ets
│ │ │ └── CategoryItem.ets
│ │ ├── entryability
│ │ │ └── EntryAbility.ets
│ │ ├── entrybackupability
│ │ │ └── EntryBackupAbility.ets
│ │ ├── pages
│ │ │ ├── Index.ets
│ │ │ ├── anchor
│ │ │ │ ├── AnchorMockData.ts
│ │ │ │ └── OmniAnchorExamplePage.ets
│ │ │ ├── autolinegrid
│ │ │ │ └── OmniAutoLineGridEntryPage.ets
│ │ │ ├── bottombar
│ │ │ │ └── OmniBottomBarExamplePage.ets
│ │ │ ├── calendar
│ │ │ │ └── OmniCalendarExamplePage.ets
│ │ │ ├── charts
│ │ │ │ ├── OmniFunnelChartExamplePage.ets
│ │ │ │ ├── OmniLineChartExamplePage.ets
│ │ │ │ ├── OmniPieChartExamplePage.ets
│ │ │ │ ├── OmniProgressBarChartExamplePage.ets
│ │ │ │ └── OmniRadarChartExamplePage.ets
│ │ │ ├── dialog
│ │ │ │ └── OmniDialogEntryPage.ets
│ │ │ ├── expandabletext
│ │ │ │ └── OmniExpandableTextEntryPage.ets
│ │ │ ├── filterbar
│ │ │ │ ├── OmniFilterBarCustomExamplePage.ets
│ │ │ │ ├── OmniFilterBarExampleEntryPage.ets
│ │ │ │ ├── OmniFilterBarMenuCustomExamplePage.ets
│ │ │ │ ├── OmniFilterBarMoreExamplePage.ets
│ │ │ │ ├── OmniFilterBarMultiGridExamplePage.ets
│ │ │ │ ├── OmniFilterBarMultiListExamplePage.ets
│ │ │ │ ├── OmniFilterBarStyleCustomExamplePage.ets
│ │ │ │ └── component
│ │ │ │ │ └── OmniCustomValueRange.ets
│ │ │ ├── gallery
│ │ │ │ ├── OmniGalleryExamplePage.ets
│ │ │ │ └── OmniSummaryExamplePage.ets
│ │ │ ├── guide
│ │ │ │ ├── OmniGuideExampleIndex.ets
│ │ │ │ └── OmniGuideMultiPageExample.ets
│ │ │ ├── imagepicker
│ │ │ │ ├── OmniImageAlbumPickerPage.ets
│ │ │ │ ├── OmniImagePickerExamplePage.ets
│ │ │ │ └── OmniImagePickerSelectExamplePage.ets
│ │ │ ├── loading
│ │ │ │ └── OmniLoadingEntryPage.ets
│ │ │ ├── navigationbar
│ │ │ │ └── OmniNavigationBarExamplePage.ets
│ │ │ ├── picker
│ │ │ │ └── OmniDataPickerEntryPage.ets
│ │ │ ├── pullable
│ │ │ │ └── OmniPullableExamplePage.ets
│ │ │ ├── richtext
│ │ │ │ └── OmniRichTextExamplePage.ets
│ │ │ ├── search
│ │ │ │ └── OmniSearchExamplePage.ets
│ │ │ ├── step
│ │ │ │ └── OmniStepLineExample.ets
│ │ │ ├── tabs
│ │ │ │ └── OmniTabExamplePage.ets
│ │ │ ├── tags
│ │ │ │ └── OmniTagEntryPage.ets
│ │ │ ├── theme
│ │ │ │ └── OmniThemeDemoPage.ets
│ │ │ └── toast
│ │ │ │ └── OmniToastEntryPage.ets
│ │ └── utils
│ │ │ └── utils.ts
│ ├── module.json5
│ └── resources
│ │ ├── base
│ │ ├── element
│ │ │ ├── color.json
│ │ │ └── string.json
│ │ ├── media
│ │ │ ├── app_icon_startwindow.png
│ │ │ ├── background.png
│ │ │ ├── bottombar_car.png
│ │ │ ├── bottombar_car_selected.png
│ │ │ ├── bottombar_home.png
│ │ │ ├── bottombar_home_selecte.png
│ │ │ ├── bottombar_mine.png
│ │ │ ├── bottombar_mine_selected.png
│ │ │ ├── bottombar_read.png
│ │ │ ├── bottombar_read_selected.png
│ │ │ ├── foreground.png
│ │ │ ├── ic_back_white.png
│ │ │ ├── ic_down_arrow.png
│ │ │ ├── ic_right_arrow.png
│ │ │ ├── icon_category_chart.svg
│ │ │ ├── icon_category_form.svg
│ │ │ ├── icon_category_navigation.svg
│ │ │ ├── icon_category_operatefeedback.svg
│ │ │ ├── icon_category_page.svg
│ │ │ ├── icon_category_theme_style.png
│ │ │ ├── icon_category_view.svg
│ │ │ ├── icon_filter_reset_custom.png
│ │ │ ├── layered_image.json
│ │ │ ├── startIcon.png
│ │ │ ├── tag_heart.png
│ │ │ └── tag_heart_fill.png
│ │ └── profile
│ │ │ ├── backup_config.json
│ │ │ ├── main_pages.json
│ │ │ └── route_map.json
│ │ ├── en_US
│ │ └── element
│ │ │ └── string.json
│ │ ├── rawfile
│ │ ├── custom_filter.json
│ │ ├── more_filter.json
│ │ ├── multi_grid_filter.json
│ │ └── multi_list_filter.json
│ │ └── zh_CN
│ │ └── element
│ │ └── string.json
│ ├── mock
│ └── mock-config.json5
│ ├── ohosTest
│ ├── ets
│ │ └── test
│ │ │ ├── Ability.test.ets
│ │ │ └── List.test.ets
│ └── module.json5
│ └── test
│ ├── List.test.ets
│ └── LocalUnit.test.ets
├── hvigor
└── hvigor-config.json5
├── hvigorfile.ts
├── oh-package-lock.json5
├── oh-package.json5
└── omni_component
├── .gitignore
├── CHANGELOG.md
├── Index.ets
├── LICENSE
├── README.md
├── build-profile.json5
├── consumer-rules.txt
├── hvigorfile.ts
├── obfuscation-rules.txt
├── oh-package-lock.json5
├── oh-package.json5
└── src
├── main
├── ets
│ ├── OmniComponent.ets
│ ├── components
│ │ ├── MainPage.ets
│ │ ├── anchor
│ │ │ └── OmniAnchor.ets
│ │ ├── autolinegrid
│ │ │ ├── AutoLineWrapLayout.ets
│ │ │ ├── LineWrapLayout.ets
│ │ │ └── OmniAutoLineGrid.ets
│ │ ├── bottomtabbar
│ │ │ └── OmniBottomTabBar.ets
│ │ ├── calendar
│ │ │ └── OmniCalendar.ets
│ │ ├── chart
│ │ │ ├── OmniChart.ets
│ │ │ ├── OmniFunnelChart.ets
│ │ │ ├── OmniLineChart.ets
│ │ │ ├── OmniPieChart.ets
│ │ │ ├── OmniProgressBarChart.ets
│ │ │ ├── OmniRadarChart.ets
│ │ │ ├── Options.ets
│ │ │ ├── Tooltip.ets
│ │ │ └── utils
│ │ │ │ ├── DrawAxisViewModel.ets
│ │ │ │ ├── DrawBaseViewModel.ets
│ │ │ │ ├── DrawHorViewModel.ets
│ │ │ │ ├── DrawLineViewModel.ets
│ │ │ │ ├── DrawPieViewModel.ets
│ │ │ │ ├── DrawRadarViewModel.ets
│ │ │ │ ├── DrawVerBarViewModel.ets
│ │ │ │ ├── chartInterface.ts
│ │ │ │ ├── defaultOption.ts
│ │ │ │ └── index.ts
│ │ ├── dialog
│ │ │ ├── OmniDialog.ets
│ │ │ ├── OmniDialogBuilder.ets
│ │ │ └── OmniDialogConstant.ets
│ │ ├── expandabletext
│ │ │ └── OmniExpandableText.ets
│ │ ├── filterbar
│ │ │ ├── OmniFilterBar.ets
│ │ │ ├── OmniFilterComponentRegistry.ets
│ │ │ ├── OmniFilterConstants.ets
│ │ │ ├── OmniFilterThemeConfig.ets
│ │ │ ├── bean
│ │ │ │ ├── OmniFilterItemBean.ets
│ │ │ │ └── OmniFilterMenuItemBean.ets
│ │ │ ├── component
│ │ │ │ ├── OmniFilterBottomPanel.ets
│ │ │ │ ├── OmniFilterGridGroup.ets
│ │ │ │ ├── OmniFilterGridItem.ets
│ │ │ │ ├── OmniFilterListGroup.ets
│ │ │ │ ├── OmniFilterListItem.ets
│ │ │ │ ├── OmniFilterMenuItem.ets
│ │ │ │ ├── OmniFilterSingleGrid.ets
│ │ │ │ └── OmniFilterSingleList.ets
│ │ │ ├── converter
│ │ │ │ └── OmniFilterConverter.ets
│ │ │ └── util
│ │ │ │ └── OmniFilterUtil.ets
│ │ ├── gallery
│ │ │ ├── OmniGallery.ets
│ │ │ ├── OmniSummary.ets
│ │ │ └── OmniVideoView.ets
│ │ ├── guide
│ │ │ ├── OmniGuide.ets
│ │ │ ├── core
│ │ │ │ ├── Controller.ets
│ │ │ │ └── OmniGuideBuilder.ets
│ │ │ ├── interface
│ │ │ │ ├── HighLight.ets
│ │ │ │ ├── OnClickListener.ets
│ │ │ │ ├── OnGuideChangedListener.ets
│ │ │ │ ├── OnGuideLifeCycleListener.ets
│ │ │ │ ├── OnHighLightDrewListener.ets
│ │ │ │ └── OnPageChangedListener.ets
│ │ │ ├── model
│ │ │ │ ├── BubbleIndicator.ets
│ │ │ │ ├── GuidePage.ets
│ │ │ │ ├── HighLightInfoOfComponent.ets
│ │ │ │ ├── HighLightInfoOfRectF.ets
│ │ │ │ ├── HighLightOptions.ets
│ │ │ │ ├── HighLightOptionsBuilder.ets
│ │ │ │ ├── HighLightShape.ets
│ │ │ │ ├── ObservedMaskVisibleState.ets
│ │ │ │ ├── ObservedPageIndex.ets
│ │ │ │ └── RectF.ets
│ │ │ └── util
│ │ │ │ ├── ComponentRectFUtil.ets
│ │ │ │ └── GlobalContext.ts
│ │ ├── imagepicker
│ │ │ ├── OmniImagePicker.ets
│ │ │ └── OmniImagePickerTrigger.ets
│ │ ├── loading
│ │ │ ├── OmniDotLoadingView.ets
│ │ │ └── OmniPageLoading.ets
│ │ ├── navigationbar
│ │ │ └── OmniNavigationBar.ets
│ │ ├── picker
│ │ │ └── OmniDataPicker.ets
│ │ ├── popup
│ │ │ ├── ArrowLocation.ets
│ │ │ ├── BaseAttachPopup.ets
│ │ │ ├── BasePopup.ets
│ │ │ ├── BubbleComponent.ets
│ │ │ ├── BubblePopup.ets
│ │ │ ├── Builder.ets
│ │ │ ├── Config.ets
│ │ │ ├── CustomBubbleComponent.ets
│ │ │ ├── CustomBuilder.ets
│ │ │ ├── CustomNodeController.ets
│ │ │ ├── OmniPopup.ets
│ │ │ ├── PopupAction.ets
│ │ │ ├── PopupCallback.ets
│ │ │ ├── PopupConfig.ets
│ │ │ ├── PopupManager.ets
│ │ │ ├── PopupPosition.ets
│ │ │ ├── PopupType.ets
│ │ │ └── entity
│ │ │ │ ├── ButtonOptions.ets
│ │ │ │ ├── PopupBean.ets
│ │ │ │ └── PopupInfo.ets
│ │ ├── pullable
│ │ │ ├── OmniPullToRefreshLayout.ets
│ │ │ ├── OmniPullable.ets
│ │ │ ├── OmniPullableController.ets
│ │ │ ├── OmniRefreshLayoutConfig.ets
│ │ │ ├── core
│ │ │ │ ├── RefreshLayout.ets
│ │ │ │ └── RefreshLayoutHelper.ets
│ │ │ └── interface.ets
│ │ ├── richtext
│ │ │ ├── OmniRichText.ets
│ │ │ └── utils
│ │ │ │ ├── ExposeData.ts
│ │ │ │ ├── HtmlParseUtil.ts
│ │ │ │ ├── MetadataStorage.ts
│ │ │ │ ├── StyleStringUtil.ets
│ │ │ │ ├── Util.ts
│ │ │ │ └── index.ts
│ │ ├── search
│ │ │ └── OmniSearchV2.ets
│ │ ├── step
│ │ │ ├── OmniLine.ets
│ │ │ └── OmniSteps.ets
│ │ ├── tabs
│ │ │ └── OmniTabs.ets
│ │ ├── tags
│ │ │ ├── OmniTag.ets
│ │ │ └── TagItemInfo.ets
│ │ └── toast
│ │ │ ├── OmniToast.ets
│ │ │ ├── OmniToastBuilders.ets
│ │ │ └── OmniToastTheme.ets
│ ├── constants
│ │ └── CommonConstants.ets
│ ├── theme
│ │ ├── OmniColorStyle.ets
│ │ ├── OmniFontStyle.ets
│ │ ├── OmniStyleModifier.ets
│ │ ├── OmniTheme.ets
│ │ └── OmniThemeUtil.ets
│ └── utils
│ │ ├── ImmersionBar.ets
│ │ ├── ScreenUtils.ets
│ │ ├── TextUtils.ts
│ │ └── Utils.ets
├── module.json5
└── resources
│ ├── base
│ ├── element
│ │ ├── color.json
│ │ └── string.json
│ └── media
│ │ ├── back.webp
│ │ ├── comm_page_icon_jt_s.png
│ │ ├── comm_page_icon_jt_x.png
│ │ ├── error.svg
│ │ ├── ic_arrow_right.svg
│ │ ├── ic_clear.png
│ │ ├── ic_highlight.svg
│ │ ├── ic_search.png
│ │ ├── icon_arrow_down.svg
│ │ ├── icon_arrow_down_selected.png
│ │ ├── icon_arrow_down_unselected.png
│ │ ├── icon_arrow_up.svg
│ │ ├── icon_arrow_up_selected.png
│ │ ├── icon_calendar_next_month.png
│ │ ├── icon_calendar_pre_month.png
│ │ ├── icon_filter_reset.png
│ │ ├── icon_filter_select.svg
│ │ ├── icon_filter_unselect.png
│ │ ├── icon_selection_reset.png
│ │ ├── icon_step_2.png
│ │ ├── icon_step_3.png
│ │ ├── icon_step_4.png
│ │ ├── icon_step_5.png
│ │ ├── icon_step_completed.svg
│ │ ├── icon_step_doing.svg
│ │ ├── image_trigger_add.png
│ │ ├── playIcon.png
│ │ ├── search.webp
│ │ ├── startIcon.png
│ │ ├── success.svg
│ │ ├── voice_off.webp
│ │ ├── voice_on.webp
│ │ ├── warning.svg
│ │ └── zr_refresh_arrow.svg
│ ├── en_US
│ └── element
│ │ └── string.json
│ └── zh_CN
│ └── element
│ └── string.json
├── ohosTest
├── ets
│ └── test
│ │ ├── Ability.test.ets
│ │ └── List.test.ets
└── module.json5
└── test
├── List.test.ets
└── LocalUnit.test.ets
/.gitignore:
--------------------------------------------------------------------------------
1 | **/node_modules
2 | /oh_modules
3 | /local.properties
4 | /.idea
5 | **/build
6 | /.hvigor
7 | .cxx
8 | /.clangd
9 | /.clang-format
10 | /.clang-tidy
11 | **/.test
12 | /.appanalyzer
13 | **/BuildProfile.ets
--------------------------------------------------------------------------------
/AppScope/app.json5:
--------------------------------------------------------------------------------
1 | {
2 | "app": {
3 | "bundleName": "com.omni.ui.component",
4 | "vendor": "example",
5 | "versionCode": 1000000,
6 | "versionName": "1.0.1",
7 | "icon": "$media:app_icon",
8 | "label": "$string:app_name"
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/AppScope/resources/base/element/string.json:
--------------------------------------------------------------------------------
1 | {
2 | "string": [
3 | {
4 | "name": "app_name",
5 | "value": "omni-ui"
6 | }
7 | ]
8 | }
9 |
--------------------------------------------------------------------------------
/AppScope/resources/base/media/app_icon.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/build-profile.json5:
--------------------------------------------------------------------------------
1 | {
2 | "app": {
3 | "signingConfigs": [
4 | ],
5 | "products": [
6 | {
7 | "name": "default",
8 | "signingConfig": "default",
9 | "compatibleSdkVersion": "5.0.0(12)",
10 | "runtimeOS": "HarmonyOS",
11 | "buildOption": {
12 | "strictMode": {
13 | "useNormalizedOHMUrl": false
14 | }
15 | }
16 | },
17 | ],
18 | "buildModeSet": [
19 | {
20 | "name": "debug",
21 | },
22 | {
23 | "name": "release"
24 | }
25 | ]
26 | },
27 | "modules": [
28 | {
29 | "name": "entry",
30 | "srcPath": "./entry",
31 | "targets": [
32 | {
33 | "name": "default",
34 | "applyToProducts": [
35 | "default"
36 | ]
37 | }
38 | ]
39 | },
40 | {
41 | "name": "omni_component",
42 | "srcPath": "./omni_component"
43 | }
44 | ]
45 | }
--------------------------------------------------------------------------------
/code-linter.json5:
--------------------------------------------------------------------------------
1 | {
2 | "files": [
3 | "**/*.ets"
4 | ],
5 | "ignore": [
6 | "**/src/ohosTest/**/*",
7 | "**/src/test/**/*",
8 | "**/src/mock/**/*",
9 | "**/node_modules/**/*",
10 | "**/oh_modules/**/*",
11 | "**/build/**/*",
12 | "**/.preview/**/*"
13 | ],
14 | "ruleSet": [
15 | "plugin:@performance/recommended",
16 | "plugin:@typescript-eslint/recommended"
17 | ],
18 | "rules": {
19 | }
20 | }
--------------------------------------------------------------------------------
/entry/.gitignore:
--------------------------------------------------------------------------------
1 | /node_modules
2 | /oh_modules
3 | /.preview
4 | /build
5 | /.cxx
6 | /.test
--------------------------------------------------------------------------------
/entry/build-profile.json5:
--------------------------------------------------------------------------------
1 | {
2 | "apiType": "stageMode",
3 | "buildOption": {
4 | },
5 | "buildOptionSet": [
6 | {
7 | "name": "release",
8 | "arkOptions": {
9 | "obfuscation": {
10 | "ruleOptions": {
11 | "enable": false,
12 | "files": [
13 | "./obfuscation-rules.txt"
14 | ]
15 | }
16 | }
17 | }
18 | },
19 | ],
20 | "targets": [
21 | {
22 | "name": "default"
23 | },
24 | {
25 | "name": "ohosTest",
26 | }
27 | ]
28 | }
--------------------------------------------------------------------------------
/entry/hvigorfile.ts:
--------------------------------------------------------------------------------
1 | import { hapTasks } from '@ohos/hvigor-ohos-plugin';
2 |
3 | export default {
4 | system: hapTasks, /* Built-in plugin of Hvigor. It cannot be modified. */
5 | plugins:[] /* Custom plugin to extend the functionality of Hvigor. */
6 | }
7 |
--------------------------------------------------------------------------------
/entry/obfuscation-rules.txt:
--------------------------------------------------------------------------------
1 | # Define project specific obfuscation rules here.
2 | # You can include the obfuscation configuration files in the current module's build-profile.json5.
3 | #
4 | # For more details, see
5 | # https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/source-obfuscation-V5
6 |
7 | # Obfuscation options:
8 | # -disable-obfuscation: disable all obfuscations
9 | # -enable-property-obfuscation: obfuscate the property names
10 | # -enable-toplevel-obfuscation: obfuscate the names in the global scope
11 | # -compact: remove unnecessary blank spaces and all line feeds
12 | # -remove-log: remove all console.* statements
13 | # -print-namecache: print the name cache that contains the mapping from the old names to new names
14 | # -apply-namecache: reuse the given cache file
15 |
16 | # Keep options:
17 | # -keep-property-name: specifies property names that you want to keep
18 | # -keep-global-name: specifies names that you want to keep in the global scope
19 |
20 | -enable-property-obfuscation
21 | -enable-toplevel-obfuscation
22 | -enable-filename-obfuscation
23 | -enable-export-obfuscation
--------------------------------------------------------------------------------
/entry/oh-package.json5:
--------------------------------------------------------------------------------
1 | {
2 | "name": "entry",
3 | "version": "1.0.0",
4 | "description": "Please describe the basic information.",
5 | "main": "",
6 | "author": "",
7 | "license": "",
8 | "dependencies": {
9 | "@omni-ui/omni_component": "file:../omni_component"
10 | }
11 | }
12 |
13 |
--------------------------------------------------------------------------------
/entry/src/main/ets/component/CategoryNavigation.ets:
--------------------------------------------------------------------------------
1 | import { CategoryItem, ComponentItem } from '../data/CategoryItem'
2 | import { promptAction, router } from '@kit.ArkUI'
3 |
4 | @Component
5 | export struct CategoryItemCard {
6 | @BuilderParam
7 | categoryItem: CategoryItem
8 | @Provide("expand") expand: boolean = false
9 | private onFlagChange = () => {
10 | animateTo({
11 | duration: 200,
12 | curve: Curve.Smooth
13 | }, () => {
14 | this.expand = !this.expand;
15 | })
16 | }
17 |
18 | build() {
19 | Column() {
20 | Row() {
21 | Image(this.categoryItem.icon)
22 | .width(24)
23 | .height(24)
24 | .objectFit(ImageFit.Fill)
25 |
26 | Text(this.categoryItem.title)
27 | .fontSize(16)
28 | .margin({ left: 16 })
29 | .fontColor(Color.Black)
30 |
31 | Blank()
32 |
33 | if (this.categoryItem.components) {
34 | Image(this.expand ? $r('app.media.ic_down_arrow') : $r('app.media.ic_right_arrow'))
35 | .width(this.expand ? 24 : 12)
36 | .height(this.expand ? 12 : 24)
37 | .margin({ right: this.expand ? 0 : 6 })
38 | }
39 | }
40 | .height(56)
41 | .width('100%')
42 | .onClick(() => {
43 | // this.expand = !this.expand;
44 | this.onFlagChange()
45 | })
46 |
47 | // Click to expand the fourth-level category
48 | if (this.expand) {
49 | ForEach(this.categoryItem.components, (componentItem: ComponentItem) => {
50 | Column() {
51 | Divider()
52 | .height(1)
53 | .opacity(0.2)
54 | .margin({ left: 42, right: 8 })
55 | .color(Color.Black)
56 |
57 | FourthLevelNavigation({ componentItem: componentItem })
58 | }
59 | })
60 | }
61 | }
62 | }
63 | }
64 |
65 | @Component
66 | struct FourthLevelNavigation {
67 | @BuilderParam
68 | private componentItem: ComponentItem
69 |
70 | @Consume('pathStack') pathStack: NavPathStack;
71 |
72 | build() {
73 | Row() {
74 | Text(this.componentItem.title)
75 | .fontSize(16)
76 | .layoutWeight(1)
77 | .margin({ left: 42 })
78 | .align(Alignment.Start)
79 | .fontFamily('HarmonyHeiTi-Medium')
80 | .fontColor(Color.Black)
81 | Blank()
82 | }
83 | .height(48)
84 | .width('100%')
85 | .onClick(() => {
86 | if (this.componentItem.url) {
87 | this.pathStack.pushPath({ name: this.componentItem.url })
88 | } else {
89 | promptAction.showToast({
90 | message: '开发中'
91 | })
92 | }
93 | })
94 | }
95 | }
--------------------------------------------------------------------------------
/entry/src/main/ets/data/CategoryItem.ets:
--------------------------------------------------------------------------------
1 | export interface CategoryItem {
2 | icon: Resource
3 | title: string
4 | components: ComponentItem[]
5 | }
6 |
7 | export interface ComponentItem {
8 | title: string,
9 | url: string | undefined
10 | }
--------------------------------------------------------------------------------
/entry/src/main/ets/entryability/EntryAbility.ets:
--------------------------------------------------------------------------------
1 | import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit';
2 | import { hilog } from '@kit.PerformanceAnalysisKit';
3 | import { window } from '@kit.ArkUI';
4 | import { BusinessError } from '@kit.BasicServicesKit';
5 | import { OmniComponent } from '@omni-ui/omni_component';
6 |
7 | export default class EntryAbility extends UIAbility {
8 | onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
9 | hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');
10 | }
11 |
12 | onDestroy(): void {
13 | hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy');
14 | }
15 |
16 | onWindowStageCreate(windowStage: window.WindowStage): void {
17 | // Main window is created, set main page for this ability
18 | hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate');
19 | windowStage.getMainWindow((err: BusinessError, data) => {
20 | const errCode: number = err.code
21 | if (errCode) {
22 | hilog.error(0x0000, 'testTag',`Failed to obtain the main window. Cause:${JSON.stringify(err)}`)
23 | return
24 | }
25 | //初始化框架
26 | OmniComponent.init(data)
27 | console.info('Succeeded in obtaining the main window. Data: ' + JSON.stringify(data));
28 | })
29 | windowStage.loadContent('pages/Index', (err) => {
30 | if (err.code) {
31 | hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
32 | return;
33 | }
34 | hilog.info(0x0000, 'testTag', 'Succeeded in loading the content.');
35 | });
36 | }
37 |
38 | onWindowStageDestroy(): void {
39 | // Main window is destroyed, release UI related resources
40 | hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy');
41 | }
42 |
43 | onForeground(): void {
44 | // Ability has brought to foreground
45 | hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground');
46 | }
47 |
48 | onBackground(): void {
49 | // Ability has back to background
50 | hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground');
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets:
--------------------------------------------------------------------------------
1 | import { hilog } from '@kit.PerformanceAnalysisKit';
2 | import { BackupExtensionAbility, BundleVersion } from '@kit.CoreFileKit';
3 |
4 | export default class EntryBackupAbility extends BackupExtensionAbility {
5 | async onBackup() {
6 | hilog.info(0x0000, 'testTag', 'onBackup ok');
7 | }
8 |
9 | async onRestore(bundleVersion: BundleVersion) {
10 | hilog.info(0x0000, 'testTag', 'onRestore ok %{public}s', JSON.stringify(bundleVersion));
11 | }
12 | }
--------------------------------------------------------------------------------
/entry/src/main/ets/pages/Index.ets:
--------------------------------------------------------------------------------
1 | import { CATEGORY_DATA } from '../data/CategoryData';
2 | import { CategoryItem } from '../data/CategoryItem';
3 | import { CategoryItemCard } from '../component/CategoryNavigation';
4 | import { OmniToast } from '@omni-ui/omni_component';
5 |
6 | @Entry
7 | @Component
8 | struct Index {
9 | @Provide('pathStack') pathStack: NavPathStack = new NavPathStack()
10 | private categoryItems: CategoryItem[] = CATEGORY_DATA
11 |
12 | aboutToAppear(): void {
13 | OmniToast.initToast(this.getUIContext())
14 | }
15 |
16 | build() {
17 | Navigation(this.pathStack) {
18 | Column() {
19 | List() {
20 | ForEach(this.categoryItems, (categoryItem: CategoryItem) => {
21 | ListItem() {
22 | Column() {
23 | CategoryItemCard({ categoryItem: categoryItem })
24 | }
25 | .ColumnStyle()
26 | }
27 | .margin({ top: 6, bottom: 6 })
28 | })
29 | }
30 | .width("100%")
31 | .height("100%")
32 | .padding({ left: 16, right: 16, top: 16 })
33 | }
34 | .width("100%")
35 | .height("100%")
36 | .backgroundColor(0xfff1f3f5)
37 | }
38 | .title('OmniUI')
39 | .titleMode(NavigationTitleMode.Mini)
40 | .mode(NavigationMode.Auto)
41 | }
42 | }
43 |
44 | @Extend(Column)
45 | function ColumnStyle() {
46 | .width('100%')
47 | .borderRadius(24)
48 | .backgroundColor(Color.White)
49 | .padding({
50 | left: 12,
51 | right: 12,
52 | bottom: 4,
53 | top: 4
54 | })
55 | }
--------------------------------------------------------------------------------
/entry/src/main/ets/pages/autolinegrid/OmniAutoLineGridEntryPage.ets:
--------------------------------------------------------------------------------
1 | import { OmniAutoLineGrid, PairItemInfo, OmniToast } from "@omni-ui/omni_component"
2 |
3 | @Builder
4 | export function OmniAutoLineGridEntryPageBuilder() {
5 | OmniAutoLineGridEntryPage()
6 | }
7 |
8 | @Entry
9 | @Component
10 | struct OmniAutoLineGridEntryPage {
11 | @State items: PairItemInfo[] = [
12 | {
13 | singleLine: false,
14 | title: '姓名',
15 | content: '王二狗'
16 | },
17 | {
18 | singleLine: false,
19 | title: '性别',
20 | content: '男'
21 | },
22 | {
23 | singleLine: false,
24 | title: '出生年月',
25 | content: '1992/01'
26 | },
27 | {
28 | singleLine: false,
29 | title: '婚姻状态',
30 | content: '未婚'
31 | },
32 | {
33 | singleLine: true,
34 | title: '身份证号',
35 | content: '110101199201101234'
36 | },
37 | {
38 | singleLine: false,
39 | title: '身高',
40 | content: '172cm'
41 | },
42 | {
43 | singleLine: false,
44 | title: '体重',
45 | content: '70kg'
46 | },
47 | {
48 | singleLine: true,
49 | title: '联系方式',
50 | content: '13012345678',
51 | rightText: '立即联系',
52 | rightIcon: $r('app.media.ic_arrow_right'),
53 | hasRightPart: true
54 | },
55 | {
56 | singleLine: true,
57 | title: '家庭地址',
58 | content: '北京市北京市东城区xx街道xx小区xx楼xx单元101',
59 | rightText: '查看详情',
60 | rightIcon: $r('app.media.ic_arrow_right'),
61 | hasRightPart: true
62 | }
63 | ]
64 |
65 | @Builder
66 | buildRightArea() {
67 | Row() {
68 | Text('r1')
69 | .fontSize(10)
70 | .fontColor('#979B9E')
71 | .margin({ right: 5 })
72 |
73 | Text('r2')
74 | .fontSize(10)
75 | .fontColor('#0B0F12')
76 | }.onClick(() => {
77 | OmniToast.showText({ msg: 'Right Area Clicked' })
78 | })
79 | }
80 |
81 | build() {
82 | NavDestination() {
83 | Column({ space: 20 }) {
84 | OmniAutoLineGrid({
85 | items: this.items, onRightAreaClick: () => {
86 | OmniToast.showText({ msg: 'Right Area Clicked' })
87 | }
88 | }).padding({
89 | left: 20,
90 | right: 20,
91 | top: 16,
92 | bottom: 16
93 | })
94 | OmniAutoLineGrid({
95 | items: this.items,
96 | rightPartBuilder: this.buildRightArea,
97 | }).padding({
98 | left: 20,
99 | right: 20,
100 | top: 16,
101 | bottom: 16
102 | })
103 | }
104 | }.title('OmniAutoLineGrid示例')
105 | }
106 | }
--------------------------------------------------------------------------------
/entry/src/main/ets/pages/charts/OmniLineChartExamplePage.ets:
--------------------------------------------------------------------------------
1 | import { OmniLineChart } from "@omni-ui/omni_component"
2 | import { Options } from "@omni-ui/omni_component/src/main/ets/components/chart/Options"
3 | import { LineDataType } from "@omni-ui/omni_component/src/main/ets/components/chart/utils/DrawLineViewModel"
4 |
5 | @Builder
6 | export function OmniLineChartExamplePageBuilder() {
7 | OmniLineChartExamplePage()
8 | }
9 |
10 | @Component
11 | export struct OmniLineChartExamplePage {
12 | @State defOption: Options = new Options({
13 | xAxis: {
14 | type: 'value',
15 | data: ['周一', '周二', '周三', '周四', '周五', '周六', '周日'],
16 | // axisLabel: {
17 | // interval: 0
18 | // },
19 | },
20 | yAxis: {
21 | type: 'category',
22 | name: '温度'
23 | },
24 | series: [
25 | {
26 | name: '最高气温',
27 | lineStyle: {
28 | width: 1.5
29 | },
30 | areaStyle: {
31 | color: {
32 | direction: [0, 0, 0, 1],
33 | colors: ['#00f39c12', '#fff39c12']
34 | }
35 | },
36 | color: '#fff39c12',
37 | data: [9, 13, 10, 15, 12, 12, 10]
38 | },
39 | {
40 | name: '最低气温',
41 | lineStyle: {
42 | width: 2.5
43 | },
44 | color: '#ff3498db',
45 | data: [0, -1, 2, 0, 3, -2, 1]
46 | },
47 |
48 | ]
49 | })
50 | build() {
51 | NavDestination() {
52 | Column() {
53 | OmniLineChart({
54 | options: this.defOption
55 | })
56 | }
57 | .height('50%')
58 | }
59 | .title('折线图示例')
60 | }
61 | }
--------------------------------------------------------------------------------
/entry/src/main/ets/pages/charts/OmniPieChartExamplePage.ets:
--------------------------------------------------------------------------------
1 | import { OmniPieChart, Options } from "@omni-ui/omni_component"
2 | import { PieDataType } from "@omni-ui/omni_component/src/main/ets/components/chart/utils/DrawPieViewModel"
3 |
4 | @Builder
5 | export function OmniPieChartExamplePageBuilder() {
6 | OmniPieChartExamplePage()
7 | }
8 |
9 | @Component
10 | export struct OmniPieChartExamplePage {
11 | @State defOption: Options = new Options({
12 | series:[
13 | {
14 | name:'最高气温',
15 | data: [
16 | {value:435, name:'直接访问'},
17 | {value:310, name:'邮件营销'},
18 | {value:234, name:'联盟广告'},
19 | {value:135, name:'视频广告'},
20 | {value:1548, name:'搜索引擎'}
21 | ]
22 | }
23 | ]
24 | })
25 | build() {
26 | NavDestination() {
27 | Column(){
28 | OmniPieChart({
29 | options: this.defOption
30 | })
31 | }
32 | .height('50%')
33 | }
34 | .title("环状图示例")
35 | }
36 | }
--------------------------------------------------------------------------------
/entry/src/main/ets/pages/charts/OmniProgressBarChartExamplePage.ets:
--------------------------------------------------------------------------------
1 | import { BarChartStyle, OmniProgressBarChart, Options } from '@omni-ui/omni_component'
2 |
3 | @Builder
4 | export function OmniProgressBarChartExamplePageBuilder() {
5 | OmniProgressBarChartExamplePage()
6 | }
7 |
8 | @Component
9 | export struct OmniProgressBarChartExamplePage {
10 | @State defOption: Options = new Options({
11 | xAxis: {
12 | type: 'value',
13 | data: ['周一', '周二', '周三', '周四', '周五', '周六', '周日'],
14 | },
15 | yAxis: {
16 | type: 'category',
17 | name: '温度'
18 | },
19 | series: [
20 | {
21 | name: '最高气温',
22 | barStyle: {
23 | width: 15,
24 | },
25 | color: '#296DFF',
26 | data: [30, 11, 25, 28, 33, 25, 20]
27 | },
28 | {
29 | name: '最低气温',
30 | barStyle: {
31 | width: 15,
32 | },
33 | color: '#61cdf8',
34 | data: [8, 9, 5, 7, 10, 6, 9]
35 | },
36 | ],
37 | })
38 |
39 | build() {
40 | NavDestination() {
41 | Column() {
42 | Column() {
43 | OmniProgressBarChart({
44 | barChartStyle: BarChartStyle.horizontal,
45 | options: this.defOption
46 | })
47 | }
48 | .height('50%')
49 |
50 | Column() {
51 | OmniProgressBarChart({
52 | options: this.defOption
53 | })
54 | }
55 | .height('50%')
56 | }
57 | }
58 | .title("柱状图示例")
59 | .height('100%')
60 | }
61 | }
--------------------------------------------------------------------------------
/entry/src/main/ets/pages/charts/OmniRadarChartExamplePage.ets:
--------------------------------------------------------------------------------
1 | import { OmniRadarChart, Options } from "@omni-ui/omni_component"
2 |
3 | @Builder
4 | export function OmniRadarChartExamplePageBuilder() {
5 | OmniRadarChartExamplePage()
6 | }
7 |
8 | @Component
9 | export struct OmniRadarChartExamplePage {
10 | @State defOption: Options = new Options({
11 | radar: {
12 | indicator: [
13 | { name: 'Sales' },
14 | { name: 'Administration' },
15 | { name: 'Information Technology' },
16 | { name: 'Customer Support' },
17 | { name: 'Development' }
18 | ]
19 | },
20 | series: [
21 | {
22 | name: '最高气温',
23 | lineStyle: {
24 | width: 1.5,
25 | color: "#ff52be80"
26 | },
27 | areaStyle: {
28 | color: {
29 | direction: [0, 1, 0, 0],
30 | colors: [
31 | '#9952be80'
32 | ]
33 | }
34 | },
35 | data: [11, 12, 15, 13, 12],
36 | },
37 | {
38 | name: '最高气温2',
39 | areaStyle: {
40 | color: {
41 | direction: [0, 1, 0, 0],
42 | colors: [
43 | '#99265fe5'
44 | ]
45 | }
46 | },
47 | data: [10, 12, 10.5, 13, 10]
48 | },
49 | ]
50 | })
51 | build() {
52 | NavDestination() {
53 | Column(){
54 | OmniRadarChart({
55 | options: this.defOption
56 | })
57 | }
58 | .height('50%')
59 | }
60 | .title("雷达图示例")
61 | }
62 | }
--------------------------------------------------------------------------------
/entry/src/main/ets/pages/expandabletext/OmniExpandableTextEntryPage.ets:
--------------------------------------------------------------------------------
1 | import { OmniExpandableText } from '@omni-ui/omni_component'
2 |
3 | @Builder
4 | export function OmniExpandableTextEntryPageBuilder() {
5 | OmniExpandableTextEntryPage()
6 | }
7 |
8 | @Preview
9 | @Entry
10 | @Component
11 | struct OmniExpandableTextEntryPage {
12 | @State content: string =
13 | '这是正文内容这是正文内容这是正文内容这是正文内容这是正文内容这是正文内容这是正文内容这是正文内容这是正文内容这是正文内容这是正文内容这是正文内容这是正文内容这是正文内容这是正文内容这是正文内容这是正文内容这是正文内容' +
14 | '这是正文内容这是正文内容这是正文内容这是正文内容这是正文内容这是正文内容这是正文内容这是正文内容这是正文内容这是正文内容这是正文内容这是正文内容' +
15 | '这是正文内容这是正文内容这是正文内容这是正文内容这是正文内容这是正文内容这是正文内容这是正文内容这是正文内容这是正文内容这是正文内容这是正文内容这是正文内容' +
16 | '这是正文内容这是正文内容这是正文内容这是正文内容这是正文内容这是正文内容这是正文内容这是正文内容这是正文内容这是正文内容这是正文内容'
17 |
18 | build() {
19 | NavDestination() {
20 | Scroll() {
21 | Column() {
22 | Text('示例一:默认样式')
23 | .fontSize(20)
24 | .fontWeight(FontWeight.Bold)
25 | .fontColor(0x333333)
26 | .padding({
27 | top: 20,
28 | bottom: 20,
29 | right: 20,
30 | left: 20
31 | })
32 | .width('100%')
33 | OmniExpandableText({
34 | content: this.content,
35 | maxLine: 5,
36 | }).margin(
37 | {
38 | left: 20,
39 | right: 20,
40 | bottom: 20
41 | }
42 | )
43 | Text('示例二:自定义样式')
44 | .fontSize(20)
45 | .fontWeight(FontWeight.Bold)
46 | .fontColor(0x333333)
47 | .padding({
48 | top: 20,
49 | bottom: 20,
50 | right: 20,
51 | left: 20
52 | })
53 | .width('100%')
54 | OmniExpandableText({
55 | content: this.content,
56 | maxLine: 6,
57 | contentFontColor: 0x333333,
58 | expandFontColor: 0xec623e
59 | })
60 | .margin({
61 | top: 20,
62 | bottom: 20,
63 | right: 20,
64 | left: 20
65 | })
66 | }
67 | }
68 | }.title('OmniExpandableText示例')
69 | }
70 | }
--------------------------------------------------------------------------------
/entry/src/main/ets/pages/filterbar/OmniFilterBarExampleEntryPage.ets:
--------------------------------------------------------------------------------
1 | @Builder
2 | export function OmniFilterBarExampleEntryPageBuilder() {
3 | OmniFilterBarExampleEntryPage()
4 | }
5 |
6 | @Entry
7 | @Component
8 | struct OmniFilterBarExampleEntryPage {
9 | @Consume('pathStack') pathStack: NavPathStack;
10 |
11 | aboutToAppear(): void {
12 |
13 | }
14 |
15 | build() {
16 | NavDestination() {
17 | Column() {
18 | Button(`多列示例`)
19 | .onClick(() => {
20 | this.pathStack.pushPath({ name: 'OmniFilterBarMultiListExamplePage' })
21 | })
22 | Button(`网格示例`)
23 | .onClick(() => {
24 | this.pathStack.pushPath({ name: 'OmniFilterBarMultiGridExamplePage' })
25 | })
26 | .margin({ top: 10 })
27 | Button(`更多示例`)
28 | .onClick(() => {
29 | this.pathStack.pushPath({ name: 'OmniFilterBarMoreExamplePage' })
30 | })
31 | .margin({ top: 10 })
32 | Button(`自定义类型示例`)
33 | .onClick(() => {
34 | this.pathStack.pushPath({ name: 'OmniFilterBarCustomExamplePage' })
35 | })
36 | .margin({ top: 10 })
37 | Button(`自定义Menu示例`)
38 | .onClick(() => {
39 | this.pathStack.pushPath({ name: 'OmniFilterBarMenuCustomExamplePage' })
40 | })
41 | .margin({ top: 10 })
42 | Button(`自定义样式`)
43 | .onClick(() => {
44 | this.pathStack.pushPath({ name: 'OmniFilterBarStyleCustomExamplePage' })
45 | })
46 | .margin({ top: 10 })
47 | }
48 | .height('100%')
49 | .width('100%')
50 | }
51 | .title('筛选示例入口')
52 |
53 | }
54 |
55 | @Builder
56 | Title() {
57 | Text('筛选示例')
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/entry/src/main/ets/pages/filterbar/OmniFilterBarMoreExamplePage.ets:
--------------------------------------------------------------------------------
1 | import { OmniFilterItemBean,
2 | OmniFilterBar
3 | } from '@omni-ui/omni_component'
4 | import {
5 | OmniFilterDataRoot} from '@omni-ui/omni_component/src/main/ets/components/filterbar/bean/OmniFilterItemBean'
6 | import util from '@ohos.util'
7 | import { OmniFilterController
8 | } from '@omni-ui/omni_component/src/main/ets/components/filterbar/OmniFilterBar'
9 | import { JSON } from '@kit.ArkTS'
10 | import ObjectUtil from '../../utils/utils'
11 |
12 | @Builder
13 | export function OmniFilterBarMoreExamplePageBuilder() {
14 | OmniFilterBarMoreExamplePage()
15 | }
16 |
17 | @Entry
18 | @Component
19 | struct OmniFilterBarMoreExamplePage {
20 | @State filterDataRoot?: OmniFilterDataRoot = undefined
21 | @State selectedParams?: Map = undefined
22 | private filterController: OmniFilterController = new OmniFilterController()
23 |
24 | aboutToAppear(): void {
25 | getContext(this).resourceManager.getRawFileContent('more_filter.json', (_err, value) => {
26 | let textDecoder = util.TextDecoder.create('utf-8', { ignoreBOM: true });
27 | const result = textDecoder.decodeWithStream(value, { stream: false })
28 | this.filterDataRoot = new OmniFilterDataRoot(OmniFilterItemBean.convertJsonToObj(result)!)
29 | });
30 | }
31 |
32 | build() {
33 | NavDestination() {
34 | Column() {
35 | if (this.filterDataRoot) {
36 | OmniFilterBar(
37 | {
38 | filterDataRoot: this.filterDataRoot,
39 | onFilterParamsChanged: (selectedParams: Map) => {
40 | this.selectedParams = selectedParams
41 | },
42 | filterController: this.filterController,
43 | }
44 | )
45 | }
46 | if (this.selectedParams) {
47 | Flex() {
48 | Column() {
49 | Text(`${JSON.stringify(ObjectUtil.ObjectFromEntries(this.selectedParams))}`)
50 | }
51 | .width(`100%`)
52 | .height(`100%`)
53 | .justifyContent(FlexAlign.Center)
54 | .alignItems(HorizontalAlign.Center)
55 | }
56 | }
57 | }
58 | .height('100%')
59 | .width('100%')
60 | }
61 | .title('筛选示例')
62 | .onWillDisappear(() => {
63 | console.log(``)
64 | this.filterController.close()
65 | })
66 | }
67 |
68 | @Builder
69 | Title() {
70 | Text('筛选示例')
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/entry/src/main/ets/pages/filterbar/OmniFilterBarMultiGridExamplePage.ets:
--------------------------------------------------------------------------------
1 | import { OmniFilterItemBean,
2 | OmniFilterBar
3 | } from '@omni-ui/omni_component'
4 | import {
5 | OmniFilterDataRoot} from '@omni-ui/omni_component/src/main/ets/components/filterbar/bean/OmniFilterItemBean'
6 | import util from '@ohos.util'
7 | import { OmniFilterController
8 | } from '@omni-ui/omni_component/src/main/ets/components/filterbar/OmniFilterBar'
9 | import { JSON } from '@kit.ArkTS'
10 | import ObjectUtil from '../../utils/utils'
11 |
12 | @Builder
13 | export function OmniFilterBarMultiGridExamplePageBuilder() {
14 | OmniFilterBarMultiGridExamplePage()
15 | }
16 |
17 | @Entry
18 | @Component
19 | struct OmniFilterBarMultiGridExamplePage {
20 | @State filterDataRoot?: OmniFilterDataRoot = undefined
21 | @State selectedParams?: Map = undefined
22 | private filterController: OmniFilterController = new OmniFilterController()
23 |
24 | aboutToAppear(): void {
25 | getContext(this).resourceManager.getRawFileContent('multi_grid_filter.json', (_err, value) => {
26 | let textDecoder = util.TextDecoder.create('utf-8', { ignoreBOM: true });
27 | const result = textDecoder.decodeWithStream(value, { stream: false })
28 | this.filterDataRoot = new OmniFilterDataRoot(OmniFilterItemBean.convertJsonToObj(result)!)
29 | });
30 | }
31 |
32 | build() {
33 | NavDestination() {
34 | Column() {
35 | if (this.filterDataRoot) {
36 | OmniFilterBar(
37 | {
38 | filterDataRoot: this.filterDataRoot,
39 | onFilterParamsChanged: (selectedParams: Map) => {
40 | this.selectedParams = selectedParams
41 | },
42 | filterController: this.filterController,
43 | }
44 | )
45 | }
46 | if (this.selectedParams) {
47 | Flex() {
48 | Column() {
49 | Text(`${JSON.stringify(ObjectUtil.ObjectFromEntries(this.selectedParams))}`)
50 | }
51 | .width(`100%`)
52 | .height(`100%`)
53 | .justifyContent(FlexAlign.Center)
54 | .alignItems(HorizontalAlign.Center)
55 | }
56 | }
57 | }
58 | .height('100%')
59 | .width('100%')
60 | }
61 | .title('筛选示例')
62 | .onWillDisappear(() => {
63 | console.log(``)
64 | this.filterController.close()
65 | })
66 | }
67 |
68 | @Builder
69 | Title() {
70 | Text('筛选示例')
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/entry/src/main/ets/pages/filterbar/OmniFilterBarMultiListExamplePage.ets:
--------------------------------------------------------------------------------
1 | import { OmniFilterItemBean,
2 | OmniFilterBar
3 | } from '@omni-ui/omni_component'
4 | import {
5 | OmniFilterDataRoot} from '@omni-ui/omni_component/src/main/ets/components/filterbar/bean/OmniFilterItemBean'
6 | import util from '@ohos.util'
7 | import { OmniFilterController
8 | } from '@omni-ui/omni_component/src/main/ets/components/filterbar/OmniFilterBar'
9 | import { JSON } from '@kit.ArkTS'
10 | import ObjectUtil from '../../utils/utils'
11 |
12 | @Builder
13 | export function OmniFilterBarMultiListExamplePageBuilder() {
14 | OmniFilterBarMultiListExamplePage()
15 | }
16 |
17 | @Entry
18 | @Component
19 | struct OmniFilterBarMultiListExamplePage {
20 | @State filterDataRoot?: OmniFilterDataRoot = undefined
21 | @State selectedParams?: Map = undefined
22 | private filterController: OmniFilterController = new OmniFilterController()
23 |
24 | aboutToAppear(): void {
25 | getContext(this).resourceManager.getRawFileContent('multi_list_filter.json', (_err, value) => {
26 | let textDecoder = util.TextDecoder.create('utf-8', { ignoreBOM: true });
27 | const result = textDecoder.decodeWithStream(value, { stream: false })
28 | this.filterDataRoot = new OmniFilterDataRoot(OmniFilterItemBean.convertJsonToObj(result)!)
29 | });
30 | }
31 |
32 | build() {
33 | NavDestination() {
34 | Column() {
35 | if (this.filterDataRoot) {
36 | OmniFilterBar(
37 | {
38 | filterDataRoot: this.filterDataRoot,
39 | onFilterParamsChanged: (selectedParams: Map) => {
40 | this.selectedParams = selectedParams
41 | },
42 | filterController: this.filterController,
43 | }
44 | )
45 | }
46 | if (this.selectedParams) {
47 | Flex() {
48 | Column() {
49 | Text(`${JSON.stringify(ObjectUtil.ObjectFromEntries(this.selectedParams))}`)
50 | }
51 | .width(`100%`)
52 | .height(`100%`)
53 | .justifyContent(FlexAlign.Center)
54 | .alignItems(HorizontalAlign.Center)
55 | }
56 | }
57 | }
58 | .height('100%')
59 | .width('100%')
60 | }
61 | .title('筛选示例')
62 | .onWillDisappear(() => {
63 | console.log(``)
64 | this.filterController.close()
65 | })
66 | }
67 |
68 | @Builder
69 | Title() {
70 | Text('筛选示例')
71 | }
72 | }
--------------------------------------------------------------------------------
/entry/src/main/ets/pages/filterbar/component/OmniCustomValueRange.ets:
--------------------------------------------------------------------------------
1 | import { OmniFilterItemBean } from "@omni-ui/omni_component/src/main/ets/components/filterbar/bean/OmniFilterItemBean"
2 | import { OmniFilterUtil } from "@omni-ui/omni_component/src/main/ets/components/filterbar/util/OmniFilterUtil"
3 |
4 | @Component
5 | export struct OmniFilterCustomValueRange {
6 | @ObjectLink item: OmniFilterItemBean
7 | onConfirmAction?: () => void
8 |
9 | build() {
10 | List() {
11 | ForEach(this.item.children, (item: OmniFilterItemBean, index: number) => {
12 | ListItem() {
13 | if (item.customMap) {
14 | Row() {
15 | Slider({
16 | style: SliderStyle.OutSet,
17 | value: 4000,
18 | min: item.customMap[`leftValue`],
19 | max: item.customMap[`rightValue`],
20 | })
21 | .selectedColor(0xFF552E)
22 | .trackColor(0xFF552E)
23 | .blockStyle({ type: SliderBlockType.DEFAULT })
24 | .layoutWeight(1)
25 | }
26 | .margin({ left: 20, right: 20 })
27 | } else {
28 | Column() {
29 | Text(`${item.title}`)
30 | .fontColor(this.tagTextColor(item))
31 | }
32 | .width("100%")
33 | .height(30)
34 | .onClick(() => {
35 | //内置工具类处理兄弟节点的选中状态(通用情况下),如有特殊逻辑需要自定义
36 | OmniFilterUtil.processBrotherItemSelectStatus(item)
37 | this.onConfirmAction?.()
38 | })
39 | }
40 | }
41 | .margin({ top: 10 })
42 | }, (item: OmniFilterItemBean, index: number) => item.generateListKey() + index)
43 | }
44 | .backgroundColor(Color.White)
45 | }
46 |
47 | private tagTextColor(item: OmniFilterItemBean): ResourceColor {
48 | if (item.isSelected) {
49 | return 0xFF552E
50 | } else {
51 | return Color.Black
52 | }
53 | }
54 | }
--------------------------------------------------------------------------------
/entry/src/main/ets/pages/guide/OmniGuideExampleIndex.ets:
--------------------------------------------------------------------------------
1 | import {
2 | BubbleBean,
3 | BubbleIndicator,
4 | BubblePosition,
5 | Controller,
6 | GuidePage,
7 | OmniGuide,
8 | OmniGuideBuilder
9 | } from '@omni-ui/omni_component';
10 |
11 | @Builder
12 | export function OmniGuideExamplePageBuilder() {
13 | OmniGuideExampleIndex()
14 | }
15 |
16 | @Entry
17 | @Component
18 | export struct OmniGuideExampleIndex {
19 | @Consume('pathStack') pathStack: NavPathStack;
20 | private builder: OmniGuideBuilder | null = null;
21 | private controller: Controller | null = null;
22 |
23 | aboutToAppear() {
24 | this.builder = new OmniGuideBuilder()
25 | .setLabel('OmniGuideExampleIndex')
26 | .alwaysShow(true)
27 | .addGuidePage(GuidePage.newInstance()
28 | .addHighLight('Simple')
29 | .setBubbleIndicator(
30 | new BubbleIndicator(
31 | 'Simple',
32 | new BubbleBean('标题栏', '这里是副标题栏,这是一个简单的演示'),
33 | BubblePosition.BOTTOM
34 | )
35 | )
36 | )
37 | }
38 |
39 | build() {
40 | NavDestination() {
41 | Column() {
42 | Stack() {
43 | OmniGuide({
44 | content: this.content,
45 | builder: this.builder,
46 | onReady: (controller: Controller) => {
47 | this.controller = controller;
48 | }
49 | })
50 | }
51 | }
52 | .width('100%')
53 | }.title('OmniGuide 示例')
54 | }
55 |
56 | @Builder
57 | private content() {
58 | Column() {
59 | Button($r('app.string.just_use_it_simply'))
60 | .onClick(() => {
61 | if (this.controller) {
62 | this.controller.show();
63 | }
64 | }).id('Simple')
65 | .margin(10)
66 | .width('50%')
67 |
68 | Button($r('app.string.multi_guide_page'))
69 | .onClick(() => {
70 | this.pathStack.pushPath({ name: 'OmniGuideMultiPageExample' })
71 | })
72 | .margin(10)
73 | .width('50%')
74 | }.alignItems(HorizontalAlign.Center)
75 | .width('100%')
76 | .height('100%');
77 | }
78 | }
--------------------------------------------------------------------------------
/entry/src/main/ets/pages/imagepicker/OmniImageAlbumPickerPage.ets:
--------------------------------------------------------------------------------
1 | import { AlbumInfo, AlbumPickerComponent, AlbumPickerOptions, PickerColorMode } from "@kit.MediaLibraryKit"
2 |
3 | @Builder
4 | export function OmniImageAlbumPickerPageBuilder() {
5 | OmniImageAlbumPickerPage()
6 | }
7 |
8 | @Component
9 | export struct OmniImageAlbumPickerPage {
10 | @Consume('pathStack') pageStack: NavPathStack;
11 |
12 | albumOptions: AlbumPickerOptions = new AlbumPickerOptions();
13 |
14 | onAlbumInfoClick(albumInfo: AlbumInfo): boolean {
15 | this.pageStack.pop(albumInfo)
16 | return true
17 | }
18 | build() {
19 | NavDestination() {
20 | AlbumPickerComponent({
21 | albumPickerOptions: this.albumOptions,
22 | onAlbumClick: (albumInfo: AlbumInfo): boolean => this.onAlbumInfoClick?.(albumInfo) ?? false
23 | })
24 | }
25 | .title("相册选择")
26 | }
27 |
28 | aboutToAppear(): void {
29 | this.albumOptions.themeColorMode = PickerColorMode.AUTO
30 |
31 | }
32 | }
--------------------------------------------------------------------------------
/entry/src/main/ets/pages/imagepicker/OmniImagePickerExamplePage.ets:
--------------------------------------------------------------------------------
1 | import {
2 | OmniImagePickerTrigger
3 | } from "@omni-ui/omni_component/src/main/ets/components/imagepicker/OmniImagePickerTrigger";
4 |
5 | @Builder
6 | export function OmniImagePickerExamplePageBuilder() {
7 | OmniImagePickerExamplePage()
8 | }
9 |
10 | @Component
11 | export struct OmniImagePickerExamplePage {
12 | @Consume('pathStack') pageStack: NavPathStack;
13 | @State selectUris: Array = new Array();
14 |
15 | build() {
16 | NavDestination() {
17 | OmniImagePickerTrigger({
18 | selectUris: $selectUris,
19 | goImagePicker: () => {
20 | this.pageStack.pushPathByName("OmniImagePickerSelectExamplePage", null, (data: PopInfo) => {
21 | if (data.result instanceof Array) {
22 | data.result.forEach((url: string) => {
23 | this.selectUris.push(url)
24 | })
25 | }
26 | }, true)
27 | }
28 | })
29 | }
30 | .title("图片选择器示例")
31 | }
32 | }
--------------------------------------------------------------------------------
/entry/src/main/ets/pages/imagepicker/OmniImagePickerSelectExamplePage.ets:
--------------------------------------------------------------------------------
1 | import { OmniImagePicker } from '@omni-ui/omni_component'
2 | import { AlbumInfo } from '@kit.MediaLibraryKit';
3 |
4 | @Builder
5 | export function OmniImagePickerSelectExamplePageBuilder() {
6 | OmniImagePickerSelectExamplePage()
7 | }
8 | @Component
9 | export struct OmniImagePickerSelectExamplePage {
10 | @Consume('pathStack') pageStack: NavPathStack;
11 |
12 | @State currentAlbumUrl?: string = ""
13 | @State currentAlbumName?: string = "照片和视频"
14 | build() {
15 | NavDestination() {
16 | OmniImagePicker({
17 | currentAlbumUrl: this.currentAlbumUrl,
18 | onFinished: (result: Object) => {
19 | this.pageStack.pop(result)
20 | },
21 | goAlbumPicker: () => {
22 | this.pageStack.pushPathByName("OmniImageAlbumPickerPage", null, (popInfo: PopInfo) => {
23 | if (popInfo.result instanceof AlbumInfo) {
24 | this.currentAlbumUrl = popInfo.result.uri
25 | this.currentAlbumName = popInfo.result.albumName
26 | }
27 | }, true)
28 | }
29 | })
30 | }
31 | .title(this.currentAlbumName)
32 | }
33 | }
--------------------------------------------------------------------------------
/entry/src/main/ets/pages/loading/OmniLoadingEntryPage.ets:
--------------------------------------------------------------------------------
1 | import { OmniDotLoadingView, OmniLoading, OmniPageLoading } from '@omni-ui/omni_component';
2 |
3 | @Builder
4 | export function OmniLoadingEntryPageBuilder() {
5 | OmniLoadingEntryPage()
6 | }
7 |
8 | @Entry
9 | @Component
10 | struct OmniLoadingEntryPage {
11 | @State loading: boolean = true;
12 |
13 | build() {
14 | NavDestination() {
15 | Column({ space: 10 }) {
16 | Text('正常Loading展示')
17 | OmniPageLoading()
18 | Text('短文案Loading展示')
19 | OmniPageLoading({ options: { content: '我是较短的的Loading' } })
20 | Text('长文案Loading展示')
21 | OmniPageLoading({ options: {content: '我是较长的我是较长的我是较长的...' }})
22 | Text('四色圆点Loading展示')
23 | OmniDotLoadingView({ loading: $loading })
24 | Button('点击开始/暂停loading')
25 | .onClick(() => {
26 | this.loading = !this.loading
27 | })
28 | Button('点击打开loading弹窗,持续2s')
29 | .onClick(() => {
30 | let loading = new OmniLoading(this.getUIContext());
31 | loading.show()
32 | setTimeout(() => {
33 | loading.dismiss()
34 | }, 2000)
35 | })
36 | }
37 | .alignItems(HorizontalAlign.Center)
38 | .width('100%')
39 | }
40 | .title('Loading示例')
41 | }
42 | }
--------------------------------------------------------------------------------
/entry/src/main/ets/pages/search/OmniSearchExamplePage.ets:
--------------------------------------------------------------------------------
1 | import {
2 | OmniSearchV2,
3 | SearchContainerModifier,
4 | SearchTextInputModifier,
5 | OmniToast
6 | } from "@omni-ui/omni_component"
7 | import { inputMethod } from "@kit.IMEKit"
8 |
9 | @Builder
10 | export function OmniSearchExamplePageBuilder() {
11 | OmniSearchExamplePage()
12 | }
13 |
14 | @Component
15 | struct OmniSearchExamplePage {
16 | build() {
17 | NavDestination() {
18 |
19 | Column() {
20 | Text('默认样式').margin({ bottom: 15 })
21 | OmniSearchV2()
22 |
23 | Text('自定义样式').margin({ bottom: 15, top: 15 })
24 | OmniSearchV2({
25 | config: {
26 | defaultText: '关键字',
27 | placeHolderText: '请输入想要搜索的内容',
28 | hasCancelBtn: false,
29 | hasClearBtn: true,
30 | hasSearchBtn: true
31 | },
32 | textInputModifier: new SearchTextInputModifier()
33 | .withCaretColor('#FF552E')
34 | .withBackgroundColor(0xffffff),
35 | foregroundContainerModifier: new SearchContainerModifier()
36 | .withHeight(44)
37 | .withBackgroundColor(0xffffff)
38 | .withBorderRadius(6)
39 | .withBorderWidth(1)
40 | .withBorderColor('#F7F7F7')
41 | .withShadow({
42 | radius: 5,
43 | type: ShadowType.BLUR,
44 | color: '#F7F7F7'
45 | })
46 | .withMargin({
47 | left: '5%',
48 | right: '5%',
49 | top: 10,
50 | bottom: 10
51 | }),
52 | backgroundContainerModifier: new SearchContainerModifier()
53 | .withWidth('100%')
54 | .withPadding({
55 | right: 10
56 | })
57 | .withBackgroundColor(0xffffff),
58 | submitCallback: (searchText) => {
59 | OmniToast.showText({ msg: `搜索:${searchText}` })
60 | },
61 | onCancel: () => {
62 | OmniToast.showText({ msg: `点击取消按钮` })
63 | },
64 | onFocusCallback: () => {
65 | // OmniToast.showText({ msg: `获取到焦点` })
66 | },
67 | onTextChange: (text) => {
68 | OmniToast.showText({ msg: `输入框内容变化:${text}` })
69 | }
70 | })
71 | }
72 | .height('100%')
73 | .onClick(() => {
74 | // 退出文本编辑状态
75 | inputMethod.getController().stopInputSession();
76 | })
77 |
78 | }.title('Search示例')
79 | }
80 | }
--------------------------------------------------------------------------------
/entry/src/main/ets/pages/tabs/OmniTabExamplePage.ets:
--------------------------------------------------------------------------------
1 | import { OmniTabConfig, OmniTabController, OmniTabItemConfig, OmniTabMode, OmniTabs } from "@omni-ui/omni_component"
2 | import { OmniToast } from "@omni-ui/omni_component/src/main/ets/components/toast/OmniToast"
3 |
4 | @Builder
5 | export function OmniTabExamplePageBuilder() {
6 | OmniTabExamplePage()
7 | }
8 |
9 | @Component
10 | export struct OmniTabExamplePage {
11 | private tabCtrl = new OmniTabController()
12 | private tabConfig: OmniTabConfig = {
13 | mode: OmniTabMode.Scrollable,
14 | labelColor: '#0090ff'
15 | }
16 | private tabConfig1: OmniTabConfig = {
17 | mode: OmniTabMode.Fix,
18 | labelColor: '#ff552e',
19 | indicatorColor: '#ff552e'
20 | }
21 | @State
22 | tabs: OmniTabItemConfig[] = [
23 | new OmniTabItemConfig("tab0"),
24 | new OmniTabItemConfig("tab1", "", $r('app.media.tag_heart_fill'), ""),
25 | new OmniTabItemConfig("tab2", "", "", "", true),
26 | new OmniTabItemConfig("tab3", "", "", $r('app.media.tag_heart')),
27 | new OmniTabItemConfig("tab4"),
28 | new OmniTabItemConfig("tab5"),
29 | new OmniTabItemConfig("tab6"),
30 | new OmniTabItemConfig("tab7"),
31 | ]
32 |
33 |
34 | build() {
35 | NavDestination() {
36 | Column() {
37 | OmniTabs({
38 | tabs: this.tabs,
39 | tabConfig: this.tabConfig,
40 | onTabClick: (index: number) => {
41 | OmniToast.showText({
42 | msg: `click tab ${index}`
43 | })
44 | }
45 | })
46 |
47 | OmniTabs({
48 | tabs: this.tabs,
49 | tabConfig: this.tabConfig1,
50 | tabController: this.tabCtrl
51 | })
52 | .margin({
53 | top: 20
54 | })
55 |
56 | Button('Tab改变index')
57 | .margin({
58 | top: 30
59 | })
60 | .onClick(() => {
61 | this.tabCtrl.changeIndex(3)
62 | })
63 |
64 | Button('添加小红点')
65 | .margin({
66 | top: 20
67 | })
68 | .onClick(() => {
69 | this.tabs[0].badgeText = "New"
70 | })
71 | Button('取消小红点')
72 | .margin({
73 | top: 20
74 | })
75 | .onClick(() => {
76 | this.tabs[0].badgeText = ""
77 | })
78 |
79 | }
80 | .height('100%')
81 | .width('100%')
82 | }
83 | .title('Tabs示例')
84 |
85 | }
86 |
87 | onDidBuild(): void {
88 |
89 | }
90 |
91 | }
--------------------------------------------------------------------------------
/entry/src/main/ets/utils/utils.ts:
--------------------------------------------------------------------------------
1 | export default class ObjectUtil {
2 | static ObjectFromEntries(source: Iterable): Object {
3 | return Object.fromEntries(source)
4 | }
5 | }
--------------------------------------------------------------------------------
/entry/src/main/module.json5:
--------------------------------------------------------------------------------
1 | {
2 | "module": {
3 | "name": "entry",
4 | "type": "entry",
5 | "description": "$string:module_desc",
6 | "mainElement": "EntryAbility",
7 | "deviceTypes": [
8 | "phone"
9 | ],
10 | "deliveryWithInstall": true,
11 | "installationFree": false,
12 | "pages": "$profile:main_pages",
13 | "routerMap": "$profile:route_map",
14 | "abilities": [
15 | {
16 | "name": "EntryAbility",
17 | "srcEntry": "./ets/entryability/EntryAbility.ets",
18 | "description": "$string:EntryAbility_desc",
19 | "icon": "$media:app_icon_startwindow",
20 | "label": "$string:EntryAbility_label",
21 | "startWindowIcon": "$media:app_icon_startwindow",
22 | "startWindowBackground": "$color:start_window_background",
23 | "exported": true,
24 | "skills": [
25 | {
26 | "entities": [
27 | "entity.system.home"
28 | ],
29 | "actions": [
30 | "action.system.home"
31 | ]
32 | }
33 | ]
34 | }
35 | ],
36 | "extensionAbilities": [
37 | {
38 | "name": "EntryBackupAbility",
39 | "srcEntry": "./ets/entrybackupability/EntryBackupAbility.ets",
40 | "type": "backup",
41 | "exported": false,
42 | "metadata": [
43 | {
44 | "name": "ohos.extension.backup",
45 | "resource": "$profile:backup_config"
46 | }
47 | ]
48 | }
49 | ],
50 | "requestPermissions": [
51 | {
52 | "name": "ohos.permission.INTERNET",
53 | "usedScene": {
54 | "abilities": [
55 | "EntryAbility"
56 | ],
57 | "when": "always"
58 | }
59 | }
60 | ]
61 | }
62 | }
--------------------------------------------------------------------------------
/entry/src/main/resources/base/element/color.json:
--------------------------------------------------------------------------------
1 | {
2 | "color": [
3 | {
4 | "name": "start_window_background",
5 | "value": "#FFFFFF"
6 | }
7 | ]
8 | }
--------------------------------------------------------------------------------
/entry/src/main/resources/base/element/string.json:
--------------------------------------------------------------------------------
1 | {
2 | "string": [
3 | {
4 | "name": "module_desc",
5 | "value": "module description"
6 | },
7 | {
8 | "name": "EntryAbility_desc",
9 | "value": "description"
10 | },
11 | {
12 | "name": "EntryAbility_label",
13 | "value": "OmniUI"
14 | },
15 | {
16 | "name": "multi_guide_page",
17 | "value": "Multi page guide page"
18 | },
19 | {
20 | "name": "just_use_it_simply",
21 | "value": "just use it simply"
22 | },
23 | {
24 | "name": "current_index",
25 | "value": "当前引导页index: "
26 | },
27 | {
28 | "name": "guide_page_switching",
29 | "value": "Guide page switching"
30 | }
31 | ]
32 | }
--------------------------------------------------------------------------------
/entry/src/main/resources/base/media/app_icon_startwindow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuba/omni-ui/35590dedca468fe76b1dd1eca21dc649daf35fad/entry/src/main/resources/base/media/app_icon_startwindow.png
--------------------------------------------------------------------------------
/entry/src/main/resources/base/media/background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuba/omni-ui/35590dedca468fe76b1dd1eca21dc649daf35fad/entry/src/main/resources/base/media/background.png
--------------------------------------------------------------------------------
/entry/src/main/resources/base/media/bottombar_car.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuba/omni-ui/35590dedca468fe76b1dd1eca21dc649daf35fad/entry/src/main/resources/base/media/bottombar_car.png
--------------------------------------------------------------------------------
/entry/src/main/resources/base/media/bottombar_car_selected.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuba/omni-ui/35590dedca468fe76b1dd1eca21dc649daf35fad/entry/src/main/resources/base/media/bottombar_car_selected.png
--------------------------------------------------------------------------------
/entry/src/main/resources/base/media/bottombar_home.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuba/omni-ui/35590dedca468fe76b1dd1eca21dc649daf35fad/entry/src/main/resources/base/media/bottombar_home.png
--------------------------------------------------------------------------------
/entry/src/main/resources/base/media/bottombar_home_selecte.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuba/omni-ui/35590dedca468fe76b1dd1eca21dc649daf35fad/entry/src/main/resources/base/media/bottombar_home_selecte.png
--------------------------------------------------------------------------------
/entry/src/main/resources/base/media/bottombar_mine.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuba/omni-ui/35590dedca468fe76b1dd1eca21dc649daf35fad/entry/src/main/resources/base/media/bottombar_mine.png
--------------------------------------------------------------------------------
/entry/src/main/resources/base/media/bottombar_mine_selected.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuba/omni-ui/35590dedca468fe76b1dd1eca21dc649daf35fad/entry/src/main/resources/base/media/bottombar_mine_selected.png
--------------------------------------------------------------------------------
/entry/src/main/resources/base/media/bottombar_read.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuba/omni-ui/35590dedca468fe76b1dd1eca21dc649daf35fad/entry/src/main/resources/base/media/bottombar_read.png
--------------------------------------------------------------------------------
/entry/src/main/resources/base/media/bottombar_read_selected.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuba/omni-ui/35590dedca468fe76b1dd1eca21dc649daf35fad/entry/src/main/resources/base/media/bottombar_read_selected.png
--------------------------------------------------------------------------------
/entry/src/main/resources/base/media/foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuba/omni-ui/35590dedca468fe76b1dd1eca21dc649daf35fad/entry/src/main/resources/base/media/foreground.png
--------------------------------------------------------------------------------
/entry/src/main/resources/base/media/ic_back_white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuba/omni-ui/35590dedca468fe76b1dd1eca21dc649daf35fad/entry/src/main/resources/base/media/ic_back_white.png
--------------------------------------------------------------------------------
/entry/src/main/resources/base/media/ic_down_arrow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuba/omni-ui/35590dedca468fe76b1dd1eca21dc649daf35fad/entry/src/main/resources/base/media/ic_down_arrow.png
--------------------------------------------------------------------------------
/entry/src/main/resources/base/media/ic_right_arrow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuba/omni-ui/35590dedca468fe76b1dd1eca21dc649daf35fad/entry/src/main/resources/base/media/ic_right_arrow.png
--------------------------------------------------------------------------------
/entry/src/main/resources/base/media/icon_category_chart.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/entry/src/main/resources/base/media/icon_category_form.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/entry/src/main/resources/base/media/icon_category_navigation.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/entry/src/main/resources/base/media/icon_category_operatefeedback.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/entry/src/main/resources/base/media/icon_category_page.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/entry/src/main/resources/base/media/icon_category_theme_style.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuba/omni-ui/35590dedca468fe76b1dd1eca21dc649daf35fad/entry/src/main/resources/base/media/icon_category_theme_style.png
--------------------------------------------------------------------------------
/entry/src/main/resources/base/media/icon_category_view.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/entry/src/main/resources/base/media/icon_filter_reset_custom.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuba/omni-ui/35590dedca468fe76b1dd1eca21dc649daf35fad/entry/src/main/resources/base/media/icon_filter_reset_custom.png
--------------------------------------------------------------------------------
/entry/src/main/resources/base/media/layered_image.json:
--------------------------------------------------------------------------------
1 | {
2 | "layered-image":
3 | {
4 | "background" : "$media:background",
5 | "foreground" : "$media:foreground"
6 | }
7 | }
--------------------------------------------------------------------------------
/entry/src/main/resources/base/media/startIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuba/omni-ui/35590dedca468fe76b1dd1eca21dc649daf35fad/entry/src/main/resources/base/media/startIcon.png
--------------------------------------------------------------------------------
/entry/src/main/resources/base/media/tag_heart.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuba/omni-ui/35590dedca468fe76b1dd1eca21dc649daf35fad/entry/src/main/resources/base/media/tag_heart.png
--------------------------------------------------------------------------------
/entry/src/main/resources/base/media/tag_heart_fill.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuba/omni-ui/35590dedca468fe76b1dd1eca21dc649daf35fad/entry/src/main/resources/base/media/tag_heart_fill.png
--------------------------------------------------------------------------------
/entry/src/main/resources/base/profile/backup_config.json:
--------------------------------------------------------------------------------
1 | {
2 | "allowToBackupRestore": true
3 | }
--------------------------------------------------------------------------------
/entry/src/main/resources/base/profile/main_pages.json:
--------------------------------------------------------------------------------
1 | {
2 | "src": [
3 | "pages/Index",
4 | "pages/loading/OmniLoadingEntryPage"
5 | ]
6 | }
--------------------------------------------------------------------------------
/entry/src/main/resources/en_US/element/string.json:
--------------------------------------------------------------------------------
1 | {
2 | "string": [
3 | {
4 | "name": "module_desc",
5 | "value": "module description"
6 | },
7 | {
8 | "name": "EntryAbility_desc",
9 | "value": "description"
10 | },
11 | {
12 | "name": "EntryAbility_label",
13 | "value": "label"
14 | },
15 | {
16 | "name": "multi_guide_page",
17 | "value": "Multi page guide page"
18 | },
19 | {
20 | "name": "just_use_it_simply",
21 | "value": "just use it simply"
22 | },
23 | {
24 | "name": "current_index",
25 | "value": "Current guide page index: "
26 | },
27 | {
28 | "name": "guide_page_switching",
29 | "value": "Guide page switching: "
30 | }
31 | ]
32 | }
--------------------------------------------------------------------------------
/entry/src/main/resources/zh_CN/element/string.json:
--------------------------------------------------------------------------------
1 | {
2 | "string": [
3 | {
4 | "name": "module_desc",
5 | "value": "模块描述"
6 | },
7 | {
8 | "name": "EntryAbility_desc",
9 | "value": "description"
10 | },
11 | {
12 | "name": "EntryAbility_label",
13 | "value": "OmniUI"
14 | },
15 | {
16 | "name": "multi_guide_page",
17 | "value": "多页引导页"
18 | },
19 | {
20 | "name": "just_use_it_simply",
21 | "value": "简单使用"
22 | },
23 | {
24 | "name": "current_index",
25 | "value": "当前引导页index: "
26 | },
27 | {
28 | "name": "guide_page_switching",
29 | "value": "引导页切换: "
30 | }
31 | ]
32 | }
--------------------------------------------------------------------------------
/entry/src/mock/mock-config.json5:
--------------------------------------------------------------------------------
1 | {
2 | }
--------------------------------------------------------------------------------
/entry/src/ohosTest/ets/test/Ability.test.ets:
--------------------------------------------------------------------------------
1 | import { hilog } from '@kit.PerformanceAnalysisKit';
2 | import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium';
3 |
4 | export default function abilityTest() {
5 | describe('ActsAbilityTest', () => {
6 | // Defines a test suite. Two parameters are supported: test suite name and test suite function.
7 | beforeAll(() => {
8 | // Presets an action, which is performed only once before all test cases of the test suite start.
9 | // This API supports only one parameter: preset action function.
10 | })
11 | beforeEach(() => {
12 | // Presets an action, which is performed before each unit test case starts.
13 | // The number of execution times is the same as the number of test cases defined by **it**.
14 | // This API supports only one parameter: preset action function.
15 | })
16 | afterEach(() => {
17 | // Presets a clear action, which is performed after each unit test case ends.
18 | // The number of execution times is the same as the number of test cases defined by **it**.
19 | // This API supports only one parameter: clear action function.
20 | })
21 | afterAll(() => {
22 | // Presets a clear action, which is performed after all test cases of the test suite end.
23 | // This API supports only one parameter: clear action function.
24 | })
25 | it('assertContain', 0, () => {
26 | // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function.
27 | hilog.info(0x0000, 'testTag', '%{public}s', 'it begin');
28 | let a = 'abc';
29 | let b = 'b';
30 | // Defines a variety of assertion methods, which are used to declare expected boolean conditions.
31 | expect(a).assertContain(b);
32 | expect(a).assertEqual(a);
33 | })
34 | })
35 | }
--------------------------------------------------------------------------------
/entry/src/ohosTest/ets/test/List.test.ets:
--------------------------------------------------------------------------------
1 | import abilityTest from './Ability.test';
2 |
3 | export default function testsuite() {
4 | abilityTest();
5 | }
--------------------------------------------------------------------------------
/entry/src/ohosTest/module.json5:
--------------------------------------------------------------------------------
1 | {
2 | "module": {
3 | "name": "entry_test",
4 | "type": "feature",
5 | "deviceTypes": [
6 | "phone"
7 | ],
8 | "deliveryWithInstall": true,
9 | "installationFree": false
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/entry/src/test/List.test.ets:
--------------------------------------------------------------------------------
1 | import localUnitTest from './LocalUnit.test';
2 |
3 | export default function testsuite() {
4 | localUnitTest();
5 | }
--------------------------------------------------------------------------------
/entry/src/test/LocalUnit.test.ets:
--------------------------------------------------------------------------------
1 | import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium';
2 |
3 | export default function localUnitTest() {
4 | describe('localUnitTest', () => {
5 | // Defines a test suite. Two parameters are supported: test suite name and test suite function.
6 | beforeAll(() => {
7 | // Presets an action, which is performed only once before all test cases of the test suite start.
8 | // This API supports only one parameter: preset action function.
9 | });
10 | beforeEach(() => {
11 | // Presets an action, which is performed before each unit test case starts.
12 | // The number of execution times is the same as the number of test cases defined by **it**.
13 | // This API supports only one parameter: preset action function.
14 | });
15 | afterEach(() => {
16 | // Presets a clear action, which is performed after each unit test case ends.
17 | // The number of execution times is the same as the number of test cases defined by **it**.
18 | // This API supports only one parameter: clear action function.
19 | });
20 | afterAll(() => {
21 | // Presets a clear action, which is performed after all test cases of the test suite end.
22 | // This API supports only one parameter: clear action function.
23 | });
24 | it('assertContain', 0, () => {
25 | // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function.
26 | let a = 'abc';
27 | let b = 'b';
28 | // Defines a variety of assertion methods, which are used to declare expected boolean conditions.
29 | expect(a).assertContain(b);
30 | expect(a).assertEqual(a);
31 | });
32 | });
33 | }
--------------------------------------------------------------------------------
/hvigor/hvigor-config.json5:
--------------------------------------------------------------------------------
1 | {
2 | "modelVersion": "5.0.0",
3 | "dependencies": {
4 | },
5 | "execution": {
6 | // "analyze": "normal", /* Define the build analyze mode. Value: [ "normal" | "advanced" | false ]. Default: "normal" */
7 | // "daemon": true, /* Enable daemon compilation. Value: [ true | false ]. Default: true */
8 | // "incremental": true, /* Enable incremental compilation. Value: [ true | false ]. Default: true */
9 | // "parallel": true, /* Enable parallel compilation. Value: [ true | false ]. Default: true */
10 | // "typeCheck": false, /* Enable typeCheck. Value: [ true | false ]. Default: false */
11 | },
12 | "logging": {
13 | // "level": "info" /* Define the log level. Value: [ "debug" | "info" | "warn" | "error" ]. Default: "info" */
14 | },
15 | "debugging": {
16 | // "stacktrace": false /* Disable stacktrace compilation. Value: [ true | false ]. Default: false */
17 | },
18 | "nodeOptions": {
19 | // "maxOldSpaceSize": 8192 /* Enable nodeOptions maxOldSpaceSize compilation. Unit M. Used for the daemon process. Default: 8192*/
20 | // "exposeGC": true /* Enable to trigger garbage collection explicitly. Default: true*/
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/hvigorfile.ts:
--------------------------------------------------------------------------------
1 | import { appTasks } from '@ohos/hvigor-ohos-plugin';
2 |
3 | export default {
4 | system: appTasks, /* Built-in plugin of Hvigor. It cannot be modified. */
5 | plugins:[] /* Custom plugin to extend the functionality of Hvigor. */
6 | }
7 |
--------------------------------------------------------------------------------
/oh-package-lock.json5:
--------------------------------------------------------------------------------
1 | {
2 | "meta": {
3 | "stableOrder": true
4 | },
5 | "lockfileVersion": 3,
6 | "ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.",
7 | "specifiers": {
8 | "@ohos/hamock@1.0.0": "@ohos/hamock@1.0.0",
9 | "@ohos/hypium@1.0.19": "@ohos/hypium@1.0.19"
10 | },
11 | "packages": {
12 | "@ohos/hamock@1.0.0": {
13 | "name": "@ohos/hamock",
14 | "version": "1.0.0",
15 | "integrity": "sha512-K6lDPYc6VkKe6ZBNQa9aoG+ZZMiwqfcR/7yAVFSUGIuOAhPvCJAo9+t1fZnpe0dBRBPxj2bxPPbKh69VuyAtDg==",
16 | "resolved": "https://repo.harmonyos.com/ohpm/@ohos/hamock/-/hamock-1.0.0.har",
17 | "registryType": "ohpm"
18 | },
19 | "@ohos/hypium@1.0.19": {
20 | "name": "@ohos/hypium",
21 | "version": "1.0.19",
22 | "integrity": "sha512-cEjDgLFCm3cWZDeRXk7agBUkPqjWxUo6AQeiu0gEkb3J8ESqlduQLSIXeo3cCsm8U/asL7iKjF85ZyOuufAGSQ==",
23 | "resolved": "https://repo.harmonyos.com/ohpm/@ohos/hypium/-/hypium-1.0.19.har",
24 | "registryType": "ohpm"
25 | }
26 | }
27 | }
--------------------------------------------------------------------------------
/oh-package.json5:
--------------------------------------------------------------------------------
1 | {
2 | "modelVersion": "5.0.0",
3 | "name": "Omni-UI",
4 | "version": "1.0.1",
5 | "description": "开箱即用、高扩展性、丰富高效的鸿蒙开源组件库。",
6 | "main": "",
7 | "author": "",
8 | "license": "",
9 | "dependencies": {
10 | },
11 | "devDependencies": {
12 | "@ohos/hypium": "1.0.19",
13 | "@ohos/hamock": "1.0.0"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/omni_component/.gitignore:
--------------------------------------------------------------------------------
1 | /node_modules
2 | /oh_modules
3 | /.preview
4 | /build
5 | /.cxx
6 | /.test
--------------------------------------------------------------------------------
/omni_component/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # 版本记录
2 |
3 | ## 1.0.1
4 | * 修复若干已知问题。
5 |
6 | ## 1.0.0
7 | * 发布1.0.0初版。
--------------------------------------------------------------------------------
/omni_component/build-profile.json5:
--------------------------------------------------------------------------------
1 | {
2 | "apiType": "stageMode",
3 | "buildOption": {
4 | },
5 | "buildOptionSet": [
6 | {
7 | "name": "release",
8 | "arkOptions": {
9 | "obfuscation": {
10 | "ruleOptions": {
11 | "enable": false,
12 | "files": [
13 | "./obfuscation-rules.txt"
14 | ]
15 | },
16 | "consumerFiles": [
17 | "./consumer-rules.txt"
18 | ]
19 | }
20 | },
21 | },
22 | ],
23 | "targets": [
24 | {
25 | "name": "default"
26 | },
27 | {
28 | "name": "ohosTest"
29 | }
30 | ]
31 | }
32 |
--------------------------------------------------------------------------------
/omni_component/consumer-rules.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuba/omni-ui/35590dedca468fe76b1dd1eca21dc649daf35fad/omni_component/consumer-rules.txt
--------------------------------------------------------------------------------
/omni_component/hvigorfile.ts:
--------------------------------------------------------------------------------
1 | import { harTasks } from '@ohos/hvigor-ohos-plugin';
2 |
3 | export default {
4 | system: harTasks, /* Built-in plugin of Hvigor. It cannot be modified. */
5 | plugins:[] /* Custom plugin to extend the functionality of Hvigor. */
6 | }
7 |
--------------------------------------------------------------------------------
/omni_component/obfuscation-rules.txt:
--------------------------------------------------------------------------------
1 | # Define project specific obfuscation rules here.
2 | # You can include the obfuscation configuration files in the current module's build-profile.json5.
3 | #
4 | # For more details, see
5 | # https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/source-obfuscation-V5
6 |
7 | # Obfuscation options:
8 | # -disable-obfuscation: disable all obfuscations
9 | # -enable-property-obfuscation: obfuscate the property names
10 | # -enable-toplevel-obfuscation: obfuscate the names in the global scope
11 | # -compact: remove unnecessary blank spaces and all line feeds
12 | # -remove-log: remove all console.* statements
13 | # -print-namecache: print the name cache that contains the mapping from the old names to new names
14 | # -apply-namecache: reuse the given cache file
15 |
16 | # Keep options:
17 | # -keep-property-name: specifies property names that you want to keep
18 | # -keep-global-name: specifies names that you want to keep in the global scope
19 |
20 | -enable-property-obfuscation
21 | -enable-toplevel-obfuscation
22 | -enable-filename-obfuscation
23 | -enable-export-obfuscation
--------------------------------------------------------------------------------
/omni_component/oh-package.json5:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@wuba58/omni-ui",
3 | "version": "1.0.1",
4 | "description": "开箱即用、高扩展性、丰富高效的鸿蒙开源组件库。",
5 | "keywords": [
6 | "鸿蒙UI库",
7 | "组件库",
8 | "UI组件库",
9 | "HarmonyUI",
10 | "富文本",
11 | "引导",
12 | "图表"
13 | ],
14 | "main": "Index.ets",
15 | "author": "wuba58",
16 | "license": "Apache-2.0",
17 | "dependencies": {
18 | "class-transformer": "^0.5.1",
19 | "@ohos/htmlparser2": "^1.0.2"
20 | },
21 | "type": "module",
22 | "repository": "https://github.com/wuba/omni-ui",
23 | "homepage": "https://wuba.github.io/omni-ui"
24 | }
--------------------------------------------------------------------------------
/omni_component/src/main/ets/OmniComponent.ets:
--------------------------------------------------------------------------------
1 | import { window } from "@kit.ArkUI";
2 | import immersionBar from "./utils/ImmersionBar";
3 |
4 | export class OmniComponent{
5 | static init(window:window.Window){
6 | immersionBar.init(window)
7 | }
8 | }
--------------------------------------------------------------------------------
/omni_component/src/main/ets/components/MainPage.ets:
--------------------------------------------------------------------------------
1 | @Component
2 | export struct MainPage {
3 | @State message: string = 'Hello World';
4 |
5 | build() {
6 | Row() {
7 | Column() {
8 | Text(this.message)
9 | .fontSize(50)
10 | .fontWeight(FontWeight.Bold)
11 | }
12 | .width('100%')
13 | }
14 | .height('100%')
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/omni_component/src/main/ets/components/autolinegrid/OmniAutoLineGrid.ets:
--------------------------------------------------------------------------------
1 | import { OmniTheme, OmniThemeStyle } from "../../theme/OmniTheme"
2 | import { AutoLineWrapLayout } from "./AutoLineWrapLayout"
3 | import { LineWrapLayout } from "./LineWrapLayout"
4 |
5 | @Component
6 | export struct OmniAutoLineGrid {
7 | @StorageLink(OmniTheme.KEY)
8 | private baseStyle: OmniThemeStyle = OmniTheme.getDefaultStyle()
9 | @Prop items: PairItemInfo[]
10 | @Prop titleStyle: TextStyle = { fontSize: this.baseStyle.fontSizeLg, fontColor: '#979B9E' }
11 | @Prop contentStyle: TextStyle = { fontSize: this.baseStyle.fontSizeLg, fontColor: '#0B0F12' }
12 | @Prop rightTextStyle: TextStyle = { fontSize: this.baseStyle.fontSizeLg, fontColor: '#517a99' }
13 | @BuilderParam rightPartBuilder?: VoidCallback | undefined | null
14 | onRightAreaClick?: (event: ClickEvent) => void
15 |
16 | build() {
17 | Stack({ alignContent: Alignment.Top }) {
18 | //内容布局
19 | Column() {
20 | AutoLineWrapLayout({ lineGap: 10, lineMaxNum: 2 }) {
21 | ForEach(this.items, (item: PairItemInfo) => {
22 | LineWrapLayout({ gap: 10, singleLine: item.singleLine, hasRightPart: item.hasRightPart ?? false }) {
23 | // left part
24 | Text(item.title)
25 | .fontSize(this.titleStyle.fontSize)
26 | .fontColor(this.titleStyle.fontColor)
27 | Text(item.content)
28 | .fontSize(this.contentStyle.fontSize)
29 | .fontColor(this.contentStyle.fontColor)
30 | .maxLines(1)
31 | .textOverflow({ overflow: TextOverflow.Ellipsis })
32 |
33 | // right part
34 | if (item.singleLine && (item.hasRightPart ?? false)) {
35 | if (this.rightPartBuilder) {
36 | this.rightPartBuilder()
37 | } else {
38 | Row() {
39 | Text(item.rightText)
40 | .fontSize(this.rightTextStyle.fontSize)
41 | .fontColor(this.rightTextStyle.fontColor)
42 |
43 | if (item.rightIcon) {
44 | Image(item.rightIcon)
45 | .size(item.rightIconSize ?? { width: 12, height: 12 })
46 | }
47 | }.onClick((event) => {
48 | if (this.onRightAreaClick) {
49 | this.onRightAreaClick(event)
50 | }
51 | })
52 | }
53 | }
54 | }
55 | })
56 | }
57 | }.width('100%')
58 | }
59 | }
60 | }
61 |
62 | export interface PairItemInfo {
63 | title: string
64 | content: string
65 | rightText?: string
66 | rightIcon?: PixelMap | ResourceStr | DrawableDescriptor
67 | rightIconSize?: SizeOptions
68 | singleLine: boolean
69 | hasRightPart?: boolean
70 | }
71 |
72 | export interface TextStyle {
73 | fontSize?: string | number | Resource
74 | fontColor?: ResourceColor
75 | }
--------------------------------------------------------------------------------
/omni_component/src/main/ets/components/chart/OmniChart.ets:
--------------------------------------------------------------------------------
1 | import { InterfaceObj, OptionInterface } from './utils/chartInterface'
2 | import { Tooltip, globalBuilder } from './Tooltip'
3 | import { Options } from './Options'
4 | import { DrawBaseViewModel } from './utils/DrawBaseViewModel'
5 |
6 | type ChartUnionData = object | number | string
7 |
8 | @Component
9 | export struct OmniChart {
10 | private settings: RenderingContextSettings = new RenderingContextSettings(true)
11 | private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)
12 | drawViewModel: DrawBaseViewModel | null = null;
13 | click: Function = (event: ClickEvent, args: InterfaceObj) => {};
14 | tooltipClick: Function = () => {};
15 | @Link @Watch('onCountUpdated') options: OptionInterface;
16 | @Link renderType: string
17 | @State isTooltipShow: boolean = false
18 | @State tooltipInfo: InterfaceObj = {}
19 | @BuilderParam customTooltip: (tooltipInfo: InterfaceObj) => void = globalBuilder; // 自定义组件
20 |
21 | onCountUpdated(options: Options): void {
22 | this.isTooltipShow = false
23 | this.drawViewModel && this.drawViewModel.draw(this.context, this.options, this.renderType)
24 | }
25 |
26 | updateTooltipInfo (flag: boolean, event: ClickEvent, pos?: InterfaceObj, title?: string, arr?: [], tooltipInfo: InterfaceObj = {}) {
27 | if (!tooltipInfo.show) {
28 | this.isTooltipShow = false
29 | return;
30 | }
31 | this.isTooltipShow = flag
32 | if (tooltipInfo.type !== 'default') {
33 | this.tooltipClick && this.tooltipClick(event, flag ? { title, pos, data: arr } : {})
34 | }
35 | if (tooltipInfo.type !== 'default') return;
36 | if (this.isTooltipShow) {
37 | this.tooltipInfo = {
38 | pos,
39 | title,
40 | data: arr
41 | }
42 | const keys = Object.keys(tooltipInfo)
43 | keys.forEach(item => {
44 | this.tooltipInfo[item] = tooltipInfo[item]
45 | })
46 | }
47 | }
48 |
49 | build() {
50 | Column () {
51 | Canvas(this.context)
52 | .width('100%')
53 | .height('100%')
54 | .onReady(() => {
55 | this.drawViewModel && this.drawViewModel.draw(this.context, this.options, this.renderType)
56 | })
57 | .onClick((event) => {
58 | if (this.drawViewModel) {
59 | this.drawViewModel.bindEvent(event, (flag: boolean, event: ClickEvent, pos: InterfaceObj = {}, title: string = '', arr: [] = [], tooltipInfo: InterfaceObj = {}) => {
60 | this.click && this.click(event, flag ? {
61 | title,
62 | data: arr
63 | } : {})
64 | this.updateTooltipInfo(flag, event, pos, title, arr, tooltipInfo)
65 | })
66 | }
67 | })
68 |
69 | if (this.isTooltipShow) {
70 | Tooltip({
71 | tooltipInfo: $tooltipInfo,
72 | customTooltip: this.customTooltip
73 | })
74 | }
75 | }
76 | .width('100%')
77 | .height('100%')
78 | .onDisAppear(() => {
79 | this.drawViewModel && this.drawViewModel.clear()
80 | })
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/omni_component/src/main/ets/components/chart/OmniLineChart.ets:
--------------------------------------------------------------------------------
1 | import { OmniChart } from './OmniChart'
2 | import { Options } from './Options'
3 | import { globalBuilder } from './Tooltip'
4 | import { InterfaceObj, OptionInterface } from './utils/chartInterface'
5 | import { DrawBaseViewModel } from './utils/DrawBaseViewModel'
6 | import { DrawLineViewModel, LineDataType } from './utils/DrawLineViewModel'
7 |
8 | @Component
9 | export struct OmniLineChart {
10 | private drawViewModel?: DrawBaseViewModel
11 | @Prop @Watch('onCountUpdated') options: Options;
12 | @State chartOption: OptionInterface = {};
13 | @State renderType: string = 'init'
14 | private click: Function = (event: InterfaceObj, params: InterfaceObj) => {
15 | }
16 | private tooltipClick: Function = (event: InterfaceObj, params: InterfaceObj) => {
17 | }
18 | @BuilderParam customTooltip: (tooltipInfo: InterfaceObj) => void = globalBuilder
19 |
20 | onCountUpdated(): void {
21 | this.renderType = 'update'
22 | this.chartOption = this.options.options
23 | }
24 |
25 | aboutToAppear() {
26 | this.chartOption = this.options.options
27 | this.drawViewModel = new DrawLineViewModel()
28 | }
29 |
30 | build() {
31 | OmniChart({
32 | options: $chartOption,
33 | drawViewModel: this.drawViewModel,
34 | renderType: this.renderType,
35 | customTooltip: this.customTooltip,
36 | click: (event: InterfaceObj, params: InterfaceObj) => {
37 | this.click(event, params)
38 | },
39 | tooltipClick: (event: InterfaceObj, params: InterfaceObj) => {
40 | this.tooltipClick(event, params)
41 | }
42 | })
43 | }
44 | }
45 |
46 |
--------------------------------------------------------------------------------
/omni_component/src/main/ets/components/chart/OmniProgressBarChart.ets:
--------------------------------------------------------------------------------
1 | import { OmniChart } from './OmniChart'
2 | import { Options } from './Options'
3 | import { globalBuilder } from './Tooltip'
4 | import { InterfaceObj, OptionInterface } from '../chart/utils/chartInterface'
5 | import { DrawBaseViewModel } from '../chart/utils/DrawBaseViewModel'
6 | import { DrawVerBarViewModel } from './utils/DrawVerBarViewModel'
7 | import { DrawHorViewModel } from './utils/DrawHorViewModel'
8 |
9 | // 柱状图样式
10 | export enum BarChartStyle {
11 | //纵向
12 | vertical,
13 |
14 | //横向
15 | horizontal,
16 | }
17 |
18 | @Component
19 | export struct OmniProgressBarChart {
20 | private drawViewModel?: DrawBaseViewModel
21 | @Prop @Watch('onCountUpdated') options: Options;
22 | @State chartOption: OptionInterface = {};
23 | @State renderType: string = 'init'
24 | // 柱状图的样式
25 | @State barChartStyle: BarChartStyle = BarChartStyle.vertical;
26 | private click: Function = (event: InterfaceObj, params: InterfaceObj) => {
27 | }
28 | private tooltipClick: Function = (event: InterfaceObj, params: InterfaceObj) => {
29 | }
30 | @BuilderParam customTooltip: (tooltipInfo: InterfaceObj) => void = globalBuilder
31 |
32 | onCountUpdated(options: Options): void {
33 | this.renderType = 'update'
34 | this.chartOption = this.options.options
35 | }
36 |
37 | aboutToAppear() {
38 | this.chartOption = this.options.options
39 | if (this.barChartStyle === BarChartStyle.vertical) {
40 | this.drawViewModel = new DrawVerBarViewModel()
41 | } else {
42 | this.drawViewModel = new DrawHorViewModel()
43 | }
44 | }
45 |
46 | build() {
47 | OmniChart({
48 | options: $chartOption,
49 | drawViewModel: this.drawViewModel,
50 | customTooltip: this.customTooltip,
51 | renderType: this.renderType,
52 | click: (event: InterfaceObj, params: InterfaceObj) => {
53 | this.click(event, params)
54 | },
55 | tooltipClick: (event: InterfaceObj, params: InterfaceObj) => {
56 | this.tooltipClick(event, params)
57 | }
58 | })
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/omni_component/src/main/ets/components/chart/OmniRadarChart.ets:
--------------------------------------------------------------------------------
1 | import { OmniChart } from './OmniChart'
2 | import { Options } from './Options'
3 | import { InterfaceObj, OptionInterface } from './utils/chartInterface'
4 | import { globalBuilder } from './Tooltip'
5 | import { DrawBaseViewModel } from './utils/DrawBaseViewModel'
6 | import { DrawRadarViewModel, RadarDataType } from './utils/DrawRadarViewModel'
7 |
8 | @Component
9 | export struct OmniRadarChart {
10 | private drawViewModel?: DrawBaseViewModel
11 | @Prop @Watch('onCountUpdated') options: Options;
12 | @State chartOption: OptionInterface = {};
13 | @State renderType: string = 'init'
14 | private click: Function = (event: InterfaceObj, params: InterfaceObj) => {
15 | }
16 | private tooltipClick: Function = (event: InterfaceObj, params: InterfaceObj) => {
17 | }
18 | @BuilderParam customTooltip: (tooltipInfo: InterfaceObj) => void = globalBuilder
19 |
20 | onCountUpdated(): void {
21 | this.chartOption = this.options.options
22 | }
23 |
24 | aboutToAppear() {
25 | this.onCountUpdated()
26 | this.drawViewModel = new DrawRadarViewModel()
27 | }
28 |
29 | build() {
30 | OmniChart({
31 | options: $chartOption,
32 | drawViewModel: this.drawViewModel,
33 | renderType: this.renderType,
34 | customTooltip: this.customTooltip,
35 | click: (event: InterfaceObj, params: InterfaceObj) => {
36 | this.click(event, params)
37 | },
38 | tooltipClick: (event: InterfaceObj, params: InterfaceObj) => {
39 | this.tooltipClick(event, params)
40 | }
41 | })
42 | }
43 | }
44 |
45 |
--------------------------------------------------------------------------------
/omni_component/src/main/ets/components/chart/Options.ets:
--------------------------------------------------------------------------------
1 | import { InterfaceObj, LegendInterface, TooltipInterface, SeriesInterface, AxisInterface, RadarInterface, OptionInterface } from './utils/chartInterface'
2 | import { xAxisOpt, yAxisOpt, tooltip, legend, legendTextStyle, radar } from './utils/defaultOption'
3 | import { deepCopy, assign } from './utils/index'
4 |
5 | export class Options {
6 | options: OptionInterface = {
7 | color: ['#296DFF', '#ff5495fd', '#ff1acffd', '#ff72e4fd', '#7B72F7', '#F85758', '#FFBF29', '#D1E9F9', '#F5FAFC', '#5A657A'],
8 | title: {},
9 | legend: deepCopy(legend),
10 | tooltip: deepCopy(tooltip),
11 | radar: deepCopy(radar),
12 | xAxis: deepCopy(xAxisOpt),
13 | yAxis: deepCopy(yAxisOpt),
14 | series: []
15 | }
16 | cPaddingT: number = 30;
17 | cPaddingB: number = 30;
18 | cPaddingL: number = 30;
19 | cPaddingR: number = 20;
20 | color: Array = [];
21 | title: InterfaceObj = {};
22 | legend: LegendInterface = {};
23 | tooltip: TooltipInterface = {};
24 | radar: RadarInterface = {};
25 | xAxis: AxisInterface = {};
26 | yAxis: AxisInterface | AxisInterface[] = {};
27 | series: Array> = [];
28 |
29 | constructor(options: OptionInterface) {
30 | this.setVal(options)
31 | }
32 |
33 | setVal (options: OptionInterface) {
34 | const oldOptions: OptionInterface = deepCopy(this.options)
35 | const keys = ['cPaddingT', 'cPaddingB', 'cPaddingL', 'cPaddingR', 'color', 'title', 'legend', 'xAxis', 'yAxis', 'tooltip', 'radar', 'dataZoom', 'series']
36 | for (let i = 0; i < keys.length; i++) {
37 | const item = keys[i]
38 | if (options[item] === undefined) continue
39 | switch (item) {
40 | case 'tooltip':
41 | oldOptions.tooltip = options[item]
42 | break
43 | case 'title':
44 | oldOptions.title = assign(oldOptions.title, options[item])
45 | break
46 | case 'color':
47 | oldOptions.color = options[item]
48 | break
49 | case 'legend':
50 | oldOptions.legend = assign(oldOptions.legend, options[item])
51 | break
52 | case 'xAxis':
53 | oldOptions.xAxis = assign(oldOptions.xAxis, options[item])
54 | break
55 | case 'yAxis':
56 | oldOptions.yAxis = assign(oldOptions.yAxis, options[item])
57 | break
58 | case 'radar':
59 | oldOptions.radar = assign(oldOptions.radar, options[item])
60 | break
61 | case 'series':
62 | const seriesData: SeriesInterface[] | undefined = options[item]
63 | if (oldOptions.series && seriesData) {
64 | if (oldOptions.series.length === seriesData.length) {
65 | oldOptions.series = oldOptions.series.map((item: SeriesInterface, index): SeriesInterface => {
66 | item = assign(item, seriesData[index])
67 | return item
68 | })
69 | } else {
70 | oldOptions.series = options[item]
71 | }
72 | } else {
73 | oldOptions.series = options[item]
74 | }
75 | break
76 | }
77 | }
78 | this.options = oldOptions
79 | }
80 | }
--------------------------------------------------------------------------------
/omni_component/src/main/ets/components/chart/Tooltip.ets:
--------------------------------------------------------------------------------
1 | import { InterfaceObj } from './utils/chartInterface'
2 | @Builder
3 | function globalBuilder($$: InterfaceObj) {
4 | Column() {
5 | if($$.tooltipInfo.title) {
6 | Text($$.tooltipInfo.title)
7 | .fancy($$.tooltipInfo)
8 | .margin({
9 | bottom: 8
10 | })
11 | }
12 | ForEach($$.tooltipInfo.data, (item: InterfaceObj, index) => {
13 | Text(item.name + ':' + item.num)
14 | .fancy($$.tooltipInfo)
15 | })
16 | }
17 | .alignItems(HorizontalAlign.Start)
18 | .padding($$.tooltipInfo.padding)
19 | .backgroundColor($$.tooltipInfo.backgroundColor)
20 | .borderColor($$.tooltipInfo.borderColor)
21 | .borderWidth($$.tooltipInfo.borderWidth)
22 | .borderRadius(10)
23 | }
24 |
25 | @Extend(Text) function fancy (tooltipInfo: InterfaceObj) {
26 | .fontSize(tooltipInfo.textStyle.fontSize || 14)
27 | .fontColor(tooltipInfo.textStyle.color || '#fff')
28 | .fontWeight(tooltipInfo.textStyle.fontWeight || 'normal')
29 | .fontFamily(tooltipInfo.textStyle.fontFamily ||'sans-serif')
30 | }
31 |
32 | export {
33 | globalBuilder
34 | }
35 |
36 | @Component
37 | export struct Tooltip {
38 | @Link @Watch('onTooltipInfoUpdated') tooltipInfo: InterfaceObj;
39 | @State x: number = -1000;
40 | @State y: number = -1000;
41 | // 自定义提示组件
42 | @BuilderParam customTooltip: (tooltipInfo: InterfaceObj) => void = globalBuilder;
43 |
44 | onTooltipInfoUpdated (): void {
45 | const pos: InterfaceObj = this.tooltipInfo.pos
46 | const x: number = pos.x
47 | if (x + 40 !== this.x) {
48 | this.x = -10000
49 | this.y = -10000
50 | }
51 | }
52 | getPos (rect: InterfaceObj) {
53 | const pos: InterfaceObj = this.tooltipInfo.pos
54 | const W: number = pos.W
55 | const H: number = pos.H
56 | const x: number = pos.x
57 | const y: number = pos.y
58 | const width: number = rect.width
59 | const height: number = rect.height
60 | if (x + 40 + width > W - 10) {
61 | this.x = Math.max(x - width + 20, 10)
62 | } else {
63 | this.x = x + 40
64 | }
65 | if (y !== undefined) {
66 | if (y + 40 + height > H - 10) {
67 | this.y = y - height + 20
68 | } else {
69 | this.y = y
70 | }
71 | } else {
72 | this.y = H / 2 - height / 2
73 | }
74 | }
75 | build() {
76 | Column () {
77 | this.customTooltip({
78 | tooltipInfo: this.tooltipInfo
79 | })
80 | }
81 | .alignItems(HorizontalAlign.Start)
82 | .position({
83 | x: this.x,
84 | y: this.y
85 | })
86 | .onAreaChange((oldValue: Area, newValue: Area) => {
87 | this.getPos(newValue)
88 | })
89 | }
90 | }
--------------------------------------------------------------------------------
/omni_component/src/main/ets/components/dialog/OmniDialog.ets:
--------------------------------------------------------------------------------
1 | import { ComponentContent, PromptAction } from "@kit.ArkUI"
2 | import { buildDialog } from "./OmniDialogBuilder"
3 | import { OmniDialogArgs, OmniDialogParams } from "./OmniDialogConstant"
4 |
5 | export function generateId() {
6 | return Math.random().toString(36)
7 | }
8 |
9 | export class OmniDialogManager {
10 | private static dialogMap: Map = new Map();
11 |
12 | private constructor() {
13 | }
14 |
15 | public static put(dialog: OmniDialog): string {
16 | const key = generateId()
17 | OmniDialogManager.dialogMap.set(key, dialog);
18 | return key
19 | }
20 |
21 | public static dismiss(key: string) {
22 | OmniDialogManager.dialogMap.get(key)?.dismiss();
23 | }
24 | }
25 |
26 | export class OmniDialogController {
27 | private key: string
28 |
29 | constructor(key: string) {
30 | this.key = key;
31 | }
32 |
33 | public dismiss() {
34 | OmniDialogManager.dismiss(this.key)
35 | }
36 | }
37 |
38 | export class OmniDialog {
39 | private uiContext: UIContext
40 | private promptAction: PromptAction
41 | private compContent?: ComponentContent
42 |
43 | constructor(uiContext: UIContext) {
44 | this.uiContext = uiContext
45 | this.promptAction = uiContext.getPromptAction()
46 | }
47 |
48 | public dismiss() {
49 | this.promptAction.closeCustomDialog(this.compContent).then(() => {
50 | this.compContent?.dispose()
51 | })
52 | }
53 |
54 | public show(args: OmniDialogArgs) {
55 | let params = new OmniDialogParams(new OmniDialogController(OmniDialogManager.put(this)), args)
56 | this.compContent = new ComponentContent(this.uiContext, wrapBuilder(buildDialog), params)
57 |
58 | this.promptAction.openCustomDialog(this.compContent, {
59 | showInSubWindow: args.showInSubWindow ?? false,
60 | autoCancel: args.autoCancel ?? true,
61 | alignment: args.alignment ?? DialogAlignment.Center,
62 | isModal: args.isModal ?? true,
63 | offset: args.offset ?? { dx: 0, dy: 0 },
64 | transition: args.transition,
65 | maskColor: args.maskColor,
66 | onDidAppear: args.onDidAppear,
67 | onDidDisappear: args.onDidDisappear
68 | })
69 | }
70 | }
--------------------------------------------------------------------------------
/omni_component/src/main/ets/components/dialog/OmniDialogConstant.ets:
--------------------------------------------------------------------------------
1 | import { OmniDialogController } from "./OmniDialog"
2 |
3 | export interface OmniDialogTextArgs {
4 | value: string
5 | style?: OmniDialogFontStyle
6 | padding?: Padding | Length | LocalizedPadding
7 | }
8 |
9 | export interface OmniDialogFontStyle {
10 | font?: Font
11 | color?: ResourceColor
12 | }
13 |
14 | export interface OmniDialogButtonArgs {
15 | value: string
16 | fontStyle?: OmniDialogFontStyle
17 | padding?: Padding | Length | LocalizedPadding
18 | backgroundColor?: ResourceColor
19 | border?: BorderOptions
20 | }
21 |
22 | export interface OmniDialogArgs {
23 | titleBuilder?: () => void
24 | contentBuilder?: () => void
25 | buttonBuilder?: (controller?: OmniDialogController) => void
26 | titleArgs?: OmniDialogTextArgs
27 | contentArgs?: OmniDialogTextArgs
28 | leftButtonArgs?: OmniDialogButtonArgs
29 | rightButtonArgs?: OmniDialogButtonArgs
30 | dialogBorder?: BorderOptions
31 | dialogBgColor?: ResourceColor
32 | dialogDivider?: OmniDialogDividerOptions
33 | isModal?: boolean
34 | showInSubWindow?: boolean
35 | autoCancel?: boolean
36 | alignment?: DialogAlignment
37 | offset?: Offset
38 | transition?: TransitionEffect
39 | maskColor?: ResourceColor
40 | onDidAppear?: VoidCallback
41 | onDidDisappear?: VoidCallback
42 | onLeftButtonClick?: (event: ClickEvent) => void
43 | onRightButtonClick?: (event: ClickEvent) => void
44 | }
45 |
46 | export class OmniDialogParams {
47 | controller: OmniDialogController
48 | titleBuilder?: () => void
49 | contentBuilder?: () => void
50 | buttonBuilder?: (controller?: OmniDialogController) => void
51 | titleArgs?: OmniDialogTextArgs
52 | contentArgs?: OmniDialogTextArgs
53 | leftButtonArgs?: OmniDialogButtonArgs
54 | rightButtonArgs?: OmniDialogButtonArgs
55 | dialogBorder?: BorderOptions
56 | dialogBgColor?: ResourceColor
57 | dialogDivider?: OmniDialogDividerOptions
58 | onLeftButtonClick?: (event: ClickEvent) => void
59 | onRightButtonClick?: (event: ClickEvent) => void
60 |
61 | constructor(controller: OmniDialogController, args: OmniDialogArgs) {
62 | this.controller = controller;
63 | this.titleBuilder = args.titleBuilder
64 | this.contentBuilder = args.contentBuilder
65 | this.buttonBuilder = args.buttonBuilder
66 | this.titleArgs = args.titleArgs
67 | this.contentArgs = args.contentArgs
68 | this.leftButtonArgs = args.leftButtonArgs
69 | this.rightButtonArgs = args.rightButtonArgs
70 | this.dialogBorder = args.dialogBorder
71 | this.dialogBgColor = args.dialogBgColor
72 | this.dialogDivider = args.dialogDivider
73 | this.onLeftButtonClick = args.onLeftButtonClick
74 | this.onRightButtonClick = args.onRightButtonClick
75 | }
76 | }
77 |
78 | export interface OmniDialogDividerOptions {
79 | strokeWidth?: number | string
80 | color?: ResourceColor
81 | margin?: Margin | Length | LocalizedMargin
82 | }
--------------------------------------------------------------------------------
/omni_component/src/main/ets/components/filterbar/OmniFilterComponentRegistry.ets:
--------------------------------------------------------------------------------
1 | import { OmniFilterItemBean } from "./bean/OmniFilterItemBean";
2 |
3 | //确认动作
4 | export declare type OnConfirmAction = () => void
5 | //关闭动作
6 | export declare type OnCloseAction = () => void
7 |
8 | export class OmniFilterComponentRegistry {
9 | // 下拉类型组件池
10 | private dropSlideTypeBuilderPool: Map> = new Map();
11 |
12 | // 右滑类型组件池
13 | private rightSlideTypeBuilderPool: Map> = new Map();
14 |
15 | // 初始化方法,用于注册默认的组件
16 | constructor() {
17 | }
18 |
19 | // 注册下拉类型的组件
20 | registerDropSlideComponent(type: string, builder: WrappedBuilder<[OmniFilterItemBean, OnConfirmAction, OnCloseAction]>) {
21 | this.dropSlideTypeBuilderPool.set(type, builder);
22 | }
23 |
24 | // 注册右滑类型的组件
25 | registerRightSlideComponent(type: string, builder: WrappedBuilder<[OmniFilterItemBean, OnConfirmAction, OnCloseAction]>) {
26 | this.rightSlideTypeBuilderPool.set(type, builder);
27 | }
28 |
29 | // 获取下拉类型的组件构建器
30 | getDropSlideComponentBuilder(type: string): WrappedBuilder<[OmniFilterItemBean, OnConfirmAction, OnCloseAction]> | undefined {
31 | return this.dropSlideTypeBuilderPool.get(type);
32 | }
33 |
34 | // 获取右滑类型的组件构建器
35 | getRightSlideComponentBuilder(type: string): WrappedBuilder<[OmniFilterItemBean, OnConfirmAction, OnCloseAction]> | undefined {
36 | return this.rightSlideTypeBuilderPool.get(type);
37 | }
38 |
39 | // 检查是否存在某个下拉类型的组件
40 | hasDropSlideType(type: string): boolean {
41 | return this.dropSlideTypeBuilderPool.has(type);
42 | }
43 |
44 | // 检查是否存在某个右滑类型的组件
45 | hasRightSlideType(type: string): boolean {
46 | return this.rightSlideTypeBuilderPool.has(type);
47 | }
48 | }
--------------------------------------------------------------------------------
/omni_component/src/main/ets/components/filterbar/OmniFilterConstants.ets:
--------------------------------------------------------------------------------
1 | export namespace OmniFilterConstants{
2 | export declare const OMNI_FILTER_LIST_DEEP_SELECT_BG = 0xFFF8F8F8
3 | export declare const OMNI_FILTER_LIST_MIDDLE_SELECT_BG = 0xFFFFFFFF
4 | export declare const OMNI_FILTER_LIST_LIGHT_SELECT_BG = 0xFFFFFFFF
5 |
6 | export declare const OMNI_FILTER_LIST_DEEP_NORMAL_BG = 0xFFF0F0F0
7 | export declare const OMNI_FILTER_LIST_MIDDLE_NORMAL_BG = 0xFFF8F8F8
8 | export declare const OMNI_FILTER_LIST_LIGHT_NORMAL_BG = 0xFFFFFFFF
9 | }
10 |
--------------------------------------------------------------------------------
/omni_component/src/main/ets/components/filterbar/OmniFilterThemeConfig.ets:
--------------------------------------------------------------------------------
1 | import { OmniResourceColor } from "../../theme/OmniTheme"
2 |
3 | export interface OmniFilterStyle {
4 | menuStyle?: OmniFilterMenuStyle
5 | gridStyle?: OmniFilterGridStyle
6 | listStyle?: OmniFilterListStyle
7 | bottomPanelStyle?: OmniFilterBottomPanelStyle
8 | }
9 |
10 | export interface OmniFilterMenuStyle {
11 | menuTextStyle?: OmniFilterTextStyle //菜单文字常规样式
12 | menuSelectedTextStyle?: OmniFilterTextStyle //菜单文字选中样式
13 | }
14 |
15 | export interface OmniFilterListStyle {
16 | maxHeight?:number
17 | itemTextStyle?: OmniFilterTextStyle; // 列表文字常规样式
18 | itemSelectedTextStyle?: OmniFilterTextStyle; // 列表文字选中样式
19 | itemMultiSelectIconUnselected?: OmniFilterIcon //多选icon
20 | itemMultiSelectIconSelected?: OmniFilterIcon //多选icon(选中)
21 | }
22 |
23 | export interface OmniFilterGridStyle {
24 | maxHeight?:number
25 | rowCount?:number//每行个数
26 | titleTextStyle?: OmniFilterTextStyle //网格标题样式
27 | itemTextStyle?: OmniFilterTextStyle //网格文字常规样式
28 | itemSelectedTextStyle?: OmniFilterTextStyle //网格文字选中样式
29 | itemBgColor?: OmniResourceColor //item背景色
30 | itemSelectedBgColor?: OmniResourceColor //item背景色(选中)
31 | }
32 |
33 | export interface OmniFilterBottomPanelStyle {
34 | resetText?:string
35 | resetTextStyle?: OmniFilterTextStyle //重置文字样式
36 | resetIcon?: OmniFilterIcon //重置图标
37 | confirmText?:string
38 | confirmTextStyle?: OmniFilterTextStyle //确定文字样式
39 | confirmButtonColor?: OmniResourceColor //确定按钮颜色
40 | }
41 |
42 | export declare type OmniFilterIcon = PixelMap | ResourceStr | DrawableDescriptor | ImageContent
43 |
44 | export interface OmniFilterTextStyle {
45 | fontColor?: OmniResourceColor //文字颜色
46 | fontSize?: number | string | Resource //文字大小
47 | fontWeight?: number | FontWeight | string //文字粗细
48 | }
49 |
--------------------------------------------------------------------------------
/omni_component/src/main/ets/components/filterbar/bean/OmniFilterMenuItemBean.ets:
--------------------------------------------------------------------------------
1 | import { OmniFilterItemBean } from "./OmniFilterItemBean"
2 |
3 | @Observed
4 | export class OmniFilterMenuItemBean {
5 | item: OmniFilterItemBean
6 | menuTitle: string | undefined
7 | isHighLight: boolean
8 | active: boolean
9 |
10 | customTitle?:string = undefined
11 | isCustomTitleHighLight:boolean = false
12 |
13 | constructor(item: OmniFilterItemBean, menuTitle: string, isHighLight: boolean, active: boolean) {
14 | this.item = item
15 | this.menuTitle = menuTitle
16 | this.isHighLight = isHighLight
17 | this.active = active
18 | }
19 |
20 | }
21 |
22 | /**
23 | * 自定义Menu标题数据结构
24 | */
25 | export class OmniFilterCustomMenuTitle{
26 | menuTitle: string
27 | isHighLight: boolean
28 |
29 | constructor(menuTitle: string, isHighLight: boolean) {
30 | this.menuTitle = menuTitle
31 | this.isHighLight = isHighLight
32 | }
33 |
34 | }
--------------------------------------------------------------------------------
/omni_component/src/main/ets/components/filterbar/component/OmniFilterBottomPanel.ets:
--------------------------------------------------------------------------------
1 | import { OmniTheme, OmniThemeStyle } from "../../../theme/OmniTheme"
2 | import { OmniFilterStyle } from "../OmniFilterThemeConfig"
3 |
4 | @Component
5 | export struct OmniFilterBottomPanel {
6 | private static DEFAULT_RESET_TEXT = `重置`
7 | private static DEFAULT_CONFIRM_TEXT = `确定`
8 | @StorageLink(OmniTheme.KEY)
9 | baseStyle: OmniThemeStyle = OmniTheme.getDefaultStyle()
10 | @Consume filterStyle: OmniFilterStyle
11 | onResetClick?: () => void
12 | onConfirmClick?: () => void
13 |
14 | build() {
15 | Column() {
16 | Divider()
17 | .color(0xFFCCCCCC)
18 | .height(1)
19 | .width(`100%`)
20 | Row() {
21 | Column() {
22 | Image(this.filterStyle.bottomPanelStyle?.resetIcon ?? $r('app.media.icon_filter_reset'))
23 | .width(24)
24 | .height(24)
25 | Text(this.filterStyle.bottomPanelStyle?.resetText ?? OmniFilterBottomPanel.DEFAULT_RESET_TEXT)
26 | .fontColor(this.filterStyle?.bottomPanelStyle?.resetTextStyle?.fontColor ?? Color.Black)
27 | .fontWeight(this.filterStyle?.bottomPanelStyle?.resetTextStyle?.fontWeight ?? FontWeight.Medium)
28 | .fontSize(this.filterStyle?.bottomPanelStyle?.resetTextStyle?.fontSize ?? this.baseStyle.fontSizeMd)
29 | }
30 | .padding({ left: 12, right: 20 })
31 | .justifyContent(FlexAlign.Center)
32 | .alignItems(HorizontalAlign.Center)
33 | .onClick(() => {
34 | this.onResetClick?.()
35 | })
36 |
37 | Button(this.filterStyle.bottomPanelStyle?.confirmText ?? OmniFilterBottomPanel.DEFAULT_CONFIRM_TEXT,
38 | { type: ButtonType.Normal, stateEffect: true })
39 | .fontColor(this.filterStyle?.bottomPanelStyle?.confirmTextStyle?.fontColor ?? Color.White)
40 | .fontWeight(this.filterStyle?.bottomPanelStyle?.confirmTextStyle?.fontWeight ?? FontWeight.Medium)
41 | .fontSize(this.filterStyle?.bottomPanelStyle?.confirmTextStyle?.fontSize ?? this.baseStyle.fontSizeMd)
42 | .width('100%')
43 | .backgroundColor(this.filterStyle?.bottomPanelStyle?.confirmButtonColor ?? this.baseStyle.primary)
44 | .borderRadius(8)
45 | .layoutWeight(1)
46 | .onClick(() => {
47 | this.onConfirmClick?.()
48 | })
49 | }
50 | .padding({
51 | left: 10,
52 | top: 10,
53 | right: 10,
54 | bottom: 10
55 | })
56 | .alignItems(VerticalAlign.Center)
57 | }
58 | .backgroundColor(Color.White)
59 | .width('100%')
60 | }
61 | }
--------------------------------------------------------------------------------
/omni_component/src/main/ets/components/filterbar/component/OmniFilterGridItem.ets:
--------------------------------------------------------------------------------
1 | import { OmniFilterItemBean } from "../bean/OmniFilterItemBean"
2 | import { OmniTheme, OmniThemeStyle } from "../../../theme/OmniTheme"
3 | import { OmniFilterStyle } from "../OmniFilterThemeConfig"
4 |
5 | @Component
6 | @Preview
7 | export struct OmniFilterGridItem {
8 | private static DEFAULT_ROW_COUNT = 3//默认网格数
9 | @StorageLink(OmniTheme.KEY)
10 | baseStyle: OmniThemeStyle = OmniTheme.getDefaultStyle()
11 | @Consume filterStyle: OmniFilterStyle
12 | @Prop item: OmniFilterItemBean
13 | @Prop focusedIndex: number
14 | @Prop listIndex: number
15 | @Prop @Require componentWidth: number = 0
16 | gridItemSelect?: () => void
17 |
18 | build() {
19 | Column() {
20 | Text(`${this.item.title}`)
21 | .fontColor(this.itemFontColor())
22 | .fontSize(this.itemFontSize())
23 | .fontWeight(this.itemFontWeight())
24 | }
25 | .borderRadius(2)
26 | .justifyContent(FlexAlign.Center)
27 | .alignItems(HorizontalAlign.Center)
28 | .width(this.tagWidth())
29 | .height(34)
30 | .backgroundColor(this.tagBackgroundColor())
31 | .onClick(() => {
32 | //TODO 最大选择数量
33 | this.gridItemSelect?.()
34 | })
35 | }
36 |
37 | private tagWidth(): number {
38 | const baseWidth = this.componentWidth
39 | const rowCount = this.filterStyle.gridStyle?.rowCount ?? OmniFilterGridItem.DEFAULT_ROW_COUNT
40 | return Math.floor(
41 | (baseWidth - 40 - 12 * (rowCount - 1)) / rowCount
42 | );
43 | }
44 |
45 | private itemFontSize(): number | string | Resource {
46 | if (this.isItemFocused()) {
47 | return this.filterStyle.gridStyle?.itemSelectedTextStyle?.fontSize ?? this.baseStyle.fontSizeMd
48 | } else {
49 | return this.filterStyle.gridStyle?.itemTextStyle?.fontSize ?? this.baseStyle.fontSizeMd
50 | }
51 | }
52 |
53 | private itemFontColor(): ResourceColor {
54 | if (this.isItemFocused()) {
55 | return this.filterStyle.gridStyle?.itemSelectedTextStyle?.fontColor ?? this.baseStyle.primary
56 | } else {
57 | return this.filterStyle.gridStyle?.itemTextStyle?.fontColor ?? Color.Black
58 | }
59 | }
60 |
61 | private itemFontWeight(): number | FontWeight | string {
62 | if (this.isItemFocused()) {
63 | return this.filterStyle.gridStyle?.itemSelectedTextStyle?.fontWeight ?? FontWeight.Regular
64 | } else {
65 | return this.filterStyle.gridStyle?.itemTextStyle?.fontWeight ?? FontWeight.Regular
66 | }
67 | }
68 |
69 | private tagBackgroundColor(): ResourceColor {
70 | if (this.isItemFocused()) {
71 | return this.filterStyle.gridStyle?.itemSelectedBgColor ?? this.baseStyle.primaryColorWithOpacity(0.12)
72 | } else {
73 | return this.filterStyle.gridStyle?.itemBgColor ?? 0xFFF8F8F8
74 | }
75 | }
76 |
77 | private isItemFocused(): boolean {
78 | let isFocused = this.focusedIndex == this.listIndex;
79 | if (!isFocused && this.item.isSelected && this.item.isInLastLevel()) {
80 | isFocused = true;
81 | }
82 | return isFocused;
83 | }
84 | }
--------------------------------------------------------------------------------
/omni_component/src/main/ets/components/filterbar/component/OmniFilterMenuItem.ets:
--------------------------------------------------------------------------------
1 | import { OmniTheme, OmniThemeStyle } from "../../../theme/OmniTheme"
2 | import { OmniFilterMenuItemBean } from "../bean/OmniFilterMenuItemBean"
3 | import { OmniFilterStyle } from "../OmniFilterThemeConfig"
4 |
5 | @Component
6 | export struct OmniFilterMenuItemComponent {
7 | @ObjectLink menuItem: OmniFilterMenuItemBean
8 | @Consume filterStyle: OmniFilterStyle
9 | @StorageLink(OmniTheme.KEY)
10 | baseStyle: OmniThemeStyle = OmniTheme.getDefaultStyle()
11 |
12 | build() {
13 | Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
14 | Text(this.menuItem.menuTitle)
15 | .fontSize(this.menuFontSize())
16 | .fontColor(this.menuFontColor())
17 | .fontWeight(this.menuFontWeight())
18 | .maxLines(1)
19 | .textOverflow({ overflow: TextOverflow.Ellipsis })
20 | .ellipsisMode(EllipsisMode.END)
21 | .flexBasis('auto')
22 | Image(this.menuItem.active ? $r('app.media.icon_arrow_up') : $r('app.media.icon_arrow_down'))
23 | .width(12)
24 | .height(6)
25 | .fillColor(this.menuFontColor())
26 | .margin({ left: 4 })
27 | }
28 | .width(`100%`)
29 | .padding({ left: 10, right: 10 })
30 | }
31 |
32 | private menuFontSize(): number | string | Resource {
33 | if (this.menuItem.isHighLight || this.menuItem.active) {
34 | return this.filterStyle.menuStyle?.menuSelectedTextStyle?.fontSize ?? this.baseStyle.fontSizeLg
35 | } else {
36 | return this.filterStyle.menuStyle?.menuTextStyle?.fontSize ?? this.baseStyle.fontSizeLg
37 | }
38 | }
39 |
40 | private menuFontColor(): ResourceColor {
41 | if (this.menuItem.isHighLight || this.menuItem.active) {
42 | return this.filterStyle.menuStyle?.menuSelectedTextStyle?.fontColor ?? this.baseStyle.primary
43 | } else {
44 | return this.filterStyle.menuStyle?.menuTextStyle?.fontColor ?? Color.Black
45 | }
46 | }
47 |
48 | private menuFontWeight(): number | FontWeight | string {
49 | if (this.menuItem.isHighLight || this.menuItem.active) {
50 | return this.filterStyle.menuStyle?.menuSelectedTextStyle?.fontWeight ?? FontWeight.Regular
51 | } else {
52 | return this.filterStyle.menuStyle?.menuTextStyle?.fontWeight ?? FontWeight.Regular
53 | }
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/omni_component/src/main/ets/components/filterbar/converter/OmniFilterConverter.ets:
--------------------------------------------------------------------------------
1 | import { OmniFilterItemBean, OmniFilterShowType, OmniFilterType } from '../bean/OmniFilterItemBean';
2 | import HashMap from '@ohos.util.HashMap';
3 | import { TextUtils } from '../../../utils/TextUtils';
4 | import { OmniFilterUtil } from '../util/OmniFilterUtil';
5 |
6 | // 筛选项数据转换器接口
7 | export interface OmniFilterConverterDelegate {
8 | convertSelectedData(selectedResults: OmniFilterItemBean[]): Map;
9 | }
10 |
11 | // 默认筛选项数据转换器
12 | export class DefaultFilterConverter implements OmniFilterConverterDelegate {
13 | constructor() {
14 | }
15 |
16 | // 将选中的数据转换为 Map
17 | convertSelectedData(selectedResults: OmniFilterItemBean[]): Map {
18 | return getFilterParams(selectedResults);
19 | }
20 | }
21 |
22 | function getFilterParams(selectedResults: OmniFilterItemBean[] | null): Map {
23 | const params = new Map();
24 |
25 | if (!selectedResults) return params;
26 |
27 | for (const menuItemEntity of selectedResults) {
28 | if (menuItemEntity.showType === OmniFilterShowType.more) {
29 | //TODO 更多的结构是否区别
30 | const childParams = getFilterParams(menuItemEntity.children);
31 | childParams.forEach((value, key) => params.set(key, value));
32 | } else {
33 |
34 | // 2. 查找层级为 1、2、3 的选中项的参数
35 | const levelCount = OmniFilterUtil.getTotalLevel(menuItemEntity);
36 | if (levelCount === 1) {
37 | mergeMap(params, getCurrentSelectedFilterParams(menuItemEntity));
38 | } else if (levelCount === 2) {
39 | mergeMap(params, getCurrentSelectedFilterParams(menuItemEntity));
40 | menuItemEntity.children.forEach(firstLevelItem => {
41 | mergeMap(params, getCurrentSelectedFilterParams(firstLevelItem));
42 | });
43 | } else if (levelCount === 3) {
44 | mergeMap(params, getCurrentSelectedFilterParams(menuItemEntity));
45 | menuItemEntity.children.forEach(firstLevelItem => {
46 | mergeMap(params, getCurrentSelectedFilterParams(firstLevelItem));
47 | firstLevelItem.children.forEach(secondLevelItem => {
48 | mergeMap(params, getCurrentSelectedFilterParams(secondLevelItem));
49 | });
50 | });
51 | }
52 | }
53 | }
54 |
55 | return params;
56 | }
57 |
58 | // 获取当前选中项的筛选数据
59 | function getCurrentSelectedFilterParams(filterItem: OmniFilterItemBean): Map {
60 | const params = new Map();
61 | const parentKey = filterItem.key;
62 |
63 | const selectedEntities = filterItem.children
64 | .filter(child => child.isSelected && !TextUtils.isBlank(child.value))
65 | .map(child => child.value);
66 |
67 | const selectedParams = selectedEntities.length > 0 ? selectedEntities.join(",") : "";
68 |
69 | if (!TextUtils.isBlank(selectedParams) && !TextUtils.isBlank(parentKey)) {
70 | params.set(parentKey!, selectedParams);
71 | }
72 |
73 | return params;
74 | }
75 |
76 | // 合并 Map
77 | function mergeMap(target: Map, source: Map) {
78 | source.forEach((value, key) => target.set(key, value));
79 | }
--------------------------------------------------------------------------------
/omni_component/src/main/ets/components/gallery/OmniSummary.ets:
--------------------------------------------------------------------------------
1 | import { OmniTheme, OmniThemeStyle } from "../../theme/OmniTheme"
2 |
3 | @Component
4 | export struct OmniSummary {
5 | /**
6 | * 组件入参,必填参数
7 | */
8 | @Prop @Require config: OmniSummaryConfig
9 | /**
10 | * item的点击事件,如查看大图
11 | */
12 | onItemClick?: (index: number, items: OmniSummaryItem[]) => void
13 | @State private columnsTemplate: string = ''
14 |
15 | @StorageLink(OmniTheme.KEY)
16 | baseStyle: OmniThemeStyle = OmniTheme.getDefaultStyle()
17 |
18 | aboutToAppear(): void {
19 | for (let i = 0; i < this.config.countPerRow; i++) {
20 | this.columnsTemplate += '1fr '
21 | }
22 | this.columnsTemplate.trimEnd()
23 | }
24 |
25 | @Builder
26 | buildSummaryItem(item: OmniSummaryItem, pIndex: number) {
27 | Column() {
28 | Text(`${item.title}(${item.images.length})`)
29 | .fontSize(20)
30 | .fontColor('#1F2326')
31 | .margin({ bottom: 20 })
32 | .fontWeight(FontWeight.Bold)
33 |
34 | Grid() {
35 | ForEach(item.images, (image: string) => {
36 | GridItem() {
37 | Image(image)
38 | .width('100%')
39 | .aspectRatio(1)
40 | .objectFit(ImageFit.Cover)
41 | .draggable(false)
42 | .animation({ curve: Curve.Sharp, duration: 300 })
43 | .onClick(() => {
44 | this.onItemClick?.(pIndex, this.config.items)
45 | })
46 | }
47 | }, (item: string, index: number) => item + index)
48 | }
49 | .width('100%')
50 | .editMode(false)
51 | .columnsGap(12)
52 | .rowsGap(12)
53 | .scrollBar(BarState.Off)
54 | .supportAnimation(true)
55 | .enableScrollInteraction(true)
56 | .columnsTemplate(this.columnsTemplate)
57 | }
58 | .alignItems(HorizontalAlign.Start)
59 | .margin({ bottom: 20 })
60 | }
61 |
62 | build() {
63 | Scroll() {
64 | List() {
65 | ForEach(this.config.items, (item: OmniSummaryItem, index: number) => {
66 | ListItem() {
67 | this.buildSummaryItem(item, index)
68 | }
69 | })
70 | }.divider({
71 | strokeWidth: 15,
72 | color: '#ffffffff'
73 | })
74 | }.nestedScroll({
75 | scrollForward: NestedScrollMode.SELF_FIRST,
76 | scrollBackward: NestedScrollMode.SELF_FIRST
77 | })
78 | }
79 | }
80 |
81 | interface OmniSummaryConfig {
82 | items: OmniSummaryItem[],
83 | countPerRow: number
84 | }
85 |
86 | export interface OmniSummaryItem {
87 | title: string
88 | images: string[]
89 | }
--------------------------------------------------------------------------------
/omni_component/src/main/ets/components/guide/core/OmniGuideBuilder.ets:
--------------------------------------------------------------------------------
1 | import { GuidePage } from '../model/GuidePage';
2 | import { OnGuideChangedListener } from '../interface/OnGuideChangedListener';
3 | import { OnPageChangedListener } from '../interface/OnPageChangedListener';
4 |
5 | export class OmniGuideBuilder {
6 | // 标签名称
7 | label: string = '';
8 | // 是否总显示引导页
9 | alwaysShowGuide: boolean = false;
10 | // 设置引导页显示次数
11 | showCounts: number = 1;
12 | // 引导页页面集合
13 | guidePages: GuidePage[] = new Array();
14 | // 页面显示状态变化监听
15 | visibleStateChangeListener: OnGuideChangedListener | null = null;
16 | // 页面页数切换监听
17 | pageChangedListener: OnPageChangedListener | null = null;
18 |
19 | /**
20 | * 设置引导页名称,必须设置,用于存储引导页显示次数
21 | * @param label 引导页标签名称
22 | * @returns 引导页组件的配置项
23 | */
24 | public setLabel(label: string): OmniGuideBuilder {
25 | this.label = label;
26 | return this;
27 | }
28 |
29 | /**
30 | * 设置引导页的显示次数
31 | * @param count 显示次数
32 | * @returns 引导页组件的配置项
33 | */
34 | public setShowCounts(count: number): OmniGuideBuilder {
35 | this.showCounts = count;
36 | return this;
37 | }
38 |
39 | /**
40 | * 是否总是显示引导页,即是否无限次的显示
41 | * 默认为false,如果设置为true,{@Link HighLightGuideBuilder#setShowCounts}将失效
42 | * @param isAlways 永久显示
43 | * @returns 引导页组件的配置项
44 | */
45 | public alwaysShow(isAlways: boolean): OmniGuideBuilder {
46 | this.alwaysShowGuide = isAlways;
47 | return this;
48 | }
49 |
50 | /**
51 | * 添加引导页
52 | * @param page 引导页对象
53 | * @returns 引导页组件的配置项
54 | */
55 | public addGuidePage(page: GuidePage): OmniGuideBuilder {
56 | this.guidePages.push(page);
57 | return this;
58 | }
59 |
60 | /**
61 | * 添加引导页组件的可见状态监听
62 | * @param listener 状态监听器
63 | * @returns 引导页组件的配置项
64 | */
65 | public setOnGuideChangedListener(listener: OnGuideChangedListener | null): OmniGuideBuilder {
66 | this.visibleStateChangeListener = listener;
67 | return this;
68 | }
69 |
70 | /**
71 | * 添加页面切换监听器
72 | * @param listener 页面切换监听器
73 | * @returns 引导页组件的配置项
74 | */
75 | public setOnPageChangedListener(listener: OnPageChangedListener | null): OmniGuideBuilder {
76 | this.pageChangedListener = listener;
77 | return this;
78 | }
79 | }
--------------------------------------------------------------------------------
/omni_component/src/main/ets/components/guide/interface/HighLight.ets:
--------------------------------------------------------------------------------
1 | import { HighLightOptions } from '../model/HighLightOptions';
2 | import { RectF } from '../model/RectF';
3 | import { HighLightShape } from '../model/HighLightShape';
4 |
5 | export default interface HighLight {
6 |
7 | /**
8 | * 获取高亮区域的类型
9 | * @returns 高亮区域的类型:组件id或指定区域
10 | */
11 | isComponentHighLight(): boolean | string;
12 |
13 | /**
14 | * 获取图形shape类型
15 | * @returns shape类型
16 | */
17 | getShape(): HighLightShape;
18 |
19 | /**
20 | * 获取高亮图形的区域坐标,组件要求必传id,rectF区域需要为相对于父组件的相对坐标,坐标值需要转换为vp,不能直接为px
21 | * @param parentId 高亮区域为组件时,必传,父组件id:__HighLightGuideComponentContainer__ + 组件创建时的时间戳,id需要整个应用内唯一
22 | * @param componentId 高亮区域为组件时,必传,组件id需要整个应用内唯一
23 | * @returns 返回高亮区域的坐标,单位为vp
24 | */
25 | getRectF(parentId?: string, componentId?: string): RectF | null;
26 |
27 | /**
28 | * 当shape为为CIRCLE时调用此方法获取半径
29 | * @param parentId 高亮区域为组件时,必传,父组件id: __HighLightGuideComponentContainer__ + 组件创建时的时间戳,id需要整个应用内唯一
30 | * @returns 圆的半径
31 | */
32 | getRadius(parentId?: string): number;
33 |
34 | /**
35 | * 获取圆角弧度,仅当shape = HighLightShape.ROUND_RECTANGLE才调用此方法
36 | * @returns 圆角矩形的圆角弧度
37 | */
38 | getRound(): number;
39 |
40 | /**
41 | * 获取高亮区域的额外参数,可设置高亮区域的点击事件,重绘高亮区域的图形,是否强制更新组件坐标(该属性用于高亮区域为组件id时有效)
42 | * @returns 高亮区域的额外配置
43 | */
44 | getOptions(): HighLightOptions | null;
45 | }
--------------------------------------------------------------------------------
/omni_component/src/main/ets/components/guide/interface/OnClickListener.ets:
--------------------------------------------------------------------------------
1 | export interface OnClickListener {
2 |
3 | /**
4 | * 高亮区域的点击事件
5 | */
6 | onClick: () => void;
7 | }
--------------------------------------------------------------------------------
/omni_component/src/main/ets/components/guide/interface/OnGuideChangedListener.ets:
--------------------------------------------------------------------------------
1 | import { Controller } from '../core/Controller';
2 |
3 | export interface OnGuideChangedListener {
4 |
5 | /**
6 | * 当前引导页组件显示时回调
7 | * @param controller 引导页组件控制器
8 | */
9 | onShowed: (controller: Controller) => void;
10 |
11 | /**
12 | * 当前引导页组件消失时回调
13 | * @param controller 引导页组件控制器
14 | */
15 | onRemoved: (controller: Controller) => void;
16 | }
--------------------------------------------------------------------------------
/omni_component/src/main/ets/components/guide/interface/OnGuideLifeCycleListener.ets:
--------------------------------------------------------------------------------
1 | export default interface OnGuideLifeCycleListener {
2 |
3 | /**
4 | * 组件蒙版即将加载到页面上,对应onAppear回调(在创建自定义组件的新实例后,在执行build()函数之前执行)
5 | */
6 | _onGuideAppear: () => void;
7 |
8 | /**
9 | * 组件蒙版即将从页面上移除,对应onDisAppear回调(在自定义组件析构销毁之前执行)
10 | */
11 | _onGuideDisAppear: () => void;
12 |
13 | /**
14 | * 指示组件的动画是否正在运行
15 | * @param isAnimationRunning 是否有动画正在运行
16 | */
17 | _onAnimationRunning: (isAnimationRunning: boolean) => void;
18 | }
--------------------------------------------------------------------------------
/omni_component/src/main/ets/components/guide/interface/OnHighLightDrewListener.ets:
--------------------------------------------------------------------------------
1 | import { RectF } from '../model/RectF';
2 |
3 | export interface OnHighLightDrewListener {
4 |
5 | /**
6 | * 自定义高亮区域的显示图形
7 | * @param canvasContext2d 画布控制上下文
8 | * @param rectF 高亮区域
9 | */
10 | onHighLightDrew: (canvasContext2d: CanvasRenderingContext2D, rectF: RectF) => void;
11 | }
--------------------------------------------------------------------------------
/omni_component/src/main/ets/components/guide/interface/OnPageChangedListener.ets:
--------------------------------------------------------------------------------
1 | export interface OnPageChangedListener {
2 |
3 | /**
4 | * 当前显示的引导页页面的index
5 | * @param pageIndex 页面索引
6 | */
7 | onPageChanged: (pageIndex: number) => void;
8 | }
--------------------------------------------------------------------------------
/omni_component/src/main/ets/components/guide/model/BubbleIndicator.ets:
--------------------------------------------------------------------------------
1 | import { PopupPosition } from '../../popup/PopupPosition';
2 |
3 | export class BubbleIndicator {
4 | private _componentId: string = "";
5 |
6 | public get componentId(): string {
7 | return this._componentId;
8 | }
9 |
10 | private _bubblePosition: BubblePosition = BubblePosition.BOTTOM;
11 |
12 | public get popupPosition(): PopupPosition {
13 | switch (this._bubblePosition) {
14 | case BubblePosition.TOP:
15 | return PopupPosition.TOP;
16 | case BubblePosition.BOTTOM:
17 | return PopupPosition.BOTTOM;
18 | case BubblePosition.LEFT:
19 | return PopupPosition.LEFT;
20 | case BubblePosition.RIGHT:
21 | return PopupPosition.RIGHT;
22 | }
23 | }
24 |
25 | private _bubbleBean?: BubbleBean | undefined;
26 |
27 | public get bubbleBean(): BubbleBean | undefined {
28 | return this._bubbleBean;
29 | }
30 |
31 | constructor(componentId: string, bubbleBean: BubbleBean, bubblePosition?: BubblePosition) {
32 | this._componentId = componentId;
33 | this._bubblePosition = bubblePosition ?? BubblePosition.BOTTOM;
34 | this._bubbleBean = bubbleBean;
35 | }
36 | }
37 |
38 | export class BubbleBean {
39 | private _title: string = "";
40 |
41 | public get title(): string {
42 | return this._title;
43 | }
44 |
45 | private _content: string = "";
46 |
47 | public get content(): string {
48 | return this._content;
49 | }
50 |
51 | constructor(title: string, content: string) {
52 | this._title = title;
53 | this._content = content;
54 | }
55 | }
56 |
57 | export enum BubblePosition {
58 | TOP,
59 | BOTTOM,
60 | LEFT,
61 | RIGHT
62 | }
63 |
64 | @Builder
65 | export function bubbleBuilder(data: BubbleBean) {
66 | Column() {
67 | Text(data.title)
68 | .fontSize(15)
69 | .fontColor(Color.Black)
70 | Text(data.content)
71 | .fontSize(14)
72 | .fontColor(Color.Gray)
73 | .margin({ top: 8 })
74 | }.alignItems(HorizontalAlign.Start)
75 | }
--------------------------------------------------------------------------------
/omni_component/src/main/ets/components/guide/model/HighLightInfoOfRectF.ets:
--------------------------------------------------------------------------------
1 | import HighLight from '../interface/HighLight';
2 | import { HighLightOptions } from './HighLightOptions';
3 | import { HighLightShape } from './HighLightShape';
4 | import { RectF } from './RectF';
5 |
6 | export default class HighLightInfoOfRectF implements HighLight {
7 | private rectF: RectF | null = null;
8 | private shape: HighLightShape = HighLightShape.ROUND_RECTANGLE;
9 | private round: number = 0;
10 | private options: HighLightOptions | null = null;
11 |
12 | constructor(rectF: RectF, shape: HighLightShape, round?: number) {
13 | this.rectF = rectF;
14 | this.shape = shape;
15 | this.round = round ? round : 0;
16 | }
17 |
18 | /**
19 | * 设置高亮区域的额外配置
20 | * @param options 额外配置
21 | */
22 | public setOptions(options: HighLightOptions): void {
23 | this.options = options;
24 | }
25 |
26 | /**
27 | * 获取高亮区域的额外配置
28 | */
29 | getOptions(): HighLightOptions | null {
30 | return this.options;
31 | }
32 |
33 | /**
34 | * 获取圆角矩形的圆角弧度,仅当shape = HighLightShape.ROUND_RECTANGLE 时调用此方法
35 | * @returns 圆角矩形的圆角弧度
36 | */
37 | getRound(): number {
38 | return this.round;
39 | }
40 |
41 | /**
42 | * 获取圆形的半径,仅当shape = HighLightShape.CIRCLE时调用此方法获取半径
43 | * @param parentId 父布局id
44 | * @returns 返回圆的半径
45 | */
46 | getRadius(parentId?: string): number {
47 | if (!this.rectF) {
48 | return 0;
49 | }
50 | return Math.min(this.rectF.getWidth() / 2, this.rectF.getHeight() / 2);
51 | }
52 |
53 | /**
54 | * 获取高亮图形的区域坐标,组件要求必传id,rectF区域需要为相对于父组件的相对坐标,坐标值需要转换为vp,不能直接为px
55 | * @param parentId 高亮区域为组件时,必传,父组件id:__HighLightGuideComponentContainer__ + 组件创建时的时间戳,id需要整个应用内唯一
56 | * @param componentId 高亮区域为组件时,必传,组件id需要整个应用内唯一
57 | * @returns 返回高亮区域的坐标,单位为vp
58 | */
59 | getRectF(parentId?: string, componentId?: string): RectF | null {
60 | return this.rectF;
61 | }
62 |
63 | /**
64 | * 获取高亮区域的图形类型
65 | */
66 | getShape() {
67 | return this.shape;
68 | }
69 |
70 | /**
71 | * 高亮区域的类型
72 | * @returns 返回组件id 即高亮区域为组件类型,否则为指定的高亮区域
73 | */
74 | isComponentHighLight(): string | boolean {
75 | return false;
76 | }
77 | }
--------------------------------------------------------------------------------
/omni_component/src/main/ets/components/guide/model/HighLightOptions.ets:
--------------------------------------------------------------------------------
1 | import { OnClickListener } from '../interface/OnClickListener';
2 | import { OnHighLightDrewListener } from '../interface/OnHighLightDrewListener';
3 |
4 | export class HighLightOptions {
5 | public onClickListener: OnClickListener | null = null;
6 | public onHighLightDrewListener: OnHighLightDrewListener | null = null;
7 | public fetchLocationEveryTime: boolean = false;
8 | }
--------------------------------------------------------------------------------
/omni_component/src/main/ets/components/guide/model/HighLightOptionsBuilder.ets:
--------------------------------------------------------------------------------
1 | import { OnClickListener } from '../interface/OnClickListener';
2 | import { OnHighLightDrewListener } from '../interface/OnHighLightDrewListener';
3 | import { HighLightOptions } from './HighLightOptions';
4 |
5 | export class HighLightOptionsBuilder {
6 | private options: HighLightOptions;
7 |
8 | constructor() {
9 | this.options = new HighLightOptions();
10 | }
11 |
12 | /**
13 | * 高亮点击事件
14 | * @param listener 点击事件回调
15 | * @returns 额外配置构建类
16 | */
17 | public setOnClickListener(listener: OnClickListener | null): HighLightOptionsBuilder {
18 | this.options.onClickListener = listener;
19 | return this;
20 | }
21 |
22 | /**
23 | * 为高亮区域添加重绘监听
24 | * @param listener 重绘高亮区域图形的监听
25 | * @returns 额外配置构建类
26 | */
27 | public setOnHighLightDrewListener(listener: OnHighLightDrewListener | null): HighLightOptionsBuilder {
28 | this.options.onHighLightDrewListener = listener;
29 | return this;
30 | }
31 |
32 | /**
33 | * 是否每次显示引导页都重新获取组件坐标
34 | * @param isFetchLocation 是否每次显示引导页都重新获取组件坐标
35 | * @returns 额外配置构建类
36 | */
37 | public isFetchLocationEveryTime(isFetchLocation: boolean): HighLightOptionsBuilder {
38 | this.options.fetchLocationEveryTime = isFetchLocation;
39 | return this;
40 | }
41 |
42 | /**
43 | * 获取高亮区域的额外配置项
44 | * @returns
45 | */
46 | public build(): HighLightOptions {
47 | return this.options;
48 | }
49 | }
--------------------------------------------------------------------------------
/omni_component/src/main/ets/components/guide/model/HighLightShape.ets:
--------------------------------------------------------------------------------
1 | export enum HighLightShape {
2 | CIRCLE, // 圆形
3 | RECTANGLE, // 矩形
4 | OVAL, // 椭圆
5 | ROUND_RECTANGLE // 圆角矩形
6 | }
--------------------------------------------------------------------------------
/omni_component/src/main/ets/components/guide/model/ObservedMaskVisibleState.ets:
--------------------------------------------------------------------------------
1 | @Observed
2 | export default class ObservedMaskVisibleState {
3 | private globalShowGuideMask: boolean = false;
4 |
5 | /**
6 | * 设置引导页蒙版显示状态
7 | * @param show 是否显示引导页蒙版
8 | */
9 | setShowGuideMask(show: boolean): void {
10 | this.globalShowGuideMask = show;
11 | }
12 |
13 | /**
14 | * 获取引导页蒙版显示状态
15 | * @returns 蒙版是否正在显示
16 | */
17 | isShowGuideMask() {
18 | return this.globalShowGuideMask;
19 | }
20 | }
--------------------------------------------------------------------------------
/omni_component/src/main/ets/components/guide/model/ObservedPageIndex.ets:
--------------------------------------------------------------------------------
1 | @Observed
2 | export default class ObservedPageIndex {
3 | private globalCurrentPageIndex: number = -1;
4 |
5 | /**
6 | * 设置引导页index
7 | * @param index 引导页索引
8 | */
9 | setCurrentPageIndex(index: number): void {
10 | this.globalCurrentPageIndex = index;
11 | }
12 |
13 | /**
14 | * 获取引导页的索引
15 | * @returns 引导页索引
16 | */
17 | getCurrentPageIndex() {
18 | return this.globalCurrentPageIndex;
19 | }
20 | }
--------------------------------------------------------------------------------
/omni_component/src/main/ets/components/guide/model/RectF.ets:
--------------------------------------------------------------------------------
1 | export class RectF {
2 | public left: number = 0;
3 | public top: number = 0;
4 | public right: number = 0;
5 | public bottom: number = 0;
6 |
7 | constructor(rect: RectF);
8 |
9 | constructor(left: number, top: number, right: number, bottom: number);
10 |
11 | constructor(left: number | RectF, top?: number, right?: number, bottom?: number) {
12 | if (typeof left === 'number') {
13 | this.check(left, top, right, bottom);
14 | this.left = left ? left : 0;
15 | this.top = top ? top : 0;
16 | this.right = right ? right : 0;
17 | this.bottom = bottom ? bottom : 0;
18 | } else if (left instanceof RectF) {
19 | this.createByRectF(left);
20 | }
21 | }
22 |
23 | /**
24 | * 通过rectF对象创建rectF
25 | * @param rectF 对象
26 | * @returns
27 | */
28 | private createByRectF(rectF: RectF): RectF {
29 | this.check(rectF.left, rectF.top, rectF.right, rectF.bottom);
30 | this.left = rectF.left;
31 | this.top = rectF.top;
32 | this.right = rectF.right;
33 | this.bottom = rectF.bottom;
34 | return this;
35 | }
36 |
37 | /**
38 | * 获取矩形中心点X轴坐标
39 | * @returns x坐标
40 | */
41 | public getCenterX(): number {
42 | this.check(this.left, this.top, this.right, this.bottom);
43 | return this.left + (this.right - this.left) / 2;
44 | }
45 |
46 | /**
47 | * 获取矩形中心点Y轴坐标
48 | * @returns Y坐标
49 | */
50 | public getCenterY(): number {
51 | this.check(this.left, this.top, this.right, this.bottom);
52 | return this.top + (this.bottom - this.top) / 2;
53 | }
54 |
55 | /**
56 | * 获取矩形的宽
57 | * @returns 矩形区域的宽
58 | */
59 | public getWidth(): number {
60 | return this.right - this.left;
61 | }
62 |
63 | /**
64 | * 获取矩形的高
65 | * @returns 矩形区域的高
66 | */
67 | public getHeight(): number {
68 | return this.bottom - this.top;
69 | }
70 |
71 | /**
72 | * 检测矩形区域坐标数据的有效性
73 | * @param left 左上角的X坐标
74 | * @param top 左上角的Y坐标
75 | * @param right 右下角的X坐标
76 | * @param bottom 右下角的Y坐标
77 | */
78 | private check(left: number | null | undefined, top: number | null | undefined, right: number | null | undefined,
79 | bottom: number | null | undefined): void {
80 | if (left == null || left == undefined ||
81 | top == null || top == undefined ||
82 | right == null || right == undefined ||
83 | bottom == null || bottom == undefined ||
84 | right < left || bottom < top) {
85 | throw new Error('please check the rect params');
86 | }
87 | }
88 | }
--------------------------------------------------------------------------------
/omni_component/src/main/ets/components/guide/util/GlobalContext.ts:
--------------------------------------------------------------------------------
1 | export class GlobalContext {
2 | private constructor() {
3 | }
4 |
5 | private static instance: GlobalContext;
6 | public static HILOG_TAG: string = 'HighLightGuide';
7 |
8 | private _objects = new Map();
9 |
10 | public static getContext(): GlobalContext {
11 | if (!GlobalContext.instance) {
12 | GlobalContext.instance = new GlobalContext();
13 | }
14 | return GlobalContext.instance;
15 | }
16 |
17 | getObject(value: string): Object | undefined {
18 | return this._objects.get(value);
19 | }
20 |
21 | setObject(key: string, objectClass: Object): void {
22 | this._objects.set(key, objectClass);
23 | }
24 | }
--------------------------------------------------------------------------------
/omni_component/src/main/ets/components/imagepicker/OmniImagePickerTrigger.ets:
--------------------------------------------------------------------------------
1 |
2 |
3 | @Component
4 | export struct OmniImagePickerTrigger {
5 |
6 | @Prop triggerImageIcon: ResourceStr
7 | @Link selectUris: Array
8 | @Require goImagePicker?: () => void
9 |
10 | build() {
11 | Column() {
12 | Grid() {
13 | ForEach(this.selectUris, (url: ResourceStr, index: number) => {
14 | GridItem() {
15 | Image(url)
16 | .width('100%')
17 | .aspectRatio(1)
18 | .borderRadius(4)
19 | .onClick(() => {
20 | if (index == 0) {
21 | this.goImagePicker?.()
22 | }
23 | })
24 | }
25 | .width('100%')
26 | })
27 | }
28 | .columnsTemplate("1fr 1fr 1fr 1fr")
29 | .columnsGap(5)
30 | .rowsGap(5)
31 | .margin({
32 | top: 10
33 | })
34 | .onAppear(() => {
35 | this.selectUris.push(this.triggerImageIcon ?? $r('app.media.image_trigger_add'))
36 |
37 | })
38 | }
39 |
40 | }
41 |
42 | aboutToAppear(): void {
43 | }
44 | }
--------------------------------------------------------------------------------
/omni_component/src/main/ets/components/loading/OmniDotLoadingView.ets:
--------------------------------------------------------------------------------
1 | @Preview
2 | @Component
3 | export struct OmniDotLoadingView {
4 | @Prop noDataText: string = '到底啦~'
5 | @Link loading: boolean
6 | private WIDTH = 8
7 | private DURATION = 200
8 | private colorArray = [0xFFFF552E, 0xFF3E80F8, 0xFF53E7AE, 0xFFFFCE5A]
9 | private scalesArray = [
10 | [1.0, 0.8, 0.6, 0.4, 0.6, 0.8, 1.0],
11 | [0.8, 1.0, 0.8, 0.6, 0.4, 0.6, 0.8],
12 | [0.6, 0.8, 1.0, 0.8, 0.6, 0.4, 0.6],
13 | [0.4, 0.6, 0.8, 1.0, 0.8, 0.6, 0.4],
14 | ]
15 | private currentIndex: number = 0
16 | @State private scales: number[] = [1.0, 0.8, 0.6, 0.4]
17 |
18 | aboutToAppear() {
19 | this._animateTo()
20 | }
21 |
22 | _animateTo() {
23 | this.getUIContext().animateTo({
24 | curve: Curve.Linear,
25 | duration: this.DURATION,
26 | onFinish: () => {
27 | this._animateTo()
28 | }
29 | }, () => {
30 | this.currentIndex = (this.currentIndex + 1) % this.scalesArray[0].length
31 | this.scales = this.scalesArray.map(scaleGroup => scaleGroup[this.currentIndex])
32 | })
33 | }
34 |
35 | build() {
36 | if (this.loading) {
37 | Row({ space: 4 }) {
38 | ForEach(this.colorArray, (color: number, i) => {
39 | Circle({ width: this.WIDTH, height: this.WIDTH })
40 | .foregroundColor(color)
41 | .opacity(this.scales[i])
42 | .scale({ x: this.scales[i], y: this.scales[i] })
43 | })
44 | }
45 | } else {
46 | Text(this.noDataText)
47 | }
48 | }
49 | }
--------------------------------------------------------------------------------
/omni_component/src/main/ets/components/loading/OmniPageLoading.ets:
--------------------------------------------------------------------------------
1 | import { ComponentContent, PromptAction } from "@kit.ArkUI"
2 | import { OmniTheme, OmniThemeStyle } from "../../theme/OmniTheme"
3 |
4 | @Component
5 | export struct OmniPageLoading {
6 | @StorageLink(OmniTheme.KEY)
7 | private baseStyle: OmniThemeStyle = OmniTheme.getDefaultStyle()
8 | @Prop options?: LoadingOptions = undefined
9 |
10 | build() {
11 | Row() {
12 | Progress({ value: 0, total: 100, type: ProgressType.Ring })
13 | .width(20)
14 | .color(Color.White)
15 | .style({ strokeWidth: 2, status: ProgressStatus.LOADING })
16 | Text(this.options?.content ?? '加载中...')
17 | .fontSize(this.options?.theme?.fontSize ?? this.baseStyle.fontSizeLg)
18 | .fontColor(this.options?.theme?.fontColor ?? Color.White)
19 | .fontWeight(this.options?.theme?.fontWeight ?? FontWeight.Medium)
20 | .margin({ left: 6 })
21 | }
22 | .backgroundColor(this.options?.theme?.backgroundColor ?? this.baseStyle.primary)
23 | .padding(10)
24 | .borderRadius(this.options?.theme?.borderRadius ?? 6)
25 | }
26 | }
27 |
28 | @Builder
29 | function buildLoading(ops?: LoadingOptions) {
30 | OmniPageLoading({
31 | options: ops
32 | })
33 | }
34 |
35 | export class OmniLoading {
36 | private static DEFAULT_CONTENT = '加载中...'
37 | private uiContext: UIContext
38 | private promptAction: PromptAction
39 | private compContent?: ComponentContent
40 |
41 | constructor(uiContext: UIContext) {
42 | this.uiContext = uiContext
43 | this.promptAction = uiContext.getPromptAction()
44 | }
45 |
46 | public show(options?: LoadingOptions) {
47 | if (this.compContent === undefined) {
48 | this.compContent =
49 | new ComponentContent(this.uiContext, wrapBuilder(buildLoading), options ?? { content: OmniLoading.DEFAULT_CONTENT })
50 | } else {
51 | this.compContent.update(options ?? { content: OmniLoading.DEFAULT_CONTENT })
52 | }
53 |
54 | // 显示 dialog
55 | this.promptAction.openCustomDialog(this.compContent, {
56 | isModal: true, // 弹窗是否为模态窗口,模态窗口有蒙层,非模态窗口无蒙层。
57 | autoCancel: false, // 是否允许点击遮障层退出,true表示关闭弹窗。false表示不关闭弹窗。
58 | alignment: DialogAlignment.Center,
59 | })
60 | }
61 |
62 | public dismiss() {
63 | this.promptAction.closeCustomDialog(this.compContent).then(() => {
64 | this.compContent?.dispose()
65 | })
66 | }
67 | }
68 |
69 | export interface LoadingOptions {
70 | content?: string
71 | theme?: LoadingTheme
72 | }
73 |
74 | export interface LoadingTheme {
75 | fontSize?: number | string | Resource
76 | fontColor?: ResourceColor
77 | fontWeight?: FontWeight
78 | backgroundColor?: ResourceColor
79 | borderRadius?: Dimension | BorderRadiuses
80 | }
--------------------------------------------------------------------------------
/omni_component/src/main/ets/components/popup/ArrowLocation.ets:
--------------------------------------------------------------------------------
1 | export enum ArrowLocation {
2 | LEFT,
3 | TOP,
4 | RIGHT,
5 | BOTTOM
6 | }
--------------------------------------------------------------------------------
/omni_component/src/main/ets/components/popup/BaseAttachPopup.ets:
--------------------------------------------------------------------------------
1 | import { BasePopup } from './BasePopup';
2 | import { componentUtils } from '@kit.ArkUI';
3 | import { PopupPosition } from './PopupPosition';
4 |
5 | /**
6 | * 依附弹窗窗口基类
7 | */
8 | export abstract class BaseAttachPopup extends BasePopup {
9 | constructor(customWrappedBuilder: WrappedBuilder) {
10 | super(customWrappedBuilder);
11 | }
12 |
13 | /**
14 | * Popup显示之前,可做一些数据处理
15 | */
16 | beforeShow(): void {
17 | if (this.attachViewId != null) {
18 | let componentInfo = componentUtils.getRectangleById(this.attachViewId)
19 | this.popupConfig.attachViewComponentInfo = componentInfo
20 | const y = componentInfo.screenOffset.y
21 | const x = componentInfo.screenOffset.x
22 | const h = componentInfo.size.height
23 | const w = componentInfo.size.width
24 | const yOffset = px2vp(y)
25 | const xOffset = px2vp(x)
26 | const height = px2vp(h)
27 | const width = px2vp(w)
28 | if (this.popupConfig.popupPosition == PopupPosition.TOP) {
29 | //向上弹窗
30 | this.dialogOptions.alignment = DialogAlignment.BottomStart
31 | this.dialogOptions.offset = {
32 | dx: 0,
33 | dy: -(px2vp(this.screenHeight) - yOffset) + this.getAttachMargin()
34 | }
35 | } else if (this.popupConfig.popupPosition == PopupPosition.LEFT) {
36 | //向左弹窗
37 | this.dialogOptions.alignment = DialogAlignment.TopEnd
38 | this.dialogOptions.offset = {
39 | dx: -(px2vp(this.screenWidth) - xOffset) + this.getAttachMargin(),
40 | dy: 0
41 | }
42 | } else if (this.popupConfig.popupPosition == PopupPosition.RIGHT) {
43 | //向右弹窗
44 | this.dialogOptions.alignment = DialogAlignment.TopStart
45 | this.dialogOptions.offset = {
46 | dx: xOffset + width + this.getAttachMargin(),
47 | dy: 0
48 | }
49 | } else {
50 | //向下
51 | this.dialogOptions.alignment = DialogAlignment.TopStart
52 | this.dialogOptions.offset = {
53 | dx: 0,
54 | dy: yOffset + height + this.getAttachMargin()
55 | }
56 | }
57 | }
58 | }
59 |
60 | getAttachMargin(): number {
61 | if (this.popupConfig.popupPosition == PopupPosition.TOP) {
62 | return -this.popupConfig.attachMargin
63 | } else if (this.popupConfig.popupPosition == PopupPosition.LEFT) {
64 | return -this.popupConfig.attachMargin
65 | } else if (this.popupConfig.popupPosition == PopupPosition.RIGHT) {
66 | return this.popupConfig.attachMargin
67 | } else {
68 | return this.popupConfig.attachMargin
69 | }
70 |
71 | }
72 | }
--------------------------------------------------------------------------------
/omni_component/src/main/ets/components/popup/BubblePopup.ets:
--------------------------------------------------------------------------------
1 | import { ArrowLocation } from './ArrowLocation';
2 | import { PopupPosition } from './PopupPosition';
3 | import { PopupType } from './PopupType';
4 | import { BaseAttachPopup } from './BaseAttachPopup';
5 |
6 | /**
7 | * 气泡弹窗
8 | */
9 | export class BubblePopup extends BaseAttachPopup {
10 | /**
11 | * 默认阴影半径
12 | */
13 | private readonly defaultShadowRadius: number = 15
14 |
15 | constructor(customBuilder: WrappedBuilder) {
16 | super(customBuilder)
17 | this.popupType = PopupType.BUBBLE
18 | }
19 |
20 | /**
21 | * Popup显示之前,可做一些数据处理
22 | */
23 | beforeShow(): void {
24 | if (this.popupConfig.shadowRadius == null) {
25 | this.popupConfig.shadowRadius = this.defaultShadowRadius
26 | }
27 | this.popupConfig.wrap = true
28 | super.beforeShow()
29 | //处理箭头方向
30 | if (this.popupConfig.popupPosition == PopupPosition.TOP) {
31 | this.popupConfig.arrowLocation = ArrowLocation.BOTTOM
32 | } else if (this.popupConfig.popupPosition == PopupPosition.LEFT) {
33 | this.popupConfig.arrowLocation = ArrowLocation.RIGHT
34 | } else if (this.popupConfig.popupPosition == PopupPosition.RIGHT) {
35 | this.popupConfig.arrowLocation = ArrowLocation.LEFT
36 | } else {
37 | this.popupConfig.arrowLocation = ArrowLocation.TOP
38 | }
39 | }
40 |
41 | getAttachMargin(): number {
42 | if (this.popupConfig.popupPosition == PopupPosition.TOP) {
43 | return -this.popupConfig.attachMargin + (this.popupConfig.shadowRadius ?? 0)
44 | } else if (this.popupConfig.popupPosition == PopupPosition.LEFT) {
45 | return -this.popupConfig.attachMargin + (this.popupConfig.shadowRadius ?? 0)
46 | } else if (this.popupConfig.popupPosition == PopupPosition.RIGHT) {
47 | return this.popupConfig.attachMargin - (this.popupConfig.shadowRadius ?? 0)
48 | } else {
49 | return this.popupConfig.attachMargin - (this.popupConfig.shadowRadius ?? 0)
50 | }
51 | }
52 | }
--------------------------------------------------------------------------------
/omni_component/src/main/ets/components/popup/Config.ets:
--------------------------------------------------------------------------------
1 | import { PopupConfig } from './PopupConfig'
2 | import { promptAction } from '@kit.ArkUI'
3 | import { PopupInfo } from './entity/PopupInfo'
4 |
5 | export class Config {
6 | /**
7 | * 弹窗基础配置参数
8 | */
9 | static dialogOptions: promptAction.BaseDialogOptions = {}
10 | /**
11 | * 弹窗设置
12 | */
13 | static popupConfig: PopupConfig = new PopupConfig()
14 | /**
15 | * 侧滑关闭
16 | */
17 | static dismissOnBackPressed: boolean = true
18 | /**
19 | * 自定义组件时,是否NodeContainer包裹,wrap=true:参数可统一设置,比如弹窗圆角、内边距等;wrap=false:所有内容都需要自己在使用地方配置,比如圆角,内边距等
20 | */
21 | static wrap: boolean = true
22 | /**
23 | * 全局设置
24 | */
25 | static popupOptions: PopupInfo = {}
26 |
27 | /**
28 | * 获取弹窗系统设置
29 | * @returns
30 | */
31 | static getDialogOptions(): promptAction.BaseDialogOptions {
32 | return JSON.parse(JSON.stringify(Config.dialogOptions))
33 | }
34 |
35 | /**
36 | * 获取窗口设置
37 | * @returns
38 | */
39 | static getPopupConfig(): PopupConfig {
40 | return JSON.parse(JSON.stringify(Config.popupConfig))
41 | }
42 |
43 | /**
44 | * 获取弹窗内默认设置
45 | * @returns
46 | */
47 | static getPopupOptions(): PopupInfo {
48 | return JSON.parse(JSON.stringify(Config.popupOptions))
49 | }
50 | }
--------------------------------------------------------------------------------
/omni_component/src/main/ets/components/popup/CustomBuilder.ets:
--------------------------------------------------------------------------------
1 | import { PopupBean } from './entity/PopupBean'
2 | import { CustomBubbleComponent } from './CustomBubbleComponent'
3 |
4 | /**
5 | * 气泡弹窗
6 | * @param data
7 | */
8 | @Builder
9 | export function bubblePopupBuilder(data: PopupBean) {
10 | CustomBubbleComponent({ data: data })
11 | }
--------------------------------------------------------------------------------
/omni_component/src/main/ets/components/popup/CustomNodeController.ets:
--------------------------------------------------------------------------------
1 | import { BuilderNode, FrameNode, NodeController, Size, UIContext } from '@kit.ArkUI';
2 |
3 | export class CustomNodeController extends NodeController {
4 | private customNode: BuilderNode | null = null
5 | private builder: WrappedBuilder
6 | private params?: T
7 |
8 | constructor(builder: WrappedBuilder, params?: T) {
9 | super();
10 | this.builder = builder;
11 | this.params = params;
12 | }
13 |
14 | makeNode(uiContext: UIContext): FrameNode | null {
15 | this.customNode = new BuilderNode(uiContext)
16 | this.customNode.build(this.builder, this.params)
17 | return this.customNode.getFrameNode()
18 | }
19 |
20 | /**
21 | * 释放节点
22 | */
23 | dispose() {
24 | if (this.customNode != null) {
25 | this.customNode.dispose()
26 | }
27 | }
28 |
29 | aboutToResize(size: Size): void {
30 | console.log("节点大小width=" + size.width + ",height" + size.height)
31 | }
32 | }
--------------------------------------------------------------------------------
/omni_component/src/main/ets/components/popup/PopupAction.ets:
--------------------------------------------------------------------------------
1 | export interface PopupAction {
2 | dismiss: Callback
3 | index?: number
4 | data?: ESObject
5 | }
--------------------------------------------------------------------------------
/omni_component/src/main/ets/components/popup/PopupCallback.ets:
--------------------------------------------------------------------------------
1 | import { PopupAction } from './PopupAction'
2 |
3 | export interface PopupCallback {
4 | /**
5 | * 弹窗准备显示
6 | */
7 | beforeShow?: () => void
8 | /**
9 | * 弹窗完全显示
10 | */
11 | onShow?: () => void
12 | /**
13 | * 弹窗完全消失
14 | */
15 | onDismiss?: () => void
16 | /**
17 | * 弹窗准备消失
18 | */
19 | beforeDismiss?: () => void
20 | /**
21 | * 返回按钮
22 | */
23 | onBackPressed?: (data: DismissDialogAction) => void
24 | /**
25 | * 确认等操作数据返回
26 | */
27 | onAction?: (data?: PopupAction) => void
28 |
29 | }
--------------------------------------------------------------------------------
/omni_component/src/main/ets/components/popup/PopupConfig.ets:
--------------------------------------------------------------------------------
1 | import { PopupPosition } from './PopupPosition'
2 | import { componentUtils } from '@kit.ArkUI'
3 | import { ArrowLocation } from './ArrowLocation'
4 |
5 | export class PopupConfig {
6 | /**
7 | * 弹窗宽度,仅限于wrap=true,底部和顶部弹窗默认 100% ,中间弹窗默认90%
8 | */
9 | width?: Length
10 | /**
11 | * 弹窗高度,仅限于wrap = true,默认50%
12 | */
13 | height?: Length
14 | /**
15 | * 弹窗最大宽度,仅限于wrap=true
16 | */
17 | maxWidth?: Length
18 | /**
19 | * 弹窗最小宽度,仅限于wrap=true
20 | */
21 | minWidth?: Length
22 | /**
23 | * 弹窗最大高度,仅限于wrap=true
24 | */
25 | maxHeight?: Length
26 | /**
27 | * 弹窗最小高度,仅限于wrap=true
28 | */
29 | minHeight?: Length
30 | /**
31 | * 背景颜色
32 | */
33 | backgroundColor: ResourceColor = Color.White
34 | /**
35 | * 圆角
36 | */
37 | borderRadius: Length | BorderRadiuses | LocalizedBorderRadiuses = 16
38 | /**
39 | * Popup弹窗内边距
40 | */
41 | popupPadding: Padding | Length | LocalizedPadding = 20
42 | /**
43 | * 主要颜色
44 | */
45 | primaryColor?: ResourceColor
46 | /**
47 | * 侧滑关闭
48 | */
49 | dismissOnBackPressed: boolean = true
50 | /**
51 | * 自定义组件时,是否NodeContainer包裹,wrap=true:参数可统一设置,比如弹窗圆角、内边距等;wrap=false:所有内容都需要自己在使用地方配置,比如圆角,内边距等
52 | */
53 | wrap: boolean = true
54 | /**
55 | * 操作完成后是否自动关闭弹窗,默认true,比如点击ConfirmPopup的确认按钮,默认自动关闭;如果为false,则不会关闭
56 | */
57 | autoDismiss: boolean = true
58 | /**
59 | * 弹窗位置
60 | */
61 | popupPosition?: PopupPosition
62 | /**
63 | * 依赖View型数据
64 | */
65 | attachViewComponentInfo?: componentUtils.ComponentInfo
66 | /**
67 | * 依附弹窗是否对组件居中
68 | */
69 | isAttachCenter:boolean = true
70 | /**
71 | * 依附组件距离指定组件的距离,默认为0
72 | */
73 | attachMargin: number = 0
74 | /**
75 | * 气泡弹窗,箭头偏移,单位vp
76 | */
77 | arrowOffset: number = 0
78 | /**
79 | * 气泡弹窗,箭头是否居中
80 | */
81 | isArrowPositionCenter: boolean = true
82 | /**
83 | * 阴影颜色
84 | */
85 | shadowColor: string = "#FF444444"
86 | /**
87 | * 阴影半径,单位:vp
88 | */
89 | shadowRadius?: number
90 | /**
91 | * 阴影X轴,单位:vp
92 | */
93 | shadowX: number = 0
94 | /**
95 | * 阴影Y轴,单位:vp
96 | */
97 | shadowY: number = 0
98 | /**
99 | * 气泡弹窗,箭头尖左边弧度,单位:vp
100 | */
101 | arrowTopLeftRadius: number = 2
102 | /**
103 | * 气泡弹窗,箭头尖右边弧度,单位:vp
104 | */
105 | arrowTopRightRadius: number = 2
106 | /**
107 | * 气泡弹窗,箭头底部左边弧度,单位:vp
108 | */
109 | arrowDownLeftRadius: number = 2
110 | /**
111 | * 气泡弹窗,箭头底部右边弧度,单位:vp
112 | */
113 | arrowDownRightRadius: number = 2
114 | /**
115 | * 气泡弹窗,箭头宽度,单位:vp
116 | */
117 | arrowWidth: number = 20
118 | /**
119 | * 气泡弹窗,箭头高度,单位:vp
120 | */
121 | arrowHeight: number = 8
122 | /**
123 | * 气泡弹窗,箭头的位置,默认顶部
124 | */
125 | arrowLocation: ArrowLocation = ArrowLocation.TOP
126 | /**
127 | * 边框颜色
128 | */
129 | borderColor: number = Color.Transparent
130 | /**
131 | * 边框大小,单位:vp
132 | */
133 | borderSize: number = 0
134 | }
--------------------------------------------------------------------------------
/omni_component/src/main/ets/components/popup/PopupManager.ets:
--------------------------------------------------------------------------------
1 | import { ComponentContent, promptAction, PromptAction, window } from '@kit.ArkUI';
2 | import { bubblePopupBuilder } from './CustomBuilder';
3 | import { PopupBean } from './entity/PopupBean';
4 | import { PopupConfig } from './PopupConfig';
5 | import { CustomNodeController } from './CustomNodeController';
6 | import { PopupType } from './PopupType';
7 |
8 | /**
9 | * 弹窗管理
10 | */
11 | export class PopupManager {
12 | private popup?: ComponentContent