Grade ListView no Reagir Nativo

Estou criando um aplicativo simples no React Native que busca listagens de uma fonte JSON remota e as exibe na canvas.

Até agora, usando o excelente exemplo aqui, consegui obter os resultados para exibir usando os componentes ListView em linhas (ou seja, 1 resultado por linha, veja captura de canvas). Preciso que os resultados sejam exibidos em uma grade, ou seja, de 3 a 6 itens por linha, dependendo do tamanho da canvas e da orientação.

Qual é a melhor maneira de obter esses resultados em uma grade? Posso usar ListView para isso, ou é apenas para resultados de uma por linha? Eu tentei brincar com os estilos de flexbox, mas como o React não parece aceitar% valores e o ListView não aceita estilos, eu ainda não tive nenhum sucesso.

É assim que minhas listagens estão sendo exibidas no momento - uma por linha.

    Você precisa usar uma combinação de flexbox e o conhecimento de que o ListView envolve o ScrollView e assim assume suas propriedades. Com isso em mente, você pode usar o contentContainerStyle prop do ScrollView para estilizar os itens.

     var TestCmp = React.createClass({ getInitialState: function() { var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2}); var data = Array.apply(null, {length: 20}).map(Number.call, Number); return { dataSource: ds.cloneWithRows(data), }; }, render: function() { return (  {rowData}} /> ); } }); 

    Apenas um ListView com alguns dados fictícios. Observe o uso de contentContainerStyle . Aqui está o object de estilo:

     var styles = StyleSheet.create({ list: { flexDirection: 'row', flexWrap: 'wrap' }, item: { backgroundColor: 'red', margin: 3, width: 100 } }); 

    Dizemos ao contêiner que queremos itens em uma linha de encapsulamento e definimos a largura de cada object-filho.

    Screenshot

    Estou adicionando isso como uma resposta, porque os comentários de estouro estão escondidos sob a resposta de Colin Ramsay: a partir do Reagir Nativo 0.28, você também precisa de alignItems: 'flex-start', no estilo listview ou o flexWrap não funciona. Graças a Kerumen no codedump.io para isso. Assim,

     var styles = StyleSheet.create({ list: { flexDirection: 'row', flexWrap: 'wrap', alignItems: 'flex-start', }, 

    … com o resto como na resposta de Colin.

    ListView agora está obsoleto e você deve usar FlatList . FlatList tem um suporte chamado numColumns que é exatamente o que queremos criar uma grade rolável.

    Por exemplo:

     const data = [ {id: 'a', value: 'A'}, {id: 'b', value: 'B'}, {id: 'c', value: 'C'}, {id: 'd', value: 'D'}, {id: 'e', value: 'E'}, {id: 'f', value: 'F'}, ]; const numColumns = 3; const size = Dimensions.get('window').width/numColumns; const styles = StyleSheet.create({ itemContainer: { width: size, height: size, }, item: { flex: 1, margin: 3, backgroundColor: 'lightblue', } }); function Grid(props) { return (  (  {item.value}  )} keyExtractor={item => item.id} numColumns={numColumns} /> ); } 

    insira a descrição da imagem aqui

    Este post faz um bom trabalho explicando os novos resources do FlatList.

    Nota: Por alguma razão, você tem que usar o keyExtractor no keyExtractor em vez do típico key prop em cada item. Caso contrário, você receberá um aviso. Código Basic FlatList lança Aviso – Reagir Nativa

    Eu tive o mesmo problema e eu escrevi um componente que resolve esse problema, você pode encontrá-lo aqui: https://github.com/pavlelekic/react-native-gridview

    Além disso, uma outra coisa que esse componente faz é garantir que a largura dos itens seja um número inteiro, para que as bordas dos itens não tenham antialiasing, elas são claras e nítidas.

    Siga a resposta de Colin Ramsay. E se você quiser meia largura para cada item, tente desta forma.

     ... import { Dimensions } from 'react-native'; const { width, height } = Dimensions.get('window'); const gutter = 0; // You can add gutter if you want ... const styles = StyleSheet.create({ item: { width: (width - gutter * 3)/2, marginBottom: gutter, flexDirection: 'column', alignSelf: 'flex-start', backgroundColor: '#ff0000', }, list: { flexDirection: 'row', justifyContent: 'space-between', flexWrap: 'wrap', paddingHorizontal: gutter, }, }); 

    use FlatList em vez de Listview em react-native. tem mais recurso de valor agregado e melhor desempenho. confira o exemplo aqui

    Você pode usar FlatList e definir numColumns para obter o resultado que é o mesmo com a grade

    Verifique o exemplo a seguir usando o componente FlatList do React Native para suportar rolagem infinita com um excelente desempenho:

     //Resize the grid onLayout = (event) => { const {width} = event.nativeEvent.layout; const itemWidth = 150 const numColumns = Math.floor(width/itemWidth) this.setState({ numColumns: numColumns }) } render() { return (   index} key={this.state.numColumns} numColumns={this.state.numColumns} renderItem={({item}) =>  } />  ) } 

    O exemplo parece

    insira a descrição da imagem aqui

    Atenciosamente, Nicholls