我发现使用TouchableOpacity
'按钮'来控制FlatList
的水平滚动时出现问题。如果我激活Remote Debugging
,一切正常,但如果我关闭调试,则触摸不会回来,应用UI无响应。
我正在尝试实现水平滚动FlatList
,这实际上是一步一步wizard
ui。
FlatList
(已启用分页,水平)数据数组中有3到7个项目,我有prev
和next
个按钮,单独使用TouchableOpacity
个组件实现查看屏幕底部。
我有一个自定义的View组件,它将代表每个步骤的内容(目前,它只有一个Text标签)。
点击next或prev应该滚动到FlatList中的下一个索引。 使用类似的东西:
this.flatListRef.scrollToIndex({index: this.state.currentStepIndex + 1, animated: true});
我在React Native GitHub repo中创建了一个问题。有没有人见过这种行为?任何已知的工作?
我在Android和iOS上看到了这一点。 这是我的环境:
react: ^16.3.2 => 16.3.2
react-native: ^0.55.3 => 0.55.3
这是我的原始代码:
render() {
console.log('Render newrequestscreen', this.state, this.flatListRef)
return (
<SafeAreaView style={baseStyles.safeAreaDark}>
<View style={baseStyles.swipeContainerView} >
<Text style ={baseStyles.emptyListSubtitleText} > {this.state.flexItems.length == this.state.currentStepIndex ? 'Review & Submit' : 'Step ' + (this.state.currentStepIndex + 1) + ' of ' + (this.state.flexItems.length) }</Text>
</View>
<FlatList
ref={(ref) => { this.flatListRef = ref; }}
scrollEnabled={false}
initialNumToRender={1}
initialScrollIndex={0}
refreshing={false}
pagingEnabled={true}
horizontal
getItemLayout={(data, index) => (
{length: Dimensions.get('window').width, offset: Dimensions.get('window').width * index, index}
)}
data={this.state.flexItems}
showsHorizontalScrollIndicator = { false }
decelerationRate={0}
renderItem={({item, index}) => {
return (
<View style={baseStyles.swipeContainerView} pointerEvents='none' >
<Text style ={baseStyles.emptyListSubtitleText} >{item.promptText}</Text>
</View>
)
}
}
keyExtractor={(item) => item.type}/>
<View style={baseStyles.swipeContainerView} >
<View style={baseStyles.requestNavView}>
<TouchableOpacity
onPress={this._previousStep.bind(this)}
style={requestComponentStyles.locationCaptureButton}>
<Text style={requestComponentStyles.locationCaptureButtonText}>Prev Step</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={this._nextStep.bind(this)}
style={requestComponentStyles.locationCaptureButton}>
<Text style={requestComponentStyles.locationCaptureButtonText}>Next Step</Text>
</TouchableOpacity>
</View>
</View>
</SafeAreaView>
);
}
_nextStep() {
console.log('next tapped...', this.flatListRef)
if (this.state.currentStepIndex < this.state.flexItems.length - 1) {
this.flatListRef.scrollToIndex({index: this.state.currentStepIndex + 1, animated: true});
this.setState(function(prevState, props) {
return {
currentStepIndex: prevState.currentStepIndex + 1
};
});
}
}
_previousStep() {
console.log('prev tapped...', this.flatListRef)
if (this.state.currentStepIndex > 0) {
this.flatListRef.scrollToIndex({index: this.state.currentStepIndex - 1, animated: true});
this.setState(function(prevState, props) {
return {
currentStepIndex: prevState.currentStepIndex - 1
};
});
}
}
以下是我正在构建的内容的屏幕截图(文本“location”的灰色区域是水平FlatList
中的全宽项目):
感谢您对此有任何帮助或想法!谢谢!
更新/注意:如果我删除FlatList,TouchableOpacity按钮工作正常,所以FlatList和同一屏幕上的其他Touchable元素之间似乎存在某种不兼容性。
编辑上面的代码,提供了一个非常“简单”的问题示例。如果我使用调试器运行,一切都很好,但如果我没有,则点击Prev或Next TouchableOpacity
按钮永远不会返回并且UI挂起。
更新:如果我更改了事物以使我的FlatList的数据和currentList道具不是this.state的一部分,我可以通过TouchableOpacity按下来推进滚动索引。问题是,我想更新状态,以便进度视图显示当前步骤信息(例如'步骤x的y')。
更新_nextStep()或_previousStep()函数中的状态不应该导致无限循环条件,对吧?我认为FlatList只会在data或extraData props更改时重新呈现。就像我之前说过的,如果我在调试器中运行,我就不会进入无限循环。
这个版本似乎有效 - 我也做了一个干净的,在Xcode中构建:
constructor(props) {
super(props)
this.state = {
stepIndex: 0
}
this.currentStepIndex = 0;
this.nextStep = this._nextStep.bind(this);
this.previousStep = this._previousStep.bind(this);
this.flexItems = [
{ promptText: 'step 1', type: 'intro' },
{ promptText: 'step 2', type: 'location' },
{ promptText: 'step 3', type: 'pickList' },
{ promptText: 'step 4', type: 'longText' },
{ promptText: 'step 5', type: 'photo' },
{ promptText: 'Review and Submit', type: 'review' }
];
this.nextStep = this._nextStep.bind(this);
this.previousStep = this._previousStep.bind(this);
console.log('State: ', this.state);
}
render() {
console.log('Render new request screen')
return (
<SafeAreaView style={baseStyles.safeAreaDark}>
<View style={baseStyles.newRequestContainerView} >
<View style={baseStyles.requestProgressView} >
<Text style ={baseStyles.emptyListSubtitleText} > {this.flexItems.length == this.state.stepIndex ? 'Review & Submit' : 'Step ' + (this.state.stepIndex + 1) + ' of ' + (this.flexItems.length) }</Text>
</View>
<FlatList
ref={(ref) => { this.flatListRef = ref; }}
scrollEnabled={false}
initialNumToRender={1}
initialScrollIndex={0}
refreshing={false}
pagingEnabled={true}
horizontal
getItemLayout={(data, index) => (
{length: Dimensions.get('window').width, offset: Dimensions.get('window').width * index, index}
)}
data={this.flexItems}
showsHorizontalScrollIndicator = { false }
decelerationRate={0}
renderItem={({item, index}) => {
if (item.type === 'intro') {
return (
<View style={baseStyles.swipeContainerView} >
<View style={baseStyles.swipeContentView} >
<Text style ={baseStyles.emptyListSubtitleText}>All About Potholes</Text>
</View>
</View>
)
} else if (item.type === 'pickList') {
return (
<View style={baseStyles.swipeContainerView} >
<View style={baseStyles.swipeContentView} >
<Text style ={baseStyles.emptyListSubtitleText} >{item.promptText}</Text>
</View>
</View>
)
} else {
return (
<View style={baseStyles.swipeContainerView} >
<View style={baseStyles.swipeContentView} >
<Text style ={baseStyles.emptyListSubtitleText} >{item.promptText}</Text>
</View>
</View>
)
}
}}
keyExtractor={(item) => item.type}/>
</View>
<View style={baseStyles.requestNavView}>
<TouchableOpacity
onPress={this.previousStep}
style={requestComponentStyles.locationCaptureButton}>
<Text style={requestComponentStyles.locationCaptureButtonText}>Prev Step</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={this.nextStep}
style={requestComponentStyles.locationCaptureButton}>
<Text style={requestComponentStyles.locationCaptureButtonText}> {this.state.stepIndex < this.flexItems.length - 1 ? 'Next Step' : 'Submit'}</Text>
</TouchableOpacity>
</View>
</SafeAreaView>
);
}
_nextStep() {
console.log('next tapped...')
if (this.currentStepIndex < this.flexItems.length - 1) {
this.currentStepIndex = this.currentStepIndex + 1;
this.flatListRef.scrollToIndex({index: this.currentStepIndex, animated: true});
this.setState (
{
stepIndex: this.currentStepIndex
}
)
} else {
this._onDismissScreen();
}
}
_previousStep () {
console.log('prev tapped...')
if (this.currentStepIndex > 0) {
this.currentStepIndex = this.currentStepIndex - 1;
this.flatListRef.scrollToIndex({index: this.currentStepIndex, animated: true});
this.setState (
{
stepIndex: this.currentStepIndex
}
)
}
}