React Native: Анимация сокращающегося заголовка с вкладками
Цель
Im пытается создать представление с анимированным сокращающимся заголовком с вкладкой, содержащей вкладки с прокручиваемым контентом.
См. Изображение.
Настройка
Я использую интерактивную навигацию с помощью TabNavigator. Заголовок представляет собой компонент с фиксированной высотой, в настоящее время над TabNavigator. Заголовок загорается над вкладками все время, занимая драгоценное пространство.
Пробные подходы
-
Я пробовал Janic Duplessis Blog Post, но я не могу заставить его работать из-за вкладок.
-
Я также попытался реализовать его с помощью двух ScrollView/FlatList: один обернутый вокруг всего представления, и одна упаковка содержимого, но я не могу получить ответ на родной для распространения края прокрутки.
Желаемый эффект такой же, как в магазине Google Play.
![Мобильная скриншот Google play]()
Ответы
Ответ 1
Мне удалось осуществить это с Animated.diffClamp
- вы можете проверить код здесь. Я написал статью, подробно объясняющую код здесь
* Я использую пакет native-base для компонентов пользовательского интерфейса (для упрощения кода UI), но интерполяции/определения анимации одинаковы с или без него.
![Demo]()
Ответ 2
Вы можете добиться этого, самостоятельно управляя действиями анимированных прокруток, используя компонент RN-Animated
. Это не совсем то, что вы просили, но его можно легко воспроизвести, чтобы получить правильные результаты, и вам действительно нужно использовать метод renderScrollComponent
любого вида списка, чтобы захватить эту же вещь... так... Вот некоторый код:
Код
constructor(props) {
super(props);
this.headerHeight = 150;
this.state = {
scrollY: new Animated.Value(0),
};
}
render() {
return (
<View style={[
styles.container,
{
width: this.props.display.width,
height: this.props.display.height,
}
]}>
{ this.renderScrollView() }
{ this.renderListHeader() }
</View>
);
}
renderListHeader() {
return (
<Animated.View
style={[
styles.headerContainer,
{
width: this.props.display.width,
height: this.state.scrollY.interpolate({
inputRange: [0, this.headerHeight],
outputRange: [this.headerHeight, this.headerHeight / 2],
extrapolate: 'clamp',
}),
}
]}>
<Text style={[bodyFontStyle, styles.testingText]}>
I am a test!
</Text>
</Animated.View>
);
}
renderScrollView() {
return (
<Animated.ScrollView
bounces={false}
scrollEventThrottle={1}
showsVerticalScrollIndicator={false}
showsHorizontalScrollIndicator={false}
onScroll={Animated.event( [{ nativeEvent: { contentOffset: { y: this.state.scrollY } } }] )}>
<Animated.View
style={[
styles.innerScrollContainer,
{
height: 800,
width: this.props.display.width,
marginTop: this.headerHeight,
}
]}>
<Text style={[bodyFontStyle, styles.innerContainerText]}>
Look ma! No Hands!
</Text>
</Animated.View>
</Animated.ScrollView>
);
}
const styles = StyleSheet.create({
container: {
position: 'relative',
backgroundColor: 'transparent',
},
headerContainer: {
position: 'absolute',
top: 0, left: 0,
overflow: 'hidden',
backgroundColor: 'green',
},
innerScrollContainer: {
position: 'relative',
backgroundColor: 'white',
},
innerContainerText: { color: 'black' },
testingText: { color: 'black' },
});
Я уверен, что вы поняли, что этот код пытается сделать... но просто выложите на него пробой.
Разбивка кода
Я использую реквизиты this.props.display.width/height для отправки ширины/высоты системного уровня ширины/высоты экрана устройства, но если вы предпочитаете использовать flex, то вместо этого.
Вам не обязательно нужен жесткий или статический размер заголовка, просто центральное место (например, уровень класса или уровень JS-модуля), чтобы использовать его в коде вашего класса.
Наконец, просто потому, что я интерполировал данные прокрутки на высоту окна, это не значит, что вам нужно. В примере, который вы показываете, он больше похож на то, что вы хотели бы перевести окно вверх, а не уменьшать его высоту.
Ответ 3
Я пытаюсь сделать подобное, но не добился успеха. Было бы намного легче, если бы у нас не было вкладок. Зачем? Каждая вкладка отображает scrollview/flatlist или аналогичную, и мы прикрепляем к ней одинаковый scrollY на обоих flatlist. Поэтому, когда мы начинаем прокрутку на tab1 и переходим к tab2, он перезапускает позицию заголовка, и это выглядит очень плохо. Я пробовал другой подход без каких-либо успехов. Самое близкое решение - это эта статья, но салфетки не работают и не уверены, можем ли мы ее реализовать. https://blog.expo.io/implementation-complex-animation-in-react-native-by-example-search-bar-with-tab-view-and-collapsing-68bb43be2dcb. Любая помощь или совет были бы замечательными...