0
点赞
收藏
分享

微信扫一扫

人工智能AI网站推荐

eelq 2024-03-06 阅读 12

基于react native的简单手动切换功能示例

代码示例

import React, {useEffect, useRef, useState} from 'react';
import {
  Animated,
  PanResponder,
  StyleSheet,
  Text,
  View,
  Dimensions,
  ScrollView,
} from 'react-native';
import {pxToPd} from '../../common/js/device';
import MatchTab from './matchTab';

const TestExampleTab = ({navigation}) => {
  const [tabCode, setTabCode] = useState(2);
  const [tabList, setTabList] = useState([
    {
      name: '报名中',
      code: 2,
    },
    {
      name: '进行中',
      code: 3,
    },
    {
      name: '已结束',
      code: 8,
    },
    {
      name: '已作废',
      code: 11,
    },
  ]);

  //手势滑动区域节点
  const animatedViewRef = useRef(null);
  //单个切换页面的宽度
  const deviceWidth = Dimensions.get('window').width;
  // 默认显示下标的页面
  let currentIndexRef = useRef(0);
  //滑动的距离
  const defaultMove = -currentIndexRef.current * deviceWidth;
  const pan = useRef(new Animated.Value(defaultMove)).current;

  const panResponder = useRef(
    PanResponder.create({
      onStartShouldSetPanResponder: () => true,
      //处理手势移动事件,其中使用了`dx`参数来表示在x轴上的移动距离
      onPanResponderMove: (evt, gestureState) => {
        //获取当前滚动区域有几个孩子节点
        const count = animatedViewRef.current._children.length;
        //每次移动的距离
        const moveX = -currentIndexRef.current * deviceWidth;
        //当移动到最左侧或者最右侧时,禁止拖动
        const start = currentIndexRef.current == 0 && gestureState.dx > 0;
        const end = currentIndexRef.current == count - 1 && gestureState.dx < 0;
        if (start || end) {
          // 禁止继续拖动
          return false;
        }
        if (Math.abs(gestureState.dx) < 50) {
          return false;
        }
        pan.setValue(moveX + gestureState.dx);
      },
      //处理手势释放时的逻辑
      onPanResponderRelease: (_, gestureState) => {
        //获取当前滚动区域有几个孩子节点
        const count = animatedViewRef.current._children.length;
        //当手指拖动区域大于100的时候,开始切换页面
        if (Math.abs(gestureState.dx) > 100) {
          let newPageIndex = currentIndexRef.current;
          if (gestureState.dx > 0) {
            newPageIndex = Math.max(0, currentIndexRef.current - 1);
          } else {
            newPageIndex = Math.min(count - 1, currentIndexRef.current + 1);
          }
          const moveX = -newPageIndex * deviceWidth;
          currentIndexRef.current = newPageIndex;
          pan.setValue(moveX);
        } else {
          pan.setValue(-currentIndexRef.current * deviceWidth);
        }
        setTabCode(() => tabList[currentIndexRef.current].code);
      },
    }),
  ).current;

  //tab切换
  const tabChangeHandle = row => {
    setTabCode(() => row.status);
    let subscript = tabList.findIndex(item => item.code == row.status);
    currentIndexRef.current = subscript;
    pan.setValue(-subscript * deviceWidth);
  };

  useEffect(() => {
    return () => {};
  }, []);

  return (
    <>
      {/* tab */}
      <View style={styles.tabWrap}>
        <MatchTab list={tabList} code={tabCode} onClick={tabChangeHandle} />
      </View>
      <View style={styles.wraper}>
        <Animated.View
          ref={animatedViewRef}
          style={{
            width: deviceWidth * tabList.length,
            flex: 1,
            flexDirection: 'row',
            transform: [{translateX: pan}],
            onStartShouldSetResponderCapture: () => false, // 禁止拦截触摸事件
          }}
          {...panResponder.panHandlers}>
          <View style={{width: deviceWidth, backgroundColor: 'red'}}>
            <Text>item One</Text>
          </View>
          <View style={{width: deviceWidth}}>
            <Text>item Two</Text>
          </View>
          <View style={{width: deviceWidth, backgroundColor: 'green'}}>
            <Text>item Three</Text>
          </View>
          <View style={{width: deviceWidth}}>
            <Text>item Four</Text>
          </View>
        </Animated.View>
      </View>
    </>
  );
};
const styles = StyleSheet.create({
  // tab
  tabWrap: {
    width: '100%',
    height: pxToPd(80),
  },
  wraper: {
    flex: 1,
    backgroundColor: '#fff',
  },
});

export default TestExampleTab;

matchTab

import React, {useRef, useState} from 'react';
import {
Image,
ScrollView,
StyleSheet,
Text,
TouchableOpacity,
View,
} from 'react-native';
import {pxToPd} from '../../common/js/device';

const MatchTabItem = ({item, current, onClick}) => {
const tabItemClickHandle = row => {
onClick && onClick(row);
};
return (
<>
<TouchableOpacity
style={styles.tabItem}
onPress={() =>
{
tabItemClickHandle(item);
}}>
{item.code == current ? (
<>
<Text style={styles.tabItemNameCurrent}>{item.name}</Text>
<View style={styles.tabLine}></View>
</>
) : (
<>
<Text style={styles.tabItemName}>{item.name}</Text>
</>

)}
</TouchableOpacity>
</>
);
};

const MatchTab = ({onClick, list = [], code = 2}) => {
//点击tab切换
const tabClickHandle = row => {
onClick &&
onClick({
type: 'status',
status: row.code,
});
};

return (
<>
<View style={styles.matchTab}>
<View style={styles.matchTabMenu}>
<ScrollView horizontal={true}>
{list.map(item => (
<MatchTabItem
key={item.code}
item={item}
current={code}
onClick={tabClickHandle}
/>

))}
</ScrollView>
</View>
</View>
</>

);
};

const styles = StyleSheet.create({
matchTab: {
width: '93.6%',
marginLeft: '3.2%',
flexDirection: 'row',
},
matchTabMenu: {
flex: 1,
},
matchTabFilter: {
width: pxToPd(120),
flexDirection: 'row',
justifyContent: 'flex-end',
alignItems: 'center',
},
filterIcon: {
width: pxToPd(32),
height: pxToPd(32),
},
filterText: {
fontSize: pxToPd(26),
fontWeight: '400',
color: '#333',
marginLeft: pxToPd(10),
},
filterTextok: {
fontSize: pxToPd(26),
fontWeight: '400',
color: '#FFA157',
marginLeft: pxToPd(10),
},
tabItem: {
height: pxToPd(70),
position: 'relative',
alignItems: 'center',
justifyContent: 'center',
marginRight: pxToPd(40),
},
tabItemName: {
fontSize: pxToPd(26),
fontWeight: '400',
color: '#333',
},
tabItemNameCurrent: {
fontSize: pxToPd(30),
fontWeight: '500',
color: '#ff9f50',
},
tabLine: {
width: pxToPd(32),
height: pxToPd(6),
backgroundColor: '#ffa157',
borderRadius: pxToPd(3),
position: 'absolute',
left: '50%',
marginLeft: -pxToPd(16),
bottom: 0,
},
});

export default MatchTab;

举报

相关推荐

0 条评论