我正在使用React Native编写应用程序.它有一个ListView
显示项目列表.
当有新的项目可用时,我会在底部添加新项目.我想滚动到底部以ListView
自动显示新项目.我怎样才能做到这一点?
jon*_*asb 10
作为本土做出反应都0.41 ListView
和ScrollView
有scrollToEnd()
方法.ListView
的文件记录在https://facebook.github.io/react-native/docs/listview.html#scrolltoend
在渲染时,您需要使用a ref
来存储对您的引用ListView
:
<ListView
dataSource={yourDataSource}
renderRow={yourRenderingCallback}
ref={listView => { this.listView = listView; }}
</ListView>
Run Code Online (Sandbox Code Playgroud)
然后,您可以调用this.listView.scrollToEnd()
滚动到列表的底部.如果您希望每次ListView
更改内容时(例如,添加内容时)都这样做,那么请在ListView
's onContentSizeChange
prop回调中执行此操作,就像使用ScrollView
.
我解决了这个问题ScrollView
.这是一个简单的例子:
class MessageList extends Component {
componentDidUpdate() {
let innerScrollView = this._scrollView.refs.InnerScrollView;
let scrollView = this._scrollView.refs.ScrollView;
requestAnimationFrame(() => {
innerScrollView.measure((innerScrollViewX, innerScrollViewY, innerScrollViewWidth, innerScrollViewHeight) => {
scrollView.measure((scrollViewX, scrollViewY, scrollViewWidth, scrollViewHeight) => {
var scrollTo = innerScrollViewHeight - scrollViewHeight + innerScrollViewY;
if (innerScrollViewHeight < scrollViewHeight) {
return;
}
this._scrollView.scrollTo(scrollTo);
});
});
});
}
render() {
return (
<ScrollView ref={component => this._scrollView = component}>
{this.props.messages.map((message, i) => {
return <Text key={i}>{message}</Text>;
})}
</ScrollView>
);
}
}
Run Code Online (Sandbox Code Playgroud)
这个问题有一个非常简单的解决方案.您可以将ListView包装在Scrollview组件中.这将提供确定列表底部位置的所有必要方法.
首先包装listView
<ScrollView>
<MyListViewElement />
</ScrollView>
Run Code Online (Sandbox Code Playgroud)
然后使用返回组件(scrollView)高度的onLayout方法.并将其保存到州.
// add this method to the scrollView component
onLayout={ (e) => {
// get the component measurements from the callbacks event
const height = e.nativeEvent.layout.height
// save the height of the scrollView component to the state
this.setState({scrollViewHeight: height })
}}
Run Code Online (Sandbox Code Playgroud)
然后使用onContentSizeChange方法返回内部组件(listView)的高度.并将其保存到州.每次从列表中添加或删除元素或更改高度时都会发生这种情况.基本上每当有人向您的列表添加新消息时.
onContentSizeChange={ (contentWidth, contentHeight) => {
// save the height of the content to the state when there’s a change to the list
// this will trigger both on layout and any general change in height
this.setState({listHeight: contentHeight })
}}
Run Code Online (Sandbox Code Playgroud)
要滚动,您需要在ScrollView中找到scrollTo方法.你可以通过在这样的状态下将它保存到ref来访问它.
<ScrollView
ref={ (component) => this._scrollView = component }
…
>
</ScrollView>
Run Code Online (Sandbox Code Playgroud)
现在,您拥有计算所需的一切,并触发滚动到列表底部.您可以选择在组件中的任何位置执行此操作,我会将其添加到组件中,componentDidUpdate()
因此无论何时组件呈现它都会滚动到底部.
componentDidUpdate(){
// calculate the bottom
const bottomOfList = this.state.listHeight - this.state.scrollViewHeight
// tell the scrollView component to scroll to it
this.scrollView.scrollTo({ y: bottomOfList })
}
Run Code Online (Sandbox Code Playgroud)
就是这样.这就是ScrollView最终应该是这样的样子
<ScrollView
ref={ (component) => this._scrollView = component }
onContentSizeChange={ (contentWidth, contentHeight) => {
this.setState({listHeight: contentHeight })
}}
onLayout={ (e) => {
const height = e.nativeEvent.layout.heigh
this.setState({scrollViewHeight: height })
}}
>
<MyListViewElement />
</ScrollView>
Run Code Online (Sandbox Code Playgroud)
一个简单的方法我使用ListView并发现使用scrollView更容易做到这一点,为了简单起见,我推荐它.这是我的消息模块的直接副本,用于滚动到底部功能.希望能帮助到你.
class Messages 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 (
<Message
key={message.id}
{...message}
/>
);
}
render(){
return(
<ScrollView
keyboardDismissMode="on-drag"
onContentSizeChange={ (contentWidth, contentHeight) => {
this.setState({listHeight: contentHeight })
}}
onLayout={ (e) => {
const height = e.nativeEvent.layout.height
this.setState({scrollViewHeight: height })
}}
ref={ (ref) => this.scrollView = ref }>
{this.props.messages.map( message => this.renderRow(message) )}
</ScrollView>
)
}
}
export default Messages
Run Code Online (Sandbox Code Playgroud)
我遇到了同样的问题,并提出了这个解决方案:
render()
{
if("listHeight" in this.state &&
"footerY" in this.state &&
this.state.footerY > this.state.listHeight)
{
var scrollDistance = this.state.listHeight - this.state.footerY;
this.refs.list.getScrollResponder().scrollTo(-scrollDistance);
}
return (
<ListView ref="list"
onLayout={(event) => {
var layout = event.nativeEvent.layout;
this.setState({
listHeight : layout.height
});
}}
renderFooter={() => {
return <View onLayout={(event)=>{
var layout = event.nativeEvent.layout;
this.setState({
footerY : layout.y
});
}}></View>
}}
/>
)
}
Run Code Online (Sandbox Code Playgroud)
基本上,我渲染一个空页脚,以确定列表底部的Y偏移量.从这里我可以根据列表容器高度导出到底部的滚动偏移量.
注意:最后一个if条件检查内容长度是否溢出列表高度,并且只检查它是否滚动.您是否需要这取决于您的设计!
希望这个解决方案可以帮助其他人处于相同的位置
FWIW我不喜欢在另一个答案中讨论的InvertibleScrollView插件,因为它对整个列表和每个列表项进行了比例转换..这听起来很贵!
请查看: https: //github.com/650Industries/react-native-invertible-scroll-view
该组件反转原始滚动视图。因此,当新项目到达时,它会自动滚动到底部。
不过,请注意两点
您的“数据数组”也需要恢复。也就是说,应该是
[new_item, old_item]
Run Code Online (Sandbox Code Playgroud)
任何新到达的项目都应插入到最前面。
尽管他们ListView
在自述文件示例中使用了此插件,但在使用此插件时仍然存在一些缺陷ListView
。相反,我建议您只使用ScrollView
,它效果很好。
反向滚动视图的示例:
var MessageList = React.createClass({
propTypes: {
messages: React.PropTypes.array,
},
renderRow(message) {
return <Text>{message.sender.username} : {message.content}</Text>;
},
render() {
return (
<InvertibleScrollView
onScroll={(e) => console.log(e.nativeEvent.contentOffset.y)}
scrollEventThrottle={200}
renderScrollView={
(props) => <InvertibleScrollView {...props} inverted />
}>
{_.map(this.props.messages, this.renderRow)}
</InvertibleScrollView>
);
}
});
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
26160 次 |
最近记录: |