javascript - 如何在与 ScrollView 的本机反应中实现 scrollspy?
问题描述
我有一个具有不同元素的 ScrollView 组件说:
<ScrollView>
<Item1/>
<Item2/>
<Item3/>
</ScrollView>
我现在有一个选项卡,我需要根据用户在滚动视图中查看的当前部分突出显示每个选项卡项。例如,如果用户<Item2/>
在滚动视图中查看/滚动到,那么我应该突出显示选项卡中的 item2 图标。
此外,如果用户单击选项卡项目,它应该自动使滚动视图滚动到相应项目的部分。
有没有办法在本机反应中实现这个滚动间谍功能?
解决方案
要实现所需的行为,您需要结合几件事。
ScrollView
有一个名为的方法scrollTo
,可以让您滚动到内容的所需位置。- 为了能够检测到
ScrollView
您需要使用onScroll
属性的当前位置是什么。您可以将此属性与 结合使用scrollEventThrottle
以获得更好的准确性。 - 要获取每个项目在其中的位置,
ScrollView
您需要onLayout
为每个项目实现属性。
下面是一个小示例应用程序,展示了如何实现上述步骤。
const Item = props => (
<View
style={{ minHeight: 500 }}
onLayout={e => props.onItemLayout(e, props.index)}>
<Text>{`Item ${props.index}`}</Text>
</View>
);
export default class App extends Component {
constructor() {
super();
this.state = {
sections: [1, 2, 3],
currentSection: 1
};
}
moveToSetion = section => {
// scroll view to section
this.scrollView.scrollTo({ x: 0, y: this.state[section], animated: true });
// set state to current section
this.setState({ currentSection: section });
};
onItemLayout = ({ nativeEvent: { layout: { x, y, width, height } } }, section) => {
// setting each items position
this.setState({ [section]: y });
};
onScroll = ({ nativeEvent: { contentOffset: { y, x } } }) => {
let _currentSection;
// loop sections to calculate which section scrollview is on
this.state.sections.forEach((section) => {
// adding 15 to calculate Text's height
if((y + 15) > this.state[section]) _currentSection = section
})
// settint the currentSection to the calculated current section
this.setState({ currentSection: _currentSection })
}
render() {
return (
<View style={styles.container}>
<View style={styles.buttonContainer}>
{this.state.sections.map(section => (
<Button
key={section}
title={`Section ${section}`}
color={this.state.currentSection === section ? 'red' : 'blue'}
onPress={() => this.moveToSetion(section)}
/>
))}
</View>
<ScrollView
style={styles.scrollView}
ref={ref => (this.scrollView = ref)}
scrollEventThrottle={100}
onScroll={this.onScroll}>
{this.state.sections.map(section => (
<Item
key={section}
index={section}
onItemLayout={this.onItemLayout}
/>
))}
</ScrollView>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
},
buttonContainer: {
flexDirection: 'row',
justifyContent: 'center',
position: 'fixed',
top: 0,
},
scrollView: {
paddingLeft: 15,
paddingRight: 15
}
});
推荐阅读
- bash - 用一个换行符替换两个换行符,用两个换行符替换两个以上的换行符
- reactjs - React-如何获取 blob SAS URL 或 SAS 令牌?
- database - 如何将环境变量传递给 mongo docker-entrypoint-initdb.d?
- java - 无法在 ec2 上初始化类 net.sourceforge.tess4j.TessAPI
- excel - Powershell - 格式化数据后读取 Excel
- android - 如何识别安装应用程序正在使用android中的哪个证书
- r - 具有其他数据密度曲线的直方图
- javascript - 如何检查js上的输入字段并根据文本值编写和回答
- android - Android Bundle 包在启动时崩溃
- ruby-on-rails - NLP / Rails 情感搜索