具有 3 张卡片分页布局的 React-Native FlatList
React-Native FlatList with 3 cards paging layout
在 this snack 中,我试图在屏幕中央放置 3 张带有水平 FlatList 的卡片,并启用分页以跳转到滚动时的下 3 张卡片。
但是布局在滚动后开始被破坏,next/previous 卡片的一些像素出现在视图中。
我应该如何设置此列表的样式以始终恰好在屏幕中央显示 3 张卡片,并且滚动会跳转到包含下 3 张卡片的下一页?或者像 GooglePlay 商店一样,固定像素的 previous/next 卡片在主要 3 张卡片的左侧和右侧可见。 (下面的示例屏幕截图)
<View style={{flex:1,justifyContent: 'center', marginLeft: 5, marginRight: 5,}}>
<FlatList
horizontal
pagingEnabled
data={data}
keyExtractor={(item) => `ìtem-${item}`}
renderItem={({ item }) => (
<Card style={{width:Dimensions.get("window").width/3-5,marginRight:5}}>
{/* some content */}
</Card>
)}
/>
</View>
我不需要像 snap-carousel
这样的图书馆...
好的,经过大量的工作和测试,我终于能够解决这个问题。
snapToInterval
必须捕捉到整个屏幕的间隔。
如果您使用 pWidth *3
,它将不起作用。现在你可能会问为什么,我真的不明白,这可能与浮点值有关。
但是如果你使用 snapToInterval={Dimensions.get('window').width}
它应该可以工作。
看看snack例子
使用 Scrollview 属性 snapToOffsets 来实现。
喜欢 google 播放示例(一一)尝试 snack.
你的例子(三乘三)试试snack.
如何使用 snapToOffsets?
const snapToOffsetsLikeGooglePlay = data.map((x, i) => {
return ((i * itemWidth) + startScroll)
})
const snapToOffsetsLikeYourExample = data.map((x, i) => {
return ((i * (itemWidth) * previewCount) + startScroll)
})
//see the example below to know
//what is `startScroll` and `previewCount` mean?
//and how to calculate `itemWidth`?
这里是完整的例子
import React from 'react';
import {FlatList, Text} from 'react-native';
import { View, StyleSheet, ScrollView, Dimensions } from 'react-native';
const { width } = Dimensions.get('window');
//you need to preview n items.
const previewCount = 3;
//to center items
//the screen will show `previewCount` + 1/4 firstItemWidth + 1/4 lastItemWidth
//so for example if previewCount = 3
//itemWidth will be =>>> itemWidth = screenWidth / (3 + 1/4 + 1/4)
const itemWidth = width/(previewCount + .5);
//to center items you start from 3/4 firstItemWidth
const startScroll = (itemWidth * 3/4);
const App = () => {
const data = [...Array(24).keys()];
const flatlistRef = React.useRef();
React.useEffect(() => {
if (flatlistRef.current) flatlistRef.current.scrollToOffset({
offset:startScroll, animated: false
});
}, [flatlistRef]);
const snapToOffsetsLikeGooglePlay = data.map((x, i) => {
return ((i * itemWidth) + startScroll)
})
const snapToOffsets = data.map((x, i) => {
return ((i * (itemWidth) * previewCount) + startScroll)
})
return (
<FlatList
ref={flatlistRef}
style={styles.container}
pagingEnabled={true}
horizontal= {true}
decelerationRate={0}
snapToOffsets={snapToOffsets}
snapToAlignment={"center"}
data={data}
renderItem={({item, index}) => (
<View style={styles.view} >
<Text style={styles.text}>{index}</Text>
</View>
)}/>
);
}
export default App;
const styles = StyleSheet.create({
container: {
},
view: {
marginTop: 100,
backgroundColor: '#eee',
width: itemWidth - 20, //20 is margin left and right
margin: 10,
height: 140,
borderRadius: 10,
justifyContent : 'center',
alignItems : 'center',
},
text : {
fontSize : 60,
fontWeight : 'bold',
color : '#aaa',
},
});
更新:作为@Amir-Mousavi 评论从零开始
一一尝试snack
1-) 评论 useEffect.
2-) 设置 const startScroll = (itemWidth * 3/4)
三个三个尝试snack
1-) 评论 useEffect.
2-) 设置 const startScroll = (itemWidth * 2.75)
在 this snack 中,我试图在屏幕中央放置 3 张带有水平 FlatList 的卡片,并启用分页以跳转到滚动时的下 3 张卡片。
但是布局在滚动后开始被破坏,next/previous 卡片的一些像素出现在视图中。
我应该如何设置此列表的样式以始终恰好在屏幕中央显示 3 张卡片,并且滚动会跳转到包含下 3 张卡片的下一页?或者像 GooglePlay 商店一样,固定像素的 previous/next 卡片在主要 3 张卡片的左侧和右侧可见。 (下面的示例屏幕截图)
<View style={{flex:1,justifyContent: 'center', marginLeft: 5, marginRight: 5,}}>
<FlatList
horizontal
pagingEnabled
data={data}
keyExtractor={(item) => `ìtem-${item}`}
renderItem={({ item }) => (
<Card style={{width:Dimensions.get("window").width/3-5,marginRight:5}}>
{/* some content */}
</Card>
)}
/>
</View>
我不需要像 snap-carousel
这样的图书馆...
好的,经过大量的工作和测试,我终于能够解决这个问题。
snapToInterval
必须捕捉到整个屏幕的间隔。
如果您使用 pWidth *3
,它将不起作用。现在你可能会问为什么,我真的不明白,这可能与浮点值有关。
但是如果你使用 snapToInterval={Dimensions.get('window').width}
它应该可以工作。
看看snack例子
使用 Scrollview 属性 snapToOffsets 来实现。
喜欢 google 播放示例(一一)尝试 snack.
你的例子(三乘三)试试snack.
如何使用 snapToOffsets?
const snapToOffsetsLikeGooglePlay = data.map((x, i) => {
return ((i * itemWidth) + startScroll)
})
const snapToOffsetsLikeYourExample = data.map((x, i) => {
return ((i * (itemWidth) * previewCount) + startScroll)
})
//see the example below to know
//what is `startScroll` and `previewCount` mean?
//and how to calculate `itemWidth`?
这里是完整的例子
import React from 'react';
import {FlatList, Text} from 'react-native';
import { View, StyleSheet, ScrollView, Dimensions } from 'react-native';
const { width } = Dimensions.get('window');
//you need to preview n items.
const previewCount = 3;
//to center items
//the screen will show `previewCount` + 1/4 firstItemWidth + 1/4 lastItemWidth
//so for example if previewCount = 3
//itemWidth will be =>>> itemWidth = screenWidth / (3 + 1/4 + 1/4)
const itemWidth = width/(previewCount + .5);
//to center items you start from 3/4 firstItemWidth
const startScroll = (itemWidth * 3/4);
const App = () => {
const data = [...Array(24).keys()];
const flatlistRef = React.useRef();
React.useEffect(() => {
if (flatlistRef.current) flatlistRef.current.scrollToOffset({
offset:startScroll, animated: false
});
}, [flatlistRef]);
const snapToOffsetsLikeGooglePlay = data.map((x, i) => {
return ((i * itemWidth) + startScroll)
})
const snapToOffsets = data.map((x, i) => {
return ((i * (itemWidth) * previewCount) + startScroll)
})
return (
<FlatList
ref={flatlistRef}
style={styles.container}
pagingEnabled={true}
horizontal= {true}
decelerationRate={0}
snapToOffsets={snapToOffsets}
snapToAlignment={"center"}
data={data}
renderItem={({item, index}) => (
<View style={styles.view} >
<Text style={styles.text}>{index}</Text>
</View>
)}/>
);
}
export default App;
const styles = StyleSheet.create({
container: {
},
view: {
marginTop: 100,
backgroundColor: '#eee',
width: itemWidth - 20, //20 is margin left and right
margin: 10,
height: 140,
borderRadius: 10,
justifyContent : 'center',
alignItems : 'center',
},
text : {
fontSize : 60,
fontWeight : 'bold',
color : '#aaa',
},
});
更新:作为@Amir-Mousavi 评论从零开始
一一尝试snack
1-) 评论 useEffect.
2-) 设置 const startScroll = (itemWidth * 3/4)
三个三个尝试snack
1-) 评论 useEffect.
2-) 设置 const startScroll = (itemWidth * 2.75)