Rate
星级评分,支持半星、只读小数与自定义图标
评分(Rate)用一排星星表达分值。每颗星由三层构成:空心星打底、实心星按填充比例裁剪覆盖、命中区平铺在最上层。两种星形取自同一字体族,字形轮廓完全对齐,半星裁剪时不会错位。
import { Rate } from '@skyroc/native-ui';基础用法
默认 5 颗星、初始 0 分。传 value + onChange 即为受控,非受控用 defaultValue。
import { Rate, Text } from '@skyroc/native-ui';
import { useState } from 'react';
import { View } from 'react-native';
const RateBasic = () => {
const [value, setValue] = useState(3);
return (
<View className="gap-2 bg-background p-4">
<Rate
value={value}
onChange={setValue}
/>
<Text color="muted">当前分值:{value}</Text>
</View>
);
};
export { RateBasic };何时使用
- 让用户给内容打分,或展示已有的平均分(配
readonly)。 - 只需要「赞 / 不赞」这类二元反馈时不要用评分。
半星
allowHalf 开启后,单颗星被切成左右两个命中区:点左半得 .5 分,点右半得整分。
import { Rate, Text } from '@skyroc/native-ui';
import { useState } from 'react';
import { View } from 'react-native';
const RateHalf = () => {
const [value, setValue] = useState(2.5);
return (
<View className="gap-2 bg-background p-4">
<Rate
allowHalf
value={value}
onChange={setValue}
/>
<Text color="muted">当前分值:{value}</Text>
</View>
);
};
export { RateHalf };可交互时分值一律量化到 0.5,保证「点出来的分值」与「看到的星」始终一致。
可清除
clearable 允许再次点中当前分值时归零。关闭时重复点击同一分值不会触发 onChange。
import { Rate, Text } from '@skyroc/native-ui';
import { useState } from 'react';
import { View } from 'react-native';
const RateClearable = () => {
const [value, setValue] = useState(3);
return (
<View className="gap-2 bg-background p-4">
<Rate
clearable
value={value}
onChange={setValue}
/>
<Text color="muted">当前分值:{value}</Text>
</View>
);
};
export { RateClearable };数量与尺寸
| 属性 | 含义 | 默认值 |
|---|---|---|
count | 星星总数,非整数向下取整、负数按 0 | 5 |
size | 图标边长(px),同时是半星裁剪基准 | 24 |
gutter | 星星间距(px) | 4 |
import { Rate } from '@skyroc/native-ui';
import { View } from 'react-native';
const RateSize = () => {
return (
<View className="gap-3 bg-background p-4">
<Rate
count={3}
defaultValue={2}
size={20}
/>
<Rate defaultValue={3} />
<Rate
count={7}
defaultValue={5}
gutter={8}
size={32}
/>
</View>
);
};
export { RateSize };分值会被裁进 [0, count],越界入参不至于渲染出半截星或多余的空星。
主题色
color 决定点亮星的颜色,默认是 warning(金色星)。未点亮的星统一用 accent-muted-foreground。
import { Rate, Text } from '@skyroc/native-ui';
import type { ThemeColor } from '@skyroc/native-ui';
import { View } from 'react-native';
const COLORS: ThemeColor[] = ['warning', 'primary', 'destructive', 'success', 'info', 'accent', 'carbon', 'secondary'];
const RateColor = () => {
return (
<View className="gap-3 bg-background p-4">
{COLORS.map(color => (
<View
key={color}
className="flex-row items-center gap-3"
>
<Rate
color={color}
defaultValue={4}
size={20}
/>
<Text color="muted">{color}</Text>
</View>
))}
</View>
);
};
export { RateColor };secondary 是浅底色,直接当星色几乎不可见,因此内部取前景色代替。
只读小数
readonly 时不响应点击;与 allowHalf 一起使用会放开填充精度,可以渲染 3.7 星这类统计值 —— 这是唯一允许任意小数的组合,其余情况都会量化。
import { Rate, Text } from '@skyroc/native-ui';
import { View } from 'react-native';
const READONLY_SCORES = [3.7, 4.2, 2.5];
const RateReadonly = () => {
return (
<View className="gap-3 bg-background p-4">
{READONLY_SCORES.map(score => (
<View
key={score}
className="flex-row items-center gap-3"
>
<Rate
allowHalf
readonly
value={score}
/>
<Text color="muted">{score} 分</Text>
</View>
))}
</View>
);
};
export { RateReadonly };禁用
disabled 阻止点击、把整体降到 50% 不透明度,并把点亮星的颜色改为灰色(与 readonly 的区别:只读保留原色)。
import { Rate } from '@skyroc/native-ui';
import { View } from 'react-native';
const RateDisabled = () => {
return (
<View className="gap-3 bg-background p-4">
<Rate
disabled
defaultValue={3}
/>
<Rate
allowHalf
disabled
defaultValue={2.5}
/>
</View>
);
};
export { RateDisabled };自定义图标
icon / voidIcon 接受一个节点,或 (index, active) => 节点 的函数(函数式写法可以按星索引给出不同图标,例如笑脸评分)。
import Ionicons from '@expo/vector-icons/Ionicons';
import { Rate } from '@skyroc/native-ui';
import { View } from 'react-native';
import { withUniwind } from 'uniwind';
/** 与库内一致的取色方式:`accent-*` 工具类映射到矢量图标的 color 上 */
const HeartIcon = withUniwind(Ionicons);
const RateIcon = () => {
return (
<View className="gap-3 bg-background p-4">
<Rate
allowHalf
color="destructive"
defaultValue={3.5}
icon={(_index, active) => (
<HeartIcon
colorClassName="accent-destructive"
name={active ? 'heart' : 'heart-outline'}
size={24}
/>
)}
voidIcon={
<HeartIcon
colorClassName="accent-muted-foreground"
name="heart-outline"
size={24}
/>
}
/>
</View>
);
};
export { RateIcon };自定义图标的实际宽度必须与 size 一致,否则半星遮罩按 size 裁剪会与图标错位。矢量图标不认 className,取色请用 withUniwind 把 accent-* 映射到 color,或直接在图标上写死颜色。
自定义样式
className 追加到根容器上,classNames 按 slot 细粒度覆盖:
| slot | 作用位置 |
|---|---|
root | 根容器 View(横向排布,间距由 gutter 决定) |
item | 单颗星的容器 |
icon | 点亮星的 colorClassName,只接受 accent-* 颜色类 |
voidIcon | 未点亮星的 colorClassName,只接受 accent-* 颜色类 |
import { Rate } from '@skyroc/native-ui';
import { View } from 'react-native';
const RateStyles = () => {
return (
<View className="gap-3 bg-background p-4">
<Rate
className="self-start rounded-lg bg-secondary px-3 py-2"
defaultValue={4}
/>
<Rate
classNames={{
icon: 'accent-info',
item: 'rounded-full bg-muted p-1'
}}
defaultValue={3}
/>
</View>
);
};
export { RateStyles };icon / voidIcon 两个 slot 只在使用内置星星时生效;传了自定义图标后取色由你自己负责。
受控
分值完全由外部 state 决定,其它控件也可以改写它。
import { Button, Rate } from '@skyroc/native-ui';
import { useState } from 'react';
import { View } from 'react-native';
const RateControlled = () => {
const [value, setValue] = useState(4);
return (
<View className="gap-3 bg-background p-4">
<Rate
allowHalf
value={value}
onChange={setValue}
/>
<View className="flex-row gap-2">
<Button
color="primary"
variant="outline"
onPress={() => setValue(Math.max(0, value - 0.5))}
>
-0.5
</Button>
<Button
color="primary"
variant="outline"
onPress={() => setValue(Math.min(5, value + 0.5))}
>
+0.5
</Button>
<Button
color="primary"
variant="ghost"
onPress={() => setValue(0)}
>
重置
</Button>
</View>
</View>
);
};
export { RateControlled };热区
单颗星默认只有 24pt,半星模式下横向命中区更是只剩一半。横向补偿会与相邻星互抢点击,因此组件只补纵向:hitSlop={{ top: 10, bottom: 10 }},把可点高度抬到 44pt 附近。命中区不嵌套 Pressable,左右两半是平级的兄弟节点,避免内外层互抢触摸响应。
API
Rate
| 属性 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| value | 当前分值(受控) | number | - |
| defaultValue | 非受控初始分值 | number | 0 |
| onChange | 分值变化回调 | (value: number) => void | - |
| count | 星星总数,非整数向下取整 | number | 5 |
| size | 图标边长(px),同时是半星遮罩的裁剪基准 | number | 24 |
| gutter | 星星间距(px) | number | 4 |
| color | 点亮星的主题色 | 'primary' | 'destructive' | 'success' | 'warning' | 'info' | 'accent' | 'carbon' | 'secondary' | 'warning' |
| allowHalf | 允许半星:左半区选半星、右半区选满星 | boolean | false |
| clearable | 再次点中当前分值时清零 | boolean | false |
| readonly | 只读,不响应点击;配合 allowHalf 可渲染任意小数 | boolean | false |
| disabled | 禁用,不响应点击并整体置灰 | boolean | false |
| icon | 点亮态图标,缺省为实心星 | RateIcon | - |
| voidIcon | 未点亮态图标,缺省为空心星 | RateIcon | - |
| className | 根容器类名,合并在 classNames.root 之后 | string | - |
| classNames | 各 slot 的类名覆盖,见「自定义样式」一节 | SlotClassNames<RateSlots> | - |
| ref | 根容器 View 的 ref,用于 measure / 滚动定位 | Ref<View> | - |
类型
import type { RateIcon, RateProps, RateSlots } from '@skyroc/native-ui';RateIcon
星星图标:直接给节点,或按星索引与点亮态动态返回节点。自定义图标的宽度必须与 size 一致。
RateSlots
可通过 classNames 覆盖的 slot 名称。
SlotClassNames
classNames 的取值形态:把 slot 名映射到类名,每个 slot 都可选。本页用到的 slot 见 RateSlots。
包内还导出了 rateVariants 与四个常量:DEFAULT_RATE_COUNT(5)、DEFAULT_RATE_SIZE(24)、DEFAULT_RATE_GUTTER(4)、RATE_HIT_SLOP(纵向 10)。