React Native Section List无法滚动问题求助(附代码示例)
SectionList无法滚动的修复方法
你的代码存在几个关键问题,导致SectionList无法正常实现滚动功能,以下是具体修复点:
1. 修复按钮点击的方法调用
按钮onPress回调中调用scrollToSection时,缺少this关键字——类的实例方法必须通过this访问:
// 错误写法 onPress={() => scrollToSection(0)} // 正确写法 onPress={() => this.scrollToSection(0)}
2. 修正scrollToLocation的itemIndex参数
每个section仅包含2个item,有效索引范围是0-1,你设置的itemIndex:66超出了合法范围,会直接导致滚动失败,改为有效索引(比如0):
this.sectionListRef.scrollToLocation({ animated: true, sectionIndex: index, itemIndex: 0, // 修改为有效索引 viewOffset: 0 });
3. 完善getItemLayout方法
原方法未计算section header的高度,SectionList的getItemLayout需要包含section header高度才能正确计算滚动位置,否则会出现滚动偏移或失效问题:
getItemLayout = (data, index, sectionIndex) => { // 计算当前section之前所有section的总高度(header高度 + 该section所有item高度) const previousSectionsHeight = SECTIONS.slice(0, sectionIndex).reduce((total, section) => { return total + ITEM_HEIGHT + (section.data.length * ITEM_HEIGHT); }, 0); // 当前section内的偏移:header高度 + 当前item之前的item总高度 const sectionOffset = ITEM_HEIGHT + (index * ITEM_HEIGHT); return { length: ITEM_HEIGHT, offset: previousSectionsHeight + sectionOffset, index, }; };
4. 补充按钮样式(可选)
原代码未定义button和buttonText样式,导致按钮显示异常,建议补充:
button: { marginVertical: 8, paddingHorizontal: 12, paddingVertical: 6, backgroundColor: '#2196F3', borderRadius: 4, }, buttonText: { color: '#fff', fontSize: 12, }
修正后的完整代码
import React, { Component } from 'react'; import { Text, View, StyleSheet, SectionList, TouchableOpacity } from 'react-native'; import { Constants } from 'expo'; const ITEM_HEIGHT = 50; const SECTIONS = [ {title:'section 1', data: [{title: 'row 1'}, {title: 'row 2'}]}, {title:'section 2', data: [{title: 'row 1'}, {title: 'row 2'}]}, {title:'section 3', data: [{title: 'row 1'}, {title: 'row 2'}]}, {title:'section 4', data: [{title: 'row 1'}, {title: 'row 2'}]}, {title:'section 5', data: [{title: 'row 1'}, {title: 'row 2'}]}, {title:'section 6', data: [{title: 'row 1'}, {title: 'row 2'}]}, {title:'section 7', data: [{title: 'row 1'}, {title: 'row 2'}]}, ]; export default class App extends Component { scrollToSection = (index) => { this.sectionListRef.scrollToLocation({ animated: true, sectionIndex: index, itemIndex: 0, // 使用有效索引 viewOffset: 0 }); }; getItemLayout = (data, index, sectionIndex) => { // 计算前面所有section的总高度 const previousSectionsHeight = SECTIONS.slice(0, sectionIndex).reduce((total, section) => { return total + ITEM_HEIGHT + (section.data.length * ITEM_HEIGHT); }, 0); // 当前section内的偏移:header + 前面item的高度 const sectionOffset = ITEM_HEIGHT + (index * ITEM_HEIGHT); return { length: ITEM_HEIGHT, offset: previousSectionsHeight + sectionOffset, index, }; }; render() { return ( <View style={styles.container}> <View style={styles.leftColumn}> <TouchableOpacity style={styles.button} onPress={() => this.scrollToSection(0)}> <Text style={styles.buttonText}>Scroll to A</Text> </TouchableOpacity> <TouchableOpacity style={styles.button} onPress={() => this.scrollToSection(1)}> <Text style={styles.buttonText}>Scroll to B</Text> </TouchableOpacity> <TouchableOpacity style={styles.button} onPress={() => this.scrollToSection(2)}> <Text style={styles.buttonText}>Scroll to C</Text> </TouchableOpacity> </View> <SectionList style={styles.sectionList} sections={SECTIONS} ref={ref => (this.sectionListRef = ref)} renderSectionHeader={this.renderSectionHeader} renderItem={this.renderItem} getItemLayout={this.getItemLayout} /> </View> ); } renderSectionHeader = ({section}) => ( <View style={styles.header}> <Text>{section.title}</Text> </View> ); renderItem = ({item}) => ( <View style={styles.item}> <Text>{item.title}</Text> </View> ); } const styles = StyleSheet.create({ container: { flex: 1, paddingTop: 10, flexDirection: 'row', }, leftColumn: { width: 64, backgroundColor: '#f0f0f0', justifyContent: 'center', alignItems: 'center', }, sectionList: { flex: 1, padding: 10 }, header: { height: ITEM_HEIGHT, justifyContent: 'center', paddingLeft: 10, backgroundColor: '#e0e0e0', }, item: { height: ITEM_HEIGHT, justifyContent: 'center', paddingLeft: 10, }, button: { marginVertical: 8, paddingHorizontal: 12, paddingVertical: 6, backgroundColor: '#2196F3', borderRadius: 4, }, buttonText: { color: '#fff', fontSize: 12, } });
内容的提问来源于stack exchange,提问作者Jeff Bootsholz
相关产品推荐
相关产品推荐

