首页 > 其他分享 >React Native 锚点 ScrollView 实现

React Native 锚点 ScrollView 实现

时间:2022-11-03 14:02:07浏览次数:44  
标签:const string ScrollView anchorArr React 锚点 height id

引用:

<Anchor
      anchorList={anchorContentCultureList}
      initCurIndex='shiming'
 />

 

Anchor.tsx 代码

// 社区Tab下 文化Tab页 锚点
import React, { ReactNode, useState, useRef } from 'react';
import { ScrollView } from 'react-native';
import { Text, View, Colors } from 'react-native-ui-lib';
import { LineSpace, Touchable } from '../../components';

type Iarr = {
  y: number,
  height: number,
  id: string
};
type IAnchorItem = {
  id: string,
  name: string,
  reactNode: ReactNode,
};
type IAnchorProps = {
  otherChildren: ReactNode, // 锚点所在滚动区的其他组件
  anchorList: IAnchorItem[], // 锚点list
  initCurIndex: string, // 初始化时选中的锚点,一般是第一个
};
const Anchor = (props: IAnchorProps) => {
  const anchorScrollViewRef: any = useRef(null); //锚点内容滚动容器
  const { otherChildren, anchorList, initCurIndex = 'shiming' } = props;
  const [curIndex, setCurIndex] = useState(initCurIndex); // 锚点的id

  const [anchorArr, setAnchorArr] = useState<Iarr[]>([]); // 存储锚点数组,记录滚动位置y 组件高度height 锚点id

  // 点击锚点,滚动到指定位置
  const handleLocation = (index: number) => {
    setCurIndex(anchorArr[index].id);
    anchorScrollViewRef && anchorScrollViewRef.current && anchorScrollViewRef.current.scrollTo({ x: 0, y: anchorArr[index].y, animated: false });  //anchorArr 就是之前定义的arr
  };

  // 文化滚动内容的一些布局属性
  const onLayout = (e: any, id: string) => {
    const newAnchorArr = [...new Set([...anchorArr, { y: e.layout.y, height: e.layout.height, id: id }])];
    // 按照y大小排序,因为苹果手机上顺序是乱的。
    newAnchorArr.sort((a: Iarr, b: Iarr) => { return a.y - b.y; });
    setAnchorArr([...newAnchorArr]);
  };
  const onScroll = (event: any) => {
    const scrollY = event?.nativeEvent?.contentOffset.y;
    for (let i = 0; i < anchorArr.length - 1; i++) {
      if (scrollY < anchorArr[0].height - 10) {
        setCurIndex(anchorArr[0].id);
      } else if (scrollY > anchorArr[i + 1].y - (anchorArr[i].height / 2)) {   //当滚动到超过当前盒子一半的时候
        setCurIndex(anchorArr[i + 1].id);
      }
    }
  };
  return (
    <View style={{ flexDirection: 'row', flex: 1 }}>
      <ScrollView
        scrollEventThrottle={100}
        showsVerticalScrollIndicator={false}
        ref={anchorScrollViewRef}
        onScroll={onScroll}
      >
        {otherChildren}
        {
          anchorList.map((item) => {
            return (
              <>
                <View
                  key={item.id}
                  onLayout={({ nativeEvent: e }) => onLayout(e, item.id)}
                >
                  {item.reactNode}
                </View>
              </>
            );
          })
        }
      </ScrollView>
      <View style={{
        position: 'absolute', top: 156, right: 10, width: 50,
      }}>
        <ScrollView showsVerticalScrollIndicator={false}>
          {anchorList.map((item, index) => (
            <View key={item.id}>
              <Touchable onPress={() => handleLocation(index)}>
                <Text
                  grey66
                  f12
                  l28
                  style={{
                    textAlign: 'center',
                    backgroundColor: curIndex === item.id ? 'rgba(74, 144, 226, 0.8)' : 'transparent',
                    color: curIndex === item.id ? Colors.white : Colors.grey66,
                    borderRadius: 4,
                  }}
                >{item.name || ''}</Text>
              </Touchable>
              <LineSpace height={24} />
            </View>
          ))}
        </ScrollView>
      </View>
    </View>
  );
};

export default Anchor;

 

 

 

 

标签:const,string,ScrollView,anchorArr,React,锚点,height,id
From: https://www.cnblogs.com/zpy521hl/p/16854241.html

相关文章