34

嗨,我正在尝试像下面的链接一样实现scrollview对齐中心gif

检查这个 Gif

但无法这样做。以下是我实现此目的的本机代码。

或者有什么方法可以滚动到像 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>
4

6 回答 6

76

您不需要其他库,您可以使用 ScrollView 做到这一点。您只需要在组件中添加以下道具。

    horizontal= {true}
    decelerationRate={0}
    snapToInterval={200} //your element width
    snapToAlignment={"center"}

查看此小吃以获取有关如何实施它的更多详细信息 https://snack.expo.io/H1CnjIeDb

于 2017-08-03T08:31:49.150 回答
9

使用 中的pagingEnabled属性ScrollView

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>
    );
  }
}
于 2019-01-15T05:23:45.470 回答
3

如果您不想使用 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

于 2019-12-18T12:26:02.777 回答
1

有几种选择。这是我尝试过并且工作正常的两个。我更喜欢第二个,因为它的文档说“像 ListView 一样,这可以呈现数百个页面而不会出现性能问题”。

  1. react-native-page-swiper
  2. react-native-viewpager
于 2016-10-05T01:41:58.307 回答
0

尝试使用snapToOffsets道具。不过,这需要一个简单的加法和乘法。

创建一个显示 2 个元素的捕捉效果,以及超出边界的左右元素的 10 个点;

// 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>
)

而已。您可以重构垂直模式。

为了获得更好的边缘到边缘效果,请确保祖先容器没有填充

于 2022-01-03T15:17:50.767 回答
0

我在 iOS 上遇到了 FlatList 的snapToInterval逻辑问题(在水平列表上它并不总是正确地捕捉到start) - 我通过增加以下属性的值来解决这个问题(我有单个项目滑块)

maxToRenderPerBatch={6}
initialNumToRender={6}
windowSize={6}
于 2021-09-10T09:44:59.480 回答