【问题标题】:React Native FlatList last item visibility issueReact Native FlatList 最后一项可见性问题
【发布时间】:2018-02-22 02:07:22
【问题描述】:

我正在获取产品列表,然后使用 FlatList 显示,我的列表包含 5 个项目,您可以看到 FlatList 行高是可变的,因为描述文本不同。所以问题是我的最后一个项目卡不完全可见,也许这是某种平面列表问题或布局问题。任何帮助将不胜感激

 renderProducts() {
        if (this.props.loading === true) {
            return (
                <View style={Styles.spinnerStyle}>
                    <ActivityIndicator size='large' />
                </View>
            );
        }

        return (
                <FlatList
                    data={this.props.myProducts}
                    keyExtractor={(item) => item.id}
                    renderItem={({ item }) => (
                        <Card 
                            title={item.title} 
                            image={{ 
                                uri: item.image !== null ? item.image.src :'../resImage.jpg' 
                            }}
                        >
                            <Text style={{ marginBottom: 10 }}>
                                {item.body_html}
                            </Text>
                            <Button
                                icon={{ name: 'code' }}
                                backgroundColor='#03A9F4'
                                fontFamily='Lato'
                                buttonStyle={{ borderRadius: 0, marginLeft: 0, marginRight: 0, marginBottom: 0 }}
                                title='VIEW NOW' 
                            />
                      </Card>
                      )}
                />
        );
    }
    
    render() {
        return (
            <View>
                <View style={Styles.viewStyle}>
                    <Text style    {Styles.textStyle}>ProductsList</Text>
                </View>
                    { 
                        this.renderProducts() 
                    }
            </View>
        );
    }

【问题讨论】:

  • "...如你所见"实际上我们不能,因为你没有发布任何代码。
  • 现在看看。
  • 尝试在FlatList 组件的底部添加填充。 &lt;FlatList style={{ paddingBottom: 20 }} ... /&gt;
  • 嘿,这是解决问题的唯一方法吗?添加一个 marginBottom 也对我有用,但这似乎有点 hack,不是吗?
  • 谢谢。它解决了我的问题:)

标签: react-native react-native-flatlist


【解决方案1】:

@krish 解决方案非常适合固定大小的列表项,但是作为 @Neeraj Sewani 说,它可能不适合动态尺寸列表项。

所以你可以像这样解决问题 - 如果方向是列 -:

<View  style={{height: '90%'}}> 
<FlatList/> 
</View>

否则,-如果方向是行-:

<View  style={{height: '90%', width:'90%'}}> 
<FlatList/> 
</View>

【讨论】:

    【解决方案2】:

    最新更新:

    react-navigation 有一个 SafeAreaView,可以选择不显示底部区域。

    import { SafeAreaView } from 'react-navigation';
    <SafeAreaView forceInset={{ bottom: 'never' }} />
    

    以下旧回复:

    您无法使用 flex: 1 看到您的列表,因为 flex: 1 会将组件增长到父组件。如果父级没有 flex: 1,它将不会拉伸到其父级或屏幕。但是请记住,带有 SafeAreaView 的 flex: 1 将导致显示底部安全区域。如果您的 SafeAreaView 背景颜色与列表背景的颜色不同,这看起来会很糟糕。

    我以前的解决方法是在项目数组的底部添加一个项目,但我仍在探索如何使用 FlatList 滚动过去/低于底部安全区域边距(这就是我发现这篇文章的开头与)。

    更新:使用 ListFooterComponent,您甚至可以创建带有高度和/或边距的纯白色“页脚”

    例如(如果我是你,我不会直接复制和粘贴此内容……肯定有更好的方法来检测无边框 iPhone,尤其是在 2019 年我们有不止一部的时候)

    ListFooterComponent={<View style={{ height: 0, marginBottom: 90 }}></View>}
    

    这就是我的做法,现在使用 iPhoneX 的高度。但这不是面向未来的,因为每次推出没有边框的新 iPhone 时都需要更新条件:

    ListFooterComponent={<View style={{ height: 0, marginBottom: noBezels ? 90 : 0 }}></View>}
    

    或者你可以总是在底部留一些间距,比如加载 gif、一条消息……随便什么。

    更新 2:

    我发现 react-native-device-info 有一个 hasNotch() 方法。通过将 hasNotch() 与 Platform.OS === 'ios' 结合使用,我发现这对于没有边框的 iPhone 的样式很有用 === 'ios'

    【讨论】:

    • 嗨@jsonp 不幸的是我没有看到你的回复,但我基本上像你一样解决了它。即使我无法及时阅读您的信息,我也想感谢您的努力,有点晚了。那谢谢啦! (也赞成)
    • 使用了这个并且效果很好,我试图在平面列表组件下添加一个设置高度的视图无济于事。这解决了我的最后一个列表项被底部导航部分覆盖的问题。
    • @Yunnosch 很抱歉回复晚了。我不确定你所说的违反规则等是什么意思。如果你看到这个,你能解释一下吗?
    • @Yunnosch Gotcha。我会牢记这一点,继续前进。谢谢。
    【解决方案3】:

    我已经解决了 contentInset={{ bottom: data.length * itemStyle.height, }} itemStyle.height 为 50 的问题。

    【讨论】:

      【解决方案4】:

      这对我来说效果很好:

        <FlatList
          data={todos}
          contentContainerStyle={{ height: '100%' }}
          renderItem={({ item }) => <Todos items={item} pressed={pressed} />}
        />
      

      【讨论】:

        【解决方案5】:

        对我来说工作得很好

        <FlatList
          data={data}
          contentContainerStyle={{ paddingBottom: 30 }}
          style={{height: '95%'}}
          renderItem={({ item, index }) => (
            <ListItem item={item} onPress={() => handlePress(item, index)} />
          )}
        />
        

        【讨论】:

          【解决方案6】:

          &lt;FlatList&gt; 内容容器设置底部填充:

          <FlatList
              contentContainerStyle={{ paddingBottom: 20 }}
          />
          

          【讨论】:

          • 我们为什么要这么做?
          • 为我工作。谢谢
          • 它对我有用,我必须将 paddingBottom 设置为 350(通过反复试验)(我的平面列表项大小更高)。但是我们如何找到所需的实际填充
          • 如果内容的高度动态变化,这将不起作用。要使 FlatLIst 的所有项目可见,请确保 父项 View 应具有固定高度或宽度,具体取决于 FlatList 方向。
          • 为我工作。谢谢!
          【解决方案7】:

          这对我有用。

          <View style={{flex: 1}}>
              <FlatList
                style={{flex: 1}}
                data={data}
                renderItem={({item}) => (
                  <ListItem item={item} onPress={() => handlePress(item)} />
                )}
              />
            </View>
          

          【讨论】:

            【解决方案8】:

            你可以试试这个解决方案

            对于VerticalFlatList

            <FlatList
             ListFooterComponent={<View />}
             ListFooterComponentStyle={{height:200}}
            />
            

            对于HorizontalFlatList

            <FlatList
              contentContainerStyle={{paddingRight:40}}
            />
            

            【讨论】:

              【解决方案9】:

              我在我们的 Android + iOS React Native 混合应用程序中看到了同样的问题。我们将 FlatList 组件嵌入到 Android 的 Fragment 中的原生 UI 中,我们无法滚动到列表中的最后一项,即使滚动指示器会显示还有更多要滚动,但 ScrollView 根本不会滚动。我尝试了使用包装 &lt;View style={{flex:1}}&gt; 包装 FlatList 以及在 FlatList 上使用 contentContainerStyle={{flexGrow:1}} 的所有组合,但均未成功。进一步追查发现 FlatList 在 Android 上需要一个绝对的、预定义的高度以允许滚动到底部 - 它在 iOS 上工作得很好,但在 Android 上使用 match_parent 是行不通的。由于我们还需要支持所有类型的设备、手机和平板电脑,因此也不可能预先定义绝对高度。

              为了解决这个问题,我创建了一个自定义的 FrameLayout 子类来容纳 ReactRootView 的片段,它覆盖了 onLayout() 以忽略子视图测量,强制视图具有 FrameLayout 的确切尺寸,有点像 Kotlin 中的:

              class StretchFrameLayout @JvmOverloads constructor(
                      context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
              ) : FrameLayout(context, attrs, defStyleAttr) {
              
                  override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
                      for (child in children){
                          if (child.visibility == View.GONE) continue
                          child.updateLayoutParams {
                              this.width = measuredWidth
                              this.height = measuredHeight
                          }
                          if (needsRelayout){
                              handler.postDelayed({child.requestLayout()},1)
                          }
                      }
                      super.onLayout(changed, left, top, right, bottom)
                  }
              }
              

              【讨论】:

                【解决方案10】:

                利用平面列表中的 contentContainerStyle 属性 &lt;FlatList contentContainerStyle={{paddingBottom: 10}} /&gt;

                【讨论】:

                  【解决方案11】:

                  只需使用 flex:1 将其包裹在视图中

                  <ParentView style={{flex:1}
                      <View style={{flex:1}}>
                      // Your flatlist
                      <View>
                  </ParentView>
                  

                  另外,请注意,包含 Flatlist 的“View”的每个父级也必须是 Flex 为 1 的 View。否则,您的 flatlist 将不可见。

                  【讨论】:

                  • “另外,请注意,包含 Flatlist 的“视图”的每个父级也必须是 Flex 为 1 的视图。否则,您的平面列表将不可见。 ....非常有用的评论!谢谢。
                  • 它就像一个魅力!虽然不知道为什么 flex=1 解决了这个问题
                  【解决方案12】:

                  {flex: 1} 添加到包含Flatlist 组件的View 标签。

                  就我而言,

                  const App = () => {
                    return (
                      <Provider store={createStore(reducers)}>
                      <View style={{ flex: 1 }}>
                        <Header headerText={'My App'} />
                        <ScreenTabs /> // this is my content with FlatList 
                      </View>
                      </Provider>
                    );
                  };
                  
                  export default App;
                  

                  【讨论】:

                  • 当我这样做时,我的列表将不再可见。
                  • 如果您的列表不可见,则可能是父视图不灵活:1,您必须找到未扩展的父视图。
                  • &lt;FlatList style={{flex: 1}} 也为我工作,没有任何父母 &lt;View/&gt;。不过必须将 {flex: 1} 添加到主容器视图。
                  【解决方案13】:

                  对于 IOS 问题,您可以应用一些 IOS 特定的道具:

                  <FlatList
                    // ...
                    contentInset={{top: 0, bottom: 20, left: 0, right: 0}}
                    contentInsetAdjustmentBehavior="automatic"
                    // ...  
                  />
                  

                  在我的情况下,使用contentContainerStyle 填充的解决方案似乎并不是解决安全区域 IOS 问题的最佳整体。

                  【讨论】:

                  • 我的平面列表处于固定高度的模式中。在我的情况下,这比任何解决方案都有效。
                  【解决方案14】:

                  使用 FlatList 的 contentContainerStyle 属性

                  <FlatList contentContainerStyle={{ paddingBottom: 20}} />
                  

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 2022-11-17
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2018-05-20
                    • 1970-01-01
                    相关资源
                    最近更新 更多