├── .gitignore
├── .idea
├── gradle.xml
├── inspectionProfiles
│ └── Project_Default.xml
├── markdown-navigator.xml
├── markdown-navigator
│ └── profiles_settings.xml
├── misc.xml
├── modules.xml
├── runConfigurations.xml
└── vcs.xml
├── LICENSE
├── README.md
├── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
├── release.jks
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── engineer
│ │ └── art
│ │ └── hybridapp
│ │ └── ExampleInstrumentedTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── assets
│ │ ├── index.bundle
│ │ └── index.bundle.meta
│ ├── java
│ │ └── com
│ │ │ └── engineer
│ │ │ └── art
│ │ │ └── hybridapp
│ │ │ ├── MainActivity.java
│ │ │ └── ReactRootActivity.java
│ └── res
│ │ ├── drawable-hdpi
│ │ └── node_modules_reactnavigation_src_views_assets_backicon.png
│ │ ├── drawable-mdpi
│ │ ├── node_modules_reactnavigation_src_views_assets_backicon.png
│ │ ├── src_images_back.png
│ │ ├── src_images_fake.jpg
│ │ ├── src_images_ic_ad_video_play.png
│ │ ├── src_images_ic_bar_back_white.png
│ │ ├── src_images_ic_chat_white.png
│ │ ├── src_images_ic_scan_gray.png
│ │ ├── src_images_ic_search_gray.png
│ │ ├── src_images_index_bg.jpg
│ │ └── src_images_live_player_bg.jpg
│ │ ├── drawable-v24
│ │ └── ic_launcher_foreground.xml
│ │ ├── drawable-xhdpi
│ │ └── node_modules_reactnavigation_src_views_assets_backicon.png
│ │ ├── drawable-xxhdpi
│ │ └── node_modules_reactnavigation_src_views_assets_backicon.png
│ │ ├── drawable-xxxhdpi
│ │ └── node_modules_reactnavigation_src_views_assets_backicon.png
│ │ ├── drawable
│ │ └── ic_launcher_background.xml
│ │ ├── layout
│ │ └── activity_main.xml
│ │ ├── mipmap-anydpi-v26
│ │ ├── ic_launcher.xml
│ │ └── ic_launcher_round.xml
│ │ ├── mipmap-hdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-mdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxxhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ └── values
│ │ ├── colors.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── test
│ └── java
│ └── com
│ └── engineer
│ └── art
│ └── hybridapp
│ └── ExampleUnitTest.java
├── build.gradle
├── capture
├── box.gif
├── index.gif
├── movie.gif
├── person.gif
├── reading.png
├── top250.gif
├── usercenter.png
├── video.gif
├── yuanxian.gif
└── yuanxian2.gif
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── index.js
├── npm-start.cmd
├── package.json
├── release.cmd
├── settings.gradle
└── src
├── App.js
├── components
├── HorizontalCardView.js
├── HorizontalListView.js
├── HorizontalSimpleView.js
├── MainToolBar.js
├── NavigationItem.js
├── RatingCard.js
├── RefreshScrollView.js
├── ToolBar.js
├── VerticalListView.js
└── widgets
│ ├── Loading.js
│ ├── MoreView.js
│ ├── TitleView.js
│ └── VerticalSapce.js
├── images
├── avatar_male_100.png
├── back.png
├── fake.jpg
├── ic_ad_video_play.png
├── ic_bar_back_white.png
├── ic_chat_white.png
├── ic_scan_gray.png
├── ic_search_gray.png
├── index_bg.jpg
├── live_player_bg.jpg
└── search.png
├── localdata
├── all.json
├── book.json
├── celebrity.json
├── coming_soon.json
├── in_theaters.json
├── index.json
├── movie_index.json
├── music.json
├── only.json
├── selected_collections.json
├── top250.json
└── usbox.json
├── nav
├── AppNav.js
└── HomeNav.js
├── page
├── BookPage.js
├── CameraPage.js
├── HomePage.js
├── IndexPage.js
├── MinePage.js
├── MovieCelebrityPage.js
├── MovieDetailPage.js
├── MovieListPage.js
├── MoviePage.js
├── MovieTabPageFuture.js
├── MovieTabPageNow.js
├── MovieVideoPlayPage.js
├── MusicPage.js
├── RankListPage.js
├── SearchPage.js
├── SubjectDetailPage.js
└── UserCenterPager.js
└── util
├── Api.js
└── Api_back.js
/.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 | # Built application files
11 | *.apk
12 | *.ap_
13 |
14 | # Files for the ART/Dalvik VM
15 | *.dex
16 |
17 | # Java class files
18 | *.class
19 |
20 | # Generated files
21 | bin/
22 | gen/
23 | out/
24 |
25 | # Gradle files
26 | .gradle/
27 | build/
28 |
29 | # Local configuration file (sdk path, etc)
30 | local.properties
31 |
32 | # Proguard folder generated by Eclipse
33 | proguard/
34 |
35 | # Log Files
36 | *.log
37 |
38 | # Android Studio Navigation editor temp files
39 | .navigation/
40 |
41 | # Android Studio captures folder
42 | captures/
43 |
44 | # Intellij
45 | *.iml
46 | .idea/workspace.xml
47 | .idea/tasks.xml
48 | .idea/gradle.xml
49 | .idea/dictionaries
50 | .idea/libraries
51 |
52 | # Keystore files
53 | # *.jks
54 |
55 | # External native build folder generated in Android Studio 2.2 and later
56 | .externalNativeBuild
57 |
58 | # Google Services (e.g. APIs or Firebase)
59 | google-services.json
60 |
61 | # Freeline
62 | freeline.py
63 | freeline/
64 | freeline_project_description.json
65 | node_modules/
66 | yarn.lock
67 | app/release/
68 | *.mp4
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/Project_Default.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 |
--------------------------------------------------------------------------------
/.idea/markdown-navigator.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 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
--------------------------------------------------------------------------------
/.idea/markdown-navigator/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/.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 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/runConfigurations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # HybridApp
2 |
3 | 这是一个在Android原生应用中集成React Native 的项目。在原生应用中集成了一个仿豆瓣客户端(很久之前写的,UI已经不怎么像了o(╯□╰)o)的React Native应用。
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 | ## 扫码下载demo体验效果
33 |
34 | 
35 |
36 | ## 集成React Native到原生应用
37 |
38 | 其实,关于怎么把React Native集成到原生应用中,React Native的官方文档[Integration with Existing Apps](http://facebook.github.io/react-native/docs/integration-with-existing-apps.html)已经有了详细的说明,**严格的**照着文档一步一步执行下来,基本上是没有什么问题的。
39 |
40 |
41 | 这里再补充一点官网没有提及的内容吧,就是如果在React Native 应用中使用到了原生应用的组件,比如常见的react-native-camera/react-native-image-picker 等,这个时候该如何正确的把这写**原生组件**集成到**原生项目**中呢?
42 |
43 | 其实,如果你用AS打开过React Native项目下Android目录的话,可以发现其实原生组件(比如react-native-camera)就是一个主工程(app)依赖的子module.在React Native的项目中,我们通过执行react-native link 这个命令,React Native框架会自动帮我们实现整个依赖过程,在这中间主要做了三件事:
44 |
45 |
46 | - 在setting.gradle 文件中添加依赖组件的别名及路径
47 |
48 | ```gradle
49 | include ':react-native-camera'
50 | project(':react-native-camera').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-camera/android')
51 | ```
52 |
53 | - 在app/build.gradle dependencies 结点中添加依赖
54 | ```gradle
55 | dependencies {
56 | compile project(':react-native-camera')
57 | compile fileTree(dir: "libs", include: ["*.jar"])
58 | compile "com.android.support:appcompat-v7:23.0.1"
59 | compile "com.facebook.react:react-native:+" // From node_modules
60 | }
61 | ```
62 |
63 | - 在MainApplication.java 的getPackages()方法中,为我们添加组件所对应的Package。
64 |
65 | ```java
66 | private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
67 | @Override
68 | public boolean getUseDeveloperSupport() {
69 | return BuildConfig.DEBUG;
70 | }
71 |
72 | @Override
73 | protected List getPackages() {
74 | return Arrays.asList(
75 | new MainReactPackage(),
76 | new RCTCameraPackage()
77 | );
78 | }
79 |
80 | @Override
81 | protected String getJSMainModuleName() {
82 | return "index";
83 | }
84 | };
85 | ```
86 |
87 | 不得不说,这几个自动实现的步骤的确很牛逼,不知道内部是咋实现的?୧(๑•̀◡•́๑)૭
88 |
89 | 稍显遗憾的是,把React Native集成到原生项目中后,再次执行react-native link后上述步骤是无法自动实现的,因此这就需要我们去手动添加**原生组价**的依赖。其实这个过程也很简单,理解了node_modules目录和项目目录之间的**相对路劲**关系即可。这里以此项目中setting.gradle 中的路劲为例:
90 |
91 | ```gradle
92 | include ':app'
93 | include ':react-native-camera'
94 | project(':react-native-camera').projectDir = new File(rootProject.projectDir, 'node_modules/react-native-camera/android')
95 | include ':react-native-video'
96 | project(':react-native-video').projectDir = new File(rootProject.projectDir, 'node_modules/react-native-video/android')
97 | include ':react-native-image-crop-picker'
98 | project(':react-native-image-crop-picker').projectDir = new File(rootProject.projectDir, 'node_modules/react-native-image-crop-picker/android')
99 | ```
100 |
101 | 这里其实和原生应用中子module是一个意思,只不过在原生项目中,子module一般都是直接创建在项目根目录中,就省去了写projectDir 的步骤了。有了这个自module,剩下的两个步骤就很简单了,这里就不再赘述,直接看代码就明白了。
102 |
103 | ### how to run
104 |
105 |
106 | - git clone https://github.com/REBOOTERS/HybridApp.git
107 | - cd HybridApp
108 | - yarn install / npm install (only once)
109 | - npm start
110 |
111 | 下面,就可以用Android Studio打开这个项目,愉快的玩耍了。
112 |
113 | ### how to release
114 |
115 | 如果想打包的话,在Windows上执行release.cmd 即可,会自动生成相应的js.bundle 文件并生成最终的apk文件。
116 |
117 | 在mac上,按照release.cmd 中的内容执行相应的bash 命令即可,手边没有环境,bash脚本没法验证,如果有人写出来并验证通过了,可以分享一下!
118 |
119 |
120 |
121 | ### 更多
122 |
123 |
124 | **应用中用到的数据,抓取自豆瓣API及[豆瓣开发平台](https://developers.douban.com/wiki/?title=movie_v2),仅供学习**
125 |
126 |
127 |
128 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 26
5 | defaultConfig {
6 | applicationId "com.engineer.art.hybridapp"
7 | minSdkVersion 19
8 | targetSdkVersion 26
9 | versionCode 1
10 | versionName "1.0"
11 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
12 | }
13 | signingConfigs {
14 | release {
15 | storeFile file(MYAPP_RELEASE_STORE_FILE)
16 | storePassword MYAPP_RELEASE_STORE_PASSWORD
17 | keyAlias MYAPP_RELEASE_KEY_ALIAS
18 | keyPassword MYAPP_RELEASE_KEY_PASSWORD
19 | }
20 | }
21 | buildTypes {
22 | release {
23 | minifyEnabled false
24 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
25 | signingConfig signingConfigs.release
26 | }
27 | }
28 | }
29 |
30 | dependencies {
31 | implementation fileTree(dir: 'libs', include: ['*.jar'])
32 | implementation 'com.android.support:appcompat-v7:26.1.0'
33 | implementation 'com.android.support.constraint:constraint-layout:1.0.2'
34 | testImplementation 'junit:junit:4.12'
35 | androidTestImplementation 'com.android.support.test:runner:1.0.1'
36 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
37 |
38 | compile "com.facebook.react:react-native:+"
39 |
40 | compile project(':react-native-video')
41 | compile project(':react-native-image-crop-picker')
42 | // compile fileTree(dir: "libs", include: ["*.jar"])
43 | // compile "com.android.support:appcompat-v7:23.0.1"
44 | // compile "com.facebook.react:react-native:+" // From node_modules
45 |
46 | // 如果只需要支持WebP格式而不需要动图
47 | compile 'com.facebook.fresco:webpsupport:1.0.1'
48 |
49 | compile project(':react-native-camera')
50 | }
51 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/app/release.jks:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/REBOOTERS/HybridApp/2f69af4e546f79d5bc4152f8a87853d21e9a4cf4/app/release.jks
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/engineer/art/hybridapp/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.engineer.art.hybridapp;
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.engineer.art.hybridapp", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/app/src/main/assets/index.bundle.meta:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/REBOOTERS/HybridApp/2f69af4e546f79d5bc4152f8a87853d21e9a4cf4/app/src/main/assets/index.bundle.meta
--------------------------------------------------------------------------------
/app/src/main/java/com/engineer/art/hybridapp/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.engineer.art.hybridapp;
2 |
3 | import android.content.Intent;
4 | import android.os.Bundle;
5 | import android.support.v7.app.AppCompatActivity;
6 | import android.view.View;
7 |
8 | public class MainActivity extends AppCompatActivity {
9 |
10 | @Override
11 | protected void onCreate(Bundle savedInstanceState) {
12 | super.onCreate(savedInstanceState);
13 | setContentView(R.layout.activity_main);
14 | findViewById(R.id.go).setOnClickListener(new View.OnClickListener() {
15 | @Override
16 | public void onClick(View v) {
17 | startActivity(new Intent(MainActivity.this, ReactRootActivity.class));
18 | }
19 | });
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/app/src/main/java/com/engineer/art/hybridapp/ReactRootActivity.java:
--------------------------------------------------------------------------------
1 | package com.engineer.art.hybridapp;
2 |
3 | import android.os.Bundle;
4 | import android.support.v7.app.AppCompatActivity;
5 |
6 | import com.brentvatne.react.ReactVideoPackage;
7 | import com.facebook.react.ReactInstanceManager;
8 | import com.facebook.react.ReactRootView;
9 | import com.facebook.react.common.LifecycleState;
10 | import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler;
11 | import com.facebook.react.shell.MainReactPackage;
12 | import com.lwansbrough.RCTCamera.RCTCameraPackage;
13 | import com.reactnative.ivpusic.imagepicker.PickerPackage;
14 |
15 | /**
16 | * author : Rookie
17 | * e-mail : yingkongshi11@gmail.com
18 | * time : 2018/02/09
19 | * desc :
20 | * version: 1.0
21 | */
22 |
23 | public class ReactRootActivity extends AppCompatActivity implements DefaultHardwareBackBtnHandler {
24 | private ReactRootView mReactRootView;
25 | private ReactInstanceManager mReactInstanceManager;
26 |
27 | @Override
28 | protected void onCreate(Bundle savedInstanceState) {
29 | super.onCreate(savedInstanceState);
30 |
31 | mReactRootView = new ReactRootView(this);
32 | mReactInstanceManager = ReactInstanceManager.builder()
33 | .setApplication(getApplication())
34 | .setBundleAssetName("index.bundle")
35 | .setJSMainModulePath("index")
36 | .addPackage(new MainReactPackage())
37 | .addPackage(new ReactVideoPackage())
38 | .addPackage(new PickerPackage())
39 | .addPackage(new RCTCameraPackage())
40 | .setUseDeveloperSupport(BuildConfig.DEBUG)
41 | .setInitialLifecycleState(LifecycleState.RESUMED)
42 | .build();
43 |
44 | // 注意这里的MyReactNativeApp必须对应“index.android.js”中的
45 | // “AppRegistry.registerComponent()”的第一个参数
46 | mReactRootView.startReactApplication(mReactInstanceManager, "Hybridapplication", null);
47 |
48 | setContentView(mReactRootView);
49 | }
50 |
51 | @Override
52 | public void invokeDefaultOnBackPressed() {
53 | super.onBackPressed();
54 | }
55 |
56 | @Override
57 | protected void onPause() {
58 | super.onPause();
59 |
60 | if (mReactInstanceManager != null) {
61 | mReactInstanceManager.onHostPause(this);
62 | }
63 | }
64 |
65 | @Override
66 | protected void onResume() {
67 | super.onResume();
68 |
69 | if (mReactInstanceManager != null) {
70 | mReactInstanceManager.onHostResume(this, this);
71 | }
72 | }
73 |
74 | @Override
75 | protected void onDestroy() {
76 | super.onDestroy();
77 |
78 | if (mReactInstanceManager != null) {
79 | mReactInstanceManager.onHostDestroy(this);
80 | }
81 | }
82 |
83 | @Override
84 | public void onBackPressed() {
85 | if (mReactInstanceManager != null) {
86 | mReactInstanceManager.onBackPressed();
87 | } else {
88 | super.onBackPressed();
89 | }
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/node_modules_reactnavigation_src_views_assets_backicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/REBOOTERS/HybridApp/2f69af4e546f79d5bc4152f8a87853d21e9a4cf4/app/src/main/res/drawable-hdpi/node_modules_reactnavigation_src_views_assets_backicon.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/node_modules_reactnavigation_src_views_assets_backicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/REBOOTERS/HybridApp/2f69af4e546f79d5bc4152f8a87853d21e9a4cf4/app/src/main/res/drawable-mdpi/node_modules_reactnavigation_src_views_assets_backicon.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/src_images_back.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/REBOOTERS/HybridApp/2f69af4e546f79d5bc4152f8a87853d21e9a4cf4/app/src/main/res/drawable-mdpi/src_images_back.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/src_images_fake.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/REBOOTERS/HybridApp/2f69af4e546f79d5bc4152f8a87853d21e9a4cf4/app/src/main/res/drawable-mdpi/src_images_fake.jpg
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/src_images_ic_ad_video_play.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/REBOOTERS/HybridApp/2f69af4e546f79d5bc4152f8a87853d21e9a4cf4/app/src/main/res/drawable-mdpi/src_images_ic_ad_video_play.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/src_images_ic_bar_back_white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/REBOOTERS/HybridApp/2f69af4e546f79d5bc4152f8a87853d21e9a4cf4/app/src/main/res/drawable-mdpi/src_images_ic_bar_back_white.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/src_images_ic_chat_white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/REBOOTERS/HybridApp/2f69af4e546f79d5bc4152f8a87853d21e9a4cf4/app/src/main/res/drawable-mdpi/src_images_ic_chat_white.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/src_images_ic_scan_gray.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/REBOOTERS/HybridApp/2f69af4e546f79d5bc4152f8a87853d21e9a4cf4/app/src/main/res/drawable-mdpi/src_images_ic_scan_gray.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/src_images_ic_search_gray.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/REBOOTERS/HybridApp/2f69af4e546f79d5bc4152f8a87853d21e9a4cf4/app/src/main/res/drawable-mdpi/src_images_ic_search_gray.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/src_images_index_bg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/REBOOTERS/HybridApp/2f69af4e546f79d5bc4152f8a87853d21e9a4cf4/app/src/main/res/drawable-mdpi/src_images_index_bg.jpg
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/src_images_live_player_bg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/REBOOTERS/HybridApp/2f69af4e546f79d5bc4152f8a87853d21e9a4cf4/app/src/main/res/drawable-mdpi/src_images_live_player_bg.jpg
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
12 |
13 |
19 |
22 |
25 |
26 |
27 |
28 |
34 |
35 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/node_modules_reactnavigation_src_views_assets_backicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/REBOOTERS/HybridApp/2f69af4e546f79d5bc4152f8a87853d21e9a4cf4/app/src/main/res/drawable-xhdpi/node_modules_reactnavigation_src_views_assets_backicon.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/node_modules_reactnavigation_src_views_assets_backicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/REBOOTERS/HybridApp/2f69af4e546f79d5bc4152f8a87853d21e9a4cf4/app/src/main/res/drawable-xxhdpi/node_modules_reactnavigation_src_views_assets_backicon.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxxhdpi/node_modules_reactnavigation_src_views_assets_backicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/REBOOTERS/HybridApp/2f69af4e546f79d5bc4152f8a87853d21e9a4cf4/app/src/main/res/drawable-xxxhdpi/node_modules_reactnavigation_src_views_assets_backicon.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
11 |
16 |
21 |
26 |
31 |
36 |
41 |
46 |
51 |
56 |
61 |
66 |
71 |
76 |
81 |
86 |
91 |
96 |
101 |
106 |
111 |
116 |
121 |
126 |
131 |
136 |
141 |
146 |
151 |
156 |
161 |
166 |
171 |
172 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/REBOOTERS/HybridApp/2f69af4e546f79d5bc4152f8a87853d21e9a4cf4/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/REBOOTERS/HybridApp/2f69af4e546f79d5bc4152f8a87853d21e9a4cf4/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/REBOOTERS/HybridApp/2f69af4e546f79d5bc4152f8a87853d21e9a4cf4/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/REBOOTERS/HybridApp/2f69af4e546f79d5bc4152f8a87853d21e9a4cf4/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/REBOOTERS/HybridApp/2f69af4e546f79d5bc4152f8a87853d21e9a4cf4/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/REBOOTERS/HybridApp/2f69af4e546f79d5bc4152f8a87853d21e9a4cf4/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/REBOOTERS/HybridApp/2f69af4e546f79d5bc4152f8a87853d21e9a4cf4/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/REBOOTERS/HybridApp/2f69af4e546f79d5bc4152f8a87853d21e9a4cf4/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/REBOOTERS/HybridApp/2f69af4e546f79d5bc4152f8a87853d21e9a4cf4/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/REBOOTERS/HybridApp/2f69af4e546f79d5bc4152f8a87853d21e9a4cf4/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | HybridApp
3 |
4 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/test/java/com/engineer/art/hybridapp/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.engineer.art.hybridapp;
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 | }
--------------------------------------------------------------------------------
/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 |
23 | maven {
24 | // All of React Native (JS, Android binaries) is installed from npm
25 | url "$rootDir/node_modules/react-native/android"
26 | }
27 | }
28 |
29 |
30 | }
31 |
32 | task clean(type: Delete) {
33 | delete rootProject.buildDir
34 | }
35 |
--------------------------------------------------------------------------------
/capture/box.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/REBOOTERS/HybridApp/2f69af4e546f79d5bc4152f8a87853d21e9a4cf4/capture/box.gif
--------------------------------------------------------------------------------
/capture/index.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/REBOOTERS/HybridApp/2f69af4e546f79d5bc4152f8a87853d21e9a4cf4/capture/index.gif
--------------------------------------------------------------------------------
/capture/movie.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/REBOOTERS/HybridApp/2f69af4e546f79d5bc4152f8a87853d21e9a4cf4/capture/movie.gif
--------------------------------------------------------------------------------
/capture/person.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/REBOOTERS/HybridApp/2f69af4e546f79d5bc4152f8a87853d21e9a4cf4/capture/person.gif
--------------------------------------------------------------------------------
/capture/reading.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/REBOOTERS/HybridApp/2f69af4e546f79d5bc4152f8a87853d21e9a4cf4/capture/reading.png
--------------------------------------------------------------------------------
/capture/top250.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/REBOOTERS/HybridApp/2f69af4e546f79d5bc4152f8a87853d21e9a4cf4/capture/top250.gif
--------------------------------------------------------------------------------
/capture/usercenter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/REBOOTERS/HybridApp/2f69af4e546f79d5bc4152f8a87853d21e9a4cf4/capture/usercenter.png
--------------------------------------------------------------------------------
/capture/video.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/REBOOTERS/HybridApp/2f69af4e546f79d5bc4152f8a87853d21e9a4cf4/capture/video.gif
--------------------------------------------------------------------------------
/capture/yuanxian.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/REBOOTERS/HybridApp/2f69af4e546f79d5bc4152f8a87853d21e9a4cf4/capture/yuanxian.gif
--------------------------------------------------------------------------------
/capture/yuanxian2.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/REBOOTERS/HybridApp/2f69af4e546f79d5bc4152f8a87853d21e9a4cf4/capture/yuanxian2.gif
--------------------------------------------------------------------------------
/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 |
14 | # When configured, Gradle will run in incubating parallel mode.
15 | # This option should only be used with decoupled projects. More details, visit
16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
17 | # org.gradle.parallel=true
18 | android.useDeprecatedNdk=true
19 |
20 |
21 | MYAPP_RELEASE_STORE_FILE=release.jks
22 | MYAPP_RELEASE_KEY_ALIAS=release
23 | MYAPP_RELEASE_STORE_PASSWORD=123456
24 | MYAPP_RELEASE_KEY_PASSWORD=123456
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/REBOOTERS/HybridApp/2f69af4e546f79d5bc4152f8a87853d21e9a4cf4/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Thu Feb 08 18:25:49 CST 2018
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 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | import './src/App';
--------------------------------------------------------------------------------
/npm-start.cmd:
--------------------------------------------------------------------------------
1 | @echo off
2 | echo npm start
3 |
4 | npm start
5 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Hybridapplication",
3 | "version": "1.0.0",
4 | "description": "hybrid application",
5 | "main": "index.js",
6 | "repository": {
7 | "type": "git",
8 | "url": "git+https://github.com/REBOOTERS/HybridApp.git"
9 | },
10 | "keywords": [
11 | "react",
12 | "native",
13 | "app",
14 | "android",
15 | "hybrid"
16 | ],
17 | "author": "rookie",
18 | "license": "ISC",
19 | "bugs": {
20 | "url": "https://github.com/REBOOTERS/HybridApp/issues"
21 | },
22 | "homepage": "https://github.com/REBOOTERS/HybridApp#readme",
23 | "scripts": {
24 | "start": "node node_modules/react-native/local-cli/cli.js start"
25 | },
26 | "dependencies": {
27 | "react": "16.0.0",
28 | "react-native": "0.51.0",
29 | "react-native-camera": "^0.12.0",
30 | "react-native-image-crop-picker": "^0.15.1",
31 | "react-native-popup-dialog": "^0.9.34",
32 | "react-native-video": "^2.0.0",
33 | "react-navigation": "^1.0.0-beta.22"
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/release.cmd:
--------------------------------------------------------------------------------
1 | @echo off
2 |
3 | echo react-native bundle --platform android --dev false --entry-file index.js --bundle-output app/src/main/assets/index.bundle --assets-dest app/src/main/res/
4 |
5 |
6 | react-native bundle --platform android --dev false --entry-file index.js --bundle-output app/src/main/assets/index.bundle --assets-dest app/src/main/res/ && echo gradlew clean && gradlew clean && echo gradlew assembleRelease && gradlew assembleRelease
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 | include ':react-native-camera'
3 | project(':react-native-camera').projectDir = new File(rootProject.projectDir, 'node_modules/react-native-camera/android')
4 | include ':react-native-video'
5 | project(':react-native-video').projectDir = new File(rootProject.projectDir, 'node_modules/react-native-video/android')
6 | include ':react-native-image-crop-picker'
7 | project(':react-native-image-crop-picker').projectDir = new File(rootProject.projectDir, 'node_modules/react-native-image-crop-picker/android')
--------------------------------------------------------------------------------
/src/App.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by Rookie on 2017/7/20.
3 | */
4 | import React, {Component} from 'react';
5 | import {
6 | AppRegistry,
7 | StatusBar,
8 | View,
9 | } from 'react-native';
10 |
11 |
12 | import AppNav from './nav/AppNav';
13 |
14 |
15 | export default class App extends Component {
16 |
17 | constructor(props){
18 | super(props);
19 | }
20 |
21 |
22 | render() {
23 | return (
24 |
25 |
29 |
30 |
31 | );
32 | }
33 | }
34 | AppRegistry.registerComponent('Hybridapplication', () => App);
--------------------------------------------------------------------------------
/src/components/HorizontalCardView.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by Rookie on 2017/7/20.
3 | */
4 |
5 | import React, { Component } from 'react';
6 |
7 | import { View, Text, Image, FlatList, TouchableNativeFeedback } from 'react-native';
8 |
9 | class SeparateComponent extends Component {
10 | render() {
11 | return ;
12 | }
13 | }
14 |
15 | export default class HorizontalListView extends Component {
16 | constructor(props) {
17 | super(props);
18 | const subjects = this.props.subjects;
19 |
20 | this.state = {
21 | subjects: subjects
22 | };
23 | }
24 |
25 | _renderItem = item => (
26 | {
28 | this.props.appNavigation.navigate('RankList', {
29 | id: item.item.id,
30 | name: item.item.name
31 | });
32 | }}
33 | >
34 |
35 |
45 |
56 | {item.item.name}
57 |
58 |
69 | {item.item.description}
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 | );
81 |
82 | _keyExtractor = item => item.id;
83 |
84 | render() {
85 | return (
86 |
87 |
95 |
96 | );
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/src/components/HorizontalListView.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by Rookie on 2017/7/20.
3 | */
4 |
5 | import React, { Component } from 'react';
6 |
7 | import { View, Text, Image, FlatList, TouchableOpacity, ImageBackground } from 'react-native';
8 |
9 | class MovieBoard extends Component {
10 | render() {
11 | let { item } = this.props.item;
12 |
13 | return (
14 |
15 | {
18 | this.props.navigation.navigate('MovieDetail', {
19 | id: item.id
20 | });
21 | }}
22 | >
23 |
24 |
29 |
40 | {item.title}
41 |
42 |
43 |
44 |
45 |
46 | );
47 | }
48 | }
49 |
50 | class MovieVideoBoard extends Component {
51 | render() {
52 | let { item } = this.props.item;
53 |
54 | return (
55 |
56 | {
59 | this.props.navigation.navigate('MovieVideoPlay', {
60 | item: item
61 | });
62 | }}
63 | >
64 |
65 |
70 |
74 |
75 |
86 | {item.subject_title}
87 |
88 |
97 | {item.title}
98 |
99 |
100 |
101 |
102 | );
103 | }
104 | }
105 |
106 | class SubjectsBoard extends Component {
107 | render() {
108 | let { item } = this.props.item;
109 |
110 | return (
111 |
112 | {
115 | this.props.navigation.navigate('SubjectDetail', {
116 | item: item
117 | });
118 | }}
119 | >
120 |
121 |
126 |
135 | {item.theme.name}
136 |
137 |
138 |
139 |
147 | {item.title}
148 |
149 |
150 |
151 |
152 |
153 | );
154 | }
155 | }
156 |
157 | class BottomTextComponent extends Component {
158 | render() {
159 | if (this.props.show) {
160 | return (
161 |
162 |
173 | {this.props.item.rating.average === 0 ? '暂无评分' : this.props.item.rating.average}
174 |
175 |
176 | );
177 | } else {
178 | return (
179 |
180 | {this.props.item.genres.map(function(gener) {
181 | return {gener} ;
182 | })}
183 |
184 | );
185 | }
186 | }
187 | }
188 |
189 | export default class HorizontalListView extends Component {
190 | constructor(props) {
191 | super(props);
192 | const type = this.props.type;
193 |
194 | this.state = {
195 | show: type === 'in_theaters'
196 | };
197 | }
198 |
199 | _renderItem = item => {
200 | switch (this.props.type) {
201 | case 'in_theaters':
202 | return ;
203 | case 'coming_soon':
204 | return ;
205 | case 'subjects':
206 | return ;
207 | case 'recommend_trailers':
208 | return (
209 |
210 | );
211 | }
212 | };
213 |
214 | _keyExtractor = item => item.id;
215 |
216 | render() {
217 | return (
218 |
225 | );
226 | }
227 | }
228 |
--------------------------------------------------------------------------------
/src/components/HorizontalSimpleView.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by Rookie on 2017/7/20.
3 | */
4 |
5 | import React, {Component} from 'react';
6 |
7 | import {
8 | View,
9 | Text,
10 | Image,
11 | FlatList,
12 | ToastAndroid,
13 | TouchableNativeFeedback,
14 | } from 'react-native';
15 |
16 |
17 |
18 | const default_avatar='https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1502705612736&di=8c0dcd505900aa1aa3b3' +
19 | 'f2b955436f80&imgtype=0&src=http%3A%2F%2Fimg4.duitang.com%2Fuploads%2Fitem%2F201403%2F20%2F20140320222513_dZf23.jpeg';
20 |
21 | class SeparateComponent extends Component {
22 | render() {
23 | return (
24 |
25 |
26 |
27 | )
28 | }
29 | }
30 |
31 |
32 |
33 | export default class HorizontalSimpleView extends Component {
34 |
35 | constructor(props) {
36 | super(props);
37 | const subjects = this.props.subjects;
38 |
39 |
40 | this.state = {
41 | subjects: subjects,
42 | }
43 | }
44 |
45 |
46 | _renderItem = ({item}) => (
47 |
48 |
49 | {
50 | this.props.navigation.navigate('MovieCelebrity', {
51 | id: item.id,
52 | name: item.name,
53 | });
54 | }}>
55 |
56 |
58 | {item.name}
68 |
69 |
70 |
71 |
72 |
73 | )
74 |
75 | _keyExtractor = (item,index) => index;
76 |
77 |
78 | render() {
79 |
80 |
81 | return (
82 |
83 |
91 |
92 |
93 |
94 |
95 | )
96 | }
97 | }
--------------------------------------------------------------------------------
/src/components/MainToolBar.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by Rookie on 2017/7/27.
3 | */
4 |
5 | import React, {Component} from 'react';
6 |
7 | import {
8 | View,
9 | Text,
10 | Image,
11 | TouchableOpacity,
12 | TouchableWithoutFeedback,
13 | ToastAndroid,
14 | } from 'react-native';
15 |
16 |
17 | let type;
18 |
19 | const title = "影视 图书 唱片 小组 舞台剧等";
20 |
21 | export default class MainToolBar extends Component {
22 |
23 |
24 | constructor(props) {
25 | super(props);
26 | type = this.props.type;
27 | }
28 |
29 |
30 | _goSearch = () => {
31 | this.props.navigation.navigate('Search', {
32 | type: type,
33 | })
34 | };
35 |
36 | _goScan = () => {
37 | this.props.navigation.navigate('Camera');
38 | };
39 |
40 | render() {
41 | return (
42 |
48 |
49 |
50 |
62 |
64 |
65 |
66 |
67 |
68 |
69 | {title}
70 |
71 |
72 |
73 |
74 |
76 |
77 |
78 |
79 |
80 |
81 |
82 | {
83 | ToastAndroid.showWithGravity("o(╯□╰)o", ToastAndroid.SHORT, ToastAndroid.CENTER);
84 | }}>
85 |
87 |
88 |
89 |
90 |
91 | )
92 | }
93 | }
--------------------------------------------------------------------------------
/src/components/NavigationItem.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2017-present, Liu Jinyong
3 | * All rights reserved.
4 | *
5 | * https://github.com/huanxsd/MeiTuan
6 | * @flow
7 | */
8 |
9 | //import liraries
10 | import React, { PureComponent } from 'react'
11 | import { View, Text, StyleSheet, TouchableOpacity, Image } from 'react-native'
12 |
13 | // create a component
14 | class NavigationItem extends PureComponent {
15 | render() {
16 | let icon = this.props.icon &&
17 |
18 |
19 | let title = this.props.title &&
20 | {this.props.title}
21 | return (
22 |
23 | {icon}
24 | {title}
25 |
26 | );
27 | }
28 | }
29 |
30 | // define your styles
31 | const styles = StyleSheet.create({
32 | container: {
33 | flex:1,
34 | flexDirection: 'row',
35 | justifyContent: 'center',
36 | alignItems: 'center',
37 | },
38 | icon: {
39 | width: 27,
40 | height: 27,
41 | margin: 8,
42 | },
43 | title: {
44 | fontSize: 15,
45 | color: '#333333',
46 | margin: 8,
47 | }
48 | });
49 |
50 | //make this component available to the app
51 | export default NavigationItem;
52 |
--------------------------------------------------------------------------------
/src/components/RatingCard.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by Rookie on 2017/7/26.
3 | */
4 |
5 | import React, {Component} from 'react';
6 |
7 | import {
8 | View,
9 | Text
10 | } from 'react-native'
11 |
12 | export default class RatingCard extends Component{
13 | render(){
14 | return(
15 |
16 | 豆瓣评分
17 | {this.props.average}
18 | {this.props.numRaters}人
19 |
20 | )
21 | }
22 | }
--------------------------------------------------------------------------------
/src/components/RefreshScrollView.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by Rookie on 2017/9/20.
3 | */
4 |
5 | import React, {Component} from 'react'
6 | import {RefreshControl, ScrollView} from "react-native";
7 |
8 |
9 | export default class RefreshScrollView extends Component {
10 | render() {
11 | return (
12 |
26 | }
27 | >
28 | {this.props.children}
29 |
30 |
31 | )
32 | }
33 | }
--------------------------------------------------------------------------------
/src/components/ToolBar.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by Rookie on 2017/7/27.
3 | */
4 |
5 | import React, {Component} from 'react';
6 |
7 | import {
8 | View,
9 | Text,
10 | Image,
11 | TouchableOpacity,
12 | } from 'react-native';
13 |
14 |
15 | let type;
16 |
17 | export default class ToolBar extends Component {
18 |
19 |
20 | constructor(props) {
21 | super(props);
22 | type = this.props.type;
23 | }
24 |
25 | _back = () => {
26 | this.props.navigation.goBack();
27 | };
28 |
29 | _goSearch = () => {
30 | this.props.navigation.navigate('Search', {
31 | type: type,
32 | })
33 | }
34 |
35 | render() {
36 | let onTab = this.props.onTab;
37 | let type = this.props.type;
38 |
39 | return (
40 |
47 |
48 |
49 | {onTab ? ( ) : (
50 |
51 |
53 | )
54 | }
55 |
56 |
57 |
58 |
59 | {this.props.title}
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 | )
68 | }
69 | }
--------------------------------------------------------------------------------
/src/components/VerticalListView.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by Rookie on 2017/7/20.
3 | */
4 |
5 | import React, {Component} from 'react';
6 |
7 | import {
8 | View,
9 | Text,
10 | Image,
11 | FlatList,
12 | ToastAndroid,
13 | TouchableNativeFeedback,
14 | } from 'react-native';
15 |
16 |
17 | class HText extends Component {
18 | render() {
19 |
20 | let text = this.props.bage + ": ";
21 |
22 | this.props.items.map(function (item) {
23 |
24 | text = text + item.name + "/";
25 |
26 | })
27 |
28 | text = text.substr(0, text.length - 1);
29 |
30 | return (
31 |
32 | {text}
33 |
34 | )
35 | }
36 | }
37 |
38 |
39 | class UxBoxItemView extends Component {
40 |
41 |
42 | render() {
43 |
44 | let item = this.props.item;
45 | let index = this.props.index;
46 |
47 | return (
48 |
49 | {this.props.showIndex ? (
50 |
51 |
52 | {parseInt(index) + 1}
56 |
57 | ) : ( )}
58 |
59 |
60 | {
61 | this.props.navigation.navigate('MovieDetail', {
62 | id: item.subject.id,
63 | });
64 | }}>
65 |
66 |
67 |
74 |
76 |
77 |
78 | {item.subject.title}
89 |
90 |
91 |
92 | {item.subject.rating.average == 0 ? "" : item.subject.rating.average}
94 |
97 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 | 票房{parseInt(item.box) / 1000}万美元
108 |
109 |
110 | )
111 | }
112 | }
113 |
114 | class Top250ItemView extends Component {
115 |
116 | render() {
117 | let item = this.props.item;
118 | let index = this.props.index;
119 |
120 | return (
121 |
122 | {this.props.showIndex ? (
123 |
124 |
125 | {parseInt(index) + 1}
129 |
130 | ) : ( )}
131 |
132 |
133 | {
134 | this.props.navigation.navigate('MovieDetail', {
135 | id: item.id,
136 | });
137 | }}>
138 |
139 |
140 |
147 |
149 |
150 |
151 | {item.title}
162 |
163 |
164 |
165 | {item.rating.average == 0 ? "" : item.rating.average}
167 |
170 |
173 |
174 |
175 |
176 |
177 |
178 | )
179 | }
180 | }
181 |
182 | export default class VerticalListView extends Component {
183 |
184 | constructor(props) {
185 | super(props);
186 | const subjects = this.props.subjects;
187 |
188 | this.state = {
189 | subjects: subjects,
190 | }
191 | }
192 |
193 |
194 | _renderItem = ({item, index}) => {
195 | switch (this.props.type) {
196 | case 'top250' :
197 | return ();
199 | case 'us_box':
200 | return (
201 | );
203 | default:
204 | return ();
206 | }
207 | };
208 |
209 |
210 | _keyExtractor = (item) => {
211 | if (item.id) {
212 | return item.id;
213 | } else if (item.rank) {
214 | return item.rank;
215 | }
216 | };
217 |
218 |
219 | render() {
220 |
221 | return (
222 |
228 | )
229 | }
230 | }
--------------------------------------------------------------------------------
/src/components/widgets/Loading.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by Rookie on 2017/9/21.
3 | */
4 |
5 | import React, {Component} from 'react';
6 | import {View, ActivityIndicator,Dimensions} from 'react-native';
7 |
8 | export default class Loading extends Component {
9 | render() {
10 | return (
11 |
12 |
18 |
21 |
22 |
26 |
27 |
28 |
29 | )
30 | }
31 | }
--------------------------------------------------------------------------------
/src/components/widgets/MoreView.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by Rookie on 2017/8/3.
3 | */
4 |
5 | import React, {Component} from 'react';
6 | import {Text, TouchableOpacity,} from "react-native";
7 |
8 |
9 | export default class MoreView extends Component {
10 |
11 |
12 | render() {
13 | return (
14 | {
15 | this.props.appNavigation.navigate('MovieList', {
16 | type: this.props.type,
17 | });
18 | }}>
19 |
20 |
21 | 更多>
22 |
23 |
24 |
25 |
26 | )
27 | }
28 | }
--------------------------------------------------------------------------------
/src/components/widgets/TitleView.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by Rookie on 2017/9/20.
3 | */
4 |
5 | import React, {Component} from 'react';
6 | import {View, Dimensions, Text,} from "react-native";
7 |
8 | const screenWidth = Dimensions.get('window').width;
9 |
10 | import MoreView from './MoreView';
11 |
12 | export default class TitleView extends Component {
13 |
14 |
15 | render() {
16 | return (
17 |
18 |
19 | {this.props.title}
20 |
21 | {this.props.needMore ? (
22 | ) : ( )}
23 |
24 | )
25 | }
26 | }
--------------------------------------------------------------------------------
/src/components/widgets/VerticalSapce.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by Rookie on 2017/9/20.
3 | */
4 |
5 | import React, {Component} from 'react';
6 | import {View,Dimensions,} from "react-native";
7 |
8 | const screenWidth = Dimensions.get('window').width;
9 |
10 | export default class VerticalSpace extends Component {
11 | render() {
12 | return ( )
13 | }
14 | }
--------------------------------------------------------------------------------
/src/images/avatar_male_100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/REBOOTERS/HybridApp/2f69af4e546f79d5bc4152f8a87853d21e9a4cf4/src/images/avatar_male_100.png
--------------------------------------------------------------------------------
/src/images/back.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/REBOOTERS/HybridApp/2f69af4e546f79d5bc4152f8a87853d21e9a4cf4/src/images/back.png
--------------------------------------------------------------------------------
/src/images/fake.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/REBOOTERS/HybridApp/2f69af4e546f79d5bc4152f8a87853d21e9a4cf4/src/images/fake.jpg
--------------------------------------------------------------------------------
/src/images/ic_ad_video_play.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/REBOOTERS/HybridApp/2f69af4e546f79d5bc4152f8a87853d21e9a4cf4/src/images/ic_ad_video_play.png
--------------------------------------------------------------------------------
/src/images/ic_bar_back_white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/REBOOTERS/HybridApp/2f69af4e546f79d5bc4152f8a87853d21e9a4cf4/src/images/ic_bar_back_white.png
--------------------------------------------------------------------------------
/src/images/ic_chat_white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/REBOOTERS/HybridApp/2f69af4e546f79d5bc4152f8a87853d21e9a4cf4/src/images/ic_chat_white.png
--------------------------------------------------------------------------------
/src/images/ic_scan_gray.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/REBOOTERS/HybridApp/2f69af4e546f79d5bc4152f8a87853d21e9a4cf4/src/images/ic_scan_gray.png
--------------------------------------------------------------------------------
/src/images/ic_search_gray.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/REBOOTERS/HybridApp/2f69af4e546f79d5bc4152f8a87853d21e9a4cf4/src/images/ic_search_gray.png
--------------------------------------------------------------------------------
/src/images/index_bg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/REBOOTERS/HybridApp/2f69af4e546f79d5bc4152f8a87853d21e9a4cf4/src/images/index_bg.jpg
--------------------------------------------------------------------------------
/src/images/live_player_bg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/REBOOTERS/HybridApp/2f69af4e546f79d5bc4152f8a87853d21e9a4cf4/src/images/live_player_bg.jpg
--------------------------------------------------------------------------------
/src/images/search.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/REBOOTERS/HybridApp/2f69af4e546f79d5bc4152f8a87853d21e9a4cf4/src/images/search.png
--------------------------------------------------------------------------------
/src/localdata/book.json:
--------------------------------------------------------------------------------
1 | {"rating":{"max":10,"numRaters":11294,"average":"9.2","min":0},"subtitle":"","author":["(法)圣埃克苏佩里"],"pubdate":"2000-9-1","tags":[{"count":2924,"name":"小王子","title":"小王子"},{"count":2311,"name":"童话","title":"童话"},{"count":1427,"name":"圣埃克苏佩里","title":"圣埃克苏佩里"},{"count":1079,"name":"法国","title":"法国"},{"count":855,"name":"经典","title":"经典"},{"count":744,"name":"外国文学","title":"外国文学"},{"count":620,"name":"感动","title":"感动"},{"count":472,"name":"寓言","title":"寓言"}],"origin_title":"","image":"https://img3.doubanio.com\/mpic\/s3294754.jpg","binding":"平装","translator":["胡雨苏"],"catalog":"序言:法兰西玫瑰\n小王子\n圣埃克苏佩里年表\n","pages":"111","images":{"small":"https://img3.doubanio.com\/spic\/s3294754.jpg","large":"https://img3.doubanio.com\/lpic\/s3294754.jpg","medium":"https://img3.doubanio.com\/mpic\/s3294754.jpg"},"alt":"https:\/\/book.douban.com\/subject\/1003078\/","id":"1003078","publisher":"中国友谊出版公司","isbn10":"7505715666","isbn13":"9787505715660","title":"小王子","url":"https:\/\/api.douban.com\/v2\/book\/1003078","alt_title":"","author_intro":"圣埃克苏佩里(1900-1944)1900年,尼采逝世。这一年,安德烈・纪德在布鲁塞尔一次会议上宣称:“当今文学土地的面貌可以说是一片沼泽。”1900年,圣埃克苏佩里诞生。净化沼泽的意愿和能力历史地落在这个“世纪儿”的身上,圣埃克苏佩里是尼采式的第二代法国作家,拿但业的儿子,琐罗亚斯德的孙子,这个飞行员受到极大的遗传影响。灾种影响使他在探索、忧虑和英雄主义的道路上走到尽头。如尼采所说:“你应该超截止自己,走得更远,登得更高,直至群星在你脚下。”尼采成为他座舱中想象的伙伴。这个飞越沙漠和海洋的年轻驾驶员同样也遵循着纪德的教诲:“与其过宁静的生活,不如过悲怆的生活。”圣埃克苏佩里在他整个的一生中都在反复思考力量和热诚的真谛。\n圣埃克苏佩里(AntoinedeSaiot-Exupery),1900年出生于法国里昂,1921-1923年在法国空军中服役,曾是后备飞行员,后来又成为民用航空驾驶员,参加了开辟法国――非洲――南美国际航线的工作,其间他还从事文学写作,作品有《南线班机》(1930),《夜航》(1931)等等。\n1939年德国法西斯入侵法国,鉴于圣埃克苏佩里曾多次受伤,医生认为他不能再入伍参战;但经他坚决要求,参加了抗德战争,被编入2\/33空军侦察大队。1940年法国在战争中溃败,他所在的部队损失惨重,该部被调往阿尔及尔,随后即被复员,他只身流亡美国。在美国期间,他继续从事写作,1940年发表了《战斗飞行员》,1943年发表了《给一个人质的信》以及《小王子》。\n1943年,在他的强烈要求下,他回到法国在北非的抗战基地阿尔及尔。他的上级考虑到他的身体和年龄状况,只同意他执行五次飞行任务,他却要求到八次,1944年7月31日上午,他出航执行第八次任务,从此再也没有回来,牺牲时,年仅44岁。\n在欧洲某地的一个湖中,发现了圣・德克旭贝里的飞机残骸。这次搜索是经过对他最后一次出航的线路和德军当时的空军记录研究以后进行的,经过认证确认是那架失踪了半个世纪的侦察机。为了纪念这位伟大的战士和文学家,当地决定为这架飞机的残骸建立一个博物馆,以他的名字命名,陈列他的作品和遗物。","summary":"小王子驾到!大家好,我是小王子,生活在B612星球,别看我是王子出生,我要做的事也不少,有时给花浇水,有时我还得耐心地把火山口通一通。实在闷得发慌的时候,为了找些事做,学点东西,我也访问一些其他的星球,像325号、326号、327号之类的。当然,我经历的事情也不少,有开心的,也有不开心的。这些事我通常会向地球上一个叫圣埃克苏佩里的人倾诉。对了,你可不要小瞧他,他是拿但业的儿子,琐罗亚斯德的孙子。他还被人们认为尼采式的第二代法国作家。他一生有两大爱好:飞行和写作。我之所以能够这样受欢迎也是他的功劳。因为他把我在其他星球的所见所闻编成了一本小书,也就是你们即将看到的这一本。它不但被誉为有史以来阅读仅次于《圣经》的书,全球发行的语言更是超过100种。可惜的是,在这本书出版后没多久,他在一次架机执行任务时一去不复返了,没有人知道他去了哪里。今天我第一次来到中国,还希望大家同样能够喜欢我。在这本书里他收藏了很多我在其他星球的精美彩图,而且,值得一提的是,中国著名的评论家周国平先生也特意为我作序。可以说,这本书不仅小朋友们爱不释手,就连大人们也会看得如痴如醉。糟糕,我还忘了告诉你,你只有在卓越网(www.joyo.com)才能找到我。有缘的话,我们很快就能相见了。\n尼采、纪德、圣埃克苏佩里是同一家庭的成员,由无可否认的联系连在一起。圣埃克苏佩里热爱尼采。纪德热爱圣埃克苏佩里。\n1945年2月1日《费加罗报》上,他谈到这位飞行员:\"他无论在何处着陆,都是为了带去欢乐。\"\n但是圣埃克苏佩里将公正置于友谊之上。他在《札记》中写道:\"纪德评价,却不曾体验。\"确切的见解。这是行动者面对思想者所感到的骄傲。尼采和纪德孕育了一种道德,并用美妙的文学冲动表现出来。只有圣埃克苏佩里一人在危险和充实中体验了这种道德。他是翱翔于九天的琐罗亚斯德,是乘风飞去的拿但业。他的书房便是机舱。他的格言:事事体验。他的作品:生活。圣埃克苏佩里对尼采的力量和纪德的热诚做作了合理的总结:他的冒险为职业,把写作当嗜好,他在飞行员的位置上实现着克尔桤郭尔的愿望:\"做一个思想家和做一个人,二者尽量不要区别开来,这样才是明智的。\"--(法)玛雅·戴斯特莱姆","price":"19.8"}
--------------------------------------------------------------------------------
/src/localdata/celebrity.json:
--------------------------------------------------------------------------------
1 | {"mobile_url": "https:\/\/movie.douban.com\/celebrity\/1052359\/mobile", "aka_en": ["Little fox (\u6635\u79f0)", "Mimi (\u6635\u79f0)", "Little fox (\u6635\u79f0)", "Mini (\u6635\u79f0)"], "name": "\u6768\u5e42", "works": [{"roles": ["\u6f14\u5458"], "subject": {"rating": {"max": 10, "average": 8.6, "stars": "45", "min": 0}, "genres": ["\u5267\u60c5", "\u4f20\u8bb0", "\u620f\u66f2"], "title": "\u7334\u5a03", "casts": [{"alt": "https:\/\/movie.douban.com\/celebrity\/1274392\/", "avatars": {"small": "https://img1.doubanio.com\/img\/celebrity\/small\/1453940528.49.jpg", "large": "https://img1.doubanio.com\/img\/celebrity\/large\/1453940528.49.jpg", "medium": "https://img1.doubanio.com\/img\/celebrity\/medium\/1453940528.49.jpg"}, "name": "\u516d\u5c0f\u9f84\u7ae5", "id": "1274392"}, {"alt": null, "avatars": null, "name": "\u674e\u6d77\u9f99", "id": null}, {"alt": "https:\/\/movie.douban.com\/celebrity\/1325171\/", "avatars": {"small": "https://img3.doubanio.com\/img\/celebrity\/small\/1394789723.05.jpg", "large": "https://img3.doubanio.com\/img\/celebrity\/large\/1394789723.05.jpg", "medium": "https://img3.doubanio.com\/img\/celebrity\/medium\/1394789723.05.jpg"}, "name": "\u7ae0\u52bc", "id": "1325171"}], "collect_count": 514, "original_title": "\u7334\u5a03", "subtype": "tv", "directors": [{"alt": "https:\/\/movie.douban.com\/celebrity\/1305125\/", "avatars": {"small": "https://img1.doubanio.com\/img\/celebrity\/small\/1378184969.47.jpg", "large": "https://img1.doubanio.com\/img\/celebrity\/large\/1378184969.47.jpg", "medium": "https://img1.doubanio.com\/img\/celebrity\/medium\/1378184969.47.jpg"}, "name": "\u738b\u541b\u6b63", "id": "1305125"}, {"alt": "https:\/\/movie.douban.com\/celebrity\/1317196\/", "avatars": {"small": "https://img1.doubanio.com\/img\/celebrity\/small\/38957.jpg", "large": "https://img1.doubanio.com\/img\/celebrity\/large\/38957.jpg", "medium": "https://img1.doubanio.com\/img\/celebrity\/medium\/38957.jpg"}, "name": "\u674e\u5c0f\u5a49", "id": "1317196"}], "year": "1993", "images": {"small": "https://img3.doubanio.com\/spic\/s3343920.jpg", "large": "https://img3.doubanio.com\/lpic\/s3343920.jpg", "medium": "https://img3.doubanio.com\/mpic\/s3343920.jpg"}, "alt": "https:\/\/movie.douban.com\/subject\/2252765\/", "id": "2252765"}}, {"roles": ["\u914d\u97f3"], "subject": {"rating": {"max": 10, "average": 7.7, "stars": "40", "min": 0}, "genres": ["\u559c\u5267", "\u52a8\u4f5c", "\u52a8\u753b"], "title": "\u529f\u592b\u718a\u732b3", "casts": [{"alt": "https:\/\/movie.douban.com\/celebrity\/1049492\/", "avatars": {"small": "https://img3.doubanio.com\/img\/celebrity\/small\/35722.jpg", "large": "https://img3.doubanio.com\/img\/celebrity\/large\/35722.jpg", "medium": "https://img3.doubanio.com\/img\/celebrity\/medium\/35722.jpg"}, "name": "\u6770\u514b\u00b7\u5e03\u83b1\u514b", "id": "1049492"}, {"alt": "https:\/\/movie.douban.com\/celebrity\/1054447\/", "avatars": {"small": "https://img3.doubanio.com\/img\/celebrity\/small\/1592.jpg", "large": "https://img3.doubanio.com\/img\/celebrity\/large\/1592.jpg", "medium": "https://img3.doubanio.com\/img\/celebrity\/medium\/1592.jpg"}, "name": "\u5b89\u5409\u4e3d\u5a1c\u00b7\u6731\u8389", "id": "1054447"}, {"alt": "https:\/\/movie.douban.com\/celebrity\/1054427\/", "avatars": {"small": "https://img3.doubanio.com\/img\/celebrity\/small\/604.jpg", "large": "https://img3.doubanio.com\/img\/celebrity\/large\/604.jpg", "medium": "https://img3.doubanio.com\/img\/celebrity\/medium\/604.jpg"}, "name": "\u8fbe\u65af\u6c40\u00b7\u970d\u592b\u66fc", "id": "1054427"}], "collect_count": 187075, "original_title": "Kung Fu Panda 3", "subtype": "movie", "directors": [{"alt": "https:\/\/movie.douban.com\/celebrity\/1301570\/", "avatars": {"small": "https://img3.doubanio.com\/img\/celebrity\/small\/27153.jpg", "large": "https://img3.doubanio.com\/img\/celebrity\/large\/27153.jpg", "medium": "https://img3.doubanio.com\/img\/celebrity\/medium\/27153.jpg"}, "name": "\u5415\u5bc5\u8363", "id": "1301570"}, {"alt": "https:\/\/movie.douban.com\/celebrity\/1351289\/", "avatars": {"small": "https://img3.doubanio.com\/img\/celebrity\/small\/1453889524.61.jpg", "large": "https://img3.doubanio.com\/img\/celebrity\/large\/1453889524.61.jpg", "medium": "https://img3.doubanio.com\/img\/celebrity\/medium\/1453889524.61.jpg"}, "name": "\u4e9a\u5386\u5c71\u5fb7\u7f57\u00b7\u5361\u7f57\u5c3c", "id": "1351289"}], "year": "2016", "images": {"small": "https://img3.doubanio.com\/view\/movie_poster_cover\/ipst\/public\/p2306653420.webp", "large": "https://img3.doubanio.com\/view\/movie_poster_cover\/lpst\/public\/p2306653420.webp", "medium": "https://img3.doubanio.com\/view\/movie_poster_cover\/spst\/public\/p2306653420.webp"}, "alt": "https:\/\/movie.douban.com\/subject\/11589036\/", "id": "11589036"}}, {"roles": ["\u6f14\u5458"], "subject": {"rating": {"max": 10, "average": 7.6, "stars": "40", "min": 0}, "genres": ["\u5267\u60c5", "\u5386\u53f2"], "title": "\u6d2a\u6b66\u5927\u6848", "casts": [{"alt": "https:\/\/movie.douban.com\/celebrity\/1274438\/", "avatars": {"small": "https://img1.doubanio.com\/img\/celebrity\/small\/32977.jpg", "large": "https://img1.doubanio.com\/img\/celebrity\/large\/32977.jpg", "medium": "https://img1.doubanio.com\/img\/celebrity\/medium\/32977.jpg"}, "name": "\u674e\u7acb\u7fa4", "id": "1274438"}, {"alt": "https:\/\/movie.douban.com\/celebrity\/1044611\/", "avatars": {"small": "https://img1.doubanio.com\/img\/celebrity\/small\/34429.jpg", "large": "https://img1.doubanio.com\/img\/celebrity\/large\/34429.jpg", "medium": "https://img1.doubanio.com\/img\/celebrity\/medium\/34429.jpg"}, "name": "\u4fdd\u5251\u950b", "id": "1044611"}, {"alt": "https:\/\/movie.douban.com\/celebrity\/1052359\/", "avatars": {"small": "https://img3.doubanio.com\/img\/celebrity\/small\/37843.jpg", "large": "https://img3.doubanio.com\/img\/celebrity\/large\/37843.jpg", "medium": "https://img3.doubanio.com\/img\/celebrity\/medium\/37843.jpg"}, "name": "\u6768\u5e42", "id": "1052359"}], "collect_count": 442, "original_title": "\u6d2a\u6b66\u5927\u6848", "subtype": "tv", "directors": [{"alt": null, "avatars": null, "name": "\u66f9\u4e1c", "id": null}], "year": "2011", "images": {"small": "https://img3.doubanio.com\/view\/movie_poster_cover\/ipst\/public\/p2374993302.webp", "large": "https://img3.doubanio.com\/view\/movie_poster_cover\/lpst\/public\/p2374993302.webp", "medium": "https://img3.doubanio.com\/view\/movie_poster_cover\/spst\/public\/p2374993302.webp"}, "alt": "https:\/\/movie.douban.com\/subject\/4925440\/", "id": "4925440"}}, {"roles": ["\u6f14\u5458"], "subject": {"rating": {"max": 10, "average": 7.6, "stars": "40", "min": 0}, "genres": ["\u5267\u60c5", "\u52a8\u4f5c", "\u6b66\u4fa0"], "title": "\u7ee3\u6625\u5200II\uff1a\u4fee\u7f57\u6218\u573a", "casts": [{"alt": "https:\/\/movie.douban.com\/celebrity\/1077991\/", "avatars": {"small": "https://img1.doubanio.com\/img\/celebrity\/small\/1453574419.48.jpg", "large": "https://img1.doubanio.com\/img\/celebrity\/large\/1453574419.48.jpg", "medium": "https://img1.doubanio.com\/img\/celebrity\/medium\/1453574419.48.jpg"}, "name": "\u5f20\u9707", "id": "1077991"}, {"alt": "https:\/\/movie.douban.com\/celebrity\/1052359\/", "avatars": {"small": "https://img3.doubanio.com\/img\/celebrity\/small\/37843.jpg", "large": "https://img3.doubanio.com\/img\/celebrity\/large\/37843.jpg", "medium": "https://img3.doubanio.com\/img\/celebrity\/medium\/37843.jpg"}, "name": "\u6768\u5e42", "id": "1052359"}, {"alt": "https:\/\/movie.douban.com\/celebrity\/1274761\/", "avatars": {"small": "https://img3.doubanio.com\/img\/celebrity\/small\/25943.jpg", "large": "https://img3.doubanio.com\/img\/celebrity\/large\/25943.jpg", "medium": "https://img3.doubanio.com\/img\/celebrity\/medium\/25943.jpg"}, "name": "\u5f20\u8bd1", "id": "1274761"}], "collect_count": 61890, "original_title": "\u7ee3\u6625\u5200II\uff1a\u4fee\u7f57\u6218\u573a", "subtype": "movie", "directors": [{"alt": "https:\/\/movie.douban.com\/celebrity\/1321200\/", "avatars": {"small": "https://img3.doubanio.com\/img\/celebrity\/small\/59201.jpg", "large": "https://img3.doubanio.com\/img\/celebrity\/large\/59201.jpg", "medium": "https://img3.doubanio.com\/img\/celebrity\/medium\/59201.jpg"}, "name": "\u8def\u9633", "id": "1321200"}], "year": "2017", "images": {"small": "https://img1.doubanio.com\/view\/movie_poster_cover\/ipst\/public\/p2492665487.webp", "large": "https://img1.doubanio.com\/view\/movie_poster_cover\/lpst\/public\/p2492665487.webp", "medium": "https://img1.doubanio.com\/view\/movie_poster_cover\/spst\/public\/p2492665487.webp"}, "alt": "https:\/\/movie.douban.com\/subject\/26270502\/", "id": "26270502"}}, {"roles": ["\u6f14\u5458"], "subject": {"rating": {"max": 10, "average": 7.6, "stars": "40", "min": 0}, "genres": ["\u5267\u60c5", "\u7231\u60c5", "\u53e4\u88c5"], "title": "\u7f8e\u4eba\u5fc3\u8ba1", "casts": [{"alt": "https:\/\/movie.douban.com\/celebrity\/1005214\/", "avatars": {"small": "https://img3.doubanio.com\/img\/celebrity\/small\/36663.jpg", "large": "https://img3.doubanio.com\/img\/celebrity\/large\/36663.jpg", "medium": "https://img3.doubanio.com\/img\/celebrity\/medium\/36663.jpg"}, "name": "\u6797\u5fc3\u5982", "id": "1005214"}, {"alt": "https:\/\/movie.douban.com\/celebrity\/1052359\/", "avatars": {"small": "https://img3.doubanio.com\/img\/celebrity\/small\/37843.jpg", "large": "https://img3.doubanio.com\/img\/celebrity\/large\/37843.jpg", "medium": "https://img3.doubanio.com\/img\/celebrity\/medium\/37843.jpg"}, "name": "\u6768\u5e42", "id": "1052359"}, {"alt": "https:\/\/movie.douban.com\/celebrity\/1313574\/", "avatars": {"small": "https://img3.doubanio.com\/img\/celebrity\/small\/18662.jpg", "large": "https://img3.doubanio.com\/img\/celebrity\/large\/18662.jpg", "medium": "https://img3.doubanio.com\/img\/celebrity\/medium\/18662.jpg"}, "name": "\u738b\u4e3d\u5764", "id": "1313574"}], "collect_count": 48461, "original_title": "\u7f8e\u4eba\u5fc3\u8ba1", "subtype": "tv", "directors": [{"alt": "https:\/\/movie.douban.com\/celebrity\/1318119\/", "avatars": {"small": "https://img1.doubanio.com\/img\/celebrity\/small\/42287.jpg", "large": "https://img1.doubanio.com\/img\/celebrity\/large\/42287.jpg", "medium": "https://img1.doubanio.com\/img\/celebrity\/medium\/42287.jpg"}, "name": "\u5434\u9526\u6e90", "id": "1318119"}, {"alt": null, "avatars": null, "name": "\u6881\u6b23\u5168", "id": null}, {"alt": null, "avatars": null, "name": "\u9648\u56fd\u534e", "id": null}], "year": "2010", "images": {"small": "https://img3.doubanio.com\/view\/movie_poster_cover\/ipst\/public\/p587755970.webp", "large": "https://img3.doubanio.com\/view\/movie_poster_cover\/lpst\/public\/p587755970.webp", "medium": "https://img3.doubanio.com\/view\/movie_poster_cover\/spst\/public\/p587755970.webp"}, "alt": "https:\/\/movie.douban.com\/subject\/3933008\/", "id": "3933008"}}], "gender": "\u5973", "avatars": {"small": "https://img3.doubanio.com\/img\/celebrity\/small\/37843.jpg", "large": "https://img3.doubanio.com\/img\/celebrity\/large\/37843.jpg", "medium": "https://img3.doubanio.com\/img\/celebrity\/medium\/37843.jpg"}, "id": "1052359", "aka": ["\u7d2b\u66e6(\u6635\u79f0)", "\u5e42\u5e42(\u6635\u79f0)", "\u72d0\u72f8(\u6635\u79f0)", "\u5c0f\u5e42(\u6635\u79f0)", "\u72d0\u5c0f\u5e42(\u6635\u79f0)", "\u6768\u51fd\u6570"], "name_en": "Mi Yang", "born_place": "\u4e2d\u56fd,\u5317\u4eac", "alt": "https:\/\/movie.douban.com\/celebrity\/1052359\/"}
--------------------------------------------------------------------------------
/src/localdata/music.json:
--------------------------------------------------------------------------------
1 | {
2 | "id":10000037,
3 | "title":"我只在乎你",
4 | "alt":"https:\/\/music.douban.com\/music\/10000037",
5 | "author":[{"name":"邓丽君"}],
6 | "alt_title":"留聲經典復刻版",
7 | "tags":[
8 | {"count":20,"name":"经典"},
9 | {"count":20,"name":"邓丽君"}
10 | ],
11 | "summary": "邓丽君在1987年推出的唱片专集《我只在乎你》中,有三首歌的词作者是“桃丽莎”。其实,桃丽莎即是邓丽君自己(英文名TERESA的中译)。根据我手中的资料,邓丽君作的词并不多,虽然她确曾向媒体表示“最大的心愿是出一张一脚踢的唱片”——即由自己包办下全部的词曲和制作,但是因意外去世而没能实现。但是,在此专集中竟有三首之多,不能不令人关注。大体上说,这三首歌具有两种风格,一为写实,一为浪漫。《非龙非彲》以现代汉语与古汉语混合,歌词的意境悲凉,心态哀痛,而且隐含着非比寻常的寓意,笔者愿在此写出来就教于方家。",
12 | "image":"https://img3.doubanio.com\/spic\/s11185741.jpg",
13 | "mobile_link":"https:\/\/m.douban.com\/music\/subject\/10000037\/",
14 | "attrs":{
15 | "publisher":["环球"],
16 | "singer":["邓丽君"],
17 | "discs":["1"],
18 | "pubdate":["1987-01-02"],
19 | "title":["我只在乎你"],
20 | "media":["CD"],
21 | "tracks":["01. 酒醉的探戈\n02. 像故事般温柔\n03. 命运之川\n04. 爱人\n05. 午夜微风\n06. 夏日圣诞\n07. 非龙非彲\n08. 不着痕迹\n09. 心路过黄昏\n10. 我只在乎你"],
22 | "version":["专辑"]
23 | },
24 | "rating":{"max":10,"average":"0.0","numRaters":20,"min":0}
25 | }
--------------------------------------------------------------------------------
/src/localdata/only.json:
--------------------------------------------------------------------------------
1 | {"rating": {"max": 10, "average": 7.7, "stars": "40", "min": 0}, "reviews_count": 898, "wish_count": 19950, "douban_site": "", "year": "2017", "images": {"small": "https://img1.doubanio.com\/view\/movie_poster_cover\/ipst\/public\/p2492665487.webp", "large": "https://img1.doubanio.com\/view\/movie_poster_cover\/lpst\/public\/p2492665487.webp", "medium": "https://img1.doubanio.com\/view\/movie_poster_cover\/spst\/public\/p2492665487.webp"}, "alt": "https:\/\/movie.douban.com\/subject\/26270502\/", "id": "26270502", "mobile_url": "https:\/\/movie.douban.com\/subject\/26270502\/mobile", "title": "\u7ee3\u6625\u5200II\uff1a\u4fee\u7f57\u6218\u573a", "do_count": null, "share_url": "https:\/\/m.douban.com\/movie\/subject\/26270502", "seasons_count": null, "schedule_url": "https:\/\/movie.douban.com\/subject\/26270502\/cinema\/", "episodes_count": null, "countries": ["\u4e2d\u56fd\u5927\u9646"], "genres": ["\u52a8\u4f5c", "\u6b66\u4fa0", "\u53e4\u88c5"], "collect_count": 27697, "casts": [{"alt": "https:\/\/movie.douban.com\/celebrity\/1077991\/", "avatars": {"small": "https://img1.doubanio.com\/img\/celebrity\/small\/1453574419.48.jpg", "large": "https://img1.doubanio.com\/img\/celebrity\/large\/1453574419.48.jpg", "medium": "https://img1.doubanio.com\/img\/celebrity\/medium\/1453574419.48.jpg"}, "name": "\u5f20\u9707", "id": "1077991"}, {"alt": "https:\/\/movie.douban.com\/celebrity\/1052359\/", "avatars": {"small": "https://img3.doubanio.com\/img\/celebrity\/small\/37843.jpg", "large": "https://img3.doubanio.com\/img\/celebrity\/large\/37843.jpg", "medium": "https://img3.doubanio.com\/img\/celebrity\/medium\/37843.jpg"}, "name": "\u6768\u5e42", "id": "1052359"}, {"alt": "https:\/\/movie.douban.com\/celebrity\/1274761\/", "avatars": {"small": "https://img3.doubanio.com\/img\/celebrity\/small\/25943.jpg", "large": "https://img3.doubanio.com\/img\/celebrity\/large\/25943.jpg", "medium": "https://img3.doubanio.com\/img\/celebrity\/medium\/25943.jpg"}, "name": "\u5f20\u8bd1", "id": "1274761"}, {"alt": "https:\/\/movie.douban.com\/celebrity\/1312940\/", "avatars": {"small": "https://img1.doubanio.com\/img\/celebrity\/small\/1454395377.49.jpg", "large": "https://img1.doubanio.com\/img\/celebrity\/large\/1454395377.49.jpg", "medium": "https://img1.doubanio.com\/img\/celebrity\/medium\/1454395377.49.jpg"}, "name": "\u96f7\u4f73\u97f3", "id": "1312940"}], "current_season": null, "original_title": "\u7ee3\u6625\u5200II\uff1a\u4fee\u7f57\u6218\u573a", "summary": "\u660e\u5929\u542f\u4e03\u5e74\uff0c\u5317\u9547\u629a\u53f8\u9526\u8863\u536b\u6c88\u70bc\uff08\u5f20\u9707 \u9970\uff09\u5728\u4e00\u6b21\u626b\u9664\u4e71\u515a\u4efb\u52a1\u4e2d\uff0c\u4e3a\u6551\u753b\u5e08\u5317\u658b\uff08\u6768\u5e42 \u9970\uff09\uff0c\u5c06\u540c\u50da\u51cc\u4e91\u94e0\uff08\u6b66\u5f3a \u9970\uff09\u706d\u53e3\u3002\u6b64\u540e\u4e00\u65b9\u9762\u8981\u6446\u8131\u6765\u81ea\u9646\u6587\u662d\uff08\u5f20\u8bd1 \u9970\uff09\u3001\u88f4\u7eb6\uff08\u96f7\u4f73\u97f3 \u9970\uff09\u7684\u8d28\u7591\u4e0e\u8c03\u67e5\uff0c\u4e00\u65b9\u9762\u53c8\u5728\u795e\u79d8\u5973\u5b50\u7684\u8981\u631f\u4e0b\u653e\u706b\u70e7\u4e86\u9526\u8863\u536b\u7ecf\u5386\u53f8\u3002\u88f9\u631f\u5728\u4e71\u4e16\uff0c\u6c88\u70bc\u4e0e\u5317\u658b\u60c5\u9677\u5176\u4e2d\uff0c\u5374\u8d8a\u9677\u8d8a\u6df1\u3002\u800c\u5728\u8fd9\u4e00\u5207\u7684\u80cc\u540e\uff0c\u5de8\u5927\u9634\u8c0b\u6b63\u6697\u4e2d\u5e03\u5c40\u3002\u4f17\u751f\u5982\u877c\u8681\u56ff\u4e8e\u4fee\u7f57\u573a\uff0c\u9006\u9cde\u4e4b\u6218\uff0c\u4e00\u89e6\u5373\u53d1\u2026\u2026", "subtype": "movie", "directors": [{"alt": "https:\/\/movie.douban.com\/celebrity\/1321200\/", "avatars": {"small": "https://img3.doubanio.com\/img\/celebrity\/small\/59201.jpg", "large": "https://img3.doubanio.com\/img\/celebrity\/large\/59201.jpg", "medium": "https://img3.doubanio.com\/img\/celebrity\/medium\/59201.jpg"}, "name": "\u8def\u9633", "id": "1321200"}], "comments_count": 16174, "ratings_count": 26886, "aka": ["\u7ee3\u6625\u52002\uff1a\u4fee\u7f57\u6218\u573a", "\u7ee3\u6625\u5200\uff1a\u4fee\u7f57\u573a", "\u7ee3\u6625\u5200\u524d\u4f20"]}
--------------------------------------------------------------------------------
/src/localdata/selected_collections.json:
--------------------------------------------------------------------------------
1 | {
2 | "url": "",
3 | "module_name": "movie_selected_collections",
4 | "data": {
5 | "total": 4,
6 | "selected_collections": [
7 | {
8 | "description": "8分以上好电影",
9 | "url": "https://m.douban.com/app_topic/movie_top250",
10 | "uri": "douban://douban.com/subject_collection/movie_top250",
11 | "covers": [
12 | "https://img3.doubanio.com/view/movie_poster_cover/mpst/public/p480747492.jpg",
13 | "https://img3.doubanio.com/view/movie_poster_cover/mpst/public/p1910813120.jpg",
14 | "https://img3.doubanio.com/view/movie_poster_cover/mpst/public/p511118051.jpg"
15 | ],
16 | "rank": true,
17 | "background_color": "#E1A01A",
18 | "id": "movie_top250",
19 | "name": "豆瓣 Top250"
20 | },
21 | {
22 | "description": "7月14日 - 7月21日",
23 | "url": "https://m.douban.com/app_topic/movie_best",
24 | "uri": "douban://douban.com/subject_collection/movie_best",
25 | "covers": [
26 | "https://img1.doubanio.com/view/movie_poster_cover/mpst/public/p2490948849.jpg",
27 | "https://img3.doubanio.com/view/movie_poster_cover/mpst/public/p2405979810.jpg",
28 | "https://img1.doubanio.com/view/movie_poster_cover/mpst/public/p2453044439.jpg"
29 | ],
30 | "rank": true,
31 | "background_color": "#33BC61",
32 | "id": "movie_best",
33 | "name": "本周口碑榜"
34 | },
35 | {
36 | "description": "7月14日 - 7月21日",
37 | "url": "https://m.douban.com/app_topic/movie_hot",
38 | "uri": "douban://douban.com/subject_collection/movie_hot",
39 | "covers": [
40 | "https://img3.doubanio.com/view/movie_poster_cover/mpst/public/p2457983084.jpg",
41 | "https://img3.doubanio.com/view/movie_poster_cover/mpst/public/p2458949885.jpg",
42 | "https://img1.doubanio.com/view/movie_poster_cover/mpst/public/p2458020487.jpg"
43 | ],
44 | "rank": true,
45 | "background_color": "#A266C3",
46 | "id": "movie_hot",
47 | "name": "新片榜"
48 | },
49 | {
50 | "current_tab": "全国",
51 | "description": "票房最高排名",
52 | "tabs": [
53 | "全国",
54 | "北美"
55 | ],
56 | "uri": "douban://douban.com/subject_collection/movie_high_box_office",
57 | "rank": true,
58 | "url": "https://m.douban.com/app_topic/movie_high_box_office",
59 | "covers": [
60 | "https://img1.doubanio.com/view/movie_poster_cover/spst/public/p2475060299.jpg",
61 | "https://img3.doubanio.com/view/movie_poster_cover/mpst/public/p2469070974.jpg",
62 | "https://img3.doubanio.com/view/movie_poster_cover/mpst/public/p2471580153.jpg"
63 | ],
64 | "background_color": "#E56B87",
65 | "id": "movie_high_box_office",
66 | "name": "票房榜"
67 | }
68 | ],
69 | "title": "精选榜单"
70 | },
71 | "uri": "",
72 | "key": "selected_collections"
73 | }
--------------------------------------------------------------------------------
/src/nav/AppNav.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by Rookie on 2017/7/20.
3 | */
4 |
5 |
6 | import React from 'react';
7 | import {StackNavigator} from 'react-navigation';
8 |
9 |
10 | import IndexPage from '../page/IndexPage';
11 | import HomePage from '../page/HomePage';
12 | import MovieDetailPage from '../page/MovieDetailPage';
13 | import MovieCelebrityPage from '../page/MovieCelebrityPage';
14 | import MovieListPage from '../page/MovieListPage';
15 | import RankListPage from '../page/RankListPage';
16 | import SearchPage from '../page/SearchPage';
17 | import CameraPage from '../page/CameraPage';
18 | import UserCenterPage from '../page/UserCenterPager';
19 | import SubjectDetailPage from '../page/SubjectDetailPage';
20 | import MovieVideoPlayPage from '../page/MovieVideoPlayPage'
21 |
22 | const AppNav = StackNavigator({
23 | Index: {
24 | screen: IndexPage,
25 | },
26 | Home: {
27 | screen: HomePage,
28 | },
29 | MovieDetail: {
30 | screen: MovieDetailPage,
31 | },
32 | MovieCelebrity: {
33 | screen: MovieCelebrityPage,
34 | },
35 | MovieList: {
36 | screen: MovieListPage,
37 | },
38 | RankList: {
39 | screen: RankListPage,
40 | },
41 | Search: {
42 | screen: SearchPage,
43 | },
44 | Camera: {
45 | screen: CameraPage,
46 | },
47 | UserCenter: {
48 | screen: UserCenterPage,
49 | },
50 | SubjectDetail: {
51 | screen: SubjectDetailPage,
52 | },
53 | MovieVideoPlay: {
54 | screen: MovieVideoPlayPage,
55 | }
56 | },
57 | {
58 | initialRouteName: 'Home', // 默认显示界面
59 | navigationOptions: { // 屏幕导航的默认选项, 也可以在组件内用 static navigationOptions 设置(会覆盖此处的设置)
60 | header: null,
61 | cardStack: {
62 | gesturesEnabled: true
63 | }
64 | }
65 | ,
66 | mode: 'push', // 页面切换模式, 左右是card(相当于iOS中的push效果), 上下是modal(相当于iOS中的modal效果)
67 | headerMode: 'screen', // 导航栏的显示模式, screen: 有渐变透明效果, float: 无透明效果, none: 隐藏导航栏
68 | // onTransitionStart: () => {
69 | // console.log('导航栏切换开始');
70 | // }, // 回调
71 | // onTransitionEnd: () => {
72 | // console.log('导航栏切换结束');
73 | // } // 回调
74 |
75 | });
76 |
77 | export default AppNav;
--------------------------------------------------------------------------------
/src/nav/HomeNav.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by Rookie on 2017/7/20.
3 | */
4 |
5 | import React from 'react';
6 |
7 | import {TabNavigator} from 'react-navigation';
8 |
9 |
10 | import Movie from '../page/MoviePage';
11 | import Music from '../page/MusicPage';
12 | import Book from '../page/BookPage';
13 | import User from '../page/MinePage';
14 |
15 | const HomeNav = TabNavigator({
16 | Movie: {
17 | screen: Movie,
18 | navigationOptions: {
19 | tabBarLabel: '电影',
20 | },
21 | },
22 | Music: {
23 | screen: Music,
24 | navigationOptions: {
25 | tabBarLabel: '音乐',
26 | },
27 | },
28 | Book: {
29 | screen: Book,
30 | navigationOptions: {
31 | tabBarLabel: '读书'
32 | }
33 | },
34 | User: {
35 | screen: User,
36 | navigationOptions: {
37 | tabBarLabel: '我的'
38 | }
39 | }
40 | }, {
41 | lazy: true,
42 | initialRouteName: 'Movie',
43 | tabBarPosition: 'bottom',//tabbar放在底部
44 | swipeEnabled: false,//不能滑动切换
45 | animationEnabled: false,//不要切换动画
46 | tabBarOptions: {
47 | indicatorStyle: {
48 | height: 0,
49 | },
50 |
51 | activeTintColor: '#33BC61',
52 | inactiveTintColor: 'black',
53 | style: {backgroundColor: 'white', borderTopColor: 'black', borderTopWidth: 0.15},
54 | },
55 |
56 |
57 | });
58 |
59 |
60 | export default HomeNav;
61 |
62 |
--------------------------------------------------------------------------------
/src/page/BookPage.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by Rookie on 2017/7/21.
3 | */
4 |
5 |
6 | import React, {Component} from 'react';
7 |
8 | import {View, Text, Image, StyleSheet, ToastAndroid, ScrollView, ActivityIndicator} from 'react-native';
9 |
10 | import Api from '../util/Api';
11 | import RatingCard from "../components/RatingCard";
12 | import MainToolBar from "../components/MainToolBar";
13 | import Loading from '../components/widgets/Loading';
14 |
15 |
16 | let data = require('../localdata/book.json');
17 |
18 |
19 | export default class BookPage extends Component {
20 |
21 | constructor(props) {
22 | super(props);
23 |
24 |
25 | this.state = {
26 | url: 'https://api.douban.com/v2/book/1003078',
27 | data: '',
28 | done: false,
29 | subjects: [],
30 | };
31 |
32 | }
33 |
34 | componentDidMount() {
35 | Api.Get(this.state.url, null, this._success, this._error)
36 |
37 | // this._error();
38 | }
39 |
40 |
41 | _success = (resData) => {
42 | console.log('成功');
43 | console.log(resData.count);
44 |
45 |
46 | let temps = [];
47 |
48 |
49 | this.setState({
50 | data: resData,
51 | done: true,
52 | subjects: temps,
53 |
54 |
55 | })
56 | };
57 |
58 |
59 | _error = (resData) => {
60 | console.log('失败');
61 | console.log(resData);
62 |
63 | ToastAndroid.show("请求数据失败", ToastAndroid.SHORT);
64 |
65 |
66 | let temps = [];
67 |
68 |
69 | this.setState({
70 | data: data,
71 | done: true,
72 | subjects: temps,
73 |
74 |
75 | })
76 |
77 |
78 | }
79 |
80 |
81 | render() {
82 |
83 | let appNavigation = this.props.screenProps.appNavigation;
84 |
85 | if (!this.state.done) {
86 | return (
87 |
88 | )
89 | } else {
90 |
91 | return (
92 |
93 |
94 |
95 |
96 |
102 |
103 |
104 |
111 |
112 |
113 |
114 | {/*信息*/}
115 |
116 |
117 | {this.state.data.title}
124 |
125 |
126 | 作者:
127 | {this.state.data.author.map(function (author) {
128 | return {author}
129 | })}
130 |
131 |
132 | 出版社:
133 | {this.state.data.publisher}
134 |
135 |
136 | 出版时间:
137 | {this.state.data.pubdate}
138 |
139 |
140 |
141 |
145 |
146 |
147 | {/*summary*/}
148 | 简介
154 | {this.state.data.summary}
163 | 作者简介
170 |
171 | {this.state.data.author_intro}
180 |
181 |
182 |
183 |
184 |
185 |
186 | );
187 |
188 | }
189 |
190 | }
191 | }
192 |
193 | const styles = StyleSheet.create({
194 | container: {
195 | flex: 1,
196 | justifyContent: 'center',
197 | alignItems: 'center'
198 | },
199 |
200 | });
--------------------------------------------------------------------------------
/src/page/CameraPage.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by Rookie on 2017/8/7.
3 | */
4 | 'use strict';
5 | import React, {Component} from 'react';
6 | import {
7 | StyleSheet,
8 | Text,
9 | View
10 | } from 'react-native';
11 | import Camera from 'react-native-camera';
12 |
13 | export default class CameraPage extends Component {
14 | render() {
15 | return (
16 |
17 | {
19 | this.camera = cam;
20 | }}
21 | style={styles.preview}
22 | aspect={Camera.constants.Aspect.fill}>
23 | [CAPTURE]
24 |
25 |
26 | );
27 | }
28 |
29 | takePicture() {
30 | const options = {};
31 | //options.location = ...
32 | this.camera.capture({metadata: options})
33 | .then((data) => {
34 | if (this.props.navigation.state.params.getPhotos) {
35 | this.props.navigation.state.params.getPhotos(data);
36 | }
37 | this.props.navigation.goBack();
38 | })
39 | .catch((err) => {
40 | console.error(err);
41 | this.props.navigation.goBack();
42 | });
43 |
44 |
45 | }
46 | }
47 |
48 | const styles = StyleSheet.create({
49 | container: {
50 | flex: 1,
51 | flexDirection: 'row',
52 | },
53 | preview: {
54 | flex: 1,
55 | justifyContent: 'flex-end',
56 | alignItems: 'center'
57 | },
58 | capture: {
59 | flex: 0,
60 | backgroundColor: '#fff',
61 | borderRadius: 5,
62 | color: '#000',
63 | padding: 10,
64 | margin: 40
65 | }
66 | });
--------------------------------------------------------------------------------
/src/page/HomePage.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by Rookie on 2017/7/20.
3 | */
4 |
5 | import React, {Component} from 'react';
6 |
7 | import {
8 | StyleSheet,
9 | } from 'react-native';
10 |
11 | import HomeNav from '../nav/HomeNav';
12 |
13 |
14 | export default class HomePage extends Component {
15 | render() {
16 | return (
17 |
19 | );
20 | }
21 | }
22 |
23 |
24 | const styles = StyleSheet.create({
25 | index: {
26 | flex: 1,
27 | }
28 | });
29 |
--------------------------------------------------------------------------------
/src/page/IndexPage.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by Rookie on 2017/7/20.
3 | */
4 |
5 | import React, {Component} from 'react';
6 |
7 | import {
8 | View,
9 | StyleSheet,
10 | Button,
11 | Image,
12 | Text,
13 | TouchableOpacity,
14 | } from 'react-native';
15 |
16 |
17 | export default class IndexPage extends Component {
18 |
19 | constructor(props) {
20 | super(props);
21 | }
22 |
23 | goHome = () => {
24 | const {navigate} = this.props.navigation;
25 | navigate('Home')
26 | };
27 |
28 |
29 | render() {
30 | return (
31 |
32 |
33 |
34 |
35 | Go
36 |
37 |
38 |
39 | );
40 | }
41 |
42 |
43 | }
44 |
45 |
46 | const styles = StyleSheet.create({
47 | index: {
48 | flex: 1,
49 | backgroundColor: 'white',
50 | alignItems: 'center'
51 | },
52 | mybutton: {
53 | width: 80,
54 | backgroundColor: 'white',
55 | position: 'absolute',
56 | bottom: 200,
57 | },
58 | text: {
59 | textAlign: 'center',
60 | padding: 10,
61 | }
62 | });
63 |
--------------------------------------------------------------------------------
/src/page/MinePage.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by Rookie on 2017/8/22.
3 | */
4 | import React, { Component } from 'react';
5 |
6 | import {
7 | View,
8 | Text,
9 | StyleSheet,
10 | Image,
11 | Dimensions,
12 | TouchableOpacity,
13 | ScrollView,
14 | ImageBackground
15 | } from 'react-native';
16 |
17 | let windowWidth = Dimensions.get('window').width;
18 |
19 | export default class MinePage extends Component {
20 | _goUserCenter = () => {
21 | this.props.screenProps.appNavigation.navigate('UserCenter');
22 | };
23 |
24 | render() {
25 | return (
26 |
27 |
28 | 我的
29 |
30 |
31 |
32 |
36 |
42 |
43 | 十万个冷笑话
44 |
50 | ID:Bad Jokers
51 |
52 | 个人主页 >
53 |
54 |
55 |
56 |
64 |
65 |
66 | 关注 2
67 | 被关注 0
68 |
69 |
70 |
71 |
80 |
81 |
82 | );
83 | }
84 | }
85 |
86 | const styles = StyleSheet.create({
87 | container: {
88 | flex: 1,
89 | backgroundColor: '#eee'
90 | },
91 | toolbar: {
92 | height: 56,
93 | alignItems: 'center',
94 | backgroundColor: 'white',
95 | justifyContent: 'center'
96 | },
97 | title: {
98 | fontSize: 16,
99 | color: 'black'
100 | },
101 | userInfobg: {
102 | flexDirection: 'row',
103 | height: 160,
104 | width: windowWidth,
105 | alignItems: 'center'
106 | },
107 | avatar: {
108 | margin: 10,
109 | width: 80,
110 | height: 80,
111 | borderRadius: 40,
112 | borderWidth: 4,
113 | borderColor: 'white'
114 | }
115 | });
116 |
--------------------------------------------------------------------------------
/src/page/MovieCelebrityPage.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by Rookie on 2017/7/24.
3 | */
4 |
5 |
6 | import React, {Component} from 'react';
7 |
8 | import {View, WebView,StyleSheet,Text,ToastAndroid} from 'react-native';
9 |
10 | import Api from '../util/Api';
11 | import ToolBar from "../components/ToolBar";
12 | import Loading from "../components/widgets/Loading";
13 |
14 | let data = require('../localdata/only.json');
15 |
16 | export default class MovieCelebrityPage extends Component {
17 |
18 | constructor(props) {
19 | super(props);
20 |
21 | let id = this.props.navigation.state.params.id;
22 |
23 | this.state = {
24 | url: 'https://api.douban.com/v2/movie/celebrity/' + id,
25 | data: '',
26 | done: false,
27 | mobile_url: '',
28 | };
29 |
30 | }
31 |
32 | componentDidMount() {
33 | Api.Get(this.state.url, null, this._success, this._error)
34 |
35 | }
36 |
37 |
38 | _success = (resData) => {
39 | console.log('成功');
40 | console.log(resData.count);
41 |
42 |
43 |
44 | this.setState({
45 | data: resData,
46 | done: true,
47 | mobile_url:resData.mobile_url,
48 |
49 | })
50 | };
51 |
52 |
53 | _error = (resData) => {
54 | console.log('失败');
55 | console.log(resData);
56 |
57 | ToastAndroid.show("请求数据失败", ToastAndroid.SHORT);
58 |
59 |
60 | let temps = [];
61 |
62 | data.directors.map(function (director) {
63 | temps.push(director)
64 | })
65 |
66 | data.casts.map(function (cast) {
67 | temps.push(cast);
68 | });
69 |
70 |
71 | this.setState({
72 | data: data,
73 | done: true,
74 | subjects: temps,
75 |
76 |
77 | })
78 |
79 |
80 | }
81 |
82 |
83 | render() {
84 |
85 | let navigation = this.props.navigation;
86 |
87 | if (!this.state.done) {
88 | return (
89 |
90 | )
91 | } else {
92 |
93 | return (
94 |
95 |
101 |
102 |
106 |
107 |
108 | )
109 |
110 | }
111 |
112 | }
113 | }
114 |
115 | const styles = StyleSheet.create({
116 | container: {
117 | flex: 1,
118 | justifyContent: 'center',
119 | alignItems: 'center'
120 | },
121 |
122 | });
--------------------------------------------------------------------------------
/src/page/MovieDetailPage.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by Rookie on 2017/7/21.
3 | */
4 |
5 |
6 | import React, {Component} from 'react';
7 |
8 | import {View, Text, Image, StyleSheet, ToastAndroid, ScrollView, ActivityIndicator} from 'react-native';
9 |
10 | import HorizontalSimpleView from '../components/HorizontalSimpleView';
11 | import Api from '../util/Api';
12 | import RatingCard from "../components/RatingCard";
13 | import ToolBar from '../components/ToolBar';
14 | import Loading from '../components/widgets/Loading';
15 |
16 |
17 | let data = require('../localdata/only.json');
18 |
19 | export default class MovieDetailPage extends Component {
20 |
21 | constructor(props) {
22 | super(props);
23 |
24 | let id = this.props.navigation.state.params.id;
25 |
26 | this.state = {
27 | url: 'https://api.douban.com/v2/movie/subject/' + id,
28 | data: '',
29 | done: false,
30 | subjects: [],
31 | };
32 |
33 | }
34 |
35 | componentDidMount() {
36 | Api.Get(this.state.url, null, this._success, this._error)
37 |
38 | // this._error();
39 | }
40 |
41 |
42 | _success = (resData) => {
43 | console.log('成功');
44 | console.log(resData.count);
45 |
46 |
47 | let temps = [];
48 |
49 | resData.directors.map(function (director) {
50 | temps.push(director)
51 | });
52 |
53 |
54 | resData.casts.map(function (cast) {
55 | temps.push(cast);
56 | });
57 |
58 |
59 | this.setState({
60 | data: resData,
61 | done: true,
62 | subjects: temps,
63 |
64 |
65 | })
66 | };
67 |
68 |
69 | _error = (resData) => {
70 | console.log('失败');
71 | console.log(resData);
72 |
73 | ToastAndroid.show("请求数据失败", ToastAndroid.SHORT);
74 |
75 |
76 | let temps = [];
77 |
78 | data.directors.map(function (director) {
79 | temps.push(director)
80 | })
81 |
82 | data.casts.map(function (cast) {
83 | temps.push(cast);
84 | });
85 |
86 |
87 | this.setState({
88 | data: data,
89 | done: true,
90 | subjects: temps,
91 |
92 |
93 | })
94 |
95 |
96 | }
97 |
98 |
99 | render() {
100 | let navigation = this.props.navigation;
101 | if (!this.state.done) {
102 | return (
103 |
104 | )
105 | } else {
106 |
107 | return (
108 |
109 |
110 |
111 |
117 |
118 |
119 |
126 |
127 |
128 |
129 | {/*信息*/}
130 |
131 |
132 | {this.state.data.title}
139 |
140 |
141 | {this.state.data.year}
142 | {this.state.data.genres.map(function (gener, index) {
143 | return /{gener}
144 | })}
145 |
146 |
147 |
148 |
149 |
150 |
151 |
155 |
156 |
157 |
158 | {/*summary*/}
159 | 简介
165 | {this.state.data.summary}
172 | 影人
179 |
180 |
182 |
183 |
184 |
185 |
186 |
187 |
188 | );
189 |
190 | }
191 |
192 | }
193 | }
194 |
195 | const styles = StyleSheet.create({
196 | container: {
197 | flex: 1,
198 | justifyContent: 'center',
199 | alignItems: 'center'
200 | },
201 |
202 | });
--------------------------------------------------------------------------------
/src/page/MovieListPage.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by Rookie on 2017/8/3.
3 | */
4 |
5 | import React, {Component} from 'react';
6 |
7 | import {View, StyleSheet, Text, ToastAndroid} from 'react-native';
8 |
9 | import {TabNavigator} from 'react-navigation'
10 | import ToolBar from "../components/ToolBar";
11 |
12 | import MovieNow from './MovieTabPageNow';
13 | import MovieFuture from './MovieTabPageFuture';
14 |
15 |
16 | export default class MovieListPage extends Component {
17 |
18 |
19 | render() {
20 |
21 | let type = this.props.navigation.state.params.type;
22 |
23 | let showLeft = type === "Now";
24 |
25 |
26 | let navigation = this.props.navigation;
27 |
28 | return (
29 |
30 |
36 |
37 | {showLeft ? ( ) : ( )}
40 |
41 |
42 | )
43 | }
44 |
45 |
46 | }
47 |
48 |
49 | //TODO 默认页面是否可由参数控制,直接由一个TabNavigator完成 ???
50 |
51 | const MovieNav1 = TabNavigator({
52 | Now: {
53 | screen: MovieNow,
54 | navigationOptions: {
55 | tabBarLabel: '正在热映'
56 | }
57 | },
58 | Future: {
59 | screen: MovieFuture,
60 | navigationOptions: {
61 | tabBarLabel: '即将上映'
62 | }
63 | }
64 | }, {
65 | lazy: true,
66 | initialRouteName: 'Now',
67 | tabBarPosition: 'top',//tabbar放在顶部
68 | tabBarOptions: {
69 | indicatorStyle: {
70 | height: 0.5,
71 | backgroundColor: 'black',
72 | },
73 | activeTintColor: '#66b219',
74 | inactiveTintColor: 'black',
75 | style: {backgroundColor: 'white', borderTopColor: 'white', borderTopWidth: 1},
76 | },
77 |
78 |
79 | });
80 | const MovieNav2 = TabNavigator({
81 | Now: {
82 | screen: MovieNow,
83 | navigationOptions: {
84 | tabBarLabel: '正在热映'
85 | }
86 | },
87 | Future: {
88 | screen: MovieFuture,
89 | navigationOptions: {
90 | tabBarLabel: '即将上映'
91 | }
92 | }
93 | }, {
94 | lazy: true,
95 | initialRouteName: 'Future',
96 | tabBarPosition: 'top',//tabbar放在顶部
97 | tabBarOptions: {
98 | indicatorStyle: {
99 | height: 0.5,
100 | backgroundColor: 'black',
101 | },
102 | activeTintColor: '#66b219',
103 | inactiveTintColor: 'black',
104 | style: {backgroundColor: 'white', borderTopColor: 'white', borderTopWidth: 1},
105 | },
106 |
107 |
108 | });
109 |
110 |
111 | const styles = StyleSheet.create({
112 | container: {
113 | flex: 1,
114 | backgroundColor: 'white'
115 | }
116 | });
117 |
--------------------------------------------------------------------------------
/src/page/MoviePage.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by Rookie on 2017/7/20.
3 | */
4 | import React, {Component} from 'react';
5 | import {
6 | View,
7 | StyleSheet,
8 | ToastAndroid,
9 | Dimensions,
10 | ActivityIndicator
11 | } from 'react-native';
12 |
13 | import Api from '../util/Api';
14 |
15 | const screenWidth = Dimensions.get('window').width;
16 |
17 | import HorizontalListView from '../components/HorizontalListView';
18 | import HorizontalCardView from '../components/HorizontalCardView';
19 | import MainToolBar from "../components/MainToolBar";
20 | import RefreshScrollView from '../components/RefreshScrollView';
21 | import VerticalSpace from '../components/widgets/VerticalSapce';
22 | import TitleView from '../components/widgets/TitleView';
23 | import Loading from '../components/widgets/Loading';
24 |
25 | let movie_modules = require('../localdata/index.json');
26 |
27 |
28 | let in_threaters_data = require('../localdata/in_theaters.json');
29 | let coming_soon_data = require('../localdata/coming_soon.json');
30 | let selected_collections_data = require('../localdata/selected_collections.json');
31 |
32 |
33 | export default class MoviePage extends Component {
34 |
35 |
36 | constructor(props) {
37 | super(props);
38 |
39 |
40 | this.state = {
41 | url_in_theaters: 'https://api.douban.com/v2/movie/in_theaters',
42 | url_coming_soon: 'https://api.douban.com/v2/movie/coming_soon',
43 | subject_themes: [],
44 | recommend_trailers: [],
45 | in_theaters_subjects: [],
46 | coming_soon_subjects: [],
47 | selected_collections: [],
48 | done: false,
49 | isRefreshing: false,
50 | };
51 |
52 | }
53 |
54 |
55 | componentDidMount() {
56 |
57 | // Api.Get(this.state.url_in_theaters, null, this._success, this._error);
58 | // Api.Get(this.state.url_coming_soon, null, this.coming_soon_success, this._error);
59 |
60 | this._error();
61 |
62 | }
63 |
64 |
65 | _success = (resData) => {
66 | console.log('成功');
67 | console.log(resData.count);
68 |
69 |
70 | ToastAndroid.show("success==" + resData.subjects.length, ToastAndroid.SHORT);
71 |
72 | this.setState({
73 | in_theaters_subjects: resData.subjects,
74 | done: true,
75 | });
76 |
77 |
78 | };
79 |
80 | coming_soon_success = (resData) => {
81 | console.log('成功');
82 | console.log(resData.count);
83 |
84 | ToastAndroid.show("success-1==" + resData.subjects.length, ToastAndroid.SHORT);
85 | this.setState({
86 | coming_soon_subjects: resData.subjects,
87 | selected_collections: selected_collections_data.data.selected_collections,
88 | })
89 | };
90 |
91 |
92 | _error = (resData) => {
93 |
94 | console.log('失败');
95 | console.log(resData);
96 |
97 | ToastAndroid.show("load-cache", ToastAndroid.SHORT);
98 |
99 |
100 | this.setState({
101 | subject_themes: movie_modules.modules[0].data.items,
102 | recommend_trailers: movie_modules.modules[5].data.items,
103 | in_theaters_subjects: in_threaters_data.subjects,
104 | coming_soon_subjects: coming_soon_data.subjects,
105 | selected_collections: selected_collections_data.data.selected_collections,
106 | done: true,
107 | isRefreshing: false,
108 | })
109 | };
110 |
111 |
112 | _onRefreshData = () => {
113 |
114 | this.setState({isRefreshing: true, done: false});
115 |
116 | // Api.Get(this.state.url_in_theaters, null, this._success, this._error);
117 | // Api.Get(this.state.url_coming_soon, null, this.coming_soon_success, this._error);
118 |
119 | setTimeout(this._error, 1000);
120 | };
121 |
122 | render() {
123 |
124 |
125 | let appNavigation = this.props.screenProps.appNavigation;
126 |
127 |
128 | if (!this.state.done) {
129 | return (
130 |
131 | )
132 | } else {
133 | return (
134 |
135 |
136 |
137 |
138 |
139 |
145 |
146 |
150 |
151 |
152 |
156 |
157 |
158 |
159 |
163 |
164 |
165 |
166 |
171 |
172 |
173 |
174 |
175 |
178 |
179 |
180 |
181 |
186 |
187 |
188 |
189 |
190 | );
191 | }
192 |
193 |
194 | }
195 | }
196 |
197 | const styles = StyleSheet.create({
198 | container: {
199 | flex: 1,
200 | backgroundColor: 'white',
201 | justifyContent: 'center',
202 | alignItems: 'center'
203 | },
204 | recommendHeader: {
205 | height: 35,
206 | justifyContent: 'center',
207 | // borderWidth: screen.onePixel,
208 | // borderColor: color.border,
209 | paddingVertical: 8,
210 | paddingLeft: 20,
211 | backgroundColor: 'white'
212 | },
213 | searchBar: {
214 | width: screenWidth * 0.7,
215 | height: 30,
216 | borderRadius: 19,
217 | flexDirection: 'row',
218 | justifyContent: 'center',
219 | alignItems: 'center',
220 | backgroundColor: 'white',
221 | alignSelf: 'center',
222 | },
223 | searchIcon: {
224 | width: 20,
225 | height: 20,
226 | margin: 5,
227 | }
228 |
229 | });
230 |
--------------------------------------------------------------------------------
/src/page/MovieTabPageFuture.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by Rookie on 2017/8/3.
3 | */
4 |
5 | import React, {Component} from 'react';
6 |
7 |
8 | import {View, StyleSheet, Text, ToastAndroid, ActivityIndicator} from 'react-native';
9 |
10 | import VerticalListView from "../components/VerticalListView";
11 | import Loading from '../components/widgets/Loading';
12 | import Api from "../util/Api";
13 |
14 | let coming_soon_data = require('../localdata/coming_soon.json');
15 |
16 | export default class MovieTabPageFuture extends Component {
17 |
18 |
19 | constructor(props) {
20 | super(props);
21 |
22 | this.state = {
23 | url_in_theaters: 'https://api.douban.com/v2/movie/in_theaters',
24 | url_coming_soon: 'https://api.douban.com/v2/movie/coming_soon',
25 | Data: [],
26 | done: false,
27 | };
28 | }
29 |
30 |
31 | componentDidMount() {
32 |
33 | Api.Get(this.state.url_coming_soon, null, this._success, this._error);
34 |
35 | // this._error();
36 |
37 | }
38 |
39 |
40 | _success = (resData) => {
41 | console.log('成功');
42 | console.log(resData.count);
43 |
44 |
45 | this.setState({
46 | Data: resData.subjects,
47 | done: true,
48 | });
49 |
50 |
51 | };
52 |
53 |
54 | _error = (resData) => {
55 |
56 | console.log('失败');
57 | console.log(resData);
58 |
59 | ToastAndroid.show("请求数据失败-1", ToastAndroid.SHORT);
60 |
61 |
62 | this.setState({
63 | Data: coming_soon_data.subjects,
64 | done: true,
65 | })
66 | }
67 |
68 |
69 | render() {
70 |
71 | let navigation = this.props.screenProps.appNavigation;
72 | if (this.state.done) {
73 | return ( )
74 | } else {
75 | return ( )
76 | }
77 |
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/src/page/MovieTabPageNow.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by Rookie on 2017/8/3.
3 | */
4 |
5 | import React, {Component} from 'react';
6 |
7 |
8 | import {View, StyleSheet, Text, ToastAndroid, ActivityIndicator} from 'react-native';
9 |
10 | import VerticalListView from "../components/VerticalListView";
11 | import Api from "../util/Api";
12 | import Loading from "../components/widgets/Loading";
13 |
14 | let in_threaters_data = require('../localdata/in_theaters.json');
15 | let coming_soon_data = require('../localdata/coming_soon.json');
16 |
17 |
18 | export default class MovieTabPageNow extends Component {
19 |
20 |
21 | constructor(props) {
22 | super(props);
23 |
24 | this.state = {
25 | url_in_theaters: 'https://api.douban.com/v2/movie/in_theaters',
26 | url_coming_soon: 'https://api.douban.com/v2/movie/coming_soon',
27 | Data: [],
28 | done: false,
29 | };
30 | }
31 |
32 |
33 | componentDidMount() {
34 |
35 | Api.Get(this.state.url_in_theaters, null, this._success, this._error);
36 |
37 | // this._error();
38 |
39 | }
40 |
41 |
42 | _success = (resData) => {
43 | console.log('成功');
44 | console.log(resData.count);
45 |
46 |
47 | this.setState({
48 | Data: resData.subjects,
49 | done: true,
50 | });
51 |
52 |
53 | };
54 |
55 |
56 | _error = (resData) => {
57 |
58 | console.log('失败');
59 | console.log(resData);
60 |
61 | ToastAndroid.show("请求数据失败-1", ToastAndroid.SHORT);
62 |
63 |
64 | this.setState({
65 | Data: in_threaters_data.subjects,
66 | done: true,
67 | })
68 | };
69 |
70 |
71 | render() {
72 |
73 | let navigation = this.props.screenProps.appNavigation;
74 |
75 | if (this.state.done) {
76 | return ( )
77 | } else {
78 | return ( )
79 | }
80 | }
81 | }
82 |
83 | const styles = StyleSheet.create({
84 | container: {
85 | flex: 1,
86 | justifyContent: 'center',
87 | alignItems: 'center',
88 | backgroundColor: 'white'
89 | }
90 | });
--------------------------------------------------------------------------------
/src/page/MovieVideoPlayPage.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by Rookie on 2017/9/21.
3 | */
4 |
5 | import React, {Component} from 'react';
6 |
7 | import {Text, View, StyleSheet, TouchableOpacity} from 'react-native';
8 | import Video from "react-native-video";
9 |
10 | let item;
11 |
12 | export default class MovieVideoPlayPage extends Component {
13 |
14 | constructor(props) {
15 | super(props);
16 | item = this.props.navigation.state.params.item;
17 | console.log("video_url===" + item.video_url);
18 | }
19 |
20 | state = {
21 | rate: 1,
22 | volume: 1,
23 | muted: false,
24 | resizeMode: 'contain',
25 | duration: 0.0,
26 | currentTime: 0.0,
27 | paused: true,
28 | };
29 |
30 | video: Video;
31 |
32 | onLoad = (data) => {
33 | this.setState({ duration: data.duration });
34 | };
35 |
36 | onProgress = (data) => {
37 | this.setState({ currentTime: data.currentTime });
38 | };
39 |
40 | onEnd = () => {
41 | this.setState({ paused: true });
42 | this.video.seek(0)
43 | };
44 |
45 | onAudioBecomingNoisy = () => {
46 | this.setState({ paused: true })
47 | };
48 |
49 | onAudioFocusChanged = (event: { hasAudioFocus: boolean }) => {
50 | this.setState({ paused: !event.hasAudioFocus })
51 | };
52 |
53 | getCurrentTimePercentage() {
54 | if (this.state.currentTime > 0) {
55 | return parseFloat(this.state.currentTime) / parseFloat(this.state.duration);
56 | }
57 | return 0;
58 | };
59 |
60 | renderRateControl(rate) {
61 | const isSelected = (this.state.rate === rate);
62 |
63 | return (
64 | { this.setState({ rate }) }}>
65 |
66 | {rate}x
67 |
68 |
69 | );
70 | }
71 |
72 | renderResizeModeControl(resizeMode) {
73 | const isSelected = (this.state.resizeMode === resizeMode);
74 |
75 | return (
76 | { this.setState({ resizeMode }) }}>
77 |
78 | {resizeMode}
79 |
80 |
81 | )
82 | }
83 |
84 | renderVolumeControl(volume) {
85 | const isSelected = (this.state.volume === volume);
86 |
87 | return (
88 | { this.setState({ volume }) }}>
89 |
90 | {volume * 100}%
91 |
92 |
93 | )
94 | }
95 |
96 |
97 | render() {
98 | const flexCompleted = this.getCurrentTimePercentage() * 100;
99 | const flexRemaining = (1 - this.getCurrentTimePercentage()) * 100;
100 |
101 |
102 |
103 | return (
104 |
105 | this.setState({ paused: !this.state.paused })}>
108 | { this.video = ref }}
110 | /* For ExoPlayer */
111 | /* source={{ uri: 'http://www.youtube.com/api/manifest/dash/id/bf5bb2419360daf1/source/youtube?as=fmp4_audio_clear,fmp4_sd_hd_clear&sparams=ip,ipbits,expire,source,id,as&ip=0.0.0.0&ipbits=0&expire=19000000000&signature=51AF5F39AB0CEC3E5497CD9C900EBFEAECCCB5C7.8506521BFC350652163895D4C26DEE124209AA9E&key=ik0', type: 'mpd' }} */
112 | source={{uri:item.video_url}}
113 | style={styles.fullScreen}
114 | rate={this.state.rate}
115 | paused={this.state.paused}
116 | volume={this.state.volume}
117 | muted={this.state.muted}
118 | resizeMode={this.state.resizeMode}
119 | onLoad={this.onLoad}
120 | onProgress={this.onProgress}
121 | onEnd={this.onEnd}
122 | onAudioBecomingNoisy={this.onAudioBecomingNoisy}
123 | onAudioFocusChanged={this.onAudioFocusChanged}
124 | repeat={false}
125 | />
126 |
127 |
128 |
129 |
130 |
131 | {this.renderRateControl(0.25)}
132 | {this.renderRateControl(0.5)}
133 | {this.renderRateControl(1.0)}
134 | {this.renderRateControl(1.5)}
135 | {this.renderRateControl(2.0)}
136 |
137 |
138 |
139 | {this.renderVolumeControl(0.5)}
140 | {this.renderVolumeControl(1)}
141 | {this.renderVolumeControl(1.5)}
142 |
143 |
144 |
145 | {this.renderResizeModeControl('cover')}
146 | {this.renderResizeModeControl('contain')}
147 | {this.renderResizeModeControl('stretch')}
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 | );
160 | }
161 | }
162 |
163 |
164 | const styles = StyleSheet.create({
165 | container: {
166 | flex: 1,
167 | justifyContent: 'center',
168 | alignItems: 'center',
169 | backgroundColor: 'black',
170 | },
171 | fullScreen: {
172 | position: 'absolute',
173 | top: 0,
174 | left: 0,
175 | bottom: 0,
176 | right: 0,
177 | },
178 | controls: {
179 | backgroundColor: 'transparent',
180 | borderRadius: 5,
181 | position: 'absolute',
182 | bottom: 20,
183 | left: 20,
184 | right: 20,
185 | },
186 | progress: {
187 | flex: 1,
188 | flexDirection: 'row',
189 | borderRadius: 3,
190 | overflow: 'hidden',
191 | },
192 | innerProgressCompleted: {
193 | height: 20,
194 | backgroundColor: '#cccccc',
195 | },
196 | innerProgressRemaining: {
197 | height: 20,
198 | backgroundColor: '#2C2C2C',
199 | },
200 | generalControls: {
201 | flex: 1,
202 | flexDirection: 'row',
203 | borderRadius: 4,
204 | overflow: 'hidden',
205 | paddingBottom: 10,
206 | },
207 | rateControl: {
208 | flex: 1,
209 | flexDirection: 'row',
210 | justifyContent: 'center',
211 | },
212 | volumeControl: {
213 | flex: 1,
214 | flexDirection: 'row',
215 | justifyContent: 'center',
216 | },
217 | resizeModeControl: {
218 | flex: 1,
219 | flexDirection: 'row',
220 | alignItems: 'center',
221 | justifyContent: 'center',
222 | },
223 | controlOption: {
224 | alignSelf: 'center',
225 | fontSize: 11,
226 | color: 'white',
227 | paddingLeft: 2,
228 | paddingRight: 2,
229 | lineHeight: 12,
230 | },
231 | });
--------------------------------------------------------------------------------
/src/page/MusicPage.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by Rookie on 2017/7/20.
3 | */
4 |
5 |
6 | import React, {Component} from 'react';
7 |
8 | import {View, Text, Image, StyleSheet, ToastAndroid, ScrollView, ActivityIndicator} from 'react-native';
9 |
10 | import Api from '../util/Api';
11 |
12 | import RatingCard from '../components/RatingCard';
13 | import MainToolBar from "../components/MainToolBar";
14 | import Loading from "../components/widgets/Loading";
15 |
16 | let data = require('../localdata/music.json');
17 |
18 | export default class MusicPage extends Component {
19 |
20 | constructor(props) {
21 | super(props);
22 |
23 |
24 | this.state = {
25 | url: 'https://api.douban.com/v2/music/10000037',
26 | data: '',
27 | done: false,
28 | };
29 |
30 | }
31 |
32 | componentDidMount() {
33 | // Api.Get(this.state.url, null, this._success, this._error)
34 |
35 | this._error();
36 | }
37 |
38 |
39 | _success = (resData) => {
40 | console.log('成功');
41 | console.log(resData.count);
42 |
43 |
44 | let temps = [];
45 |
46 |
47 | this.setState({
48 | data: resData,
49 | done: true,
50 | subjects: temps,
51 |
52 |
53 | })
54 | };
55 |
56 |
57 | _error = (resData) => {
58 | console.log('失败');
59 | console.log(resData);
60 |
61 | ToastAndroid.show("请求数据失败", ToastAndroid.SHORT);
62 |
63 |
64 | let temps = [];
65 |
66 |
67 | this.setState({
68 | data: data,
69 | done: true,
70 | subjects: temps,
71 |
72 |
73 | })
74 |
75 |
76 | }
77 |
78 |
79 | render() {
80 |
81 | let appNavigation = this.props.screenProps.appNavigation;
82 |
83 | if (!this.state.done) {
84 | return (
85 |
86 | )
87 | } else {
88 |
89 | return (
90 |
91 |
97 |
98 |
105 |
106 |
107 |
108 | {/*信息*/}
109 |
110 |
111 | {this.state.data.title}
118 |
119 |
120 | 表演者:
121 | {this.state.data.author.map(function (author) {
122 | return {author.name}
123 | })}
124 |
125 |
126 |
127 |
128 |
132 |
133 |
134 | {/*summary*/}
135 | 简介
141 | {this.state.data.summary}
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 | );
160 |
161 | }
162 |
163 | }
164 | }
165 |
166 | const styles = StyleSheet.create({
167 | container: {
168 | flex: 1,
169 | justifyContent: 'center',
170 | alignItems: 'center'
171 | },
172 |
173 | });
--------------------------------------------------------------------------------
/src/page/RankListPage.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by Rookie on 2017/7/25.
3 | */
4 |
5 |
6 | import React, {Component} from 'react';
7 |
8 | import {View, StyleSheet, Text, ToastAndroid} from 'react-native';
9 |
10 | import VerticalListView from '../components/VerticalListView';
11 |
12 | import Api from '../util/Api';
13 | import ToolBar from "../components/ToolBar";
14 | import Loading from "../components/widgets/Loading";
15 |
16 |
17 | let data;
18 |
19 | let subUrl = '';
20 | export default class RankListPage extends Component {
21 |
22 | constructor(props) {
23 | super(props);
24 |
25 | let id = this.props.navigation.state.params.id;
26 |
27 | if (id === 'movie_top250') {
28 | subUrl = 'top250';
29 | data = require('../localdata/top250.json')
30 | } else if (id === 'movie_high_box_office') {
31 | data = require('../localdata/usbox.json');
32 | subUrl = 'us_box';
33 | } else {
34 | subUrl = 'top250';
35 | }
36 |
37 | this.state = {
38 | url: 'https://api.douban.com/v2/movie/' + subUrl,
39 | data: '',
40 | done: false,
41 | subjects: [],
42 | };
43 |
44 | }
45 |
46 | componentDidMount() {
47 | Api.Get(this.state.url, null, this._success, this._error)
48 | }
49 |
50 |
51 | _success = (resData) => {
52 | console.log('成功');
53 | console.log(resData);
54 |
55 |
56 | this.setState({
57 | data: resData,
58 | done: true,
59 | subjects: resData.subjects,
60 |
61 | })
62 | };
63 |
64 |
65 | _error = (resData) => {
66 | console.log('失败');
67 | console.log(resData);
68 |
69 |
70 | this.setState({
71 | subjects: data.subjects,
72 | done: true,
73 | })
74 |
75 |
76 | };
77 |
78 |
79 | render() {
80 | let navigation = this.props.navigation;
81 | if (!this.state.done) {
82 | return ( )
83 | } else {
84 | return (
85 |
86 |
92 |
93 |
98 |
99 |
100 | )
101 | }
102 |
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/src/page/SearchPage.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by Rookie on 2017/7/21.
3 | */
4 |
5 |
6 | import React, {Component} from 'react';
7 |
8 | import {View, Text, Image, StyleSheet, ToastAndroid, ScrollView} from 'react-native';
9 |
10 |
11 | export default class MovieDetailPage extends Component {
12 |
13 |
14 | constructor(props) {
15 | super(props);
16 | }
17 |
18 |
19 | render() {
20 |
21 |
22 | return (
23 |
24 |
25 |
26 | {this.props.navigation.state.params.type}
27 |
28 |
29 |
30 |
31 | );
32 |
33 |
34 | }
35 | }
36 |
37 | const styles = StyleSheet.create({
38 | container: {
39 | flex: 1,
40 | justifyContent: 'center',
41 | alignItems: 'center'
42 | },
43 |
44 | });
--------------------------------------------------------------------------------
/src/page/SubjectDetailPage.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by Rookie on 2017/7/24.
3 | */
4 |
5 |
6 | import React, {Component} from 'react';
7 |
8 | import {View, WebView, StyleSheet, Text, ToastAndroid, TouchableOpacity, Image} from 'react-native';
9 |
10 |
11 | class ToolBar extends Component {
12 |
13 | render() {
14 | return (
18 |
19 |
21 |
22 |
23 | 日记
24 | )
25 | }
26 | }
27 |
28 |
29 | export default class SubjectDetailPage extends Component {
30 |
31 |
32 | constructor(props) {
33 | super(props);
34 | this.state = {
35 | canGoBack: false,
36 | }
37 | }
38 |
39 | _onNavigationStateChange = (event) => {
40 | this.setState({
41 | canGoBack: event.canGoBack,
42 | })
43 | };
44 |
45 | _back = () => {
46 | if (this.state.canGoBack) {
47 | this.refs.WebViews.goBack();
48 | } else {
49 | this.props.navigation.goBack();
50 | }
51 | };
52 |
53 | render() {
54 | return (
55 |
56 |
57 | this._onNavigationStateChange(event)}
60 | startInLoadingState={true}
61 | showsVerticalScrollIndicator={false}
62 | source={{uri: this.props.navigation.state.params.item.target.url}}
63 | />
64 |
65 | )
66 | }
67 | }
68 |
69 | const styles = StyleSheet.create({
70 | container: {
71 | flex: 1,
72 | justifyContent: 'center',
73 | alignItems: 'center'
74 | },
75 |
76 | });
--------------------------------------------------------------------------------
/src/page/UserCenterPager.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by Rookie on 2017/8/22.
3 | */
4 | import React, {Component} from 'react';
5 |
6 | import {
7 | View, Text, StyleSheet, ScrollView, Image, Dimensions, TouchableOpacity, ToastAndroid, Animated,
8 |
9 | } from 'react-native';
10 |
11 | import PopupDialog, {DialogButton, DialogTitle, SlideAnimation, FadeAnimation} from 'react-native-popup-dialog';
12 | import ImagePicker from 'react-native-image-crop-picker';
13 |
14 | let windowWidth = Dimensions.get('window').width;
15 | let windowHeight = Dimensions.get('window').height;
16 |
17 | export default class UserCenterPager extends Component {
18 |
19 |
20 | constructor(props) {
21 | super(props);
22 |
23 |
24 | this.state = {
25 | backgroundPhotoUri: 'https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=264358067,1297679371&fm=26&gp=0.jpg',
26 | opacity: new Animated.Value(0),
27 |
28 | };
29 | }
30 |
31 | onPhotoResult = (data) => {
32 | this.setState({
33 | backgroundPhotoUri: data.path,
34 | });
35 | };
36 |
37 |
38 | _openCamera = () => {
39 | this.popupDialog.dismiss();
40 | this.props.navigation.navigate('Camera', {getPhotos: this.onPhotoResult});
41 | };
42 |
43 | _openCameraRoll = () => {
44 | this.popupDialog.dismiss();
45 |
46 |
47 | ImagePicker.openPicker({
48 | width: 300,
49 | height: 400,
50 | cropping: true
51 | }).then(this.onPhotoResult)
52 | .catch((err) => {
53 | console.log(err);
54 | })
55 | };
56 |
57 |
58 | _onContentScroll = (e) => {
59 | // console.log(e.nativeEvent.contentOffset.y);
60 |
61 | let percent = Math.abs(e.nativeEvent.contentOffset.y) / 200;
62 |
63 | console.log(percent);
64 |
65 | if (percent >= 1.0) {
66 | percent = 1.0;
67 | }
68 |
69 | if (percent < 0) {
70 | percent = 0;
71 | }
72 |
73 |
74 | this.setState(
75 | {
76 | opacity: percent,
77 | }
78 | )
79 |
80 |
81 | };
82 |
83 | render() {
84 |
85 | return (
86 |
87 |
88 |
89 |
93 |
94 | {
95 | this.popupDialog.show();
96 | }}>
97 |
99 |
100 |
101 |
102 |
103 |
104 |
105 | A
106 |
107 |
108 | A
109 |
110 |
111 | A
112 |
113 |
114 | A
115 |
116 |
117 | A
118 |
119 |
120 | A
121 |
122 |
123 | A
124 |
125 |
126 | A
127 |
128 |
129 | A
130 |
131 |
132 | A
133 |
134 |
135 | A
136 |
137 |
138 | A
139 |
140 |
141 | A
142 |
143 |
144 | A
145 |
146 |
147 | A
148 |
149 |
150 | A
151 |
152 |
153 | A
154 |
155 |
156 | A
157 |
158 |
159 | A
160 |
161 |
162 | A
163 |
164 |
165 | A
166 |
167 |
168 | A
169 |
170 |
171 | A
172 |
173 |
174 | A
175 |
176 |
177 | A
178 |
179 |
180 |
181 |
182 |
183 |
192 |
193 | A
194 |
195 |
196 |
197 |
198 |
199 | }
203 | actions={[ {
206 | this.popupDialog.dismiss()
207 | }} key="button-1"/>]}
208 | ref={(popupDialog) => {
209 | this.popupDialog = popupDialog;
210 | }}
211 | dialogAnimation={new FadeAnimation({toValue: 1})}>
212 |
213 |
214 | Camera
215 |
216 |
217 |
218 | CameraRoll
219 |
220 |
221 |
222 |
223 |
224 | );
225 | }
226 | }
227 |
228 | const
229 | styles = StyleSheet.create({
230 | container: {
231 | flex: 1
232 | },
233 | userInfobg: {
234 | height: 250,
235 | alignItems: 'center',
236 | width: windowWidth,
237 | justifyContent: 'center'
238 | },
239 | avatar: {
240 | margin: 10,
241 | width: 80,
242 | height: 80,
243 | borderRadius: 40,
244 | borderWidth: 4,
245 | borderColor: 'white'
246 | }
247 | });
--------------------------------------------------------------------------------
/src/util/Api.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by Rookie on 2017/7/20.
3 | */
4 | export default class Api {
5 |
6 |
7 | static Get(url, param, success, fail) {
8 |
9 | if (param) {
10 |
11 | var keys = Object.keys(param);
12 |
13 | var totalParamString = '';
14 |
15 | keys.forEach((key, i) => {
16 |
17 | var string;
18 | if (i === 0) {
19 | string = '?';
20 | }
21 | else if (i > 0) {
22 |
23 | string = '&';
24 | }
25 |
26 | var value = param[key];
27 |
28 | totalParamString += string;
29 |
30 | totalParamString = totalParamString + key + '=' + value;
31 |
32 | })
33 |
34 | url = url + totalParamString;
35 | }
36 |
37 | console.log('url=' + url);
38 |
39 |
40 | fetch(url)
41 | .then(res => res.json())
42 | .then(resData => {
43 | if (success) {
44 | success(resData);
45 | }
46 | }).catch(error => {
47 | if (fail) {
48 | fail(error);
49 | }
50 | })
51 | }
52 | }
--------------------------------------------------------------------------------
/src/util/Api_back.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by Rookie on 2017/7/20.
3 | */
4 | export default class Api {
5 |
6 |
7 | static Get(url, param, success, fail) {
8 |
9 | if (param) {
10 |
11 | var keys = Object.keys(param);
12 |
13 | var totalParamString = '';
14 |
15 | keys.forEach((key, i) => {
16 |
17 | var string;
18 | if (i === 0) {
19 | string = '?';
20 | }
21 | else if (i > 0) {
22 |
23 | string = '&';
24 | }
25 |
26 | var value = param[key];
27 |
28 | totalParamString += string;
29 |
30 | totalParamString = totalParamString + key + '=' + value;
31 |
32 | })
33 |
34 | url = url + totalParamString;
35 | }
36 |
37 | console.log('url=' + url);
38 |
39 |
40 | fetch(url,
41 | {
42 | headers: {
43 | 'appkey': 'ef1fc57c13007e33',
44 | }
45 | })
46 | .then(res => res.json())
47 | .then(resData => {
48 | if (success) {
49 | success(resData);
50 | }
51 | }).catch(error => {
52 | if (fail) {
53 | fail(error);
54 | }
55 | })
56 | }
57 | }
--------------------------------------------------------------------------------