Flex макет с ScrollView
Некоторое время назад я делал макеты для экранов в React Native с Flexbox и не столкнулся с какими-либо проблемами до сегодняшнего дня, когда мне нужно было сделать этот очень простой макет:
- Раздел заголовка (не NavBar).
- Раздел содержимого → ScrollView с плоским списком внутри него.
- Раздел нижнего колонтитула.
Я хочу, чтобы раздел содержимого был в 3 раза больше, чем верхний и нижний колонтитулы, поэтому, естественно, я установил flex на 1 (верхний колонтитул), 3 (контентный), 1 (нижний колонтитул).
Независимо от того, что содержимое остается, как будто оно имеет flex: 1
,
Единственный способ, которым я мог управлять макетом так, как я хотел, это оставить контент flex: 1
и установите нижний колонтитул и заголовок в flex: 0.33
,
Я подозреваю, что это может быть как-то связано с реквизитом ScrollView's contentContainerStyle, который я установил в flexGrow: 1, flexShrink: 1
,
Вот минимальный пример, который воспроизводит это.
2 ответа
Обновление 2:
Мне было указано, что я не должен использовать ListView, заключенный в ScrollView, поскольку может произойти следующее:
Это может привести к некоторым странным поведениям, таким как
onEndReached
стрельба непрерывно.Обтекание ListView внутри ScrollView заставляет родительское действие прокрутки доминировать над дочерним действием прокрутки, которое приводит только к прокрутке ScrollView.
Хорошо, я не уверен, почему это работает, но нашел решение после нескольких часов попыток:
После шага, упомянутого в обновлении 1, я добавил следующий стиль flexGrow: 0
к FlatList внутри ScrollView, и контент стал центрированным и уменьшал размер контента, пока он не стал прокручиваемым, работает также отлично.
В основном это результирующий код:
render() {
return (
<View style={{ flex: 1 }}>
<View style={{ flex: 1 }}>
<Text>HEADER</Text>
</View>
<View style={{ flex: 6 }}> // Change this to affect ScrollView size
<ScrollView contentContainerStyle={{ flexGrow: 1, justifyContent: 'center' }}>
<FlatList
data={listItems}
renderItem={Item}
keyExtractor={(index, item) => item}
style={{ flexGrow: 0 }} // This was the solution to centering
/>
</ScrollView>
</View>
<View style={{ flex: 1 }}>
<Text>FOOTER</Text>
</View>
</View>
);
}
Вот окончательное рабочее решение, если вы хотите попробовать его.
Обновление 1:
Управляется размером ScrollView с помощью Flex в обычном режиме (то есть с использованием целочисленных значений flex, как и предполагалось вначале), оборачивая ScrollView внутри View с помощью flex: 1
,
Недостатком является то, что если я устанавливаю секцию Scrollable (контент) на достаточно высокое значение flex, чтобы он больше не прокручивался, контент не отображается по центру. Даже если justifyContent: 'center'
применены.
Вот пример ОБНОВЛЕНИЕ 1.
С минимальными изменениями это работает для меня, я использовал этот стиль:
const styles = StyleSheet.create({
screen: {
backgroundColor: 'lightgray',
flex: 1,
},
header: {
flex: 0.33,
backgroundColor: 'lightblue',
justifyContent: 'center',
alignItems: 'center',
},
scrollView: {
flex: 1,
},
footer: {
backgroundColor: 'lightpink',
flex: 0.33,
alignItems: 'center',
justifyContent: 'center',
},
});
Полный код >>> https://snack.expo.io/Hk9tbHR4Q
Это результат: