1.通过onLayout快速的获得一个view的位置、宽、高
class TestView extends Component {
// 构造
constructor(props) {
super(props);
this.state = {
x: 0,
y: 0,
width: 0,
height: 0
}
}
measureView(event) {
console.log('event peroperties: ', event);
this.setState({
x: event.nativeEvent.layout.x,
y: event.nativeEvent.layout.y,
width: event.nativeEvent.layout.width,
height: event.nativeEvent.layout.height
})
}
changeHeight() {
this.setState({
viewHeight: 200
})
}
render(){
return (
<View >
<View onLayout={(event) => this.measureView(event)} style={{height:this.state.viewHeight, marginTop:120, backgroundColor: 'orange'}}>
<Text >The outer view of this text is being measured!</Text>
<Text>x: {this.state.x}</Text>
<Text>y: {this.state.y}</Text>
<Text>width: {this.state.width}</Text>
<Text>height: {this.state.height}</Text>
</View>
<TouchableHighlight style={{flexDirection:'row', alignItems: 'center', justifyContent: 'center', padding:15, backgroundColor: '#ddd', marginTop:10}} onPress={() => this.changeHeight() }>
<Text style={{fontSize:18}}>Change height of container</Text>
</TouchableHighlight>
</View>
);
}
}
2. 用ScrollView+Items来实现滚动到ScrollView的底部
class TestView extends Component {
// 构造
constructor(props) {
super(props);
this.state = {
listHeight: 0,
scrollViewHeight: 0
}
}
componentDidUpdate(){
this.scrollToBottom()
}
scrollToBottom(){
const bottomOfList = this.state.listHeight - this.state.scrollViewHeight
console.log('scrollToBottom');
this.scrollView.scrollTo({ y: bottomOfList })
}
renderRow(message, index){
return <Text key={index}> {message} </Text>
}
render() {
return (
<View style={{flex: 1}}>
<View style={{height: 200, backgroundColor: 'red'}}></View>
<ScrollView
keyboardDismissMode="on-drag"
onContentSizeChange={ (contentWidth, contentHeight) => {
this.setState({listHeight: contentHeight })
}}
onLayout={ (e) => {
const height = e.nativeEvent.layout.height
console.log("------------scollview height: " + height)
this.setState({scrollViewHeight: height })
}}
ref={ (ref) => this.scrollView = ref }>
{this.props.messages.map( message => this.renderRow(message) )}
</ScrollView>
</View>
)
}
}
滚动的距离=listHeight - viewHeight=列表内容高度 - 视口高度
3.利用footer来定位ListView底部坐标
class TestView extends Component {
// 构造
constructor(props) {
super(props);
this.ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2})
this.data = []
for (let i = 0; i < 1000; ++i) {
this.data.push(i)
}
this.state = {
listHeight: 0,
dataSource: this.ds.cloneWithRows(this.data)
}
}
componentDidUpdate() {
this.scrollToBottom()
}
scrollToBottom() {
if (this.listHeight && this.footerY && this.footerY > this.listHeight) {
let delta = this.footerY - this.listHeight
let scrollResponder = this.listView.getScrollResponder()
scrollResponder.scrollTo({y: delta, animated: true})
}
}
renderRow(rowData, sectionID, rowID, highlightRow) {
console.log("renderRow:" + utils.toString(rowData))
return <Text key={rowData}>{rowData}</Text>
}
render() {
return (
<View style={{flex: 1}}>
<Text style={{height: 100, backgroundColor: 'green'}} onPress={() => this.onClicked()}> ClickedMe </Text>
<ListView
ref={(listview) => this.listView = listview}
initialListSize={30}
pageSize={30}
onLayout={
e => {
console.log("----------------ListView onLayout:" + e.nativeEvent.layout.height)
this.listHeight = e.nativeEvent.layout.height
}
}
dataSource={this.state.dataSource}
renderRow={(...args) => this.renderRow(...args)}
renderFooter = {() => {
return (
<View onLayout={ (e) => {
console.log("--------------------render footer" + e.nativeEvent.layout.y)
this.footerY = e.nativeEvent.layout.y}
}></View>
)
}}
>
</ListView>
</View>
)
}
onClicked() {
this.scrollToBottom()
}
}
缺点:
- renderFooter需要设置页刷新行数等优化数据,否则效率低,会不断调用renderfooter
- ListView数据大的时候,不会一次性渲染完所有数据,所以调用scrollToBottom,可能只滚动到中间部分
eg.1000行数据,每次渲染50行,renderFooter每隔50行计算一次footer坐标y,每次定位底部坐标都是 50H、100H、150H...950H、1000H
也就是说,除非一次性渲染完所有的数据,否则无法直接滚动到底部
网友评论