This commit is contained in:
oneao committed 2026-01-14 22:25:14 +08:00
1 parent cb4562361a
commit b38583a9fe
11 files changed
+174 -85

No files matched your search

@@ -4,14 +4,14 @@ import PagerView from 'react-native-pager-view'
interface TabItem {
label: string
key: string
key: string | number
content?: React.ReactNode
}
interface TabProps {
data?: TabItem[]
defaultIndex?: number
onChange?: (index: number) => void
defaultKey?: TabItem['key']
onChange?: (key: TabItem['key']) => void
tabBarClass?: string
tabItemClass?: string
activeTabItemClass?: string
@@ -19,47 +19,66 @@ interface TabProps {
export default function Tab({
data,
defaultIndex = 0,
defaultKey,
onChange,
tabBarClass = 'flex flex-row gap-2 overflow-hidden',
tabItemClass = 'items-center justify-center rounded-md px-4 py-2 bg-gray-200',
activeTabItemClass = 'items-center justify-center rounded-md px-4 py-2 bg-gray-800',
}: TabProps) {
const [selectedIndex, setSelectedIndex] = useState(defaultIndex)
const pagerRef = useRef<PagerView>(null)
if (!data || data.length === 0)
return null
// 判断是否至少有一个 tab 含 content
// 默认选中 key(没传就用第一个)
const initialKey = defaultKey ?? data[0].key
const [selectedKey, setSelectedKey] = useState(initialKey)
const pagerRef = useRef<PagerView>(null)
// 是否有 content
const hasContent = useMemo(
() => data.some(item => item.content),
[data],
)
const handlePress = (index: number) => {
setSelectedIndex(index)
onChange?.(index)
if (hasContent)
pagerRef.current?.setPage(index)
// key -> index
const getIndexByKey = (key: TabItem['key']) =>
data.findIndex(item => item.key === key)
// index -> key
const getKeyByIndex = (index: number) =>
data[index]?.key
const handlePress = (key: TabItem['key']) => {
setSelectedKey(key)
onChange?.(key)
if (hasContent) {
const index = getIndexByKey(key)
if (index !== -1)
pagerRef.current?.setPage(index)
}
}
const onPageSelected = (e: any) => {
const index = e.nativeEvent.position
setSelectedIndex(index)
onChange?.(index)
const key = getKeyByIndex(index)
if (key !== undefined) {
setSelectedKey(key)
onChange?.(key)
}
}
return (
<View className="flex-1">
{/* tab bar */}
<View className={tabBarClass}>
{data.map((item, index) => {
const isActive = index === selectedIndex
{data.map((item) => {
const isActive = item.key === selectedKey
return (
<Pressable
key={item.key}
onPress={() => handlePress(index)}
onPress={() => handlePress(item.key)}
className={isActive ? activeTabItemClass : tabItemClass}
>
<Text className={isActive ? 'text-white' : 'text-gray-700'}>
@@ -74,7 +93,7 @@ export default function Tab({
<PagerView
ref={pagerRef}
style={{ flex: 1, marginTop: 16 }}
initialPage={defaultIndex}
initialPage={getIndexByKey(initialKey)}
onPageSelected={onPageSelected}
>
{data.map(item => (