Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Grid layout using FlatList not rendering properly for IOS #13939

Closed
nishant1000 opened this issue May 12, 2017 · 19 comments
Closed

Grid layout using FlatList not rendering properly for IOS #13939

nishant1000 opened this issue May 12, 2017 · 19 comments
Labels
Resolution: Locked This issue was locked by the bot.

Comments

@nishant1000
Copy link

Description

I am trying to make grid view where items have a minimum and a maximum width. The number of items on grid scale according to screen size.
I was able to achieve this with ListView, but same is not happening with FlatList. The items in the FlatList are sticking to minimum width, even though extra space is available.
Here is an example at Snack. You can check yourself the issue. The issue is only for ios, on Android it is running fine.
https://snack.expo.io/SywBhpMgW

Code to reproduce

import React, { Component } from 'react';
import {View, StyleSheet, FlatList } from 'react-native';

export default class App extends Component {
renderItem({ item, index }) {
return <View style={{
flex: 1,
margin: 5,
minWidth: 170,
maxWidth: 223,
height: 304,
maxHeight:304,
backgroundColor: '#CCC',
}}/>
}
render () {
return (<FlatList
contentContainerStyle={styles.list}
data={[{key: 'a'}, {key: 'b'},{key: 'c'},{key: 'd'}, {key: 'e'},{key: 'f'},{key: 'g'}, {key: 'h'},{key: 'i'},{key: 'j'}]}
renderItem={this.renderItem}
/>);
}
}

const styles = StyleSheet.create({
list: {
justifyContent: 'center',
flexDirection: 'row',
flexWrap: 'wrap',
}
});

Additional Information

  • React Native version:0.44
  • Platform: IOS
  • Development Operating System: macOS
  • Dev tools: Visual Studio Code
@sahrens
Copy link
Contributor

sahrens commented May 15, 2017

flexWrap: 'wrap' is not supported with the new list components. If you want a grid, use numColumns={<number>}. If you need to do something fancier like a masonry layout or different numbers of columns based on sizes of elements, you'll probably just want to use use a regular ScrollView.

@sahrens sahrens closed this as completed May 15, 2017
@jh97uk
Copy link

jh97uk commented Nov 30, 2017

But ScrollView may not be suitable if we're dealing with a list that has > 50 items at one time. (One of my masonry layouts is > 200 items big) Im gathering ListView will not cut it for a list that large.

@tyeon95
Copy link

tyeon95 commented Nov 30, 2017

Is there a reason why flexWrap: 'wrap' is not supported?

Is there a way to dynamically specify the number of columns so that it mimics the behavior of flexWrap: 'wrap'?
Note: I am not listing images, but buttons that users will be able to choose

@sahrens
Copy link
Contributor

sahrens commented Nov 30, 2017

Is there a reason why flexWrap: 'wrap' is not supported?

Because there has not been sufficient demand to justify the effort and complexity of building it.

You can use flexWrap inside of rows in your FlatList, or you can just use a ScrollView instead of FlatList. Depends on what you need.

@tyeon95
Copy link

tyeon95 commented Dec 7, 2017

flexWrap:'wrap' seems to work for now, but I get a warning. Is this because it is not explicitly supported so it may be depreciated?

@jdnichollsc
Copy link

jdnichollsc commented Jan 3, 2018

@sahrens I think that a grid with dynamic columns (resize depending of the width of the device) is very very important (iPhone, iPad, etc), for example: idibidiart/react-native-responsive-grid#15 (comment)
But using only FlatList I can see a warning:

Warning: `flexWrap: `wrap`` is not supported with the `VirtualizedList` components.Consider using `numColumns` with `FlatList` instead.

captura de pantalla 2018-01-03 a la s 11 47 01 a m

Any solution that works with multiple devices, changing the orientation and supports infinite scrolling? For example, with NativeScript is very easy => http://docs.telerik.com/devtools/nativescript-ui/Controls/Angular/ListView/overview#different-layouts

Thanks in advance!

@sahrens
Copy link
Contributor

sahrens commented Jan 3, 2018

Can you measure (e.g. with onLayout) and use that to specify numColumns? Or you can use ScrollView with flexWrap and build infinite scrolling logic yourself without too much trouble.

@jdnichollsc
Copy link

@sahrens You can't specify numColumns because it's different if you change the orientation of the device (A very common situation). On the other hand, with the ScrollView and the flexWrap exist any example to center the items?

@sahrens
Copy link
Contributor

sahrens commented Jan 3, 2018

onLayout will fire with new measurements when the orientation updates and you can update numColumns at that point. You’ll need to also change the key on the list for force a full re-render, and might want to scroll back to where the user was before as well.

@jdnichollsc
Copy link

ohh any example to change the key? I'm learning React Native and scroll back to where the user was before looks complicated

@jdnichollsc
Copy link

With the ScrollView I can only find an example with the onScroll event to know the scroll position: https://stackoverflow.com/a/47984187/1532821

@jdnichollsc
Copy link

ok, looks perfect using the onLayout, example:

onLayout = () => { 
    const {width} = Dimensions.get('window')
    const itemWidth = 187
    const numColumns = Math.floor(width/itemWidth)
    this.setState({ numColumns: numColumns })
}
<Content 
  contentContainerStyle={{flex:1, alignItems: 'center'}}
  onLayout={this.onLayout}>
  <FlatList
    data={this.state.products}
    keyExtractor={(item, index) => index}
    key={this.state.numColumns}
    numColumns={this.state.numColumns}
    renderItem={({item}) => 
    <ListThumb
      navigation={navigation}
      brand={item.brand}
      price={item.price}
      discount={item.discount}
      discountedPrice={item.sale_price}
      id={item.id}
      description={ item.title.length > 25 ? `${item.title.substring(0, 25)} ...` : item.title }
      imageSource={item.image_link}/>
    }
    />
</Content>

captura de pantalla 2018-01-03 a la s 4 20 57 p m

Thanks @sahrens!

@sahrens
Copy link
Contributor

sahrens commented Jan 4, 2018

I'm glad that worked, but you should probably use the width that's passed into your onLayout callback rather than using the Dimensions module:

onLayout = (event) => { 
    const {width} = event.nativeEvent.layout;
    ...

@tyeon95
Copy link

tyeon95 commented Jan 5, 2018

Can you measure (e.g. with onLayout) and use that to specify numColumns? Or you can use ScrollView with flexWrap and build infinite scrolling logic yourself without too much trouble.

How would you calculate numColumns if the width of the items are dynamic (ie the width of each items are difference from each other and we don't know the width until runtime)? The width size is dependent on the text. @sahrens

screen shot 2018-01-05 at 17 01 04

@sahrens
Copy link
Contributor

sahrens commented Jan 5, 2018

That’s not supported by FlatList, you’ll need to use ScrollView or something else.

@joaoanes
Copy link

joaoanes commented Jan 5, 2018

I'm currently able to setup a wrappable list of equally-sized items inside a FlatList using flexWrap: 'wrap' in 0.50. I like this since I can delegate away layout calculations, eg "how many columns should I have for this screen size", to yoga, which I feel is the whole point of even using yoga and css.

This solution works for me, and my basic case. There seems to be a degree of support already, so how "unsupported" is it truly? I'm guessing it breaks when dealing with multiple sized items, but I'd like some clarification if possible.

@sahrens
Copy link
Contributor

sahrens commented Jan 6, 2018

Many features of FlatList will break, such as virtualization, viewability callbacks, scroll to index, etc. You should just use a ScrollView in that case. You can even make your own simple wrapper component that copies the FlatList API if you want.

@superandrew213
Copy link

@sahrens are there any plans of adding this?

numColumns doesn't work with LayoutAnimation wheres

{
  flexDirection: 'row',
  flexWrap: 'wrap',
}

works as it should.

@sahrens
Copy link
Contributor

sahrens commented Mar 22, 2018

No plans. Please just use a ScrollView.

@facebook facebook locked as resolved and limited conversation to collaborators May 24, 2018
@react-native-bot react-native-bot added the Resolution: Locked This issue was locked by the bot. label Jul 18, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Resolution: Locked This issue was locked by the bot.
Projects
None yet
Development

No branches or pull requests

8 participants