├── testApp
├── app
│ ├── .gitignore
│ ├── src
│ │ ├── main
│ │ │ ├── res
│ │ │ │ ├── values
│ │ │ │ │ ├── strings.xml
│ │ │ │ │ ├── colors.xml
│ │ │ │ │ └── styles.xml
│ │ │ │ ├── drawable
│ │ │ │ │ ├── pulling.gif
│ │ │ │ │ ├── pullok.png
│ │ │ │ │ └── pullrelease.gif
│ │ │ │ ├── mipmap-mdpi
│ │ │ │ │ ├── pullok.png
│ │ │ │ │ ├── pulling.gif
│ │ │ │ │ ├── ic_launcher.png
│ │ │ │ │ ├── pullrelease.gif
│ │ │ │ │ └── ic_launcher_round.png
│ │ │ │ ├── drawable-v24
│ │ │ │ │ ├── pulling.gif
│ │ │ │ │ ├── pullok.png
│ │ │ │ │ ├── pullrelease.gif
│ │ │ │ │ └── ic_launcher_foreground.xml
│ │ │ │ ├── mipmap-hdpi
│ │ │ │ │ ├── ic_launcher.png
│ │ │ │ │ └── ic_launcher_round.png
│ │ │ │ ├── mipmap-xhdpi
│ │ │ │ │ ├── ic_launcher.png
│ │ │ │ │ ├── ic_launcher_round.png
│ │ │ │ │ ├── share_icon_moments.png
│ │ │ │ │ └── share_icon_wechat.png
│ │ │ │ ├── mipmap-xxhdpi
│ │ │ │ │ ├── ic_launcher.png
│ │ │ │ │ └── ic_launcher_round.png
│ │ │ │ ├── mipmap-xxxhdpi
│ │ │ │ │ ├── ic_launcher.png
│ │ │ │ │ └── ic_launcher_round.png
│ │ │ │ ├── mipmap-anydpi-v26
│ │ │ │ │ ├── ic_launcher.xml
│ │ │ │ │ └── ic_launcher_round.xml
│ │ │ │ ├── anim
│ │ │ │ │ ├── slide_in_right.xml
│ │ │ │ │ ├── slide_out_left.xml
│ │ │ │ │ ├── slide_out_right.xml
│ │ │ │ │ └── slide_in_left.xml
│ │ │ │ ├── layout
│ │ │ │ │ ├── fakestatus.xml
│ │ │ │ │ ├── activity_my_react.xml
│ │ │ │ │ ├── pull_layout.xml
│ │ │ │ │ ├── activity_other.xml
│ │ │ │ │ ├── activity_test.xml
│ │ │ │ │ ├── activity_main.xml
│ │ │ │ │ ├── header.xml
│ │ │ │ │ └── share.xml
│ │ │ │ └── values-v21
│ │ │ │ │ └── styles.xml
│ │ │ ├── java
│ │ │ │ └── com
│ │ │ │ │ └── example
│ │ │ │ │ └── wuyunqiang
│ │ │ │ │ └── testapp
│ │ │ │ │ ├── gesture
│ │ │ │ │ ├── RNGestureHandlerRootInterface.java
│ │ │ │ │ ├── RNGestureHandlerEventDataExtractor.java
│ │ │ │ │ ├── RNGestureHandlerRootView.java
│ │ │ │ │ ├── RNViewConfigurationHelper.java
│ │ │ │ │ ├── RNGestureHandlerEvent.java
│ │ │ │ │ ├── RNGestureHandlerEnabledRootView.java
│ │ │ │ │ ├── RNGestureHandlerStateChangeEvent.java
│ │ │ │ │ ├── RNGestureHandlerPackage.java
│ │ │ │ │ ├── RNGestureHandlerInteractionManager.java
│ │ │ │ │ └── RNGestureHandlerRegistry.java
│ │ │ │ │ ├── codepush
│ │ │ │ │ ├── CodePushInvalidUpdateException.java
│ │ │ │ │ ├── DownloadProgressCallback.java
│ │ │ │ │ ├── CodePushUnknownException.java
│ │ │ │ │ ├── CodePushUpdateState.java
│ │ │ │ │ ├── CodePushInvalidPublicKeyException.java
│ │ │ │ │ ├── CodePushNotInitializedException.java
│ │ │ │ │ ├── CodePushInstallMode.java
│ │ │ │ │ ├── CodePushMalformedDataException.java
│ │ │ │ │ ├── ReactInstanceHolder.java
│ │ │ │ │ ├── DownloadProgress.java
│ │ │ │ │ ├── Promiss.java
│ │ │ │ │ ├── CodePushBuilder.java
│ │ │ │ │ └── CodePushConstants.java
│ │ │ │ │ ├── gesturehandler
│ │ │ │ │ ├── GestureHandlerRegistry.java
│ │ │ │ │ ├── OnTouchEventListener.java
│ │ │ │ │ ├── ViewConfigurationHelper.java
│ │ │ │ │ ├── GestureHandlerInteractionController.java
│ │ │ │ │ ├── PointerEvents.java
│ │ │ │ │ ├── PointerEventsSpec.java
│ │ │ │ │ ├── PointerEventsConfig.java
│ │ │ │ │ ├── ViewConfigurationHelperImpl.java
│ │ │ │ │ ├── BaseGestureHandlerInteractionController.java
│ │ │ │ │ ├── GestureHandlerRegistryImpl.java
│ │ │ │ │ ├── GestureHandlerViewWrapper.java
│ │ │ │ │ ├── LongPressGestureHandler.java
│ │ │ │ │ ├── RotationGestureHandler.java
│ │ │ │ │ ├── TapGestureHandler.java
│ │ │ │ │ └── PinchGestureHandler.java
│ │ │ │ │ ├── fastimage
│ │ │ │ │ ├── FastImageGlideModule.java
│ │ │ │ │ ├── FastImageViewWithUrl.java
│ │ │ │ │ ├── FastImageProgressListener.java
│ │ │ │ │ ├── FastImageViewPackage.java
│ │ │ │ │ ├── FastImageViewModule.java
│ │ │ │ │ ├── FastImageViewConverter.java
│ │ │ │ │ └── FastImageRequestListener.java
│ │ │ │ │ ├── MyReactActivity.java
│ │ │ │ │ ├── activity
│ │ │ │ │ ├── OtherActivity.java
│ │ │ │ │ └── TestActivity.java
│ │ │ │ │ ├── RNFetchBlob
│ │ │ │ │ ├── RNFetchBlobConst.java
│ │ │ │ │ ├── RNFetchBlobPackage.java
│ │ │ │ │ ├── RNFetchBlobProgressConfig.java
│ │ │ │ │ ├── RNFetchBlobConfig.java
│ │ │ │ │ ├── Response
│ │ │ │ │ │ └── RNFetchBlobDefaultResp.java
│ │ │ │ │ └── RNFetchBlobUtils.java
│ │ │ │ │ ├── RNPackage.java
│ │ │ │ │ ├── view
│ │ │ │ │ ├── ModalHostShadowNode.java
│ │ │ │ │ └── ModalHostHelper.java
│ │ │ │ │ ├── preloadreact
│ │ │ │ │ ├── ReactNativePreLoader.java
│ │ │ │ │ └── PreLoadReactActivity.java
│ │ │ │ │ └── MainApplication.java
│ │ │ └── AndroidManifest.xml
│ │ ├── test
│ │ │ └── java
│ │ │ │ └── com
│ │ │ │ └── example
│ │ │ │ └── wuyunqiang
│ │ │ │ └── testapp
│ │ │ │ └── ExampleUnitTest.java
│ │ └── androidTest
│ │ │ └── java
│ │ │ └── com
│ │ │ └── example
│ │ │ └── wuyunqiang
│ │ │ └── testapp
│ │ │ └── ExampleInstrumentedTest.java
│ ├── libs
│ │ └── nimbus-jose-jwt-5.1.jar
│ ├── proguard-rules.pro
│ └── build.gradle
├── settings.gradle
├── RN_src
│ ├── assets
│ │ ├── home
│ │ │ ├── back.png
│ │ │ ├── back@2x.png
│ │ │ ├── back@3x.png
│ │ │ ├── share_icon_moments.png
│ │ │ ├── share_icon_wechat.png
│ │ │ └── backgroundImageHeader.png
│ │ ├── list
│ │ │ ├── nodata.png
│ │ │ ├── nodata@2x.png
│ │ │ ├── nodata@3x.png
│ │ │ ├── nonetwork.png
│ │ │ ├── nonetwork@2x.png
│ │ │ └── nonetwork@3x.png
│ │ ├── tab
│ │ │ ├── home_active.png
│ │ │ ├── home_active@2x.png
│ │ │ ├── home_active@3x.png
│ │ │ ├── home_unactive.png
│ │ │ ├── profile_active.png
│ │ │ ├── project_active.png
│ │ │ ├── home_unactive@2x.png
│ │ │ ├── home_unactive@3x.png
│ │ │ ├── profile_active@2x.png
│ │ │ ├── profile_active@3x.png
│ │ │ ├── profile_unactive.png
│ │ │ ├── project_active@2x.png
│ │ │ ├── project_active@3x.png
│ │ │ ├── project_unactive.png
│ │ │ ├── xindaiicon_active.png
│ │ │ ├── profile_unactive@2x.png
│ │ │ ├── profile_unactive@3x.png
│ │ │ ├── project_unactive@2x.png
│ │ │ ├── project_unactive@3x.png
│ │ │ ├── xindaiicon_active@2x.png
│ │ │ ├── xindaiicon_active@3x.png
│ │ │ ├── xindaiicon_unactive.png
│ │ │ ├── xindaiicon_unactive@2x.png
│ │ │ └── xindaiicon_unactive@3x.png
│ │ └── index.js
│ ├── data
│ │ ├── icons
│ │ │ ├── icon5.png
│ │ │ ├── icon10@2x.png
│ │ │ ├── icon10@3x.png
│ │ │ ├── icon1@2x.png
│ │ │ ├── icon1@3x.png
│ │ │ ├── icon2@2x.png
│ │ │ ├── icon2@3x.png
│ │ │ ├── icon3@2x.png
│ │ │ ├── icon3@3x.png
│ │ │ ├── icon4@2x.png
│ │ │ ├── icon4@3x.png
│ │ │ ├── icon6@2x.png
│ │ │ ├── icon6@3x.png
│ │ │ ├── icon7@2x.png
│ │ │ ├── icon7@3x.png
│ │ │ ├── icon8@2x.png
│ │ │ ├── icon8@3x.png
│ │ │ ├── icon9@2x.png
│ │ │ ├── icon9@3x.png
│ │ │ └── index.js
│ │ └── common.js
│ ├── actions
│ │ ├── ActionTypes.js
│ │ └── home.js
│ ├── pull
│ │ ├── i18n
│ │ │ ├── All.js
│ │ │ └── index.js
│ │ ├── style
│ │ │ └── index.js
│ │ ├── PullLayout.js
│ │ ├── LoadingSpinner.js
│ │ └── PullView.js
│ ├── utils
│ │ ├── NavigationReduxUtil.js
│ │ ├── StyleColor.js
│ │ └── index.js
│ ├── sagas
│ │ ├── index.js
│ │ └── home.js
│ ├── list
│ │ └── SGList
│ │ │ ├── Card.js
│ │ │ ├── CardListView.js
│ │ │ ├── CardListController.js
│ │ │ └── CardListDataSource.js
│ ├── reducers
│ │ ├── index.js
│ │ ├── navigator.js
│ │ └── home.js
│ ├── component
│ │ ├── modol.js
│ │ └── Tab.js
│ ├── page
│ │ ├── GesturePage.js
│ │ ├── TestActivity.js
│ │ └── Pull.js
│ ├── store
│ │ └── configure-store.js
│ ├── root.js
│ └── gesture
│ │ ├── PressBox.js
│ │ ├── draggable.js
│ │ └── TapOrPan.js
├── gradle
│ └── wrapper
│ │ ├── gradle-wrapper.jar
│ │ └── gradle-wrapper.properties
├── .gitignore
├── .idea
│ ├── encodings.xml
│ ├── modules.xml
│ ├── runConfigurations.xml
│ ├── gradle.xml
│ └── misc.xml
├── index.js
├── gradle.properties
├── build.gradle
├── package.json
└── gradlew.bat
└── README.md
/testApp/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/testApp/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------
/testApp/RN_src/assets/home/back.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/RN_src/assets/home/back.png
--------------------------------------------------------------------------------
/testApp/RN_src/data/icons/icon5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/RN_src/data/icons/icon5.png
--------------------------------------------------------------------------------
/testApp/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | TestApp
3 |
4 |
--------------------------------------------------------------------------------
/testApp/RN_src/assets/list/nodata.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/RN_src/assets/list/nodata.png
--------------------------------------------------------------------------------
/testApp/RN_src/assets/home/back@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/RN_src/assets/home/back@2x.png
--------------------------------------------------------------------------------
/testApp/RN_src/assets/home/back@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/RN_src/assets/home/back@3x.png
--------------------------------------------------------------------------------
/testApp/RN_src/assets/list/nodata@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/RN_src/assets/list/nodata@2x.png
--------------------------------------------------------------------------------
/testApp/RN_src/assets/list/nodata@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/RN_src/assets/list/nodata@3x.png
--------------------------------------------------------------------------------
/testApp/RN_src/assets/list/nonetwork.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/RN_src/assets/list/nonetwork.png
--------------------------------------------------------------------------------
/testApp/RN_src/data/icons/icon10@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/RN_src/data/icons/icon10@2x.png
--------------------------------------------------------------------------------
/testApp/RN_src/data/icons/icon10@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/RN_src/data/icons/icon10@3x.png
--------------------------------------------------------------------------------
/testApp/RN_src/data/icons/icon1@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/RN_src/data/icons/icon1@2x.png
--------------------------------------------------------------------------------
/testApp/RN_src/data/icons/icon1@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/RN_src/data/icons/icon1@3x.png
--------------------------------------------------------------------------------
/testApp/RN_src/data/icons/icon2@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/RN_src/data/icons/icon2@2x.png
--------------------------------------------------------------------------------
/testApp/RN_src/data/icons/icon2@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/RN_src/data/icons/icon2@3x.png
--------------------------------------------------------------------------------
/testApp/RN_src/data/icons/icon3@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/RN_src/data/icons/icon3@2x.png
--------------------------------------------------------------------------------
/testApp/RN_src/data/icons/icon3@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/RN_src/data/icons/icon3@3x.png
--------------------------------------------------------------------------------
/testApp/RN_src/data/icons/icon4@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/RN_src/data/icons/icon4@2x.png
--------------------------------------------------------------------------------
/testApp/RN_src/data/icons/icon4@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/RN_src/data/icons/icon4@3x.png
--------------------------------------------------------------------------------
/testApp/RN_src/data/icons/icon6@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/RN_src/data/icons/icon6@2x.png
--------------------------------------------------------------------------------
/testApp/RN_src/data/icons/icon6@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/RN_src/data/icons/icon6@3x.png
--------------------------------------------------------------------------------
/testApp/RN_src/data/icons/icon7@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/RN_src/data/icons/icon7@2x.png
--------------------------------------------------------------------------------
/testApp/RN_src/data/icons/icon7@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/RN_src/data/icons/icon7@3x.png
--------------------------------------------------------------------------------
/testApp/RN_src/data/icons/icon8@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/RN_src/data/icons/icon8@2x.png
--------------------------------------------------------------------------------
/testApp/RN_src/data/icons/icon8@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/RN_src/data/icons/icon8@3x.png
--------------------------------------------------------------------------------
/testApp/RN_src/data/icons/icon9@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/RN_src/data/icons/icon9@2x.png
--------------------------------------------------------------------------------
/testApp/RN_src/data/icons/icon9@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/RN_src/data/icons/icon9@3x.png
--------------------------------------------------------------------------------
/testApp/app/libs/nimbus-jose-jwt-5.1.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/app/libs/nimbus-jose-jwt-5.1.jar
--------------------------------------------------------------------------------
/testApp/RN_src/assets/tab/home_active.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/RN_src/assets/tab/home_active.png
--------------------------------------------------------------------------------
/testApp/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/testApp/RN_src/assets/list/nonetwork@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/RN_src/assets/list/nonetwork@2x.png
--------------------------------------------------------------------------------
/testApp/RN_src/assets/list/nonetwork@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/RN_src/assets/list/nonetwork@3x.png
--------------------------------------------------------------------------------
/testApp/RN_src/assets/tab/home_active@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/RN_src/assets/tab/home_active@2x.png
--------------------------------------------------------------------------------
/testApp/RN_src/assets/tab/home_active@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/RN_src/assets/tab/home_active@3x.png
--------------------------------------------------------------------------------
/testApp/RN_src/assets/tab/home_unactive.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/RN_src/assets/tab/home_unactive.png
--------------------------------------------------------------------------------
/testApp/RN_src/assets/tab/profile_active.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/RN_src/assets/tab/profile_active.png
--------------------------------------------------------------------------------
/testApp/RN_src/assets/tab/project_active.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/RN_src/assets/tab/project_active.png
--------------------------------------------------------------------------------
/testApp/app/src/main/res/drawable/pulling.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/app/src/main/res/drawable/pulling.gif
--------------------------------------------------------------------------------
/testApp/app/src/main/res/drawable/pullok.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/app/src/main/res/drawable/pullok.png
--------------------------------------------------------------------------------
/testApp/RN_src/assets/tab/home_unactive@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/RN_src/assets/tab/home_unactive@2x.png
--------------------------------------------------------------------------------
/testApp/RN_src/assets/tab/home_unactive@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/RN_src/assets/tab/home_unactive@3x.png
--------------------------------------------------------------------------------
/testApp/RN_src/assets/tab/profile_active@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/RN_src/assets/tab/profile_active@2x.png
--------------------------------------------------------------------------------
/testApp/RN_src/assets/tab/profile_active@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/RN_src/assets/tab/profile_active@3x.png
--------------------------------------------------------------------------------
/testApp/RN_src/assets/tab/profile_unactive.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/RN_src/assets/tab/profile_unactive.png
--------------------------------------------------------------------------------
/testApp/RN_src/assets/tab/project_active@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/RN_src/assets/tab/project_active@2x.png
--------------------------------------------------------------------------------
/testApp/RN_src/assets/tab/project_active@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/RN_src/assets/tab/project_active@3x.png
--------------------------------------------------------------------------------
/testApp/RN_src/assets/tab/project_unactive.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/RN_src/assets/tab/project_unactive.png
--------------------------------------------------------------------------------
/testApp/RN_src/assets/tab/xindaiicon_active.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/RN_src/assets/tab/xindaiicon_active.png
--------------------------------------------------------------------------------
/testApp/app/src/main/res/mipmap-mdpi/pullok.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/app/src/main/res/mipmap-mdpi/pullok.png
--------------------------------------------------------------------------------
/testApp/RN_src/assets/home/share_icon_moments.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/RN_src/assets/home/share_icon_moments.png
--------------------------------------------------------------------------------
/testApp/RN_src/assets/home/share_icon_wechat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/RN_src/assets/home/share_icon_wechat.png
--------------------------------------------------------------------------------
/testApp/RN_src/assets/tab/profile_unactive@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/RN_src/assets/tab/profile_unactive@2x.png
--------------------------------------------------------------------------------
/testApp/RN_src/assets/tab/profile_unactive@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/RN_src/assets/tab/profile_unactive@3x.png
--------------------------------------------------------------------------------
/testApp/RN_src/assets/tab/project_unactive@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/RN_src/assets/tab/project_unactive@2x.png
--------------------------------------------------------------------------------
/testApp/RN_src/assets/tab/project_unactive@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/RN_src/assets/tab/project_unactive@3x.png
--------------------------------------------------------------------------------
/testApp/RN_src/assets/tab/xindaiicon_active@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/RN_src/assets/tab/xindaiicon_active@2x.png
--------------------------------------------------------------------------------
/testApp/RN_src/assets/tab/xindaiicon_active@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/RN_src/assets/tab/xindaiicon_active@3x.png
--------------------------------------------------------------------------------
/testApp/RN_src/assets/tab/xindaiicon_unactive.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/RN_src/assets/tab/xindaiicon_unactive.png
--------------------------------------------------------------------------------
/testApp/app/src/main/res/drawable-v24/pulling.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/app/src/main/res/drawable-v24/pulling.gif
--------------------------------------------------------------------------------
/testApp/app/src/main/res/drawable-v24/pullok.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/app/src/main/res/drawable-v24/pullok.png
--------------------------------------------------------------------------------
/testApp/app/src/main/res/drawable/pullrelease.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/app/src/main/res/drawable/pullrelease.gif
--------------------------------------------------------------------------------
/testApp/app/src/main/res/mipmap-mdpi/pulling.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/app/src/main/res/mipmap-mdpi/pulling.gif
--------------------------------------------------------------------------------
/testApp/RN_src/assets/home/backgroundImageHeader.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/RN_src/assets/home/backgroundImageHeader.png
--------------------------------------------------------------------------------
/testApp/RN_src/assets/tab/xindaiicon_unactive@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/RN_src/assets/tab/xindaiicon_unactive@2x.png
--------------------------------------------------------------------------------
/testApp/RN_src/assets/tab/xindaiicon_unactive@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/RN_src/assets/tab/xindaiicon_unactive@3x.png
--------------------------------------------------------------------------------
/testApp/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/testApp/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/testApp/app/src/main/res/mipmap-mdpi/pullrelease.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/app/src/main/res/mipmap-mdpi/pullrelease.gif
--------------------------------------------------------------------------------
/testApp/app/src/main/res/drawable-v24/pullrelease.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/app/src/main/res/drawable-v24/pullrelease.gif
--------------------------------------------------------------------------------
/testApp/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/testApp/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/testApp/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/testApp/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/testApp/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/testApp/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/testApp/app/src/main/res/mipmap-xhdpi/share_icon_moments.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/app/src/main/res/mipmap-xhdpi/share_icon_moments.png
--------------------------------------------------------------------------------
/testApp/app/src/main/res/mipmap-xhdpi/share_icon_wechat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/app/src/main/res/mipmap-xhdpi/share_icon_wechat.png
--------------------------------------------------------------------------------
/testApp/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/testApp/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/workspace.xml
5 | /.idea/libraries
6 | .DS_Store
7 | /build
8 | /captures
9 | .externalNativeBuild
10 |
--------------------------------------------------------------------------------
/testApp/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wuyunqiang/AndroidToRN/HEAD/testApp/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/testApp/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/testApp/RN_src/actions/ActionTypes.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by wuyunqiang on 2018/01/24.
3 | */
4 |
5 | export default class ActionTypes{
6 | static REQUEST = 'REQUEST';
7 | static FETCH = 'FETCH';
8 | static RECEIVE = 'RECEIVE';
9 | }
10 |
11 | global.ActionTypes = ActionTypes;
--------------------------------------------------------------------------------
/testApp/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Fri Dec 01 10:38:58 CST 2017
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip
7 |
--------------------------------------------------------------------------------
/testApp/app/src/main/java/com/example/wuyunqiang/testapp/gesture/RNGestureHandlerRootInterface.java:
--------------------------------------------------------------------------------
1 | package com.example.wuyunqiang.testapp.gesture;
2 |
3 | import javax.annotation.Nullable;
4 |
5 | public interface RNGestureHandlerRootInterface {
6 | @Nullable
7 | RNGestureHandlerRootHelper getRootHelper();
8 | }
9 |
--------------------------------------------------------------------------------
/testApp/app/src/main/java/com/example/wuyunqiang/testapp/codepush/CodePushInvalidUpdateException.java:
--------------------------------------------------------------------------------
1 | package com.example.wuyunqiang.testapp.codepush;
2 |
3 | public class CodePushInvalidUpdateException extends RuntimeException {
4 | public CodePushInvalidUpdateException(String message) {
5 | super(message);
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/testApp/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/testApp/app/src/main/java/com/example/wuyunqiang/testapp/codepush/DownloadProgressCallback.java:
--------------------------------------------------------------------------------
1 | package com.example.wuyunqiang.testapp.codepush;
2 |
3 | import com.example.wuyunqiang.testapp.codepush.*;
4 |
5 | interface DownloadProgressCallback {
6 | void call(com.example.wuyunqiang.testapp.codepush.DownloadProgress downloadProgress);
7 | }
8 |
--------------------------------------------------------------------------------
/testApp/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/testApp/RN_src/pull/i18n/All.js:
--------------------------------------------------------------------------------
1 | export default {
2 | "": {
3 | pulling: "pulling...",
4 | pullok: "pull ok......",
5 | pullrelease: "refreshing......"
6 | },
7 | "zh_CN": {
8 | pulling: "下拉刷新...",
9 | pullok: "松开刷新......",
10 | pullrelease: "玩命刷新中......"
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/testApp/app/src/main/java/com/example/wuyunqiang/testapp/gesturehandler/GestureHandlerRegistry.java:
--------------------------------------------------------------------------------
1 | package com.example.wuyunqiang.testapp.gesturehandler;
2 |
3 | import android.view.View;
4 |
5 | import java.util.ArrayList;
6 |
7 | public interface GestureHandlerRegistry {
8 | ArrayList getHandlersForView(View view);
9 | }
10 |
--------------------------------------------------------------------------------
/testApp/app/src/main/res/anim/slide_in_right.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
9 |
--------------------------------------------------------------------------------
/testApp/app/src/main/res/anim/slide_out_left.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
9 |
--------------------------------------------------------------------------------
/testApp/app/src/main/res/anim/slide_out_right.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
9 |
--------------------------------------------------------------------------------
/testApp/app/src/main/res/anim/slide_in_left.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
9 |
10 |
--------------------------------------------------------------------------------
/testApp/app/src/main/java/com/example/wuyunqiang/testapp/gesturehandler/OnTouchEventListener.java:
--------------------------------------------------------------------------------
1 | package com.example.wuyunqiang.testapp.gesturehandler;
2 |
3 | import android.view.MotionEvent;
4 |
5 | public interface OnTouchEventListener {
6 | void onTouchEvent(T handler, MotionEvent event);
7 | void onStateChange(T handler, int newState, int oldState);
8 | }
9 |
--------------------------------------------------------------------------------
/testApp/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/testApp/app/src/main/java/com/example/wuyunqiang/testapp/gesturehandler/ViewConfigurationHelper.java:
--------------------------------------------------------------------------------
1 | package com.example.wuyunqiang.testapp.gesturehandler;
2 |
3 | import android.view.View;
4 | import android.view.ViewGroup;
5 |
6 | public interface ViewConfigurationHelper {
7 | PointerEventsConfig getPointerEventsConfigForView(View view);
8 | View getChildInDrawingOrderAtIndex(ViewGroup parent, int index);
9 | }
10 |
--------------------------------------------------------------------------------
/testApp/app/src/main/java/com/example/wuyunqiang/testapp/fastimage/FastImageGlideModule.java:
--------------------------------------------------------------------------------
1 | package com.example.wuyunqiang.testapp.fastimage;
2 |
3 | import com.bumptech.glide.annotation.GlideModule;
4 | import com.bumptech.glide.module.AppGlideModule;
5 |
6 | // We need an AppGlideModule to be present for progress events to work.
7 | @GlideModule
8 | public final class FastImageGlideModule extends AppGlideModule {
9 | }
10 |
--------------------------------------------------------------------------------
/testApp/app/src/main/java/com/example/wuyunqiang/testapp/gesture/RNGestureHandlerEventDataExtractor.java:
--------------------------------------------------------------------------------
1 | package com.example.wuyunqiang.testapp.gesture;
2 |
3 | import com.example.wuyunqiang.testapp.gesturehandler.GestureHandler;
4 | import com.facebook.react.bridge.WritableMap;
5 |
6 | public interface RNGestureHandlerEventDataExtractor {
7 | void extractEventData(T handler, WritableMap eventData);
8 | }
9 |
--------------------------------------------------------------------------------
/testApp/RN_src/utils/NavigationReduxUtil.js:
--------------------------------------------------------------------------------
1 |
2 | import {
3 | createReactNavigationReduxMiddleware,
4 | createReduxBoundAddListener,
5 | } from 'react-navigation-redux-helpers';
6 |
7 | const middleware = createReactNavigationReduxMiddleware(
8 | "root",
9 | state => state.nav,
10 | );
11 | const addListener = createReduxBoundAddListener("root");
12 |
13 | export {
14 | middleware,
15 | addListener,
16 | };
--------------------------------------------------------------------------------
/testApp/app/src/main/java/com/example/wuyunqiang/testapp/codepush/CodePushUnknownException.java:
--------------------------------------------------------------------------------
1 | package com.example.wuyunqiang.testapp.codepush;
2 |
3 | class CodePushUnknownException extends RuntimeException {
4 |
5 | public CodePushUnknownException(String message, Throwable cause) {
6 | super(message, cause);
7 | }
8 |
9 | public CodePushUnknownException(String message) {
10 | super(message);
11 | }
12 | }
--------------------------------------------------------------------------------
/testApp/app/src/main/java/com/example/wuyunqiang/testapp/codepush/CodePushUpdateState.java:
--------------------------------------------------------------------------------
1 | package com.example.wuyunqiang.testapp.codepush;
2 |
3 | public enum CodePushUpdateState {
4 | RUNNING(0),
5 | PENDING(1),
6 | LATEST(2);
7 |
8 | private final int value;
9 | CodePushUpdateState(int value) {
10 | this.value = value;
11 | }
12 | public int getValue() {
13 | return this.value;
14 | }
15 | }
--------------------------------------------------------------------------------
/testApp/app/src/main/res/layout/fakestatus.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/testApp/app/src/main/java/com/example/wuyunqiang/testapp/fastimage/FastImageViewWithUrl.java:
--------------------------------------------------------------------------------
1 | package com.example.wuyunqiang.testapp.fastimage;
2 | import android.content.Context;
3 | import android.widget.ImageView;
4 |
5 | import com.bumptech.glide.load.model.GlideUrl;
6 |
7 | class FastImageViewWithUrl extends ImageView {
8 | public GlideUrl glideUrl;
9 |
10 | public FastImageViewWithUrl(Context context) {
11 | super(context);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/testApp/app/src/main/java/com/example/wuyunqiang/testapp/codepush/CodePushInvalidPublicKeyException.java:
--------------------------------------------------------------------------------
1 | package com.example.wuyunqiang.testapp.codepush;
2 |
3 | class CodePushInvalidPublicKeyException extends RuntimeException {
4 |
5 | public CodePushInvalidPublicKeyException(String message, Throwable cause) {
6 | super(message, cause);
7 | }
8 |
9 | public CodePushInvalidPublicKeyException(String message) {
10 | super(message);
11 | }
12 | }
--------------------------------------------------------------------------------
/testApp/app/src/main/java/com/example/wuyunqiang/testapp/codepush/CodePushNotInitializedException.java:
--------------------------------------------------------------------------------
1 | package com.example.wuyunqiang.testapp.codepush;
2 |
3 | public final class CodePushNotInitializedException extends RuntimeException {
4 |
5 | public CodePushNotInitializedException(String message, Throwable cause) {
6 | super(message, cause);
7 | }
8 |
9 | public CodePushNotInitializedException(String message) {
10 | super(message);
11 | }
12 | }
--------------------------------------------------------------------------------
/testApp/app/src/main/java/com/example/wuyunqiang/testapp/codepush/CodePushInstallMode.java:
--------------------------------------------------------------------------------
1 | package com.example.wuyunqiang.testapp.codepush;
2 |
3 | public enum CodePushInstallMode {
4 | IMMEDIATE(0),
5 | ON_NEXT_RESTART(1),
6 | ON_NEXT_RESUME(2),
7 | ON_NEXT_SUSPEND(3);
8 |
9 | private final int value;
10 | CodePushInstallMode(int value) {
11 | this.value = value;
12 | }
13 | public int getValue() {
14 | return this.value;
15 | }
16 | }
--------------------------------------------------------------------------------
/testApp/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #FF4081
4 | #80000000
5 | #FF4081
6 | #E9967A
7 | #FCFCFC
8 | #80080808
9 | #F0F0F0
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/testApp/RN_src/pull/style/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | import {
4 | StyleSheet
5 | } from 'react-native';
6 |
7 | export default StyleSheet.create({
8 | wrap: {
9 | flex: 1,
10 | flexGrow: 1,
11 | flexDirection: 'column',
12 | zIndex:-999,
13 | },
14 | hide: {
15 | position: 'absolute',
16 | left: 10000
17 | },
18 | show: {
19 | position: 'relative',
20 | left: 0
21 | }
22 | });
23 |
--------------------------------------------------------------------------------
/testApp/app/src/main/res/layout/activity_my_react.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/testApp/app/src/test/java/com/example/wuyunqiang/testapp/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.example.wuyunqiang.testapp;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() throws Exception {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/testApp/app/src/main/java/com/example/wuyunqiang/testapp/MyReactActivity.java:
--------------------------------------------------------------------------------
1 | package com.example.wuyunqiang.testapp;
2 |
3 | import com.example.wuyunqiang.testapp.preloadreact.PreLoadReactActivity;
4 | import com.facebook.react.ReactActivityDelegate;
5 | import com.facebook.react.ReactRootView;
6 |
7 | import javax.annotation.Nullable;
8 |
9 | public class MyReactActivity extends PreLoadReactActivity {
10 |
11 | @Nullable
12 | @Override
13 | protected String getMainComponentName() {
14 | return "RNActivity";
15 | }
16 |
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/testApp/app/src/main/java/com/example/wuyunqiang/testapp/fastimage/FastImageProgressListener.java:
--------------------------------------------------------------------------------
1 | package com.example.wuyunqiang.testapp.fastimage;
2 | public interface FastImageProgressListener {
3 |
4 | void onProgress(String key, long bytesRead, long expectedLength);
5 |
6 | /**
7 | * Control how often the listener needs an update. 0% and 100% will always be dispatched.
8 | *
9 | * @return in percentage (0.2 = call {@link #onProgress} around every 0.2 percent of progress)
10 | */
11 | float getGranularityPercentage();
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/testApp/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Sample React Native App
3 | * https://github.com/facebook/react-native
4 | * @flow
5 | */
6 |
7 | import React, {Component} from 'react';
8 | import {
9 | AppRegistry,
10 | Platform,
11 | StyleSheet,
12 | Text,
13 | View,
14 | DeviceEventEmitter
15 | } from 'react-native';
16 | import './RN_src/utils'
17 | import './RN_src/assets'
18 | import Root from './RN_src/root'
19 | import Test from './RN_src/page/TestActivity'
20 | AppRegistry.registerComponent('RNActivity', () => Root);
21 |
22 | AppRegistry.registerComponent('TestActivity', () => Test);
--------------------------------------------------------------------------------
/testApp/app/src/main/java/com/example/wuyunqiang/testapp/gesturehandler/GestureHandlerInteractionController.java:
--------------------------------------------------------------------------------
1 | package com.example.wuyunqiang.testapp.gesturehandler;
2 |
3 | public interface GestureHandlerInteractionController {
4 | boolean shouldWaitForHandlerFailure(GestureHandler handler, GestureHandler otherHandler);
5 | boolean shouldRequireHandlerToWaitForFailure(GestureHandler handler, GestureHandler otherHandler);
6 | boolean shouldRecognizeSimultaneously(GestureHandler handler, GestureHandler otherHandler);
7 | boolean shouldHandlerBeCancelledBy(GestureHandler handler, GestureHandler otherHandler);
8 | }
9 |
--------------------------------------------------------------------------------
/testApp/.idea/runConfigurations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 |
12 |
--------------------------------------------------------------------------------
/testApp/app/src/main/java/com/example/wuyunqiang/testapp/codepush/CodePushMalformedDataException.java:
--------------------------------------------------------------------------------
1 | package com.example.wuyunqiang.testapp.codepush;
2 |
3 | import java.net.MalformedURLException;
4 |
5 | public class CodePushMalformedDataException extends RuntimeException {
6 | public CodePushMalformedDataException(String path, Throwable cause) {
7 | super("Unable to parse contents of " + path + ", the file may be corrupted.", cause);
8 | }
9 | public CodePushMalformedDataException(String url, MalformedURLException cause) {
10 | super("The package has an invalid downloadUrl: " + url, cause);
11 | }
12 | }
--------------------------------------------------------------------------------
/testApp/app/src/main/res/values-v21/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
12 |
--------------------------------------------------------------------------------
/testApp/app/src/main/java/com/example/wuyunqiang/testapp/codepush/ReactInstanceHolder.java:
--------------------------------------------------------------------------------
1 | package com.example.wuyunqiang.testapp.codepush;
2 |
3 | import com.facebook.react.ReactInstanceManager;
4 |
5 | /**
6 | * Provides access to a {@link ReactInstanceManager}.
7 | *
8 | * ReactNativeHost already implements this interface, if you make use of that react-native
9 | * component (just add `implements ReactInstanceHolder`).
10 | */
11 | public interface ReactInstanceHolder {
12 |
13 | /**
14 | * Get the current {@link ReactInstanceManager} instance. May return null.
15 | */
16 | ReactInstanceManager getReactInstanceManager();
17 | }
18 |
--------------------------------------------------------------------------------
/testApp/app/src/main/java/com/example/wuyunqiang/testapp/gesturehandler/PointerEvents.java:
--------------------------------------------------------------------------------
1 | package com.example.wuyunqiang.testapp.gesturehandler;
2 |
3 | public enum PointerEvents {
4 |
5 | /**
6 | * Neither the container nor its children receive events.
7 | */
8 | NONE,
9 |
10 | /**
11 | * Container doesn't get events but all of its children do.
12 | */
13 | BOX_NONE,
14 |
15 | /**
16 | * Container gets events but none of its children do.
17 | */
18 | BOX_ONLY,
19 |
20 | /**
21 | * Container and all of its children receive touch events (like pointerEvents is unspecified).
22 | */
23 | AUTO,
24 | ;
25 | }
26 |
--------------------------------------------------------------------------------
/testApp/app/src/main/java/com/example/wuyunqiang/testapp/gesturehandler/PointerEventsSpec.java:
--------------------------------------------------------------------------------
1 | package com.example.wuyunqiang.testapp.gesturehandler;
2 |
3 | public enum PointerEventsSpec {
4 |
5 | /**
6 | * Neither the container nor its children receive events.
7 | */
8 | NONE,
9 |
10 | /**
11 | * Container doesn't get events but all of its children do.
12 | */
13 | BOX_NONE,
14 |
15 | /**
16 | * Container gets events but none of its children do.
17 | */
18 | BOX_ONLY,
19 |
20 | /**
21 | * Container and all of its children receive touch events (like pointerEvents is unspecified).
22 | */
23 | AUTO,
24 | ;
25 | }
26 |
--------------------------------------------------------------------------------
/testApp/app/src/main/java/com/example/wuyunqiang/testapp/gesturehandler/PointerEventsConfig.java:
--------------------------------------------------------------------------------
1 | package com.example.wuyunqiang.testapp.gesturehandler;
2 |
3 | public enum PointerEventsConfig {
4 |
5 | /**
6 | * Neither the container nor its children receive events.
7 | */
8 | NONE,
9 |
10 | /**
11 | * Container doesn't get events but all of its children do.
12 | */
13 | BOX_NONE,
14 |
15 | /**
16 | * Container gets events but none of its children do.
17 | */
18 | BOX_ONLY,
19 |
20 | /**
21 | * Container and all of its children receive touch events (like pointerEvents is unspecified).
22 | */
23 | AUTO,
24 | ;
25 | }
26 |
--------------------------------------------------------------------------------
/testApp/app/src/main/java/com/example/wuyunqiang/testapp/gesturehandler/ViewConfigurationHelperImpl.java:
--------------------------------------------------------------------------------
1 | package com.example.wuyunqiang.testapp.gesturehandler;
2 |
3 | import android.view.View;
4 | import android.view.ViewGroup;
5 |
6 | public class ViewConfigurationHelperImpl implements ViewConfigurationHelper {
7 |
8 | @Override
9 | public PointerEventsConfig getPointerEventsConfigForView(View view) {
10 | return view.isEnabled() ? PointerEventsConfig.AUTO : PointerEventsConfig.NONE;
11 | }
12 |
13 | @Override
14 | public View getChildInDrawingOrderAtIndex(ViewGroup parent, int index) {
15 | return parent.getChildAt(index);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/testApp/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/testApp/RN_src/data/icons/index.js:
--------------------------------------------------------------------------------
1 | /*
2 | *
3 | * Created by Stone
4 | * https://github.com/bolan9999
5 | * Email: bolan999999@gmail.com
6 | * Date: 2017/12/14
7 | *
8 | */
9 |
10 |
11 | let iconObject = {
12 | icon1:require("./icon1.png"),
13 | icon2:require("./icon2.png"),
14 | icon3:require("./icon3.png"),
15 | icon4:require("./icon4.png"),
16 | icon5:require("./icon5.png"),
17 | icon6:require("./icon6.png"),
18 | icon7:require("./icon7.png"),
19 | icon8:require("./icon8.png"),
20 | icon9:require("./icon9.png"),
21 | icon10:require("./icon10.png"),
22 | icon11:require("./icon8.png"),
23 | }
24 |
25 | let iconArray = Object.values(iconObject);
26 |
27 | export {iconObject,iconArray};
--------------------------------------------------------------------------------
/testApp/app/src/main/res/layout/pull_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/testApp/RN_src/pull/i18n/index.js:
--------------------------------------------------------------------------------
1 | import { Platform, NativeModules } from 'react-native';
2 | import all from './All.js';
3 |
4 | function getLocale() {
5 | try {
6 | if (Platform.OS === 'android') {
7 | return NativeModules.I18nManager.localeIdentifier;
8 | } else {
9 | return NativeModules.SettingsManager.settings.AppleLocale;
10 | }
11 | } catch (e) {
12 | return null;
13 | } finally {}
14 | }
15 | function getI18N(v) {
16 | let locale = getLocale();
17 | if(v[locale]) {
18 | return v[locale];
19 | } else if(v[""]) {
20 | return v[""];
21 | } else {
22 | return v["default"];
23 | }
24 | }
25 | var i18n = getI18N(all);
26 | export default i18n;
27 |
--------------------------------------------------------------------------------
/testApp/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/testApp/RN_src/actions/home.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by wuyunqiang on 2018/01/24.
3 | */
4 |
5 | //请求数据的前发送的action
6 | export function FetchData(refresh = false , loadmore = false) {
7 | console.log('ActionTypes.HOME_FETCH');
8 | return {
9 | type: ActionTypes.FETCH,
10 | refresh,
11 | loadmore,
12 | };
13 | }
14 |
15 | //请求结束 发送action
16 | export function ReceiveData(data) {
17 | console.log('ActionTypes.HOME_RECEIVE');
18 | return {
19 | type: ActionTypes.RECEIVE,
20 | data,
21 | };
22 | }
23 |
24 | //请求数据的action
25 | export function RequestData(url,params){
26 | console.log('ActionTypes.HOME_REQUEST');
27 | console.log('home url',url);
28 | console.log('home params',params);
29 | return {
30 | type: ActionTypes.REQUEST,
31 | url,
32 | params
33 | };
34 | }
35 |
--------------------------------------------------------------------------------
/testApp/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | org.gradle.jvmargs=-Xmx1536m
13 | android.enableAapt2=false
14 | android.useDeprecatedNdk=true
15 |
16 | # When configured, Gradle will run in incubating parallel mode.
17 | # This option should only be used with decoupled projects. More details, visit
18 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
19 | # org.gradle.parallel=true
20 |
--------------------------------------------------------------------------------
/testApp/RN_src/sagas/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | * Copyright 2016-present reading
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | *
17 | */
18 | import { fork } from 'redux-saga/effects';
19 | import { watchHomeRequestData } from './home';
20 | export default function* rootSaga() {
21 | yield [fork(watchHomeRequestData)];
22 | }
23 |
--------------------------------------------------------------------------------
/testApp/app/src/main/res/layout/activity_other.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
18 |
19 |
--------------------------------------------------------------------------------
/testApp/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 |
5 | repositories {
6 | google()
7 | jcenter()
8 | }
9 | dependencies {
10 | classpath 'com.android.tools.build:gradle:3.0.1'
11 |
12 |
13 | // NOTE: Do not place your application dependencies here; they belong
14 | // in the individual module build.gradle files
15 | }
16 | }
17 |
18 | allprojects {
19 | repositories {
20 | google()
21 | jcenter()
22 | mavenLocal()
23 | maven {
24 | // All of React Native (JS, Android binaries) is installed from npm
25 | url "../node_modules/react-native/android"
26 | }
27 | }
28 | }
29 |
30 | task clean(type: Delete) {
31 | delete rootProject.buildDir
32 | }
33 |
--------------------------------------------------------------------------------
/testApp/app/src/main/java/com/example/wuyunqiang/testapp/fastimage/FastImageViewPackage.java:
--------------------------------------------------------------------------------
1 | package com.example.wuyunqiang.testapp.fastimage;
2 | import com.facebook.react.ReactPackage;
3 | import com.facebook.react.bridge.NativeModule;
4 | import com.facebook.react.bridge.ReactApplicationContext;
5 | import com.facebook.react.uimanager.ViewManager;
6 |
7 | import java.util.Collections;
8 | import java.util.List;
9 |
10 | public class FastImageViewPackage implements ReactPackage {
11 | @Override
12 | public List createNativeModules(ReactApplicationContext reactContext) {
13 | return Collections.singletonList(new FastImageViewModule(reactContext));
14 | }
15 |
16 | @Override
17 | public List createViewManagers(ReactApplicationContext reactContext) {
18 | return Collections.singletonList(new FastImageViewManager());
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/testApp/app/src/main/java/com/example/wuyunqiang/testapp/gesturehandler/BaseGestureHandlerInteractionController.java:
--------------------------------------------------------------------------------
1 | package com.example.wuyunqiang.testapp.gesturehandler;
2 |
3 | public abstract class BaseGestureHandlerInteractionController
4 | implements GestureHandlerInteractionController {
5 |
6 | @Override
7 | public boolean shouldWaitForHandlerFailure(GestureHandler handler,
8 | GestureHandler otherHandler) {
9 | return false;
10 | }
11 |
12 | @Override
13 | public boolean shouldRequireHandlerToWaitForFailure(GestureHandler handler,
14 | GestureHandler otherHandler) {
15 | return false;
16 | }
17 |
18 | @Override
19 | public boolean shouldRecognizeSimultaneously(GestureHandler handler,
20 | GestureHandler otherHandler) {
21 | return false;
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/testApp/app/src/androidTest/java/com/example/wuyunqiang/testapp/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.example.wuyunqiang.testapp;
2 |
3 | import android.content.Context;
4 | import android.support.test.InstrumentationRegistry;
5 | import android.support.test.runner.AndroidJUnit4;
6 |
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 |
10 | import static org.junit.Assert.*;
11 |
12 | /**
13 | * Instrumented test, which will execute on an Android device.
14 | *
15 | * @see Testing documentation
16 | */
17 | @RunWith(AndroidJUnit4.class)
18 | public class ExampleInstrumentedTest {
19 | @Test
20 | public void useAppContext() throws Exception {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getTargetContext();
23 |
24 | assertEquals("com.example.wuyunqiang.testapp", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/testApp/RN_src/list/SGList/Card.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Image, StyleSheet, Text, View } from 'react-native';
3 | import FastImage from 'react-native-fast-image'
4 | export default class Card extends React.Component {
5 | render() {
6 | return (
7 |
8 | {this.props.deal.title}
9 |
14 |
15 | );
16 | }
17 | }
18 |
19 | const styles = StyleSheet.create({
20 | container: {
21 | flex: 1,
22 | justifyContent: 'center',
23 | alignItems: 'center',
24 | backgroundColor: '#F5FCFF',
25 | borderWidth: 1,
26 | borderColor: '#CCC',
27 | marginTop: 20,
28 | },
29 | image: {
30 | height: 200,
31 | alignSelf: 'stretch',
32 | },
33 | });
34 |
35 |
--------------------------------------------------------------------------------
/testApp/RN_src/reducers/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | * Copyright 2016-present reading
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | *
17 | */
18 | import { combineReducers } from 'redux';
19 | import {Map, fromJS} from 'immutable';
20 | import home from './home';
21 | import navigator from './navigator';
22 | const rootReducer = combineReducers({
23 | nav:navigator,
24 | home,
25 | });
26 |
27 | export default rootReducer;
28 |
--------------------------------------------------------------------------------
/testApp/app/src/main/java/com/example/wuyunqiang/testapp/activity/OtherActivity.java:
--------------------------------------------------------------------------------
1 | package com.example.wuyunqiang.testapp.activity;
2 |
3 | import android.os.Bundle;
4 | import android.support.v7.app.AppCompatActivity;
5 | import android.util.Log;
6 |
7 | import com.example.wuyunqiang.testapp.R;
8 | import com.scwang.smartrefresh.layout.api.RefreshLayout;
9 | import com.scwang.smartrefresh.layout.listener.OnLoadmoreListener;
10 | import com.scwang.smartrefresh.layout.listener.OnRefreshListener;
11 |
12 | public class OtherActivity extends AppCompatActivity {
13 |
14 | @Override
15 | protected void onCreate(Bundle savedInstanceState) {
16 | super.onCreate(savedInstanceState);
17 | setContentView(R.layout.activity_other);
18 | }
19 |
20 | @Override
21 | public void onBackPressed() {
22 | super.onBackPressed();
23 | this.finish();
24 | overridePendingTransition(R.anim.slide_in_left,R.anim.slide_out_left);
25 | }
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/testApp/app/src/main/java/com/example/wuyunqiang/testapp/gesturehandler/GestureHandlerRegistryImpl.java:
--------------------------------------------------------------------------------
1 | package com.example.wuyunqiang.testapp.gesturehandler;
2 |
3 | import android.view.View;
4 |
5 | import java.util.ArrayList;
6 | import java.util.WeakHashMap;
7 |
8 | public class GestureHandlerRegistryImpl implements GestureHandlerRegistry {
9 |
10 | private WeakHashMap> mHandlers = new WeakHashMap<>();
11 |
12 | public T registerHandlerForView(View view, T handler) {
13 | ArrayList listToAdd = mHandlers.get(view);
14 | if (listToAdd == null) {
15 | listToAdd = new ArrayList<>(1);
16 | listToAdd.add(handler);
17 | mHandlers.put(view, listToAdd);
18 | } else {
19 | listToAdd.add(handler);
20 | }
21 | return handler;
22 | }
23 |
24 | @Override
25 | public ArrayList getHandlersForView(View view) {
26 | return mHandlers.get(view);
27 | }
28 | }
29 |
30 |
--------------------------------------------------------------------------------
/testApp/app/src/main/java/com/example/wuyunqiang/testapp/RNFetchBlob/RNFetchBlobConst.java:
--------------------------------------------------------------------------------
1 | package com.example.wuyunqiang.testapp.RNFetchBlob;
2 |
3 |
4 | public class RNFetchBlobConst {
5 | public static final String EVENT_UPLOAD_PROGRESS = "RNFetchBlobProgress-upload";
6 | public static final String EVENT_PROGRESS = "RNFetchBlobProgress";
7 | public static final String EVENT_HTTP_STATE = "RNFetchBlobState";
8 | public static final String EVENT_MESSAGE = "RNFetchBlobMessage";
9 | public static final String FILE_PREFIX = "RNFetchBlob-file://";
10 | public static final String FILE_PREFIX_BUNDLE_ASSET = "bundle-assets://";
11 | public static final String FILE_PREFIX_CONTENT = "content://";
12 | public static final String DATA_ENCODE_URI = "uri";
13 | public static final String RNFB_RESPONSE_BASE64 = "base64";
14 | public static final String RNFB_RESPONSE_UTF8 = "utf8";
15 | public static final String RNFB_RESPONSE_PATH = "path";
16 | public static final Integer GET_CONTENT_INTENT = 99900;
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/testApp/RN_src/utils/StyleColor.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by wuyunqiang on 2017/8/8.
3 | */
4 |
5 | export default class StyleColor {
6 | static e35041 = '#e35041';
7 | static white = 'white';
8 | static fb3b3f = '#fb3b3f';//header颜色
9 | static f5f5f5 = '#f5f5f5';//全局背景色
10 | static f3f3f3 = '#f3f3f3';
11 | static C999999 = '#999999';
12 | static C333333 = '#333333';
13 | static C666666 = '#666666';
14 | static ff7b41 = '#ff7b41';//审批中
15 | static eaeaea = '#eaeaea';//细分割线
16 | static C01af81 = '#01af81';
17 | static C5995f5 = '#5995f5';//按钮颜色
18 | static f7f7f7 = '#f7f7f7';
19 | static C7b7b7b = '#7b7b7b';//未选中文字颜色
20 | static faf9f9 = '#faf9f9';
21 | static dddddd = '#dddddd';
22 | static ffffff = '#ffffff';
23 | static f3474b = '#f3474b';//选中的颜色
24 | static fde2e3 = '#fde2e3';
25 | static fff7e7 = '#fff7e7';
26 | static f6f8fb = '#f6f8fb';//时间背景色
27 | static fe461c ='#fe461c';
28 | static ffe7d6 = '#ffe7d6';
29 | static f97578 = '#f97578'
30 | }
31 |
32 | global.Color = StyleColor;
--------------------------------------------------------------------------------
/testApp/app/src/main/java/com/example/wuyunqiang/testapp/codepush/DownloadProgress.java:
--------------------------------------------------------------------------------
1 | package com.example.wuyunqiang.testapp.codepush;
2 |
3 | import com.facebook.react.bridge.WritableMap;
4 | import com.facebook.react.bridge.WritableNativeMap;
5 |
6 | class DownloadProgress {
7 | private long mTotalBytes;
8 | private long mReceivedBytes;
9 |
10 | public DownloadProgress (long totalBytes, long receivedBytes){
11 | mTotalBytes = totalBytes;
12 | mReceivedBytes = receivedBytes;
13 | }
14 |
15 | public WritableMap createWritableMap() {
16 | WritableMap map = new WritableNativeMap();
17 | if (mTotalBytes < Integer.MAX_VALUE) {
18 | map.putInt("totalBytes", (int) mTotalBytes);
19 | map.putInt("receivedBytes", (int) mReceivedBytes);
20 | } else {
21 | map.putDouble("totalBytes", mTotalBytes);
22 | map.putDouble("receivedBytes", mReceivedBytes);
23 | }
24 | return map;
25 | }
26 |
27 | public boolean isCompleted() {
28 | return mTotalBytes == mReceivedBytes;
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/testApp/RN_src/list/SGList/CardListView.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { ListView } from 'react-native';
3 | import SGListView from 'react-native-sglistview';
4 | import Card from './Card';
5 | import PropTypes from 'prop-types';
6 | const LIST_VIEW = 'listview';
7 |
8 | export default class CardListView extends React.Component {
9 | renderRow(rowData, sectionID, rowID) {
10 | return (
11 |
12 | );
13 | }
14 |
15 | render() {
16 | return (
17 |
23 | );
24 | }
25 |
26 | getDataSource() {
27 | const dataSource = new ListView.DataSource(
28 | { rowHasChanged: (r1, r2) => r1.uuid !== r2.uuid });
29 |
30 | const deals = this.props.deals.length > 0;
31 | return deals ? dataSource.cloneWithRows(this.props.deals) : dataSource;
32 | }
33 | }
34 |
35 | CardListView.propTypes = {
36 | deals: PropTypes.object.isRequired,
37 | onEndReached: PropTypes.func.isRequired,
38 | };
39 |
40 |
--------------------------------------------------------------------------------
/testApp/app/src/main/java/com/example/wuyunqiang/testapp/RNFetchBlob/RNFetchBlobPackage.java:
--------------------------------------------------------------------------------
1 | package com.example.wuyunqiang.testapp.RNFetchBlob;
2 |
3 | import com.facebook.react.ReactPackage;
4 | import com.facebook.react.bridge.JavaScriptModule;
5 | import com.facebook.react.bridge.NativeModule;
6 | import com.facebook.react.bridge.ReactApplicationContext;
7 | import com.facebook.react.uimanager.ViewManager;
8 |
9 | import java.util.ArrayList;
10 | import java.util.Collections;
11 | import java.util.List;
12 |
13 |
14 | public class RNFetchBlobPackage implements ReactPackage {
15 |
16 | @Override
17 | public List createNativeModules(ReactApplicationContext reactContext) {
18 | List modules = new ArrayList<>();
19 | modules.add(new RNFetchBlob(reactContext));
20 | return modules;
21 | }
22 |
23 | public List> createJSModules() {
24 | return Collections.emptyList();
25 | }
26 |
27 | @Override
28 | public List createViewManagers(ReactApplicationContext reactContext) {
29 | return Collections.emptyList();
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/testApp/RN_src/component/modol.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by wuyunqiang on 2018/1/16.
3 | */
4 | import React, { Component } from 'react';
5 | import {
6 | AppRegistry,
7 | Platform,
8 | StyleSheet,
9 | Text,
10 | View,
11 | ScrollView,
12 | Image,
13 | UIManager,
14 | TouchableOpacity,
15 | NativeModules,
16 | ImageBackground,
17 | DeviceEventEmitter,
18 | requireNativeComponent,
19 | } from 'react-native';
20 | const ReactNative = require('ReactNative');
21 | import PropTypes from 'prop-types';
22 | var ModalView = requireNativeComponent('ModalAndroid', App);//内部使用popwindow实现全屏
23 | export default class App extends Component {
24 | constructor(props){
25 | super(props);
26 | }
27 |
28 | render() {
29 | return (
30 | {this.PopModal = PopModal}}
32 | {...this.props}>
33 |
34 | {this.props.children}
35 |
36 |
37 | )
38 | }
39 | }
40 |
41 | ModalView.propTypes = {
42 | ...View.propTypes,
43 | visible:PropTypes.bool,
44 | };
--------------------------------------------------------------------------------
/testApp/RN_src/page/GesturePage.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { Animated,Dimensions,Alert,Text,StyleSheet, View } from 'react-native';
3 | import {
4 | PanGestureHandler,
5 | LongPressGestureHandler,
6 | ScrollView,
7 | State,
8 | TapGestureHandler,
9 | } from 'react-native-gesture-handler';
10 | import TapOrPan from '../gesture/TapOrPan'
11 | import PressBox from '../gesture/PressBox'
12 | import { LoremIpsum } from '../data/common';
13 | import DraggableBox from '../gesture/draggable'
14 |
15 | export default class Example extends Component {
16 | render() {
17 | return (
18 |
21 |
22 |
23 |
24 |
25 | );
26 | }
27 | }
28 |
29 | const styles = StyleSheet.create({
30 | scrollView: {
31 | flex: 1,
32 | },
33 | box: {
34 | width: 150,
35 | height: 150,
36 | alignSelf: 'center',
37 | backgroundColor: 'plum',
38 | margin: 10,
39 | zIndex: 200,
40 | },
41 | });
42 |
--------------------------------------------------------------------------------
/testApp/RN_src/page/TestActivity.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Sample React Native App
3 | * https://github.com/facebook/react-native
4 | * @flow
5 | */
6 |
7 | import React, { Component } from 'react';
8 | import {
9 | AppRegistry,
10 | Platform,
11 | StyleSheet,
12 | Text,
13 | View,
14 | Dimensions,
15 | DeviceEventEmitter
16 | } from 'react-native';
17 | let WIDTH = Dimensions.get('window').width;
18 |
19 | export default class App extends Component {
20 |
21 | constructor(props){
22 | super(props);
23 | console.log("TestActivity 执行构造函数")
24 | }
25 |
26 | componentDidMount() {
27 | console.log("TestActivity componentDidMount")
28 | }
29 |
30 | render() {
31 | return (
32 |
33 | Hello, 这里是RN view
34 |
35 | )
36 | }
37 | }
38 |
39 | const styles = StyleSheet.create({
40 | container: {
41 | flex:1,
42 | width:WIDTH,
43 | backgroundColor:'gray'
44 | },
45 | hello: {
46 | marginTop:20,
47 | fontSize: 20,
48 | textAlign: 'center',
49 | margin: 10,
50 | },
51 | });
52 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/testApp/RN_src/list/SGList/CardListController.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import DataSource from './CardListDataSource';
3 | import CardListView from './CardListView';
4 |
5 | class CardList extends React.Component {
6 | constructor(props) {
7 | super(props);
8 | const self = this;
9 |
10 | this.state = {
11 | deals: [],
12 | };
13 |
14 | this.cache = {
15 | offset: 0,
16 | limit: 10,
17 | lat: 45.52,
18 | lng: -122.681944,
19 | };
20 |
21 | DataSource.fetch(this.cache, (err, res) => {
22 | if (err) console.warn(err);
23 | else self.setState({deals:res.body.deals});
24 | });
25 | }
26 |
27 | render() {
28 | return (
29 |
33 | );
34 | }
35 |
36 | onEndReached() {
37 | this.cache.offset += 10;
38 | var self = this;
39 |
40 | DataSource.fetch(this.cache, (err, res) => {
41 | if (err) console.warn(err);
42 | else self.setState({deals:self.state.deals.concat(res.body.deals)}); // concat deals to the end of the array
43 | });
44 | }
45 | }
46 |
47 | module.exports = CardList;
48 |
--------------------------------------------------------------------------------
/testApp/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "testapp",
3 | "version": "1.0.0",
4 | "description": "test",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "start": "node node_modules/react-native/local-cli/cli.js start",
9 | "bundle": "react-native bundle --entry-file index.js --bundle-output ./bundle/index.android.bundle--platform android --assets-dest ./bundle --dev false "
10 | },
11 | "author": "",
12 | "license": "ISC",
13 | "dependencies": {
14 | "add": "^2.0.6",
15 | "immutable": "^3.8.2",
16 | "react": "^16.2.0",
17 | "react-native": "0.55.4",
18 | "react-native-code-push": "^5.3.4",
19 | "react-native-fast-image": "^4.0.14",
20 | "react-native-fetch-blob": "^0.10.8",
21 | "react-native-gesture-handler": "^1.0.0-alpha.40",
22 | "react-native-largelist": "^1.2.4",
23 | "react-native-root-toast": "^3.0.0",
24 | "react-native-sglistview": "^0.4.5",
25 | "react-navigation": "^2.0.1",
26 | "react-navigation-redux-helpers": "^1.0.1",
27 | "react-redux": "^5.0.6",
28 | "redux": "^3.7.2",
29 | "redux-logger": "^3.0.6",
30 | "redux-saga": "^0.16.0",
31 | "superagent": "^3.8.2",
32 | "yarn": "^1.3.2"
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/testApp/app/src/main/java/com/example/wuyunqiang/testapp/RNFetchBlob/RNFetchBlobProgressConfig.java:
--------------------------------------------------------------------------------
1 | package com.example.wuyunqiang.testapp.RNFetchBlob;
2 |
3 | /**
4 | * Created by wkh237 on 2016/9/24.
5 | */
6 | public class RNFetchBlobProgressConfig {
7 |
8 | public enum ReportType {
9 | Upload,
10 | Download
11 | };
12 |
13 | long lastTick = 0;
14 | int tick = 0;
15 | int count = -1;
16 | public int interval = -1;
17 | public boolean enable = false;
18 | public ReportType type = ReportType.Download;
19 |
20 | RNFetchBlobProgressConfig(boolean report, int interval, int count, ReportType type) {
21 | this.enable = report;
22 | this.interval = interval;
23 | this.type = type;
24 | this.count = count;
25 | }
26 |
27 | public boolean shouldReport(float progress) {
28 | boolean checkCount = true;
29 | if(count > 0 && progress > 0)
30 | checkCount = Math.floor(progress*count)> tick;
31 | boolean result = (System.currentTimeMillis() - lastTick> interval) && enable && checkCount;
32 | if(result) {
33 | tick++;
34 | lastTick = System.currentTimeMillis();
35 | }
36 | return result;
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/testApp/app/src/main/java/com/example/wuyunqiang/testapp/RNPackage.java:
--------------------------------------------------------------------------------
1 | package com.example.wuyunqiang.testapp;
2 |
3 | import com.example.wuyunqiang.testapp.rnmodules.NativeUtil;
4 | import com.example.wuyunqiang.testapp.rnview.PopModalManager;
5 | import com.example.wuyunqiang.testapp.rnview.PullLayout;
6 | import com.facebook.react.ReactPackage;
7 | import com.facebook.react.bridge.ReactApplicationContext;
8 | import com.facebook.react.uimanager.ViewManager;
9 |
10 | import java.util.ArrayList;
11 | import java.util.List;
12 |
13 | /**
14 | * Created by wuyunqiang on 2018/1/2.
15 | */
16 |
17 | public class RNPackage implements ReactPackage {
18 |
19 | @Override
20 | public List createNativeModules(ReactApplicationContext reactContext) {
21 | List modules = new ArrayList<>();
22 | modules.add(new NativeUtil(reactContext));
23 |
24 | return modules;
25 | }
26 |
27 | @Override
28 | public List createViewManagers(ReactApplicationContext reactContext) {
29 | List views = new ArrayList<>();
30 | views.add(new PullLayout());
31 | views.add(new PopModalManager());
32 | return views;
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/testApp/app/src/main/java/com/example/wuyunqiang/testapp/codepush/Promiss.java:
--------------------------------------------------------------------------------
1 | package com.example.wuyunqiang.testapp.codepush;
2 |
3 | import android.util.Log;
4 |
5 | import com.facebook.react.bridge.Promise;
6 |
7 | import javax.annotation.Nullable;
8 |
9 | /**
10 | * Created by wuyunqiang on 2018/1/9.
11 | */
12 |
13 | public class Promiss implements Promise {
14 |
15 | public static String TAG = "CodePush";
16 |
17 |
18 | @Override
19 | public void resolve(@Nullable Object value) {
20 | Log.i(TAG,"resolve:");
21 | }
22 |
23 | @Override
24 | public void reject(String code, String message) {
25 | Log.i(TAG,"reject: "+message);
26 |
27 | }
28 |
29 | @Override
30 | public void reject(String code, Throwable e) {
31 | Log.i(TAG,"reject: "+e.getMessage());
32 |
33 | }
34 |
35 | @Override
36 | public void reject(String code, String message, Throwable e) {
37 | Log.i(TAG,"reject: "+"code:"+code+" message:"+message+" e:"+e.getMessage());
38 | }
39 |
40 | @Override
41 | public void reject(String message) {
42 | Log.i(TAG,"reject: "+message);
43 | }
44 |
45 | @Override
46 | public void reject(Throwable reason) {
47 | Log.i(TAG,"reject: "+reason.getMessage());
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/testApp/RN_src/reducers/navigator.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by wuyunqiang on 2018/01/24.
3 | */
4 | import {fromJS} from 'immutable';
5 | import {NavigationActions} from 'react-navigation';
6 |
7 | import AppNavigator from '../router';
8 |
9 | // *****************方式重复跳转页面
10 | const navigateOnce = (getStateForAction) => (action, state) => {
11 | const {type, routeName} = action
12 | console.log('执行了这里跳转页面',"routeName:",routeName);
13 | return (
14 | state &&
15 | type === NavigationActions.NAVIGATE &&
16 | routeName === state.routes[state.routes.length - 1].routeName
17 | ) ? null : getStateForAction(action, state)
18 | };
19 | AppNavigator.router.getStateForAction= navigateOnce(AppNavigator.router.getStateForAction);
20 | // *****************
21 |
22 | export default function navigator(state, action) {
23 | console.log('navigator reduce',state,'action',action);
24 | const newState = AppNavigator.router.getStateForAction(action, state);
25 |
26 | return newState || state;
27 | // Initial state
28 | // if (!state) {
29 | // return fromJS(AppNavigator.router.getStateForAction(action, state));
30 | // }
31 | // // Is this a navigation action that we should act upon?
32 | // if (includes(NavigationActions, action.type)) {
33 | // return fromJS(AppNavigator.router.getStateForAction(action, state.toJS()));
34 | // }
35 | // return state;
36 | }
37 |
--------------------------------------------------------------------------------
/testApp/app/src/main/java/com/example/wuyunqiang/testapp/codepush/CodePushBuilder.java:
--------------------------------------------------------------------------------
1 | package com.example.wuyunqiang.testapp.codepush;
2 |
3 | import android.content.Context;
4 |
5 | public class CodePushBuilder {
6 | private String mDeploymentKey;
7 | private Context mContext;
8 |
9 | private boolean mIsDebugMode;
10 | private String mServerUrl;
11 | private Integer mPublicKeyResourceDescriptor;
12 |
13 | public CodePushBuilder(String deploymentKey, Context context) {
14 | this.mDeploymentKey = deploymentKey;
15 | this.mContext = context;
16 | this.mServerUrl = com.example.wuyunqiang.testapp.codepush.CodePush.getServiceUrl();
17 | }
18 |
19 | public CodePushBuilder setIsDebugMode(boolean isDebugMode) {
20 | this.mIsDebugMode = isDebugMode;
21 | return this;
22 | }
23 |
24 | public CodePushBuilder setServerUrl(String serverUrl) {
25 | this.mServerUrl = serverUrl;
26 | return this;
27 | }
28 |
29 | public CodePushBuilder setPublicKeyResourceDescriptor(int publicKeyResourceDescriptor) {
30 | this.mPublicKeyResourceDescriptor = publicKeyResourceDescriptor;
31 | return this;
32 | }
33 |
34 | public com.example.wuyunqiang.testapp.codepush.CodePush build() {
35 | return new com.example.wuyunqiang.testapp.codepush.CodePush(this.mDeploymentKey, this.mContext, this.mIsDebugMode, this.mServerUrl, this.mPublicKeyResourceDescriptor);
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/testApp/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
12 |
13 |
22 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/testApp/RN_src/assets/index.js:
--------------------------------------------------------------------------------
1 | /*
2 | * 图片资源
3 | * */
4 |
5 | const List = {
6 | get nodata() {return require('../assets/list/nodata.png')},
7 | get nonetwork() {return require('../assets/list/nonetwork.png')},
8 | };
9 |
10 |
11 | const tab = {
12 | get xindaiicon_unactive() {return require('./tab/xindaiicon_unactive.png');},
13 | get xindaiicon_active() {return require('./tab/xindaiicon_active.png');},
14 | get home_active() {return require('./tab/home_active.png');},
15 | get home_unactive() {return require('./tab/home_unactive.png');},
16 | get project_active() {return require('./tab/project_active.png');},
17 | get project_unactive() {return require('./tab/project_unactive.png');},
18 | get profile_active() {return require('./tab/profile_active.png');},
19 | get profile_unactive() {return require('./tab/profile_unactive.png');},
20 | };
21 |
22 | const Home = {
23 | get back() {return require('../assets/home/back.png')},
24 | get backgroundImageHeader() {return require('../assets/home/backgroundImageHeader.png')},
25 | get share_icon_moments() {return require('../assets/home/share_icon_moments.png')},
26 | get share_icon_wechat() {return require('../assets/home/share_icon_wechat.png')},
27 |
28 | };
29 |
30 |
31 | const AppImages = {
32 | get List(){
33 | return List;
34 | },
35 | get tab(){
36 | return tab;
37 | },
38 |
39 | get Home(){
40 | return Home;
41 | },
42 | };
43 | export default AppImages;
44 | global.AppImages = AppImages;
--------------------------------------------------------------------------------
/testApp/RN_src/store/configure-store.js:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | * Copyright 2016-present reading
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | * 2018/01/24.
17 | */
18 | import { createStore, applyMiddleware } from 'redux';
19 | import createSagaMiddleware, { END } from 'redux-saga';
20 | import rootReducer from '../reducers/index';
21 |
22 | const middlewares = [];
23 | const { logger } = require('redux-logger');
24 |
25 | // configuring saga middleware
26 | const sagaMiddleware = createSagaMiddleware();
27 |
28 | middlewares.push(sagaMiddleware);
29 | /* global __DEV__ */
30 | if (__DEV__) {
31 | middlewares.push(logger);
32 | }
33 | const createStoreWithMiddleware = applyMiddleware(...middlewares)(createStore);
34 |
35 | export default function configureStore(initialState) {
36 | const store = createStoreWithMiddleware(rootReducer, initialState);
37 | // install saga run
38 | store.runSaga = sagaMiddleware.run;
39 | store.close = () => store.dispatch(END);
40 |
41 | return store;
42 | }
43 |
--------------------------------------------------------------------------------
/testApp/app/src/main/java/com/example/wuyunqiang/testapp/gesture/RNGestureHandlerRootView.java:
--------------------------------------------------------------------------------
1 | package com.example.wuyunqiang.testapp.gesture;
2 |
3 | import android.content.Context;
4 | import android.view.MotionEvent;
5 |
6 | import com.facebook.infer.annotation.Assertions;
7 | import com.facebook.react.bridge.ReactContext;
8 | import com.facebook.react.views.view.ReactViewGroup;
9 |
10 | import javax.annotation.Nullable;
11 |
12 | public class RNGestureHandlerRootView extends ReactViewGroup {
13 |
14 | private @Nullable
15 | RNGestureHandlerRootHelper mRootHelper;
16 |
17 | public RNGestureHandlerRootView(Context context) {
18 | super(context);
19 | }
20 |
21 | @Override
22 | protected void onAttachedToWindow() {
23 | super.onAttachedToWindow();
24 | if (mRootHelper == null) {
25 | mRootHelper = new RNGestureHandlerRootHelper((ReactContext) getContext(), this);
26 | }
27 | }
28 |
29 | public void tearDown() {
30 | if (mRootHelper != null) {
31 | mRootHelper.tearDown();
32 | }
33 | }
34 |
35 | @Override
36 | public boolean dispatchTouchEvent(MotionEvent ev) {
37 | if (Assertions.assertNotNull(mRootHelper).dispatchTouchEvent(ev)) {
38 | return true;
39 | }
40 | return super.dispatchTouchEvent(ev);
41 | }
42 |
43 | @Override
44 | public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {
45 | Assertions.assertNotNull(mRootHelper).requestDisallowInterceptTouchEvent(disallowIntercept);
46 | super.requestDisallowInterceptTouchEvent(disallowIntercept);
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/testApp/app/src/main/res/layout/activity_test.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
20 |
28 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/testApp/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
18 |
24 |
25 |
31 |
32 |
33 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/testApp/RN_src/list/SGList/CardListDataSource.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | import http from 'superagent';
4 |
5 | var CardListDataSource = {
6 | fetch:function(props, callback) {
7 | var self = this;
8 | let query = "https://api.groupon.com/v2/deals?offset=" + props.offset +
9 | "&client_id=" + "1a36af586a2ced1684fea9ecdc7c1f6f" +
10 | "&client_version_id=" + "16.2" +
11 | "&division_id=portland&include_travel_bookable_deals=true&lang=en" +
12 | "&lat=" + props.lat +
13 | "&limit=" + props.limit +
14 | "&lng=" + props.lng + "&location_time=2015-06-09T22%3A56%3A19Z&metadata=true&secure_assets=false&show=id%2Ctitle%2CplacementPriority%2CsidebarImageUrl%2CendAt%2CdealTypes%2Cmerchant%2CisSoldOut%2CsoldQuantity%2CsoldQuantityMessage%2Cstatus%2Coptions%28images%2Ctrait%2CpricingMetadata%2CschedulerOptions%29%2CannouncementTitle%2ClargeImageUrl%2Cgrid4ImageUrl%2Cgrid6ImageUrl%2CmediumImageUrl%2CshippingAddressRequired%2CredemptionLocation%2Cchannels%2CdealUrl%2Cdivision%2CpitchHtml%2ChighlightsHtml%2CisEarly%2CisExtended%2CredemptionLocations%2CisTipped%2CtippingPoint%2ClocationNote%2CspecificAttributes%2CisTravelBookableDeal%2CisMerchandisingDeal%2Cdefault%2Cuuid%2Ctraits%2Cimages&zero_day=true";
15 |
16 |
17 |
18 |
19 | http.get(query)
20 | .end((err, res) => {
21 | console.log('res',res);
22 | if (err) { return callback(err); };
23 |
24 | callback(false, res);
25 | });
26 | }
27 | };
28 |
29 | module.exports = CardListDataSource;
30 |
--------------------------------------------------------------------------------
/testApp/app/src/main/res/layout/header.xml:
--------------------------------------------------------------------------------
1 |
2 |
12 |
18 |
25 |
32 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/testApp/RN_src/utils/index.js:
--------------------------------------------------------------------------------
1 | import {Dimensions,PixelRatio,Platform} from 'react-native';
2 | import './StyleColor'
3 | import './HttpUtil'
4 | export const deviceWidth = Dimensions.get('window').width; //设备的宽度
5 | export const deviceHeight = Dimensions.get('window').height; //设备的高度
6 | let fontScale = PixelRatio.getFontScale(); //返回字体大小缩放比例
7 | let pixelRatio = PixelRatio.get(); //当前设备的像素密度
8 | const defaultPixel = 2;
9 | //iphone6的像素密度
10 | //px转换成dp
11 | const defaultW = Platform.OS ==='ios'?750:720;
12 | const defaultH = Platform.OS ==='ios'?1334:1280;
13 | const w2 = defaultW / defaultPixel;
14 | const h2 = defaultH / defaultPixel;
15 | const scale = Math.min(deviceHeight / h2, deviceWidth / w2); //获取缩放比例
16 | //noinspection JSAnnotator
17 | /**
18 | * 设置text为sp
19 | * @param size sp
20 | * return number dp
21 | */
22 | export function setSpText(size: number) {
23 | // size = size/pixelRatio;
24 | // size = Math.round((size * scale + 0.5) * pixelRatio / fontScale);
25 | return size;
26 | }
27 |
28 | //noinspection JSAnnotator
29 | export function scaleSize(size: number) {
30 | size = Math.round(size * scale + 0.5);
31 | return size / defaultPixel;
32 | }
33 |
34 | export function Log(...params){
35 | if(__DEV__){
36 | // debug模式
37 | console.log(...params)
38 | }else{
39 | // release模式
40 | // Log('release模式');
41 | }
42 |
43 | }
44 |
45 | global.FONT = setSpText;
46 |
47 | global.SCALE = scaleSize;
48 |
49 | global.WIDTH = deviceWidth;
50 |
51 | global.HEIGHT = deviceHeight;
52 |
53 | global.Log = Log;
54 |
55 |
56 |
--------------------------------------------------------------------------------
/testApp/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/testApp/app/src/main/java/com/example/wuyunqiang/testapp/gesturehandler/GestureHandlerViewWrapper.java:
--------------------------------------------------------------------------------
1 | package com.example.wuyunqiang.testapp.gesturehandler;
2 |
3 | import android.content.Context;
4 | import android.util.AttributeSet;
5 | import android.view.MotionEvent;
6 | import android.widget.FrameLayout;
7 |
8 | public class GestureHandlerViewWrapper extends FrameLayout {
9 |
10 | private final GestureHandlerOrchestrator mOrchestrator;
11 | private final GestureHandlerRegistryImpl mRegistry;
12 |
13 | public GestureHandlerViewWrapper(Context context) {
14 | super(context);
15 | mRegistry = new GestureHandlerRegistryImpl();
16 | mOrchestrator = new GestureHandlerOrchestrator(this, mRegistry, new ViewConfigurationHelperImpl());
17 | }
18 |
19 | public GestureHandlerViewWrapper(Context context, AttributeSet attrs) {
20 | super(context, attrs);
21 | mRegistry = new GestureHandlerRegistryImpl();
22 | mOrchestrator = new GestureHandlerOrchestrator(this, mRegistry, new ViewConfigurationHelperImpl());
23 | }
24 |
25 | public GestureHandlerViewWrapper(Context context, AttributeSet attrs, int defStyleAttr) {
26 | super(context, attrs, defStyleAttr);
27 | mRegistry = new GestureHandlerRegistryImpl();
28 | mOrchestrator = new GestureHandlerOrchestrator(this, mRegistry, new ViewConfigurationHelperImpl());
29 | }
30 |
31 | public GestureHandlerRegistryImpl getRegistry() {
32 | return mRegistry;
33 | }
34 |
35 | @Override
36 | public boolean onInterceptTouchEvent(MotionEvent ev) {
37 | return true;
38 | }
39 |
40 | @Override
41 | public boolean onTouchEvent(MotionEvent event) {
42 | return mOrchestrator.onTouchEvent(event);
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/testApp/app/src/main/java/com/example/wuyunqiang/testapp/view/ModalHostShadowNode.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2015-present, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the BSD-style license found in the
6 | * LICENSE file in the root directory of this source tree. An additional grant
7 | * of patent rights can be found in the PATENTS file in the same directory.
8 | */
9 |
10 | package com.example.wuyunqiang.testapp.view;
11 |
12 | import android.graphics.Point;
13 |
14 | import com.facebook.react.uimanager.LayoutShadowNode;
15 | import com.facebook.react.uimanager.ReactShadowNodeImpl;
16 |
17 | /**
18 | * We implement the Modal by using an Android Dialog. That will fill the entire window of the
19 | * application. To get layout to work properly, we need to layout all the elements within the
20 | * Modal's inner content view as if they can fill the entire window. To do that, we need to
21 | * explicitly set the styleWidth and styleHeight on the LayoutShadowNode of the child of this node
22 | * to be the window size. This will then cause the children of the Modal to layout as if they can
23 | * fill the window.
24 | */
25 | public class ModalHostShadowNode extends LayoutShadowNode {
26 |
27 | /**
28 | * We need to set the styleWidth and styleHeight of the one child (represented by the
29 | * within the in Modal.js. This needs to fill the entire window.
30 | */
31 | @Override
32 | public void addChildAt(ReactShadowNodeImpl child, int i) {
33 | super.addChildAt(child, i);
34 | Point modalSize = ModalHostHelper.getModalHostSize(getThemedContext());
35 | child.setStyleWidth(modalSize.x);
36 | child.setStyleHeight(modalSize.y);
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/testApp/RN_src/reducers/home.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by wuyunqiang on 2018/01/24.
3 | */
4 | import { Map,is,fromJS } from 'immutable';
5 | const initialState = Map({
6 | refresh:false,
7 | loading:true,
8 | loadmore:false,
9 | data: fromJS({}),
10 | url:'',
11 | params:{},
12 | });
13 |
14 | export default function home(state = initialState, action) {
15 | switch (action.type) {
16 | case ActionTypes.FETCH:
17 | return state
18 | .set('loading',true)
19 | .set('refresh',action.refresh?action.refresh:false)
20 | .set('loadmore',action.loadmore?action.loadmore:false);
21 | case ActionTypes.RECEIVE:
22 | const map1 = fromJS(action.data);//网络获取
23 | const map2 = state.get('data');//本地已经有的数据
24 | console.log('是否更新 reduce',!is(map1,map2));
25 | if(is(map1,map2)){
26 | return state
27 | .set('loading',false)
28 | .set('refresh',false)
29 | .set('loadmore',false)
30 | }
31 | return state
32 | .set('data',map1)
33 | .set('loading',false)
34 | .set('refresh',false)
35 | .set('loadmore',false);
36 |
37 | default:
38 | return state;
39 | }
40 | }
41 |
42 | function loadMore(state, action) {
43 | // state.get('articleList')[action.typeId] = state.get('articleList')[action.typeId].concat(
44 | // action.articleList
45 | // );
46 | // console.log('loadMore state', state.get('articleList'));
47 | return state.get('articleList');
48 | // state.articleList[action.typeId] = state.articleList[action.typeId].concat(
49 | // action.articleList
50 | // );
51 | // return state.articleList;
52 | }
53 |
--------------------------------------------------------------------------------
/testApp/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/testApp/RN_src/sagas/home.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by wuyunqiang on 2017/10/10.
3 | */
4 | import { put, take, call, fork } from 'redux-saga/effects';
5 | import * as home from '../actions/home';
6 |
7 | export function* RequestData(url, params) {
8 | console.log('sagas url',params);
9 | let query = url + params.offset +
10 | "&client_id=" + "1a36af586a2ced1684fea9ecdc7c1f6f" +
11 | "&client_version_id=" + "16.2" +
12 | "&division_id=portland&include_travel_bookable_deals=true&lang=en" +
13 | "&lat=" + params.lat +
14 | "&limit=" + params.limit +
15 | "&lng=" + params.lng + "&location_time=2015-06-09T22%3A56%3A19Z&metadata=true&secure_assets=false&show=id%2Ctitle%2CplacementPriority%2CsidebarImageUrl%2CendAt%2CdealTypes%2Cmerchant%2CisSoldOut%2CsoldQuantity%2CsoldQuantityMessage%2Cstatus%2Coptions%28images%2Ctrait%2CpricingMetadata%2CschedulerOptions%29%2CannouncementTitle%2ClargeImageUrl%2Cgrid4ImageUrl%2Cgrid6ImageUrl%2CmediumImageUrl%2CshippingAddressRequired%2CredemptionLocation%2Cchannels%2CdealUrl%2Cdivision%2CpitchHtml%2ChighlightsHtml%2CisEarly%2CisExtended%2CredemptionLocations%2CisTipped%2CtippingPoint%2ClocationNote%2CspecificAttributes%2CisTravelBookableDeal%2CisMerchandisingDeal%2Cdefault%2Cuuid%2Ctraits%2Cimages&zero_day=true";
16 |
17 | try {
18 | console.log('网络请求前');
19 | //调用函数返回promise会阻塞
20 | const data = yield call(HttpUtil.GET, query);
21 | console.log('网路请求后 获得数据');
22 | //触发一个action
23 | yield put(home.ReceiveData(data));
24 | } catch (error) {
25 | console.log('网络请求 出现错误');
26 | yield put(home.ReceiveData({}));
27 | }
28 | }
29 |
30 | export function* watchHomeRequestData() {
31 | while (true) {
32 | const action = yield take([ActionTypes.REQUEST]);
33 | yield fork(
34 | ...action
35 | );
36 |
37 | }
38 | }
--------------------------------------------------------------------------------
/testApp/RN_src/root.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by wuyunqiang on 2017/10/9.
3 | */
4 | import './assets'
5 | import './utils';
6 | import './actions/ActionTypes'
7 | import React from 'react';
8 | import {
9 | BackHandler,
10 | Platform
11 | } from 'react-native';
12 | import { addListener } from './utils/NavigationReduxUtil';
13 | import PropTypes from 'prop-types';
14 | import { Provider,connect } from 'react-redux';
15 | import { StackNavigator,TabNavigator,NavigationActions} from 'react-navigation';
16 | import configureStore from './store/configure-store';//配置reduce
17 | import rootSaga from './sagas/index';//配置sagas异步操作
18 | import AppNavigator from './router'
19 | const store = configureStore();
20 | store.runSaga(rootSaga);//配置数据通过saga获取 然后通过reduce返回存储到store中 store作为唯一数据源
21 |
22 | // const getCurrentRouteName = (navigationState) => {
23 | // if (!navigationState) {
24 | // return null;
25 | // }
26 | // const route = navigationState.routes[navigationState.index];
27 | // // dive into nested navigators
28 | // if (route.routes) {
29 | // return getCurrentRouteName(route);
30 | // }
31 | // return route.routeName;
32 | // }
33 |
34 | class NavigatorView extends React.Component {
35 | static propTypes = {
36 | dispatch: PropTypes.func.isRequired,
37 | nav: PropTypes.object.isRequired,
38 | };
39 |
40 | render (){
41 | const { dispatch, nav } = this.props;
42 | //react-navigation与redux集成
43 | return ()
48 | }
49 | }
50 | /**
51 | * 注入数据流
52 | * **/
53 | const mapStateToProps = state => ({
54 | nav: state.nav,
55 | });
56 | const AppWithNavigationState = connect(mapStateToProps)(NavigatorView);
57 |
58 | const Root = () => (
59 |
60 | );
61 |
62 | export default Root;
63 |
64 |
--------------------------------------------------------------------------------
/testApp/app/src/main/java/com/example/wuyunqiang/testapp/gesture/RNViewConfigurationHelper.java:
--------------------------------------------------------------------------------
1 | package com.example.wuyunqiang.testapp.gesture;
2 |
3 | import android.view.View;
4 | import android.view.ViewGroup;
5 |
6 | import com.example.wuyunqiang.testapp.gesturehandler.PointerEventsConfig;
7 | import com.example.wuyunqiang.testapp.gesturehandler.ViewConfigurationHelper;
8 | import com.facebook.react.uimanager.PointerEvents;
9 | import com.facebook.react.uimanager.ReactPointerEventsView;
10 | import com.facebook.react.views.view.ReactViewGroup;
11 |
12 | public class RNViewConfigurationHelper implements ViewConfigurationHelper {
13 |
14 | @Override
15 | public PointerEventsConfig getPointerEventsConfigForView(View view) {
16 | PointerEvents pointerEvents;
17 | pointerEvents = view instanceof ReactPointerEventsView ?
18 | ((ReactPointerEventsView) view).getPointerEvents() :
19 | PointerEvents.AUTO;
20 |
21 | // Views that are disabled should never be the target of pointer events. However, their children
22 | // can be because some views (SwipeRefreshLayout) use enabled but still have children that can
23 | // be valid targets.
24 | if (!view.isEnabled()) {
25 | if (pointerEvents == PointerEvents.AUTO) {
26 | return PointerEventsConfig.BOX_NONE;
27 | } else if (pointerEvents == PointerEvents.BOX_ONLY) {
28 | return PointerEventsConfig.NONE;
29 | }
30 | }
31 |
32 | switch (pointerEvents) {
33 | case BOX_ONLY: return PointerEventsConfig.BOX_ONLY;
34 | case BOX_NONE: return PointerEventsConfig.BOX_NONE;
35 | case NONE: return PointerEventsConfig.NONE;
36 | }
37 |
38 | return PointerEventsConfig.AUTO;
39 | }
40 |
41 | @Override
42 | public View getChildInDrawingOrderAtIndex(ViewGroup parent, int index) {
43 | if (parent instanceof ReactViewGroup) {
44 | return parent.getChildAt(((ReactViewGroup) parent).getZIndexMappedChildIndex(index));
45 | }
46 | return parent.getChildAt(index);
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/testApp/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
12 |
13 |
19 |
22 |
25 |
26 |
27 |
28 |
34 |
35 |
--------------------------------------------------------------------------------
/testApp/RN_src/gesture/PressBox.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by wuyunqiang on 2018/2/6.
3 | */
4 | import React, { Component } from 'react';
5 | import { Animated,Dimensions,Alert,Text,StyleSheet, View } from 'react-native';
6 | import {
7 | PanGestureHandler,
8 | LongPressGestureHandler,
9 | ScrollView,
10 | State,
11 | TapGestureHandler,
12 | } from 'react-native-gesture-handler';
13 |
14 | export default class PressBox extends Component {
15 | _onHandlerStateChange = event => {
16 | if (event.nativeEvent.state === State.ACTIVE) {
17 | Alert.alert("I'm being pressed for so long");
18 | }
19 | };
20 | _onSingleTap = event => {
21 | if (event.nativeEvent.state === State.ACTIVE) {
22 | Alert.alert("I'm touched");
23 | }
24 | };
25 | _onDoubleTap = event => {
26 | if (event.nativeEvent.state === State.ACTIVE) {
27 | Alert.alert('D0able tap, good job!');
28 | }
29 | };
30 | render() {
31 | return (
32 |
36 |
40 |
44 |
45 |
46 |
47 |
48 | );
49 | }
50 | }
51 |
52 | const styles = StyleSheet.create({
53 | scrollView: {
54 | flex: 1,
55 | },
56 | box: {
57 | width: 150,
58 | height: 150,
59 | alignSelf: 'center',
60 | backgroundColor: 'plum',
61 | margin: 10,
62 | zIndex: 200,
63 | },
64 | });
--------------------------------------------------------------------------------
/testApp/app/src/main/java/com/example/wuyunqiang/testapp/codepush/CodePushConstants.java:
--------------------------------------------------------------------------------
1 | package com.example.wuyunqiang.testapp.codepush;
2 |
3 | public class CodePushConstants {
4 | public static final String ASSETS_BUNDLE_PREFIX = "assets://";
5 | public static final String BINARY_MODIFIED_TIME_KEY = "binaryModifiedTime";
6 | public static final String CODE_PUSH_FOLDER_PREFIX = "CodePush";
7 | public static final String CODE_PUSH_HASH_FILE_NAME = "CodePushHash";
8 | public static final String CODE_PUSH_OLD_HASH_FILE_NAME = "CodePushHash.json";
9 | public static final String CODE_PUSH_PREFERENCES = "CodePush";
10 | public static final String CURRENT_PACKAGE_KEY = "currentPackage";
11 | public static final String DEFAULT_JS_BUNDLE_NAME = "index.android.bundle";
12 | public static final String DIFF_MANIFEST_FILE_NAME = "hotcodepush.json";
13 | public static final int DOWNLOAD_BUFFER_SIZE = 1024 * 256;
14 | public static final String DOWNLOAD_FILE_NAME = "download.zip";
15 | public static final String DOWNLOAD_PROGRESS_EVENT_NAME = "CodePushDownloadProgress";
16 | public static final String DOWNLOAD_URL_KEY = "downloadUrl";
17 | public static final String FAILED_UPDATES_KEY = "CODE_PUSH_FAILED_UPDATES";
18 | public static final String PACKAGE_FILE_NAME = "app.json";
19 | public static final String PACKAGE_HASH_KEY = "packageHash";
20 | public static final String PENDING_UPDATE_HASH_KEY = "hash";
21 | public static final String PENDING_UPDATE_IS_LOADING_KEY = "isLoading";
22 | public static final String PENDING_UPDATE_KEY = "CODE_PUSH_PENDING_UPDATE";
23 | public static final String PREVIOUS_PACKAGE_KEY = "previousPackage";
24 | public static final String REACT_NATIVE_LOG_TAG = "ReactNative";
25 | public static final String RELATIVE_BUNDLE_PATH_KEY = "bundlePath";
26 | public static final String RESOURCES_BUNDLE = "resources.arsc";
27 | public static final String STATUS_FILE = "codepush.json";
28 | public static final String UNZIPPED_FOLDER_NAME = "unzipped";
29 | public static final String CODE_PUSH_APK_BUILD_TIME_KEY = "CODE_PUSH_APK_BUILD_TIME";
30 | public static final String BUNDLE_JWT_FILE = ".codepushrelease";
31 | }
32 |
--------------------------------------------------------------------------------
/testApp/app/src/main/java/com/example/wuyunqiang/testapp/preloadreact/ReactNativePreLoader.java:
--------------------------------------------------------------------------------
1 | package com.example.wuyunqiang.testapp.preloadreact;
2 |
3 | import android.app.Activity;
4 | import android.util.ArrayMap;
5 | import android.util.Log;
6 | import android.view.ViewGroup;
7 |
8 | import com.example.wuyunqiang.testapp.gesture.RNGestureHandlerEnabledRootView;
9 | import com.facebook.react.ReactApplication;
10 |
11 | import java.util.Map;
12 |
13 | /**
14 | * 预加载工具类
15 | * Created by Song on 2017/5/10.
16 | */
17 | public class ReactNativePreLoader {
18 |
19 | private static final Map CACHE = new ArrayMap<>();
20 |
21 | /**
22 | * 初始化ReactRootView,并添加到缓存
23 | * @param activity
24 | * @param componentName
25 | */
26 | public static void preLoad(Activity activity, String componentName) {
27 |
28 | if (CACHE.get(componentName) != null) {
29 | return;
30 | }
31 | // 1.创建ReactRootView
32 | RNGestureHandlerEnabledRootView rootView = new RNGestureHandlerEnabledRootView(activity);
33 | rootView.startReactApplication(
34 | ((ReactApplication) activity.getApplication()).getReactNativeHost().getReactInstanceManager(),
35 | componentName,
36 | null);
37 |
38 | // 2.添加到缓存
39 | CACHE.put(componentName, rootView);
40 | }
41 |
42 | /**
43 | * 获取ReactRootView
44 | * @param componentName
45 | * @return
46 | */
47 | public static RNGestureHandlerEnabledRootView getReactRootView(String componentName) {
48 | return CACHE.get(componentName);
49 | }
50 |
51 | /**
52 | * 从当前界面移除 ReactRootView
53 | * @param component
54 | */
55 | public static void deatchView(String component) {
56 | try {
57 | RNGestureHandlerEnabledRootView rootView = getReactRootView(component);
58 | ViewGroup parent = (ViewGroup) rootView.getParent();
59 | if (parent != null) {
60 | parent.removeView(rootView);
61 | }
62 | } catch (Throwable e) {
63 | Log.e("ReactNativePreLoader",e.getMessage());
64 | }
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/testApp/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | project.ext.react = [
4 | entryFile : "index.js",
5 | nodeExecutableAndArgs: ["/usr/local/bin/node"]//添加node路径
6 | ]
7 |
8 | apply from: "../node_modules/react-native/react.gradle"
9 | apply from: "codepush.gradle"
10 |
11 | def _ext = rootProject.ext
12 | def _glideVersion = _ext.has('glideVersion') ? _ext.glideVersion : '4.7.1'
13 |
14 | android {
15 | compileSdkVersion 26
16 | buildToolsVersion '26.0.2'
17 | defaultConfig {
18 | applicationId "com.example.wuyunqiang.testapp"
19 | minSdkVersion 19
20 | targetSdkVersion 26
21 | versionCode 1
22 | versionName "1.0.1 "
23 | multiDexEnabled true
24 | ndk {
25 | abiFilters "armeabi-v7a", "x86"
26 | }
27 | }
28 |
29 |
30 | signingConfigs {
31 | release {
32 | storeFile file('/Users/wuyunqiang/Desktop/wuyunqiang.jks')
33 | storePassword 'wuyunqiang'
34 | keyAlias 'wuyunqiang'
35 | keyPassword 'wuyunqiang'
36 | }
37 | }
38 |
39 | buildTypes {
40 | release {
41 | minifyEnabled false
42 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
43 | signingConfig signingConfigs.release
44 | }
45 | }
46 | }
47 |
48 | dependencies {
49 | compile 'com.android.support:multidex:1.0.0'
50 | compile 'com.scwang.smartrefresh:SmartRefreshLayout:1.0.4-7'
51 | compile 'com.gyf.barlibrary:barlibrary:2.3.0'
52 | compile ("com.facebook.react:react-native:0.55.4"){force = true} // From node_modules.
53 | compile fileTree(dir: 'libs', include: ['*.jar'])
54 | compile 'com.android.support:appcompat-v7:26.0.0'
55 | compile 'com.android.support.constraint:constraint-layout:1.0.2'
56 |
57 | compile("com.github.bumptech.glide:glide:${_glideVersion}") {
58 | exclude group: "com.android.support"
59 | }
60 | compile("com.github.bumptech.glide:annotations:${_glideVersion}") {
61 | exclude group: "com.android.support"
62 | }
63 | annotationProcessor "com.github.bumptech.glide:compiler:${_glideVersion}"
64 | compile("com.github.bumptech.glide:okhttp3-integration:${_glideVersion}") {
65 | exclude group: "com.android.support"
66 | exclude group: 'glide-parent'
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/testApp/app/src/main/java/com/example/wuyunqiang/testapp/RNFetchBlob/RNFetchBlobConfig.java:
--------------------------------------------------------------------------------
1 | package com.example.wuyunqiang.testapp.RNFetchBlob;
2 |
3 | import com.facebook.react.bridge.ReadableArray;
4 | import com.facebook.react.bridge.ReadableMap;
5 |
6 | import java.util.HashMap;
7 |
8 |
9 | public class RNFetchBlobConfig {
10 |
11 | public Boolean fileCache;
12 | public String path;
13 | public String appendExt;
14 | public ReadableMap addAndroidDownloads;
15 | public Boolean trusty;
16 | public String key;
17 | public String mime;
18 | public Boolean auto;
19 | public Boolean overwrite = true;
20 | public long timeout = 60000;
21 | public Boolean increment = false;
22 | public Boolean followRedirect = true;
23 | public ReadableArray binaryContentTypes = null;
24 |
25 | RNFetchBlobConfig(ReadableMap options) {
26 | if(options == null)
27 | return;
28 | this.fileCache = options.hasKey("fileCache") ? options.getBoolean("fileCache") : false;
29 | this.path = options.hasKey("path") ? options.getString("path") : null;
30 | this.appendExt = options.hasKey("appendExt") ? options.getString("appendExt") : "";
31 | this.trusty = options.hasKey("trusty") ? options.getBoolean("trusty") : false;
32 | if(options.hasKey("addAndroidDownloads")) {
33 | this.addAndroidDownloads = options.getMap("addAndroidDownloads");
34 | }
35 | if(options.hasKey("binaryContentTypes"))
36 | this.binaryContentTypes = options.getArray("binaryContentTypes");
37 | if(this.path != null && path.toLowerCase().contains("?append=true")) {
38 | this.overwrite = false;
39 | }
40 | if(options.hasKey("overwrite"))
41 | this.overwrite = options.getBoolean("overwrite");
42 | if(options.hasKey("followRedirect")) {
43 | this.followRedirect = options.getBoolean("followRedirect");
44 | }
45 | this.key = options.hasKey("key") ? options.getString("key") : null;
46 | this.mime = options.hasKey("contentType") ? options.getString("contentType") : null;
47 | this.increment = options.hasKey("increment") ? options.getBoolean("increment") : false;
48 | this.auto = options.hasKey("auto") ? options.getBoolean("auto") : false;
49 | if(options.hasKey("timeout")) {
50 | this.timeout = options.getInt("timeout");
51 | }
52 | }
53 |
54 | }
55 |
--------------------------------------------------------------------------------
/testApp/app/src/main/java/com/example/wuyunqiang/testapp/fastimage/FastImageViewModule.java:
--------------------------------------------------------------------------------
1 | package com.example.wuyunqiang.testapp.fastimage;
2 | import android.app.Activity;
3 | import android.graphics.Color;
4 | import android.graphics.drawable.ColorDrawable;
5 | import android.graphics.drawable.Drawable;
6 |
7 | import com.bumptech.glide.Glide;
8 | import com.bumptech.glide.Priority;
9 | import com.bumptech.glide.load.engine.DiskCacheStrategy;
10 | import com.bumptech.glide.load.model.GlideUrl;
11 | import com.bumptech.glide.request.RequestOptions;
12 | import com.facebook.react.bridge.ReactApplicationContext;
13 | import com.facebook.react.bridge.ReactContextBaseJavaModule;
14 | import com.facebook.react.bridge.ReactMethod;
15 | import com.facebook.react.bridge.ReadableArray;
16 | import com.facebook.react.bridge.ReadableMap;
17 |
18 | class FastImageViewModule extends ReactContextBaseJavaModule {
19 |
20 | private static final String REACT_CLASS = "FastImageView";
21 |
22 | FastImageViewModule(ReactApplicationContext reactContext) {
23 | super(reactContext);
24 | }
25 |
26 | @Override
27 | public String getName() {
28 | return REACT_CLASS;
29 | }
30 |
31 | private static Drawable TRANSPARENT_DRAWABLE = new ColorDrawable(Color.TRANSPARENT);
32 |
33 | @ReactMethod
34 | public void preload(final ReadableArray sources) {
35 | final Activity activity = getCurrentActivity();
36 | if (activity == null) return;
37 | activity.runOnUiThread(new Runnable() {
38 | @Override
39 | public void run() {
40 | for (int i = 0; i < sources.size(); i++) {
41 | final ReadableMap source = sources.getMap(i);
42 | final GlideUrl glideUrl = FastImageViewConverter.glideUrl(source);
43 | final Priority priority = FastImageViewConverter.priority(source);
44 |
45 | RequestOptions options = new RequestOptions()
46 | .placeholder(TRANSPARENT_DRAWABLE)
47 | .diskCacheStrategy(DiskCacheStrategy.AUTOMATIC)
48 | .priority(priority);
49 |
50 | Glide
51 | .with(activity.getApplicationContext())
52 | .applyDefaultRequestOptions(options)
53 | .load(glideUrl)
54 | .preload();
55 | }
56 | }
57 | });
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/testApp/app/src/main/java/com/example/wuyunqiang/testapp/gesturehandler/LongPressGestureHandler.java:
--------------------------------------------------------------------------------
1 | package com.example.wuyunqiang.testapp.gesturehandler;
2 |
3 | import android.content.Context;
4 | import android.os.Handler;
5 | import android.view.MotionEvent;
6 |
7 | public class LongPressGestureHandler extends GestureHandler {
8 |
9 | private static final long DEFAULT_MIN_DURATION_MS = 1000; // 1 sec
10 | private static float DEFAULT_MAX_DIST_DP = 20; // 20dp
11 |
12 | private long mMinDurationMs = DEFAULT_MIN_DURATION_MS;
13 | private float mMaxDistSq;
14 | private float mStartX, mStartY;
15 | private Handler mHandler;
16 |
17 | public LongPressGestureHandler(Context context) {
18 | setShouldCancelWhenOutside(true);
19 | mMaxDistSq = DEFAULT_MAX_DIST_DP * context.getResources().getDisplayMetrics().density;
20 | }
21 |
22 | public void setMinDurationMs(long minDurationMs) {
23 | mMinDurationMs = minDurationMs;
24 | }
25 |
26 | public LongPressGestureHandler setMaxDist(float maxDist) {
27 | mMaxDistSq = maxDist * maxDist;
28 | return this;
29 | }
30 |
31 | @Override
32 | protected void onHandle(MotionEvent event) {
33 | if (getState() == STATE_UNDETERMINED) {
34 | begin();
35 | mStartX = event.getRawX();
36 | mStartY = event.getRawY();
37 | mHandler = new Handler();
38 | mHandler.postDelayed(new Runnable() {
39 | @Override
40 | public void run() {
41 | activate();
42 | }
43 | }, mMinDurationMs);
44 | }
45 | if (event.getActionMasked() == MotionEvent.ACTION_UP) {
46 | if (mHandler != null) {
47 | mHandler.removeCallbacksAndMessages(null);
48 | mHandler = null;
49 | }
50 | if (getState() == STATE_ACTIVE) {
51 | end();
52 | } else {
53 | fail();
54 | }
55 | } else {
56 | // calculate distance from start
57 | float deltaX = event.getRawX() - mStartX;
58 | float deltaY = event.getRawY() - mStartY;
59 | float distSq = deltaX * deltaX + deltaY * deltaY;
60 | if (distSq > mMaxDistSq) {
61 | if (getState() == STATE_ACTIVE) {
62 | cancel();
63 | } else {
64 | fail();
65 | }
66 | }
67 | }
68 | }
69 |
70 | @Override
71 | protected void onStateChange(int newState, int previousState) {
72 | if (mHandler != null) {
73 | mHandler.removeCallbacksAndMessages(null);
74 | mHandler = null;
75 | }
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/testApp/RN_src/pull/PullLayout.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by wuyunqiang on 2018/1/16.
3 | */
4 | import React, { Component } from 'react';
5 | import {
6 | AppRegistry,
7 | Platform,
8 | StyleSheet,
9 | Text,
10 | View,
11 | ScrollView,
12 | Image,
13 | UIManager,
14 | TouchableOpacity,
15 | NativeModules,
16 | ImageBackground,
17 | DeviceEventEmitter,
18 | requireNativeComponent,
19 | } from 'react-native';
20 | const ReactNative = require('ReactNative');
21 | import PropTypes from 'prop-types';
22 | var PullLayout = requireNativeComponent('PullLayout', App);
23 | export default class App extends Component {
24 | constructor(props){
25 | super(props);
26 | }
27 |
28 | //数据获取后回调 刷新结束
29 | finishRefresh = (key)=>{
30 | Log("结束下拉"+key);
31 | UIManager.dispatchViewManagerCommand(ReactNative.findNodeHandle(this),
32 | UIManager.PullLayout.Commands.FinishRefresh,[key])
33 | };
34 |
35 | render() {
36 | return (
37 | {this.pullLayout = pull}}
39 | style={[{flex: 1,backgroundColor:'white',},this.props.style]}
40 | EnableOverScrollDrag = {true}
41 | EnableOverScrollBounce = {false}
42 | DisableContentWhenRefresh = {false}
43 | onRefreshReleased={this.props.onRefreshReleased}
44 | {...this.props}
45 | >
46 |
47 | {this.props.children}
48 |
49 |
50 | )
51 | }
52 | }
53 |
54 | PullLayout.propTypes = {
55 | ...View.propTypes,
56 | Key:PropTypes.string.isRequired,//必须 否则监听回调可能无法被调用
57 | onRefreshReleased:PropTypes.func,//网络请求加载数据
58 | EnableOverScrollDrag:PropTypes.bool,//设置是否启用越界回弹
59 | EnableOverScrollBounce:PropTypes.bool,//设置是否启用越界拖动(仿苹果效果)
60 | DragRate:PropTypes.number, //显示拖动高度/真实拖动高度(默认0.5,阻尼效果)
61 | HeaderMaxDragRate:PropTypes.number,//设置下拉最大高度和Header高度的比率(将会影响可以下拉的最大高度)
62 | HeaderTriggerRate:PropTypes.number,//设置 触发刷新距离 与 HeaderHieght 的比率
63 | ReboundDuration:PropTypes.number,//设置回弹动画时长
64 | EnableRefresh:PropTypes.bool,//是否启用下拉刷新(默认启用)
65 | EnableHeaderTranslationContent:PropTypes.bool,//设置是否启在下拉Header的同时下拉内容
66 | DisableContentWhenRefresh:PropTypes.bool,//设置是否开启在刷新时候禁止操作内容视图
67 | EnablePureScrollMode:PropTypes.bool,//设置是否开启纯滚动模式
68 | EnableNestedScroll:PropTypes.bool,//设置是会否启用嵌套滚动功能(默认关闭+智能开启)
69 | };
--------------------------------------------------------------------------------
/testApp/app/src/main/java/com/example/wuyunqiang/testapp/gesture/RNGestureHandlerEvent.java:
--------------------------------------------------------------------------------
1 | package com.example.wuyunqiang.testapp.gesture;
2 |
3 | import android.support.v4.util.Pools;
4 |
5 | import com.example.wuyunqiang.testapp.gesturehandler.GestureHandler;
6 | import com.facebook.react.bridge.Arguments;
7 | import com.facebook.react.bridge.WritableMap;
8 | import com.facebook.react.uimanager.events.Event;
9 | import com.facebook.react.uimanager.events.RCTEventEmitter;
10 |
11 | import javax.annotation.Nullable;
12 |
13 | public class RNGestureHandlerEvent extends Event {
14 |
15 | public static final String EVENT_NAME = "topGestureHandlerEvent";
16 | public static final String REGISTRATION_NAME = "onGestureHandlerEvent";
17 |
18 | private static final int TOUCH_EVENTS_POOL_SIZE = 7; // magic
19 |
20 | private static final Pools.SynchronizedPool EVENTS_POOL =
21 | new Pools.SynchronizedPool<>(TOUCH_EVENTS_POOL_SIZE);
22 |
23 | public static RNGestureHandlerEvent obtain(
24 | GestureHandler handler,
25 | @Nullable RNGestureHandlerEventDataExtractor dataExtractor) {
26 | RNGestureHandlerEvent event = EVENTS_POOL.acquire();
27 | if (event == null) {
28 | event = new RNGestureHandlerEvent();
29 | }
30 | event.init(handler, dataExtractor);
31 | return event;
32 | }
33 |
34 | private WritableMap mExtraData;
35 |
36 | private RNGestureHandlerEvent() {
37 | }
38 |
39 | private void init(
40 | GestureHandler handler,
41 | @Nullable RNGestureHandlerEventDataExtractor dataExtractor) {
42 | super.init(handler.getView().getId());
43 | mExtraData = Arguments.createMap();
44 | if (dataExtractor != null) {
45 | dataExtractor.extractEventData(handler, mExtraData);
46 | }
47 | mExtraData.putInt("handlerTag", handler.getTag());
48 | mExtraData.putInt("state", handler.getState());
49 | }
50 |
51 | @Override
52 | public void onDispose() {
53 | mExtraData = null;
54 | EVENTS_POOL.release(this);
55 | }
56 |
57 | @Override
58 | public String getEventName() {
59 | return EVENT_NAME;
60 | }
61 |
62 | @Override
63 | public boolean canCoalesce() {
64 | // TODO: coalescing
65 | return false;
66 | }
67 |
68 | @Override
69 | public short getCoalescingKey() {
70 | // TODO: coalescing
71 | return 0;
72 | }
73 |
74 | @Override
75 | public void dispatch(RCTEventEmitter rctEventEmitter) {
76 | rctEventEmitter.receiveEvent(getViewTag(), EVENT_NAME, mExtraData);
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/testApp/app/src/main/java/com/example/wuyunqiang/testapp/gesture/RNGestureHandlerEnabledRootView.java:
--------------------------------------------------------------------------------
1 | package com.example.wuyunqiang.testapp.gesture;
2 |
3 | import android.content.Context;
4 | import android.os.Bundle;
5 | import android.view.MotionEvent;
6 |
7 | import com.facebook.react.ReactInstanceManager;
8 | import com.facebook.react.ReactRootView;
9 |
10 | import javax.annotation.Nullable;
11 |
12 | public class RNGestureHandlerEnabledRootView extends ReactRootView {
13 |
14 | private @Nullable ReactInstanceManager mReactInstanceManager;
15 | private @Nullable
16 | RNGestureHandlerRootHelper mGestureRootHelper;
17 |
18 | public RNGestureHandlerEnabledRootView(Context context) {
19 | super(context);
20 | }
21 |
22 | @Override
23 | public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {
24 | if (mGestureRootHelper != null) {
25 | mGestureRootHelper.requestDisallowInterceptTouchEvent(disallowIntercept);
26 | }
27 | super.requestDisallowInterceptTouchEvent(disallowIntercept);
28 | }
29 |
30 | @Override
31 | public boolean dispatchTouchEvent(MotionEvent ev) {
32 | if (mGestureRootHelper != null && mGestureRootHelper.dispatchTouchEvent(ev)) {
33 | return true;
34 | }
35 | return super.dispatchTouchEvent(ev);
36 | }
37 |
38 | /**
39 | * This method is used to enable root view to start processing touch events through the gesture
40 | * handler library logic. Unless this method is called (which happens as a result of instantiating
41 | * new gesture handler from JS) the root view component will just proxy all touch related methods
42 | * to its superclass. Thus in the "disabled" state all touch related events will fallback to
43 | * default RN behavior.
44 | */
45 | public void initialize() {
46 | if (mGestureRootHelper != null) {
47 | throw new IllegalStateException("GestureHandler already initialized for root view " + this);
48 | }
49 | mGestureRootHelper = new RNGestureHandlerRootHelper(
50 | mReactInstanceManager.getCurrentReactContext(), this);
51 | }
52 |
53 | public void tearDown() {
54 | if (mGestureRootHelper != null) {
55 | mGestureRootHelper.tearDown();
56 | mGestureRootHelper = null;
57 | }
58 | }
59 |
60 | @Override
61 | public void startReactApplication(
62 | ReactInstanceManager reactInstanceManager,
63 | String moduleName,
64 | @Nullable Bundle initialProperties) {
65 | super.startReactApplication(reactInstanceManager, moduleName, initialProperties);
66 | mReactInstanceManager = reactInstanceManager;
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/testApp/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/testApp/app/src/main/java/com/example/wuyunqiang/testapp/gesture/RNGestureHandlerStateChangeEvent.java:
--------------------------------------------------------------------------------
1 | package com.example.wuyunqiang.testapp.gesture;
2 |
3 | import android.support.v4.util.Pools;
4 |
5 | import com.example.wuyunqiang.testapp.gesturehandler.GestureHandler;
6 | import com.facebook.react.bridge.Arguments;
7 | import com.facebook.react.bridge.WritableMap;
8 | import com.facebook.react.uimanager.events.Event;
9 | import com.facebook.react.uimanager.events.RCTEventEmitter;
10 |
11 | import javax.annotation.Nullable;
12 |
13 | public class RNGestureHandlerStateChangeEvent extends Event{
14 |
15 | public static final String EVENT_NAME = "topGestureHandlerStateChange";
16 | public static final String REGISTRATION_NAME = "onGestureHandlerStateChange";
17 |
18 | private static final int TOUCH_EVENTS_POOL_SIZE = 7; // magic
19 |
20 | private static final Pools.SynchronizedPool EVENTS_POOL =
21 | new Pools.SynchronizedPool<>(TOUCH_EVENTS_POOL_SIZE);
22 |
23 | public static RNGestureHandlerStateChangeEvent obtain(
24 | GestureHandler handler,
25 | int newState,
26 | int oldState,
27 | @Nullable RNGestureHandlerEventDataExtractor dataExtractor) {
28 | RNGestureHandlerStateChangeEvent event = EVENTS_POOL.acquire();
29 | if (event == null) {
30 | event = new RNGestureHandlerStateChangeEvent();
31 | }
32 | event.init(handler, newState, oldState, dataExtractor);
33 | return event;
34 | }
35 |
36 | private WritableMap mExtraData;
37 |
38 | private RNGestureHandlerStateChangeEvent() {
39 | }
40 |
41 | private void init(
42 | GestureHandler handler,
43 | int newState,
44 | int oldState,
45 | @Nullable RNGestureHandlerEventDataExtractor dataExtractor) {
46 | super.init(handler.getView().getId());
47 | mExtraData = Arguments.createMap();
48 | if (dataExtractor != null) {
49 | dataExtractor.extractEventData(handler, mExtraData);
50 | }
51 | mExtraData.putInt("handlerTag", handler.getTag());
52 | mExtraData.putInt("state", newState);
53 | mExtraData.putInt("oldState", oldState);
54 | }
55 |
56 | @Override
57 | public void onDispose() {
58 | mExtraData = null;
59 | EVENTS_POOL.release(this);
60 | }
61 |
62 | @Override
63 | public String getEventName() {
64 | return EVENT_NAME;
65 | }
66 |
67 | @Override
68 | public boolean canCoalesce() {
69 | // TODO: coalescing
70 | return false;
71 | }
72 |
73 | @Override
74 | public short getCoalescingKey() {
75 | // TODO: coalescing
76 | return 0;
77 | }
78 |
79 | @Override
80 | public void dispatch(RCTEventEmitter rctEventEmitter) {
81 | rctEventEmitter.receiveEvent(getViewTag(), EVENT_NAME, mExtraData);
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/testApp/RN_src/page/Pull.js:
--------------------------------------------------------------------------------
1 |
2 | import React, { Component } from 'react';
3 | import {
4 | AppRegistry,
5 | Platform,
6 | StyleSheet,
7 | Text,
8 | Image,
9 | View,
10 | ImageBackground,
11 | TouchableOpacity,
12 | Dimensions,
13 | DeviceEventEmitter, NativeModules
14 | } from 'react-native';
15 | export default class Pull extends Component {
16 |
17 | static navigationOptions = ({navigation})=> ({
18 | header:(
19 |
20 | {
21 | navigation.goBack(null)
22 | // console.log("search",search);
23 | }}>
24 |
25 |
28 |
29 |
30 | )
31 |
32 | })
33 |
34 | constructor(props){
35 | super(props);
36 | }
37 |
38 | render(){
39 | return
40 | this.props.navigation.navigate("PullScrollView")}>
41 |
48 | 测试scrollview下拉刷新
49 |
50 |
51 |
52 | this.props.navigation.navigate("PullFlatList")}>
53 |
60 | 测试flatlist下拉刷新
61 |
62 |
63 |
64 |
65 | }
66 | }
67 |
68 |
69 | const styles = StyleSheet.create({
70 | header: {
71 | flexDirection: 'row',
72 | alignItems: 'flex-end',
73 | height: SCALE(100),
74 | paddingBottom:SCALE(20),
75 | backgroundColor: Color.C5995f5,
76 | borderWidth: 0,
77 | borderBottomWidth: 0,
78 | },
79 | item:{
80 | width:WIDTH,
81 | height:SCALE(100),
82 | justifyContent:'center',
83 | alignItems:'center',
84 | marginVertical:SCALE(50)
85 | }
86 |
87 | });
--------------------------------------------------------------------------------
/testApp/app/src/main/java/com/example/wuyunqiang/testapp/gesturehandler/RotationGestureHandler.java:
--------------------------------------------------------------------------------
1 | package com.example.wuyunqiang.testapp.gesturehandler;
2 |
3 | import android.view.MotionEvent;
4 |
5 | public class RotationGestureHandler extends GestureHandler {
6 |
7 | private static final double ROTATION_RECOGNITION_THRESHOLD = Math.PI / 36.; // 5 deg in radians
8 |
9 | private RotationGestureDetector mRotationGestureDetector;
10 | private double mLastRotation;
11 | private double mLastVelocity;
12 |
13 | private RotationGestureDetector.OnRotationGestureListener mGestureListener = new RotationGestureDetector.OnRotationGestureListener() {
14 |
15 | @Override
16 | public boolean onRotation(RotationGestureDetector detector) {
17 | double prevRotation = mLastRotation;
18 | mLastRotation += detector.getRotation();
19 | long delta = detector.getTimeDelta();
20 | if (delta > 0) {
21 | mLastVelocity = (mLastRotation - prevRotation) / delta;
22 | }
23 | if (Math.abs(mLastRotation) >= ROTATION_RECOGNITION_THRESHOLD && getState() == STATE_BEGAN) {
24 | activate();
25 | }
26 | return true;
27 | }
28 |
29 | @Override
30 | public boolean onRotationBegin(RotationGestureDetector detector) {
31 | return true;
32 | }
33 |
34 | @Override
35 | public void onRotationEnd(RotationGestureDetector detector) {
36 | end();
37 | }
38 | };
39 |
40 | public RotationGestureHandler() {
41 | setShouldCancelWhenOutside(false);
42 | }
43 |
44 | @Override
45 | protected void onHandle(MotionEvent event) {
46 | int state = getState();
47 | if (state == STATE_UNDETERMINED) {
48 | mLastVelocity = 0f;
49 | mLastRotation = 0f;
50 | mRotationGestureDetector = new RotationGestureDetector(mGestureListener);
51 |
52 | begin();
53 | }
54 |
55 | if (mRotationGestureDetector != null) {
56 | mRotationGestureDetector.onTouchEvent(event);
57 | }
58 |
59 | if (event.getActionMasked() == MotionEvent.ACTION_UP) {
60 | if (state == STATE_ACTIVE) {
61 | end();
62 | } else {
63 | fail();
64 | }
65 | }
66 | }
67 |
68 | @Override
69 | protected void onReset() {
70 | mRotationGestureDetector = null;
71 | mLastVelocity = 0f;
72 | mLastRotation = 0f;
73 | }
74 |
75 | public double getRotation() {
76 | return mLastRotation;
77 | }
78 |
79 | public double getVelocity() {
80 | return mLastVelocity;
81 | }
82 |
83 | public float getAnchorX() {
84 | if (mRotationGestureDetector == null) {
85 | return Float.NaN;
86 | }
87 | return mRotationGestureDetector.getAnchorX();
88 | }
89 |
90 | public float getAnchorY() {
91 | if (mRotationGestureDetector == null) {
92 | return Float.NaN;
93 | }
94 | return mRotationGestureDetector.getAnchorY();
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/testApp/app/src/main/java/com/example/wuyunqiang/testapp/gesture/RNGestureHandlerPackage.java:
--------------------------------------------------------------------------------
1 | package com.example.wuyunqiang.testapp.gesture;
2 |
3 | import com.facebook.react.ReactPackage;
4 | import com.facebook.react.bridge.NativeModule;
5 | import com.facebook.react.bridge.ReactApplicationContext;
6 | import com.facebook.react.common.MapBuilder;
7 | import com.facebook.react.uimanager.ThemedReactContext;
8 | import com.facebook.react.uimanager.ViewGroupManager;
9 | import com.facebook.react.uimanager.ViewManager;
10 |
11 | import java.util.Arrays;
12 | import java.util.List;
13 | import java.util.Map;
14 |
15 | import javax.annotation.Nullable;
16 |
17 | public class RNGestureHandlerPackage implements ReactPackage {
18 |
19 | private static class DummyViewManager extends ViewGroupManager {
20 | @Override
21 | public String getName() {
22 | return "GestureHandlerRootView";
23 | }
24 |
25 | @Override
26 | protected RNGestureHandlerRootView createViewInstance(ThemedReactContext reactContext) {
27 | return new RNGestureHandlerRootView(reactContext);
28 | }
29 |
30 | @Override
31 | public void onDropViewInstance(RNGestureHandlerRootView view) {
32 | view.tearDown();
33 | }
34 |
35 | /**
36 | * The following event configuration is necessary even if you are not using
37 | * GestureHandlerRootView component directly.
38 | *
39 | * This direct event configuration serves the purpose of translating event names from
40 | * the names used in native code to "registration names" used in JS. This is necessary for the
41 | * native Animated implementation that has to match events by their names on the native side
42 | * given their "registration names" passed down from JS. For relevant code parts please refer to
43 | * the following react-native core code parts:
44 | * - {@link UIManagerModule.CustomEventNamesResolver}
45 | * - {@link UIManagerModuleConstantsHelper#createConstantsForViewManager}
46 | * - {@link NativeAnimatedNodesManager#handleEvent}
47 | */
48 | @Override
49 | public @Nullable Map getExportedCustomDirectEventTypeConstants() {
50 | return MapBuilder.of(
51 | RNGestureHandlerEvent.EVENT_NAME,
52 | MapBuilder.of("registrationName", RNGestureHandlerEvent.REGISTRATION_NAME),
53 | RNGestureHandlerStateChangeEvent.EVENT_NAME,
54 | MapBuilder.of("registrationName", RNGestureHandlerStateChangeEvent.REGISTRATION_NAME));
55 | }
56 | }
57 |
58 | @Override
59 | public List createNativeModules(ReactApplicationContext reactContext) {
60 | return Arrays.asList(new RNGestureHandlerModule(reactContext));
61 | }
62 |
63 | @Override
64 | public List createViewManagers(ReactApplicationContext reactContext) {
65 | return Arrays.asList(
66 | new RNGestureHandlerButtonViewManager(),
67 | new DummyViewManager());
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/testApp/app/src/main/java/com/example/wuyunqiang/testapp/fastimage/FastImageViewConverter.java:
--------------------------------------------------------------------------------
1 | package com.example.wuyunqiang.testapp.fastimage;
2 | import android.widget.ImageView;
3 | import android.widget.ImageView.ScaleType;
4 |
5 | import com.bumptech.glide.Priority;
6 | import com.bumptech.glide.load.model.GlideUrl;
7 | import com.bumptech.glide.load.model.LazyHeaders;
8 | import com.facebook.react.bridge.NoSuchKeyException;
9 | import com.facebook.react.bridge.ReadableMap;
10 | import com.facebook.react.bridge.ReadableMapKeySetIterator;
11 |
12 | import java.util.HashMap;
13 | import java.util.Map;
14 |
15 | class FastImageViewConverter {
16 | static GlideUrl glideUrl(ReadableMap source) {
17 | final String uriProp = source.getString("uri");
18 | // Get the headers prop and add to glideUrl.
19 | GlideUrl glideUrl;
20 | try {
21 | final ReadableMap headersMap = source.getMap("headers");
22 | ReadableMapKeySetIterator headersIterator = headersMap.keySetIterator();
23 | LazyHeaders.Builder headersBuilder = new LazyHeaders.Builder();
24 | while (headersIterator.hasNextKey()) {
25 | String key = headersIterator.nextKey();
26 | String value = headersMap.getString(key);
27 | headersBuilder.addHeader(key, value);
28 | }
29 | LazyHeaders headers = headersBuilder.build();
30 | glideUrl = new GlideUrl(uriProp, headers);
31 | } catch (NoSuchKeyException e) {
32 | // If there is no headers object.
33 | glideUrl = new GlideUrl(uriProp);
34 | }
35 | return glideUrl;
36 | }
37 |
38 | private static Map REACT_PRIORITY_MAP =
39 | new HashMap() {{
40 | put("low", Priority.LOW);
41 | put("normal", Priority.NORMAL);
42 | put("high", Priority.HIGH);
43 | }};
44 |
45 | static Priority priority(ReadableMap source) {
46 | // Get the priority prop.
47 | String priorityProp = "normal";
48 | try {
49 | priorityProp = source.getString("priority");
50 | } catch (Exception e) {
51 | // Noop.
52 | }
53 | final Priority priority = REACT_PRIORITY_MAP.get(priorityProp);
54 | return priority;
55 | }
56 |
57 | private static Map REACT_RESIZE_MODE_MAP =
58 | new HashMap() {{
59 | put("contain", ScaleType.FIT_CENTER);
60 | put("cover", ScaleType.CENTER_CROP);
61 | put("stretch", ScaleType.FIT_XY);
62 | put("center", ScaleType.CENTER);
63 | }};
64 |
65 | public static ScaleType scaleType(String resizeMode) {
66 | if (resizeMode == null) resizeMode = "cover";
67 | final ImageView.ScaleType scaleType = REACT_RESIZE_MODE_MAP.get(resizeMode);
68 | return scaleType;
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/testApp/RN_src/gesture/draggable.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { Animated, StyleSheet, View } from 'react-native';
3 |
4 | import {
5 | PanGestureHandler,
6 | ScrollView,
7 | State,
8 | } from 'react-native-gesture-handler';
9 | const USE_NATIVE_DRIVER={
10 | USE_NATIVE_DRIVER: true,
11 | };
12 |
13 | export default class DraggableBox extends Component {
14 | constructor(props) {
15 | super(props);
16 | this._translateX = new Animated.Value(0);
17 | this._translateY = new Animated.Value(0);
18 | this._lastOffset = { x: 0, y: 0 };
19 | this._onGestureEvent = Animated.event(
20 | [
21 | {
22 | nativeEvent: {
23 | // translationX: this._translateX,
24 | translationY: this._translateY,
25 | },
26 | },
27 | ],
28 | { useNativeDriver: USE_NATIVE_DRIVER }
29 | );
30 | }
31 | _onHandlerStateChange = event => {
32 | console.log('_onHandlerStateChange oldState',event.nativeEvent);
33 | if (event.nativeEvent.oldState === State.ACTIVE) {
34 | // this._lastOffset.x += event.nativeEvent.translationX;
35 | this._lastOffset.y += event.nativeEvent.translationY;
36 | // this._translateX.setOffset(this._lastOffset.x);
37 | this._translateX.setValue(0);
38 | this._translateY.setOffset(this._lastOffset.y);
39 | this._translateY.setValue(0);
40 | }
41 | };
42 |
43 | begin=(event)=>{
44 | console.log('onBegin event',event.nativeEvent);
45 | };
46 |
47 | failed =(event)=>{
48 | console.log('failed event',event.nativeEvent);
49 | }
50 |
51 | cancel = (event)=>{
52 | console.log('cancel event',event.nativeEvent);
53 | }
54 |
55 | activaty = (event)=>{
56 | console.log('activaty event',event.nativeEvent);
57 | }
58 |
59 | end = (event)=>{
60 | console.log('end event',event.nativeEvent);
61 | }
62 |
63 | render() {
64 | return (
65 |
75 |
86 |
87 | );
88 | }
89 | }
90 |
91 | const styles = StyleSheet.create({
92 | scrollView: {
93 | flex: 1,
94 | },
95 | box: {
96 | width: 150,
97 | height: 150,
98 | alignSelf: 'center',
99 | backgroundColor: 'plum',
100 | margin: 10,
101 | zIndex: 200,
102 | },
103 | });
104 |
--------------------------------------------------------------------------------
/testApp/app/src/main/java/com/example/wuyunqiang/testapp/view/ModalHostHelper.java:
--------------------------------------------------------------------------------
1 | // Copyright 2004-present Facebook. All Rights Reserved.
2 |
3 | package com.example.wuyunqiang.testapp.view;
4 |
5 | import android.annotation.TargetApi;
6 | import android.content.Context;
7 | import android.content.res.Resources;
8 | import android.content.res.TypedArray;
9 | import android.graphics.Point;
10 | import android.view.Display;
11 | import android.view.WindowManager;
12 |
13 | import com.facebook.infer.annotation.Assertions;
14 |
15 | /**
16 | * Helper class for Modals.
17 | */
18 | /*package*/ class ModalHostHelper {
19 |
20 | private static final Point MIN_POINT = new Point();
21 | private static final Point MAX_POINT = new Point();
22 | private static final Point SIZE_POINT = new Point();
23 |
24 | /**
25 | * To get the size of the screen, we use information from the WindowManager and
26 | * default Display. We don't use DisplayMetricsHolder, or Display#getSize() because
27 | * they return values that include the status bar. We only want the values of what
28 | * will actually be shown on screen.
29 | * We use Display#getSize() to determine if the screen is in portrait or landscape.
30 | * We don't use getRotation because the 'natural' rotation will be portrait on phones
31 | * and landscape on tablets.
32 | * This should only be called on the native modules/shadow nodes thread.
33 | */
34 | @TargetApi(16)
35 | public static Point getModalHostSize(Context context) {
36 | WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
37 | Display display = Assertions.assertNotNull(wm).getDefaultDisplay();
38 | // getCurrentSizeRange will return the min and max width and height that the window can be
39 | display.getCurrentSizeRange(MIN_POINT, MAX_POINT);
40 | // getSize will return the dimensions of the screen in its current orientation
41 | display.getSize(SIZE_POINT);
42 |
43 | int[] attrs = {android.R.attr.windowFullscreen};
44 | Resources.Theme theme = context.getTheme();
45 | TypedArray ta = theme.obtainStyledAttributes(attrs);
46 | boolean windowFullscreen = ta.getBoolean(0, false);
47 |
48 | // We need to add the status bar height to the height if we have a fullscreen window,
49 | // because Display.getCurrentSizeRange doesn't include it.
50 | Resources resources = context.getResources();
51 | int statusBarId = resources.getIdentifier("status_bar_height", "dimen", "android");
52 | int statusBarHeight = 0;
53 | if (windowFullscreen && statusBarId > 0) {
54 | statusBarHeight = (int) resources.getDimension(statusBarId);
55 | }
56 |
57 | if (SIZE_POINT.x < SIZE_POINT.y) {
58 | // If we are vertical the width value comes from min width and height comes from max height
59 | return new Point(MIN_POINT.x, MAX_POINT.y + statusBarHeight);
60 | } else {
61 | // If we are horizontal the width value comes from max width and height comes from min height
62 | return new Point(MAX_POINT.x, MIN_POINT.y + statusBarHeight);
63 | }
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/testApp/app/src/main/java/com/example/wuyunqiang/testapp/fastimage/FastImageRequestListener.java:
--------------------------------------------------------------------------------
1 | package com.example.wuyunqiang.testapp.fastimage;
2 | import android.graphics.drawable.Drawable;
3 |
4 | import com.bumptech.glide.load.DataSource;
5 | import com.bumptech.glide.load.engine.GlideException;
6 | import com.bumptech.glide.request.RequestListener;
7 | import com.bumptech.glide.request.target.ImageViewTarget;
8 | import com.bumptech.glide.request.target.Target;
9 | import com.facebook.react.bridge.WritableMap;
10 | import com.facebook.react.bridge.WritableNativeMap;
11 | import com.facebook.react.uimanager.ThemedReactContext;
12 | import com.facebook.react.uimanager.events.RCTEventEmitter;
13 |
14 | public class FastImageRequestListener implements RequestListener {
15 | static final String REACT_ON_ERROR_EVENT = "onFastImageError";
16 | static final String REACT_ON_LOAD_EVENT = "onFastImageLoad";
17 | static final String REACT_ON_LOAD_END_EVENT = "onFastImageLoadEnd";
18 |
19 | private String key = null;
20 |
21 | FastImageRequestListener(String key) {
22 | this.key = key;
23 | }
24 |
25 | private static WritableMap mapFromResource(Drawable resource) {
26 | WritableMap resourceData = new WritableNativeMap();
27 | resourceData.putInt("width", resource.getIntrinsicWidth());
28 | resourceData.putInt("height", resource.getIntrinsicHeight());
29 | return resourceData;
30 | }
31 |
32 | @Override
33 | public boolean onLoadFailed(@android.support.annotation.Nullable GlideException e, Object model, Target target, boolean isFirstResource) {
34 | FastImageOkHttpProgressGlideModule.forget(key);
35 | if (!(target instanceof ImageViewTarget)) {
36 | return false;
37 | }
38 | FastImageViewWithUrl view = (FastImageViewWithUrl) ((ImageViewTarget) target).getView();
39 | ThemedReactContext context = (ThemedReactContext) view.getContext();
40 | RCTEventEmitter eventEmitter = context.getJSModule(RCTEventEmitter.class);
41 | int viewId = view.getId();
42 | eventEmitter.receiveEvent(viewId, REACT_ON_ERROR_EVENT, new WritableNativeMap());
43 | eventEmitter.receiveEvent(viewId, REACT_ON_LOAD_END_EVENT, new WritableNativeMap());
44 | return false;
45 | }
46 |
47 | @Override
48 | public boolean onResourceReady(Drawable resource, Object model, Target target, DataSource dataSource, boolean isFirstResource) {
49 | if (!(target instanceof ImageViewTarget)) {
50 | return false;
51 | }
52 | FastImageViewWithUrl view = (FastImageViewWithUrl) ((ImageViewTarget) target).getView();
53 | ThemedReactContext context = (ThemedReactContext) view.getContext();
54 | RCTEventEmitter eventEmitter = context.getJSModule(RCTEventEmitter.class);
55 | int viewId = view.getId();
56 | eventEmitter.receiveEvent(viewId, REACT_ON_LOAD_EVENT, mapFromResource(resource));
57 | eventEmitter.receiveEvent(viewId, REACT_ON_LOAD_END_EVENT, new WritableNativeMap());
58 | return false;
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/testApp/RN_src/data/common.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Text, StyleSheet } from 'react-native';
3 |
4 | const styles = StyleSheet.create({
5 | lipsum: {
6 | padding: 10,
7 | },
8 | });
9 |
10 | export class LoremIpsum extends React.Component {
11 | static defaultProps = {
12 | words: 1000,
13 | style: styles.lipsum,
14 | };
15 | loremIpsum() {
16 | return LOREM_IPSUM.split(' ').slice(0, this.props.words).join(' ');
17 | }
18 | render() {
19 | return (
20 |
21 | {this.loremIpsum()}
22 |
23 | );
24 | }
25 | }
26 |
27 | const LOREM_IPSUM = `
28 | Curabitur accumsan sit amet massa quis cursus. Fusce sollicitudin nunc nisl, quis efficitur quam tristique eget. Ut non erat molestie, ullamcorper turpis nec, euismod neque. Praesent aliquam risus ultricies, cursus mi consectetur, bibendum lorem. Nunc eleifend consectetur metus quis pulvinar. In vitae lacus eu nibh tincidunt sagittis ut id lorem. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Quisque sagittis mauris rhoncus, maximus justo in, consequat dolor. Pellentesque ornare laoreet est vulputate vestibulum. Aliquam sit amet metus lorem.
29 |
30 | Morbi tempus elit lorem, ut pulvinar nunc sagittis pharetra. Nulla mi sem, elementum non bibendum eget, viverra in purus. Vestibulum efficitur ex id nisi luctus egestas. Quisque in urna vitae leo consectetur ultricies sit amet at nunc. Cras porttitor neque at nisi ornare, mollis ornare dolor pharetra. Donec iaculis lacus orci, et pharetra eros imperdiet nec. Morbi leo nunc, placerat eget varius nec, volutpat ac velit. Phasellus pulvinar vulputate tincidunt. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Fusce elementum dui at ipsum hendrerit, vitae consectetur erat pulvinar. Sed vehicula sapien felis, id tristique dolor tempor feugiat. Aenean sit amet erat libero.
31 |
32 | Nam posuere at mi ut porttitor. Vivamus dapibus vehicula mauris, commodo pretium nibh. Mauris turpis metus, vulputate iaculis nibh eu, maximus tincidunt nisl. Vivamus in mauris nunc. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse convallis ornare finibus. Quisque leo ex, vulputate quis molestie auctor, congue nec arcu.
33 |
34 | Praesent ac risus nec augue commodo semper eu eget quam. Donec aliquam sodales convallis. Etiam interdum eu nulla at tempor. Duis nec porttitor odio, consectetur tempor turpis. Sed consequat varius lorem vel fermentum. Maecenas dictum sapien vitae lobortis tempus. Aliquam iaculis vehicula velit, non tempus est varius nec. Nunc congue dolor nec sem gravida, nec tincidunt mi luctus. Nam ut porttitor diam.
35 |
36 | Fusce interdum nisi a risus aliquet, non dictum metus cursus. Praesent imperdiet sapien orci, quis sodales metus aliquet id. Aliquam convallis pharetra erat. Fusce gravida diam ut tellus elementum sodales. Fusce varius congue neque, quis laoreet sapien blandit vestibulum. Donec congue libero sapien, nec varius risus viverra ut. Quisque eu maximus magna. Phasellus tortor nisi, tincidunt vitae dignissim nec, interdum vel mi. Ut accumsan urna finibus posuere mattis.
37 | `;
38 |
--------------------------------------------------------------------------------
/testApp/app/src/main/java/com/example/wuyunqiang/testapp/activity/TestActivity.java:
--------------------------------------------------------------------------------
1 | package com.example.wuyunqiang.testapp.activity;
2 |
3 | import android.content.Intent;
4 | import android.graphics.Color;
5 | import android.os.Bundle;
6 | import android.util.Log;
7 | import android.view.LayoutInflater;
8 | import android.view.View;
9 | import android.widget.LinearLayout;
10 |
11 | import com.example.wuyunqiang.testapp.MyReactActivity;
12 | import com.example.wuyunqiang.testapp.R;
13 | import com.example.wuyunqiang.testapp.preloadreact.ReactNativePreLoader;
14 | import com.facebook.react.ReactActivity;
15 | import com.facebook.react.ReactRootView;
16 |
17 | import javax.annotation.Nullable;
18 |
19 | public class TestActivity extends ReactActivity {
20 |
21 |
22 | static final String TAG = "TestActivity";
23 | private ReactRootView mReactRootView;
24 |
25 | @Nullable
26 | @Override
27 | protected String getMainComponentName() {
28 | return "TestActivity";
29 | }
30 |
31 | @Override
32 | protected void onCreate(Bundle savedInstanceState) {
33 | super.onCreate(savedInstanceState);
34 |
35 | LinearLayout root = new LinearLayout(this);//根视图
36 | LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.MATCH_PARENT);
37 | root.setLayoutParams(params);
38 | root.setBackgroundColor(Color.CYAN);
39 | root.setOrientation(LinearLayout.VERTICAL);
40 |
41 | //加载原生视图
42 | LinearLayout nativeroot = (LinearLayout) LayoutInflater.from(this).inflate(R.layout.activity_test,null);
43 | root.addView(nativeroot);
44 |
45 | //实例化rn视图
46 | mReactRootView = ReactNativePreLoader.getReactRootView("TestActivity");
47 | if(mReactRootView==null){
48 | mReactRootView = new ReactRootView(this);
49 | mReactRootView.startReactApplication(
50 | getReactInstanceManager(),
51 | "TestActivity",
52 | null);
53 | }
54 |
55 | LinearLayout rnroot = new LinearLayout(this);
56 | rnroot.setLayoutParams(params);
57 | rnroot.addView(mReactRootView);
58 | rnroot.setOrientation(LinearLayout.VERTICAL);
59 |
60 | root.addView(rnroot);
61 | setContentView(root);
62 | }
63 |
64 |
65 | @Override
66 | protected void onDestroy() {
67 | super.onDestroy();
68 | ReactNativePreLoader.deatchView("TestActivity");
69 | Log.i(TAG,"onDestroy");
70 | }
71 |
72 | @Override
73 | public void onBackPressed() {
74 | super.onBackPressed();
75 | Log.i(TAG,"onBackPressed");
76 | this.finish();
77 | overridePendingTransition(R.anim.slide_in_left,R.anim.slide_out_left);
78 | }
79 |
80 | public void onClick(View view) {
81 | if(view.getId()==R.id.roRN){
82 | Intent it = new Intent(this,MyReactActivity.class);
83 | it.putExtra("name","wuyunqiang");
84 | startActivity(it);
85 | overridePendingTransition(R.anim.slide_in_right,R.anim.slide_out_right);
86 | }
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/testApp/app/src/main/java/com/example/wuyunqiang/testapp/gesture/RNGestureHandlerInteractionManager.java:
--------------------------------------------------------------------------------
1 | package com.example.wuyunqiang.testapp.gesture;
2 |
3 | import android.util.SparseArray;
4 |
5 | import com.example.wuyunqiang.testapp.gesturehandler.GestureHandler;
6 | import com.example.wuyunqiang.testapp.gesturehandler.GestureHandlerInteractionController;
7 | import com.facebook.react.bridge.ReadableArray;
8 | import com.facebook.react.bridge.ReadableMap;
9 |
10 | public class RNGestureHandlerInteractionManager implements GestureHandlerInteractionController {
11 |
12 | private static final String KEY_WAIT_FOR = "waitFor";
13 | private static final String KEY_SIMULTANEOUS_HANDLERS = "simultaneousHandlers";
14 |
15 | private SparseArray mWaitForRelations = new SparseArray<>();
16 | private SparseArray mSimultaneousRelations = new SparseArray<>();
17 |
18 | public void dropRelationsForHandlerWithTag(int handlerTag) {
19 | mWaitForRelations.remove(handlerTag);
20 | mSimultaneousRelations.remove(handlerTag);
21 | }
22 |
23 | private int[] convertHandlerTagsArray(ReadableMap config, String key) {
24 | ReadableArray array = config.getArray(key);
25 | int[] result = new int[array.size()];
26 | for (int i = 0; i < result.length; i++) {
27 | result[i] = array.getInt(i);
28 | }
29 | return result;
30 | }
31 |
32 | public void configureInteractions(GestureHandler handler, ReadableMap config) {
33 | handler.setInteractionController(this);
34 | if (config.hasKey(KEY_WAIT_FOR)) {
35 | int[] tags = convertHandlerTagsArray(config, KEY_WAIT_FOR);
36 | mWaitForRelations.put(handler.getTag(), tags);
37 | }
38 | if (config.hasKey(KEY_SIMULTANEOUS_HANDLERS)) {
39 | int[] tags = convertHandlerTagsArray(config, KEY_SIMULTANEOUS_HANDLERS);
40 | mSimultaneousRelations.put(handler.getTag(), tags);
41 | }
42 | }
43 |
44 | @Override
45 | public boolean shouldWaitForHandlerFailure(GestureHandler handler, GestureHandler otherHandler) {
46 | int[] waitForTags = mWaitForRelations.get(handler.getTag());
47 | if (waitForTags != null) {
48 | for (int i = 0; i < waitForTags.length; i++) {
49 | if (waitForTags[i] == otherHandler.getTag()) {
50 | return true;
51 | }
52 | }
53 | }
54 | return false;
55 | }
56 |
57 | @Override
58 | public boolean shouldRequireHandlerToWaitForFailure(GestureHandler handler,
59 | GestureHandler otherHandler) {
60 | return false;
61 | }
62 |
63 | @Override
64 | public boolean shouldHandlerBeCancelledBy(GestureHandler handler, GestureHandler otherHandler) {
65 | return false;
66 | }
67 |
68 | @Override
69 | public boolean shouldRecognizeSimultaneously(GestureHandler handler,
70 | GestureHandler otherHandler) {
71 | int[] simultHandlerTags = mSimultaneousRelations.get(handler.getTag());
72 | if (simultHandlerTags != null) {
73 | for (int i = 0; i < simultHandlerTags.length; i++) {
74 | if (simultHandlerTags[i] == otherHandler.getTag()) {
75 | return true;
76 | }
77 | }
78 | }
79 | return false;
80 | }
81 |
82 | public void reset() {
83 | mWaitForRelations.clear();
84 | mSimultaneousRelations.clear();
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/testApp/RN_src/gesture/TapOrPan.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by wuyunqiang on 2018/2/6.
3 | */
4 | import React, { Component } from 'react';
5 | import { Animated,Dimensions,Alert,Text,StyleSheet, View } from 'react-native';
6 | import {
7 | PanGestureHandler,
8 | LongPressGestureHandler,
9 | ScrollView,
10 | State,
11 | TapGestureHandler,
12 | } from 'react-native-gesture-handler';
13 | const circleRadius = 30;
14 | const USE_NATIVE_DRIVER={
15 | USE_NATIVE_DRIVER: true,
16 | };
17 | export default class TapOrPan extends Component {
18 | constructor(props) {
19 | super(props);
20 | this._touchX = new Animated.Value(WIDTH / 2 - circleRadius);
21 | this._translateX = Animated.add(
22 | this._touchX,
23 | new Animated.Value(-circleRadius)
24 | );
25 | this._onPanGestureEvent = Animated.event(
26 | [
27 | {
28 | nativeEvent: {
29 | x: this._touchX,
30 | },
31 | },
32 | ],
33 |
34 | );
35 | }
36 |
37 | _onTapHandlerStateChange = ({ nativeEvent }) => {
38 | if (nativeEvent.oldState === State.ACTIVE) {
39 | // Once tap happened we set the position of the circle under the tapped spot
40 | this._touchX.setValue(nativeEvent.x);
41 | }
42 | };
43 |
44 | render() {
45 | return (
46 |
51 |
56 |
57 |
69 |
70 |
71 |
72 | );
73 | }
74 | }
75 |
76 |
77 | const styles = StyleSheet.create({
78 | scrollView: {
79 | flex: 1,
80 | },
81 | box: {
82 | width: 150,
83 | height: 150,
84 | alignSelf: 'center',
85 | backgroundColor: 'plum',
86 | margin: 10,
87 | zIndex: 200,
88 | },
89 | horizontalPan: {
90 | backgroundColor: '#f48fb1',
91 | height: 150,
92 | justifyContent: 'center',
93 | marginVertical: 10,
94 | },
95 | circle: {
96 | backgroundColor: '#42a5f5',
97 | borderRadius: circleRadius,
98 | height: circleRadius * 2,
99 | width: circleRadius * 2,
100 | },
101 | });
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # AndroidToRN
2 | 1:原生android中嵌入React Native
3 | 2:封装原生view,viewgroup,原生module
4 | 3:使用codepush热更新
5 | 4:react navigation自定义tab实现凸起
6 | 5:下拉刷新+无限列表+大量图片
7 | 6:statusbar颜色+图片
8 | 7:modal通过原生popwindow实现全屏,解决status覆盖问题
9 | 8:集成redux
10 |
11 | # 环境:
12 | Android studio3.0
13 | react native 0.55.4
14 | Mac 10.12.6
15 | # 如有问题或者需要我添加什么请提issue,我会去实现的
16 |
17 | CSDN:[http://blog.csdn.net/u014041033?viewmode=contents](http://blog.csdn.net/u014041033?viewmode=contents)
18 | 简书:[简书](http://www.jianshu.com/u/1386d6b454e5)
19 |
20 | 项目下载后
21 | 1: cd testApp
22 | 2: yarn install
23 | 3: npm start
24 | 4: android studio打开项目testApp 报错
25 | 
26 | 5:按照[codepush3之Android原生引用集成codepush](http://blog.csdn.net/u014041033/article/details/79004351)所示修改路径
27 | 或者如下修改
28 | change react.gradle的14行reactRoot路径
29 | 
30 | 6:andorid studio 运行项目即可
31 |
32 | # ChangeLog:
33 | 1.0.6
34 | 
35 | 
36 |
37 | 1.0.5
38 | 原生下拉刷新+大列表(Flatlist||SGListView)+大量图片 不会卡顿
39 | 
40 |
41 | 1.0.4
42 | 1:新增pullLayout->此组件是原生下拉刷新组件的封装(因为android下拉刷新组件一直存在性能问题所以自己封装了一个)
43 | 组件基于[SmartRefreshLayout](https://github.com/wuyunqiang/react-native-pullview)仅限Android使用
44 | 效果如下:
45 | 
46 |
47 | 1.0.3
48 | 1:添加下拉刷新[react-native-pullview](https://github.com/wuyunqiang/react-native-pullview)
49 | 2:添加自定义Tab
50 | 效果:
51 | 
52 | 
53 |
54 |
55 | 1.0.2
56 | 纯原生->一半rn一半原生->纯rn
57 | 效果:
58 | 
59 |
60 |
61 | 1.0.1
62 | 1:添加react navigation可以跳转页面
63 | 2:添加code push(bug fixed) 有关codepush问题https://github.com/wuyunqiang/ReactNativeUtil/issues/26
64 | 3:优化添加预加载reactnative页面 (参考:https://github.com/songxiaoliang/ReactNativeApp)
65 |
66 |
67 | 运行效果:
68 | 
69 |
70 | 代码仅供参考:
71 | 如要运行,需要下载node_modules。
72 | 另外本人在学习的过程中遇到很多坑,深知找解决问题的路途艰难险阻
73 | 所以我正在做一个收集react native的bug解决+工具的库,
74 | 希望可以帮助大家在学习中更有效率的写代码。
75 | 详情[ReactNativeUtil](https://github.com/wuyunqiang/ReactNativeUtil)
76 | 通过label搜索关键字,也欢迎大家丰富内容。
77 |
78 |
--------------------------------------------------------------------------------
/testApp/app/src/main/res/layout/share.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
12 |
13 |
18 |
28 |
32 |
39 |
40 |
44 |
45 |
55 |
59 |
65 |
66 |
67 |
68 |
72 |
78 |
84 |
85 |
86 |
--------------------------------------------------------------------------------
/testApp/RN_src/pull/LoadingSpinner.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from "react";
2 | import {Dimensions, ActivityIndicator,View, Text} from "react-native";
3 | const {width, height} = Dimensions.get('window');
4 | export default class LoadingSpinner extends Component {
5 |
6 | static defaultProps = {
7 | width: width,
8 | height: height,
9 | spinnerColor: 'white',
10 | textColor: 'white',
11 | text: '努力加载中...',
12 | backgroundColor:'transparent'
13 | };
14 |
15 | render() {
16 | if(this.props.type==='normal'){
17 | return (
18 |
19 |
20 |
21 | {this.props.text}
22 |
23 |
24 | )
25 | }else if(this.props.type==='bottom'){
26 | return (
27 |
28 |
29 | {this.props.text}
30 |
31 | )
32 | }else if(this.props.type==='allLoaded'){
33 | return (没有更多数据了)
34 | } else if(this.props.type==='home'){
35 | return (
36 |
37 | );
38 |
39 | }else{
40 | return (
41 |
52 |
58 |
59 | {this.props.text}
60 |
61 |
62 | );
63 | }
64 |
65 | }
66 | }
67 |
68 | const styles = {
69 | allLoaded:{
70 | marginLeft: SCALE(20),
71 | marginRight: SCALE(20),
72 | justifyContent:'center',
73 | alignItems:'center',
74 | height:SCALE(100),
75 | backgroundColor:Color.f3f3f3,
76 | },
77 | statusText:{
78 | backgroundColor:'transparent',
79 | fontSize:FONT(13),
80 | color:Color.C333333,
81 | }
82 | };
83 |
--------------------------------------------------------------------------------
/testApp/RN_src/pull/PullView.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | import React, { Component } from 'react';
4 | import {
5 | Platform,
6 | ScrollView,
7 | } from 'react-native';
8 | import Pullable from './Pullable';
9 |
10 | /**
11 | 支持android&ios可以下拉刷新的PullView组件
12 | Demo:
13 | import {PullView} from 'react-native-pullview';
14 |
15 | {}} topIndicatorHeight={60}
17 | >
18 |
19 | Demo2:
20 | topIndicatorRender(pulling, pullok, pullrelease) {
21 | return
22 |
23 | {pulling ? 下拉刷新2... : null}
24 | {pullok ? 松开刷新2...... : null}
25 | {pullrelease ? 玩命刷新中2...... : null}
26 | ;
27 | }
28 |
29 |
30 |
31 |
32 | Demo3:
33 |
34 | onRefresh() {
35 | this.setState({refreshing: true});
36 | return new Promise((resolve) => {
37 | setTimeout(() => {resolve()}, 9000);
38 | }).then(() => {
39 | this.setState({refreshing: false})
40 | })
41 | // setTimeout(() => {
42 | // this.setState({refreshing: false});
43 | // }, 3000);
44 | }
45 |
46 |
47 |
48 | */
49 |
50 | export default class extends Pullable {
51 | constructor(props) {
52 | super(props);
53 | this.state = {
54 | ...this.BaseState,
55 | };
56 | const defaultFlag = {pulling: false, pullok: false, pullrelease: false};
57 | this.setFlag(defaultFlag);
58 | this.scrollTo = this.scrollTo.bind(this);
59 | this.scrollToEnd = this.scrollToEnd.bind(this);
60 | this.type='View';
61 | }
62 |
63 | scrollTo(...args) {
64 | this.scroll&&this.scroll.scrollTo(...args);
65 | }
66 |
67 | scrollToEnd(args) {
68 | this.scroll&&this.scroll.scrollTo(args);
69 | }
70 |
71 | onContentSizeChange = (contentWidth, contentHeight)=>{
72 | Log('contentWidth',contentWidth);
73 | Log('contentHeight',contentHeight);
74 | Log('Height',HEIGHT);
75 | this.type='View';
76 | if(contentHeight {this.scroll = c;}}
87 | refreshControl={refreshControl}
88 | onScroll={this.onScroll}
89 | scrollEnabled={Platform.OS==='android'?this.state.scrollEnabled:true}
90 | scrollEventThrottle={16}
91 | onContentSizeChange = {this.onContentSizeChange}
92 | {...this.props}
93 | >
94 | {this.props.children}
95 |
96 | );
97 | }
98 |
99 | }
100 |
--------------------------------------------------------------------------------
/testApp/app/src/main/java/com/example/wuyunqiang/testapp/MainApplication.java:
--------------------------------------------------------------------------------
1 | package com.example.wuyunqiang.testapp;
2 |
3 | import android.app.Application;
4 | import android.content.Context;
5 | import android.support.multidex.MultiDex;
6 | import android.util.Log;
7 |
8 | import com.example.wuyunqiang.testapp.RNFetchBlob.RNFetchBlobPackage;
9 | import com.example.wuyunqiang.testapp.codepush.CodePush;
10 | import com.example.wuyunqiang.testapp.fastimage.FastImageViewPackage;
11 | import com.example.wuyunqiang.testapp.gesture.RNGestureHandlerPackage;
12 | import com.facebook.react.ReactApplication;
13 | import com.facebook.react.ReactNativeHost;
14 | import com.facebook.react.ReactPackage;
15 | import com.facebook.react.shell.MainReactPackage;
16 | import com.facebook.soloader.SoLoader;
17 |
18 | import java.util.ArrayList;
19 | import java.util.List;
20 |
21 | import javax.annotation.Nullable;
22 |
23 | /**
24 | * Created by wuyunqiang on 2017/12/25.
25 | */
26 |
27 | public class MainApplication extends Application implements ReactApplication {
28 |
29 | public static String TAG = "MainApplication";
30 | private static MainApplication instance;
31 |
32 | @Override
33 | public void onCreate() {
34 | super.onCreate();
35 | instance = this;
36 | Log.i(TAG,"onCreate");
37 | SoLoader.init(this,false);
38 | }
39 |
40 | @Override
41 | protected void attachBaseContext(Context base) {
42 | super.attachBaseContext(base);
43 | MultiDex.install(this);
44 | }
45 |
46 | private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
47 |
48 | @Nullable
49 | @Override
50 | protected String getJSBundleFile() {
51 | return CodePush.getJSBundleFile();
52 | // return CodePush.getJSBundleFile("main.bundle");
53 | }
54 |
55 | @Override
56 | public boolean getUseDeveloperSupport() {
57 | return BuildConfig.DEBUG;
58 | }
59 |
60 | @Override
61 | protected List getPackages() {
62 | Log.i(TAG,"getPackages");
63 | List modules = new ArrayList<>();
64 | modules.add(new MainReactPackage());
65 | modules.add(new RNPackage());
66 | modules.add(new FastImageViewPackage());
67 | modules.add(new RNFetchBlobPackage());
68 | modules.add(new CodePush("cItSIwCesoQ5X23wCbzEe2xCM66J4ksvOXqog",
69 | getApplicationContext(), BuildConfig.DEBUG,"http://172.28.32.244:3000/"));
70 | modules.add(new RNGestureHandlerPackage());
71 |
72 | // modules.add(new CodePush("M9ezsCkj7OUhZcXONMg4accqVUu54ksvOXqog",
73 | // getApplicationContext(), BuildConfig.DEBUG,"http://172.28.110.180:3000/"));
74 | return modules;
75 | }
76 |
77 |
78 | @Override
79 | protected String getJSMainModuleName() {
80 | return "index";
81 | }
82 | };
83 |
84 | @Override
85 | public ReactNativeHost getReactNativeHost() {
86 | Log.i(TAG,"ReactNativeHost");
87 | return mReactNativeHost;
88 | }
89 |
90 | /**
91 | *包名
92 | */
93 | public String getAppPackageName() {
94 | return this.getPackageName();
95 | }
96 |
97 | /**
98 | * 获取Application实例
99 | */
100 | public static MainApplication getInstance() {
101 | return instance;
102 | }
103 |
104 |
105 | }
106 |
--------------------------------------------------------------------------------
/testApp/app/src/main/java/com/example/wuyunqiang/testapp/preloadreact/PreLoadReactActivity.java:
--------------------------------------------------------------------------------
1 | package com.example.wuyunqiang.testapp.preloadreact;
2 |
3 | import android.content.Intent;
4 | import android.os.Bundle;
5 | import android.util.Log;
6 | import android.view.KeyEvent;
7 |
8 | import com.example.wuyunqiang.testapp.MyReactActivity;
9 | import com.facebook.react.ReactActivity;
10 | import com.facebook.react.ReactActivityDelegate;
11 | import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler;
12 | import com.facebook.react.modules.core.PermissionAwareActivity;
13 | import com.facebook.react.modules.core.PermissionListener;
14 |
15 | import javax.annotation.Nullable;
16 |
17 | /**
18 | * 预加载Activity基类
19 | * Created by Song on 2017/5/10.
20 | */
21 | public class PreLoadReactActivity extends ReactActivity implements DefaultHardwareBackBtnHandler, PermissionAwareActivity {
22 |
23 | private PreLoadReactDelegate mPreLoadReactDelegate;
24 |
25 | protected PreLoadReactActivity() {
26 | mPreLoadReactDelegate = createPreLoadReactDelegate();
27 | }
28 |
29 | private PreLoadReactDelegate createPreLoadReactDelegate() {
30 | // return new RNGestureHandlerEnabledRootView(MyReactActivity.this);
31 | return new PreLoadReactDelegate(this,getMainComponentName());
32 | }
33 |
34 | /**
35 | * 子类重写,返回RN对应的界面组件名称
36 | * @return
37 | */
38 | protected @Nullable String getMainComponentName() {
39 | return null;
40 | }
41 |
42 | @Override
43 | protected void onCreate(Bundle savedInstanceState) {
44 | super.onCreate(savedInstanceState);
45 | mPreLoadReactDelegate.onCreate();
46 | }
47 |
48 | @Override
49 | protected void onResume() {
50 | super.onResume();
51 | mPreLoadReactDelegate.onResume();
52 | }
53 |
54 | @Override
55 | protected void onPause() {
56 | super.onPause();
57 | mPreLoadReactDelegate.onPause();
58 | }
59 |
60 | @Override
61 | protected void onDestroy() {
62 | super.onDestroy();
63 | mPreLoadReactDelegate.onDestroy();
64 | }
65 |
66 | @Override
67 | public void onNewIntent(Intent intent) {
68 | if(!mPreLoadReactDelegate.onNewIntent(intent)) {
69 | super.onNewIntent(intent);
70 | }
71 | }
72 |
73 | @Override
74 | public void onActivityResult(int requestCode, int resultCode, Intent data) {
75 | mPreLoadReactDelegate.onActivityResult(requestCode,resultCode,data);
76 | }
77 |
78 | @Override
79 | public boolean onKeyUp(int keyCode, KeyEvent event) {
80 | return mPreLoadReactDelegate.onRNKeyUp(keyCode) || super.onKeyUp(keyCode, event);
81 | }
82 |
83 | /**
84 | * 处理权限授权
85 | * @param permissions
86 | * @param requestCode
87 | * @param listener
88 | */
89 | @Override
90 | public void requestPermissions(String[] permissions, int requestCode, PermissionListener listener) {
91 | mPreLoadReactDelegate.requestPermissions(permissions,requestCode,listener);
92 | }
93 |
94 | /**
95 | * 授权结果
96 | * @param requestCode
97 | * @param permissions
98 | * @param grantResults
99 | */
100 | @Override
101 | public void onRequestPermissionsResult(final int requestCode, final String[] permissions, final int[] grantResults) {
102 | mPreLoadReactDelegate.onRequestPermissionsResult(requestCode,permissions,grantResults);
103 | }
104 |
105 | }
106 |
107 |
--------------------------------------------------------------------------------
/testApp/app/src/main/java/com/example/wuyunqiang/testapp/gesturehandler/TapGestureHandler.java:
--------------------------------------------------------------------------------
1 | package com.example.wuyunqiang.testapp.gesturehandler;
2 |
3 | import android.os.Handler;
4 | import android.view.MotionEvent;
5 |
6 | public class TapGestureHandler extends GestureHandler {
7 |
8 | private static final long DEFAULT_MAX_DURATION_MS = 500;
9 | private static final long DEFAULT_MAX_DELAY_MS = 500;
10 | private static final int DEFAULT_NUMBER_OF_TAPS= 1;
11 |
12 | private long mMaxDurationMs = DEFAULT_MAX_DURATION_MS;
13 | private long mMaxDelayMs = DEFAULT_MAX_DELAY_MS;
14 | private int mNumberOfTaps = DEFAULT_NUMBER_OF_TAPS;
15 |
16 | private float mLastX, mLastY;
17 | private float mLastEventOffsetX, mLastEventOffsetY;
18 |
19 | private Handler mHandler;
20 | private int mTapsSoFar;
21 |
22 | private final Runnable mFailDelayed = new Runnable() {
23 | @Override
24 | public void run() {
25 | fail();
26 | }
27 | };
28 |
29 | public TapGestureHandler setNumberOfTaps(int numberOfTaps) {
30 | mNumberOfTaps = numberOfTaps;
31 | return this;
32 | }
33 |
34 | public TapGestureHandler setMaxDelayMs(long maxDelayMs) {
35 | mMaxDelayMs = maxDelayMs;
36 | return this;
37 | }
38 |
39 | public TapGestureHandler setMaxDurationMs(long maxDurationMs) {
40 | mMaxDurationMs = maxDurationMs;
41 | return this;
42 | }
43 |
44 | public TapGestureHandler() {
45 | setShouldCancelWhenOutside(true);
46 | }
47 |
48 | private void startTap() {
49 | if (mHandler == null) {
50 | mHandler = new Handler();
51 | } else {
52 | mHandler.removeCallbacksAndMessages(null);
53 | }
54 | mHandler.postDelayed(mFailDelayed, mMaxDurationMs);
55 | }
56 |
57 | private void endTap() {
58 | if (mHandler == null) {
59 | mHandler = new Handler();
60 | } else {
61 | mHandler.removeCallbacksAndMessages(null);
62 | }
63 | if (++mTapsSoFar == mNumberOfTaps) {
64 | activate();
65 | end();
66 | } else {
67 | mHandler.postDelayed(mFailDelayed, mMaxDelayMs);
68 | }
69 | }
70 |
71 | @Override
72 | protected void onHandle(MotionEvent event) {
73 | int state = getState();
74 |
75 | mLastEventOffsetX = event.getRawX() - event.getX();
76 | mLastEventOffsetY = event.getRawY() - event.getY();
77 | mLastX = event.getRawX();
78 | mLastY = event.getRawY();
79 |
80 | if (state == STATE_UNDETERMINED) {
81 | begin();
82 | mTapsSoFar = 0;
83 | startTap();
84 | }
85 | if (state == STATE_BEGAN) {
86 | int action = event.getActionMasked();
87 | if (action == MotionEvent.ACTION_UP) {
88 | endTap();
89 | } else if (action == MotionEvent.ACTION_DOWN) {
90 | startTap();
91 | }
92 | }
93 | }
94 |
95 | @Override
96 | protected void onCancel() {
97 | if (mHandler != null) {
98 | mHandler.removeCallbacksAndMessages(null);
99 | }
100 | }
101 |
102 | @Override
103 | protected void onReset() {
104 | mTapsSoFar = 0;
105 | if (mHandler != null) {
106 | mHandler.removeCallbacksAndMessages(null);
107 | }
108 | }
109 |
110 | public float getLastAbsolutePositionX() {
111 | return mLastX;
112 | }
113 |
114 | public float getLastAbsolutePositionY() {
115 | return mLastY;
116 | }
117 |
118 | public float getLastRelativePositionX() {
119 | return mLastX - mLastEventOffsetX;
120 | }
121 |
122 | public float getLastRelativePositionY() {
123 | return mLastY - mLastEventOffsetY;
124 | }
125 | }
126 |
--------------------------------------------------------------------------------
/testApp/app/src/main/java/com/example/wuyunqiang/testapp/gesturehandler/PinchGestureHandler.java:
--------------------------------------------------------------------------------
1 | package com.example.wuyunqiang.testapp.gesturehandler;
2 |
3 | import android.content.Context;
4 | import android.view.MotionEvent;
5 | import android.view.ScaleGestureDetector;
6 | import android.view.ViewConfiguration;
7 |
8 | public class PinchGestureHandler extends GestureHandler {
9 |
10 | private ScaleGestureDetector mScaleGestureDetector;
11 | private double mLastScaleFactor;
12 | private double mLastVelocity;
13 |
14 | private float mStartingSpan;
15 | private float mSpanSlop;
16 |
17 | private ScaleGestureDetector.OnScaleGestureListener mGestureListener =
18 | new ScaleGestureDetector.OnScaleGestureListener() {
19 |
20 | @Override
21 | public boolean onScale(ScaleGestureDetector detector) {
22 | double prevScaleFactor = mLastScaleFactor;
23 | mLastScaleFactor *= detector.getScaleFactor();
24 | long delta = detector.getTimeDelta();
25 | if (delta > 0) {
26 | mLastVelocity = (mLastScaleFactor - prevScaleFactor) / delta;
27 | }
28 | if (Math.abs(mStartingSpan - detector.getCurrentSpan()) >= mSpanSlop
29 | && getState() == STATE_BEGAN) {
30 | activate();
31 | }
32 | return true;
33 | }
34 |
35 | @Override
36 | public boolean onScaleBegin(ScaleGestureDetector detector) {
37 | mStartingSpan = detector.getCurrentSpan();
38 | return true;
39 | }
40 |
41 | @Override
42 | public void onScaleEnd(ScaleGestureDetector detector) {
43 | // ScaleGestureDetector thinks that when fingers are 27mm away that's a sufficiently good
44 | // reason to trigger this method giving us no other choice but to ignore it completely.
45 | }
46 | };
47 |
48 | public PinchGestureHandler() {
49 | setShouldCancelWhenOutside(false);
50 | }
51 |
52 | @Override
53 | protected void onHandle(MotionEvent event) {
54 | if (getState() == STATE_UNDETERMINED) {
55 | Context context = getView().getContext();
56 | mLastVelocity = 0f;
57 | mLastScaleFactor = 1f;
58 | mScaleGestureDetector = new ScaleGestureDetector(context, mGestureListener);
59 | ViewConfiguration configuration = ViewConfiguration.get(context);
60 | mSpanSlop = configuration.getScaledTouchSlop();
61 |
62 | begin();
63 | }
64 |
65 | if (mScaleGestureDetector != null) {
66 | mScaleGestureDetector.onTouchEvent(event);
67 | }
68 |
69 | int activePointers = event.getPointerCount();
70 | if (event.getActionMasked() == MotionEvent.ACTION_POINTER_UP) {
71 | activePointers -= 1;
72 | }
73 |
74 | if (getState() == STATE_ACTIVE && activePointers < 2) {
75 | end();
76 | } else if (event.getActionMasked() == MotionEvent.ACTION_UP) {
77 | fail();
78 | }
79 | }
80 |
81 | @Override
82 | protected void onReset() {
83 | mScaleGestureDetector = null;
84 | mLastVelocity = 0f;
85 | mLastScaleFactor = 1f;
86 | }
87 |
88 | public double getScale() {
89 | return mLastScaleFactor;
90 | }
91 |
92 | public double getVelocity() {
93 | return mLastVelocity;
94 | }
95 |
96 | public float getFocalPointX() {
97 | if (mScaleGestureDetector == null) {
98 | return Float.NaN;
99 | }
100 | return mScaleGestureDetector.getFocusX();
101 | }
102 |
103 | public float getFocalPointY() {
104 | if (mScaleGestureDetector == null) {
105 | return Float.NaN;
106 | }
107 | return mScaleGestureDetector.getFocusY();
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/testApp/app/src/main/java/com/example/wuyunqiang/testapp/gesture/RNGestureHandlerRegistry.java:
--------------------------------------------------------------------------------
1 | package com.example.wuyunqiang.testapp.gesture;
2 |
3 | import android.util.SparseArray;
4 | import android.view.View;
5 |
6 | import com.example.wuyunqiang.testapp.gesturehandler.GestureHandler;
7 | import com.example.wuyunqiang.testapp.gesturehandler.GestureHandlerRegistry;
8 |
9 | import java.util.ArrayList;
10 |
11 | import javax.annotation.Nullable;
12 |
13 | public class RNGestureHandlerRegistry implements GestureHandlerRegistry {
14 |
15 | private final SparseArray mHandlers = new SparseArray<>();
16 | private final SparseArray mAttachedTo = new SparseArray<>();
17 | private final SparseArray> mHandlersForView = new SparseArray<>();
18 |
19 | public synchronized void registerHandler(GestureHandler handler) {
20 | mHandlers.put(handler.getTag(), handler);
21 | }
22 |
23 | public synchronized @Nullable GestureHandler getHandler(int handlerTag) {
24 | return mHandlers.get(handlerTag);
25 | }
26 |
27 | public synchronized boolean attachHandlerToView(int handlerTag, int viewTag) {
28 | GestureHandler handler = mHandlers.get(handlerTag);
29 | if (handler != null) {
30 | detachHandler(handler);
31 | registerHandlerForViewWithTag(viewTag, handler);
32 | return true;
33 | } else {
34 | return false;
35 | }
36 | }
37 |
38 | private synchronized void registerHandlerForViewWithTag(int viewTag, GestureHandler handler) {
39 | if (mAttachedTo.get(handler.getTag()) != null) {
40 | throw new IllegalStateException("Handler " + handler + " already attached");
41 | }
42 | mAttachedTo.put(handler.getTag(), viewTag);
43 | ArrayList listToAdd = mHandlersForView.get(viewTag);
44 | if (listToAdd == null) {
45 | listToAdd = new ArrayList<>(1);
46 | listToAdd.add(handler);
47 | mHandlersForView.put(viewTag, listToAdd);
48 | } else {
49 | listToAdd.add(handler);
50 | }
51 | }
52 |
53 | private synchronized void detachHandler(GestureHandler handler) {
54 | Integer attachedToView = mAttachedTo.get(handler.getTag());
55 | if (attachedToView != null) {
56 | mAttachedTo.remove(handler.getTag());
57 | ArrayList attachedHandlers = mHandlersForView.get(attachedToView);
58 | if (attachedHandlers != null) {
59 | attachedHandlers.remove(handler);
60 | if (attachedHandlers.size() == 0) {
61 | mHandlersForView.remove(attachedToView);
62 | }
63 | }
64 | }
65 | if (handler.getView() != null) {
66 | // Handler is in "prepared" state which means it is registered in the orchestrator and can
67 | // receive touch events. This means that before we remove it from the registry we need to
68 | // "cancel" it so that orchestrator does no longer keep a reference to it.
69 | handler.cancel();
70 | }
71 | }
72 |
73 | public synchronized void dropHandler(int handlerTag) {
74 | GestureHandler handler = mHandlers.get(handlerTag);
75 | if (handler != null) {
76 | detachHandler(handler);
77 | mHandlers.remove(handlerTag);
78 | }
79 | }
80 |
81 | public synchronized void dropAllHandlers() {
82 | mHandlers.clear();
83 | mAttachedTo.clear();
84 | mHandlersForView.clear();
85 | }
86 |
87 | public synchronized ArrayList getHandlersForViewWithTag(int viewTag) {
88 | return mHandlersForView.get(viewTag);
89 | }
90 |
91 | @Override
92 | public synchronized ArrayList getHandlersForView(View view) {
93 | return getHandlersForViewWithTag(view.getId());
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/testApp/app/src/main/java/com/example/wuyunqiang/testapp/RNFetchBlob/Response/RNFetchBlobDefaultResp.java:
--------------------------------------------------------------------------------
1 | package com.example.wuyunqiang.testapp.RNFetchBlob.Response;
2 |
3 | import com.example.wuyunqiang.testapp.RNFetchBlob.RNFetchBlobConst;
4 | import com.example.wuyunqiang.testapp.RNFetchBlob.RNFetchBlobProgressConfig;
5 | import com.example.wuyunqiang.testapp.RNFetchBlob.RNFetchBlobReq;
6 | import com.facebook.react.bridge.Arguments;
7 | import com.facebook.react.bridge.ReactApplicationContext;
8 | import com.facebook.react.bridge.WritableMap;
9 | import com.facebook.react.modules.core.DeviceEventManagerModule;
10 |
11 | import java.io.IOException;
12 | import java.nio.charset.Charset;
13 |
14 | import okhttp3.MediaType;
15 | import okhttp3.ResponseBody;
16 | import okio.Buffer;
17 | import okio.BufferedSource;
18 | import okio.Okio;
19 | import okio.Source;
20 | import okio.Timeout;
21 |
22 | /**
23 | * Created by wkh237 on 2016/7/11.
24 | */
25 | public class RNFetchBlobDefaultResp extends ResponseBody {
26 |
27 | String mTaskId;
28 | ReactApplicationContext rctContext;
29 | ResponseBody originalBody;
30 | boolean isIncrement = false;
31 |
32 | public RNFetchBlobDefaultResp(ReactApplicationContext ctx, String taskId, ResponseBody body, boolean isIncrement) {
33 | this.rctContext = ctx;
34 | this.mTaskId = taskId;
35 | this.originalBody = body;
36 | this.isIncrement = isIncrement;
37 | }
38 |
39 | @Override
40 | public MediaType contentType() {
41 | return originalBody.contentType();
42 | }
43 |
44 | @Override
45 | public long contentLength() {
46 | return originalBody.contentLength();
47 | }
48 |
49 | @Override
50 | public BufferedSource source() {
51 | return Okio.buffer(new ProgressReportingSource(originalBody.source()));
52 | }
53 |
54 | private class ProgressReportingSource implements Source {
55 |
56 | BufferedSource mOriginalSource;
57 | long bytesRead = 0;
58 |
59 | ProgressReportingSource(BufferedSource originalSource) {
60 | mOriginalSource = originalSource;
61 | }
62 |
63 | @Override
64 | public long read(Buffer sink, long byteCount) throws IOException {
65 |
66 | long read = mOriginalSource.read(sink, byteCount);
67 | bytesRead += read > 0 ? read : 0;
68 | RNFetchBlobProgressConfig reportConfig = RNFetchBlobReq.getReportProgress(mTaskId);
69 | long cLen = contentLength();
70 | if(reportConfig != null && cLen != 0 && reportConfig.shouldReport(bytesRead/contentLength())) {
71 | WritableMap args = Arguments.createMap();
72 | args.putString("taskId", mTaskId);
73 | args.putString("written", String.valueOf(bytesRead));
74 | args.putString("total", String.valueOf(contentLength()));
75 | if(isIncrement) {
76 | args.putString("chunk", sink.readString(Charset.defaultCharset()));
77 | }
78 | else {
79 | args.putString("chunk", "");
80 | }
81 |
82 | rctContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
83 | .emit(RNFetchBlobConst.EVENT_PROGRESS, args);
84 | }
85 | return read;
86 | }
87 |
88 | @Override
89 | public Timeout timeout() {
90 | return null;
91 | }
92 |
93 | @Override
94 | public void close() throws IOException {
95 |
96 | }
97 | }
98 |
99 | }
100 |
--------------------------------------------------------------------------------
/testApp/RN_src/component/Tab.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by wuyunqiang on 2018/1/12.
3 | */
4 | import React, { Component } from 'react';
5 | import {
6 | AppRegistry,
7 | Platform,
8 | StyleSheet,
9 | Text,
10 | View,
11 | TouchableOpacity,
12 | NativeModules,
13 | ImageBackground,
14 | DeviceEventEmitter
15 | } from 'react-native';
16 |
17 | export default class Tab extends Component {
18 | renderItem = (route, index) => {
19 | const {
20 | navigation,
21 | jumpToIndex,
22 | } = this.props;
23 |
24 | const focused = index === navigation.state.index;
25 | const color = focused ? this.props.activeTintColor : this.props.inactiveTintColor;
26 | let TabScene = {
27 | focused:focused,
28 | route:route,
29 | tintColor:color
30 | };
31 |
32 | if(index==1){
33 | return (
36 |
37 | );
38 | }
39 |
40 | return (
41 | jumpToIndex(index)}
45 | >
46 |
48 | {this.props.renderIcon(TabScene)}
49 | {this.props.getLabel(TabScene)}
50 |
51 |
52 | );
53 | };
54 | render(){
55 | const {navigation,jumpToIndex} = this.props;
56 | const {routes,} = navigation.state;
57 | const focused = 1 === navigation.state.index;
58 | const color = focused ? this.props.activeTintColor : this.props.inactiveTintColor;
59 | let TabScene = {
60 | focused:focused,
61 | route:routes[1],
62 | tintColor:color
63 | };
64 | return (
67 |
68 | {routes && routes.map((route,index) => this.renderItem(route, index))}
69 |
70 | jumpTo(routes[1].key)}>
74 |
76 | {this.props.renderIcon(TabScene)}
77 |
78 |
79 | );
80 | }
81 | }
82 | const styles = {
83 | tab:{
84 | width:WIDTH,
85 | backgroundColor:'transparent',
86 | flexDirection:'row',
87 | justifyContent:'space-around',
88 | alignItems:'flex-end'
89 | },
90 | tabItem:{
91 | height:SCALE(80),
92 | width:SCALE(100),
93 | alignItems:'center',
94 | justifyContent:'center'
95 | },
96 | tabText:{
97 | marginTop:SCALE(13),
98 | fontSize:FONT(10),
99 | color:Color.C7b7b7b
100 | },
101 | tabTextChoose:{
102 | color:Color.f3474b
103 | },
104 | tabImage:{
105 | width:SCALE(42),
106 | height:SCALE(42),
107 | },
108 | }
109 |
--------------------------------------------------------------------------------
/testApp/app/src/main/java/com/example/wuyunqiang/testapp/RNFetchBlob/RNFetchBlobUtils.java:
--------------------------------------------------------------------------------
1 | package com.example.wuyunqiang.testapp.RNFetchBlob;
2 |
3 | import com.facebook.react.bridge.Arguments;
4 | import com.facebook.react.bridge.WritableMap;
5 | import com.facebook.react.modules.core.DeviceEventManagerModule;
6 |
7 | import java.security.MessageDigest;
8 | import java.security.cert.CertificateException;
9 |
10 | import javax.net.ssl.HostnameVerifier;
11 | import javax.net.ssl.SSLContext;
12 | import javax.net.ssl.SSLSession;
13 | import javax.net.ssl.SSLSocketFactory;
14 | import javax.net.ssl.TrustManager;
15 | import javax.net.ssl.X509TrustManager;
16 |
17 | import okhttp3.OkHttpClient;
18 |
19 |
20 | public class RNFetchBlobUtils {
21 |
22 | public static String getMD5(String input) {
23 | String result = null;
24 |
25 | try {
26 | MessageDigest md = MessageDigest.getInstance("MD5");
27 | md.update(input.getBytes());
28 | byte[] digest = md.digest();
29 |
30 | StringBuffer sb = new StringBuffer();
31 |
32 | for (byte b : digest) {
33 | sb.append(String.format("%02x", b & 0xff));
34 | }
35 |
36 | result = sb.toString();
37 | } catch (Exception ex) {
38 | ex.printStackTrace();
39 | } finally {
40 | return result;
41 | }
42 |
43 | }
44 |
45 | public static void emitWarningEvent(String data) {
46 | WritableMap args = Arguments.createMap();
47 | args.putString("event", "warn");
48 | args.putString("detail", data);
49 |
50 | // emit event to js context
51 | RNFetchBlob.RCTContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
52 | .emit(RNFetchBlobConst.EVENT_MESSAGE, args);
53 | }
54 |
55 | public static OkHttpClient.Builder getUnsafeOkHttpClient(OkHttpClient client) {
56 | try {
57 | // Create a trust manager that does not validate certificate chains
58 | final TrustManager[] trustAllCerts = new TrustManager[]{
59 | new X509TrustManager() {
60 | @Override
61 | public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
62 | }
63 |
64 | @Override
65 | public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
66 | }
67 |
68 | @Override
69 | public java.security.cert.X509Certificate[] getAcceptedIssuers() {
70 | return new java.security.cert.X509Certificate[]{};
71 | }
72 | }
73 | };
74 |
75 | // Install the all-trusting trust manager
76 | final SSLContext sslContext = SSLContext.getInstance("SSL");
77 | sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
78 | // Create an ssl socket factory with our all-trusting manager
79 | final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
80 |
81 | OkHttpClient.Builder builder = client.newBuilder();
82 | builder.sslSocketFactory(sslSocketFactory);
83 | builder.hostnameVerifier(new HostnameVerifier() {
84 | @Override
85 | public boolean verify(String hostname, SSLSession session) {
86 | return true;
87 | }
88 | });
89 |
90 | return builder;
91 | } catch (Exception e) {
92 | throw new RuntimeException(e);
93 | }
94 | }
95 | }
96 |
--------------------------------------------------------------------------------