本文记录把 react-native-circle-checkbox(圆形复选框)适配到 HarmonyOS 的完整过程。

这个库很小——一个组件、12 个属性、三层同心圆加一个 label。但它给这一轮带来两个别处遇不到的问题:

  1. 交付方真的改了库的实现(3 行),而且必须改,否则在 RN 0.84 上 import 就崩;
  2. 它是第一个带运行时依赖的库,而 file: 这种接入方式不会把它的依赖装上,于是打包直接失败。

另外,这是个没有返回值的纯视觉组件,所以整轮验证只能靠"渲染出来的几何"。

在这里插入图片描述


一、先说结论

项结果
上游最新版0.1.6(npm gitHead = e6d4c254…)
是否需要原生适配不需要——纯 JS,无原生模块
与 npm 上游的差异index.js 改了 3 行(去掉 ViewPropTypes、两处样式校验改为 PropTypes.any)
这 3 行必须改RN 0.84.1 不再从根导出 ViewPropTypes,Text 上也没有 propTypes ⇒ 上游代码在 static propTypes 初始化时抛 TypeError,模块加载即崩
开箱即用的拦路虎⚠️ 运行时依赖 prop-types 通过 file: 接入时不会被安装 ⇒ Metro 在库自己的文件里报 Unable to resolve module prop-types,打包 exit 1
编译assembleHap 4 分 12 秒;HAP 81,647,755 → 81,725,574 字节(+77,819,含 prop-types@15.8.1)
设备侧断言✅ 29 / 29 全部通过
几何实测✅ 外圆 78px=26vp、中圆 69px=23vp、内圆 54px=18vp;同心偏移 5 / 8;未勾选时内圆不存在(0×0)
交互实测✅ 点圆心 → onToggle(true) → 内圆出现 → 状态行更新
发现的库缺陷⚠️ 尺寸 props 完全非响应式:同一个 outerSize=60,挂载时给 = 180px,挂载后改 = 78px

一句话结论:功能可用,圆环几何精确、勾选链路完整。但有两条硬约束:必须自己补装 prop-types,以及三个尺寸 prop 必须在挂载时就给对(运行时改无效,且增大 outerSize 不会自动放大另外两环)。


二、判定过程:不需要原生适配,但交付方改了 3 行

判断一个 RN 库要不要做原生适配,我固定走三步:

步做法这个库的结果
①package.json 里有没有 harmony.autolinking没有
②仓库里有没有 harmony/没有
③代码里有没有 NativeModules / requireNativeComponent没有

三步都指向"纯 JS,不需要原生适配"。但这一轮多了一步,而且这一步很关键:

步做法这个库的结果
④与 npm 上游 tarball 逐文件 diffindex.js 不一致(3,798 vs 3,700 字节)

前三个库里交付包都是原样透传,所以一开始我以为又是换行符差异。但字节差对不上(+98 而 CR 有 126 个),于是逐行比:

- import {StyleSheet, Text, TouchableOpacity, View, ViewPropTypes} from 'react-native';
+ import {StyleSheet, Text, TouchableOpacity, View} from 'react-native';

-     styleCheckboxContainer: ViewPropTypes.style,
+     styleCheckboxContainer: PropTypes.any,

-     styleLabel: Text.propTypes.style,
+     styleLabel: PropTypes.any,

只有这 3 行。 字节数也严格对得上:+126(CR)−28(去掉 , ViewPropTypes 与两处 .style → .any 的净减)= +98 ✓

结论:这是一个纯 JS 库,但它被改过实现。所以下面的问题不是"要不要原生适配",而是"这 3 行改动对不对"。


三、交付方的 3 行改动是对的,而且是必须的

3.1 先看被改掉的是什么

被改掉的三个符号都属于 React Native 早已废弃并移除的运行时 propTypes:

  • ViewPropTypes:RN 0.44 起弃用,后来从包根入口移除;
  • Text.propTypes:同理。

3.2 在 RN 0.84.1 上核实

检查结果
node_modules/react-native/index.js 里出现 ViewPropTypes0 次 ⇒ 根入口不再导出
Libraries/Text/Text.js 里有 propTypes没有 ⇒ Text.propTypes 是 undefined

光看源码还不够,因为"文档说移除了"和"运行时真的崩"是两回事。于是在设备上原地执行上游那两行:

在设备上执行结果
typeof RN.ViewPropTypesundefined
typeof Text.propTypesundefined
RN.ViewPropTypes.style(上游写法)抛 TypeError
Text.propTypes.style(上游写法)抛 TypeError

3.3 为什么会"加载即崩"

关键在于这两行写在 static propTypes = {…} 里:

export default class CircleCheckBox extends React.Component {
  static propTypes = {
    …
    styleCheckboxContainer: ViewPropTypes.style,   // ← 类定义时求值
    styleLabel: Text.propTypes.style,              // ← 类定义时求值
  };

静态字段是类定义时求值的,也就是模块被 import 的那一刻。所以上游代码在 RN 0.84 上的表现不是"某个 prop 校验失效",而是 import 阶段直接抛 TypeError,整个模块不可用。

⇒ 交付方这 3 行改动是正确的、必要的。 改法也恰当:用同库已经依赖的 prop-types 的 PropTypes.any 替代被移除的运行时校验器。

代价:ViewPropTypes.style / Text.propTypes.style → PropTypes.any 之后,失去样式合法性校验(原本能在开发期提示"style 里写了非法属性")。属于必要取舍。

3.4 但它没有被任何文档披露 ← 本轮最该补的一条

  • 仓库里的代码检查报告写的是「代码沿用上游 JavaScript 实现」;
  • README 写的是「API 行为沿用上游版本,本次交付没有新增原生能力」。

两处都没有提到为了适配 RN 0.84 改了 3 行。严格说"沿用"可以解释为"基于",但对拿着交付包去和上游 diff 的人来说是意外——而且这 3 行恰恰是它能跑起来的原因,是最该写进文档的一条。

建议:README 加一节「相对上游的改动」,列出这 3 行与原因(ViewPropTypes / Text.propTypes 已从新版 RN 移除)。


四、接入宿主:一个必须补的运行时依赖

4.1 现象

库的 index.js 第一屏就 import 了它:

import PropTypes from 'prop-types';

package.json 也声明了 dependencies: {"prop-types": "latest"}。按常规把它以 file: 加进宿主:

npm install --ignore-scripts    →  exit 0,"added 1 package",软链建好
node_modules\prop-types         →  不存在
npm ls prop-types               →  (empty)

接着打包:

error Unable to resolve module prop-types from
      E:\rnoh-work\react-native-circle-checkbox\index.js:
      prop-types could not be found within the project or in these directories

⇒ 库连自己声明的依赖都解析不到,打包直接失败。

4.2 这不是库的打包问题,是 file: 的通用行为

为了把因果钉死,我造了一个最小工程:宿主用 file: 引用一个声明了 dependencies: {"prop-types":"latest"} 的本地包。

接入方式包本身传递依赖 prop-types
"libb": "file:../libb"(junction 软链)✅ 装上❌ 不装
npm install libb-1.0.0.tgz✅ 装上✅ 装上

环境:npm 11.9.0 / Node v24.14.0。

⇒ npm 不会为 file: 依赖安装它自己的 dependencies(只建软链);换成 tarball 安装就会正常带上。所以这是接入方式导致的,不是交付包写错了依赖。

4.3 修复:显式补装

npm install prop-types
# added 3 packages;得到 prop-types@15.8.1
npm run dev
# exit 0

打包产物里 react-native-circle-checkbox 出现 6 次、prop-types 出现 28 次 ⇒ 解析成功。

4.4 交付方仍应补一句文档

README 写着「该库为纯 JavaScript 实现,不需要 HAR、权限、link-harmony 或 ohpm 接线」,通篇没有提 prop-types 这个运行时依赖。照着它用 file: 接入的人会直接撞上打包失败。

建议:安装一节补上 npm install prop-types,并说明"库有运行时依赖,file: 软链不会自动带上"。


五、验证设计:纯视觉组件的证据只在"渲染出来的几何"里

这个库没有返回值、没有系统状态、没有原生模块。它的全部契约是两件事:

  1. 三层同心圆的尺寸必须等于 outerSize / filterSize / innerSize;
  2. 勾选时内圆出现/消失,label 在左或在右。

这些都无法从 JS state 观察(state 里只有一个 customStyle),所以唯一诚实的证据是布局系统给出的矩形。

5.1 从布局 dump 里认圆

devecocli ui layout

输出每个节点的 [x1,y1,x2,y2]。圆形就是正方形 View,按"宽=高"筛出来即可:

. E:\rnoh-work\circle-probe.ps1
Get-SquareHistogram      # 各正方形尺寸出现次数,一眼看出三层环
Get-Squares              # 每个圆的尺寸与坐标

5.2 测量口径

要验的手段
三层圆的直径布局 dump 里正方形的边长 ÷ devicePixelRatio(3)
是否同心相邻两环的坐标偏移 vs (外径−内径)/2
勾选是否生效内圆节点出现 / 不存在(未勾选时它是无样式的 <View />,即 0×0)
label 在左还是右label 文本节点与外圆的 X 区间相对次序
onToggle 是否触发hilog 里的调用记录

⚠️ 弹层类组件要注意滚动,圆环类不用:圆环跟着内容一起滚,但它的外径不随滚动变化,所以尺寸测量是滚动无关的。只有"label 在左还是在右"要看相对次序而不是绝对 X(整行会因为居中而整体位移)。

5.3 分组口径

组进通过率内容
A 契约与导出✅导出形态、LABEL_POSITION、12 个 propTypes、全部 defaultProps、上游崩溃点复现
B 渲染与几何✅两个实例的外径实测(onLayout)
C 交互与 props✅受控语义、尺寸冻结不变量、label 状态
外部协议信息三层圆环矩形、点击链路、label 左右、尺寸冻结对照

六、实测一:三层同心圆的几何与勾选链路

设备:Pura X View 模拟器,1320×2232(density 3)。

6.1 未勾选时:三层里只渲染两层

圆环实测矩形÷3对应 props
外圆78×78 @ (72,1846)26 vpouterSize: 26 ✓(defaultProps)
中圆(filter)69×69 @ (77,1851)23 vpfilterSize: 23 ✓
内圆不存在—checked=false ⇒ _renderInner() 返回无样式 <View /> ⇒ 0×0

同心性可以反推:偏移 (5,5),而 (78−69)/2 = 4.5 ⇒ 居中 ✓

"内圆不存在"本身就是一条证据:组件在未勾选时不是"把内圆设成透明",而是渲染了一个没有样式的 View,它的尺寸是 0×0,所以在布局里根本不是一个正方形。

6.2 勾选后:内圆出现

在应用外用 uitest uiInput click 点圆心:

圆环实测矩形÷3
外圆78×78 @ (72,1816)26 vp
中圆69×69 @ (77,1821)23 vp
内圆54×54 @ (85,1829)18 vp = innerSize: 18 ✓

偏移:外→中 5((78−69)/2 = 4.5),中→内 8((69−54)/2 = 7.5)⇒ 三层同心 ✓

hilog 同时出现 onToggle(true) ⇒ 点击 → onToggle(!checked) → 父组件 setState → 内圆渲染 整条链路通。

在这里插入图片描述

6.3 label 的左右位置

labelPositionlabel 矩形外圆矩形关系
rightx = 165…250x = 72…150label 在圆右侧(165 > 150)✓
leftx = 87…172x = 186…264label 在圆左侧(172 < 186)✓

(整行 flexDirection:'row' + 居中,切到 left 后圆整体右移,所以必须看相对次序。)

label='' 时:圆环仍在(78/69/54),label 文本节点数为 0 ✓ —— _renderLabel 返回的是空 <View />。


七、实测二:尺寸 props 是非响应式的

7.1 机制

组件的尺寸样式是在构造函数里创建的:

constructor(props) {
  const outerSize = (parseInt(props.outerSize) < 10 || isNaN(...)) ? 10 : parseInt(props.outerSize);
  const customStyle = StyleSheet.create({
    _circleOuterStyle: {width: outerSize, height: outerSize, borderRadius: outerSize/2, …},
    …
  });
  this.state = {customStyle: customStyle};
}

StyleSheet.create 只在构造函数里跑一次,之后就只读 this.state.customStyle。⇒ 挂载后修改 outerSize / filterSize / innerSize 不会有任何效果,而且不报错、不警告,静默失效。

7.2 怎么验才算数:挂两个实例做对照

光"改了没变"还不够有力——可能只是我改的方式不对。所以测试页挂了两个实例:

  • 实例 A:outerSize 来自 state,先以 26 挂载,随后把 state 改成 60;
  • 对照实例:挂载时就是 outerSize={60}。
实例outerSize 的值挂载时机实测外圆
实例 A60挂载后改的 state78×78 = 26 vp(没变)
对照实例60挂载时就是 60180×180 = 60 vp ✓

⇒ 同一个库、同一个数值,180 与 78 的差别只来自"什么时候给的"。 这就把"尺寸被冻结在构造函数"钉死了——不是"prop 没传进去",而是"传进去了但样式已经生成完了"。

在这里插入图片描述

7.3 顺带发现的第二个问题:单独调大 outerSize 会得到比例失调的圆

对照实例只给了 outerSize={60},filterSize 仍是默认 23:

圆环实测若按 26 : 23 : 18 等比放大应为
外圆180 = 60 vp60 vp ✓
中圆69 = 23 vp约 53 vp ✗
内圆54 = 18 vp约 41 vp ✗

原因在构造函数里的钳制规则——它只会下调尺寸,不会随 outerSize 放大另外两环:

const filterSize = (parseInt(props.filterSize) > outerSize + 3 || isNaN(...))
  ? outerSize - 3          // 太大才缩小,不会放大
  : parseInt(props.filterSize);

⇒ 要改尺寸就得三个 prop 一起给;而且因为 7.2 的冻结行为,给错了也没法在运行时救回来,只能改 key 让组件重新挂载(或直接重进页面)。


八、交付包质量

做得好的:

  • 那 3 行改动是对的、必要的(见第三节),改法也恰当;
  • LICENSE 文件确为 MIT,与 package.json 声明的 MIT 一致;
  • scripts.test 换成了可运行的 node --test(上游是 echo "Error: no test specified" && exit 1);
  • README 对验证范围的说法诚实(自述为"包级 smoke test")。

问题:

① 改了 3 行实现但没有任何文档披露(本轮最该补的一条,见 3.4)。

② README 没提运行时依赖 prop-types,反而强调"不需要任何接线"。照它用 file: 接入会打包失败(见第四节)。

③ README 的「能力一览」只有 2 行、没有组件属性表。 这个库的全部 API 就是那 12 个 props,README 一个都没写。

④ spec.json 缺 license 字段,也没有 upstreamCommit(上游 gitHead 可从 npm 查到),validation 是裸字符串 "pass"。三者都让可追溯性只能靠人读 README。

⑤ 契约测试通过 ≠ 能用。 测试是同一份包级 smoke test,只断言包名、版本、主入口文件存在、中文 README 存在:

assert.ok(require.resolve(path.resolve(__dirname, '..', pkg.main || 'index.js')));
assert.ok(fs.existsSync(path.resolve(__dirname, '..', 'README.OpenHarmony_CN.md')));

而这个包在 file: 宿主里连自己的依赖都解析不到、打包直接失败——这份测试照样全绿。建议至少加一条"本包 dependencies 在消费者环境里可达"的检查。

⑥ 上游的 "prop-types": "latest" 是浮动版本(交付方如实透传)。latest 意味着每次安装解析到的版本可能不同,构建不可复现。建议改成 ^15.8.1 这类固定范围。

⑦ 许可证信息三处不一致:package.json 用的是已废弃的 licenses 数组,README 写"SEE LICENSE IN LICENSE",而 LICENSE 文件本身是标准 MIT。应以文件为准。


九、已知限制

9.1 库本身的

  1. 尺寸 props 非响应式:outerSize / filterSize / innerSize 在构造函数里被固化成样式,挂载后修改无效且不报错。要动态尺寸只能改 key 重新挂载。
  2. 单独调大 outerSize 不会放大另外两环:钳制规则只下调不放大 ⇒ 会把圆环比例搞乱,三个尺寸得一起给。
  3. 未勾选时渲染的是一个无样式的 <View />(不是 null),它在布局里是 0×0。如果外层依赖子元素存在性做判断,会拿到一个"存在但没尺寸"的节点。
  4. label 必须是字符串:_renderLabel 里有 this.props.label.length > 0,传数字或节点会在渲染时抛错。
  5. 默认 renderItem 之外没有无障碍标注:组件没有 accessibilityRole="checkbox" / accessibilityState,屏幕阅读器无法识别为复选框。
  6. 运行时依赖 prop-types,且上游声明为 latest(浮动版本)。
  7. onToggle 在 propTypes 里标为必填,但内部有 if (this.props.onToggle) 守卫 ⇒ 不传不会崩,只在开发期由 prop-types 警告。

9.2 本次验证的边界

  1. 只在一台模拟器上验证(Pura X View,1320×2232,density 3),没有真机。
  2. 颜色没有做像素取色:outerColor / filterColor / innerColor 只验证了声明与默认值,以及布局中没有异常;布局 dump 不含颜色,所以"渲染出来是不是 #FC9527"未验证。
  3. styleCheckboxContainer / styleLabel 自定义样式未逐一验证(只验证了它们存在、类型为 PropTypes.any)。
  4. 钳制边界未穷举:只测了默认值(26/23/18)和 outerSize=60 两个点,没有遍历 <10、>outerSize+3 等各种非法组合。
  5. onToggle 缺失时的行为未实测。
  6. 无障碍未测。
  7. 多实例同时切换、长列表里大量实例的性能未测。
  8. 没有跨平台对照:没在 iOS/Android 上跑同一份用例比对。

未改动库代码。


十、常见问题

Q1:需要原生适配吗?

不需要。package.json 里没有 harmony.autolinking、仓库里没有 harmony/、代码里没有 NativeModules,接进宿主只改 package.json、metro.config.js、index.js 三处。

Q2:怎么装?

npm install "git+https://atomgit.com/oh-react-native/react-native-circle-checkbox.git#0.1.6-ohos-1.0.0"
# 或本地 file: 方式
npm install ../react-native-circle-checkbox

无论哪种方式,都要额外补装运行时依赖:

npm install prop-types

Q3:为什么我必须自己装 prop-types?

因为库 import 了它,而 npm 不会为 file: 依赖安装它自己的 dependencies(只建软链)。实测(npm 11.9.0):同一个包用 file: 引用 → prop-types 不装;打成 .tgz 安装 → 装。

不装的后果不是"少个开发期警告",而是打包直接失败:

error Unable to resolve module prop-types from …/react-native-circle-checkbox/index.js

Q4:为什么这个交付包改了上游代码?

因为不改就跑不起来。RN 0.84 不再从根入口导出 ViewPropTypes,Text 上也没有 propTypes,而上游代码把这两个值写在 static propTypes 里(类定义时求值)⇒ import 阶段就抛 TypeError。

交付方把 3 行替换成了 PropTypes.any:

- import {StyleSheet, Text, TouchableOpacity, View, ViewPropTypes} from 'react-native';
+ import {StyleSheet, Text, TouchableOpacity, View} from 'react-native';
-     styleCheckboxContainer: ViewPropTypes.style,
+     styleCheckboxContainer: PropTypes.any,
-     styleLabel: Text.propTypes.style,
+     styleLabel: PropTypes.any,

代价是失去样式合法性校验。

Q5:我只想改圆的大小,怎么改?

三个尺寸必须一起给,而且必须在挂载时就给对:

<CircleCheckBox
  checked={checked}
  onToggle={setChecked}
  outerSize={40}
  filterSize={36}   // 约 outerSize - 4
  innerSize={28}    // 约 filterSize - 8
  label="同意"
/>

因为:

  • 只给 outerSize 时,filterSize 保持默认 23 不会跟着放大,圆环比例会乱;
  • outerSize 等 prop 在构造函数里被固化成样式,挂载后修改无效(实测:同一个 60,挂载时给 = 180px,挂载后改 = 78px)。

要动态尺寸,只能改 key 让组件重新挂载:

<CircleCheckBox key={size} outerSize={size} filterSize={size - 4} innerSize={size - 12} … />

Q6:checked 是受控的吗?

是。组件自己不持有勾选状态,点击时只调 onToggle(!checked),由父组件决定要不要改。所以父组件不更新状态的话,界面不会有任何变化。

Q7:怎么判断它到底有没有勾选?

看内圆在不在。未勾选时 _renderInner() 返回的是一个没有样式的 <View />(尺寸 0×0),勾选后才换成真正的内圆(默认 18vp):

未勾选:外圆 78×78、中圆 69×69、内圆(无)
已勾选:外圆 78×78、中圆 69×69、内圆 54×54

(1320×2232、density 3 的设备上,78 / 69 / 54 分别对应 26 / 23 / 18 vp。)

Q8:label 的位置怎么控制?

labelPosition 取 LABEL_POSITION.RIGHT(默认)或 LABEL_POSITION.LEFT。

import CircleCheckBox, {LABEL_POSITION} from 'react-native-circle-checkbox';
<CircleCheckBox label="同意" labelPosition={LABEL_POSITION.LEFT} … />

注意 label 必须是字符串——内部会访问 label.length。

Q9:它是无障碍的复选框吗?

不是。 组件没有设置 accessibilityRole="checkbox" / accessibilityState,屏幕阅读器只会把它当成一个可点击区域。对无障碍有要求的场景需要自己包一层并补上这些属性。


小结

react-native-circle-checkbox 是个小库:一个组件、12 个属性、三层同心圆加一个 label。但这轮撞到两件前几轮没遇到的事,两件都值得记住:

  1. 交付包可能真的改过实现,而"改得对"和"文档写了"是两件事。 前几个库的 index.js 都是逐字节一致,所以这次我差点把 3 行差异当成换行符问题——字节差对不上时才去逐行 diff。查清后发现改动是必须的(RN 0.84 不再导出 ViewPropTypes、Text 上没有 propTypes,而上游把它们写在 static propTypes 里 ⇒ import 阶段即崩),但交付包的文档一个字都没提。

  2. file: 依赖不会带上它自己的 dependencies。 这是本轮最大的坑,而且是通用规律:npm 11.9.0 实测,同一个包用 file: 引用时传递依赖不装、打成 .tgz 就装。前 16 个库都没有运行时依赖,所以从没暴露过。⇒ 以后每接一个库,先看它有没有 dependencies;有就必须显式补装,否则 Metro 会在库自己的文件里报解析失败——错误信息看起来像是库坏了,实际是接入方式的问题。

  3. 纯视觉组件的证据只在"渲染出来的几何"里。 这个库没有返回值、没有系统状态,能拿到的硬证据就是布局矩形:78 / 69 / 54 与 26 / 23 / 18 精确对应、同心偏移可由 (外径−内径)/2 反推、未勾选时"内圆不存在"本身就是一条证据(它渲染的是 0×0 的无样式 View)。

  4. 验证 props 的响应性,要挂两个实例做对照。 只说"我改了 outerSize 但圆没变大"说服力不够——可能是我改的方式不对。同一个值,一个挂载时给、一个挂载后改,拿到 180px vs 78px,才是干净的因果证据。

  5. 断言写错要认账。 首跑 24/29,5 条失败全是我自己的断言问题:isRequired 的判别特征我记反了(prop-types 里必填版本的 .isRequired 是 undefined,可选版本才是函数)、量外径时忘了外层包裹层的 padding、把"外部点过才有"的交互结果写成了自动跑就成立的断言。改完 29/29。


本篇用到的库

项内容
三方库react-native-circle-checkbox(上游 0.1.6 的鸿蒙适配版)
适配仓库https://atomgit.com/oh-react-native/react-native-circle-checkbox
适配 TAG0.1.6-ohos-1.0.0
需要 HAR / 权限 / ohpm都不需要(纯 JS)
运行时依赖prop-types(必须自行补装,见 Q3)
是否改过上游实现改了 3 行(去掉 ViewPropTypes / Text.propTypes,详见 Q4)
上游仓库https://github.com/paramoshkinandrew/ReactNativeCircleCheckbox(基线 commit e6d4c25402847623283c344bf4784555b1f2b52f,MIT)
宿主工程RNOH084Demo(测试页 rnAppKey = CircleCheckboxTestApp)

接入方式(纯 JS,零原生接线,但依赖要自己补):

// package.json
"react-native-circle-checkbox": "file:../react-native-circle-checkbox"
// 或直接从适配仓库装(替代上面的 file: 方式)
"react-native-circle-checkbox": "git+https://atomgit.com/oh-react-native/react-native-circle-checkbox.git#0.1.6-ohos-1.0.0"
# ⚠️ 无论哪种方式都要补这一条,否则打包会失败
npm install prop-types
// metro.config.js —— file: 装进来是 junction,必须让 Metro 找得到源码
watchFolders: [path.resolve(__dirname, '../react-native-circle-checkbox')],
import CircleCheckBox, {LABEL_POSITION} from 'react-native-circle-checkbox';

// 三个尺寸必须一起给,而且要在挂载时给对(挂载后改无效)
<CircleCheckBox
  checked={checked}
  onToggle={setChecked}
  outerSize={26}
  filterSize={23}
  innerSize={18}
  label="同意"
  labelPosition={LABEL_POSITION.RIGHT}
  styleCheckboxContainer={{margin: 8}}
/>
# 换页启动测试页(force-stop 不能省,换页参数只在冷启动生效)
hdc shell aa force-stop com.rnoh084.demo
hdc shell aa start -b com.rnoh084.demo -a EntryAbility --ps rnAppKey CircleCheckboxTestApp

# 外部几何:三层圆的直径
devecocli ui layout | Select-String 'View#'

# 点圆心触发勾选
hdc shell "uitest uiInput click 111 1885"

验证环境

项版本
React Native0.84.1
React19.2.3
RNOH(npm / ohpm)@react-native-oh/react-native-harmony / @rnoh/react-native-openharmony 0.84.3
Node.js / npmv24.14.0 / 11.9.0
DevEco Studio26.0.0.621
HarmonyOS SDKAPI 26(26.0.0.32)
设备HarmonyOS 7.0.0(26.0.0) Beta2 模拟器 Pura X View(ohos-x64),1320×2232,density 3
宿主 HAP 产物entry-default-signed.hap(81.73 MB)
本次增量构建assembleHap 4 分 12 秒,HAP +77,819 字节(含 prop-types@15.8.1)
验证规模设备侧 29 / 29 断言全部通过;三层圆环几何(78/69/54 px)外部实测;勾选链路 1 次点击;尺寸冻结对照 180px vs 78px;label 左右 2 个方向;上游崩溃点 2 处设备复现;file: 依赖行为 最小工程对照

欢迎加入 CPF-RN 鸿蒙社区:https://atomgit.com/CPF-RN

React Native for OpenHarmony 组织:https://atomgit.com/oh-react-native

RN 三方库鸿蒙适配清单:https://atomgit.com/oh-react-native/rn-ohos-adaptation-overview

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐