bad fix to the tab bar animation

zio/stable
Ansh Nanda 2023-05-16 17:27:46 -07:00
parent 532bc88ecc
commit 139027ac5f
2 changed files with 82 additions and 73 deletions

View File

@ -53,6 +53,7 @@ export const FeedsTabBar = observer(
<UserAvatar avatar={store.me.avatar} size={30} />
</TouchableOpacity>
<TabBar
key={store.me.savedFeeds.listOfPinnedFeedNames.join(',')}
{...props}
items={items}
indicatorPosition="bottom"

View File

@ -1,10 +1,9 @@
import React, {createRef, useState, useMemo, useRef} from 'react'
import {Animated, StyleSheet, View} from 'react-native'
import {Animated, StyleSheet, View, ScrollView} from 'react-native'
import {Text} from '../util/text/Text'
import {PressableWithHover} from '../util/PressableWithHover'
import {usePalette} from 'lib/hooks/usePalette'
import {isDesktopWeb} from 'platform/detection'
import {ScrollView} from 'react-native-gesture-handler'
interface Layout {
x: number
@ -35,59 +34,71 @@ export function TabBar({
onPressSelected,
}: TabBarProps) {
const pal = usePalette('default')
// const [itemLayouts, setItemLayouts] = useState<Layout[]>(
// items.map(() => ({x: 0, width: 0})),
// )
const [itemLayouts, setItemLayouts] = useState<Layout[]>(
items.map(() => ({x: 0, width: 0})),
)
const itemRefs = useMemo(
() => Array.from({length: items.length}).map(() => createRef<View>()),
[items.length],
)
// const panX = Animated.add(position, offset)
const panX = Animated.add(position, offset)
const containerRef = useRef<View>(null)
const [scrollX, setScrollX] = useState(0)
// const indicatorStyle = {
// backgroundColor: indicatorColor || pal.colors.link,
// bottom:
// indicatorPosition === 'bottom' ? (isDesktopWeb ? 0 : -1) : undefined,
// top: indicatorPosition === 'top' ? (isDesktopWeb ? 0 : -1) : undefined,
// transform: [
// {
// translateX: panX.interpolate({
// inputRange: items.map((_item, i) => i),
// outputRange: itemLayouts.map(l => l.x + l.width / 2),
// }),
// },
// {
// scaleX: panX.interpolate({
// inputRange: items.map((_item, i) => i),
// outputRange: itemLayouts.map(l => l.width),
// }),
// },
// ],
// }
const indicatorStyle = useMemo(
() => ({
backgroundColor: indicatorColor || pal.colors.link,
bottom:
indicatorPosition === 'bottom' ? (isDesktopWeb ? 0 : -1) : undefined,
top: indicatorPosition === 'top' ? (isDesktopWeb ? 0 : -1) : undefined,
transform: [
{
translateX: panX.interpolate({
inputRange: items.map((_item, i) => i),
outputRange: itemLayouts.map(l => l.x + l.width / 2 - scrollX),
}),
},
{
scaleX: panX.interpolate({
inputRange: items.map((_item, i) => i),
outputRange: itemLayouts.map(l => l.width),
}),
},
],
}),
[
indicatorColor,
indicatorPosition,
itemLayouts,
items,
panX,
pal.colors.link,
scrollX,
],
)
// const onLayout = () => {
// const promises = []
// for (let i = 0; i < items.length; i++) {
// promises.push(
// new Promise<Layout>(resolve => {
// if (!containerRef.current || !itemRefs[i].current) {
// return resolve({x: 0, width: 0})
// }
const onLayout = () => {
const promises = []
for (let i = 0; i < items.length; i++) {
promises.push(
new Promise<Layout>(resolve => {
if (!containerRef.current || !itemRefs[i].current) {
return resolve({x: 0, width: 0})
}
// itemRefs[i].current?.measureLayout(
// containerRef.current,
// (x: number, _y: number, width: number) => {
// resolve({x, width})
// },
// )
// }),
// )
// }
// Promise.all(promises).then((layouts: Layout[]) => {
// setItemLayouts(layouts)
// })
// }
itemRefs[i].current?.measureLayout(
containerRef.current,
(x: number, _y: number, width: number) => {
resolve({x, width})
},
)
}),
)
}
Promise.all(promises).then((layouts: Layout[]) => {
setItemLayouts(layouts)
})
}
const onPressItem = (index: number) => {
onSelect?.(index)
@ -100,31 +111,33 @@ export function TabBar({
<View
testID={testID}
style={[pal.view, styles.outer]}
// onLayout={onLayout}
onLayout={onLayout}
ref={containerRef}>
<Animated.View style={[styles.indicator]} />
<ScrollView horizontal={true} showsHorizontalScrollIndicator={false}>
<Animated.View style={[styles.indicator, indicatorStyle]} />
<ScrollView
horizontal={true}
showsHorizontalScrollIndicator={false}
onScroll={({nativeEvent}) => {
setScrollX(nativeEvent.contentOffset.x)
}}>
{items.map((item, i) => {
const selected = i === selectedPage
return (
<Animated.View key={item} style={selected ? styles.active : []}>
<PressableWithHover
ref={itemRefs[i]}
style={[
indicatorPosition === 'top'
? styles.itemTop
: styles.itemBottom,
]}
hoverStyle={pal.viewLight}
onPress={() => onPressItem(i)}>
<Text
type="xl-bold"
testID={testID ? `${testID}-${item}` : undefined}
style={selected ? pal.text : pal.textLight}>
{item}
</Text>
</PressableWithHover>
</Animated.View>
<PressableWithHover
ref={itemRefs[i]}
key={item}
style={
indicatorPosition === 'top' ? styles.itemTop : styles.itemBottom
}
hoverStyle={pal.viewLight}
onPress={() => onPressItem(i)}>
<Text
type="xl-bold"
testID={testID ? `${testID}-${item}` : undefined}
style={selected ? pal.text : pal.textLight}>
{item}
</Text>
</PressableWithHover>
)
})}
</ScrollView>
@ -155,7 +168,6 @@ const styles = isDesktopWeb
height: 3,
zIndex: 1,
},
active: {},
})
: StyleSheet.create({
outer: {
@ -178,8 +190,4 @@ const styles = isDesktopWeb
width: 1,
height: 3,
},
active: {
borderBottomColor: 'blue',
borderBottomWidth: 3,
},
})