案例:
界面上部分橫向滾動(dòng)(Scrollview)的標(biāo)題卫枝,下部分是內(nèi)容列表(FlatList)泻肯,但是由于 flatlist 的item 高度不定渊迁,無法準(zhǔn)確使用getItemLayout計(jì)算高度,導(dǎo)致無法使用scrollToIndex以及scrollToItem定位方法灶挟,而我的需求是:點(diǎn)擊上部分的某個(gè)標(biāo)題能準(zhǔn)確跳轉(zhuǎn)到某一個(gè) item琉朽。
scrollToIndex()
scrollToIndex(params);
將位于指定位置的元素滾動(dòng)到可視區(qū)的指定位置,當(dāng)viewPosition
為 0 時(shí)將它滾動(dòng)到屏幕頂部稚铣,為 1 時(shí)將它滾動(dòng)到屏幕底部箱叁,為 0.5 時(shí)將它滾動(dòng)到屏幕中央墅垮。
注意:如果不設(shè)置
getItemLayout
屬性的話,無法跳轉(zhuǎn)到當(dāng)前渲染區(qū)域以外的位置耕漱。
scrollToItem()
scrollToItem(params);
這個(gè)方法會(huì)順序遍歷元素算色。盡可能使用scrollToIndex
代替。
注意:如果不設(shè)置
getItemLayout
屬性的話螟够,無法跳轉(zhuǎn)到當(dāng)前渲染區(qū)域以外的位置灾梦。
scrollToOffset()
scrollToOffset(params);
滾動(dòng)列表到指定的偏移(以像素為單位),等同于ScrollView
的scrollTo
方法妓笙。
案例UI
我的item 是 下面三種樣式若河,
肯定有童鞋想說為什么不用numColumns ={2}的屬性設(shè)置,如果使用了這個(gè)寞宫,我無法控制一部分item上面的標(biāo)題UI萧福,當(dāng)然,如果你可以辈赋,歡迎留言教教我
item的樣式1
item的樣式2
item的樣式3
好了鲫忍,上面說了這么多,就是想引出钥屈,下面如何動(dòng)態(tài)計(jì)算高度悟民,以及精準(zhǔn)定位。
<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方法篷就,計(jì)算每個(gè)item 的高度逾雄,存儲(chǔ)起來
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);
<!--重點(diǎn)在這里,計(jì)算每個(gè)item的高度-->
layoutText.push({
height: event.nativeEvent.layout.height,
index: index,
});
}}>
{hasMainTitle && (
<View style={[styles.discount_subclass_text_wrap]}>
<!--主標(biāo)題內(nèi)容腻脏,例如 111-->
</View>
)}
{hasMainTitle && rule_title != '' ? (
<View style={[styles.ruleTitleWrap]}>
<!--副標(biāo)題-->
</View>
) : null}
{hasMainTitle && rule_desc != '' ? (
<View style={[styles.ruleDescWrap]}>
<!--副標(biāo)題的描述-->
</View>
) : null}
<View
style={{
flex: 1,
paddingHorizontal: px2dp(50),
flexDirection: 'row',
justifyContent: 'space-between',
}}>
<!--左邊的整體布局-->
<!--右邊的整體布局-->
</View>
</View>
);
};
點(diǎn)擊上部分的title,使用scrollToOffset方法跳轉(zhuǎn)定位到某個(gè)位置,由于每個(gè)title下的item數(shù)量不定银锻,所以我之前存儲(chǔ)過每個(gè)item 的行數(shù) this.nums=[{index: 0,num: 12},...]永品,表示第1個(gè)title下,有12行數(shù)據(jù)
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});
}