├── .buckconfig ├── .eslintrc.js ├── .flowconfig ├── .gitattributes ├── .gitignore ├── .prettierrc.js ├── .watchmanconfig ├── App.js ├── Examples ├── BouncesAndScrollEnabledExample.js ├── ComplexExample.js ├── InputExample.js ├── RefreshAndLoadingExample.js ├── ScrollToAndOnScrollExample.js ├── Test.js └── index.js ├── LICENSE ├── README.md ├── __tests__ └── App-test.js ├── android ├── app │ ├── _BUCK │ ├── build.gradle │ ├── build_defs.bzl │ ├── debug.keystore │ ├── proguard-rules.pro │ └── src │ │ ├── debug │ │ ├── AndroidManifest.xml │ │ └── java │ │ │ └── com │ │ │ └── ssvexample │ │ │ └── ReactNativeFlipper.java │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ └── com │ │ │ └── ssvexample │ │ │ ├── MainActivity.java │ │ │ └── MainApplication.java │ │ └── res │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ └── values │ │ ├── strings.xml │ │ └── styles.xml ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle ├── app.json ├── babel.config.js ├── docs ├── .nojekyll ├── _coverpage.md ├── _navbar.md ├── en │ ├── README.md │ ├── V2 │ │ ├── BasicContent.md │ │ ├── BasicControl.md │ │ ├── CustomLoading.md │ │ ├── CustomRefresh.md │ │ ├── DetailControl.md │ │ ├── Event.md │ │ ├── GettingStart.md │ │ ├── KnownIssues.md │ │ ├── Loading.md │ │ ├── Refresh.md │ │ ├── Scroll.md │ │ ├── TextInput.md │ │ └── Usage.md │ ├── V3 │ │ ├── BasicContent.md │ │ ├── BasicControl.md │ │ ├── DetailControl.md │ │ ├── Event.md │ │ ├── GettingStart.md │ │ ├── KnownIssues.md │ │ ├── Loading.md │ │ ├── Refresh.md │ │ ├── Scroll.md │ │ ├── TextInput.md │ │ └── Usage.md │ └── _sidebar.md ├── index.html ├── res │ ├── LoadingBottoming.gif │ ├── LoadingStickyContent.gif │ ├── LoadingStickyScrollView.gif │ ├── LottieLoading.gif │ ├── LottieRefreshing.gif │ ├── RefreshingStickyContent.gif │ ├── RefreshingStickyScrollView.gif │ ├── RefreshingTopping.gif │ ├── android-test.gif │ └── loading.png └── zh-cn │ ├── README.md │ ├── V1 │ ├── BasicContent.md │ ├── BasicControl.md │ ├── CustomLoading.md │ ├── CustomRefresh.md │ ├── DetailControl.md │ ├── GettingStart.md │ ├── Loading.md │ ├── README.md │ ├── Refresh.md │ ├── Scroll.md │ ├── TextInput.md │ ├── Usage.md │ └── _sidebar.md │ ├── V2 │ ├── BasicContent.md │ ├── BasicControl.md │ ├── CustomLoading.md │ ├── CustomRefresh.md │ ├── DetailControl.md │ ├── Event.md │ ├── GettingStart.md │ ├── KnownIssues.md │ ├── Loading.md │ ├── Refresh.md │ ├── Scroll.md │ ├── TextInput.md │ └── Usage.md │ ├── V3 │ ├── BasicContent.md │ ├── BasicControl.md │ ├── DetailControl.md │ ├── Event.md │ ├── GettingStart.md │ ├── KnownIssues.md │ ├── Loading.md │ ├── Refresh.md │ ├── Scroll.md │ ├── TextInput.md │ └── Usage.md │ └── _sidebar.md ├── index.js ├── ios ├── Podfile ├── Podfile.lock ├── SSVExample-Bridging-Header.h ├── SSVExample.xcodeproj │ ├── project.pbxproj │ └── xcshareddata │ │ └── xcschemes │ │ └── SSVExample.xcscheme ├── SSVExample.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── SSVExample │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Empty.swift │ ├── Images.xcassets │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ ├── Info.plist │ ├── LaunchScreen.storyboard │ └── main.m ├── SSVExampleTests-Bridging-Header.h └── SSVExampleTests │ ├── Info.plist │ └── SSVExampleTests.m ├── metro.config.js ├── package.json └── src ├── .gitattributes ├── .npmignore ├── Customize ├── ChineseNormalFooter.js ├── ChineseNormalHeader.js ├── ChineseWithLastDateFooter.js ├── ChineseWithLastDateHeader.js ├── CommonLottieFooter.js ├── CommonLottieHeader.js ├── WithLastDateFooter.js ├── WithLastDateHeader.js ├── index.d.ts ├── index.js └── res │ ├── arrow@2x.png │ ├── loading.json │ ├── refreshing.json │ └── refreshing2.json ├── LoadingFooter.js ├── NormalFooter.js ├── NormalHeader.js ├── RNSpringScrollView.podspec ├── RefreshHeader.js ├── SpringScrollView.js ├── SpringScrollViewNative.js ├── Types.js ├── android ├── build.gradle ├── react-native-spring-scroll-view.iml └── src │ └── main │ ├── AndroidManifest.xml │ └── java │ └── com │ └── bolan9999 │ ├── DecelerateAnimation.java │ ├── ScrollEvent.java │ ├── SpringScrollView.java │ ├── SpringScrollViewManager.java │ ├── SpringScrollViewPackage.java │ └── Types.java ├── idx.js ├── index.d.ts ├── index.js ├── ios ├── RNSpringScrollView.xcodeproj │ └── project.pbxproj └── SpringScrollView │ ├── STSpringScrollContentViewManager.h │ ├── STSpringScrollContentViewManager.m │ ├── STSpringScrollView.h │ ├── STSpringScrollView.m │ ├── STSpringScrollViewManager.h │ └── STSpringScrollViewManager.m ├── package.json └── styles.js /.buckconfig: -------------------------------------------------------------------------------- 1 | 2 | [android] 3 | target = Google Inc.:Google APIs:23 4 | 5 | [maven_repositories] 6 | central = https://repo1.maven.org/maven2 7 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | extends: '@react-native-community', 4 | }; 5 | -------------------------------------------------------------------------------- /.flowconfig: -------------------------------------------------------------------------------- 1 | [ignore] 2 | ; We fork some components by platform 3 | .*/*[.]android.js 4 | 5 | ; Ignore "BUCK" generated dirs 6 | /\.buckd/ 7 | 8 | ; Ignore polyfills 9 | node_modules/react-native/Libraries/polyfills/.* 10 | 11 | ; These should not be required directly 12 | ; require from fbjs/lib instead: require('fbjs/lib/warning') 13 | node_modules/warning/.* 14 | 15 | ; Flow doesn't support platforms 16 | .*/Libraries/Utilities/LoadingView.js 17 | 18 | [untyped] 19 | .*/node_modules/@react-native-community/cli/.*/.* 20 | 21 | [include] 22 | 23 | [libs] 24 | node_modules/react-native/Libraries/react-native/react-native-interface.js 25 | node_modules/react-native/flow/ 26 | 27 | [options] 28 | emoji=true 29 | 30 | esproposal.optional_chaining=enable 31 | esproposal.nullish_coalescing=enable 32 | 33 | module.file_ext=.js 34 | module.file_ext=.json 35 | module.file_ext=.ios.js 36 | 37 | munge_underscores=true 38 | 39 | module.name_mapper='^react-native$' -> '/node_modules/react-native/Libraries/react-native/react-native-implementation' 40 | module.name_mapper='^react-native/\(.*\)$' -> '/node_modules/react-native/\1' 41 | module.name_mapper='^[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> '/node_modules/react-native/Libraries/Image/RelativeImageStub' 42 | 43 | suppress_type=$FlowIssue 44 | suppress_type=$FlowFixMe 45 | suppress_type=$FlowFixMeProps 46 | suppress_type=$FlowFixMeState 47 | 48 | suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(\\)? *\\(site=[a-z,_]*react_native\\(_ios\\)?_\\(oss\\|fb\\)[a-z,_]*\\)?)\\) 49 | suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(\\)? *\\(site=[a-z,_]*react_native\\(_ios\\)?_\\(oss\\|fb\\)[a-z,_]*\\)?)\\)?:? #[0-9]+ 50 | suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError 51 | 52 | [lints] 53 | sketchy-null-number=warn 54 | sketchy-null-mixed=warn 55 | sketchy-number=warn 56 | untyped-type-import=warn 57 | nonstrict-import=warn 58 | deprecated-type=warn 59 | unsafe-getters-setters=warn 60 | inexact-spread=warn 61 | unnecessary-invariant=warn 62 | signature-verification-failure=warn 63 | deprecated-utility=error 64 | 65 | [strict] 66 | deprecated-type 67 | nonstrict-import 68 | sketchy-null 69 | unclear-type 70 | unsafe-getters-setters 71 | untyped-import 72 | untyped-type-import 73 | 74 | [version] 75 | ^0.105.0 76 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.pbxproj -text 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | # 3 | .DS_Store 4 | 5 | # Xcode 6 | # 7 | build/ 8 | *.pbxuser 9 | !default.pbxuser 10 | *.mode1v3 11 | !default.mode1v3 12 | *.mode2v3 13 | !default.mode2v3 14 | *.perspectivev3 15 | !default.perspectivev3 16 | xcuserdata 17 | *.xccheckout 18 | *.moved-aside 19 | DerivedData 20 | *.hmap 21 | *.ipa 22 | *.xcuserstate 23 | 24 | # Android/IntelliJ 25 | # 26 | build/ 27 | .idea 28 | .gradle 29 | local.properties 30 | *.iml 31 | 32 | # node.js 33 | # 34 | node_modules/ 35 | npm-debug.log 36 | yarn-error.log 37 | yarn.lock 38 | 39 | # BUCK 40 | buck-out/ 41 | \.buckd/ 42 | *.keystore 43 | !debug.keystore 44 | 45 | # fastlane 46 | # 47 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 48 | # screenshots whenever they are needed. 49 | # For more information about the recommended setup visit: 50 | # https://docs.fastlane.tools/best-practices/source-control/ 51 | 52 | */fastlane/report.xml 53 | */fastlane/Preview.html 54 | */fastlane/screenshots 55 | 56 | # Bundle artifact 57 | *.jsbundle 58 | 59 | # CocoaPods 60 | /ios/Pods/ 61 | -------------------------------------------------------------------------------- /.prettierrc.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: 石破天惊 3 | * @email: shanshang130@gmail.com 4 | * @Date: 2020-11-05 10:44:46 5 | * @LastEditTime: 2021-07-22 20:00:20 6 | * @LastEditors: 石破天惊 7 | * @Description: 8 | */ 9 | module.exports = { 10 | bracketSpacing: false, 11 | jsxBracketSameLine: false, 12 | singleQuote: false, 13 | trailingComma: 'all' 14 | }; 15 | -------------------------------------------------------------------------------- /.watchmanconfig: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /App.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Sample React Native App 3 | * https://github.com/facebook/react-native 4 | * 5 | * @format 6 | * @flow strict-local 7 | */ 8 | 9 | import React from 'react'; 10 | import type {Node} from 'react'; 11 | import { 12 | SafeAreaView, 13 | ScrollView, 14 | StatusBar, 15 | StyleSheet, 16 | Text, 17 | useColorScheme, 18 | View, 19 | } from 'react-native'; 20 | 21 | import { 22 | Colors, 23 | DebugInstructions, 24 | Header, 25 | LearnMoreLinks, 26 | ReloadInstructions, 27 | } from 'react-native/Libraries/NewAppScreen'; 28 | 29 | const Section = ({children, title}): Node => { 30 | const isDarkMode = useColorScheme() === 'dark'; 31 | return ( 32 | 33 | 40 | {title} 41 | 42 | 49 | {children} 50 | 51 | 52 | ); 53 | }; 54 | 55 | const App: () => Node = () => { 56 | const isDarkMode = useColorScheme() === 'dark'; 57 | 58 | const backgroundStyle = { 59 | backgroundColor: isDarkMode ? Colors.darker : Colors.lighter, 60 | }; 61 | 62 | return ( 63 | 64 | 65 | 68 |
69 | 73 |
74 | Edit App.js to change this 75 | screen and then come back to see your edits. 76 |
77 |
78 | 79 |
80 |
81 | 82 |
83 |
84 | Read the docs to discover what to do next: 85 |
86 | 87 |
88 | 89 | 90 | ); 91 | }; 92 | 93 | const styles = StyleSheet.create({ 94 | sectionContainer: { 95 | marginTop: 32, 96 | paddingHorizontal: 24, 97 | }, 98 | sectionTitle: { 99 | fontSize: 24, 100 | fontWeight: '600', 101 | }, 102 | sectionDescription: { 103 | marginTop: 8, 104 | fontSize: 18, 105 | fontWeight: '400', 106 | }, 107 | highlight: { 108 | fontWeight: '700', 109 | }, 110 | }); 111 | 112 | export default App; 113 | -------------------------------------------------------------------------------- /Examples/BouncesAndScrollEnabledExample.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: 石破天惊 3 | * @email: shanshang130@gmail.com 4 | * @Date: 2021-07-21 13:05:32 5 | * @LastEditTime: 2021-09-18 10:39:36 6 | * @LastEditors: 石破天惊 7 | * @Description: 8 | */ 9 | /* 10 | * 11 | * Created by Stone 12 | * https://github.com/bolan9999 13 | * Email: shanshang130@gmail.com 14 | * Date: 2018/7/15 15 | * 16 | */ 17 | 18 | import React from 'react'; 19 | import {StyleSheet, Text, TouchableOpacity, View} from 'react-native'; 20 | import {SpringScrollView} from '../src'; 21 | 22 | export class BouncesAndScrollEnabledExample extends React.Component { 23 | state = { 24 | contentCount: 100, 25 | bounces: true, 26 | scrollEnabled: true, 27 | showsVerticalScrollIndicator: true, 28 | }; 29 | 30 | render() { 31 | const arr = []; 32 | for (let i = 0; i < this.state.contentCount; ++i) arr.push(i); 33 | return ( 34 | 39 | {arr.map((i, index) => ( 40 | { 43 | this.setState((p) => ({ 44 | contentCount: p.contentCount === 1 ? 100 : 1, 45 | })); 46 | }}> 47 | 48 | Modify the 'contentCount','bounces' and 'scrollEnabled' state in 49 | BouncesExample.js to check if VerticalScrollView works well. 50 | 51 | 52 | ))} 53 | 54 | ); 55 | } 56 | } 57 | 58 | const styles = StyleSheet.create({ 59 | text: { 60 | fontSize: 16, 61 | margin: 20, 62 | }, 63 | }); 64 | -------------------------------------------------------------------------------- /Examples/ComplexExample.js: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Created by Stone 4 | * https://github.com/bolan9999 5 | * Email: shanshang130@gmail.com 6 | * Date: 2018/7/4 7 | * 8 | */ 9 | 10 | import React from "react"; 11 | import { 12 | StyleSheet, 13 | Text, 14 | TouchableOpacity, 15 | Easing, 16 | TextInput, 17 | View 18 | } from "react-native"; 19 | import { SpringScrollView } from "../src"; 20 | import { NormalHeader } from "../src/NormalHeader"; 21 | import { NormalFooter } from "../src/NormalFooter"; 22 | 23 | export class ComplexExample extends React.Component { 24 | _refs; 25 | _scrollView; 26 | constructor(props) { 27 | super(props); 28 | this.state = { 29 | scrollEnabled: true, 30 | refreshing: false, 31 | loading: false, 32 | number: 8 33 | }; 34 | this._refs = []; 35 | for (let i = 0; i < this.state.number; ++i) { 36 | this._refs.push(React.createRef()); 37 | } 38 | } 39 | 40 | render() { 41 | return ( 42 | (this._scrollView = ref)} 45 | contentStyle={styles.content} 46 | showsVerticalScrollIndicator={false} 47 | bounces={true} 48 | scrollEnabled={this.state.scrollEnabled} 49 | textInputRefs={this._refs} 50 | inputToolBarHeight={20} 51 | refreshHeader={NormalHeader} 52 | onRefresh={() => { 53 | console.log("onRefresh"); 54 | setTimeout(() => this._scrollView.endRefresh(), 1000); 55 | }} 56 | loadingFooter={NormalFooter} 57 | loadingFooterHeight={80} 58 | onLoading={() => { 59 | console.log("onLoading"); 60 | setTimeout(() => this._scrollView.endLoading(true), 1000); 61 | }} 62 | > 63 | {this._renderContent()} 64 | 65 | ); 66 | } 67 | 68 | renderElement1(text, index) { 69 | return ( 70 | 76 | ); 77 | } 78 | 79 | renderElement(text) { 80 | return ( 81 | console.log("text")} 85 | > 86 | 87 | {text} 88 | 89 | 90 | 91 | ); 92 | } 93 | 94 | _renderContent() { 95 | const arr = []; 96 | for (let i = 0; i < this.state.number; ++i) arr.push(`Text${i}`); 97 | return arr.map(this.renderElement.bind(this)); 98 | } 99 | } 100 | 101 | const styles = StyleSheet.create({ 102 | container: { 103 | flex: 1 104 | // marginTop:20 105 | // overflow: "visible" 106 | }, 107 | content: { 108 | // alignItems: "stretch" 109 | // backgroundColor: "#EEE" 110 | }, 111 | btn: {}, 112 | text: { 113 | marginVertical: 20, 114 | fontSize: 20, 115 | textAlign: "center", 116 | alignSelf: "stretch" 117 | }, 118 | line: { 119 | height: 1, 120 | backgroundColor: "#EEE" 121 | } 122 | }); 123 | -------------------------------------------------------------------------------- /Examples/InputExample.js: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Created by Stone 4 | * https://github.com/bolan9999 5 | * Email: shanshang130@gmail.com 6 | * Date: 2018/7/14 7 | * 8 | */ 9 | 10 | import React from 'react'; 11 | import {SpringScrollView} from '../src'; 12 | import {TextInput, StyleSheet, Text, ScrollView, View} from 'react-native'; 13 | 14 | export class InputExample extends React.Component { 15 | _topInput = React.createRef(); 16 | _bottomInput = React.createRef(); 17 | 18 | render() { 19 | return ( 20 | 21 | 25 | 31 | 123123 32 | 33 | 39 | 40 | Keyboard will never cover the focused TextInput 41 | 42 | 47 | 48 | 49 | 50 | ); 51 | } 52 | } 53 | 54 | const styles = StyleSheet.create({ 55 | container: { 56 | flex: 1, 57 | }, 58 | input: { 59 | marginHorizontal: 20, 60 | marginVertical: 20, 61 | }, 62 | text: { 63 | marginHorizontal: 20, 64 | marginVertical: 300, 65 | fontSize: 30, 66 | }, 67 | }); 68 | -------------------------------------------------------------------------------- /Examples/RefreshAndLoadingExample.js: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Created by Stone 4 | * https://github.com/bolan9999 5 | * Email: shanshang130@gmail.com 6 | * Date: 2018/7/15 7 | * 8 | */ 9 | 10 | import React from 'react'; 11 | import {StyleSheet, Text, Platform, View, TouchableOpacity} from 'react-native'; 12 | import {SpringScrollView} from '../src'; 13 | import { 14 | ChineseNormalFooter, 15 | ChineseNormalHeader, 16 | ChineseWithLastDateHeader, 17 | WithLastDateHeader, 18 | WithLastDateFooter, 19 | ChineseWithLastDateFooter, 20 | } from '../src/Customize'; 21 | import {CommonLottieHeader} from '../src/Customize/CommonLottieHeader'; 22 | import {CommonLottieFooter} from '../src/Customize/CommonLottieFooter'; 23 | 24 | export class RefreshAndLoadingExample extends React.Component { 25 | _scrollView; 26 | _step = 33; 27 | 28 | constructor(props) { 29 | super(props); 30 | this.state = { 31 | count: this._step, 32 | allLoaded: false, 33 | }; 34 | } 35 | 36 | render() { 37 | const arr = []; 38 | for (let i = 0; i < this.state.count; ++i) arr.push(i); 39 | return ( 40 | (this._scrollView = ref)} 42 | style={styles.container} 43 | inverted 44 | onRefresh={this._onRefresh} 45 | onLoading={this._onLoading} 46 | // onScroll={()=>console.log("RefreshAndLoadingExample onScroll")} 47 | // allLoaded={this.state.allLoaded} 48 | refreshHeader={ChineseWithLastDateHeader} 49 | loadingFooter={ChineseWithLastDateFooter}> 50 | this._scrollView.beginRefresh()}> 53 | BeginRefresh 54 | 55 | {arr.map((item) => ( 56 | 57 | This is a Refresh and Loading Test{item} 58 | 59 | ))} 60 | 61 | ); 62 | } 63 | 64 | _onRefresh = () => { 65 | setTimeout(() => { 66 | this._scrollView.endRefresh(); 67 | this.setState({count: this._step, allLoaded: false}); 68 | }, 3000); 69 | }; 70 | 71 | _onLoading = () => { 72 | setTimeout(() => { 73 | this._scrollView.endLoading(); 74 | this.setState((p) => ({ 75 | count: p.count + this._step, 76 | allLoaded: false, 77 | })); 78 | }, 3000); 79 | }; 80 | } 81 | 82 | const styles = StyleSheet.create({ 83 | container: { 84 | flex: 1, 85 | marginTop: Platform.OS === 'ios' ? 20 : 0, 86 | }, 87 | text: { 88 | marginHorizontal: 50, 89 | paddingVertical: 20, 90 | fontSize: 16, 91 | textAlign: 'center', 92 | transform: [{scaleY: -1}], 93 | }, 94 | }); 95 | -------------------------------------------------------------------------------- /Examples/ScrollToAndOnScrollExample.js: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Created by Stone 4 | * https://github.com/bolan9999 5 | * Email: shanshang130@gmail.com 6 | * Date: 2018/7/22 7 | * 8 | */ 9 | 10 | import React from 'react'; 11 | import { 12 | StyleSheet, 13 | Text, 14 | TouchableOpacity, 15 | View, 16 | Platform, 17 | Animated, 18 | ScrollView, 19 | } from 'react-native'; 20 | import {SpringScrollView} from '../src'; 21 | 22 | const AnimatedSpringScrollView = Animated.createAnimatedComponent(SpringScrollView); 23 | export class ScrollToAndOnScrollExample extends React.Component { 24 | _contentCount = 20; 25 | _scrollView; 26 | _nativeOffset = { 27 | y: new Animated.Value(0), 28 | }; 29 | 30 | render() { 31 | const arr = []; 32 | for (let i = 0; i < this._contentCount; ++i) arr.push(i); 33 | return ( 34 | 35 | 36 | Tap to ScrollTo y=200 37 | 38 | (this._scrollView = ref)} 41 | onTouchBegin={this._onTouchBegin} 42 | onTouchEnd={this._onTouchEnd} 43 | onMomentumScrollBegin={this.onMomentumScrollBegin} 44 | onMomentumScrollEnd={this._onMomentumScrollEnd} 45 | onScrollBeginDrag={this._onScrollBeginDrag} 46 | onScrollEndDrag={this._onScrollEndDrag} 47 | onNativeContentOffsetExtract={this._nativeOffset} 48 | > 49 | {arr.map((i, index) => ( 50 | 51 | Scroll and Look up the console log to check if 52 | 'onScroll','onTouchBegin','onTouchEnd','onMomentumScrollBegin' and 53 | 'onMomentumScrollEnd' work well! 54 | 55 | ))} 56 | 57 | Test `onNativeContentOffsetExtract` 58 | 59 | 60 | 61 | ); 62 | } 63 | 64 | _stickyHeaderStyle = { 65 | position: 'absolute', 66 | top: 20, 67 | left: 0, 68 | right: 0, 69 | height: 40, 70 | justifyContent: 'center', 71 | alignItems: 'center', 72 | backgroundColor: 'red', 73 | transform: [{translateY: this._nativeOffset.y}], 74 | }; 75 | 76 | _scrollTo = () => { 77 | if (this._scrollView) { 78 | this._scrollView 79 | .scrollTo({x: 0, y: 200}) 80 | .then(() => console.log('ScrollTo has finished')); 81 | } 82 | }; 83 | 84 | _onTouchBegin = () => { 85 | console.log('onTouchBegin'); 86 | }; 87 | 88 | _onTouchEnd = () => { 89 | console.log('onTouchEnd'); 90 | }; 91 | 92 | onMomentumScrollBegin = () => { 93 | console.log('onMomentumScrollBegin'); 94 | }; 95 | _onMomentumScrollEnd = () => { 96 | console.log('onMomentumScrollEnd'); 97 | }; 98 | 99 | _onScrollBeginDrag = () => { 100 | console.log('onScrollBeginDrag'); 101 | }; 102 | 103 | _onScrollEndDrag = () => { 104 | console.log('onScrollEndDrag'); 105 | }; 106 | } 107 | 108 | const styles = StyleSheet.create({ 109 | container: { 110 | flex: 1, 111 | }, 112 | scrollTo: { 113 | marginTop: Platform.OS === 'ios' ? 20 : 0, 114 | backgroundColor: 'gray', 115 | zIndex: 100, 116 | height: 50, 117 | justifyContent: 'center', 118 | alignItems: 'center', 119 | }, 120 | text: { 121 | fontSize: 16, 122 | margin: 20, 123 | }, 124 | }); 125 | -------------------------------------------------------------------------------- /Examples/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Created by Stone 4 | * https://github.com/bolan9999 5 | * Email: shanshang130@gmail.com 6 | * Date: 2018/7/4 7 | * 8 | */ 9 | 10 | import React from "react"; 11 | import { Button, StyleSheet, View, SafeAreaView } from "react-native"; 12 | import { InputExample } from "./InputExample"; 13 | import { ComplexExample } from "./ComplexExample"; 14 | import { BouncesAndScrollEnabledExample } from "./BouncesAndScrollEnabledExample"; 15 | import { RefreshAndLoadingExample } from "./RefreshAndLoadingExample"; 16 | import { ScrollToAndOnScrollExample } from "./ScrollToAndOnScrollExample"; 17 | import {Test} from "./Test"; 18 | 19 | export class Examples extends React.Component { 20 | constructor(props) { 21 | super(props); 22 | this.state = { select: 0 }; 23 | } 24 | 25 | render(){ 26 | return 27 | {this._renderContent()} 28 | 29 | } 30 | 31 | _renderContent() { 32 | switch (this.state.select) { 33 | case 0: 34 | return this._renderSelect(); 35 | case 1: 36 | return ; 37 | case 2: 38 | return ; 39 | 40 | case 3: 41 | return ; 42 | case 4: 43 | return ; 44 | case 5: 45 | return ; 46 | } 47 | } 48 | 49 | _renderSelect() { 50 | return ( 51 | 52 |