React Native — подробное объяснение использования ListView

React.js React Native

что такое ListView

ListView — основной компонент для эффективного отображения вертикально прокручиваемого списка изменяющихся данных. Самый простой способ его использования — создатьListView.DataSourceисточник данных, затем передать ему обычный массив данных и использовать источник данных для создания экземпляраListViewкомпонент и определить егоrenderRowФункция обратного вызова, эта функция будет принимать все данные в массиве в качестве параметра и возвращать визуализируемый компонент (как каждую строку списка)

Проще говоря, это компонент списка, используемый для отображения представлений списка, аналогичный ListView в Android и UITableView в iOS. В качестве компонента списка ListView очень часто используется. Хотя в официальной документации указано, что срок действия ListView истек, а FlatList и SectionList указаны для использования вместо ListView, я думаю, необходимо иметь более глубокое понимание этого элемента управления, и во многих случаях использовать ListView очень удобно.

Связанные свойства ListView

Здесь я перечисляю только наиболее важные атрибуты, которые обычно используются для объяснения, а остальные атрибуты можно найти в официальной документации.

dataSource——ListView.DataSourceЭкземпляр, используемый для установки источника данных списка

renderRow——Метод, используемый для рендеринга каждой строки в списке, этот метод имеет четыре параметра (rowData, sectionID, rowID, highlightRow), вы можете задавать данные каждой строки, передавая параметры, различать разные секции и строки. Четыре параметра представляют часть данных в источнике данных, идентификатор группы, идентификатор строки и информацию о том, является ли маркер выделенной информацией о состоянии.

С двумя свойствами dataSource и renderRow мы можем завершить представление ListView.Эти два свойства являются самыми основными свойствами ListView и должны быть установлены.

renderHeader——Визуализация представления заголовка.В качестве примера возьмем iOS, UITableView имеет свойство tableHeaderView, которое может установить представление заголовка.Здесь renderHeader также может отображать пользовательское представление заголовка.

renderFooter- Визуализация нижнего вида, аналогичного tableFooterView компонента UITableView, вы можете установить хвостовой вид.

renderSectionHeader- Для каждого раздела вид головы, представленного вязкого, похожего в представлении раздела UiableView.

stickySectionHeadersEnabled—— Поддерживает ли sectionHeader прилипание, на самом деле, поддерживает ли текущий sectionHeader наведение курсора на ListView при его скольжении. Этот эффект аналогичен эффекту sectionHeader простого стиля в UITableView.

renderSeparator—— Отрисовывать разделительную линию каждой строки.Обычно я не привык это делать.Вы можете напрямую установить ширину внизу представления строки в renderRow и использовать borderBottomWidth и borderColor для получения разделительной линии.

onEndReached- Вызывается, когда все данные были обработаны, а список был прокручен меньше, чем onEndReachedThreshold пикселей снизу. Этот метод мы используем для подтягивания списка.

onEndReachedThreshold— Это свойство является значением в ListView, а метод в onEndReached срабатывает, когда список прокручивается вниз меньше, чем это значение. В FlatList и SectionList это значение представляет собой отношение между 0 и 1, которое здесь необходимо четко различать.

Использование ListView

В этой статье мы используем ListView для реализации трех различных списковых представлений, которые в основном охватывают наше повседневное использование ListView.

Во-первых, реализация простого представления списка

Как показано на рисунке, для реализации такого списка нам нужно только установить источник данных dataSource и renderRow.

При использовании dataSource нам нужно сначала создать новый объект dataSource.Для списка одного раздела используйтеrowHasChanged(prevRowData, nextRowData) иcloneWithRows(dataBlob, rowIdentities) для создания источника данных.

Для каждой строки представлений нам нужен компонент изображения для отображения изображения, компонент Text для отображения текста, используйте компонент TouchableOpacity для переноса изображения и текста и установите для него событие щелчка, и renderRow готов.

код показывает, как показано ниже:

constructor(props) {  
    super(props);  
    let ds = new ListView.DataSource({ rowHasChanged: (r1, r2) => r1 !== r2  });  
    this.state = {    
        dataSource: ds.cloneWithRows(data)  
    }
}

render() {  
    return (    
        <View style={styles.container}>      
            <ListView        
                dataSource={this.state.dataSource}        
                renderRow={this._renderRow}      
            />    
        </View>  
    )
}


_renderRow = (rowData) => {  
    return (    
        <TouchableOpacity style={styles.cellContainer} onPress={() => {}}>      
            <Image source={rowData.image} style={styles.image}/>      
            <Text style={styles.title}>{rowData.title}</Text>    
        </TouchableOpacity>  
    )
}

Где данные представляют собой массив, содержащий фотографии и заголовок. С помощью установки источника данных и видов строки Render мы получаем простой список.

Во-вторых, список в виде сетки

Чтобы реализовать такое представление Grid Layout, на самом деле очень просто, просто нужно изменить приведенный выше код. Измените стиль содержимого ListView на горизонтальное расположение (flexDirection: 'row'), а затем поддержите перенос строк (flexWrap: 'wrap'), элементы, отображаемые в renderRow, будут располагаться горизонтально, и если все элементы не могут отображаться в один ряд, они будут автоматически перенесены.

render() {  
    return (    
        <View style={{ flex: 1}}>      
            <ListView        
                contentContainerStyle={styles.listView}        
                dataSource={this.state.dataSource}        
                renderRow={this._renderRow}      
            />    
        </View>  
    )
}

ListView наследуется от ScrollView, поэтому здесь мы можем установить для него стиль содержимого (обратите внимание, что это contentContainerStyle, а не стиль).

listView: {  
    flexDirection:'row',  
    flexWrap:'wrap',  
    justifyContent:'space-between',  
    paddingLeft: 20,  
    paddingRight: 20,
},

Затем настройте стили изображений, текста и контейнеров в renderRow, и список GridLayout будет готов.

Третье, сгруппированное представление, содержит списки в один столбец и в виде сетки.

Допустим, у нас есть такой список, есть несколько групп (разделов), стиль отображения строк в каждом разделе разный, некоторые в один столбец, некоторые в виде сетки. В настоящее время мы не можем просто изменить стиль содержимого ListView, как GridLayout, потому что после изменения стиля содержимого ListView затрагиваются все элементы внутри, либо все они отображаются вертикально, либо все они горизонтально, что не может добиться желаемого эффекта. Здесь есть два метода:

  1. Для раздела элемента сетки мы устанавливаем источник данных этого раздела как массив только с одним фрагментом данных, используем View в renderRow для переноса всех дочерних элементов и используем метод map массива для отображения дочерние элементы в сетке циклически. Стиль содержимого представления такой же, как и у GridLayout, который отображается горизонтально, а затем переносится. Сгруппированный формат источника данных ListView:
    { sectionID_1: [ rowData1, rowData2, ... ],  sectionID_2: [rowData], sectionID_3: [ rowData1, rowData2, ... ], ...}

    или

    [[ rowData1, rowData2, ... ], [ rowData], [ rowData1, rowData2, ... ], ...]
    Группировка sectionID_2 используется для отображения сетки.
  2. Вставьте ListView в раздел, где вы хотите отображать элементы сетки, так же, как GridLayout.

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

Здесь следует отметить, что реализация dataSource отличается для ListView из нескольких разделов и ListView из одного раздела.

  • одна секция
let ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
this.state = {  dataSource: ds.cloneWithRows(data)}
  • Несколько разделов
let ds = new ListView.DataSource({  
    rowHasChanged: (r1, r2) => r1 !== r2,  
    sectionHeaderHasChanged: (s1, s2) => s1 !== s2
});
this.state = {  dataSource: ds.cloneWithRowsAndSections(data)}

Схема эффекта выглядит следующим образом

Демонстрационный адрес:GitHub.com/Nobody Arron at/Hot…