Я пытаюсь создать эту панель навигации в моем RN-приложении. По сути, горизонтальный вид прокрутки категорий, которые выделяют текущую категорию на основе прокрутки Y.
Благодаря видео великого Уильяма Кэндильона ( https://www.youtube.com/watch?v=xutPT1oZL2M&t=1369s) Я довольно близко, но у меня есть главная проблема.
Я использую интерполяцию для перевода позиции X категории View при прокрутке. И тогда у меня есть Scrollview, оборачивающий этот Анимированный Вид. Проблема в том, что Scrollview не работает, так как он не имеет ссылки на позицию анимированного представления. Как вы можете видеть в gif ниже (синий -> Animated.View / red -> Scrollview)
Мне нравится подход интерполяции, поскольку он декларативный и работает в собственном потоке, поэтому я постарался максимально избежать создания слушателя, подключенного к функции scrollTo ().
Какой подход вы бы рассмотрели?
export default ({ y, scrollView, tabs }) => {
const index = new Value(0);
const [measurements, setMeasurements] = useState(
new Array(tabs.length).fill(0)
);
const indexTransition = withTransition(index);
const width = interpolate(indexTransition, {
inputRange: tabs.map((_, i) => i),
outputRange: measurements
});
const translateX = interpolate(indexTransition, {
inputRange: tabs.map((_tab, i) => i),
outputRange: measurements.map((_, i) => {
return (
-1 *
measurements
.filter((_measurement, j) => j < i)
.reduce((acc, m) => acc + m, 0) -
8 * i
);
})
});
const style = {
borderRadius: 24,
backgroundColor: 'black',
width,
flex: 1
};
const maskElement = <Animated.View {...{ style }} />;
useCode(
() =>
block(
tabs.map((tab, i) =>
cond(
i === tabs.length - 1
? greaterOrEq(y, tab.anchor)
: and(
greaterOrEq(y, tab.anchor),
lessOrEq(y, tabs[i + 1].anchor)
),
set(index, i)
)
)
),
[index, tabs, y]
);
return (
<Animated.View style={[styles.container, {}]}>
<Animated.ScrollView
scrollEventThrottle={16}
horizontal
style={{ backgroundColor: 'red', flex: 1 }}
>
<Animated.View
style={{
transform: [{ translateX }],
backgroundColor: 'blue'
}}
>
<Tabs
onPress={i => {
if (scrollView) {
scrollView.getNode().scrollTo({ y: tabs[i].anchor + 1 });
}
}}
onMeasurement={(i, m) => {
measurements[i] = m;
setMeasurements([...measurements]);
}}
{...{ tabs, translateX }}
/>
</Animated.View>
</Animated.ScrollView>
</Animated.View>
);
};