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

React Native FlatList滚动时左侧出现额外空白问题求助

React Native FlatList滚动后左侧出现空白的问题

问题现象

FlatList初始渲染正常,但滚动到不同索引位置时,当前项左侧会出现额外空白,导致部分内容被挤到下一项,后续的项也会出现同样的左侧空白问题。期望每个FlatList项能占满其容器的宽度,且不会出现左侧额外空白。

相关代码

import {
  Animated,
  FlatList,
  View,
  ViewToken,
  useWindowDimensions,
} from 'react-native';
import React, {useRef, useState} from 'react';
import CustomTextInput from './TextInput';
import ImageRender from './ImageRender';
import CustomText from './Text';
import {ChatIcon, HeartIcon, SendIcon} from '../assets/icons';
import Paginator from './Paginator';

interface CardProps {
  id: string;
  profileImage?: any;
  profileName?: string;
  caption: string;
  likes: number | string;
  comment: number | string;
  share: number | string;
}

interface Props {
  data: CardProps[];
  imageUrl: any;
}

const Card: React.FC<Props> = ({data, imageUrl}) => {
  const [cptn, setCptn] = useState('');
  const scrollX = useRef(new Animated.Value(0)).current;
  const slideRef = useRef(null);
  const [currentIndex, setCurrentIndex] = useState(0);
  const viewableIndexChange = ({
    viewableItems,
  }: {
    viewableItems: ViewToken[];
  }) => {
    if (viewableItems && viewableItems.length > 0) {
      setCurrentIndex(viewableItems[0].index ?? 0);
    }
  };

  const viewabilityConfig = useRef({
    viewAreaCoveragePercentThreshold: 50,
  }).current;

  const {width} = useWindowDimensions();

  return (
    <View style={styles.container}>
      <View style={styles.upperUpper}>
        <View style={styles.upper}>
          <View style={styles.upperProfile}>
            <ImageRender
              source={require('../assets/images/image1.png')}
              width={34}
              circular={true}
              height={34}
            />
            <CustomText text="Albert Flores" size="medium" variant="body" />
          </View>
          <View style={styles.ellipse}>
            <ImageRender
              source={require('../assets/images/ellipse24.png')}
              width={3}
              height={3}
              circular={false}
            />
            <ImageRender
              source={require('../assets/images/ellipse24.png')}
              width={3}
              height={3}
              circular={false}
            />
            <ImageRender
              source={require('../assets/images/ellipse24.png')}
              width={3}
              height={3}
              circular={false}
            />
          </View>
        </View>
        <CustomText text={cptn} variant="body" size="medium" weight="bold" />
      </View>
      <View style={styles.main}>
        <View style={{marginTop: -15}}>
          <CustomTextInput
            bottomSheet={true}
            placeholder="Add Caption"
            size="large"
            value={cptn}
            onChangeText={text => setCptn(text)}
            homeCaption={true}
          />
        </View>
        <ImageRender source={imageUrl} width="100%" height={220} />
        <FlatList
          data={data}
          renderItem={({item}) => {
            return (
              <View style={[styles.flatListItem, {width}]}>
                <View style={styles.cardFooter}>
                  <View style={styles.profile}>
                    <ImageRender
                      circular={true}
                      source={item.profileImage}
                      width={22}
                      height={22}
                    />
                    <CustomText
                      text={item.profileName}
                      variant="body"
                      size="smaller"
                      weight="bold"
                    />
                  </View>
                  <View style={styles.caption}>
                    <CustomText
                      text={item.caption}
                      variant="body"
                      weight="bold"
                      size="large"
                    />
                  </View>
                  <View style={styles.stats}>
                    <View style={styles.likeChat}>
                      <View style={styles.like}>
                        <HeartIcon size={16} />
                        <CustomText
                          text={item.likes}
                          size="small"
                          variant="body"
                        />
                      </View>
                      <View style={styles.comments}>
                        <ChatIcon size={16} />
                        <CustomText
                          text={item.comment}
                          size="small"
                          variant="body"
                        />
                      </View>
                    </View>
                    <View style={styles.share}>
                      <SendIcon size={16} />
                      <CustomText
                        text={item.share}
                        size="small"
                        variant="body"
                      />
                    </View>
                  </View>
                </View>
              </View>
            );
          }}
          horizontal
          keyExtractor={item => item.id}
          showsHorizontalScrollIndicator={false}
          pagingEnabled={true}
          bounces={false}
          onScroll={Animated.event(
            [{nativeEvent: {contentOffset: {x: scrollX}}}],
            {useNativeDriver: false},
          )}
          scrollEventThrottle={32}
          onViewableItemsChanged={viewableIndexChange}
          viewabilityConfig={viewabilityConfig}
          ref={slideRef}
        />
      </View>
      <View style={{alignItems: 'center'}}>
        <Paginator data={data} currentIndex={currentIndex} />
      </View>
    </View>
  );
};

const styles = {
  container: {
    flex: 1,
    width: '90%',
    gap: 10,
  },
  upperUpper: {
    flexDirection: 'column',
    gap: 12,
  },
  upper: {
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'space-between',
    marginTop: 20,
  },
  ellipse: {
    flexDirection: 'row',
    gap: 2,
  },
  upperProfile: {
    flexDirection: 'row',
    alignItems: 'center',
    gap: 8,
  },
  main: {
    width: '100%',
    minHeight: 415,
    gap: -17,
    borderRadius: 8,
    marginTop: 10,
    backgroundColor: '#fff',
  },
  cardFooter: {
    paddingVertical: 13,
    gap: 8,
    paddingHorizontal: 12,
    width: '90%',
  },
  flatListItem: {
    justifyContent: 'center',
    aliignItems: 'center',
  },
  profile: {
    width: 124,
    flexDirection: 'row',
    gap: 8,
    alignItems: 'center',
  },
  stats: {
    flexDirection: 'row',
    justifyContent: 'space-between',
  },
  likeChat: {
    flexDirection: 'row',
    gap: 24,
    alignItems: 'center',
  },
  like: {
    flexDirection: 'row',
    gap: 4,
    alignItems: 'center',
  },
  comments: {
    flexDirection: 'row',
    gap: 4,
    alignItems: 'center',
  },
  share: {
    flexDirection: 'row',
    gap: 4,
    alignItems: 'center',
  },
  secondCardMain: {
    width: '100%',
    height: 116,
    borderWidth: 1,
    borderRadius: 8,
    marginTop: 10,
    backgroundColor: '#ff',
    paddingVertical: 13,
    paddingHorizontal: 12,
  },
};
export default Card;

修复方案

1. 修正样式拼写错误

flatListItem里的aliignItems是拼写错误,改为alignItems,否则子元素无法正确居中对齐:

flatListItem: {
  justifyContent: 'center',
  alignItems: 'center', // 修正拼写错误
  width: '100%' // 改为相对宽度,匹配父容器
},

2. 调整FlatList项宽度

原代码给flatListItem设置了屏幕全宽width,但它的父容器main是基于container的90%宽度,直接用屏幕宽度会超出容器范围,导致滚动偏移。移除手动设置的width,改用样式里的width: '100%':

// 原代码
<View style={[styles.flatListItem, {width}]}>
// 修改后
<View style={styles.flatListItem}>

3. 让内容占满项宽度

cardFooter设置了width: '90%',导致内容无法占满项的宽度,改为width: '100%':

cardFooter: {
  paddingVertical: 13,
  gap: 8,
  paddingHorizontal: 12,
  width: '100%', // 从90%改为100%
},

4. 移除异常负间距

main样式里的gap: -17属于异常负间距,可能导致FlatList位置偏移,建议移除或调整为合理正值:

main: {
  width: '100%',
  minHeight: 415,
  // gap: -17, // 移除该负间距
  borderRadius: 8,
  marginTop: 10,
  backgroundColor: '#fff',
},

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 15:11:01