目前发生的事情是我有 4 个类别,即:全部、类别 1、类别 2 和类别 3
现在的情况是,如果我来自所有类别并选择类别 1,则滚动效果动画效果完美,同样适用于所有 -> 类别 2、所有 -> 类别 3 或类别 1 -> 类别 2 等等。
现在,如果我像从类别 3 -> 类别 2 那样反转,它也可以正常工作,但是当我尝试类别 3 或类别 2 -> 所有类别时,滚动效果动画不起作用。
这是我的代码
interface Item {
id: string;
title: string;
}
const getItemMargin = (isFirstIndex: boolean, isLastIndex: boolean) => {
return {
marginLeft: isFirstIndex ? 24 : 0,
marginRight: isLastIndex ? 24 : 8,
};
};
interface CSProps<T extends Item> extends ViewProps {
items: T[];
onSelectItem: (id: T['id']) => void;
selectedId: string;
// categoryIndex: number;
}
const CategoryList = <T extends Item>({
style,
items,
onSelectItem,
selectedId,
// categoryIndex,
...rest
}: CSProps<T>): JSX.Element => {
const {t} = useTranslation();
const flatList = useRef<FlatList>(null);
const [cIndex, setCIndex] = useState<number>(0);
useEffect(() => {
if (selectedId === 'all') {
setCIndex(0);
} else if (selectedId === 'category 1') {
setCIndex(1);
} else if (selectedId === 'category 2') {
setCIndex(2);
} else {
setCIndex(3);
}
const timeout = setTimeout(() => {
console.log(`Check cIndex : ${cIndex}`);
flatList?.current?.scrollToIndex({
index: cIndex,
animated: true,
viewOffset: 10,
});
}, 100); // You can adjust the delay as needed
return () => clearTimeout(timeout);
}, [cIndex, items.length, selectedId]);
/**
* For smooth transition of category tab on FlatList
* @param data
* @param index
* @returns
*/
const getItemLayout = (data: any, index: any) => {
return {
length: styles.item.height,
offset: styles.item.height * index,
index,
};
};
const onMomentumScrollEnd = (event: any) => {
const windowWidth = Dimensions.get('window').width;
const currentIndex = Math.round(
event.nativeEvent.contentOffset.x / windowWidth,
);
if (currentIndex !== cIndex) {
console.log(`Check cIndex: ${currentIndex}`);
setCIndex(currentIndex);
}
};
const renderItem = ({item, index}: {item: T; index: Number}) => {
const backgroundColor =
item.id === selectedId
? Colors.PRIMARY_01_BLUE_4
: Colors.PRIMARY_03_WHITE;
const color =
item.id === selectedId
? Colors.PRIMARY_03_WHITE
: Colors.PRIMARY_01_BLUE_4;
const borderWidth = item.id === selectedId ? 0 : 1;
const isFirstIndex = index === 0;
const isLastIndex = index === items.length - 1;
return (
<TouchableOpacity
testID={item.title.replace(/[A-Z]/g, c => c.toLowerCase())}
onPress={() => onSelectItem(item.id)}
style={[
styles.item,
{backgroundColor},
{borderWidth},
getItemMargin(isFirstIndex, isLastIndex),
]}>
<Text style={[styles.title, {color}]}>{t(item.title)}</Text>
</TouchableOpacity>
);
};
return (
<View style={style} {...rest}>
<FlatList
ref={flatList}
horizontal
// initialScrollIndex={cIndex}
data={items}
renderItem={renderItem}
keyExtractor={({id}) => String(id)}
extraData={selectedId}
showsHorizontalScrollIndicator={false}
onMomentumScrollEnd={onMomentumScrollEnd}
snapToAlignment="center"
onScrollToIndexFailed={info =>
setTimeout(() => {
console.log(
`Check if failed to scrollIndeX: ${JSON.stringify(info)}`,
);
flatList.current?.scrollToIndex({
index: info.index,
animated: false,
});
}, 500)
}
getItemLayout={getItemLayout}
/>
</View>
);
};
const styles = StyleSheet.create({
input: {
...Typography.BODY_2_16_BOOK,
borderBottomColor: Colors.PRIMARY_03_GREY_3,
borderBottomWidth: 0.7,
paddingVertical: 12,
},
inputActive: {
borderBottomColor: Colors.PRIMARY_01_BLUE_4,
},
item: {
borderRadius: 16,
borderStyle: 'solid',
borderColor: Colors.PRIMARY_03_GREY_3,
paddingHorizontal: 16,
height: 28,
justifyContent: 'center',
alignItems: 'flex-start',
},
title: {
...Typography.REMARK_1_13_MEDIUM,
},
});
根据代码和您描述的情况,问题似乎来自从特定类别返回“所有”类别时管理滚动的方式。一个潜在的问题可能是,当您从特定类别导航到“全部”类别时,cIndex 状态未正确更改。截至目前,selectedId 值决定了 cIndex 状态的设置方式,并且仅当 selectedId 状态更改时才会更改。然而,当从特定类别浏览到“全部”类别时,selectedId 值并没有改变,这意味着 cIndex 状态没有被更新。
useEffect(() => {
let newIndex;
if (selectedId === 'all') {
newIndex = 0;
} else {
newIndex = items.findIndex((item) => item.id === selectedId);
}
setCIndex(newIndex); // Update the state
const timeout = setTimeout(() => {
console.log(`Check newIndex: ${newIndex}`);
flatList?.current?.scrollToIndex({
index: newIndex,
animated: true,
viewOffset: 10,
});
}, 100);
return () => clearTimeout(timeout);
}, [selectedId, items]);
如果偏移值为零,可以通过更新getItemLayout函数将其调整为零,以验证索引值是否为零。
const getItemLayout = (data: any, index: any) => {
const offset = index === 0 ? 0 : styles.item.height * index;
return {
length: styles.item.height,
offset,
index,
};
};