#javascript #react-native #react-native-flatlist #flatlist
Вопрос:
У меня есть <FlatList />
. Внутри этого <FlatList />
у меня есть еще <FlatList />
одно . Вложенное <FlatList />
дает мне какое-то странное поведение. Он превышает пределы своего контейнера. Как вы можете видеть, Флаги идут над yellow
полем, которые представляют границы <FlatList />
.
Вот вам закуска https://snack.expo.dev/@stophfacee/nested-flatlist что воспроизводит проблему.
Пожалуйста, обратите внимание: анимация (при касании hotpink
прямоугольника) работает неправильно. Я не уверен, почему. Однако я все равно включил его, потому что не уверен, что в этом может быть проблема.
Комментарии:
1.
overflow: hidden
Дает ли добавлениеstyles.flagsContainer
вам желаемое поведение?2. @Dan, который ограничивает его
yellow
контейнером, но делает его разворачиваемым.3. Ну, я думаю, вам следует проверить recyclerlistview
4. Я предпочитаю использовать
SectionList
для таких вещей.5. Что делать, если вы измените внешний плоский список на вид прокрутки, содержащий все карты (включая плоский список)?
Ответ №1:
Возможно, это тот результат, которого вы хотели. Пожалуйста, проверьте это один раз!
import React, { useState } from 'react';
import {
View,
StyleSheet,
Animated,
Dimensions,
TouchableOpacity,
Text,
ScrollView,
} from 'react-native';
import Constants from 'expo-constants';
import CountryFlag from 'react-native-country-flag';
import { FlatList } from 'react-native-gesture-handler';
export default function App() {
const _renderFlag = (country) => {
return (
<TouchableOpacity onPress={() => console.log('Flag touched')}>
<CountryFlag
isoCode={'NZ'}
size={50}
style={{ alignSelf: 'flex-end' }}
/>
</TouchableOpacity>
);
};
const _createCard = (card, index) => {
return (
<View style={styles.card} key={index}>
<TouchableOpacity
style={styles.touchable}
onPress={() => console.log('toggle')}>
<Text>{card}</Text>
</TouchableOpacity>
<View style={{ height: 200 }}>
<FlatList
nestedScrollEnabled={true}
style={{ marginTop: 20, backgroundColor: 'yellow' }}
columnWrapperStyle={{
justifyContent: 'space-around',
}}
ItemSeparatorComponent={() => <View style={{ margin: 10 }}/>}
numColumns={3}
data={[
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
]}
renderItem={_renderFlag}
keyExtractor={(item, index) => index.toString()}
getItemLayout={(data, index) => ({
length: 50,
offset: 50 * index,
index,
})}
/>
</View>
</View>
);
};
return (
<View style={{ flex: 1 }}>
<FlatList
style={{ margin: 20 }}
data={['a', 'b', 'c']}
keyExtractor={(item, index) => index.toString()}
renderItem={({ item, index }) => _createCard(item, index)}
/>
</View>
);
}
const styles = StyleSheet.create({
card: {
borderColor: 'red',
borderWidth: 2,
padding: 8,
marginBottom: 15,
},
touchable: {
backgroundColor: 'hotpink',
height: 50,
width: '100%',
justifyContent: 'center',
alignItems: 'center',
},
});
Комментарии:
1. Это не решение проблемы. Когда вы вкладываете a
<FlatList />
в a<ScrollView />
, вы получаете следующее предупреждение: виртуализированные списки никогда не должны быть вложены в простые представления прокрутки с той же ориентацией — вместо этого используйте другой контейнер с поддержкой VirtualizeList.2. Я обновил ответ. Немного покопавшись, я обнаружил, что для включения прокрутки вложенного плоского списка мы должны импортировать плоский список из обработчика жестов react-native.
Ответ №2:
Я не очень хорошо разбираюсь в react native, и я действительно не вижу вашей проблемы, однако вы упомянули, что она проходит через контейнер. Я взглянул на ваш код и знаю, что в обычном css/web ваш стиль не будет работать.
У вас есть <FlatList
, и вы придали ему стиль style={styles.container}
. Стиль этого контейнера таков:
container: {
paddingTop: 50,
height: '100%',
widht: '100%',
}
Там вы указываете, чтобы контейнер был height: 100%
, а затем вы также указываете, чтобы он имел заполнение 50. Это приведет к общей высоте 100% 50. Для того, чтобы исправить это, вы должны использовать height: calc(100% - 50)
вместе с вашей прокладкой, тогда она идеально подойдет.
Я понятия не имею, является ли это вашей реальной проблемой, но я не вижу, как это будет работать, если только react native не делает какие-то странные вещи с дополнениями.
На самом деле вы также сделали это в нескольких местах на своей карте, которую вы использовали width: '90%'
вместе с padding: 8
, так что эта карта переполнит свой контейнер 6. Там вам тоже нужно это сделать width: calc(100% - 16)
.
Это станет еще более запутанным, если у вас есть borderWidth: 2
и у вас нет box-sizing: border-box
, что приведет к тому, что он будет еще на 4 больше по ширине контейнера.
Вы должны быть осторожны с дополнительными дополнениями/границами/и т.д., Которые вы добавляете, когда указываете, что это 100% ширина/высота.
Ответ №3:
Принимая во внимание советы Дэна и Амерлики, это возможное использование SectionList
, которое, по-видимому, решит вашу проблему:
Не забудьте импортировать SectionList
из react-native
!
const sections = [
{ title: 'Section 1', data: ['a', 'b', 'c'].map((card, index) => _createCard(card, index)) },
{ title: 'Section 2', data: ['a', 'b', 'c'].map((card, index) => _createCard(card, index)) },
{ title: 'Section 3', data: ['a', 'b', 'c'].map((card, index) => _createCard(card, index)) },
];
return (
<SectionList
initialNumToRender={2}
contentContainerStyle={{ alignItems: 'center' }}
style={styles.container}
sections={sections}
renderItem={(item) => {
return item.item;
}}
renderSectionHeader={({ section: { title } }) => (
<View style={{ backgroundColor: 'pink', width:200, alignItems: 'center', justifyContent: 'center', height: 50 }}>
<Text>{title}</Text>
</View>
)}
/>
);