From 02af5671983542edd44c19249aa1aa95e0ce716a Mon Sep 17 00:00:00 2001 From: zhanghang Date: Thu, 23 Oct 2025 09:02:35 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0grid=20capi=20demo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zhanghang --- ArkUIKit/NativeNodeBaseSample/README.md | 12 +- .../main/cpp/GridIrregularIndexesMaker.cpp | 212 ++++++++++++++++++ .../src/main/cpp/GridIrregularIndexesMaker.h | 124 ++++++++++ .../entry/src/main/cpp/GridLayoutOptions.h | 36 +++ .../src/main/cpp/GridRectByIndexMaker.cpp | 186 +++++++++++++++ .../entry/src/main/cpp/GridRectByIndexMaker.h | 114 ++++++++++ .../entry/src/main/cpp/manager.cpp | 14 ++ .../entry/src/main/cpp/manager.h | 2 + .../entry/src/main/cpp/napi_init.cpp | 4 + .../src/main/cpp/types/libentry/Index.d.ts | 2 + .../entry/src/main/ets/pages/Index.ets | 2 +- .../entry/src/main/ets/pages/PageGrid.ets | 75 +++++++ .../ets/pages/grid/PageGridGetRectByIndex.ets | 34 +++ .../pages/grid/PageGridIrregularIndexes.ets | 34 +++ .../PageGridNormal.ets} | 2 +- .../resources/base/profile/main_pages.json | 7 +- .../entry/src/main/ets/pages/PageGrid.ets | 75 +++++++ .../ets/pages/grid/PageGridGetRectByIndex.ets | 34 +++ .../pages/grid/PageGridIrregularIndexes.ets | 34 +++ .../main/ets/pages/grid/PageGridNormal.ets} | 2 +- ArkUIKit/NativeTypeSample/README.md | 18 +- .../main/cpp/GridIrregularIndexesMaker.cpp | 212 ++++++++++++++++++ .../src/main/cpp/GridIrregularIndexesMaker.h | 124 ++++++++++ .../entry/src/main/cpp/GridLayoutOptions.h | 36 +++ .../src/main/cpp/GridRectByIndexMaker.cpp | 187 +++++++++++++++ .../entry/src/main/cpp/GridRectByIndexMaker.h | 114 ++++++++++ .../entry/src/main/cpp/manager.cpp | 56 +++++ .../entry/src/main/cpp/manager.h | 2 + .../entry/src/main/cpp/napi_init.cpp | 4 + .../src/main/cpp/types/libentry/Index.d.ts | 4 +- .../entry/src/main/ets/pages/Index.ets | 2 +- .../entry/src/main/ets/pages/PageGrid.ets | 75 +++++++ .../ets/pages/grid/PageGridGetRectByIndex.ets | 34 +++ .../pages/grid/PageGridIrregularIndexes.ets | 34 +++ .../main/ets/pages/grid/PageGridNormal.ets | 34 +++ .../resources/base/profile/main_pages.json | 7 +- 36 files changed, 1935 insertions(+), 13 deletions(-) create mode 100644 ArkUIKit/NativeNodeBaseSample/entry/src/main/cpp/GridIrregularIndexesMaker.cpp create mode 100644 ArkUIKit/NativeNodeBaseSample/entry/src/main/cpp/GridIrregularIndexesMaker.h create mode 100644 ArkUIKit/NativeNodeBaseSample/entry/src/main/cpp/GridLayoutOptions.h create mode 100644 ArkUIKit/NativeNodeBaseSample/entry/src/main/cpp/GridRectByIndexMaker.cpp create mode 100644 ArkUIKit/NativeNodeBaseSample/entry/src/main/cpp/GridRectByIndexMaker.h create mode 100644 ArkUIKit/NativeNodeBaseSample/entry/src/main/ets/pages/PageGrid.ets create mode 100644 ArkUIKit/NativeNodeBaseSample/entry/src/main/ets/pages/grid/PageGridGetRectByIndex.ets create mode 100644 ArkUIKit/NativeNodeBaseSample/entry/src/main/ets/pages/grid/PageGridIrregularIndexes.ets rename ArkUIKit/NativeNodeBaseSample/entry/src/main/ets/pages/{page_grid.ets => grid/PageGridNormal.ets} (98%) create mode 100644 ArkUIKit/NativeNodeNapiSample/entry/src/main/ets/pages/PageGrid.ets create mode 100644 ArkUIKit/NativeNodeNapiSample/entry/src/main/ets/pages/grid/PageGridGetRectByIndex.ets create mode 100644 ArkUIKit/NativeNodeNapiSample/entry/src/main/ets/pages/grid/PageGridIrregularIndexes.ets rename ArkUIKit/{NativeTypeSample/entry/src/main/ets/pages/page_grid.ets => NativeNodeNapiSample/entry/src/main/ets/pages/grid/PageGridNormal.ets} (98%) create mode 100644 ArkUIKit/NativeTypeSample/entry/src/main/cpp/GridIrregularIndexesMaker.cpp create mode 100644 ArkUIKit/NativeTypeSample/entry/src/main/cpp/GridIrregularIndexesMaker.h create mode 100644 ArkUIKit/NativeTypeSample/entry/src/main/cpp/GridLayoutOptions.h create mode 100644 ArkUIKit/NativeTypeSample/entry/src/main/cpp/GridRectByIndexMaker.cpp create mode 100644 ArkUIKit/NativeTypeSample/entry/src/main/cpp/GridRectByIndexMaker.h create mode 100644 ArkUIKit/NativeTypeSample/entry/src/main/ets/pages/PageGrid.ets create mode 100644 ArkUIKit/NativeTypeSample/entry/src/main/ets/pages/grid/PageGridGetRectByIndex.ets create mode 100644 ArkUIKit/NativeTypeSample/entry/src/main/ets/pages/grid/PageGridIrregularIndexes.ets create mode 100644 ArkUIKit/NativeTypeSample/entry/src/main/ets/pages/grid/PageGridNormal.ets diff --git a/ArkUIKit/NativeNodeBaseSample/README.md b/ArkUIKit/NativeNodeBaseSample/README.md index 58a4caac25b..a8e054749b1 100644 --- a/ArkUIKit/NativeNodeBaseSample/README.md +++ b/ArkUIKit/NativeNodeBaseSample/README.md @@ -57,8 +57,12 @@ entry/src/main/cpp/ ├── CMakeLists.txt (CMake脚本) ├── form_manager.cpp ├── form_manager.h +├── GridIrregularIndexesMaker.cpp +├── GridIrregularIndexesMaker.h ├── GridMaker.cpp ├── GridMaker.h +├── GridRectByIndexMaker.cpp +├── GridRectByIndexMaker.h ├── imagespan_manager.cpp ├── imagespan_manager.h ├── ListItemGroup.h @@ -98,7 +102,7 @@ entry/src/main/ets/ └── pages ├── Index.ets (获取导航页面) ├── page_form.ets (Form页面) - ├── page_grid.ets (Grid页面) + ├── PageGrid.ets (Grid页面) ├── page_imagespan.ets (imagespan页面) ├── page_list.ets (List页面) ├── page_refresh.ets (Refresh页面) @@ -108,7 +112,11 @@ entry/src/main/ets/ ├──page_xcomponent.ets (XComponent界面) ├── page_waterflow.ets (WaterFlow界面) ├──page_waterflow.ets (WaterFlow界面) - └── page_public_event.ets (通用属性界面) + ├── page_public_event.ets (通用属性界面) + └── grid + ├── PageGridNormal.ets (普通Grid页面) + ├── PageGridIrregularIndexes.ets (可滚动Grid设置跨行跨列节点页面) + └── PageGridGetRectByIndex.ets (固定行列Grid页面) entry/src/main/resources/ ├── base diff --git a/ArkUIKit/NativeNodeBaseSample/entry/src/main/cpp/GridIrregularIndexesMaker.cpp b/ArkUIKit/NativeNodeBaseSample/entry/src/main/cpp/GridIrregularIndexesMaker.cpp new file mode 100644 index 00000000000..5f21ecaef01 --- /dev/null +++ b/ArkUIKit/NativeNodeBaseSample/entry/src/main/cpp/GridIrregularIndexesMaker.cpp @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the License. + */ + +#include "GridIrregularIndexesMaker.h" + +#include +#include +#include +#include // snprintf +#include +#include +#include +#include +#include + +#include "ArkUINodeAdapter.h" +#include "ScrollableNode.h" + +namespace { +// ===== 布局与样式常量 ===== +constexpr char K_COLUMNS_TEMPLATE[] = "1fr 1fr 1fr 1fr 1fr"; +constexpr float K_WIDTH_PERCENT = 0.9f; +constexpr float K_COLUMNS_GAP = 10.0f; +constexpr float K_ROWS_GAP = 10.0f; +constexpr float K_HEIGHT = 300.0f; +constexpr float K_TEXT_SIZE = 16.0f; +constexpr float K_ITEM_HEIGHT = 80.0f; +constexpr float K_ITEM_WIDTH_PERCENT = 1.0f; +constexpr float K_NODE_FONT_SIZE = 16.0f; +constexpr uint32_t K_ITEM_BG_COLOR = 0xFFF9CF93U; +constexpr uint32_t K_BG_COLOR = 0xFFFAEEE0; +constexpr uint32_t K_TEXT_COLOR = 0xFFCCCCCC; +constexpr uint32_t NUMBER_0 = 0; +constexpr uint32_t NUMBER_2 = 2; +constexpr uint32_t NUMBER_5 = 5; +const std::string CONTENT = "scroll"; +} // namespace +std::shared_ptr GridIrregularIndexesMaker::layoutOptions1_; +std::shared_ptr GridIrregularIndexesMaker::layoutOptions2_; +// ---------- 配置 Grid 外观/交互 ---------- +static void ConfigureGrid(const std::shared_ptr& grid) +{ + grid->SetColumnsTemplate(K_COLUMNS_TEMPLATE); + grid->SetColumnsGap(K_COLUMNS_GAP); + grid->SetRowsGap(K_ROWS_GAP); + grid->SetScrollBar(ARKUI_SCROLL_BAR_DISPLAY_MODE_OFF); + grid->SetWidthPercent(K_WIDTH_PERCENT); + grid->SetHeight(K_HEIGHT); + grid->SetBackgroundColor(K_BG_COLOR); +} + +static std::vector BuildData() +{ + std::vector data; + for (size_t i = NUMBER_0; i < NUMBER_5; i++) { + for (size_t j = NUMBER_0; j < NUMBER_5; j++) { + data.emplace_back(std::to_string(j)); + } + } + return data; +} + +// ---------- 适配器回调(创建/绑定) ---------- +static ArkUI_NodeHandle GridCreateItem(ArkUI_NativeNodeAPI_1* api) +{ + ArkUI_NodeHandle text = api->createNode(ARKUI_NODE_TEXT); + ArkUI_NodeHandle item = api->createNode(ARKUI_NODE_GRID_ITEM); + api->addChild(item, text); + return item; +} + +static void GridBindItem(ArkUI_NativeNodeAPI_1* api, ArkUI_NodeHandle item, int32_t index, + const std::shared_ptr>& data) +{ + SetAttributeFloat32(api, item, NODE_FONT_SIZE, K_NODE_FONT_SIZE); + SetAttributeUInt32(api, item, NODE_BACKGROUND_COLOR, K_ITEM_BG_COLOR); + SetAttributeFloat32(api, item, NODE_HEIGHT, K_ITEM_HEIGHT); + SetAttributeUInt32(api, item, NODE_TEXT_ALIGN, ARKUI_TEXT_ALIGNMENT_CENTER); + SetAttributeFloat32(api, item, NODE_WIDTH_PERCENT, K_ITEM_WIDTH_PERCENT); + + ArkUI_NodeHandle text = api->getFirstChild(item); + if (!text) { + return; + } + + const int32_t n = static_cast(data->size()); + const char* s = (index >= 0 && index < n) ? (*data)[static_cast(index)].c_str() : ""; + SetTextContent(api, text, s); +} + +// ---------- 构建 Adapter ---------- +static std::shared_ptr MakeGridAdapter(const std::shared_ptr>& data) +{ + auto adapter = std::make_shared(); + adapter->EnsurePlaceholderTypeOr(static_cast(ARKUI_NODE_GRID_ITEM)); + + ArkUINodeAdapter::Callbacks cb {}; + cb.getTotalCount = [data]() -> int32_t { return static_cast(data->size()); }; + cb.getStableId = [data](int32_t i) -> uint64_t { + const int32_t n = static_cast(data->size()); + if (i >= 0 && i < n) { + return static_cast(std::hash {}((*data)[static_cast(i)])); + } + return static_cast(i); + }; + cb.onCreate = [](ArkUI_NativeNodeAPI_1* api, int32_t /*index*/) -> ArkUI_NodeHandle { return GridCreateItem(api); }; + cb.onBind = [data](ArkUI_NativeNodeAPI_1* api, ArkUI_NodeHandle item, int32_t index) { + GridBindItem(api, item, index, data); + }; + + adapter->SetCallbacks(cb); + return adapter; +} + +std::shared_ptr GridIrregularIndexesMaker::BuildGrid1() +{ + auto grid = std::make_shared(); + ConfigureGrid(grid); + auto data = std::make_shared>(BuildData()); + auto adapter = MakeGridAdapter(data); + grid->SetLazyAdapter(adapter); + adapter->ReloadAllItems(); + + uint32_t irregularIndexes[] = { 0, 6 }; + OH_ArkUI_GridLayoutOptions_SetIrregularIndexes(layoutOptions1_->GetLayoutOptions(), irregularIndexes, NUMBER_2); + grid->SetLayoutOptions(layoutOptions1_->GetLayoutOptions()); + GetKeepAliveContainer().emplace_back(grid); + return grid; +} + +// ---------- 构建指定GridItemRect Grid ---------- +std::shared_ptr GridIrregularIndexesMaker::BuildGrid2() +{ + auto grid = std::make_shared(); + ConfigureGrid(grid); + + auto data = std::make_shared>(BuildData()); + auto adapter = MakeGridAdapter(data); + grid->SetLazyAdapter(adapter); + adapter->ReloadAllItems(); + + uint32_t irregularIndexes[] = { 0, 7 }; + OH_ArkUI_GridLayoutOptions_SetIrregularIndexes(layoutOptions2_->GetLayoutOptions(), irregularIndexes, NUMBER_2); + OH_ArkUI_GridLayoutOptions_RegisterGetIrregularSizeByIndexCallback( + layoutOptions2_->GetLayoutOptions(), nullptr, [](int32_t itemIndex, void* userData) -> ArkUI_GridItemSize { + if (itemIndex == 0) { + return { 1, 5 }; + } + return { 1, static_cast(itemIndex % 6 + 1) }; + }); + grid->SetLayoutOptions(layoutOptions2_->GetLayoutOptions()); + GetKeepAliveContainer().emplace_back(grid); + return grid; +} + +// ---------- 构建 Text ---------- +static std::shared_ptr BuildText( + ArkUI_NativeNodeAPI_1* api, const std::string& content, uint32_t fontColor, float fontSize) +{ + ArkUI_NodeHandle textNode = api->createNode(ARKUI_NODE_TEXT); + SetTextContent(api, textNode, content.c_str()); + SetAttributeFloat32(api, textNode, NODE_FONT_SIZE, fontSize); + SetAttributeUInt32(api, textNode, NODE_FONT_COLOR, fontColor); + return std::make_shared(textNode); +} + +ArkUI_NodeHandle GridIrregularIndexesMaker::CreateNativeNode() +{ + ArkUI_NativeNodeAPI_1* api = nullptr; + OH_ArkUI_GetModuleInterface(ARKUI_NATIVE_NODE, ArkUI_NativeNodeAPI_1, api); + if (api == nullptr) { + return nullptr; + } + + // 根容器全屏 + ArkUI_NodeHandle page = api->createNode(ARKUI_NODE_COLUMN); + if (page == nullptr) { + return nullptr; + } + SetAttributeFloat32(api, page, NODE_WIDTH_PERCENT, 1.0f); + SetAttributeFloat32(api, page, NODE_HEIGHT_PERCENT, 1.0f); + + // 构建 Grid + std::shared_ptr grid = BuildGrid1(); + if (grid && grid->GetHandle() != nullptr) { + api->addChild(page, grid->GetHandle()); + } + + // 构建Text + std::shared_ptr text = BuildText(api, CONTENT, K_TEXT_COLOR, K_TEXT_SIZE); + if (text) { + api->addChild(page, *text); + } + + // 构建不规则Grid + std::shared_ptr grid2 = BuildGrid2(); + if (grid2 && grid2->GetHandle() != nullptr) { + api->addChild(page, grid2->GetHandle()); + } + return page; +} \ No newline at end of file diff --git a/ArkUIKit/NativeNodeBaseSample/entry/src/main/cpp/GridIrregularIndexesMaker.h b/ArkUIKit/NativeNodeBaseSample/entry/src/main/cpp/GridIrregularIndexesMaker.h new file mode 100644 index 00000000000..d889fb27d35 --- /dev/null +++ b/ArkUIKit/NativeNodeBaseSample/entry/src/main/cpp/GridIrregularIndexesMaker.h @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef GRID_IRREGULAR_INDEXES_NODE_H +#define GRID_IRREGULAR_INDEXES_NODE_H + +#include +#include + +#include "ArkUINodeAdapter.h" +#include "GridLayoutOptions.h" +#include "ScrollableEvent.h" +#include "ScrollableNode.h" +#include "ScrollableUtils.h" + +class GridIrregularIndexesMaker : public BaseNode { +public: + struct GridParam {}; + static ArkUI_NodeHandle CreateNativeNode(); + + GridIrregularIndexesMaker() + : BaseNode(NodeApiInstance::GetInstance()->GetNativeNodeAPI()->createNode(ARKUI_NODE_GRID)), + nodeApi_(NodeApiInstance::GetInstance()->GetNativeNodeAPI()) + { + if (!IsNotNull(nodeApi_) || !IsNotNull(GetHandle())) { + return; + } + + nodeApi_->addNodeEventReceiver(GetHandle(), StaticEventReceiver); + scrollEventGuard_.Bind(nodeApi_, GetHandle(), this, SCROLL_EVT_ALL); + layoutOptions1_ = std::make_shared(); + layoutOptions2_ = std::make_shared(); + } + + ~GridIrregularIndexesMaker() override + { + scrollEventGuard_.Release(); + nodeAdapter_.reset(); + layoutOptions1_ = nullptr; + layoutOptions2_ = nullptr; + } + + // ======================================== + // 模板和间距设置 + // ======================================== + void SetRowsTemplate(const char* rowsTemplate) + { + SetAttributeString(nodeApi_, GetHandle(), NODE_GRID_ROW_TEMPLATE, rowsTemplate); + } + + void SetColumnsTemplate(const char* columnsTemplate) + { + SetAttributeString(nodeApi_, GetHandle(), NODE_GRID_COLUMN_TEMPLATE, columnsTemplate); + } + + void SetColumnsGap(float gap) + { + SetAttributeFloat32(nodeApi_, GetHandle(), NODE_GRID_COLUMN_GAP, gap); + } + + void SetRowsGap(float gap) + { + SetAttributeFloat32(nodeApi_, GetHandle(), NODE_GRID_ROW_GAP, gap); + } + + void SetScrollBar(int32_t displayMode) + { + SetAttributeFloat32(nodeApi_, GetHandle(), NODE_SCROLL_BAR_DISPLAY_MODE, displayMode); + } + // ======================================== + // 适配器设置 + // ======================================== + void SetLazyAdapter(const std::shared_ptr& adapter) + { + if (!IsNotNull(adapter)) { + return; + } + ArkUI_AttributeItem item { nullptr, 0, nullptr, adapter->GetAdapter() }; + nodeApi_->setAttribute(GetHandle(), NODE_GRID_NODE_ADAPTER, &item); + nodeAdapter_ = adapter; + } + + // ======================================== + // 设置属性 + // ======================================== + void SetLayoutOptions(ArkUI_GridLayoutOptions* layoutOptions) + { + if (layoutOptions == nullptr) { + return; + } + + ArkUI_AttributeItem item = { .object = layoutOptions }; + nodeApi_->setAttribute(GetHandle(), NODE_GRID_LAYOUT_OPTIONS, &item); + } + +protected: + void OnNodeEvent(ArkUI_NodeEvent* event) override + { + BaseNode::OnNodeEvent(event); + } + +private: + static std::shared_ptr BuildGrid1(); + static std::shared_ptr BuildGrid2(); + ArkUI_NativeNodeAPI_1* nodeApi_ = nullptr; + std::shared_ptr nodeAdapter_; + ScrollEventGuard scrollEventGuard_; + static std::shared_ptr layoutOptions1_; + static std::shared_ptr layoutOptions2_; +}; + +#endif // GRID_IRREGULAR_INDEXES_NODE_H diff --git a/ArkUIKit/NativeNodeBaseSample/entry/src/main/cpp/GridLayoutOptions.h b/ArkUIKit/NativeNodeBaseSample/entry/src/main/cpp/GridLayoutOptions.h new file mode 100644 index 00000000000..5dc4e862865 --- /dev/null +++ b/ArkUIKit/NativeNodeBaseSample/entry/src/main/cpp/GridLayoutOptions.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License") + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef GRID_LAYOUT_OPTIONS_H +#define GRID_LAYOUT_OPTIONS_H + +#include +class GridLayoutOptions { +public: + GridLayoutOptions() : layoutOptions_(OH_ArkUI_GridLayoutOptions_Create()) {} + ~GridLayoutOptions() + { + OH_ArkUI_GridLayoutOptions_Dispose(layoutOptions_); + layoutOptions_ = nullptr; + } + + ArkUI_GridLayoutOptions* GetLayoutOptions() const + { + return layoutOptions_; + } + +private: + ArkUI_GridLayoutOptions* layoutOptions_ = nullptr; +}; +#endif // GRID_LAYOUT_OPTIONS_H diff --git a/ArkUIKit/NativeNodeBaseSample/entry/src/main/cpp/GridRectByIndexMaker.cpp b/ArkUIKit/NativeNodeBaseSample/entry/src/main/cpp/GridRectByIndexMaker.cpp new file mode 100644 index 00000000000..01f2bce12e5 --- /dev/null +++ b/ArkUIKit/NativeNodeBaseSample/entry/src/main/cpp/GridRectByIndexMaker.cpp @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the License. + */ + +#include "GridRectByIndexMaker.h" + +#include +#include +#include +#include // snprintf +#include +#include +#include +#include +#include + +#include "ArkUINodeAdapter.h" +#include "ScrollableNode.h" + +namespace { +// ===== 布局与样式常量 ===== +constexpr char K_ROWS_TEMPLATE[] = "1fr 1fr 1fr 1fr 1fr"; +constexpr char K_COLUMNS_TEMPLATE[] = "1fr 1fr 1fr 1fr 1fr"; +constexpr char K_ROWS_TEMPLATE_RECT_BY_INDEX[] = "1fr 1fr 1fr 1fr 1fr 1fr"; +constexpr char K_COLUMNS_TEMPLATE_RECT_BY_INDEX[] = "1fr 1fr 1fr 1fr 1fr 1fr"; +constexpr float K_WIDTH_PERCENT = 0.9f; +constexpr float K_COLUMNS_GAP = 10.0f; +constexpr float K_ROWS_GAP = 10.0f; +constexpr float K_HEIGHT = 300.0f; +constexpr uint32_t K_ITEM_BG_COLOR = 0xFFF9CF93U; +constexpr uint32_t K_BG_COLOR = 0xFFFAEEE0; +constexpr uint32_t K_TEXT_COLOR = 0xFFCCCCCC; +constexpr float K_TEXT_SIZE = 16.0f; +constexpr float K_ITEM_HEIGHT_PERCENT = 1.0f; +constexpr float K_ITEM_WIDTH_PERCENT = 1.0f; +constexpr float K_NODE_FONT_SIZE = 16.0f; +constexpr unsigned int K_LOG_PRINT_DOMAIN = 0xFF00; +constexpr int K_GRID_INDEX_WIDTH = 2; +constexpr uint32_t NUMBER_0 = 0; +constexpr uint32_t NUMBER_1 = 1; +constexpr uint32_t NUMBER_2 = 2; +constexpr uint32_t NUMBER_3 = 3; +constexpr uint32_t NUMBER_4 = 4; +constexpr uint32_t NUMBER_5 = 5; +constexpr uint32_t NUMBER_6 = 6; +const std::vector NUMBERS_1 = { "0", "1", "2", "3", "4" }; +const std::vector NUMBERS_2 = { "0", "1", "2", "3", "4", "5" }; +const std::string CONTENT = "GridLayoutOptions的使用:onGetRectByIndex。"; +} // namespace +std::shared_ptr GridRectByIndexMaker::layoutOptions_; + +static std::shared_ptr CreateGridItem(ArkUI_NativeNodeAPI_1* api, const std::string& content) +{ + ArkUI_NodeHandle text = api->createNode(ARKUI_NODE_TEXT); + ArkUI_NodeHandle item = api->createNode(ARKUI_NODE_GRID_ITEM); + SetAttributeUInt32(api, text, NODE_TEXT_ALIGN, ARKUI_TEXT_ALIGNMENT_CENTER); + SetAttributeUInt32(api, text, NODE_BACKGROUND_COLOR, K_ITEM_BG_COLOR); + SetAttributeFloat32(api, text, NODE_HEIGHT_PERCENT, K_ITEM_HEIGHT_PERCENT); + SetAttributeFloat32(api, text, NODE_WIDTH_PERCENT, K_ITEM_WIDTH_PERCENT); + SetAttributeFloat32(api, text, NODE_FONT_SIZE, K_NODE_FONT_SIZE); + SetTextContent(api, text, content.c_str()); + api->addChild(item, text); + return std::make_shared(item); +} + +// ---------- 整体构建普通Grid ---------- +static std::shared_ptr BuildGrid() +{ + ArkUI_NativeNodeAPI_1* nodeAPI = nullptr; + OH_ArkUI_GetModuleInterface(ARKUI_NATIVE_NODE, ArkUI_NativeNodeAPI_1, nodeAPI); + + auto grid = std::make_shared(); + grid->SetWidthPercent(K_WIDTH_PERCENT); + grid->SetHeight(K_HEIGHT); + grid->SetColumnsTemplate(K_COLUMNS_TEMPLATE); + grid->SetRowsTemplate(K_ROWS_TEMPLATE); + grid->SetColumnsGap(K_COLUMNS_GAP); + grid->SetRowsGap(K_ROWS_GAP); + grid->SetBackgroundColor(K_BG_COLOR); + + for (auto i = 0; i < NUMBERS_1.size(); i++) { + for (auto j = 0; j < NUMBERS_1.size(); j++) { + auto gridItem = CreateGridItem(nodeAPI, std::to_string(i)); + nodeAPI->addChild(grid->GetHandle(), *gridItem); + } + } + + GetKeepAliveContainer().emplace_back(grid); + return grid; +} + +// ---------- 构建指定GridItemRect Grid ---------- +std::shared_ptr GridRectByIndexMaker::BuildGridRectByIndex() +{ + ArkUI_NativeNodeAPI_1* nodeAPI = nullptr; + OH_ArkUI_GetModuleInterface(ARKUI_NATIVE_NODE, ArkUI_NativeNodeAPI_1, nodeAPI); + auto grid = std::make_shared(); + grid->SetWidthPercent(K_WIDTH_PERCENT); + grid->SetHeight(K_HEIGHT); + grid->SetColumnsTemplate(K_COLUMNS_TEMPLATE_RECT_BY_INDEX); + grid->SetRowsTemplate(K_ROWS_TEMPLATE_RECT_BY_INDEX); + grid->SetColumnsGap(K_COLUMNS_GAP); + grid->SetRowsGap(K_ROWS_GAP); + + for (auto i = 0; i < NUMBERS_2.size(); i++) { + auto gridItem = CreateGridItem(nodeAPI, std::to_string(i)); + nodeAPI->addChild(grid->GetHandle(), *gridItem); + } + + OH_ArkUI_GridLayoutOptions_RegisterGetRectByIndexCallback( + layoutOptions_->GetLayoutOptions(), nullptr, [](int32_t itemIndex, void* userData) -> ArkUI_GridItemRect { + if (itemIndex == NUMBER_0) { + return ArkUI_GridItemRect { 0, 0, 1, 1 }; + } else if (itemIndex == NUMBER_1) { + return ArkUI_GridItemRect { 0, 1, 2, 2 }; + } else if (itemIndex == NUMBER_2) { + return ArkUI_GridItemRect { 0, 3, 3, 3 }; + } else if (itemIndex == NUMBER_3) { + return ArkUI_GridItemRect { 3, 0, 3, 3 }; + } else if (itemIndex == NUMBER_4) { + return ArkUI_GridItemRect { 4, 3, 2, 2 }; + } else { + return ArkUI_GridItemRect { 5, 5, 1, 1 }; + } + }); + grid->SetLayoutOptions(layoutOptions_->GetLayoutOptions()); + GetKeepAliveContainer().emplace_back(grid); + return grid; +} + +// ---------- 构建 Text ---------- +static std::shared_ptr BuildText( + ArkUI_NativeNodeAPI_1* api, const std::string& content, uint32_t fontColor, float fontSize) +{ + ArkUI_NodeHandle textNode = api->createNode(ARKUI_NODE_TEXT); + SetTextContent(api, textNode, content.c_str()); + SetAttributeFloat32(api, textNode, NODE_FONT_SIZE, fontSize); + SetAttributeUInt32(api, textNode, NODE_FONT_COLOR, fontColor); + return std::make_shared(textNode); +} + +ArkUI_NodeHandle GridRectByIndexMaker::CreateNativeNode() +{ + ArkUI_NativeNodeAPI_1* api = nullptr; + OH_ArkUI_GetModuleInterface(ARKUI_NATIVE_NODE, ArkUI_NativeNodeAPI_1, api); + if (api == nullptr) { + return nullptr; + } + + // 根容器全屏 + ArkUI_NodeHandle page = api->createNode(ARKUI_NODE_COLUMN); + if (page == nullptr) { + return nullptr; + } + SetAttributeFloat32(api, page, NODE_WIDTH_PERCENT, 1.0f); + SetAttributeFloat32(api, page, NODE_HEIGHT_PERCENT, 1.0f); + + // 构建 Grid + std::shared_ptr grid = BuildGrid(); + if (grid && grid->GetHandle() != nullptr) { + api->addChild(page, grid->GetHandle()); + } + + // 构建Text + std::shared_ptr text = BuildText(api, CONTENT, K_TEXT_COLOR, K_TEXT_SIZE); + if (text) { + api->addChild(page, *text); + } + + // 构建不规则Grid + std::shared_ptr grid2 = BuildGridRectByIndex(); + if (grid2 && grid2->GetHandle() != nullptr) { + api->addChild(page, grid2->GetHandle()); + } + return page; +} \ No newline at end of file diff --git a/ArkUIKit/NativeNodeBaseSample/entry/src/main/cpp/GridRectByIndexMaker.h b/ArkUIKit/NativeNodeBaseSample/entry/src/main/cpp/GridRectByIndexMaker.h new file mode 100644 index 00000000000..2668292f50a --- /dev/null +++ b/ArkUIKit/NativeNodeBaseSample/entry/src/main/cpp/GridRectByIndexMaker.h @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef GRID_RECT_BY_INDEX_NODE_H +#define GRID_RECT_BY_INDEX_NODE_H + +#include + +#include "ArkUINodeAdapter.h" +#include "GridLayoutOptions.h" +#include "ScrollableEvent.h" +#include "ScrollableNode.h" +#include "ScrollableUtils.h" + +class GridRectByIndexMaker : public BaseNode { +public: + static ArkUI_NodeHandle CreateNativeNode(); + + GridRectByIndexMaker() + : BaseNode(NodeApiInstance::GetInstance()->GetNativeNodeAPI()->createNode(ARKUI_NODE_GRID)), + nodeApi_(NodeApiInstance::GetInstance()->GetNativeNodeAPI()) + { + if (!IsNotNull(nodeApi_) || !IsNotNull(GetHandle())) { + return; + } + + nodeApi_->addNodeEventReceiver(GetHandle(), StaticEventReceiver); + scrollEventGuard_.Bind(nodeApi_, GetHandle(), this, SCROLL_EVT_ALL); + layoutOptions_ = std::make_shared(); + } + + ~GridRectByIndexMaker() override + { + scrollEventGuard_.Release(); + nodeAdapter_.reset(); + layoutOptions_ = nullptr; + } + + // ======================================== + // 模板和间距设置 + // ======================================== + void SetRowsTemplate(const char* rowsTemplate) + { + SetAttributeString(nodeApi_, GetHandle(), NODE_GRID_ROW_TEMPLATE, rowsTemplate); + } + + void SetColumnsTemplate(const char* columnsTemplate) + { + SetAttributeString(nodeApi_, GetHandle(), NODE_GRID_COLUMN_TEMPLATE, columnsTemplate); + } + + void SetColumnsGap(float gap) + { + SetAttributeFloat32(nodeApi_, GetHandle(), NODE_GRID_COLUMN_GAP, gap); + } + + void SetRowsGap(float gap) + { + SetAttributeFloat32(nodeApi_, GetHandle(), NODE_GRID_ROW_GAP, gap); + } + + // ======================================== + // 适配器设置 + // ======================================== + void SetLazyAdapter(const std::shared_ptr& adapter) + { + if (!IsNotNull(adapter)) { + return; + } + ArkUI_AttributeItem item { nullptr, 0, nullptr, adapter->GetAdapter() }; + nodeApi_->setAttribute(GetHandle(), NODE_GRID_NODE_ADAPTER, &item); + nodeAdapter_ = adapter; + } + + // ======================================== + // 设置属性 + // ======================================== + void SetLayoutOptions(ArkUI_GridLayoutOptions* layoutOptions) + { + if (layoutOptions == nullptr) { + return; + } + + ArkUI_AttributeItem item = { .object = layoutOptions }; + nodeApi_->setAttribute(GetHandle(), NODE_GRID_LAYOUT_OPTIONS, &item); + } + +protected: + void OnNodeEvent(ArkUI_NodeEvent* event) override + { + BaseNode::OnNodeEvent(event); + } + +private: + static std::shared_ptr BuildGridRectByIndex(); + ArkUI_NativeNodeAPI_1* nodeApi_ = nullptr; + std::shared_ptr nodeAdapter_; + ScrollEventGuard scrollEventGuard_; + static std::shared_ptr layoutOptions_; +}; + +#endif // GRID_RECT_BY_INDEX_NODE_H diff --git a/ArkUIKit/NativeNodeBaseSample/entry/src/main/cpp/manager.cpp b/ArkUIKit/NativeNodeBaseSample/entry/src/main/cpp/manager.cpp index 29ab7ac94a3..b8ae5cbc99a 100644 --- a/ArkUIKit/NativeNodeBaseSample/entry/src/main/cpp/manager.cpp +++ b/ArkUIKit/NativeNodeBaseSample/entry/src/main/cpp/manager.cpp @@ -14,7 +14,9 @@ */ #include "manager.h" +#include "GridIrregularIndexesMaker.h" #include "GridMaker.h" +#include "GridRectByIndexMaker.h" #include "TextMaker.h" #include "SwiperMaker.h" #include "AccessibilityMaker.h" @@ -130,6 +132,18 @@ napi_value Manager::CreateGridNativeNode(napi_env env, napi_callback_info info) []() -> ArkUI_NodeHandle { return GridMaker::CreateNativeNode(); }); } +napi_value Manager::CreateGridNativeNodeOnGetRectByIndex(napi_env env, napi_callback_info info) +{ + return CreateNativeNode(env, info, "CreateGridNativeNodeOnGetRectByIndex", + []() -> ArkUI_NodeHandle { return GridRectByIndexMaker::CreateNativeNode(); }); +} + +napi_value Manager::CreateGridNativeNodeIrregularIndexes(napi_env env, napi_callback_info info) +{ + return CreateNativeNode(env, info, "CreateGridNativeNodeIrregularIndexes", + []() -> ArkUI_NodeHandle { return GridIrregularIndexesMaker::CreateNativeNode(); }); +} + napi_value Manager::CreateScrollNativeNode(napi_env env, napi_callback_info info) { return CreateNativeNode(env, info, "CreateScrollNativeNode", diff --git a/ArkUIKit/NativeNodeBaseSample/entry/src/main/cpp/manager.h b/ArkUIKit/NativeNodeBaseSample/entry/src/main/cpp/manager.h index cabcf1cf227..1876df12b1b 100644 --- a/ArkUIKit/NativeNodeBaseSample/entry/src/main/cpp/manager.h +++ b/ArkUIKit/NativeNodeBaseSample/entry/src/main/cpp/manager.h @@ -39,6 +39,8 @@ public: static napi_value CreateNativeEmbeddedComponentNode(napi_env env, napi_callback_info info); static napi_value CreateWaterFlowNativeNode(napi_env env, napi_callback_info info); static napi_value CreateGridNativeNode(napi_env env, napi_callback_info info); + static napi_value CreateGridNativeNodeOnGetRectByIndex(napi_env env, napi_callback_info info); + static napi_value CreateGridNativeNodeIrregularIndexes(napi_env env, napi_callback_info info); static napi_value CreateScrollNativeNode(napi_env env, napi_callback_info info); static napi_value CreateRefreshNativeNode(napi_env env, napi_callback_info info); static napi_value CreateListNativeNode(napi_env env, napi_callback_info info); diff --git a/ArkUIKit/NativeNodeBaseSample/entry/src/main/cpp/napi_init.cpp b/ArkUIKit/NativeNodeBaseSample/entry/src/main/cpp/napi_init.cpp index 51320784278..2c50525f68a 100644 --- a/ArkUIKit/NativeNodeBaseSample/entry/src/main/cpp/napi_init.cpp +++ b/ArkUIKit/NativeNodeBaseSample/entry/src/main/cpp/napi_init.cpp @@ -25,6 +25,10 @@ napi_property_descriptor desc[] = { {"createWaterFlowNativeNode", nullptr, Manager::CreateWaterFlowNativeNode, nullptr, nullptr, nullptr, napi_default, nullptr}, {"createGridNativeNode", nullptr, Manager::CreateGridNativeNode, nullptr, nullptr, nullptr, napi_default, nullptr}, + {"createGridNativeNodeOnGetRectByIndex", nullptr, Manager::CreateGridNativeNodeOnGetRectByIndex, nullptr, + nullptr, nullptr, napi_default, nullptr }, + {"createGridNativeNodeIrregularIndexes", nullptr, Manager::CreateGridNativeNodeIrregularIndexes, nullptr, + nullptr, nullptr, napi_default, nullptr }, {"createScrollNativeNode", nullptr, Manager::CreateScrollNativeNode, nullptr, nullptr, nullptr, napi_default, nullptr}, {"createRefreshNativeNode", nullptr, Manager::CreateRefreshNativeNode, nullptr, nullptr, nullptr, napi_default, diff --git a/ArkUIKit/NativeNodeBaseSample/entry/src/main/cpp/types/libentry/Index.d.ts b/ArkUIKit/NativeNodeBaseSample/entry/src/main/cpp/types/libentry/Index.d.ts index 6e739663251..773fbf8b636 100644 --- a/ArkUIKit/NativeNodeBaseSample/entry/src/main/cpp/types/libentry/Index.d.ts +++ b/ArkUIKit/NativeNodeBaseSample/entry/src/main/cpp/types/libentry/Index.d.ts @@ -36,3 +36,5 @@ export const removeImageSpanNode: (nodeId: number) => void; export const setImageSpanAttribute: (nodeId: number, nodeType: number, attributeType: number, attributeValue: string) => number; export const getImageSpanAttribute: (nodeId: number, nodeType: number, attributeType: number) => string; export const resetImageSpanAttribute: (nodeId: number, nodeType: number, attributeType: number) => number; +export const createGridNativeNodeOnGetRectByIndex: (content: Object) => void; +export const createGridNativeNodeIrregularIndexes: (content: Object) => void; diff --git a/ArkUIKit/NativeNodeBaseSample/entry/src/main/ets/pages/Index.ets b/ArkUIKit/NativeNodeBaseSample/entry/src/main/ets/pages/Index.ets index 2398d331bf7..09c5084d4e8 100644 --- a/ArkUIKit/NativeNodeBaseSample/entry/src/main/ets/pages/Index.ets +++ b/ArkUIKit/NativeNodeBaseSample/entry/src/main/ets/pages/Index.ets @@ -31,7 +31,7 @@ struct MenuIndex { { title: 'accessibility', url: 'pages/page_accessibility', id: '' }, { title: 'embedded component', url: 'pages/page_embedded_component', id: '' }, { title: 'WaterFlow', url: 'pages/page_waterflow', id: '' }, - { title: 'Grid', url: 'pages/page_grid', id: '' }, + { title: 'Grid', url: 'pages/PageGrid', id: '' }, { title: 'Public', url: 'pages/page_public_event', id: 'Public' }, { title: 'Scroll', url: 'pages/page_scroll', id: '' }, { title: 'Refresh', url: 'pages/page_refresh', id: '' }, diff --git a/ArkUIKit/NativeNodeBaseSample/entry/src/main/ets/pages/PageGrid.ets b/ArkUIKit/NativeNodeBaseSample/entry/src/main/ets/pages/PageGrid.ets new file mode 100644 index 00000000000..be8cad60fc5 --- /dev/null +++ b/ArkUIKit/NativeNodeBaseSample/entry/src/main/ets/pages/PageGrid.ets @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License") + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { router } from '@kit.ArkUI'; + +interface ListCategories { + title: string, + url: string +} + +@Entry +@Component +struct MenuIndex { + private items: ListCategories[] = + [ + { title: '普通Grid', url: 'pages/grid/PageGridNormal' }, + { title: '固定行列Grid', url: 'pages/grid/PageGridGetRectByIndex' }, + { title: '可滚动Grid设置跨行跨列节点', url: 'pages/grid/PageGridIrregularIndexes' }, + ]; + + build() { + Scroll(new Scroller()) { + Column() { + Text('Grid选择页面') + .fontWeight(FontWeight.Bold) + .fontSize('20vp') + .textAlign(TextAlign.Center) + .height('5%') + .margin($r('sys.float.titlebar_title_margin_right')) + List() { + ForEach(this.items, (item: ListCategories) => { + ListItem() { + Row() { + Text(item.title) + .fontSize($r('sys.float.text_button_font_size')) + .fontColor(Color.Black) + .textAlign(TextAlign.Start) + .height('100%') + .width('50%') + .padding($r('sys.float.padding_level10')) + Text('>') + .fontSize('25vp') + .fontColor(Color.Black) + .textAlign(TextAlign.End) + .fontColor(Color.Gray) + .height('100%') + .width('50%') + .padding($r('sys.float.padding_level10')) + } + .width('100%') + .height('10%') + .borderRadius($r('sys.float.select_border_radius_default')) + .backgroundColor(Color.White) + .onClick(() => { + router.pushUrl({ url: item.url }) + }) + }.margin($r('sys.float.menu_item_content_align')) + }) + }.width('95%').height('90%').alignListItem(ListItemAlign.Center) + }.width('100%') + }.height('100%').backgroundColor($r('app.color.background_color')) + } +} \ No newline at end of file diff --git a/ArkUIKit/NativeNodeBaseSample/entry/src/main/ets/pages/grid/PageGridGetRectByIndex.ets b/ArkUIKit/NativeNodeBaseSample/entry/src/main/ets/pages/grid/PageGridGetRectByIndex.ets new file mode 100644 index 00000000000..7bda73e8c7b --- /dev/null +++ b/ArkUIKit/NativeNodeBaseSample/entry/src/main/ets/pages/grid/PageGridGetRectByIndex.ets @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License") + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import Napi from 'libentry.so'; +import { NodeContent } from '@kit.ArkUI'; + +@Entry +@Component +struct Index { + private nodeContent = new NodeContent(); + aboutToAppear() { + // 通过C-API创建节点,并添加到管理器nodeContent上 + Napi.createGridNativeNodeOnGetRectByIndex(this.nodeContent); + } + build() { + Column() { + ContentSlot(this.nodeContent) + } + .width('100%') + .height('100%') + } +} diff --git a/ArkUIKit/NativeNodeBaseSample/entry/src/main/ets/pages/grid/PageGridIrregularIndexes.ets b/ArkUIKit/NativeNodeBaseSample/entry/src/main/ets/pages/grid/PageGridIrregularIndexes.ets new file mode 100644 index 00000000000..d1280f828a2 --- /dev/null +++ b/ArkUIKit/NativeNodeBaseSample/entry/src/main/ets/pages/grid/PageGridIrregularIndexes.ets @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License") + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import Napi from 'libentry.so'; +import { NodeContent } from '@kit.ArkUI'; + +@Entry +@Component +struct Index { + private nodeContent = new NodeContent(); + aboutToAppear() { + // 通过C-API创建节点,并添加到管理器nodeContent上 + Napi.createGridNativeNodeIrregularIndexes(this.nodeContent); + } + build() { + Column() { + ContentSlot(this.nodeContent) + } + .width('100%') + .height('100%') + } +} diff --git a/ArkUIKit/NativeNodeBaseSample/entry/src/main/ets/pages/page_grid.ets b/ArkUIKit/NativeNodeBaseSample/entry/src/main/ets/pages/grid/PageGridNormal.ets similarity index 98% rename from ArkUIKit/NativeNodeBaseSample/entry/src/main/ets/pages/page_grid.ets rename to ArkUIKit/NativeNodeBaseSample/entry/src/main/ets/pages/grid/PageGridNormal.ets index 91c26abb9ae..9247aacc07d 100644 --- a/ArkUIKit/NativeNodeBaseSample/entry/src/main/ets/pages/page_grid.ets +++ b/ArkUIKit/NativeNodeBaseSample/entry/src/main/ets/pages/grid/PageGridNormal.ets @@ -18,7 +18,7 @@ import { NodeContent } from '@kit.ArkUI'; @Entry @Component -struct Index { +struct GridNormal { private nodeContent = new NodeContent(); aboutToAppear() { // 通过C-API创建节点,并添加到管理器nodeContent上 diff --git a/ArkUIKit/NativeNodeBaseSample/entry/src/main/resources/base/profile/main_pages.json b/ArkUIKit/NativeNodeBaseSample/entry/src/main/resources/base/profile/main_pages.json index f465f6cd414..b8bb6974667 100644 --- a/ArkUIKit/NativeNodeBaseSample/entry/src/main/resources/base/profile/main_pages.json +++ b/ArkUIKit/NativeNodeBaseSample/entry/src/main/resources/base/profile/main_pages.json @@ -6,13 +6,16 @@ "pages/page_accessibility", "pages/page_embedded_component", "pages/page_waterflow", - "pages/page_grid", + "pages/PageGrid", "pages/page_scroll", "pages/page_refresh", "pages/page_xcomponent", "pages/page_list", "pages/page_form", "pages/page_public_event", - "pages/page_imagespan" + "pages/page_imagespan", + "pages/grid/PageGridIrregularIndexes", + "pages/grid/PageGridNormal", + "pages/grid/PageGridGetRectByIndex" ] } diff --git a/ArkUIKit/NativeNodeNapiSample/entry/src/main/ets/pages/PageGrid.ets b/ArkUIKit/NativeNodeNapiSample/entry/src/main/ets/pages/PageGrid.ets new file mode 100644 index 00000000000..be8cad60fc5 --- /dev/null +++ b/ArkUIKit/NativeNodeNapiSample/entry/src/main/ets/pages/PageGrid.ets @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License") + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { router } from '@kit.ArkUI'; + +interface ListCategories { + title: string, + url: string +} + +@Entry +@Component +struct MenuIndex { + private items: ListCategories[] = + [ + { title: '普通Grid', url: 'pages/grid/PageGridNormal' }, + { title: '固定行列Grid', url: 'pages/grid/PageGridGetRectByIndex' }, + { title: '可滚动Grid设置跨行跨列节点', url: 'pages/grid/PageGridIrregularIndexes' }, + ]; + + build() { + Scroll(new Scroller()) { + Column() { + Text('Grid选择页面') + .fontWeight(FontWeight.Bold) + .fontSize('20vp') + .textAlign(TextAlign.Center) + .height('5%') + .margin($r('sys.float.titlebar_title_margin_right')) + List() { + ForEach(this.items, (item: ListCategories) => { + ListItem() { + Row() { + Text(item.title) + .fontSize($r('sys.float.text_button_font_size')) + .fontColor(Color.Black) + .textAlign(TextAlign.Start) + .height('100%') + .width('50%') + .padding($r('sys.float.padding_level10')) + Text('>') + .fontSize('25vp') + .fontColor(Color.Black) + .textAlign(TextAlign.End) + .fontColor(Color.Gray) + .height('100%') + .width('50%') + .padding($r('sys.float.padding_level10')) + } + .width('100%') + .height('10%') + .borderRadius($r('sys.float.select_border_radius_default')) + .backgroundColor(Color.White) + .onClick(() => { + router.pushUrl({ url: item.url }) + }) + }.margin($r('sys.float.menu_item_content_align')) + }) + }.width('95%').height('90%').alignListItem(ListItemAlign.Center) + }.width('100%') + }.height('100%').backgroundColor($r('app.color.background_color')) + } +} \ No newline at end of file diff --git a/ArkUIKit/NativeNodeNapiSample/entry/src/main/ets/pages/grid/PageGridGetRectByIndex.ets b/ArkUIKit/NativeNodeNapiSample/entry/src/main/ets/pages/grid/PageGridGetRectByIndex.ets new file mode 100644 index 00000000000..7bda73e8c7b --- /dev/null +++ b/ArkUIKit/NativeNodeNapiSample/entry/src/main/ets/pages/grid/PageGridGetRectByIndex.ets @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License") + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import Napi from 'libentry.so'; +import { NodeContent } from '@kit.ArkUI'; + +@Entry +@Component +struct Index { + private nodeContent = new NodeContent(); + aboutToAppear() { + // 通过C-API创建节点,并添加到管理器nodeContent上 + Napi.createGridNativeNodeOnGetRectByIndex(this.nodeContent); + } + build() { + Column() { + ContentSlot(this.nodeContent) + } + .width('100%') + .height('100%') + } +} diff --git a/ArkUIKit/NativeNodeNapiSample/entry/src/main/ets/pages/grid/PageGridIrregularIndexes.ets b/ArkUIKit/NativeNodeNapiSample/entry/src/main/ets/pages/grid/PageGridIrregularIndexes.ets new file mode 100644 index 00000000000..d1280f828a2 --- /dev/null +++ b/ArkUIKit/NativeNodeNapiSample/entry/src/main/ets/pages/grid/PageGridIrregularIndexes.ets @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License") + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import Napi from 'libentry.so'; +import { NodeContent } from '@kit.ArkUI'; + +@Entry +@Component +struct Index { + private nodeContent = new NodeContent(); + aboutToAppear() { + // 通过C-API创建节点,并添加到管理器nodeContent上 + Napi.createGridNativeNodeIrregularIndexes(this.nodeContent); + } + build() { + Column() { + ContentSlot(this.nodeContent) + } + .width('100%') + .height('100%') + } +} diff --git a/ArkUIKit/NativeTypeSample/entry/src/main/ets/pages/page_grid.ets b/ArkUIKit/NativeNodeNapiSample/entry/src/main/ets/pages/grid/PageGridNormal.ets similarity index 98% rename from ArkUIKit/NativeTypeSample/entry/src/main/ets/pages/page_grid.ets rename to ArkUIKit/NativeNodeNapiSample/entry/src/main/ets/pages/grid/PageGridNormal.ets index 91c26abb9ae..9247aacc07d 100644 --- a/ArkUIKit/NativeTypeSample/entry/src/main/ets/pages/page_grid.ets +++ b/ArkUIKit/NativeNodeNapiSample/entry/src/main/ets/pages/grid/PageGridNormal.ets @@ -18,7 +18,7 @@ import { NodeContent } from '@kit.ArkUI'; @Entry @Component -struct Index { +struct GridNormal { private nodeContent = new NodeContent(); aboutToAppear() { // 通过C-API创建节点,并添加到管理器nodeContent上 diff --git a/ArkUIKit/NativeTypeSample/README.md b/ArkUIKit/NativeTypeSample/README.md index 977de00b478..85b350eeb61 100644 --- a/ArkUIKit/NativeTypeSample/README.md +++ b/ArkUIKit/NativeTypeSample/README.md @@ -53,6 +53,7 @@ 11. 点击Slider选择框进入Slider组件的CAPI接口展示界面; 12. 点击CheckboxShape选择框进入checkbox组件的CAPI接口展示界面; 13. 点击HoverModeAreaType选择框进入HoverModeArea组件的CAPI接口展示界面; +14. 点击Grid选择框进入Grid组件的CAPI选择界面; ## 工程目录 @@ -78,7 +79,12 @@ entry/src/main/ets/ ├── page_image.ets (图片页面) ├── page_image_animator.ets (图片帧页面) ├── page_text_picker.ets (文本选择器页面) - └── page_embedded_component.ets (嵌入式组件界面) + ├── page_embedded_component.ets (嵌入式组件界面) + ├── PageGrid.ets (Grid页面) + └── grid + ├── PageGridNormal.ets (普通Grid页面) + ├── PageGridIrregularIndexes.ets (可滚动Grid设置跨行跨列节点页面) + └── PageGridGetRectByIndex.ets (固定行列Grid页面) entry/src/main/ ├── cpp │ ├── types @@ -121,7 +127,13 @@ entry/src/main/ | ├── CheckboxShapeMaker.cpp │ ├── CheckboxShapeMaker.h | ├── HoverModeAreaTypeMaker.cpp -│ └── HoverModeAreaTypeMaker.h +│ ├── HoverModeAreaTypeMaker.h +│ ├── GridIrregularIndexesMaker.cpp +│ ├── GridIrregularIndexesMaker.h +│ ├── GridMaker.cpp +│ ├── GridMaker.h +│ ├── GridRectByIndexMaker.cpp +│ └── GridRectByIndexMaker.h └── resources ├── base │ ├── element @@ -145,6 +157,8 @@ entry/src/main/ 为图片组件,常用于在应用中显示图片。 6. [ImageAnimator组件](https://gitcode.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis-arkui/capi-native-node-h.md#arkui_nodetype) 该组件提供帧动画组件来实现逐帧播放图片的能力,可以配置需要播放的图片列表,每张图片可以配置时长。 +7. [Grid组件](https://gitcode.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis-arkui/capi-native-node-h.md#arkui_nodetype) + 为网格布局组件,用于在应用中创建网格布局。 ## 相关权限 diff --git a/ArkUIKit/NativeTypeSample/entry/src/main/cpp/GridIrregularIndexesMaker.cpp b/ArkUIKit/NativeTypeSample/entry/src/main/cpp/GridIrregularIndexesMaker.cpp new file mode 100644 index 00000000000..5f21ecaef01 --- /dev/null +++ b/ArkUIKit/NativeTypeSample/entry/src/main/cpp/GridIrregularIndexesMaker.cpp @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the License. + */ + +#include "GridIrregularIndexesMaker.h" + +#include +#include +#include +#include // snprintf +#include +#include +#include +#include +#include + +#include "ArkUINodeAdapter.h" +#include "ScrollableNode.h" + +namespace { +// ===== 布局与样式常量 ===== +constexpr char K_COLUMNS_TEMPLATE[] = "1fr 1fr 1fr 1fr 1fr"; +constexpr float K_WIDTH_PERCENT = 0.9f; +constexpr float K_COLUMNS_GAP = 10.0f; +constexpr float K_ROWS_GAP = 10.0f; +constexpr float K_HEIGHT = 300.0f; +constexpr float K_TEXT_SIZE = 16.0f; +constexpr float K_ITEM_HEIGHT = 80.0f; +constexpr float K_ITEM_WIDTH_PERCENT = 1.0f; +constexpr float K_NODE_FONT_SIZE = 16.0f; +constexpr uint32_t K_ITEM_BG_COLOR = 0xFFF9CF93U; +constexpr uint32_t K_BG_COLOR = 0xFFFAEEE0; +constexpr uint32_t K_TEXT_COLOR = 0xFFCCCCCC; +constexpr uint32_t NUMBER_0 = 0; +constexpr uint32_t NUMBER_2 = 2; +constexpr uint32_t NUMBER_5 = 5; +const std::string CONTENT = "scroll"; +} // namespace +std::shared_ptr GridIrregularIndexesMaker::layoutOptions1_; +std::shared_ptr GridIrregularIndexesMaker::layoutOptions2_; +// ---------- 配置 Grid 外观/交互 ---------- +static void ConfigureGrid(const std::shared_ptr& grid) +{ + grid->SetColumnsTemplate(K_COLUMNS_TEMPLATE); + grid->SetColumnsGap(K_COLUMNS_GAP); + grid->SetRowsGap(K_ROWS_GAP); + grid->SetScrollBar(ARKUI_SCROLL_BAR_DISPLAY_MODE_OFF); + grid->SetWidthPercent(K_WIDTH_PERCENT); + grid->SetHeight(K_HEIGHT); + grid->SetBackgroundColor(K_BG_COLOR); +} + +static std::vector BuildData() +{ + std::vector data; + for (size_t i = NUMBER_0; i < NUMBER_5; i++) { + for (size_t j = NUMBER_0; j < NUMBER_5; j++) { + data.emplace_back(std::to_string(j)); + } + } + return data; +} + +// ---------- 适配器回调(创建/绑定) ---------- +static ArkUI_NodeHandle GridCreateItem(ArkUI_NativeNodeAPI_1* api) +{ + ArkUI_NodeHandle text = api->createNode(ARKUI_NODE_TEXT); + ArkUI_NodeHandle item = api->createNode(ARKUI_NODE_GRID_ITEM); + api->addChild(item, text); + return item; +} + +static void GridBindItem(ArkUI_NativeNodeAPI_1* api, ArkUI_NodeHandle item, int32_t index, + const std::shared_ptr>& data) +{ + SetAttributeFloat32(api, item, NODE_FONT_SIZE, K_NODE_FONT_SIZE); + SetAttributeUInt32(api, item, NODE_BACKGROUND_COLOR, K_ITEM_BG_COLOR); + SetAttributeFloat32(api, item, NODE_HEIGHT, K_ITEM_HEIGHT); + SetAttributeUInt32(api, item, NODE_TEXT_ALIGN, ARKUI_TEXT_ALIGNMENT_CENTER); + SetAttributeFloat32(api, item, NODE_WIDTH_PERCENT, K_ITEM_WIDTH_PERCENT); + + ArkUI_NodeHandle text = api->getFirstChild(item); + if (!text) { + return; + } + + const int32_t n = static_cast(data->size()); + const char* s = (index >= 0 && index < n) ? (*data)[static_cast(index)].c_str() : ""; + SetTextContent(api, text, s); +} + +// ---------- 构建 Adapter ---------- +static std::shared_ptr MakeGridAdapter(const std::shared_ptr>& data) +{ + auto adapter = std::make_shared(); + adapter->EnsurePlaceholderTypeOr(static_cast(ARKUI_NODE_GRID_ITEM)); + + ArkUINodeAdapter::Callbacks cb {}; + cb.getTotalCount = [data]() -> int32_t { return static_cast(data->size()); }; + cb.getStableId = [data](int32_t i) -> uint64_t { + const int32_t n = static_cast(data->size()); + if (i >= 0 && i < n) { + return static_cast(std::hash {}((*data)[static_cast(i)])); + } + return static_cast(i); + }; + cb.onCreate = [](ArkUI_NativeNodeAPI_1* api, int32_t /*index*/) -> ArkUI_NodeHandle { return GridCreateItem(api); }; + cb.onBind = [data](ArkUI_NativeNodeAPI_1* api, ArkUI_NodeHandle item, int32_t index) { + GridBindItem(api, item, index, data); + }; + + adapter->SetCallbacks(cb); + return adapter; +} + +std::shared_ptr GridIrregularIndexesMaker::BuildGrid1() +{ + auto grid = std::make_shared(); + ConfigureGrid(grid); + auto data = std::make_shared>(BuildData()); + auto adapter = MakeGridAdapter(data); + grid->SetLazyAdapter(adapter); + adapter->ReloadAllItems(); + + uint32_t irregularIndexes[] = { 0, 6 }; + OH_ArkUI_GridLayoutOptions_SetIrregularIndexes(layoutOptions1_->GetLayoutOptions(), irregularIndexes, NUMBER_2); + grid->SetLayoutOptions(layoutOptions1_->GetLayoutOptions()); + GetKeepAliveContainer().emplace_back(grid); + return grid; +} + +// ---------- 构建指定GridItemRect Grid ---------- +std::shared_ptr GridIrregularIndexesMaker::BuildGrid2() +{ + auto grid = std::make_shared(); + ConfigureGrid(grid); + + auto data = std::make_shared>(BuildData()); + auto adapter = MakeGridAdapter(data); + grid->SetLazyAdapter(adapter); + adapter->ReloadAllItems(); + + uint32_t irregularIndexes[] = { 0, 7 }; + OH_ArkUI_GridLayoutOptions_SetIrregularIndexes(layoutOptions2_->GetLayoutOptions(), irregularIndexes, NUMBER_2); + OH_ArkUI_GridLayoutOptions_RegisterGetIrregularSizeByIndexCallback( + layoutOptions2_->GetLayoutOptions(), nullptr, [](int32_t itemIndex, void* userData) -> ArkUI_GridItemSize { + if (itemIndex == 0) { + return { 1, 5 }; + } + return { 1, static_cast(itemIndex % 6 + 1) }; + }); + grid->SetLayoutOptions(layoutOptions2_->GetLayoutOptions()); + GetKeepAliveContainer().emplace_back(grid); + return grid; +} + +// ---------- 构建 Text ---------- +static std::shared_ptr BuildText( + ArkUI_NativeNodeAPI_1* api, const std::string& content, uint32_t fontColor, float fontSize) +{ + ArkUI_NodeHandle textNode = api->createNode(ARKUI_NODE_TEXT); + SetTextContent(api, textNode, content.c_str()); + SetAttributeFloat32(api, textNode, NODE_FONT_SIZE, fontSize); + SetAttributeUInt32(api, textNode, NODE_FONT_COLOR, fontColor); + return std::make_shared(textNode); +} + +ArkUI_NodeHandle GridIrregularIndexesMaker::CreateNativeNode() +{ + ArkUI_NativeNodeAPI_1* api = nullptr; + OH_ArkUI_GetModuleInterface(ARKUI_NATIVE_NODE, ArkUI_NativeNodeAPI_1, api); + if (api == nullptr) { + return nullptr; + } + + // 根容器全屏 + ArkUI_NodeHandle page = api->createNode(ARKUI_NODE_COLUMN); + if (page == nullptr) { + return nullptr; + } + SetAttributeFloat32(api, page, NODE_WIDTH_PERCENT, 1.0f); + SetAttributeFloat32(api, page, NODE_HEIGHT_PERCENT, 1.0f); + + // 构建 Grid + std::shared_ptr grid = BuildGrid1(); + if (grid && grid->GetHandle() != nullptr) { + api->addChild(page, grid->GetHandle()); + } + + // 构建Text + std::shared_ptr text = BuildText(api, CONTENT, K_TEXT_COLOR, K_TEXT_SIZE); + if (text) { + api->addChild(page, *text); + } + + // 构建不规则Grid + std::shared_ptr grid2 = BuildGrid2(); + if (grid2 && grid2->GetHandle() != nullptr) { + api->addChild(page, grid2->GetHandle()); + } + return page; +} \ No newline at end of file diff --git a/ArkUIKit/NativeTypeSample/entry/src/main/cpp/GridIrregularIndexesMaker.h b/ArkUIKit/NativeTypeSample/entry/src/main/cpp/GridIrregularIndexesMaker.h new file mode 100644 index 00000000000..d889fb27d35 --- /dev/null +++ b/ArkUIKit/NativeTypeSample/entry/src/main/cpp/GridIrregularIndexesMaker.h @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef GRID_IRREGULAR_INDEXES_NODE_H +#define GRID_IRREGULAR_INDEXES_NODE_H + +#include +#include + +#include "ArkUINodeAdapter.h" +#include "GridLayoutOptions.h" +#include "ScrollableEvent.h" +#include "ScrollableNode.h" +#include "ScrollableUtils.h" + +class GridIrregularIndexesMaker : public BaseNode { +public: + struct GridParam {}; + static ArkUI_NodeHandle CreateNativeNode(); + + GridIrregularIndexesMaker() + : BaseNode(NodeApiInstance::GetInstance()->GetNativeNodeAPI()->createNode(ARKUI_NODE_GRID)), + nodeApi_(NodeApiInstance::GetInstance()->GetNativeNodeAPI()) + { + if (!IsNotNull(nodeApi_) || !IsNotNull(GetHandle())) { + return; + } + + nodeApi_->addNodeEventReceiver(GetHandle(), StaticEventReceiver); + scrollEventGuard_.Bind(nodeApi_, GetHandle(), this, SCROLL_EVT_ALL); + layoutOptions1_ = std::make_shared(); + layoutOptions2_ = std::make_shared(); + } + + ~GridIrregularIndexesMaker() override + { + scrollEventGuard_.Release(); + nodeAdapter_.reset(); + layoutOptions1_ = nullptr; + layoutOptions2_ = nullptr; + } + + // ======================================== + // 模板和间距设置 + // ======================================== + void SetRowsTemplate(const char* rowsTemplate) + { + SetAttributeString(nodeApi_, GetHandle(), NODE_GRID_ROW_TEMPLATE, rowsTemplate); + } + + void SetColumnsTemplate(const char* columnsTemplate) + { + SetAttributeString(nodeApi_, GetHandle(), NODE_GRID_COLUMN_TEMPLATE, columnsTemplate); + } + + void SetColumnsGap(float gap) + { + SetAttributeFloat32(nodeApi_, GetHandle(), NODE_GRID_COLUMN_GAP, gap); + } + + void SetRowsGap(float gap) + { + SetAttributeFloat32(nodeApi_, GetHandle(), NODE_GRID_ROW_GAP, gap); + } + + void SetScrollBar(int32_t displayMode) + { + SetAttributeFloat32(nodeApi_, GetHandle(), NODE_SCROLL_BAR_DISPLAY_MODE, displayMode); + } + // ======================================== + // 适配器设置 + // ======================================== + void SetLazyAdapter(const std::shared_ptr& adapter) + { + if (!IsNotNull(adapter)) { + return; + } + ArkUI_AttributeItem item { nullptr, 0, nullptr, adapter->GetAdapter() }; + nodeApi_->setAttribute(GetHandle(), NODE_GRID_NODE_ADAPTER, &item); + nodeAdapter_ = adapter; + } + + // ======================================== + // 设置属性 + // ======================================== + void SetLayoutOptions(ArkUI_GridLayoutOptions* layoutOptions) + { + if (layoutOptions == nullptr) { + return; + } + + ArkUI_AttributeItem item = { .object = layoutOptions }; + nodeApi_->setAttribute(GetHandle(), NODE_GRID_LAYOUT_OPTIONS, &item); + } + +protected: + void OnNodeEvent(ArkUI_NodeEvent* event) override + { + BaseNode::OnNodeEvent(event); + } + +private: + static std::shared_ptr BuildGrid1(); + static std::shared_ptr BuildGrid2(); + ArkUI_NativeNodeAPI_1* nodeApi_ = nullptr; + std::shared_ptr nodeAdapter_; + ScrollEventGuard scrollEventGuard_; + static std::shared_ptr layoutOptions1_; + static std::shared_ptr layoutOptions2_; +}; + +#endif // GRID_IRREGULAR_INDEXES_NODE_H diff --git a/ArkUIKit/NativeTypeSample/entry/src/main/cpp/GridLayoutOptions.h b/ArkUIKit/NativeTypeSample/entry/src/main/cpp/GridLayoutOptions.h new file mode 100644 index 00000000000..648060f792d --- /dev/null +++ b/ArkUIKit/NativeTypeSample/entry/src/main/cpp/GridLayoutOptions.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License") + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef GRIDLAYOUTOPTIONS_H +#define GRIDLAYOUTOPTIONS_H + +#include +class GridLayoutOptions { +public: + GridLayoutOptions() : layoutOptions_(OH_ArkUI_GridLayoutOptions_Create()) {} + ~GridLayoutOptions() + { + OH_ArkUI_GridLayoutOptions_Dispose(layoutOptions_); + layoutOptions_ = nullptr; + } + + ArkUI_GridLayoutOptions* GetLayoutOptions() const + { + return layoutOptions_; + } + +private: + ArkUI_GridLayoutOptions* layoutOptions_ = nullptr; +}; +#endif // GRIDLAYOUTOPTIONS_H diff --git a/ArkUIKit/NativeTypeSample/entry/src/main/cpp/GridRectByIndexMaker.cpp b/ArkUIKit/NativeTypeSample/entry/src/main/cpp/GridRectByIndexMaker.cpp new file mode 100644 index 00000000000..2749f102384 --- /dev/null +++ b/ArkUIKit/NativeTypeSample/entry/src/main/cpp/GridRectByIndexMaker.cpp @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the License. + */ + +#include "GridRectByIndexMaker.h" + +#include +#include +#include +#include // snprintf +#include +#include +#include +#include +#include + +#include "ArkUINodeAdapter.h" +#include "ScrollableNode.h" + +namespace { +// ===== 布局与样式常量 ===== +constexpr char K_ROWS_TEMPLATE[] = "1fr 1fr 1fr 1fr 1fr"; +constexpr char K_COLUMNS_TEMPLATE[] = "1fr 1fr 1fr 1fr 1fr"; +constexpr char K_ROWS_TEMPLATE_RECT_BY_INDEX[] = "1fr 1fr 1fr 1fr 1fr 1fr"; +constexpr char K_COLUMNS_TEMPLATE_RECT_BY_INDEX[] = "1fr 1fr 1fr 1fr 1fr 1fr"; +constexpr float K_WIDTH_PERCENT = 0.9f; +constexpr float K_COLUMNS_GAP = 10.0f; +constexpr float K_ROWS_GAP = 10.0f; +constexpr float K_HEIGHT = 300.0f; +constexpr uint32_t K_ITEM_BG_COLOR = 0xFFF9CF93U; +constexpr uint32_t K_BG_COLOR = 0xFFFAEEE0; +constexpr uint32_t K_TEXT_COLOR = 0xFFCCCCCC; +constexpr float K_TEXT_SIZE = 16.0f; +constexpr float K_ITEM_HEIGHT_PERCENT = 1.0f; +constexpr float K_ITEM_WIDTH_PERCENT = 1.0f; +constexpr float K_NODE_FONT_SIZE = 16.0f; +constexpr unsigned int K_LOG_PRINT_DOMAIN = 0xFF00; +constexpr int K_GRID_INDEX_WIDTH = 2; +constexpr uint32_t NUMBER_0 = 0; +constexpr uint32_t NUMBER_1 = 1; +constexpr uint32_t NUMBER_2 = 2; +constexpr uint32_t NUMBER_3 = 3; +constexpr uint32_t NUMBER_4 = 4; +constexpr uint32_t NUMBER_5 = 5; +constexpr uint32_t NUMBER_6 = 6; +const std::vector NUMBERS_1 = { "0", "1", "2", "3", "4" }; +const std::vector NUMBERS_2 = { "0", "1", "2", "3", "4", "5" }; +const std::string CONTENT = "GridLayoutOptions的使用:onGetRectByIndex。"; + +} // namespace +std::shared_ptr GridRectByIndexMaker::layoutOptions_; + +static std::shared_ptr CreateGridItem(ArkUI_NativeNodeAPI_1* api, const std::string& content) +{ + ArkUI_NodeHandle text = api->createNode(ARKUI_NODE_TEXT); + ArkUI_NodeHandle item = api->createNode(ARKUI_NODE_GRID_ITEM); + SetAttributeUInt32(api, text, NODE_TEXT_ALIGN, ARKUI_TEXT_ALIGNMENT_CENTER); + SetAttributeUInt32(api, text, NODE_BACKGROUND_COLOR, K_ITEM_BG_COLOR); + SetAttributeFloat32(api, text, NODE_HEIGHT_PERCENT, K_ITEM_HEIGHT_PERCENT); + SetAttributeFloat32(api, text, NODE_WIDTH_PERCENT, K_ITEM_WIDTH_PERCENT); + SetAttributeFloat32(api, text, NODE_FONT_SIZE, K_NODE_FONT_SIZE); + SetTextContent(api, text, content.c_str()); + api->addChild(item, text); + return std::make_shared(item); +} + +// ---------- 整体构建普通Grid ---------- +static std::shared_ptr BuildGrid() +{ + ArkUI_NativeNodeAPI_1* nodeAPI = nullptr; + OH_ArkUI_GetModuleInterface(ARKUI_NATIVE_NODE, ArkUI_NativeNodeAPI_1, nodeAPI); + + auto grid = std::make_shared(); + grid->SetWidthPercent(K_WIDTH_PERCENT); + grid->SetHeight(K_HEIGHT); + grid->SetColumnsTemplate(K_COLUMNS_TEMPLATE); + grid->SetRowsTemplate(K_ROWS_TEMPLATE); + grid->SetColumnsGap(K_COLUMNS_GAP); + grid->SetRowsGap(K_ROWS_GAP); + grid->SetBackgroundColor(K_BG_COLOR); + + for (auto i = 0; i < NUMBERS_1.size(); i++) { + for (auto j = 0; j < NUMBERS_1.size(); j++) { + auto gridItem = CreateGridItem(nodeAPI, std::to_string(i)); + nodeAPI->addChild(grid->GetHandle(), *gridItem); + } + } + + GetKeepAliveContainer().emplace_back(grid); + return grid; +} + +// ---------- 构建指定GridItemRect Grid ---------- +std::shared_ptr GridRectByIndexMaker::BuildGridRectByIndex() +{ + ArkUI_NativeNodeAPI_1* nodeAPI = nullptr; + OH_ArkUI_GetModuleInterface(ARKUI_NATIVE_NODE, ArkUI_NativeNodeAPI_1, nodeAPI); + auto grid = std::make_shared(); + grid->SetWidthPercent(K_WIDTH_PERCENT); + grid->SetHeight(K_HEIGHT); + grid->SetColumnsTemplate(K_COLUMNS_TEMPLATE_RECT_BY_INDEX); + grid->SetRowsTemplate(K_ROWS_TEMPLATE_RECT_BY_INDEX); + grid->SetColumnsGap(K_COLUMNS_GAP); + grid->SetRowsGap(K_ROWS_GAP); + + for (auto i = 0; i < NUMBERS_2.size(); i++) { + auto gridItem = CreateGridItem(nodeAPI, std::to_string(i)); + nodeAPI->addChild(grid->GetHandle(), *gridItem); + } + + OH_ArkUI_GridLayoutOptions_RegisterGetRectByIndexCallback( + layoutOptions_->GetLayoutOptions(), nullptr, [](int32_t itemIndex, void* userData) -> ArkUI_GridItemRect { + if (itemIndex == NUMBER_0) { + return ArkUI_GridItemRect { 0, 0, 1, 1 }; + } else if (itemIndex == NUMBER_1) { + return ArkUI_GridItemRect { 0, 1, 2, 2 }; + } else if (itemIndex == NUMBER_2) { + return ArkUI_GridItemRect { 0, 3, 3, 3 }; + } else if (itemIndex == NUMBER_3) { + return ArkUI_GridItemRect { 3, 0, 3, 3 }; + } else if (itemIndex == NUMBER_4) { + return ArkUI_GridItemRect { 4, 3, 2, 2 }; + } else { + return ArkUI_GridItemRect { 5, 5, 1, 1 }; + } + }); + grid->SetLayoutOptions(layoutOptions_->GetLayoutOptions()); + GetKeepAliveContainer().emplace_back(grid); + return grid; +} + +// ---------- 构建 Text ---------- +static std::shared_ptr BuildText( + ArkUI_NativeNodeAPI_1* api, const std::string& content, uint32_t fontColor, float fontSize) +{ + ArkUI_NodeHandle textNode = api->createNode(ARKUI_NODE_TEXT); + SetTextContent(api, textNode, content.c_str()); + SetAttributeFloat32(api, textNode, NODE_FONT_SIZE, fontSize); + SetAttributeUInt32(api, textNode, NODE_FONT_COLOR, fontColor); + return std::make_shared(textNode); +} + +ArkUI_NodeHandle GridRectByIndexMaker::CreateNativeNode() +{ + ArkUI_NativeNodeAPI_1* api = nullptr; + OH_ArkUI_GetModuleInterface(ARKUI_NATIVE_NODE, ArkUI_NativeNodeAPI_1, api); + if (api == nullptr) { + return nullptr; + } + + // 根容器全屏 + ArkUI_NodeHandle page = api->createNode(ARKUI_NODE_COLUMN); + if (page == nullptr) { + return nullptr; + } + SetAttributeFloat32(api, page, NODE_WIDTH_PERCENT, 1.0f); + SetAttributeFloat32(api, page, NODE_HEIGHT_PERCENT, 1.0f); + + // 构建 Grid + std::shared_ptr grid = BuildGrid(); + if (grid && grid->GetHandle() != nullptr) { + api->addChild(page, grid->GetHandle()); + } + + // 构建Text + std::shared_ptr text = BuildText(api, CONTENT, K_TEXT_COLOR, K_TEXT_SIZE); + if (text) { + api->addChild(page, *text); + } + + // 构建不规则Grid + std::shared_ptr grid2 = BuildGridRectByIndex(); + if (grid2 && grid2->GetHandle() != nullptr) { + api->addChild(page, grid2->GetHandle()); + } + return page; +} \ No newline at end of file diff --git a/ArkUIKit/NativeTypeSample/entry/src/main/cpp/GridRectByIndexMaker.h b/ArkUIKit/NativeTypeSample/entry/src/main/cpp/GridRectByIndexMaker.h new file mode 100644 index 00000000000..2668292f50a --- /dev/null +++ b/ArkUIKit/NativeTypeSample/entry/src/main/cpp/GridRectByIndexMaker.h @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef GRID_RECT_BY_INDEX_NODE_H +#define GRID_RECT_BY_INDEX_NODE_H + +#include + +#include "ArkUINodeAdapter.h" +#include "GridLayoutOptions.h" +#include "ScrollableEvent.h" +#include "ScrollableNode.h" +#include "ScrollableUtils.h" + +class GridRectByIndexMaker : public BaseNode { +public: + static ArkUI_NodeHandle CreateNativeNode(); + + GridRectByIndexMaker() + : BaseNode(NodeApiInstance::GetInstance()->GetNativeNodeAPI()->createNode(ARKUI_NODE_GRID)), + nodeApi_(NodeApiInstance::GetInstance()->GetNativeNodeAPI()) + { + if (!IsNotNull(nodeApi_) || !IsNotNull(GetHandle())) { + return; + } + + nodeApi_->addNodeEventReceiver(GetHandle(), StaticEventReceiver); + scrollEventGuard_.Bind(nodeApi_, GetHandle(), this, SCROLL_EVT_ALL); + layoutOptions_ = std::make_shared(); + } + + ~GridRectByIndexMaker() override + { + scrollEventGuard_.Release(); + nodeAdapter_.reset(); + layoutOptions_ = nullptr; + } + + // ======================================== + // 模板和间距设置 + // ======================================== + void SetRowsTemplate(const char* rowsTemplate) + { + SetAttributeString(nodeApi_, GetHandle(), NODE_GRID_ROW_TEMPLATE, rowsTemplate); + } + + void SetColumnsTemplate(const char* columnsTemplate) + { + SetAttributeString(nodeApi_, GetHandle(), NODE_GRID_COLUMN_TEMPLATE, columnsTemplate); + } + + void SetColumnsGap(float gap) + { + SetAttributeFloat32(nodeApi_, GetHandle(), NODE_GRID_COLUMN_GAP, gap); + } + + void SetRowsGap(float gap) + { + SetAttributeFloat32(nodeApi_, GetHandle(), NODE_GRID_ROW_GAP, gap); + } + + // ======================================== + // 适配器设置 + // ======================================== + void SetLazyAdapter(const std::shared_ptr& adapter) + { + if (!IsNotNull(adapter)) { + return; + } + ArkUI_AttributeItem item { nullptr, 0, nullptr, adapter->GetAdapter() }; + nodeApi_->setAttribute(GetHandle(), NODE_GRID_NODE_ADAPTER, &item); + nodeAdapter_ = adapter; + } + + // ======================================== + // 设置属性 + // ======================================== + void SetLayoutOptions(ArkUI_GridLayoutOptions* layoutOptions) + { + if (layoutOptions == nullptr) { + return; + } + + ArkUI_AttributeItem item = { .object = layoutOptions }; + nodeApi_->setAttribute(GetHandle(), NODE_GRID_LAYOUT_OPTIONS, &item); + } + +protected: + void OnNodeEvent(ArkUI_NodeEvent* event) override + { + BaseNode::OnNodeEvent(event); + } + +private: + static std::shared_ptr BuildGridRectByIndex(); + ArkUI_NativeNodeAPI_1* nodeApi_ = nullptr; + std::shared_ptr nodeAdapter_; + ScrollEventGuard scrollEventGuard_; + static std::shared_ptr layoutOptions_; +}; + +#endif // GRID_RECT_BY_INDEX_NODE_H diff --git a/ArkUIKit/NativeTypeSample/entry/src/main/cpp/manager.cpp b/ArkUIKit/NativeTypeSample/entry/src/main/cpp/manager.cpp index 0b00be632b2..8db754b3344 100644 --- a/ArkUIKit/NativeTypeSample/entry/src/main/cpp/manager.cpp +++ b/ArkUIKit/NativeTypeSample/entry/src/main/cpp/manager.cpp @@ -18,7 +18,9 @@ #include "ArkUIVisualEffectsNode.h" #include "ButtonMaker.h" #include "SliderMaker.h" +#include "GridIrregularIndexesMaker.h" #include "GridMaker.h" +#include "GridRectByIndexMaker.h" #include "ListMaker.h" #include "RefreshMaker.h" #include "ScrollMaker.h" @@ -350,6 +352,60 @@ napi_value Manager::CreateGridNativeNode(napi_env env, napi_callback_info info) return nullptr; } +napi_value Manager::CreateGridNativeNodeOnGetRectByIndex(napi_env env, napi_callback_info info) +{ + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Manager", "CreateNativeNode BEGIN"); + if ((env == nullptr) || (info == nullptr)) { + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Manager", "CreateNativeNode env or info is null"); + return nullptr; + } + size_t argCnt = ConstIde::NUMBER_1; + napi_value args[ConstIde::NUMBER_1] = {nullptr}; + if (napi_get_cb_info(env, info, &argCnt, args, nullptr, nullptr) != napi_ok) { + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Manager", "CreateNativeNode napi_get_cb_info failed"); + } + + ArkUI_NodeContentHandle nodeContentHandle = nullptr; + + OH_ArkUI_GetNodeContentFromNapiValue(env, args[ConstIde::NUMBER_0], &nodeContentHandle); + + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Manager", "OH_ArkUI_GetBasicNodeAPI after"); + if (nodeAPI_ != nullptr) { + if (nodeAPI_->createNode != nullptr && nodeAPI_->addChild != nullptr) { + ArkUI_NodeHandle testNode = GridRectByIndexMaker::CreateNativeNode(); + OH_ArkUI_NodeContent_AddNode(nodeContentHandle, testNode); + } + } + return nullptr; +} + +napi_value Manager::CreateGridNativeNodeIrregularIndexes(napi_env env, napi_callback_info info) +{ + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Manager", "CreateNativeNode BEGIN"); + if ((env == nullptr) || (info == nullptr)) { + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Manager", "CreateNativeNode env or info is null"); + return nullptr; + } + size_t argCnt = ConstIde::NUMBER_1; + napi_value args[ConstIde::NUMBER_1] = {nullptr}; + if (napi_get_cb_info(env, info, &argCnt, args, nullptr, nullptr) != napi_ok) { + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Manager", "CreateNativeNode napi_get_cb_info failed"); + } + + ArkUI_NodeContentHandle nodeContentHandle = nullptr; + + OH_ArkUI_GetNodeContentFromNapiValue(env, args[ConstIde::NUMBER_0], &nodeContentHandle); + + OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Manager", "OH_ArkUI_GetBasicNodeAPI after"); + if (nodeAPI_ != nullptr) { + if (nodeAPI_->createNode != nullptr && nodeAPI_->addChild != nullptr) { + ArkUI_NodeHandle testNode = GridIrregularIndexesMaker::CreateNativeNode(); + OH_ArkUI_NodeContent_AddNode(nodeContentHandle, testNode); + } + } + return nullptr; +} + napi_value Manager::CreateScrollNativeNode(napi_env env, napi_callback_info info) { OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Manager", "CreateNativeNode BEGIN"); diff --git a/ArkUIKit/NativeTypeSample/entry/src/main/cpp/manager.h b/ArkUIKit/NativeTypeSample/entry/src/main/cpp/manager.h index 8620b36d23d..0853b1e3945 100644 --- a/ArkUIKit/NativeTypeSample/entry/src/main/cpp/manager.h +++ b/ArkUIKit/NativeTypeSample/entry/src/main/cpp/manager.h @@ -71,6 +71,8 @@ public: static napi_value CreateNativeEmbeddedComponentNode(napi_env env, napi_callback_info info); static napi_value CreateWaterFlowNativeNode(napi_env env, napi_callback_info info); static napi_value CreateGridNativeNode(napi_env env, napi_callback_info info); + static napi_value CreateGridNativeNodeOnGetRectByIndex(napi_env env, napi_callback_info info); + static napi_value CreateGridNativeNodeIrregularIndexes(napi_env env, napi_callback_info info); static napi_value CreateScrollNativeNode(napi_env env, napi_callback_info info); static napi_value CreateRefreshNativeNode(napi_env env, napi_callback_info info); static napi_value CreateListNativeNode(napi_env env, napi_callback_info info); diff --git a/ArkUIKit/NativeTypeSample/entry/src/main/cpp/napi_init.cpp b/ArkUIKit/NativeTypeSample/entry/src/main/cpp/napi_init.cpp index c2341b5738a..805a004f594 100644 --- a/ArkUIKit/NativeTypeSample/entry/src/main/cpp/napi_init.cpp +++ b/ArkUIKit/NativeTypeSample/entry/src/main/cpp/napi_init.cpp @@ -267,6 +267,10 @@ static napi_value Init(napi_env env, napi_value exports) napi_default, nullptr}, {"createGridNativeNode", nullptr, Manager::CreateGridNativeNode, nullptr, nullptr, nullptr, napi_default, nullptr}, + {"createGridNativeNodeOnGetRectByIndex", nullptr, Manager::CreateGridNativeNodeOnGetRectByIndex, nullptr, + nullptr, nullptr, napi_default, nullptr }, + {"createGridNativeNodeIrregularIndexes", nullptr, Manager::CreateGridNativeNodeIrregularIndexes, nullptr, + nullptr, nullptr, napi_default, nullptr }, {"createScrollNativeNode", nullptr, Manager::CreateScrollNativeNode, nullptr, nullptr, nullptr, napi_default, nullptr}, {"createRefreshNativeNode", nullptr, Manager::CreateRefreshNativeNode, nullptr, nullptr, nullptr, napi_default, diff --git a/ArkUIKit/NativeTypeSample/entry/src/main/cpp/types/libentry/Index.d.ts b/ArkUIKit/NativeTypeSample/entry/src/main/cpp/types/libentry/Index.d.ts index a9d44283f23..abebd3f579c 100644 --- a/ArkUIKit/NativeTypeSample/entry/src/main/cpp/types/libentry/Index.d.ts +++ b/ArkUIKit/NativeTypeSample/entry/src/main/cpp/types/libentry/Index.d.ts @@ -55,4 +55,6 @@ export const getProgressLinearStyleOptionAndDestroy: () =>string; export const getImageAnimatorFrameInfo: () =>string; export const setContentHandle: (content: Object) =>void; export const setUpTextCrossLanguage: (isCross: boolean) =>void; -export const clearNodes: () =>void; \ No newline at end of file +export const clearNodes: () =>void; +export const createGridNativeNodeOnGetRectByIndex: (content: Object) => void; +export const createGridNativeNodeIrregularIndexes: (content: Object) => void; \ No newline at end of file diff --git a/ArkUIKit/NativeTypeSample/entry/src/main/ets/pages/Index.ets b/ArkUIKit/NativeTypeSample/entry/src/main/ets/pages/Index.ets index 8389e634a2d..57e521b3a54 100644 --- a/ArkUIKit/NativeTypeSample/entry/src/main/ets/pages/Index.ets +++ b/ArkUIKit/NativeTypeSample/entry/src/main/ets/pages/Index.ets @@ -32,7 +32,7 @@ struct MenuIndex { { title: 'accessibility', url: 'pages/page_accessibility' }, { title: 'embedded component', url: 'pages/page_embedded_component' }, { title: 'WaterFlow', url: 'pages/page_waterflow' }, - { title: 'Grid', url: 'pages/page_grid' }, + { title: 'Grid', url: 'pages/PageGrid' }, { title: 'Scroll', url: 'pages/page_scroll' }, { title: 'Refresh', url: 'pages/page_refresh' }, { title: 'List', url: 'pages/page_list' }, diff --git a/ArkUIKit/NativeTypeSample/entry/src/main/ets/pages/PageGrid.ets b/ArkUIKit/NativeTypeSample/entry/src/main/ets/pages/PageGrid.ets new file mode 100644 index 00000000000..be8cad60fc5 --- /dev/null +++ b/ArkUIKit/NativeTypeSample/entry/src/main/ets/pages/PageGrid.ets @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License") + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { router } from '@kit.ArkUI'; + +interface ListCategories { + title: string, + url: string +} + +@Entry +@Component +struct MenuIndex { + private items: ListCategories[] = + [ + { title: '普通Grid', url: 'pages/grid/PageGridNormal' }, + { title: '固定行列Grid', url: 'pages/grid/PageGridGetRectByIndex' }, + { title: '可滚动Grid设置跨行跨列节点', url: 'pages/grid/PageGridIrregularIndexes' }, + ]; + + build() { + Scroll(new Scroller()) { + Column() { + Text('Grid选择页面') + .fontWeight(FontWeight.Bold) + .fontSize('20vp') + .textAlign(TextAlign.Center) + .height('5%') + .margin($r('sys.float.titlebar_title_margin_right')) + List() { + ForEach(this.items, (item: ListCategories) => { + ListItem() { + Row() { + Text(item.title) + .fontSize($r('sys.float.text_button_font_size')) + .fontColor(Color.Black) + .textAlign(TextAlign.Start) + .height('100%') + .width('50%') + .padding($r('sys.float.padding_level10')) + Text('>') + .fontSize('25vp') + .fontColor(Color.Black) + .textAlign(TextAlign.End) + .fontColor(Color.Gray) + .height('100%') + .width('50%') + .padding($r('sys.float.padding_level10')) + } + .width('100%') + .height('10%') + .borderRadius($r('sys.float.select_border_radius_default')) + .backgroundColor(Color.White) + .onClick(() => { + router.pushUrl({ url: item.url }) + }) + }.margin($r('sys.float.menu_item_content_align')) + }) + }.width('95%').height('90%').alignListItem(ListItemAlign.Center) + }.width('100%') + }.height('100%').backgroundColor($r('app.color.background_color')) + } +} \ No newline at end of file diff --git a/ArkUIKit/NativeTypeSample/entry/src/main/ets/pages/grid/PageGridGetRectByIndex.ets b/ArkUIKit/NativeTypeSample/entry/src/main/ets/pages/grid/PageGridGetRectByIndex.ets new file mode 100644 index 00000000000..7bda73e8c7b --- /dev/null +++ b/ArkUIKit/NativeTypeSample/entry/src/main/ets/pages/grid/PageGridGetRectByIndex.ets @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License") + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import Napi from 'libentry.so'; +import { NodeContent } from '@kit.ArkUI'; + +@Entry +@Component +struct Index { + private nodeContent = new NodeContent(); + aboutToAppear() { + // 通过C-API创建节点,并添加到管理器nodeContent上 + Napi.createGridNativeNodeOnGetRectByIndex(this.nodeContent); + } + build() { + Column() { + ContentSlot(this.nodeContent) + } + .width('100%') + .height('100%') + } +} diff --git a/ArkUIKit/NativeTypeSample/entry/src/main/ets/pages/grid/PageGridIrregularIndexes.ets b/ArkUIKit/NativeTypeSample/entry/src/main/ets/pages/grid/PageGridIrregularIndexes.ets new file mode 100644 index 00000000000..d1280f828a2 --- /dev/null +++ b/ArkUIKit/NativeTypeSample/entry/src/main/ets/pages/grid/PageGridIrregularIndexes.ets @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License") + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import Napi from 'libentry.so'; +import { NodeContent } from '@kit.ArkUI'; + +@Entry +@Component +struct Index { + private nodeContent = new NodeContent(); + aboutToAppear() { + // 通过C-API创建节点,并添加到管理器nodeContent上 + Napi.createGridNativeNodeIrregularIndexes(this.nodeContent); + } + build() { + Column() { + ContentSlot(this.nodeContent) + } + .width('100%') + .height('100%') + } +} diff --git a/ArkUIKit/NativeTypeSample/entry/src/main/ets/pages/grid/PageGridNormal.ets b/ArkUIKit/NativeTypeSample/entry/src/main/ets/pages/grid/PageGridNormal.ets new file mode 100644 index 00000000000..9247aacc07d --- /dev/null +++ b/ArkUIKit/NativeTypeSample/entry/src/main/ets/pages/grid/PageGridNormal.ets @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License") + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import Napi from 'libentry.so'; +import { NodeContent } from '@kit.ArkUI'; + +@Entry +@Component +struct GridNormal { + private nodeContent = new NodeContent(); + aboutToAppear() { + // 通过C-API创建节点,并添加到管理器nodeContent上 + Napi.createGridNativeNode(this.nodeContent); + } + build() { + Column() { + ContentSlot(this.nodeContent) + } + .width('100%') + .height('100%') + } +} diff --git a/ArkUIKit/NativeTypeSample/entry/src/main/resources/base/profile/main_pages.json b/ArkUIKit/NativeTypeSample/entry/src/main/resources/base/profile/main_pages.json index 0a0cee4bcb7..5002f07dc4e 100644 --- a/ArkUIKit/NativeTypeSample/entry/src/main/resources/base/profile/main_pages.json +++ b/ArkUIKit/NativeTypeSample/entry/src/main/resources/base/profile/main_pages.json @@ -6,7 +6,7 @@ "pages/page_accessibility", "pages/page_embedded_component", "pages/page_waterflow", - "pages/page_grid", + "pages/PageGrid", "pages/page_scroll", "pages/page_refresh", "pages/page_xcomponent", @@ -21,6 +21,9 @@ "pages/page_date_picker", "pages/page_image", "pages/page_calendar_picker", - "pages/page_image_animator" + "pages/page_image_animator", + "pages/grid/PageGridIrregularIndexes", + "pages/grid/PageGridNormal", + "pages/grid/PageGridGetRectByIndex" ] } -- Gitee