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

React Native水平FlatList中InstructionCard组件尺寸不一致问题

解决水平FlatList中卡片无法填满区域且尺寸不一致的问题

核心问题分析

水平方向的FlatList不会自动让子组件填充垂直空间,且子组件默认会根据内容自适应尺寸,导致卡片大小不一。需要通过以下调整让卡片占满目标区域:


修改步骤及代码

1. 调整Routine页面的FlatList容器布局

将FlatList放入指定的红色背景容器中,明确容器的flex占比,确保有足够的空间让卡片填充:

import { Text, View, Pressable, StyleSheet, FlatList } from 'react-native';
import { Link } from 'expo-router';
import InstructionCard from '../../../components/InstructionCard';
import { SafeAreaView } from 'react-native-safe-area-context';

const Routine = () => {
    const TestData = [
        { id: '1', stepNum: 1, duration: 6, specialText: 'testing', brush: 'brush test' },
        { id: '2', stepNum: 2, duration: 8, specialText: 'random special text 1', brush: 'brush A' },
        { id: '3', stepNum: 3, duration: 10, specialText: 'special message here', brush: 'brush C' },
        { id: '4', stepNum: 4, duration: 12, specialText: 'something unique', brush: 'brush D' }
    ];

    return (
        <SafeAreaView style={styles.container}>
            <View style={styles.model}>
                <Text>Model</Text>
            </View>

            <View style={styles.animation}>
                <Text>Animation</Text>
            </View>

            {/* 把FlatList放入红色背景容器 */}
            <View style={styles.instructions}>
                <FlatList
                    contentContainerStyle={{ paddingHorizontal: 10, gap: 10 }} // 左右内边距+卡片间距
                    data={TestData}
                    renderItem={({ item }) =>
                        <InstructionCard
                            stepNum={item.stepNum}
                            specialText={item.specialText}
                            brush={item.brush}
                            duration={item.duration}
                        />
                    }
                    keyExtractor={item => item.id}
                    horizontal
                    pagingEnabled
                    snapToAlignment='start'
                    showsHorizontalScrollIndicator={false}
                />
            </View>
        </SafeAreaView>
    );
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
    },
    model: {
        flex: 2,
        width: '100%',
        backgroundColor: 'grey',
        justifyContent: 'center',
        alignItems: 'center'
    },
    animation: {
        flex: 2,
        width: '100%',
        backgroundColor: 'green',
        justifyContent: 'center',
        alignItems: 'center'
    },
    instructions: {
        flex: 5, // 和model、animation的flex比例匹配,占满剩余空间
        backgroundColor: 'red',
        justifyContent: 'center' // 让卡片垂直居中
    },
})

export default Routine;

2. 修改InstructionCard组件,让卡片占满容器空间

设置卡片的固定宽度(适配屏幕)和flex高度,同时调整内部元素的垂直分配:

import { Text, StyleSheet, View, Pressable, useWindowDimensions } from 'react-native'
import { useFonts, Inter_600SemiBold, Inter_400Regular, Inter_700Bold } from '@expo-google-fonts/inter'
import { MaterialCommunityIcons, MaterialIcons } from '@expo/vector-icons';
import { CountdownCircleTimer } from 'react-native-countdown-circle-timer'

interface InstructionCardProps {
    stepNum: number,
    specialText: string,
    brush: string,
    duration: number
}

const InstructionCard: React.FC<InstructionCardProps> = ({ stepNum, specialText, brush, duration }) => {
    const [fontsLoaded] = useFonts({
        Inter_600SemiBold,
        Inter_400Regular,
        Inter_700Bold,
    })

    const { width } = useWindowDimensions();

    if (!fontsLoaded) { return null }

    return (
        <View style={[styles.cardContainer, { width: width - 20 }]}> {/* 减去FlatList的左右内边距 */}
            <View style={[styles.group, { flex: 1, justifyContent: 'space-between' }]}>
                <Text style={styles.fontBold}>Step {stepNum}</Text>
                <CountdownCircleTimer
                    isPlaying={true}
                    duration={duration}
                    colors={'#0064FF'}
                    size={width / 10}
                    strokeWidth={width / 75}
                    trailColor='#ffffff'
                    strokeLinecap='butt'
                />
            </View>

            <View style={[styles.group, { flex: 2 }]}>
                <MaterialIcons name="info-outline" size={30} color="black" />
                <Text style={styles.fontRegular}>{specialText}</Text>
            </View>

            <View style={[styles.group, { flex: 2 }]}>
                <MaterialCommunityIcons name="toothbrush" size={30} color="black" />
                <Text style={styles.fontRegular}>{brush}</Text>
            </View>
        </View>
    )
}

const styles = StyleSheet.create({
    cardContainer: {
        backgroundColor: '#CEE2FF',
        borderRadius: 10,
        padding: 20,
        shadowColor: 'black',
        shadowOffset: { width: 0, height: 2 },
        shadowOpacity: 0.25,
        shadowRadius: 2,
        flex: 1, // 让卡片占满父容器的高度
    },
    fontBold: {
        fontFamily: 'Inter_700Bold',
        fontSize: 23
    },
    fontRegular: {
        fontFamily: 'Inter_400Regular',
        fontSize: 16,
    },
    group: {
        flexDirection: 'row',
        alignItems: 'center',
        gap: 15,
    }
})

export default InstructionCard

修改说明

  1. FlatList容器:通过styles.instructions的flex:5明确分配空间,确保红色区域有足够高度,同时用justifyContent: 'center'让卡片垂直居中。
  2. 卡片宽度:使用useWindowDimensions获取屏幕宽度,减去FlatList的内边距,让每个卡片占满屏幕宽度(除了边距)。
  3. 卡片高度:给cardContainer设置flex:1,让卡片自动填充父容器的垂直空间。
  4. 内部元素布局:通过给每个group设置不同的flex值,垂直分配卡片内的空间,确保内容填满卡片高度。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 03:44:55