You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Native Expo中设置FlatList滚动宽度实现周选择器

问题描述

尝试用FlatList实现日期选择器,渲染多个可横向滚动的周(如week1、week2等),期望单个周占满设备宽度,滚动时自动对齐到单个周,始终完整显示周日至周六,但当前一屏约显示1.75个周,尝试过justifyContent和flexGrow属性效果不佳,需要实现每次仅滚动一个周的效果。

现有代码

组件代码

const Week = ({ item, selectedId, setSelectedId }) => (
    <View style={styles.weekContainer}>
        {item.days.map((day) => {
            return (
                <TouchableOpacity
                    onPress={() => setSelectedId(day.id)}
                    style={[
                        day.id == selectedId ? styles.unselectedDay : styles.selectedDay,
                    ]}
                    key={day.id}
                >
                    <Text
                        style={[
                            day.id == selectedId ? styles.unselectedDayText : styles.selectedDayText
                        ]}
                    >
                        {day.name}
                    </Text>
                </TouchableOpacity>
            )
        })}
    </View>
);

export const DateHeader = () => {
    const [selectedId, setSelectedId] = useState(today.toLocaleDateString());
    const width = Dimensions.get('window').width
    const renderItem = ({ item }) => {
        return (
            <Week
                item={item}
                selectedId={selectedId}
                setSelectedId={setSelectedId}
            />
        );
    }
    return (<>
        <FlatList
            data={weeks}
            renderItem={renderItem}
            keyExtractor={(item) => item.id}
            extraData={selectedId}
            horizontal={true}
            inverted={true}
            style={styles.flatList}
            showsHorizontalScrollIndicator={false}
            decelerationRate={0}
            snapToInterval={width}
            snapToAlignment={'center'}

        />
    </>)
}

样式代码

const styles = StyleSheet.create({
    flatList: {
        flexGrow: 0,
    },
    weekContainer: {
        flexGrow: 1,
        flexDirection: 'row',
        borderColor:'red',
        borderWidth: '2px',

    },
    unselectedDay: {
        fontSize: 16,
        padding: 10,
        height: 50,
        backgroundColor: '#6e3b6e',
    },
    selectedDay: {
        fontSize: 16,
        padding: 10,
        height: 50,
        backgroundColor: '#f9c2ff',
    },
    unselectedDayText: {
        textColor: 'white'
    },
    selectedDayText: {
        textColor: 'black'
    },
});

当前效果

当前效果:一屏显示约1.75个周

解决方案

问题核心在于每个Week组件的容器未设置固定宽度,导致FlatList无法正确计算项宽,进而影响滚动对齐效果,按以下步骤修改即可:

  1. 给周容器设置固定屏幕宽度
    在DateHeader中已获取width = Dimensions.get('window').width,直接传递给Week组件并设置宽度:

    // 修改Week组件接收width参数并设置容器宽度
    const Week = ({ item, selectedId, setSelectedId, width }) => (
        <View style={[styles.weekContainer, { width: width }]}>
            {/* 原有内容不变 */}
        </View>
    );
    
    // 在renderItem中传递width
    const renderItem = ({ item }) => {
        return (
            <Week
                item={item}
                selectedId={selectedId}
                setSelectedId={setSelectedId}
                width={width}
            />
        );
    }
    

    同时移除weekContainer的flexGrow:1,固定宽度下无需该属性:

    weekContainer: {
        // flexGrow: 1,  // 移除此行
        flexDirection: 'row',
        borderColor:'red',
        borderWidth: 2,  // React Native中borderWidth无需加px,直接写数字
    },
    
  2. 优化FlatList滚动对齐参数
    将snapToAlignment改为'start',让滚动后周从屏幕左侧对齐,同时添加disableIntervalMomentum让滚动更干脆:

    <FlatList
        // 其他属性不变
        snapToInterval={width}
        snapToAlignment={'start'}
        disableIntervalMomentum={true}
    />
    
  3. 修复样式错误
    React Native的Text样式中没有textColor属性,替换为color:

    unselectedDayText: {
        color: 'white'
    },
    selectedDayText: {
        color: 'black'
    },
    

修改完成后,每个周容器会占满屏幕宽度,滚动时自动对齐单个周,每次滚动仅切换一个周的内容。

内容的提问来源于stack exchange,提问作者benwl

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 03:40:31