案例:
界面上部分横向滚动(Scrollview)的标题,下部分是内容列表(FlatList),但是由于 flatlist 的item 高度不定,无法准确使用getItemLayout计算高度,导致无法使用scrollToIndex以及scrollToItem定位方法,而我的需求是:点击上部分的某个标题能准确跳转到某一个 item。
scrollToIndex()
scrollToIndex(params);
将位于指定位置的元素滚动到可视区的指定位置,当viewPosition
为 0 时将它滚动到屏幕顶部,为 1 时将它滚动到屏幕底部,为 0.5 时将它滚动到屏幕中央。
注意:如果不设置
getItemLayout
属性的话,无法跳转到当前渲染区域以外的位置。
scrollToItem()
scrollToItem(params);
这个方法会顺序遍历元素。尽可能使用scrollToIndex
代替。
注意:如果不设置
getItemLayout
属性的话,无法跳转到当前渲染区域以外的位置。
scrollToOffset()
scrollToOffset(params);
滚动列表到指定的偏移(以像素为单位),等同于ScrollView
的scrollTo
方法。
我的item 是 下面三种样式,
肯定有童鞋想说为什么不用numColumns ={2}的属性设置,如果使用了这个,我无法控制一部分item上面的标题UI,当然,如果你可以,欢迎留言教教我
item的样式1
item的样式2
item的样式3
好了,上面说了这么多,就是想引出,下面如何动态计算高度,以及精准定位。
<FlatList
ref={view => {
this.flatlist = view;
}}
initialNumToRender={3}
data={dataArray}
keyExtractor={(item, index) => index.toString()}
renderItem={this.renderItem}
ListHeaderComponent={this.renderHeader}
onScroll={this.listScroll}
/>
<ScrollView
showsHorizontalScrollIndicator={false}
showsVerticalScrollIndicator={false}
horizontal={true}
style={[styles.nav_scroll_top, styles.topTabs]}
scrollEventThrottle={20}
onScroll={this.navScroll}
ref={ref => {
this.myNavScrollTop = ref;
}}>
<View style={styles.nav_top}>
{title.map((item, index) => {
return (
<TouchableOpacity
key={index}
style={styles.nav_view}
onPress={() => this.navSelect(index)}
activeOpacity={1}>
<Text
style={[
styles.nav_title,
navIndex == index ? styles.nav_title_select : null,
]}>
{item}
</Text>
{navIndex == index ? (
<Text style={styles.nav} />
) : null}
</TouchableOpacity>
);
})}
</View>
</ScrollView>
使用onLayout方法,计算每个item 的高度,存储起来
renderItem = rowData => {
const {item, index} = rowData;
const {
hasMainTitle,
field_title,
rule_title,
rule_desc,
leftItem,
rightItem,
} = item;
// console.log('rowItem-===', item);
return (
<View
onLayout={event => {
// console.log('renderItem===', event.nativeEvent.layout.height);
<!--重点在这里,计算每个item的高度-->
layoutText.push({
height: event.nativeEvent.layout.height,
index: index,
});
}}>
{hasMainTitle && (
<View style={[styles.discount_subclass_text_wrap]}>
<!--主标题内容,例如 111-->
</View>
)}
{hasMainTitle && rule_title != '' ? (
<View style={[styles.ruleTitleWrap]}>
<!--副标题-->
</View>
) : null}
{hasMainTitle && rule_desc != '' ? (
<View style={[styles.ruleDescWrap]}>
<!--副标题的描述-->
</View>
) : null}
<View
style={{
flex: 1,
paddingHorizontal: px2dp(50),
flexDirection: 'row',
justifyContent: 'space-between',
}}>
<!--左边的整体布局-->
<!--右边的整体布局-->
</View>
</View>
);
};
点击上部分的title,使用scrollToOffset方法跳转定位到某个位置,由于每个title下的item数量不定,所以我之前存储过每个item 的行数 this.nums=[{index: 0,num: 12},...],表示第1个title下,有12行数据
navSelect(index) {
let layoutHeight = 0;
let allLines = 0;
this.nums.map((item, mapIndex) => {
if (index > mapIndex) {
allLines += item.num;
}
});
layoutText.forEach((item, layoutIndex) => {
if (allLines > layoutIndex) {
layoutHeight += layoutText[layoutIndex].height;
}
});
if (index == 0) {
layoutHeight = 0;
} else {
layoutHeight = layoutHeight + px2dp(220);
}
console.log('layoutHeight==', layoutHeight);
this.flatlist.scrollToOffset({offset: layoutHeight, animated: true});
}
网友评论