水平滚动视图捕捉反应本机
Horizontal scrollview snapping react native
您好,我正在尝试实现 scrollview
居中对齐
如下所示 gif
link
但是做不到。以下是实现此目的的本机反应代码。
或者是否有任何方法可以滚动到滚动视图元素的特定索引,例如 android?
如有任何帮助,我们将不胜感激。
提前致谢
<ScrollView
style={[styles.imgContainer,{backgroundColor:colorBg,paddingLeft:20}]}
automaticallyAdjustInsets={false}
horizontal={true}
pagingEnabled={true}
scrollEnabled={true}
decelerationRate={0}
snapToAlignment='center'
snapToInterval={DEVICE_WIDTH-100}
scrollEventThrottle={16}
onScroll={(event) => {
var contentOffsetX=event.nativeEvent.contentOffset.x;
var contentOffsetY=event.nativeEvent.contentOffset.y;
var cellWidth = (DEVICE_WIDTH-100).toFixed(2);
var cellHeight=(DEVICE_HEIGHT-200).toFixed(2);
var cellIndex = Math.floor(contentOffsetX/ cellWidth);
// Round to the next cell if the scrolling will stop over halfway to the next cell.
if ((contentOffsetX- (Math.floor(contentOffsetX / cellWidth) * cellWidth)) > cellWidth) {
cellIndex++;
}
// Adjust stopping point to exact beginning of cell.
contentOffsetX = cellIndex * cellWidth;
contentOffsetY= cellIndex * cellHeight;
event.nativeEvent.contentOffsetX=contentOffsetX;
event.nativeEvent.contentOffsetY=contentOffsetY;
// this.setState({contentOffsetX:contentOffsetX,contentOffsetY:contentOffsetY});
console.log('cellIndex:'+cellIndex);
console.log("contentOffsetX:"+contentOffsetX);
// contentOffset={{x:this.state.contentOffsetX,y:0}}
}}
>
{rows}
</ScrollView>
有几个选项。这里有两个我已经尝试过并且工作正常。我更喜欢第二个,因为正如它的文档所说 "like ListView, this can render hundreds of pages without performance issue".
您不需要其他库,您可以使用 ScrollView 做到这一点。您只需要在您的组件中添加以下道具。
horizontal= {true}
decelerationRate={0}
snapToInterval={200} //your element width
snapToAlignment={"center"}
查看此快餐以了解有关如何实施它的更多详细信息
https://snack.expo.io/H1CnjIeDb
在ScrollView
中使用pagingEnabled
属性。
const screenHeight = Dimensions.get('window').height;
class Screen extends Component {
constructor(props) {
super(props);
}
render() {
return (
<ScrollView pagingEnabled>
<Page1 style={{height: screenHeight}} />
<Page2 style={{height: screenHeight}} />
</ScrollView>
);
}
}
如果您不想使用 snapToInterval 因为长列表未对齐,您可以使用更精确的 snapToOffsets。
例如:
const { width } = Dimensions.get('window');
this.IMAGE_WIDTH = width * (1 / 2.5)
this.image_margin = 5
this.nishhar = width - ((this.IMAGE_WIDTH + this.image_margin) * 2 + this.image_margin * 2)
dataNum = [1, 2, 3, 4, 5, 6]
return (<FlatList
data={dataNum}
renderItem={item => {
return (
<View style={{
backgroundColor: item.index % 2 == 0 ? 'red' : 'blue',
width: this.IMAGE_WIDTH,
height: this.IMAGE_WIDTH,
marginLeft: this.image_margin,
marginRight: this.image_margin,
}}>
</View>)
}}
keyExtractor={this.keyGenerator}
horizontal={true}
snapToAlignment={"start"}
snapToOffsets={[...Array(dataNum.length)].map((x, i) => (i * (this.IMAGE_WIDTH + 2 * this.image_margin) - (this.nishhar * 0.5)))}
decelerationRate={"fast"}
pagingEnabled
/>)
或者您也可以查看此示例:
https://snack.expo.io/SyWXFqDAB
我在 iOS 上遇到了 FlatList 的 snapToInterval
逻辑问题(在水平列表上它并不总是正确地捕捉到 start
) - 我通过增加以下属性的值来解决这个问题(我有单项滑块)
maxToRenderPerBatch={6}
initialNumToRender={6}
windowSize={6}
尝试使用 snapToOffsets
道具。不过这需要简单的加法和乘法。
要创建显示 2 个元素的对齐效果,以及与超出边界的左右元素 10pts;
// import useWindowDimensions from 'react-native'
const { width: windowWidth } = useWindowDimensions();
// the width of a card in ScrollView
// 20 is so out of bound cards on left & right can have 10pts visible;
const cardWidth = (windowWidth / 2) - 20;
// gap between each cards;
const gap = 16;
const halfGap = gap / 2;
const cardContent = [1, 2, 3, 4, 5]
// THIS IS THE FUN PART
const snapOffsets = cardContent
.map((_, index) => {
return (cardWidth * index) + (halfGap * index)
})
// add left and right margin to <Card/> for gap effect,
// as well as width using cardWidth above
// conditional left margin to first card, and right margin to last card
return (
<ScrollView
horizontal={true}
snapToOffsets={snapOffsets}
>
{
cardContent.map((item, index, arr) => {
return (
<Card
key={index}
title={item}
style={{
width: cardWidth,
marginLeft: index == 0 ? gap : 0,
marginRight: index == arr.length - 1 ? gap : halfGap
}}
/>
)
})
}
</ScrollView>
)
就是这样。您可以重构垂直模式。
For a better edge to edge effect, make sure that ancestor containers don't have padding
您好,我正在尝试实现 scrollview
居中对齐
如下所示 gif
link
但是做不到。以下是实现此目的的本机反应代码。
或者是否有任何方法可以滚动到滚动视图元素的特定索引,例如 android?
如有任何帮助,我们将不胜感激。 提前致谢
<ScrollView
style={[styles.imgContainer,{backgroundColor:colorBg,paddingLeft:20}]}
automaticallyAdjustInsets={false}
horizontal={true}
pagingEnabled={true}
scrollEnabled={true}
decelerationRate={0}
snapToAlignment='center'
snapToInterval={DEVICE_WIDTH-100}
scrollEventThrottle={16}
onScroll={(event) => {
var contentOffsetX=event.nativeEvent.contentOffset.x;
var contentOffsetY=event.nativeEvent.contentOffset.y;
var cellWidth = (DEVICE_WIDTH-100).toFixed(2);
var cellHeight=(DEVICE_HEIGHT-200).toFixed(2);
var cellIndex = Math.floor(contentOffsetX/ cellWidth);
// Round to the next cell if the scrolling will stop over halfway to the next cell.
if ((contentOffsetX- (Math.floor(contentOffsetX / cellWidth) * cellWidth)) > cellWidth) {
cellIndex++;
}
// Adjust stopping point to exact beginning of cell.
contentOffsetX = cellIndex * cellWidth;
contentOffsetY= cellIndex * cellHeight;
event.nativeEvent.contentOffsetX=contentOffsetX;
event.nativeEvent.contentOffsetY=contentOffsetY;
// this.setState({contentOffsetX:contentOffsetX,contentOffsetY:contentOffsetY});
console.log('cellIndex:'+cellIndex);
console.log("contentOffsetX:"+contentOffsetX);
// contentOffset={{x:this.state.contentOffsetX,y:0}}
}}
>
{rows}
</ScrollView>
有几个选项。这里有两个我已经尝试过并且工作正常。我更喜欢第二个,因为正如它的文档所说 "like ListView, this can render hundreds of pages without performance issue".
您不需要其他库,您可以使用 ScrollView 做到这一点。您只需要在您的组件中添加以下道具。
horizontal= {true}
decelerationRate={0}
snapToInterval={200} //your element width
snapToAlignment={"center"}
查看此快餐以了解有关如何实施它的更多详细信息 https://snack.expo.io/H1CnjIeDb
在ScrollView
中使用pagingEnabled
属性。
const screenHeight = Dimensions.get('window').height;
class Screen extends Component {
constructor(props) {
super(props);
}
render() {
return (
<ScrollView pagingEnabled>
<Page1 style={{height: screenHeight}} />
<Page2 style={{height: screenHeight}} />
</ScrollView>
);
}
}
如果您不想使用 snapToInterval 因为长列表未对齐,您可以使用更精确的 snapToOffsets。
例如:
const { width } = Dimensions.get('window');
this.IMAGE_WIDTH = width * (1 / 2.5)
this.image_margin = 5
this.nishhar = width - ((this.IMAGE_WIDTH + this.image_margin) * 2 + this.image_margin * 2)
dataNum = [1, 2, 3, 4, 5, 6]
return (<FlatList
data={dataNum}
renderItem={item => {
return (
<View style={{
backgroundColor: item.index % 2 == 0 ? 'red' : 'blue',
width: this.IMAGE_WIDTH,
height: this.IMAGE_WIDTH,
marginLeft: this.image_margin,
marginRight: this.image_margin,
}}>
</View>)
}}
keyExtractor={this.keyGenerator}
horizontal={true}
snapToAlignment={"start"}
snapToOffsets={[...Array(dataNum.length)].map((x, i) => (i * (this.IMAGE_WIDTH + 2 * this.image_margin) - (this.nishhar * 0.5)))}
decelerationRate={"fast"}
pagingEnabled
/>)
或者您也可以查看此示例: https://snack.expo.io/SyWXFqDAB
我在 iOS 上遇到了 FlatList 的 snapToInterval
逻辑问题(在水平列表上它并不总是正确地捕捉到 start
) - 我通过增加以下属性的值来解决这个问题(我有单项滑块)
maxToRenderPerBatch={6}
initialNumToRender={6}
windowSize={6}
尝试使用 snapToOffsets
道具。不过这需要简单的加法和乘法。
要创建显示 2 个元素的对齐效果,以及与超出边界的左右元素 10pts;
// import useWindowDimensions from 'react-native'
const { width: windowWidth } = useWindowDimensions();
// the width of a card in ScrollView
// 20 is so out of bound cards on left & right can have 10pts visible;
const cardWidth = (windowWidth / 2) - 20;
// gap between each cards;
const gap = 16;
const halfGap = gap / 2;
const cardContent = [1, 2, 3, 4, 5]
// THIS IS THE FUN PART
const snapOffsets = cardContent
.map((_, index) => {
return (cardWidth * index) + (halfGap * index)
})
// add left and right margin to <Card/> for gap effect,
// as well as width using cardWidth above
// conditional left margin to first card, and right margin to last card
return (
<ScrollView
horizontal={true}
snapToOffsets={snapOffsets}
>
{
cardContent.map((item, index, arr) => {
return (
<Card
key={index}
title={item}
style={{
width: cardWidth,
marginLeft: index == 0 ? gap : 0,
marginRight: index == arr.length - 1 ? gap : halfGap
}}
/>
)
})
}
</ScrollView>
)
就是这样。您可以重构垂直模式。
For a better edge to edge effect, make sure that ancestor containers don't have padding