FlatList 超出其内容的容器:How to make FlatList with fixed height
FlatList exceeds its container with its content: How to make FlatList with fixed height
我有一个<FlatList />
。在这个 <FlatList />
我还有另一个 <FlatList />
。嵌套的 <FlatList />
给了我一些奇怪的行为。它超出了容器的边距。如您所见,标志越过 yellow
框,代表 <FlatList />
.
的边界
这是重现问题的 Snack https://snack.expo.dev/@stophfacee/nested-flatlist。
请注意:动画(触摸 hotpink
矩形时)无法正常工作。我不确定为什么。但是,我仍然包含它,因为我不确定这是否可能是问题所在。
考虑到 Dan 和 AmerllicA 的建议,这是 SectionList
的一种可能用法,它似乎可以解决您的问题:
别忘了从 react-native
导入 SectionList
!
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>
)}
/>
);
这可能就是您想要的结果。请检查一次!
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',
},
});
我对本机反应不是很好,我也看不到你的问题,但你提到它正在通过容器。我查看了您的代码,我知道在正常情况下 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% width/height.
时,您必须小心添加额外的 paddings/borders/etc
我有一个<FlatList />
。在这个 <FlatList />
我还有另一个 <FlatList />
。嵌套的 <FlatList />
给了我一些奇怪的行为。它超出了容器的边距。如您所见,标志越过 yellow
框,代表 <FlatList />
.
这是重现问题的 Snack https://snack.expo.dev/@stophfacee/nested-flatlist。
请注意:动画(触摸 hotpink
矩形时)无法正常工作。我不确定为什么。但是,我仍然包含它,因为我不确定这是否可能是问题所在。
考虑到 Dan 和 AmerllicA 的建议,这是 SectionList
的一种可能用法,它似乎可以解决您的问题:
别忘了从 react-native
导入 SectionList
!
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>
)}
/>
);
这可能就是您想要的结果。请检查一次!
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',
},
});
我对本机反应不是很好,我也看不到你的问题,但你提到它正在通过容器。我查看了您的代码,我知道在正常情况下 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% width/height.
时,您必须小心添加额外的 paddings/borders/etc