2015-04-01 4 views
50

Я создаю простое приложение в React Native, которое извлекает списки из удаленного источника JSON и отображает их на экране.ListView grid in React Native

До сих пор, используя отличный example здесь, мне удалось получить результаты для отображения с использованием компонентов ListView в строках (т. Е. 1 результат на строку, см. Снимок экрана). Мне нужны результаты для отображения в сетке, т. Е. От 3 до 6 элементов на строку, в зависимости от размера экрана и ориентации.

Каков наилучший способ получить эти результаты в сетке? Могу ли я использовать ListView для этого или это только для результатов за одну строку? Я пробовал играть со стилями flexbox, но, поскольку React, похоже, не принимает значения%, а ListView не принимает стили, я пока не добился успеха.

This is how my listings are displaying at the moment - one per row.

ответ

104

Вы должны использовать комбинацию из flexbox, и знание того, что ListView обертывания Scrollview и так берет на его свойства. Имея это в виду, вы можете использовать опору ScrollView contentContainerStyle для стилизации элементов.

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 (
     <ListView contentContainerStyle={styles.list} 
      dataSource={this.state.dataSource} 
      renderRow={(rowData) => <Text style={styles.item}>{rowData}</Text>} 
     /> 
    ); 
    } 
}); 

Просто ListView с некоторыми фиктивными данными. Обратите внимание на использование contentContainerStyle. Вот объект стиля:

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

Мы говорим контейнер мы хотим пунктов в оберточном ряде, и мы задаем ширину каждого дочернего объекта.

Screenshot

+0

Колин, большое вам спасибо за это. Я попробую. – Mateo

+0

Это именно то, что я искал для чего-то, что я делаю! Благодаря! –

+0

СПАСИБО! Это именно то, на что я надеялся, но не думал, что существует. – rxb

33

Я добавляю это как ответ, потому что переливные комментарии скрыты под ответ Колина Рэмси: от React Native 0.28, вы также должны alignItems: 'flex-start', в стилизации списка следует или flexWrap не будут работать. Благодаря Керумену на codedump.io для этого. Таким образом,

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

... с остальными, как в ответе Колина.

+3

Это такой важный комментарий. Спасибо :) – ppsreejith

+1

@kwishnu ты бог! – kjonsson

+0

Я не ответил на codedump. Это было на StackOverflow;) http://stackoverflow.com/questions/39313268/react-native-grid-view-flexbox-wrap-not-working/39316901 – Kerumen

5

Следуйте за ответом Колина Рамсей. И если вы хотите получить половину ширины для каждого элемента, попробуйте этот путь.

... 
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, 
    }, 
}); 
+0

Я долгое время болтал, прежде чем споткнуться о вашем ответе. Спасибо за тонну за это! –

+0

добро пожаловать. –

6

У меня была такая же проблема, и я написал компонент, который решает эту проблему, вы можете найти его здесь: https://github.com/pavlelekic/react-native-gridview

Кроме того, одна вещь, этот компонент делает это гарантирует, что элементы ширины целое число, так что границы предметов не имеют сглаживания, они четкие и четкие.

+0

Работает в 0,42. Надеюсь, это привлечет больше внимания. – RedGiant

+0

Это должен быть правильный ответ, спасибо! – leo7r

+0

@Pavle Lekic, спасибо, что написал эту библиотеку. Я добавил вопрос о renderHeader, который не имеет размера для полной ширины. – pmont

2

использовать FlatList вместо Listview в реакции-native. он обладает большей добавленной стоимостью и лучшей производительностью. checkout the example here

8

ListView теперь deprecated, и вместо этого вы должны использовать FlatList. У FlatList есть указатель, который называется numColumns, и именно это мы хотим создать прокручиваемую сетку.

Например:

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 (
    <FlatList 
     data={data} 
     renderItem={({item}) => (
     <View style={styles.itemContainer}> 
      <Text style={styles.item}>{item.value}</Text> 
     </View> 
    )} 
     keyExtractor={item => item.id} 
     numColumns={numColumns} /> 
); 
} 

enter image description here

Это blog post делает хорошую работу, объясняющую новые возможности FlatList.

Примечание: по какой-либо причине вы должны использовать keyExtractor на FlatList вместо типичной опоры key для каждого элемента. В противном случае вы получите предупреждение. Basic FlatList code throws Warning - React Native

1

Вы можете использовать FlatList и установить numColumns, чтобы получить результат, который является такой же сеткой

0

Проверьте следующий пример, используя FlatList компонент Реагировать Native поддерживать бесконечный скроллинг с отличной производительностью:

//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 (
    <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 //Custom component, it's only an example. 
      navigation={navigation} 
      brand={item.brand} 
      price={item.price} 
      imageSource={item.image_link}/> 
     } 
    /> 
    </Content> 
) 
}  

пример выглядит

enter image description here

С уважением, Николс