├── .DS_Store ├── ScrollableMixin.js ├── package.json ├── demo ├── ScrollView.js └── ListView.js ├── README.md └── PullRefreshScrollView.js /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lvming6816077/react-native-pullRefreshScrollView/HEAD/.DS_Store -------------------------------------------------------------------------------- /ScrollableMixin.js: -------------------------------------------------------------------------------- 1 | let ScrollableMixin = { 2 | getInnerViewNode(): any { 3 | return this.getScrollResponder().getInnerViewNode(); 4 | }, 5 | 6 | scrollTo(destY?: number, destX?: number) { 7 | this.getScrollResponder().scrollTo(destY, destX); 8 | }, 9 | 10 | scrollWithoutAnimationTo(destY?: number, destX?: number) { 11 | this.getScrollResponder().scrollWithoutAnimationTo(destY, destX); 12 | }, 13 | }; 14 | 15 | module.exports = ScrollableMixin; -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-pullrefresh-scrollview", 3 | "version": "1.1.2", 4 | "description": "", 5 | "main": "PullRefreshScrollView.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/lvming6816077/react-native-pullRefreshScrollView.git" 12 | }, 13 | "author": "lvming", 14 | "license": "ISC", 15 | "keywords": [ 16 | "react", 17 | "react-native", 18 | "react-component", 19 | "react-native-component", 20 | "pull-to-refresh", 21 | "ui" 22 | ], 23 | "bugs": { 24 | "url": "https://github.com/lvming6816077/react-native-pullRefreshScrollView/issues" 25 | }, 26 | "homepage": "https://github.com/lvming6816077/react-native-pullRefreshScrollView#readme" 27 | } -------------------------------------------------------------------------------- /demo/ScrollView.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import React, { Component } from 'react'; 4 | import { 5 | View, 6 | ListView, 7 | Image, 8 | Text, 9 | TouchableOpacity, 10 | TouchableHighlight, 11 | StyleSheet, 12 | Alert, 13 | ScrollView, 14 | Dimensions, 15 | InteractionManager, 16 | AppRegistry, 17 | } from 'react-native'; 18 | 19 | 20 | import PullRefreshScrollView from 'react-native-pullrefresh-scrollview'; 21 | 22 | 23 | 24 | 25 | 26 | export default class Projects extends Component { 27 | constructor(props) { 28 | super(props); 29 | 30 | } 31 | 32 | onRefresh(){ 33 | console.log('refresh'); 34 | var self = this; 35 | setTimeout(function(){ 36 | self.refs.PullRefresh.onRefreshEnd(); 37 | },2000); 38 | } 39 | 40 | render() { 41 | 42 | 43 | return ( 44 | 45 | 46 | 47 | 48 | this.onRefresh()}> 49 | Scroll1 50 | Scroll2 51 | Scroll3 52 | Scroll4 53 | Scroll5 54 | Scroll6 55 | 56 | 57 | 58 | 59 | 60 | ); 61 | } 62 | } 63 | 64 | 65 | 66 | const styles = StyleSheet.create({ 67 | container: { 68 | flex: 1 69 | }, 70 | header:{ 71 | height:64, 72 | backgroundColor: '#293447', 73 | }, 74 | scrollItem:{ 75 | flex:1, 76 | height:80, 77 | marginBottom:10, 78 | backgroundColor: '#ccc', 79 | alignItems:'center', 80 | justifyContent:'center' 81 | }, 82 | separator: { 83 | height: 1, 84 | backgroundColor: '#CCCCCC', 85 | }, 86 | }); 87 | AppRegistry.registerComponent('demo', () => Projects); 88 | -------------------------------------------------------------------------------- /demo/ListView.js: -------------------------------------------------------------------------------- 1 | 2 | 'use strict'; 3 | import React, { Component } from 'react'; 4 | import { 5 | View, 6 | ListView, 7 | Image, 8 | Text, 9 | TouchableOpacity, 10 | TouchableHighlight, 11 | StyleSheet, 12 | Alert, 13 | ScrollView, 14 | Dimensions, 15 | InteractionManager, 16 | AppRegistry 17 | } from 'react-native'; 18 | 19 | 20 | import PullRefreshScrollView from 'react-native-pullrefresh-scrollview';; 21 | 22 | 23 | 24 | 25 | 26 | export default class Projects extends Component { 27 | constructor(props) { 28 | super(props); 29 | var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2}); 30 | this.data = ['有种你滑我啊', '有种你滑我啊', '有种你滑我啊', '有种你滑我啊', '有种你滑我啊', '有种你滑我啊', '有种你滑我啊', '有种你滑我啊', '有种你滑我啊', '有种你滑我啊']; 31 | this.state = { 32 | dataSource: ds.cloneWithRows(this.data), 33 | 34 | } 35 | } 36 | 37 | onRefresh(PullRefresh){ 38 | console.log('refresh'); 39 | 40 | 41 | setTimeout(function(){ 42 | PullRefresh.onRefreshEnd(); 43 | },2000); 44 | 45 | } 46 | 47 | onLoadMore(PullRefresh) { 48 | var self = this; 49 | setTimeout(function(){ 50 | 51 | self.data = self.data.concat(['有种你滑我啊(新)']); 52 | self.setState({ 53 | dataSource: self.state.dataSource.cloneWithRows(self.data) 54 | }); 55 | // PullRefresh.onLoadMoreEnd(); uncomment to end loadmore确保下一页没有数据的时候在调用这个方法 56 | },2000); 57 | 58 | console.log('onLoadMore'); 59 | } 60 | 61 | render() { 62 | 63 | 64 | return ( 65 | 66 | 67 | 68 | 69 | this.onRefresh(PullRefresh)} onLoadMore={(PullRefresh)=>this.onLoadMore(PullRefresh)} useLoadMore={1}{...props} />} 72 | 73 | dataSource={this.state.dataSource} 74 | renderSeparator={(sectionID, rowID) => } 75 | renderRow={(rowData) => {rowData}} 76 | /> 77 | 78 | 79 | ); 80 | } 81 | } 82 | 83 | 84 | 85 | const styles = StyleSheet.create({ 86 | container: { 87 | flex: 1 88 | }, 89 | header:{ 90 | height:64, 91 | backgroundColor: '#293447', 92 | }, 93 | rowItem:{ 94 | flex:1, 95 | height:50, 96 | alignItems:'center', 97 | justifyContent:'center' 98 | }, 99 | separator: { 100 | height: 1, 101 | backgroundColor: '#CCCCCC', 102 | }, 103 | }); 104 | AppRegistry.registerComponent('ReactnativeIOS', () => Projects); 105 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## English | [中文](#user-content-中文--english) 2 | 3 | # react-native-pullRefreshScrollView 4 | React Native Pull To Refresh Component for ios platform support ScrollView,ListView 5 | 6 | ## Demo 7 | 8 | #### ScrollView: 9 | 10 | 11 | 12 | 13 | #### ListView: 14 | 15 | 16 | 17 | ## How to use 18 | 19 | ##### Download from npm 20 | 21 |
npm install --save react-native-pullrefresh-scrollview
22 | 23 | ##### Use in Scrollview 24 | 25 | ```javascript 26 | import PullRefreshScrollView from 'react-native-pullrefresh-scrollview'; 27 | 28 | render() { 29 | 30 | return ( 31 | this.onRefresh()}> 32 | Scroll1 33 | 34 | ); 35 | } 36 | ``` 37 | ##### Use in Listview 38 | 39 | ```javascript 40 | import PullRefreshScrollView from 'react-native-pullrefresh-scrollview'; 41 | 42 | render() { 43 | return ( 44 | this.onRefresh(PullRefresh)} {...props} />} 46 | 47 | dataSource={this.state.dataSource} 48 | renderRow={(rowData) => {rowData}} 49 | /> 50 | ); 51 | } 52 | 53 | ``` 54 | ##### image 55 | 56 | 57 | 58 | ##### Only text 59 | 60 | 61 | 62 | ##### Only image 63 | 64 | 65 | 66 | ##### LoadMore 67 | 68 | 69 | 70 | ##### End LoadMore 71 | 72 | 73 | 74 | ##### props 75 | 76 |
 77 | onRefresh:
 78 | refreshedText: ''
 79 | refreshingText: ''
 80 | refreshText:''
 81 | useLoadMore:false
 82 | endText:''
 83 | endingText:''
 84 | indicatorArrowImg: { //  default arrow.png
 85 |     style:{},
 86 |     url:''
 87 | }
 88 | indicatorImg: {  //  default 
 89 |     style:{},
 90 |     url:''
 91 | }
 92 | refreshType:'normal'  // normal  image  text
 93 | 
94 | 95 | ##### Regain the PullRefresh 96 | 97 | ```javascript 98 | onRefresh(PullRefresh){ 99 | PullRefresh.onRefreshEnd(); 100 | } 101 | ``` 102 | ##### End the LoadMore 103 | 104 | ```javascript 105 | onLoadMore(PullRefresh){ 106 | PullRefresh.onLoadMoreEnd(); 107 | } 108 | ``` 109 | ## Advice 110 | 111 | mail:441403517@qq.com 112 | 113 | ## 中文 | [English](#user-content-english--中文) 114 | 115 | # react-native-pullRefreshScrollView 116 | React Native下拉刷新组件 ios 平台 支持ScrollView,ListView 117 | 118 | ## 效果展示 119 | 120 | #### ScrollView: 121 | 122 | 123 | 124 | 125 | #### ListView: 126 | 127 | 128 | 129 | ## 如何引入 130 | 131 | ##### 从npm上下载组件 132 | 133 |
npm install --save react-native-pullrefresh-scrollview
134 | 135 | ##### 在ScrollView中使用 136 | 137 | ```javascript 138 | import PullRefreshScrollView from 'react-native-pullrefresh-scrollview'; 139 | 140 | render() { 141 | 142 | return ( 143 | this.onRefresh()}> 144 | Scroll1 145 | 146 | ); 147 | } 148 | ``` 149 | ##### 在ListView中使用 150 | 151 | ```javascript 152 | import PullRefreshScrollView from 'react-native-pullrefresh-scrollview'; 153 | 154 | render() { 155 | return ( 156 | this.onRefresh(PullRefresh)} {...props} />} 158 | 159 | dataSource={this.state.dataSource} 160 | renderRow={(rowData) => {rowData}} 161 | /> 162 | ); 163 | } 164 | 165 | ``` 166 | ##### 定制图片 167 | 168 | 169 | 170 | ##### 纯文字 171 | 172 | 173 | 174 | ##### 纯图片 175 | 176 | 177 | 178 | ##### 上拉加载 179 | 180 | 181 | 182 | ##### 上拉加载完成 183 | 184 | 185 | 186 | ##### props 187 | 188 |
189 | onRefresh:当触发刷新时的回调
190 | refreshedText: '释放立即刷新'
191 | refreshingText: '正在刷新数据中..'
192 | refreshText:'下拉可以刷新'
193 | useLoadMore:false //是否使用滚动加载功能 即上拉加载
194 | endText:'已经加载完成'
195 | endingText:'加载更多数据'
196 | indicatorArrowImg: { // 下拉箭头图片和样式 default arrow.png
197 |     style:{},
198 |     url:''
199 | }
200 | indicatorImg: {  // loading图片和样式 default 
201 |     style:{},
202 |     url:''
203 | }
204 | refreshType:'normal'  // normal  image  text
205 | 
206 | 207 | ##### 收回下拉刷新 208 | 209 | ```javascript 210 | onRefresh(PullRefresh){ 211 | PullRefresh.onRefreshEnd(); 212 | } 213 | ``` 214 | ##### 结束滚动加载 215 | 216 | ```javascript 217 | onLoadMore(PullRefresh){ 218 | PullRefresh.onLoadMoreEnd(); 219 | } 220 | ``` 221 | ## 建议和反馈 222 | 223 | 此组件还在不断更新中,如有需求欢迎提出反馈441403517@qq.com 224 | 225 | ## 合作开发 226 | 此组件目前仅支持ios平台,android平台暂不支持,欢迎有兴趣的小伙伴一起加入开发,将android版的开发出来! 227 | -------------------------------------------------------------------------------- /PullRefreshScrollView.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | import React, { Component } from 'react'; 3 | import { 4 | View, 5 | Text, 6 | Image, 7 | StyleSheet, 8 | AsyncStorage, 9 | Animated, 10 | Easing, 11 | ScrollView, 12 | ListView, 13 | ActivityIndicator, 14 | AppRegistry, 15 | } from 'react-native'; 16 | 17 | import ScrollableMixin from './ScrollableMixin'; 18 | 19 | export default class PullRefreshScrollView extends Component { 20 | constructor(props) { 21 | super(props); 22 | // = this.scrollView; 23 | this.refreshedText = props.refreshedText; 24 | this.refreshingText = props.refreshingText; 25 | this.refreshText = props.refreshText; 26 | this.endText = props.endText; 27 | this.endingText = props.endingText; 28 | this.useLoadMore = props.useLoadMore; 29 | this.state = { 30 | prTitle:this.refreshText, 31 | prState:0, 32 | prTimeDisplay:'暂无更新', 33 | prLoading:false, 34 | prArrowDeg:new Animated.Value(0), 35 | lmState:0 36 | }; 37 | 38 | 39 | this.base64Icon = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAABQBAMAAAD8TNiNAAAAJ1BMVEUAAACqqqplZWVnZ2doaGhqampoaGhpaWlnZ2dmZmZlZWVmZmZnZ2duD78kAAAADHRSTlMAA6CYqZOlnI+Kg/B86E+1AAAAhklEQVQ4y+2LvQ3CQAxGLSHEBSg8AAX0jECTnhFosgcjZKr8StE3VHz5EkeRMkF0rzk/P58k9rgOW78j+TE99OoeKpEbCvcPVDJ0OvsJ9bQs6Jxs26h5HCrlr9w8vi8zHphfmI0fcvO/ZXJG8wDzcvDFO2Y/AJj9ADE7gXmlxFMIyVpJ7DECzC9J2EC2ECAAAAAASUVORK5CYII='; 40 | this.dragFlag = false; //scrollview是否处于拖动状态的标志 41 | this.prStoryKey = 'prtimekey'; 42 | 43 | 44 | 45 | } 46 | // 滚动触发 47 | onScroll(e){ 48 | let target = e.nativeEvent; 49 | let y = target.contentOffset.y; 50 | 51 | if (this.dragFlag) { 52 | if (y <= -70) { 53 | this.upState(); 54 | 55 | } else { 56 | this.downState(); 57 | } 58 | } 59 | 60 | this.onCheckEndReached(target); 61 | 62 | 63 | if (this.props.onScroll) { 64 | this.props.onScroll(e); 65 | } 66 | } 67 | // 高于临界值状态 68 | upState(){ 69 | this.setState({ 70 | prTitle:this.refreshedText, 71 | prState:1 72 | }); 73 | 74 | Animated.timing(this.state.prArrowDeg, { 75 | toValue: 1, 76 | duration: 100, 77 | easing: Easing.inOut(Easing.quad) 78 | }).start(); 79 | } 80 | // 低于临界值状态 81 | downState(){ 82 | this.setState({ 83 | prTitle:this.refreshText, 84 | prState:0 85 | }); 86 | Animated.timing(this.state.prArrowDeg, { 87 | toValue: 0, 88 | duration: 100, 89 | easing: Easing.inOut(Easing.quad) 90 | }).start(); 91 | } 92 | 93 | // 手指离开 94 | onScrollEndDrag(){ 95 | 96 | this.dragFlag = false; 97 | if (this.state.prState) { 98 | 99 | // 回到待收起状态 100 | this.scrollView.scrollTo({x:0,y:-70,animated:true}); 101 | 102 | 103 | 104 | this.setState({ 105 | prTitle:this.refreshingText, 106 | prLoading:true, 107 | prArrowDeg:new Animated.Value(0), 108 | 109 | }); 110 | 111 | // 触发外部的下拉刷新方法 112 | if (this.props.onRefresh) { 113 | this.props.onRefresh(this); 114 | } 115 | } 116 | 117 | } 118 | // 手指未离开 119 | onScrollBeginDrag(){ 120 | this.setState({ 121 | beginScroll: true 122 | }); 123 | this.dragFlag = true; 124 | 125 | if (this.props.onScrollBeginDrag) { 126 | this.props.onScrollBeginDrag(); 127 | } 128 | } 129 | onCheckEndReached(target){ 130 | if (!this.useLoadMore || this.state.lmState) { 131 | return; 132 | } 133 | let contentSize = target.contentSize; 134 | let layoutMeasurement = target.layoutMeasurement; 135 | let y = target.contentOffset.y; 136 | 137 | if (contentSize.height - layoutMeasurement.height - y < 40) { 138 | 139 | // 触发外部的滚动加载方法 140 | if (this.props.onLoadMore && this.lastContentHeight != contentSize.height) { 141 | this.lastContentHeight = contentSize.height; 142 | this.props.onLoadMore(this); 143 | } 144 | 145 | } 146 | 147 | } 148 | onLoadMoreEnd(target){ 149 | this.setState({ 150 | lmState:1 151 | }); 152 | 153 | } 154 | onBeginLoadMore(target){ 155 | this.setState({ 156 | lmState:0 157 | }); 158 | 159 | } 160 | onRefreshEnd(){ 161 | let now = new Date().getTime(); 162 | this.setState({ 163 | prTitle:this.refreshText, 164 | prLoading:false, 165 | beginScroll: false, 166 | prTimeDisplay:dateFormat(now,'yyyy-MM-dd hh:mm') 167 | }); 168 | 169 | // 存一下刷新时间 170 | AsyncStorage.setItem(this.prStoryKey, now.toString()); 171 | this.scrollView.scrollTo({x:0,y:0,animated:true}); 172 | } 173 | componentDidMount(){ 174 | 175 | AsyncStorage.getItem(this.prStoryKey, (error, result) => { 176 | 177 | 178 | if (result) { 179 | result = parseInt(result); 180 | 181 | //将时间传入下拉刷新的state 182 | this.setState({ 183 | prTimeDisplay:dateFormat(new Date(result),'yyyy-MM-dd hh:mm'), 184 | }); 185 | 186 | } 187 | 188 | 189 | }); 190 | } 191 | renderNormalContent(){ 192 | this.transform = [{rotate:this.state.prArrowDeg.interpolate({ 193 | inputRange: [0,1], 194 | outputRange: ['0deg', '-180deg'] 195 | })}]; 196 | let jsxarr = []; 197 | let arrowStyle = { 198 | position:'absolute', 199 | width:14, 200 | height:23, 201 | left:-50, 202 | top:-4, 203 | transform:this.transform 204 | }; 205 | let indicatorStyle = { 206 | position:'absolute', 207 | left:-40, 208 | top:-1, 209 | width:16, 210 | height:16 211 | }; 212 | 213 | if (this.props.indicatorImg.url) { 214 | if (this.props.indicatorImg.style) { 215 | indicatorStyle = this.props.indicatorImg.style; 216 | } 217 | if (this.state.prLoading) { 218 | jsxarr.push(); 219 | } else { 220 | jsxarr.push(null); 221 | } 222 | } else { 223 | if (this.state.prLoading) { 224 | jsxarr.push(); 225 | } else { 226 | jsxarr.push(null); 227 | } 228 | } 229 | 230 | if (this.props.indicatorArrowImg.url) { 231 | if (this.props.indicatorArrowImg.style) { 232 | arrowStyle = this.props.arrowStyle.style; 233 | } 234 | arrowStyle.transform = this.transform; 235 | if (!this.state.prLoading) { 236 | jsxarr.push(); 237 | } else { 238 | jsxarr.push(null); 239 | } 240 | } else { 241 | if (!this.state.prLoading) { 242 | jsxarr.push(); 243 | } else { 244 | jsxarr.push(null); 245 | } 246 | } 247 | jsxarr.push({this.state.prTitle}) 248 | 249 | return ( 250 | 251 | 252 | 253 | {jsxarr.map((item,index)=>{ 254 | return {item} 255 | })} 256 | 257 | 258 | 上次更新时间:{this.state.prTimeDisplay} 259 | 260 | ); 261 | 262 | } 263 | renderBottomContent(){ 264 | let jsx = []; 265 | let indicatorStyle = { 266 | position:'absolute', 267 | left:-40, 268 | top:-1, 269 | width:16, 270 | height:16 271 | }; 272 | 273 | if (this.state.lmState) { 274 | jsx.push({this.endText}); 275 | } else { 276 | jsx.push(); 277 | jsx.push({this.endingText}); 278 | } 279 | 280 | return (jsx); 281 | } 282 | rendeTextContent(){ 283 | 284 | let prStateStyle = { 285 | marginBottom:20, 286 | fontSize:12, 287 | }; 288 | return ({this.state.prTitle}); 289 | } 290 | rendeImgContent(){ 291 | this.transform = [{rotate:this.state.prArrowDeg.interpolate({ 292 | inputRange: [0,1], 293 | outputRange: ['0deg', '-180deg'] 294 | })}]; 295 | let jsxarr = []; 296 | let arrowStyle = { 297 | width:14, 298 | height:23, 299 | marginBottom:20, 300 | transform:this.transform 301 | }; 302 | let indicatorStyle = { 303 | width:16, 304 | height:16, 305 | marginBottom:20, 306 | }; 307 | if (this.props.indicatorImg.url) { 308 | if (this.props.indicatorImg.style) { 309 | indicatorStyle = this.props.indicatorImg.style; 310 | } 311 | if (this.state.prLoading) { 312 | jsxarr.push(); 313 | } else { 314 | jsxarr.push(null); 315 | } 316 | } else { 317 | if (this.state.prLoading) { 318 | jsxarr.push(); 319 | } else { 320 | jsxarr.push(null); 321 | } 322 | } 323 | 324 | if (this.props.indicatorArrowImg.url) { 325 | if (this.props.indicatorArrowImg.style) { 326 | arrowStyle = this.props.arrowStyle.style; 327 | } 328 | arrowStyle.transform = this.transform; 329 | if (!this.state.prLoading) { 330 | jsxarr.push(); 331 | } else { 332 | jsxarr.push(null); 333 | } 334 | } else { 335 | if (!this.state.prLoading) { 336 | jsxarr.push(); 337 | } else { 338 | jsxarr.push(null); 339 | } 340 | } 341 | 342 | return jsxarr; 343 | } 344 | renderIndicatorContent(){ 345 | if (!this.state.beginScroll) { 346 | //return null; 347 | } 348 | 349 | let type = this.props.refreshType; 350 | let jsx; 351 | 352 | if (type == 'normal') { 353 | jsx = [this.renderNormalContent()]; 354 | } 355 | if (type == 'text') { 356 | jsx = [this.rendeTextContent()]; 357 | } 358 | 359 | if (type == 'image') { 360 | jsx = this.rendeImgContent(); 361 | } 362 | 363 | return ( 364 | 365 | 366 | {jsx.map((item,index)=>{ 367 | return {item} 368 | })} 369 | 370 | ); 371 | } 372 | renderIndicatorContentBottom(){ 373 | let jsx = [this.renderBottomContent()]; 374 | return ( 375 | 376 | 377 | {jsx.map((item,index)=>{ 378 | return {item} 379 | })} 380 | 381 | ); 382 | } 383 | getScrollResponder() { 384 | return this.scrollView.getScrollResponder(); 385 | } 386 | 387 | setNativeProps(props) { 388 | this.scrollView.setNativeProps(props); 389 | } 390 | fixSticky() { 391 | let stickyHeaderIndices = []; 392 | let propsStickHeader = this.props.stickyHeaderIndices || []; 393 | for (let i = 0 ; i < propsStickHeader.length ; i++) { 394 | if (i > 0) { 395 | stickyHeaderIndices.push(propsStickHeader[i]+1); 396 | } 397 | 398 | } 399 | return stickyHeaderIndices; 400 | } 401 | render() { 402 | 403 | return React.cloneElement( this.scrollView = scrollView} 405 | {...this.props} 406 | stickyHeaderIndices={this.fixSticky()} 407 | scrollEventThrottle={16} 408 | onScrollEndDrag={()=>this.onScrollEndDrag()} 409 | onScrollBeginDrag={()=>this.onScrollBeginDrag()} 410 | onScroll={(e)=>this.onScroll(e)} 411 | 412 | > 413 | 414 | 415 | {this.renderIndicatorContent()} 416 | {this.props.children} 417 | {this.useLoadMore ? this.renderIndicatorContentBottom() : null} 418 | , { 419 | ref: component => { 420 | this.scrollView = component; 421 | }, 422 | }); 423 | 424 | } 425 | 426 | } 427 | 428 | const dateFormat = function(dateTime, fmt) { 429 | let date = new Date(dateTime); 430 | fmt = fmt || 'yyyy-MM-dd'; 431 | let o = { 432 | "M+": date.getMonth() + 1, //月份 433 | "d+": date.getDate(), //日 434 | "h+": date.getHours(), //小时 435 | "m+": date.getMinutes(), //分 436 | "s+": date.getSeconds(), //秒 437 | "q+": Math.floor((date.getMonth() + 3) / 3), //季度 438 | "S": date.getMilliseconds() //毫秒 439 | }; 440 | if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length)); 441 | for (let k in o) 442 | if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length))); 443 | return fmt; 444 | } 445 | const styles = StyleSheet.create({ 446 | pullRefresh:{ 447 | position:'absolute', 448 | top:-69, 449 | left:0, 450 | backfaceVisibility: 'hidden', 451 | right:0, 452 | height:70, 453 | backgroundColor:'#fafafa', 454 | alignItems:'center', 455 | justifyContent:'flex-end' 456 | }, 457 | loadMore: { 458 | height:35, 459 | backgroundColor:'#fafafa', 460 | alignItems:'center', 461 | justifyContent:'center' 462 | }, 463 | text: { 464 | height:70, 465 | backgroundColor:'#fafafa', 466 | }, 467 | prText:{ 468 | marginBottom:4, 469 | color:'#000', 470 | fontSize:12, 471 | }, 472 | 473 | prState:{ 474 | marginBottom:4, 475 | fontSize:12, 476 | }, 477 | lmState:{ 478 | fontSize:12, 479 | }, 480 | indicatorContent:{ 481 | flexDirection:'row', 482 | marginBottom:5 483 | }, 484 | 485 | }); 486 | 487 | 488 | PullRefreshScrollView.defaultProps = { 489 | refreshedText: '释放立即刷新', 490 | refreshingText: '正在刷新数据中..', 491 | refreshText:'下拉可以刷新', 492 | endText:'已加载完成', 493 | endingText:'加载更多数据', 494 | indicatorArrowImg: { 495 | style:'', 496 | url:'' 497 | }, 498 | indicatorImg: { 499 | style:'', 500 | url:'' 501 | }, 502 | refreshType:'normal', 503 | onRefresh:'' 504 | }; 505 | Object.assign(PullRefreshScrollView.prototype, ScrollableMixin); 506 | --------------------------------------------------------------------------------