Notify
贴边横幅通知,命令式调用为主
通知(Notify)在屏幕顶部或底部贴边浮出一条整宽色带,用于系统级消息:断网、版本更新、后台任务结果。主用法是命令式的 showNotify,面板通过 Portal 挂载(zIndex 1100,高于 Toast —— 它贴边显示不会压住居中的 Toast,即便与 Toast 的遮罩同时存在也应保持可见可点)。
import { showNotify, closeNotify } from '@skyroc/native-ui';命令式调用依赖 PortalHost,请确保 App 内已经挂了它。
基础用法
showNotify 参数可以直接传字符串(等价于 { message }),返回一个实例句柄;closeNotify() 关闭当前通知。
import { Button, closeNotify, showNotify } from '@skyroc/native-ui';
import { View } from 'react-native';
const NotifyBasic = () => {
return (
<View className="flex-row flex-wrap items-center gap-3 bg-background p-4">
<Button
variant="tonal"
onPress={() => showNotify('这是一条基础通知')}
>
字符串简写
</Button>
<Button
variant="tonal"
onPress={() => showNotify({ message: '使用 options 传入通知内容' })}
>
options 调用
</Button>
<Button
variant="outline"
onPress={closeNotify}
>
关闭当前通知
</Button>
</View>
);
};
export { NotifyBasic };同一时刻只显示一条,新的会顶掉旧的(旧的那条会触发 onClose)。
何时使用
- 系统级、需要横贯全屏宣告的消息。
- 操作反馈用
Toast;需要用户确认用Dialog。
通知类型
type 决定背景色与文字色,四种语义各取对应的 -foreground token(而不是写死白字:warning / success 的背景在浅色主题下并不深,固定白字对比度不达标,主题切换时也无从跟随):
| 类型 | 背景 |
|---|---|
danger | bg-destructive(默认) |
primary | bg-primary |
success | bg-success |
warning | bg-warning |
import type { NotifyType } from '@skyroc/native-ui';
import { Button, showNotify } from '@skyroc/native-ui';
import { View } from 'react-native';
const TYPES: NotifyType[] = ['primary', 'success', 'warning', 'danger'];
const NotifyTypes = () => {
return (
<View className="flex-row flex-wrap items-center gap-3 bg-background p-4">
{TYPES.map(type => (
<Button
key={type}
variant="tonal"
onPress={() => showNotify({ message: `${type} 通知`, type })}
>
{type}
</Button>
))}
</View>
);
};
export { NotifyTypes };显示位置
position 控制贴顶还是贴底,命令式路径下还会自动补对应一侧的安全区(补偿落在带背景色的容器上,色块因此一直铺到状态栏 / home indicator)。
import type { NotifyPosition } from '@skyroc/native-ui';
import { Button, showNotify } from '@skyroc/native-ui';
import { View } from 'react-native';
const POSITIONS: NotifyPosition[] = ['top', 'bottom'];
const NotifyPositions = () => {
return (
<View className="flex-row flex-wrap items-center gap-3 bg-background p-4">
{POSITIONS.map(position => (
<Button
key={position}
variant="tonal"
onPress={() => showNotify({ message: `贴 ${position} 显示`, position })}
>
{position}
</Button>
))}
</View>
);
};
export { NotifyPositions };展示时长与关闭
duration 默认 3000ms,0 表示常驻 —— 此时用返回实例的 close() 关闭。
import { Button, showNotify } from '@skyroc/native-ui';
import { View } from 'react-native';
const NotifyDuration = () => {
function handleManualClose() {
const instance = showNotify({ duration: 0, message: '常驻通知,2 秒后由实例关闭' });
setTimeout(() => instance.close(), 2000);
}
return (
<View className="flex-row flex-wrap items-center gap-3 bg-background p-4">
<Button
variant="tonal"
onPress={() => showNotify({ duration: 1000, message: '1 秒后自动关闭' })}
>
自定义时长
</Button>
<Button
variant="tonal"
onPress={handleManualClose}
>
常驻 + 实例关闭
</Button>
</View>
);
};
export { NotifyDuration };点击事件
传了 onClick 后通知可响应点击;不传时不拦截触摸,下层内容照常可点。
import { Button, showNotify } from '@skyroc/native-ui';
import { View } from 'react-native';
const NotifyInteraction = () => {
return (
<View className="bg-background p-4">
<Button
variant="tonal"
onPress={() =>
showNotify({
duration: 0,
message: '点我触发 onClick',
onClick: () => showNotify({ message: '收到点击', type: 'success' })
})
}
>
可点击
</Button>
</View>
);
};
export { NotifyInteraction };原地更新
实例的 update(options) 原地更新内容与配置,不重放进场动画,并按新的 duration 重新计时。
import { Button, showNotify } from '@skyroc/native-ui';
import { View } from 'react-native';
const NotifyUpdate = () => {
function handleUpdate() {
const instance = showNotify({ duration: 0, message: '处理中...', type: 'primary' });
setTimeout(() => instance.update({ duration: 2000, message: '处理成功', type: 'success' }), 1500);
}
return (
<View className="bg-background p-4">
<Button
variant="tonal"
onPress={handleUpdate}
>
原地更新通知
</Button>
</View>
);
};
export { NotifyUpdate };关闭回调
onClose 在超时关闭、主动关闭、被新通知顶替三条路径下都会触发,且每条通知只触发一次。
import { Button, Text, showNotify } from '@skyroc/native-ui';
import { useState } from 'react';
import { View } from 'react-native';
const NotifyLifecycle = () => {
const [closeCount, setCloseCount] = useState(0);
function handleCountedNotify() {
showNotify({
message: '关闭时计数 +1',
onClose: () => setCloseCount(prev => prev + 1)
});
}
function handleReplaced() {
// 第一条会被第二条顶替,被顶替同样算关闭,它的 onClose 也应各记一次
showNotify({ message: '第一条(即将被顶替)', onClose: () => setCloseCount(prev => prev + 1) });
showNotify({ message: '第二条(顶替了第一条)', onClose: () => setCloseCount(prev => prev + 1) });
}
return (
<View className="bg-background p-4">
<View className="mb-2 flex-row flex-wrap items-center gap-3">
<Button
variant="tonal"
onPress={handleCountedNotify}
>
onClose 计数
</Button>
<Button
variant="tonal"
onPress={handleReplaced}
>
顶替(应 +1)
</Button>
</View>
<Text color="muted">onClose 已触发 {closeCount} 次(每关闭一条只应 +1)</Text>
</View>
);
};
export { NotifyLifecycle };全局默认配置
import { setNotifyDefaultOptions, resetNotifyDefaultOptions } from '@skyroc/native-ui';
setNotifyDefaultOptions({ duration: 5000, type: 'primary' });
resetNotifyDefaultOptions();setNotifyDefaultOptions 是增量合并(与已有默认值合并),resetNotifyDefaultOptions 清空全部。合并优先级是「全局默认 < 调用参数」。
import { Button, resetNotifyDefaultOptions, setNotifyDefaultOptions, showNotify } from '@skyroc/native-ui';
import { View } from 'react-native';
const NotifyDefaults = () => {
function handleShowWithDefaults() {
setNotifyDefaultOptions({ duration: 5000, position: 'bottom', type: 'primary' });
showNotify('使用全局默认配置');
}
function handleResetDefaults() {
resetNotifyDefaultOptions();
showNotify('已恢复默认配置');
}
return (
<View className="flex-row flex-wrap items-center gap-3 bg-background p-4">
<Button
variant="tonal"
onPress={handleShowWithDefaults}
>
设置并使用默认配置
</Button>
<Button
variant="outline"
onPress={handleResetDefaults}
>
重置默认配置
</Button>
</View>
);
};
export { NotifyDefaults };自定义样式与内容
className / classNames 优先使用主题类名;background / color 只在颜色来自主题之外(如服务端下发的品牌色)时使用。message 也可以传自定义节点。
| slot | 作用位置 |
|---|---|
root | 色带本体(背景色、安全区补偿) |
content | 内容容器(内边距、居中) |
message | 消息文字 |
import { Button, Text, showNotify } from '@skyroc/native-ui';
import { View } from 'react-native';
const NotifyCustom = () => {
return (
<View className="flex-row flex-wrap items-center gap-3 bg-background p-4">
<Button
variant="tonal"
onPress={() =>
showNotify({
className: 'bg-carbon',
classNames: { content: 'py-4', message: 'text-base text-carbon-foreground' },
message: '用 className 覆盖(跟随主题)'
})
}
>
className 覆盖
</Button>
<Button
variant="tonal"
onPress={() => showNotify({ background: '#7232dd', color: '#ffffff', message: '写死的品牌色' })}
>
背景色兜底
</Button>
<Button
variant="tonal"
onPress={() =>
showNotify({
message: (
<View className="flex-row items-center gap-2">
<Text className="text-2xl">🎉</Text>
<Text className="text-sm font-medium text-primary-foreground">自定义节点</Text>
</View>
),
type: 'primary'
})
}
>
自定义节点
</Button>
</View>
);
};
export { NotifyCustom };声明式受控模式
<Notify> 组件就地渲染:show 控制显隐,onUpdateShow 接收自动关闭请求(组件到点后只通知,真正的隐藏仍由调用方改 show 完成)。
import { Button, Notify } from '@skyroc/native-ui';
import { useState } from 'react';
import { View } from 'react-native';
const NotifyDeclarative = () => {
const [declarativeShow, setDeclarativeShow] = useState(false);
return (
<View className="bg-background p-4">
<View className="flex-row flex-wrap items-center gap-3">
<Button
variant="outline"
onPress={() => setDeclarativeShow(true)}
>
显示受控 Notify
</Button>
</View>
<Notify
message="受控 Notify,3 秒后自动关闭"
show={declarativeShow}
type="success"
onUpdateShow={setDeclarativeShow}
/>
</View>
);
};
export { NotifyDeclarative };声明式不做贴边定位、也不补安全区 —— 内联在页面里它就是一条普通色块,贴边显示交给命令式路径的渲染器。两条路径共用同一份 duration 默认值规则,不会出现行为分叉。
API
命令式函数
function showNotify(options: NotifyOptions | string): NotifyInstance;
function closeNotify(): void;
function setNotifyDefaultOptions(options: NotifyOptions): void;
function resetNotifyDefaultOptions(): void;NotifyOptions
| 属性 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| message | 消息内容,字符串会自动包一层 Text | ReactNode | - |
| type | 类型,决定背景色与文字色 | 'danger' | 'primary' | 'success' | 'warning' | 'danger' |
| position | 显示位置 | 'top' | 'bottom' | 'top' |
| duration | 自动关闭延时(毫秒),0 表示常驻 | number | 3000 |
| onClick | 点击回调;不传时不拦截触摸,下层内容可点 | () => void | - |
| onClose | 关闭时回调,三条关闭路径都只触发一次 | () => void | - |
| background | 自定义背景色;仅用于主题外的颜色,能写成类名时优先用 className | string | - |
| color | 自定义文字颜色;仅用于主题外的颜色,能写成类名时优先用 classNames.message | string | - |
| className | 色带本体类名,合并在 classNames.root 之后 | string | - |
| classNames | 各 slot 的类名覆盖 | SlotClassNames<NotifySlots> | - |
Notify
声明式组件,属性为 NotifyOptions 加上:
| 属性 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| show | 是否显示 | boolean | false |
| onUpdateShow | 显示状态变更回调(到点时触发) | (show: boolean) => void | - |
类型
import type {
NotifyInstance,
NotifyOptions,
NotifyPosition,
NotifyProps,
NotifySlots,
NotifyType
} from '@skyroc/native-ui';NotifyType
通知类型,决定背景色与文字色。
NotifyPosition
显示位置,命令式路径下还决定安全区补偿画在哪一侧。
NotifySlots
可通过 classNames 覆盖的 slot 名称。
SlotClassNames
classNames 的取值形态:把 slot 名映射到类名,每个 slot 都可选。本页用到的 slot 见 NotifySlots。
NotifyInstance
showNotify 的返回值。
| 字段 | 类型 | 说明 |
|---|---|---|
| close* | () => void | 关闭此条通知;已被后来的通知顶替时不做任何事。 |
| update* | (options: NotifyOptions) => void | 原地更新此条通知的内容,不重放动画,并按新的 duration 重新计时。 |
包内还导出了 notifyVariants、notifyPositionVariants 与 NotifyRenderer(由命令式路径自动挂载,一般不需要直接使用)。