React Native for OpenHarmony 实战:三方库 react-native-circle-checkbox 的鸿蒙化适配指南
本文记录把 react-native-circle-checkbox(圆形复选框)适配到 HarmonyOS 的完整过程。
这个库很小——一个组件、12 个属性、三层同心圆加一个 label。但它给这一轮带来两个别处遇不到的问题:
- 交付方真的改了库的实现(3 行),而且必须改,否则在 RN 0.84 上 import 就崩;
- 它是第一个带运行时依赖的库,而
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 逐文件 diff | index.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 里出现 ViewPropTypes | 0 次 ⇒ 根入口不再导出 |
Libraries/Text/Text.js 里有 propTypes | 没有 ⇒ Text.propTypes 是 undefined |
光看源码还不够,因为"文档说移除了"和"运行时真的崩"是两回事。于是在设备上原地执行上游那两行:
| 在设备上执行 | 结果 |
|---|---|
typeof RN.ViewPropTypes | undefined |
typeof Text.propTypes | undefined |
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: 软链不会自动带上"。
五、验证设计:纯视觉组件的证据只在"渲染出来的几何"里
这个库没有返回值、没有系统状态、没有原生模块。它的全部契约是两件事:
- 三层同心圆的尺寸必须等于
outerSize/filterSize/innerSize; - 勾选时内圆出现/消失,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 vp | outerSize: 26 ✓(defaultProps) |
| 中圆(filter) | 69×69 @ (77,1851) | 23 vp | filterSize: 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 的左右位置
labelPosition | label 矩形 | 外圆矩形 | 关系 |
|---|---|---|---|
right | x = 165…250 | x = 72…150 | label 在圆右侧(165 > 150)✓ |
left | x = 87…172 | x = 186…264 | label 在圆左侧(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 的值 | 挂载时机 | 实测外圆 |
|---|---|---|---|
| 实例 A | 60 | 挂载后改的 state | 78×78 = 26 vp(没变) |
| 对照实例 | 60 | 挂载时就是 60 | 180×180 = 60 vp ✓ |
⇒ 同一个库、同一个数值,180 与 78 的差别只来自"什么时候给的"。 这就把"尺寸被冻结在构造函数"钉死了——不是"prop 没传进去",而是"传进去了但样式已经生成完了"。

7.3 顺带发现的第二个问题:单独调大 outerSize 会得到比例失调的圆
对照实例只给了 outerSize={60},filterSize 仍是默认 23:
| 圆环 | 实测 | 若按 26 : 23 : 18 等比放大应为 |
|---|---|---|
| 外圆 | 180 = 60 vp | 60 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 库本身的
- 尺寸 props 非响应式:
outerSize/filterSize/innerSize在构造函数里被固化成样式,挂载后修改无效且不报错。要动态尺寸只能改key重新挂载。 - 单独调大
outerSize不会放大另外两环:钳制规则只下调不放大 ⇒ 会把圆环比例搞乱,三个尺寸得一起给。 - 未勾选时渲染的是一个无样式的
<View />(不是null),它在布局里是 0×0。如果外层依赖子元素存在性做判断,会拿到一个"存在但没尺寸"的节点。 label必须是字符串:_renderLabel里有this.props.label.length > 0,传数字或节点会在渲染时抛错。- 默认
renderItem之外没有无障碍标注:组件没有accessibilityRole="checkbox"/accessibilityState,屏幕阅读器无法识别为复选框。 - 运行时依赖
prop-types,且上游声明为latest(浮动版本)。 onToggle在propTypes里标为必填,但内部有if (this.props.onToggle)守卫 ⇒ 不传不会崩,只在开发期由 prop-types 警告。
9.2 本次验证的边界
- 只在一台模拟器上验证(
Pura X View,1320×2232,density 3),没有真机。 - 颜色没有做像素取色:
outerColor/filterColor/innerColor只验证了声明与默认值,以及布局中没有异常;布局 dump 不含颜色,所以"渲染出来是不是#FC9527"未验证。 styleCheckboxContainer/styleLabel自定义样式未逐一验证(只验证了它们存在、类型为PropTypes.any)。- 钳制边界未穷举:只测了默认值(26/23/18)和
outerSize=60两个点,没有遍历<10、>outerSize+3等各种非法组合。 onToggle缺失时的行为未实测。- 无障碍未测。
- 多实例同时切换、长列表里大量实例的性能未测。
- 没有跨平台对照:没在 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。但这轮撞到两件前几轮没遇到的事,两件都值得记住:
-
交付包可能真的改过实现,而"改得对"和"文档写了"是两件事。 前几个库的
index.js都是逐字节一致,所以这次我差点把 3 行差异当成换行符问题——字节差对不上时才去逐行 diff。查清后发现改动是必须的(RN 0.84 不再导出ViewPropTypes、Text上没有propTypes,而上游把它们写在static propTypes里 ⇒ import 阶段即崩),但交付包的文档一个字都没提。 -
file:依赖不会带上它自己的dependencies。 这是本轮最大的坑,而且是通用规律:npm 11.9.0 实测,同一个包用file:引用时传递依赖不装、打成.tgz就装。前 16 个库都没有运行时依赖,所以从没暴露过。⇒ 以后每接一个库,先看它有没有dependencies;有就必须显式补装,否则 Metro 会在库自己的文件里报解析失败——错误信息看起来像是库坏了,实际是接入方式的问题。 -
纯视觉组件的证据只在"渲染出来的几何"里。 这个库没有返回值、没有系统状态,能拿到的硬证据就是布局矩形:78 / 69 / 54 与 26 / 23 / 18 精确对应、同心偏移可由
(外径−内径)/2反推、未勾选时"内圆不存在"本身就是一条证据(它渲染的是 0×0 的无样式 View)。 -
验证 props 的响应性,要挂两个实例做对照。 只说"我改了
outerSize但圆没变大"说服力不够——可能是我改的方式不对。同一个值,一个挂载时给、一个挂载后改,拿到 180px vs 78px,才是干净的因果证据。 -
断言写错要认账。 首跑 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 |
| 适配 TAG | 0.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 Native | 0.84.1 |
| React | 19.2.3 |
| RNOH(npm / ohpm) | @react-native-oh/react-native-harmony / @rnoh/react-native-openharmony 0.84.3 |
| Node.js / npm | v24.14.0 / 11.9.0 |
| DevEco Studio | 26.0.0.621 |
| HarmonyOS SDK | API 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
更多推荐


所有评论(0)