├── .gitignore ├── .idea ├── .name ├── compiler.xml ├── copyright │ └── profiles_settings.xml ├── dictionaries │ └── xhinliang.xml ├── gradle.xml ├── inspectionProfiles │ ├── Project_Default.xml │ └── profiles_settings.xml ├── misc.xml ├── modules.xml ├── runConfigurations.xml └── vcs.xml ├── Api.md ├── LICENSE ├── README.md ├── app ├── .gitignore ├── app-release.apk ├── build.gradle ├── libs │ ├── armeabi │ │ └── libbspatch.so │ └── umeng-update-v2.6.0.1.jar ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── wecan │ │ └── xhin │ │ └── studio │ │ └── ApplicationTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── wecan │ │ │ └── xhin │ │ │ └── studio │ │ │ ├── App.java │ │ │ ├── activity │ │ │ ├── AboutActivity.java │ │ │ ├── LoginActivity.java │ │ │ ├── MainActivity.java │ │ │ ├── MyDetailsActivity.java │ │ │ ├── PictureActivity.java │ │ │ ├── RegisterActivity.java │ │ │ ├── TestActivity.java │ │ │ └── UserDetailsActivity.java │ │ │ ├── adapter │ │ │ ├── LibrariesAdapter.java │ │ │ ├── SimpleAdapter.java │ │ │ └── UsersAdapter.java │ │ │ ├── api │ │ │ └── Api.java │ │ │ ├── bean │ │ │ ├── GitRepository.java │ │ │ ├── Simple.java │ │ │ ├── common │ │ │ │ └── User.java │ │ │ ├── down │ │ │ │ ├── BaseData.java │ │ │ │ └── UsersData.java │ │ │ └── up │ │ │ │ ├── RegisterBody.java │ │ │ │ └── SignBody.java │ │ │ ├── fragment │ │ │ ├── AllUserFragment.java │ │ │ ├── BooksFragment.java │ │ │ ├── RxBindingFragment.java │ │ │ ├── SignedUserFragment.java │ │ │ └── UsersFragment.java │ │ │ ├── net │ │ │ └── OkHttpGlideModule.java │ │ │ └── reactivex │ │ │ └── BindingRecyclerView.java │ └── res │ │ ├── drawable-hdpi │ │ ├── defimgs.png │ │ ├── header.jpg │ │ ├── umeng_update_btn_check_off_focused_holo_light.png │ │ ├── umeng_update_btn_check_off_holo_light.png │ │ ├── umeng_update_btn_check_off_pressed_holo_light.png │ │ ├── umeng_update_btn_check_on_focused_holo_light.png │ │ ├── umeng_update_btn_check_on_holo_light.png │ │ ├── umeng_update_btn_check_on_pressed_holo_light.png │ │ ├── umeng_update_close_bg_normal.png │ │ └── umeng_update_close_bg_tap.png │ │ ├── drawable-xxxhdpi │ │ ├── ic_sign.png │ │ └── ic_unsign.png │ │ ├── drawable │ │ ├── bg_material_button_lite_blue.xml │ │ ├── ic_menu_camera.xml │ │ ├── ic_menu_gallery.xml │ │ ├── ic_menu_manage.xml │ │ ├── ic_menu_send.xml │ │ ├── ic_menu_share.xml │ │ ├── ic_menu_slideshow.xml │ │ ├── tb_munion_icon.xml │ │ ├── tb_munion_item_selector.xml │ │ ├── umeng_common_gradient_green.xml │ │ ├── umeng_common_gradient_orange.xml │ │ ├── umeng_common_gradient_red.xml │ │ ├── umeng_update_button_cancel_bg_focused.xml │ │ ├── umeng_update_button_cancel_bg_normal.xml │ │ ├── umeng_update_button_cancel_bg_selector.xml │ │ ├── umeng_update_button_cancel_bg_tap.xml │ │ ├── umeng_update_button_check_selector.xml │ │ ├── umeng_update_button_close_bg_selector.xml │ │ ├── umeng_update_button_ok_bg_focused.xml │ │ ├── umeng_update_button_ok_bg_normal.xml │ │ ├── umeng_update_button_ok_bg_selector.xml │ │ ├── umeng_update_button_ok_bg_tap.xml │ │ ├── umeng_update_dialog_bg.xml │ │ ├── umeng_update_title_bg.xml │ │ └── umeng_update_wifi_disable.png │ │ ├── layout-v9 │ │ └── umeng_common_download_notification.xml │ │ ├── layout │ │ ├── activity_about.xml │ │ ├── activity_login.xml │ │ ├── activity_main.xml │ │ ├── activity_picture.xml │ │ ├── activity_register.xml │ │ ├── activity_user_details.xml │ │ ├── fragment_users.xml │ │ ├── include_nav_header_main.xml │ │ ├── recycler_item_header.xml │ │ ├── recycler_item_library.xml │ │ ├── recycler_item_simple.xml │ │ ├── recycler_item_user.xml │ │ ├── tb_munion_aditem.xml │ │ ├── umeng_common_download_notification.xml │ │ └── umeng_update_dialog.xml │ │ ├── menu │ │ ├── activity_main_drawer.xml │ │ ├── main.xml │ │ └── menu_scrolling.xml │ │ ├── mipmap-hdpi │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxxhdpi │ │ └── ic_launcher.png │ │ ├── values-en-rUs │ │ └── arrays.xml │ │ ├── values-en │ │ ├── strings.xml │ │ ├── tb_munion_strings.xml │ │ ├── umeng_common_strings.xml │ │ └── umeng_update_string.xml │ │ ├── values-v19 │ │ └── styles.xml │ │ ├── values-v21 │ │ └── styles.xml │ │ ├── values-zh-rCn │ │ └── arrays.xml │ │ ├── values-zh │ │ ├── strings.xml │ │ ├── tb_munion_strings.xml │ │ ├── umeng_common_strings.xml │ │ └── umeng_update_string.xml │ │ └── values │ │ ├── arrays.xml │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── drawables.xml │ │ ├── strings.xml │ │ ├── styles.xml │ │ ├── tb_munion_strings.xml │ │ ├── umeng_common_strings.xml │ │ └── umeng_update_string.xml │ └── test │ └── java │ └── com │ └── wecan │ └── xhin │ └── studio │ └── ExampleUnitTest.java ├── baselib ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── wecan │ │ └── xhin │ │ └── baselib │ │ └── ApplicationTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── wecan │ │ │ └── xhin │ │ │ └── baselib │ │ │ ├── activity │ │ │ ├── BaseActivity.java │ │ │ └── SingleFragmentActivity.java │ │ │ ├── fragment │ │ │ └── BaseFragment.java │ │ │ ├── net │ │ │ └── LoggingInterceptor.java │ │ │ ├── rx │ │ │ ├── RxEndlessRecyclerView.java │ │ │ └── RxNetworking.java │ │ │ ├── util │ │ │ └── PreferenceHelper.java │ │ │ └── widget │ │ │ ├── StatusBarHolderView.java │ │ │ └── VideoImageView.java │ └── res │ │ ├── layout │ │ ├── activity_single_fragment.xml │ │ └── include_toolbar.xml │ │ └── values │ │ └── strings.xml │ └── test │ └── java │ └── com │ └── wecan │ └── xhin │ └── baselib │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle └── wef.md /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | -------------------------------------------------------------------------------- /.idea/.name: -------------------------------------------------------------------------------- 1 | Studio -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/dictionaries/xhinliang.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | addplease 5 | appid 6 | attacher 7 | balysv 8 | donglua 9 | imgurl 10 | liang 11 | mailto 12 | mantou 13 | nineoldandroids 14 | okhttp 15 | oxoooo 16 | photopicker 17 | pojo 18 | trello 19 | unsign 20 | wecanstudio 21 | xidian 22 | 23 | 24 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 20 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 19 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 46 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Api.md: -------------------------------------------------------------------------------- 1 | # # 接口规范 2 | 3 | 需要实现基于 HTTP/JSON 的 RESTful API,至少包含以下接口: 4 | 5 | 基地址 http://121.42.209.19/RestfulApi/index.php/ 6 | 7 | 1. 登录 8 | 2. 注册 9 | 3. 修改用户信息 10 | 4. 用户签到 11 | 5. 用户签退 12 | 6. 获取所有用户信息 13 | 7. 获取已签到用户信息 14 | 8. 增加邀请码信息 15 | 9. 获取所有邀请码信息 16 | 17 | 18 | 19 | 20 | 如果需要传参的接口,传过来的请求体 json 格式有误或验证结果错误。则返回错误状态 21 | 22 | ``` 23 | { 24 | "status": "-1" 25 | } 26 | ``` 27 | 28 | ## 登录 29 | 30 | `GET /user` 31 | 32 | ##### 请求体 33 | 34 | 参数名 | 类型 | 描述 35 | ---|---|--- 36 | name | string | 用户名 37 | phone | string | 密码 38 | 39 | #####请求示例 40 | 41 | ``` 42 | GET /api/users?name=xxx&phone=xxx 43 | ``` 44 | 45 | ##### 响应示例 46 | 47 | ``` 48 | 200 OK 49 | { 50 | "id": "10", 51 | "name": "wer123", 52 | "sex": "1", 53 | "group_name": "2", 54 | "phone": "121", 55 | "imgurl": "www.123456.com", 56 | "position": "3", 57 | "sign_date": "2015-11-20 15:52:31", 58 | "status": "0" 59 | } 60 | ``` 61 | 62 | ##### 异常示例 63 | 64 | 用户名不存在或者密码错误: 65 | 66 | ``` 67 | 403 Forbidden 68 | { 69 | "status": -1, 70 | "message": "用户名密码错误" 71 | } 72 | ``` 73 | 74 | 75 | ## 注册 76 | 77 | `POST /api/users` 78 | 79 | #### 请求体 80 | 81 | 参数名 | 类型 | 描述 82 | ---|---|--- 83 | name | string | 用户名 84 | sex | int | 性别 85 | group_name | int | 小组类别 86 | imgurl | string | 头像 87 | phone | string | 电话号码 88 | position | int | 职位 89 | code | string | 邀请码 90 | 91 | 92 | 93 | #### 请求示例 94 | 95 | ``` 96 | POST /api/users 97 | 98 | {"name" : "wer12312", "sex" : 1, "group_name" : 2, "imgurl" : "www.123456.com", "phone" : "121", "position" : 3, "code" : "123"} 99 | 100 | 101 | ``` 102 | 103 | #### 响应示例 104 | 105 | ``` 106 | 200 OK 107 | { 108 | "status": 1 109 | } 110 | ``` 111 | 112 | #### 异常示例 113 | 邀请码不存在或已被注册 114 | 115 | ``` 116 | 403 Forbidden 117 | { 118 | "status": -1, 119 | "message": "邀请码不存在" 120 | } 121 | ``` 122 | 123 | 用户名重复 124 | 125 | ``` 126 | { 127 | "status": -1, 128 | "message": "用户名重复" 129 | } 130 | ``` 131 | 132 | 133 | 134 | ## 修改用户信息 135 | 136 | 137 | #### 请求体 138 | 139 | 参数名 | 类型 | 描述 140 | ---|---|--- 141 | name | string | 用户名 142 | sex | int | 性别 143 | group_name | int | 小组类别 144 | imgurl | string | 头像 145 | phone | string | 电话号码 146 | position | int | 职位 147 | 148 | 149 | 150 | #### 请求示例 151 | 152 | ``` 153 | PUT api/users 154 | {"name" : "wer123", "sex" : 1, "group_name" : 2, "imgurl" : "www.123456123.com", "phone" : "121", "position" : 3} 155 | ``` 156 | 157 | 158 | #### 响应示例 159 | 160 | ``` 161 | 200 OK 162 | { 163 | "id": "10", 164 | "name": "wer123", 165 | "sex": "1", 166 | "group_name": 2, 167 | "phone": "121", 168 | "imgurl": "www.123456123.com", 169 | "position": 3, 170 | "sign_date": "2015-11-20 15:52:31", 171 | "status": "0" 172 | } 173 | ``` 174 | 175 | #### 异常示例 176 | ``` 177 | 403 Forbidden 178 | { 179 | "status": -1, 180 | "message": "用户名信息错误" 181 | } 182 | ``` 183 | 184 | 185 | ####说明 186 | ``` 187 | name与sex无法更改 188 | ``` 189 | 190 | 191 | ## 用户签到 192 | 193 | `POST /api/sign` 194 | 195 | ##### 请求体 196 | 197 | 参数名 | 类型 | 描述 198 | ---|---|--- 199 | name | string | 用户名 200 | 201 | #### 请求示例 202 | 203 | ``` 204 | POST /api/sign 205 | { 206 | "name" : "wer123" 207 | } 208 | ``` 209 | 210 | #### 响应示例 211 | 212 | 签到成功 213 | 214 | ``` 215 | 200 OK 216 | { 217 | "status":"1" 218 | } 219 | ``` 220 | 221 | 222 | #### 异常示例 223 | 224 | ``` 225 | 403 226 | { 227 | "status": -1, 228 | "message": "用户还没有下线" 229 | } 230 | ``` 231 | 232 | 233 | 234 | 235 | ## 用户签退 236 | 237 | `DELETE /api/sign` 238 | 239 | ##### 请求体 240 | 241 | 参数名 | 类型 | 描述 242 | ---|---|--- 243 | name | string | 类型名称 244 | 245 | #### 请求示例 246 | 247 | ``` 248 | DELETE /api/sign?name=xxx 249 | ``` 250 | 251 | #### 响应示例 252 | 253 | ``` 254 | 200 OK 255 | { 256 | "status": 1 257 | } 258 | ``` 259 | 260 | #### 异常示例 261 | 262 | 用户名没有签到 263 | 264 | ``` 265 | 403 266 | { 267 | "status": -1, 268 | "message": "用户还没有签到" 269 | } 270 | ``` 271 | 272 | 273 | 274 | 275 | ## 获取所有用户信息 276 | `GET /api/message_all` 277 | 278 | 279 | 280 | #### 请求示例 281 | 282 | ``` 283 | GET /api/message_all 284 | ``` 285 | 286 | #### 响应示例 287 | 288 | ``` 289 | 200 OK 290 | { 291 | "status": 1, 292 | "data": [ 293 | { 294 | "id": "13", 295 | "name": "wer12312", 296 | "sex": "1", 297 | "group_name": "2", 298 | "phone": "121", 299 | "imgurl": "www.123456.com", 300 | "position": "3", 301 | "sign_date": "2015-11-20 18:45:20", 302 | "status": "0" 303 | }, 304 | { 305 | "id": "10", 306 | "name": "wer123", 307 | "sex": "1", 308 | "group_name": "2", 309 | "phone": "121", 310 | "imgurl": "www.123456123.com", 311 | "position": "3", 312 | "sign_date": "2015-11-20 15:52:31", 313 | "status": "0" 314 | }, 315 | { 316 | "id": "12", 317 | "name": "wer1231231", 318 | "sex": "1", 319 | "group_name": "1", 320 | "phone": "123", 321 | "imgurl": "www.123.com", 322 | "position": "1", 323 | "sign_date": "2015-11-20 15:55:01", 324 | "status": "0" 325 | } 326 | ] 327 | } 328 | ``` 329 | 330 | 331 | 332 | ## 获取已签到用户信息 333 | `GET /api/message` 334 | 335 | 336 | 337 | #### 响应示例 338 | 339 | ``` 340 | 200 OK 341 | { 342 | "status": 1, 343 | "data": [ 344 | { 345 | "id": "4", 346 | "name": "wer", 347 | "sex": "1", 348 | "group_name": "1", 349 | "phone": "123", 350 | "imgurl": "www.123.com", 351 | "position": "1", 352 | "sign_date": "2015-11-20 15:07:47", 353 | "status": "1" 354 | } 355 | ] 356 | } 357 | ``` 358 | 359 | 360 | 361 | ## 增加邀请码信息 362 | 363 | `GET /api/addplease/(num)` 364 | 365 | 366 | 367 | #### 请求示例 368 | 369 | ``` 370 | GET /api/addplease/(num) 371 | 372 | ``` 373 | 374 | #### 响应示例 375 | 376 | ``` 377 | 200 OK 378 | { 379 | "status": 1 380 | } 381 | ``` 382 | 383 | 384 | 385 | 386 | ## 获取所有邀请码 387 | 388 | `GET /api/getplease` 389 | 390 | 391 | 392 | #### 请求示例 393 | 394 | ``` 395 | GET /api/getplease 396 | 397 | ``` 398 | 399 | #### 响应示例 400 | 401 | ``` 402 | 200 OK 403 | { 404 | "status": 1, 405 | "data": [ 406 | { 407 | "id": "1", 408 | "num": "123", 409 | "status": "1" 410 | }, 411 | { 412 | "id": "2", 413 | "num": "974c5743-3f6a-6dd5-f24f-f3e05bd3031d", 414 | "status": "1" 415 | }, 416 | { 417 | "id": "3", 418 | "num": "296d19ad-d6b1-fa6e-b8d3-0a6abb303257", 419 | "status": "1" 420 | }, 421 | { 422 | "id": "4", 423 | "num": "8a43cfa6-30ee-5c2c-fb6a-1dd14dc5650b", 424 | "status": "1" 425 | } 426 | ] 427 | } 428 | ``` 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Studio 2 | 微客工作室 for Android. 3 | 4 | ## Thanks 5 | - [OkHttp](https://square.github.io/okhttp) 6 | - [Retrofit](https://square.github.io/retrofit) 7 | - [Gson](https://github.com/google/gson) 8 | - [RxJava](https://github.com/ReactiveX/RxJava) 9 | - [RxAndroid](https://github.com/ReactiveX/RxAndroid) 10 | - [RxBinding](https://github.com/JakeWharton/RxBinding) 11 | - [NineOldAndroids](https://github.com/JakeWharton/NineOldAndroids) 12 | - [RxLifecycle](https://github.com/trello/RxLifecycle) 13 | - [mr-mantou-android](https://github.com/oxoooo/mr-mantou-android) 14 | - [Meizhi](https://github.com/drakeet/Meizhi) 15 | - [PhotoPicker](https://github.com/donglua/PhotoPicker) 16 | - [material-ripple](https://github.com/balysv/material-ripple) 17 | 18 | ## License 19 | 20 | Copyright 2015 XhinLiang 21 | 22 | Licensed under the Apache License, Version 2.0 (the "License"); 23 | you may not use this file except in compliance with the License. 24 | You may obtain a copy of the License at 25 | 26 | http://www.apache.org/licenses/LICENSE-2.0 27 | 28 | Unless required by applicable law or agreed to in writing, software 29 | distributed under the License is distributed on an "AS IS" BASIS, 30 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 31 | See the License for the specific language governing permissions and 32 | limitations under the License. 33 | 34 | 35 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/app-release.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XhinLiang/Studio/656a82dde75ae8bb6d477d3e976cd2211e3cbfc6/app/app-release.apk -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | apply plugin: 'com.android.databinding' 3 | 4 | android { 5 | compileSdkVersion 23 6 | buildToolsVersion "23.0.2" 7 | 8 | //为了解决部分第三方库重复打包了META-INF的问题 9 | packagingOptions { 10 | exclude 'META-INF/LICENSE.txt' 11 | exclude 'META-INF/NOTICE.txt' 12 | } 13 | 14 | lintOptions { 15 | abortOnError false 16 | } 17 | 18 | defaultConfig { 19 | applicationId "com.wecan.xhin.studio" 20 | minSdkVersion 16 21 | targetSdkVersion 23 22 | versionCode 8 23 | versionName "1.0.2" 24 | } 25 | buildTypes { 26 | release { 27 | minifyEnabled false 28 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 29 | } 30 | } 31 | } 32 | 33 | dependencies { 34 | compile fileTree(include: ['*.jar'], dir: 'libs') 35 | testCompile 'junit:junit:4.12' 36 | compile project(':baselib') 37 | compile 'cn.leancloud.android:avoscloud-sdk:v3.8.1' 38 | } 39 | -------------------------------------------------------------------------------- /app/libs/armeabi/libbspatch.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XhinLiang/Studio/656a82dde75ae8bb6d477d3e976cd2211e3cbfc6/app/libs/armeabi/libbspatch.so -------------------------------------------------------------------------------- /app/libs/umeng-update-v2.6.0.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XhinLiang/Studio/656a82dde75ae8bb6d477d3e976cd2211e3cbfc6/app/libs/umeng-update-v2.6.0.1.jar -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /opt/android-sdk-linux/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/wecan/xhin/studio/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.wecan.xhin.studio; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 43 | 44 | 47 | 50 | 51 | 52 | 53 | 54 | 55 | 58 | 59 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 71 | 72 | 75 | 76 | 79 | 80 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /app/src/main/java/com/wecan/xhin/studio/App.java: -------------------------------------------------------------------------------- 1 | 2 | package com.wecan.xhin.studio; 3 | 4 | import android.app.Application; 5 | import android.content.Context; 6 | 7 | import com.avos.avoscloud.AVOSCloud; 8 | import com.google.gson.FieldNamingPolicy; 9 | import com.google.gson.Gson; 10 | import com.google.gson.GsonBuilder; 11 | import com.squareup.okhttp.Interceptor; 12 | import com.squareup.okhttp.OkHttpClient; 13 | import com.squareup.okhttp.Response; 14 | import com.wecan.xhin.baselib.net.LoggingInterceptor; 15 | import com.wecan.xhin.studio.api.Api; 16 | 17 | import java.io.IOException; 18 | import java.util.HashMap; 19 | 20 | import retrofit.GsonConverterFactory; 21 | import retrofit.Retrofit; 22 | import retrofit.RxJavaCallAdapterFactory; 23 | 24 | public class App extends Application { 25 | 26 | 27 | public static final String VALUE_AVOS_APPID = "AkVsXJ4RoWq1juPauOHe1OW5"; 28 | public static final String VALUE_AVOS_APPKEY = "gFICBkjJSxlI5fHnvNyB7Lfj"; 29 | 30 | public static final String KEY_PREFERENCE_USER = "user"; 31 | public static final String KEY_PREFERENCE_PHONE = "phone"; 32 | public static final String KEY_BUILD_VERSION = "build_version"; 33 | public static final String DATE_FORMAT_PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"; 34 | 35 | private final HashMap apis = new HashMap<>(); 36 | 37 | private Retrofit retrofit; 38 | 39 | //返回当前单例的静态方法,判断是否是当前的App调用 40 | public static App from(Context context) { 41 | Context application = context.getApplicationContext(); 42 | if (application instanceof App) 43 | return (App) application; 44 | throw new IllegalArgumentException("Context must be from Studio"); 45 | } 46 | 47 | 48 | @Override 49 | public void onCreate() { 50 | super.onCreate(); 51 | 52 | AVOSCloud.initialize(this, VALUE_AVOS_APPID, VALUE_AVOS_APPKEY); 53 | OkHttpClient okHttpClient = new OkHttpClient(); 54 | //OKHttp的使用 55 | okHttpClient.networkInterceptors().add(new Interceptor() { 56 | @Override 57 | public Response intercept(Chain chain) throws IOException { 58 | return chain.proceed(chain.request().newBuilder() 59 | .header(KEY_BUILD_VERSION, BuildConfig.VERSION_NAME) 60 | .build()); 61 | } 62 | }); 63 | 64 | if (BuildConfig.DEBUG) { 65 | okHttpClient.networkInterceptors().add(new LoggingInterceptor()); 66 | } 67 | 68 | //初始化Gson 69 | Gson gson = new GsonBuilder() 70 | .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES) 71 | .setDateFormat(DATE_FORMAT_PATTERN) 72 | .create(); 73 | 74 | 75 | //初始化Retrofit 76 | retrofit = new Retrofit.Builder() 77 | .client(okHttpClient) 78 | .addConverterFactory(GsonConverterFactory.create(gson)) 79 | .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) 80 | .baseUrl(Api.BASE_URL) 81 | .build(); 82 | } 83 | 84 | //返回Retrofit的API 85 | public T createApi(Class service) { 86 | if (!apis.containsKey(service)) { 87 | T instance = retrofit.create(service); 88 | apis.put(service, instance); 89 | } 90 | //noinspection unchecked 91 | return (T) apis.get(service); 92 | } 93 | 94 | public OkHttpClient getHttpClient() { 95 | return retrofit.client(); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /app/src/main/java/com/wecan/xhin/studio/activity/AboutActivity.java: -------------------------------------------------------------------------------- 1 | package com.wecan.xhin.studio.activity; 2 | 3 | import android.app.ProgressDialog; 4 | import android.content.DialogInterface; 5 | import android.content.Intent; 6 | import android.content.pm.ResolveInfo; 7 | import android.databinding.DataBindingUtil; 8 | import android.net.Uri; 9 | import android.os.Bundle; 10 | import android.support.v7.app.AlertDialog; 11 | import android.widget.EditText; 12 | 13 | import com.jakewharton.rxbinding.view.RxView; 14 | import com.jakewharton.rxbinding.view.ViewClickEvent; 15 | import com.wecan.xhin.baselib.activity.BaseActivity; 16 | import com.wecan.xhin.baselib.rx.RxNetworking; 17 | import com.wecan.xhin.studio.App; 18 | import com.wecan.xhin.studio.R; 19 | import com.wecan.xhin.studio.adapter.LibrariesAdapter; 20 | import com.wecan.xhin.studio.api.Api; 21 | import com.wecan.xhin.studio.bean.GitRepository; 22 | import com.wecan.xhin.studio.bean.down.BaseData; 23 | import com.wecan.xhin.studio.databinding.ActivityAboutBinding; 24 | 25 | import java.util.LinkedList; 26 | import java.util.List; 27 | 28 | import rx.Observable; 29 | import rx.android.schedulers.AndroidSchedulers; 30 | import rx.functions.Action1; 31 | import rx.functions.Func0; 32 | import rx.functions.Func1; 33 | import rx.schedulers.Schedulers; 34 | 35 | /** 36 | * Created by xhinliang on 15-11-23. 37 | * xhinliang@gmail.com 38 | */ 39 | public class AboutActivity extends BaseActivity implements LibrariesAdapter.Listener { 40 | 41 | private List libraries = new LinkedList<>(); 42 | private Api api; 43 | private Observable.Transformer networkingIndicator; 44 | 45 | @Override 46 | protected void onCreate(Bundle savedInstanceState) { 47 | super.onCreate(savedInstanceState); 48 | ActivityAboutBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_about); 49 | setSupportActionBar(binding.toolbar); 50 | setHasHomeButton(); 51 | 52 | setRxClick(binding.fab) 53 | .subscribe(new Action1() { 54 | @Override 55 | public void call(ViewClickEvent viewClickEvent) { 56 | composeEmail(getString(R.string.author_email)); 57 | } 58 | }); 59 | 60 | RxView.clickEvents(binding.toolbar) 61 | .elementAt(5) 62 | .compose(this.bindToLifecycle()) 63 | .subscribe(new Action1() { 64 | @Override 65 | public void call(ViewClickEvent viewClickEvent) { 66 | addCode(); 67 | } 68 | }); 69 | 70 | setupRecyclerView(binding); 71 | initData(); 72 | } 73 | 74 | private void initData() { 75 | api = App.from(this).createApi(Api.class); 76 | ProgressDialog pd = new ProgressDialog(this); 77 | networkingIndicator = RxNetworking.bindConnecting(pd); 78 | } 79 | 80 | private void addCodeToServer(final String code) { 81 | Observable 82 | .defer(new Func0>() { 83 | @Override 84 | public Observable call() { 85 | return api.addCode(code); 86 | } 87 | }) 88 | .subscribeOn(Schedulers.io()) 89 | .observeOn(AndroidSchedulers.mainThread()) 90 | .compose(networkingIndicator) 91 | .compose(AboutActivity.this.bindToLifecycle()) 92 | .subscribe(new Action1() { 93 | @Override 94 | public void call(BaseData baseData) { 95 | showSimpleDialog(R.string.add_code_result, R.string.succeed); 96 | } 97 | }, new Action1() { 98 | @Override 99 | public void call(Throwable throwable) { 100 | showSimpleDialog(R.string.add_code_result, R.string.fail); 101 | } 102 | }); 103 | } 104 | 105 | private void addCode() { 106 | final EditText editText = new EditText(this); 107 | editText.setHint(R.string.add_code); 108 | new AlertDialog.Builder(this) 109 | .setTitle(R.string.add_code) 110 | .setView(editText) 111 | .setPositiveButton(R.string.confirm, new DialogInterface.OnClickListener() { 112 | @Override 113 | public void onClick(DialogInterface dialog, int which) { 114 | addCodeToServer(editText.getText().toString()); 115 | } 116 | }) 117 | .create() 118 | .show(); 119 | } 120 | 121 | private void setupRecyclerView(ActivityAboutBinding binding) { 122 | libraries.add(new GitRepository(null, getString(R.string.visit_wecan), null)); 123 | libraries.add(new GitRepository(getString(R.string.xidian_university), getString(R.string.wecan_studio), getString(R.string.wecan_website))); 124 | libraries.add(new GitRepository(null, getString(R.string.visit_github), null)); 125 | libraries.add(new GitRepository(getString(R.string.author), getString(R.string.app_name), getString(R.string.source_code))); 126 | libraries.add(new GitRepository(null, "Thanks to", null)); 127 | libraries.add(new GitRepository("Square", "Okhttp", "https://square.github.io/okhttp")); 128 | libraries.add(new GitRepository("Square", "Retrofit", "https://square.github.io/retrofit")); 129 | libraries.add(new GitRepository("Google", "Gson", "https://github.com/google/gson")); 130 | libraries.add(new GitRepository("ReactiveX", "RxJava", "https://github.com/ReactiveX/RxJava")); 131 | libraries.add(new GitRepository("ReactiveX", "RxAndroid", "https://github.com/ReactiveX/RxAndroid")); 132 | libraries.add(new GitRepository("JakeWharton", "RxBinding", "https://github.com/JakeWharton/RxBinding")); 133 | libraries.add(new GitRepository("JakeWharton", "nineoldandroids", "https://github.com/JakeWharton/NineOldAndroids")); 134 | libraries.add(new GitRepository("Trello", "RxLifecycle", "https://github.com/trello/RxLifecycle")); 135 | libraries.add(new GitRepository("OXO", "mr-mantou-android", "https://github.com/oxoooo/mr-mantou-android")); 136 | libraries.add(new GitRepository("drakeet", "Meizhi", "https://github.com/drakeet/Meizhi")); 137 | libraries.add(new GitRepository("donglua", "PhotoPicker", "https://github.com/donglua/PhotoPicker")); 138 | libraries.add(new GitRepository("balysv", "material-ripple", "https://github.com/balysv/material-ripple")); 139 | binding.libraries.setAdapter(new LibrariesAdapter(libraries, getLayoutInflater(), this)); 140 | } 141 | 142 | 143 | private void composeEmail(String address) { 144 | final Intent intent = new Intent(Intent.ACTION_SENDTO); 145 | intent.setData(Uri.parse("mailto:")); 146 | intent.putExtra(Intent.EXTRA_EMAIL, address); 147 | Observable.just(intent) 148 | .subscribeOn(Schedulers.io()) 149 | .map(new Func1>() { 150 | @Override 151 | public List call(Intent intent) { 152 | return getPackageManager().queryIntentActivities(intent, MODE_PRIVATE); 153 | } 154 | }) 155 | .observeOn(AndroidSchedulers.mainThread()) 156 | .filter(new Func1, Boolean>() { 157 | @Override 158 | public Boolean call(List resolveInfo) { 159 | if (resolveInfo.size() == 0) { 160 | showSimpleDialog(R.string.no_email_app); 161 | return false; 162 | } 163 | return true; 164 | } 165 | }) 166 | .compose(this.>bindToLifecycle()) 167 | .subscribe(new Action1>() { 168 | @Override 169 | public void call(List resolveInfo) { 170 | startActivity(intent); 171 | } 172 | }); 173 | } 174 | 175 | private void viewGitHub(String url) { 176 | Intent intent = new Intent(Intent.ACTION_VIEW); 177 | intent.setData(Uri.parse(url)); 178 | intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 179 | startActivity(intent); 180 | } 181 | 182 | @Override 183 | public void onLibraryClick(LibrariesAdapter.ItemViewHolder holder) { 184 | int position = holder.getAdapterPosition(); 185 | viewGitHub(libraries.get(position).url); 186 | } 187 | 188 | 189 | } 190 | -------------------------------------------------------------------------------- /app/src/main/java/com/wecan/xhin/studio/activity/LoginActivity.java: -------------------------------------------------------------------------------- 1 | package com.wecan.xhin.studio.activity; 2 | 3 | import android.app.ProgressDialog; 4 | import android.content.Intent; 5 | import android.databinding.DataBindingUtil; 6 | import android.os.Bundle; 7 | 8 | import com.jakewharton.rxbinding.view.RxView; 9 | import com.jakewharton.rxbinding.view.ViewClickEvent; 10 | import com.umeng.update.UmengUpdateAgent; 11 | import com.wecan.xhin.baselib.activity.BaseActivity; 12 | import com.wecan.xhin.baselib.rx.RxNetworking; 13 | import com.wecan.xhin.baselib.util.PreferenceHelper; 14 | import com.wecan.xhin.studio.App; 15 | import com.wecan.xhin.studio.R; 16 | import com.wecan.xhin.studio.api.Api; 17 | import com.wecan.xhin.studio.bean.common.User; 18 | import com.wecan.xhin.studio.databinding.ActivityLoginBinding; 19 | 20 | import java.io.IOException; 21 | 22 | import retrofit.HttpException; 23 | import rx.Observable; 24 | import rx.android.schedulers.AndroidSchedulers; 25 | import rx.functions.Action1; 26 | import rx.functions.Func0; 27 | import rx.schedulers.Schedulers; 28 | 29 | public class LoginActivity extends BaseActivity { 30 | 31 | private ActivityLoginBinding binding; 32 | private Observable observableConnect; 33 | private Api api; 34 | 35 | 36 | @Override 37 | protected void onCreate(Bundle savedInstanceState) { 38 | super.onCreate(savedInstanceState); 39 | 40 | 41 | binding = DataBindingUtil.setContentView(this, R.layout.activity_login); 42 | setSupportActionBar(binding.toolbar); 43 | api = App.from(this).createApi(Api.class); 44 | ProgressDialog pd = new ProgressDialog(this); 45 | 46 | Observable.Transformer networkingIndicator = RxNetworking.bindConnecting(pd); 47 | 48 | binding.setName(PreferenceHelper.getInstance(this).getString(App.KEY_PREFERENCE_USER, getString(R.string.nothing))); 49 | binding.setPhone(PreferenceHelper.getInstance(this).getString(App.KEY_PREFERENCE_PHONE, getString(R.string.nothing))); 50 | 51 | observableConnect = Observable 52 | //defer操作符是直到有订阅者订阅时,才通过Observable的工厂方法创建Observable并执行 53 | //defer操作符能够保证Observable的状态是最新的 54 | .defer(new Func0>() { 55 | @Override 56 | public Observable call() { 57 | return api.login(binding.etName.getText().toString(), binding.etPhone.getText().toString()); 58 | } 59 | }) 60 | .subscribeOn(Schedulers.io()) 61 | .observeOn(AndroidSchedulers.mainThread()) 62 | .compose(networkingIndicator); 63 | 64 | RxView.clickEvents(binding.btnLogin) 65 | .filter(new EditTextFilter(binding.etName, R.string.name_no_input)) 66 | .filter(new EditTextFilter(binding.etPhone, R.string.phone_no_input)) 67 | .compose(this.bindToLifecycle()) 68 | .subscribe(new Action1() { 69 | @Override 70 | public void call(ViewClickEvent viewClickEvent) { 71 | login(); 72 | } 73 | }); 74 | 75 | setRxClick(binding.btnRegister) 76 | .compose(this.bindToLifecycle()) 77 | .subscribe(new Action1() { 78 | @Override 79 | public void call(ViewClickEvent viewClickEvent) { 80 | startActivity(new Intent(LoginActivity.this, RegisterActivity.class)); 81 | } 82 | }); 83 | 84 | setupUmengUpdate(); 85 | } 86 | 87 | private void login() { 88 | observableConnect 89 | .compose(this.bindToLifecycle()) 90 | .subscribe(new Action1() { 91 | @Override 92 | public void call(User user) { 93 | PreferenceHelper.getInstance(LoginActivity.this).saveParam(App.KEY_PREFERENCE_USER, binding.etName.getText().toString()); 94 | PreferenceHelper.getInstance(LoginActivity.this).saveParam(App.KEY_PREFERENCE_PHONE, binding.etPhone.getText().toString()); 95 | startActivity(new Intent(LoginActivity.this, MainActivity.class).putExtra(MainActivity.KEY_USER, user)); 96 | finish(); 97 | } 98 | }, new Action1() { 99 | @Override 100 | public void call(Throwable throwable) { 101 | //事实上在code != 200 的时候 , 可以获取响应的body. 102 | if (throwable instanceof HttpException) { 103 | try { 104 | showSimpleDialog(R.string.login_fail, ((HttpException) throwable).response().errorBody().string()); 105 | } catch (IOException e) { 106 | showSimpleDialog(R.string.login_fail, throwable.getMessage()); 107 | } 108 | return; 109 | } 110 | showSimpleDialog(R.string.login_fail, throwable.getMessage()); 111 | } 112 | }); 113 | } 114 | 115 | 116 | private void setupUmengUpdate() { 117 | UmengUpdateAgent.update(this); 118 | UmengUpdateAgent.setDeltaUpdate(false); 119 | UmengUpdateAgent.setUpdateOnlyWifi(false); 120 | } 121 | } 122 | 123 | -------------------------------------------------------------------------------- /app/src/main/java/com/wecan/xhin/studio/activity/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.wecan.xhin.studio.activity; 2 | 3 | import android.content.Intent; 4 | import android.databinding.DataBindingUtil; 5 | import android.os.Bundle; 6 | import android.support.v4.app.Fragment; 7 | import android.support.v4.app.FragmentTransaction; 8 | import android.support.v4.view.GravityCompat; 9 | import android.support.v4.widget.DrawerLayout; 10 | import android.support.v7.app.ActionBarDrawerToggle; 11 | import android.view.MenuItem; 12 | 13 | import com.jakewharton.rxbinding.support.design.widget.RxNavigationView; 14 | import com.jakewharton.rxbinding.support.v4.widget.RxDrawerLayout; 15 | import com.wecan.xhin.baselib.activity.BaseActivity; 16 | import com.wecan.xhin.studio.R; 17 | import com.wecan.xhin.studio.bean.common.User; 18 | import com.wecan.xhin.studio.databinding.ActivityMainBinding; 19 | import com.wecan.xhin.studio.databinding.IncludeNavHeaderMainBinding; 20 | import com.wecan.xhin.studio.fragment.AllUserFragment; 21 | import com.wecan.xhin.studio.fragment.SignedUserFragment; 22 | import com.wecan.xhin.studio.fragment.BooksFragment; 23 | 24 | import rx.functions.Action1; 25 | import rx.functions.Func1; 26 | 27 | public class MainActivity extends BaseActivity { 28 | 29 | public static final String KEY_USER = "user"; 30 | public static final int REQUEST_MY_DETAIL = 0; 31 | 32 | private ActivityMainBinding binding; 33 | private IncludeNavHeaderMainBinding headerBinding; 34 | private User user; 35 | private Fragment signedUserFragment, allFellowFragment, booksFragment; 36 | 37 | 38 | @Override 39 | protected void onCreate(Bundle savedInstanceState) { 40 | super.onCreate(savedInstanceState); 41 | binding = DataBindingUtil.setContentView(this, R.layout.activity_main); 42 | setSupportActionBar(binding.toolbar); 43 | 44 | user = getIntent().getParcelableExtra(KEY_USER); 45 | binding.setUser(user); 46 | 47 | ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, binding.drawerLayout, 48 | binding.toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close); 49 | binding.drawerLayout.setDrawerListener(toggle); 50 | toggle.syncState(); 51 | 52 | 53 | headerBinding = DataBindingUtil 54 | .inflate(getLayoutInflater(), R.layout.include_nav_header_main, null, false); 55 | headerBinding.setUser(user); 56 | binding.navView.addHeaderView(headerBinding.getRoot()); 57 | 58 | 59 | RxNavigationView.itemSelections(binding.navView) 60 | .map(new Func1() { 61 | @Override 62 | public Integer call(MenuItem menuItem) { 63 | return menuItem.getItemId(); 64 | } 65 | }) 66 | .compose(this.bindToLifecycle()) 67 | .subscribe(new Action1() { 68 | @Override 69 | public void call(Integer menuItem) { 70 | setTabSelection(menuItem); 71 | RxDrawerLayout.open(binding.drawerLayout, GravityCompat.START) 72 | .call(false); 73 | } 74 | }); 75 | initNavigationSelection(); 76 | } 77 | 78 | private void initNavigationSelection() { 79 | binding.navView.setCheckedItem(R.id.signed_user); 80 | FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); 81 | signedUserFragment = SignedUserFragment.newInstance(user); 82 | transaction.add(R.id.fl_content, signedUserFragment); 83 | transaction.commit(); 84 | } 85 | 86 | private void setTabSelection(int itemId) { 87 | FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); 88 | switch (itemId) { 89 | case R.id.signed_user: 90 | hideFragments(transaction); 91 | if (signedUserFragment == null) { 92 | signedUserFragment = SignedUserFragment.newInstance(user); 93 | transaction.add(R.id.fl_content, signedUserFragment); 94 | break; 95 | } 96 | transaction.show(signedUserFragment); 97 | break; 98 | case R.id.book: 99 | hideFragments(transaction); 100 | if (booksFragment == null) { 101 | booksFragment = new BooksFragment(); 102 | transaction.add(R.id.fl_content, booksFragment); 103 | break; 104 | } 105 | transaction.show(booksFragment); 106 | break; 107 | case R.id.all_user: 108 | hideFragments(transaction); 109 | if (allFellowFragment == null) { 110 | allFellowFragment = AllUserFragment.newInstance(); 111 | transaction.add(R.id.fl_content, allFellowFragment); 112 | break; 113 | } 114 | transaction.show(allFellowFragment); 115 | break; 116 | case R.id.about: 117 | startActivity(new Intent(this, AboutActivity.class)); 118 | break; 119 | case R.id.me: 120 | startActivityForResult(new Intent(this, MyDetailsActivity.class) 121 | .putExtra(UserDetailsActivity.KEY_USER, user), REQUEST_MY_DETAIL); 122 | break; 123 | } 124 | transaction.commit(); 125 | } 126 | 127 | 128 | private void hideFragments(FragmentTransaction transaction) { 129 | if (signedUserFragment != null) { 130 | transaction.hide(signedUserFragment); 131 | } 132 | if (allFellowFragment != null) { 133 | transaction.hide(allFellowFragment); 134 | } 135 | if (booksFragment != null) { 136 | transaction.hide(booksFragment); 137 | } 138 | } 139 | 140 | @Override 141 | protected void onActivityResult(int requestCode, int resultCode, Intent data) { 142 | super.onActivityResult(requestCode, resultCode, data); 143 | if (resultCode != RESULT_OK) 144 | return; 145 | switch (requestCode) { 146 | case REQUEST_MY_DETAIL: 147 | user = data.getParcelableExtra(KEY_USER); 148 | binding.setUser(user); 149 | headerBinding.setUser(user); 150 | break; 151 | } 152 | } 153 | 154 | @Override 155 | public void onBackPressed() { 156 | DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); 157 | if (drawer.isDrawerOpen(GravityCompat.START)) { 158 | drawer.closeDrawer(GravityCompat.START); 159 | return; 160 | } 161 | super.onBackPressed(); 162 | } 163 | 164 | } 165 | -------------------------------------------------------------------------------- /app/src/main/java/com/wecan/xhin/studio/activity/PictureActivity.java: -------------------------------------------------------------------------------- 1 | package com.wecan.xhin.studio.activity; 2 | 3 | import android.databinding.DataBindingUtil; 4 | import android.os.Bundle; 5 | import android.support.v4.view.ViewCompat; 6 | import android.widget.ImageView; 7 | 8 | import com.bumptech.glide.Glide; 9 | import com.bumptech.glide.RequestManager; 10 | import com.bumptech.glide.load.engine.DiskCacheStrategy; 11 | import com.wecan.xhin.baselib.activity.BaseActivity; 12 | import com.wecan.xhin.studio.R; 13 | import com.wecan.xhin.studio.databinding.ActivityPictureBinding; 14 | 15 | import uk.co.senab.photoview.PhotoViewAttacher; 16 | 17 | public class PictureActivity extends BaseActivity { 18 | 19 | public static final String KEY_IMAGE_URL = "image_url"; 20 | public static final String TRANSIT_PIC = "picture"; 21 | 22 | private PhotoViewAttacher mPhotoViewAttacher; 23 | private ActivityPictureBinding binding; 24 | private RequestManager requestManager; 25 | 26 | protected void setAppBarAlpha(float alpha) { 27 | binding.appBar.setAlpha(alpha); 28 | } 29 | 30 | @Override 31 | protected void onCreate(Bundle savedInstanceState) { 32 | super.onCreate(savedInstanceState); 33 | binding = DataBindingUtil.setContentView(this, R.layout.activity_picture); 34 | setSupportActionBar(binding.toolbar); 35 | setHasHomeButton(); 36 | 37 | requestManager = Glide.with(this); 38 | String imgUrl = getIntent().getStringExtra(KEY_IMAGE_URL); 39 | 40 | ViewCompat.setTransitionName(binding.picture, TRANSIT_PIC); 41 | setupImage(binding.picture, imgUrl); 42 | 43 | setAppBarAlpha(0.7f); 44 | setupPhotoAttacher(); 45 | } 46 | 47 | private void setupImage(ImageView image, String imageUrl) { 48 | if (imageUrl == null || imageUrl.length() == 0) 49 | return; 50 | requestManager.load(imageUrl) 51 | .diskCacheStrategy(DiskCacheStrategy.ALL) 52 | .error(R.drawable.defimgs) 53 | .into(image); 54 | } 55 | 56 | private void setupPhotoAttacher() { 57 | mPhotoViewAttacher = new PhotoViewAttacher(binding.picture); 58 | } 59 | 60 | @Override 61 | protected void onDestroy() { 62 | super.onDestroy(); 63 | mPhotoViewAttacher.cleanup(); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /app/src/main/java/com/wecan/xhin/studio/activity/RegisterActivity.java: -------------------------------------------------------------------------------- 1 | package com.wecan.xhin.studio.activity; 2 | 3 | import android.app.ProgressDialog; 4 | import android.databinding.DataBindingUtil; 5 | import android.os.Bundle; 6 | 7 | import com.jakewharton.rxbinding.view.ViewClickEvent; 8 | import com.wecan.xhin.baselib.activity.BaseActivity; 9 | import com.wecan.xhin.baselib.rx.RxNetworking; 10 | import com.wecan.xhin.studio.App; 11 | import com.wecan.xhin.studio.R; 12 | import com.wecan.xhin.studio.api.Api; 13 | import com.wecan.xhin.studio.bean.down.BaseData; 14 | import com.wecan.xhin.studio.bean.up.RegisterBody; 15 | import com.wecan.xhin.studio.databinding.ActivityRegisterBinding; 16 | 17 | import rx.Observable; 18 | import rx.android.schedulers.AndroidSchedulers; 19 | import rx.functions.Action1; 20 | import rx.functions.Func0; 21 | import rx.schedulers.Schedulers; 22 | 23 | /** 24 | * Created by xhinliang on 15-11-23. 25 | * xhinliang@gmail.com 26 | */ 27 | public class RegisterActivity extends BaseActivity { 28 | 29 | private ActivityRegisterBinding binding; 30 | private Api api; 31 | private Observable observableRegister; 32 | 33 | @Override 34 | protected void onCreate(Bundle savedInstanceState) { 35 | super.onCreate(savedInstanceState); 36 | binding = DataBindingUtil.setContentView(this, R.layout.activity_register); 37 | setSupportActionBar(binding.toolbar); 38 | if (getSupportActionBar() != null) { 39 | getSupportActionBar().setDisplayHomeAsUpEnabled(true); 40 | getSupportActionBar().setHomeButtonEnabled(true); 41 | } 42 | api = App.from(this).createApi(Api.class); 43 | ProgressDialog pd = new ProgressDialog(this); 44 | Observable.Transformer networkingIndicator = RxNetworking.bindConnecting(pd); 45 | 46 | observableRegister = Observable 47 | //defer操作符是直到有订阅者订阅时,才通过Observable的工厂方法创建Observable并执行 48 | //defer操作符能够保证Observable的状态是最新的 49 | .defer(new Func0>() { 50 | @Override 51 | public Observable call() { 52 | return api.register(new RegisterBody(binding.acpPosition.getSelectedItemPosition() 53 | , binding.acpGroupName.getSelectedItemPosition() 54 | , binding.etPhone.getText().toString().trim() 55 | , binding.acpSex.getSelectedItemPosition() 56 | , binding.etName.getText().toString().trim() 57 | , binding.etCode.getText().toString().trim())); 58 | } 59 | }) 60 | .subscribeOn(Schedulers.io()) 61 | .observeOn(AndroidSchedulers.mainThread()) 62 | .compose(networkingIndicator); 63 | 64 | 65 | setRxClick(binding.btnRegister) 66 | .filter(new SpinnerFilter(binding.acpGroupName, R.string.group_no_selected)) 67 | .filter(new SpinnerFilter(binding.acpSex, R.string.sex_no_selected)) 68 | .filter(new SpinnerFilter(binding.acpPosition, R.string.position_no_selected)) 69 | .filter(new EditTextFilter(binding.etName, R.string.name_no_input)) 70 | .filter(new EditTextFilter(binding.etPhone, R.string.phone_no_input)) 71 | .filter(new EditTextFilter(binding.etCode, R.string.code_no_input)) 72 | .compose(this.bindToLifecycle()) 73 | .subscribe(new Action1() { 74 | @Override 75 | public void call(ViewClickEvent event) { 76 | register(); 77 | } 78 | }); 79 | } 80 | 81 | private void register() { 82 | observableRegister 83 | .compose(this.bindToLifecycle()) 84 | .subscribe(new Action1() { 85 | @Override 86 | public void call(BaseData baseData) { 87 | showSimpleDialog(baseData.status == 1 ? R.string.succeed : R.string.register_fail); 88 | } 89 | }, new Action1() { 90 | @Override 91 | public void call(Throwable throwable) { 92 | showSimpleDialog(R.string.register_fail); 93 | } 94 | }); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /app/src/main/java/com/wecan/xhin/studio/activity/TestActivity.java: -------------------------------------------------------------------------------- 1 | package com.wecan.xhin.studio.activity; 2 | 3 | import android.app.Activity; 4 | import android.content.pm.PackageManager; 5 | import android.os.Bundle; 6 | import android.util.Log; 7 | 8 | /** 9 | * Created by xhinliang on 15-12-21. 10 | * xhinliang@gmail.com 11 | */ 12 | public class TestActivity extends Activity { 13 | private static final String TAG = "TestActivity"; 14 | 15 | @Override 16 | protected void onCreate(Bundle savedInstanceState) { 17 | super.onCreate(savedInstanceState); 18 | showPath(); 19 | showMetaData(); 20 | } 21 | 22 | private void showMetaData() { 23 | try { 24 | Log.d(TAG, getPackageManager() 25 | .getApplicationInfo(getPackageName(), PackageManager.GET_META_DATA) 26 | .metaData.getString("UMENG_APPKEY")); 27 | } catch (PackageManager.NameNotFoundException e) { 28 | e.printStackTrace(); 29 | } 30 | } 31 | 32 | private void showPath() { 33 | Log.d(TAG, getFilesDir().getAbsolutePath()); 34 | Log.d(TAG, getCacheDir().getAbsolutePath()); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /app/src/main/java/com/wecan/xhin/studio/activity/UserDetailsActivity.java: -------------------------------------------------------------------------------- 1 | package com.wecan.xhin.studio.activity; 2 | 3 | import android.Manifest; 4 | import android.content.Intent; 5 | import android.content.pm.PackageManager; 6 | import android.databinding.DataBindingUtil; 7 | import android.net.Uri; 8 | import android.os.Bundle; 9 | import android.support.v4.app.ActivityCompat; 10 | import android.widget.ImageView; 11 | 12 | import com.bumptech.glide.Glide; 13 | import com.bumptech.glide.RequestManager; 14 | import com.bumptech.glide.load.engine.DiskCacheStrategy; 15 | import com.jakewharton.rxbinding.view.ViewClickEvent; 16 | import com.wecan.xhin.baselib.activity.BaseActivity; 17 | import com.wecan.xhin.studio.R; 18 | import com.wecan.xhin.studio.bean.common.User; 19 | import com.wecan.xhin.studio.databinding.ActivityUserDetailsBinding; 20 | 21 | import rx.functions.Action1; 22 | 23 | public class UserDetailsActivity extends BaseActivity { 24 | 25 | public static final String KEY_USER = "user"; 26 | 27 | protected RequestManager requestManager; 28 | protected ActivityUserDetailsBinding binding; 29 | 30 | @Override 31 | protected void onCreate(Bundle savedInstanceState) { 32 | super.onCreate(savedInstanceState); 33 | requestManager = Glide.with(this); 34 | binding = DataBindingUtil.setContentView(this, R.layout.activity_user_details); 35 | setSupportActionBar(binding.toolbar); 36 | setHasHomeButton(); 37 | final User user = getIntent().getParcelableExtra(KEY_USER); 38 | binding.setUser(user); 39 | 40 | setupImage(binding.ivPicture, binding.getUser().imgurl); 41 | setRxClick(binding.fab) 42 | .compose(this.bindToLifecycle()) 43 | .subscribe(new Action1() { 44 | @Override 45 | public void call(ViewClickEvent viewClickEvent) { 46 | Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:" + user.phone)); 47 | //打电话有可能被拒绝 48 | if (ActivityCompat.checkSelfPermission(UserDetailsActivity.this, Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) { 49 | return; 50 | } 51 | startActivity(intent); 52 | } 53 | }); 54 | 55 | setRxClick(binding.ivPicture) 56 | .compose(this.bindToLifecycle()) 57 | .subscribe(new Action1() { 58 | @Override 59 | public void call(ViewClickEvent viewClickEvent) { 60 | startActivity(new Intent(UserDetailsActivity.this, PictureActivity.class) 61 | .putExtra(PictureActivity.KEY_IMAGE_URL, user.imgurl)); 62 | } 63 | }); 64 | } 65 | 66 | private void setupImage(ImageView image, String imageUrl) { 67 | if (imageUrl == null || imageUrl.length() == 0) 68 | return; 69 | requestManager.load(imageUrl) 70 | .diskCacheStrategy(DiskCacheStrategy.ALL) 71 | .error(R.drawable.defimgs) 72 | .into(image); 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /app/src/main/java/com/wecan/xhin/studio/adapter/LibrariesAdapter.java: -------------------------------------------------------------------------------- 1 | package com.wecan.xhin.studio.adapter; 2 | 3 | import android.support.v7.widget.RecyclerView; 4 | import android.view.LayoutInflater; 5 | import android.view.ViewGroup; 6 | 7 | import com.jakewharton.rxbinding.view.RxView; 8 | import com.jakewharton.rxbinding.view.ViewClickEvent; 9 | import com.wecan.xhin.studio.bean.GitRepository; 10 | import com.wecan.xhin.studio.databinding.RecyclerItemHeaderBinding; 11 | import com.wecan.xhin.studio.databinding.RecyclerItemLibraryBinding; 12 | import com.wecan.xhin.studio.reactivex.BindingRecyclerView; 13 | 14 | import java.util.List; 15 | 16 | import rx.functions.Action1; 17 | 18 | /** 19 | * Created by xhinliang on 15-11-23. 20 | * xhinliang@gmail.com 21 | */ 22 | public class LibrariesAdapter extends RecyclerView.Adapter { 23 | 24 | private static final int VALUE_TYPE_HEADER = 0; 25 | private static final int VALUE_TYPE_LIBRARY = 1; 26 | 27 | private List libraries; 28 | private LayoutInflater inflater; 29 | private Listener listener; 30 | 31 | public LibrariesAdapter(List list, LayoutInflater inflater, Listener listener) { 32 | this.libraries = list; 33 | this.inflater = inflater; 34 | this.listener = listener; 35 | } 36 | 37 | @Override 38 | public BindingRecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 39 | if (viewType == 0) 40 | return new HeaderViewHolder(RecyclerItemHeaderBinding.inflate(inflater, parent, false)); 41 | return new ItemViewHolder(RecyclerItemLibraryBinding.inflate(inflater, parent, false)); 42 | } 43 | 44 | @Override 45 | public void onBindViewHolder(BindingRecyclerView.ViewHolder holder, int position) { 46 | if (holder.getItemViewType() == VALUE_TYPE_HEADER) { 47 | ((HeaderViewHolder) holder).binding.setName(libraries.get(position).name); 48 | return; 49 | } 50 | ItemViewHolder itemHolder = (ItemViewHolder) holder; 51 | itemHolder.binding.setName(libraries.get(position).toString()); 52 | } 53 | 54 | @Override 55 | public int getItemViewType(int position) { 56 | return libraries.get(position).author == null ? VALUE_TYPE_HEADER : VALUE_TYPE_LIBRARY; 57 | } 58 | 59 | @Override 60 | public int getItemCount() { 61 | return libraries.size(); 62 | } 63 | 64 | 65 | class HeaderViewHolder extends BindingRecyclerView.ViewHolder { 66 | public HeaderViewHolder(RecyclerItemHeaderBinding binding) { 67 | super(binding); 68 | } 69 | } 70 | 71 | public interface Listener { 72 | void onLibraryClick(ItemViewHolder holder); 73 | } 74 | 75 | public class ItemViewHolder extends BindingRecyclerView.ViewHolder { 76 | public ItemViewHolder(RecyclerItemLibraryBinding binding) { 77 | super(binding); 78 | RxView.clickEvents(itemView) 79 | .subscribe(new Action1() { 80 | @Override 81 | public void call(ViewClickEvent viewClickEvent) { 82 | listener.onLibraryClick(ItemViewHolder.this); 83 | } 84 | }); 85 | } 86 | } 87 | } -------------------------------------------------------------------------------- /app/src/main/java/com/wecan/xhin/studio/adapter/SimpleAdapter.java: -------------------------------------------------------------------------------- 1 | package com.wecan.xhin.studio.adapter; 2 | 3 | import android.support.v7.widget.RecyclerView; 4 | import android.view.LayoutInflater; 5 | import android.view.ViewGroup; 6 | 7 | import com.jakewharton.rxbinding.view.RxView; 8 | import com.jakewharton.rxbinding.view.ViewClickEvent; 9 | import com.wecan.xhin.studio.bean.Simple; 10 | import com.wecan.xhin.studio.databinding.RecyclerItemSimpleBinding; 11 | import com.wecan.xhin.studio.reactivex.BindingRecyclerView; 12 | 13 | import java.util.List; 14 | 15 | import rx.functions.Action1; 16 | 17 | /** 18 | * Created by xhinliang on 15-11-23. 19 | * xhinliang@gmail.com 20 | */ 21 | public class SimpleAdapter extends RecyclerView.Adapter { 22 | private List libraries; 23 | private LayoutInflater inflater; 24 | private Listener listener; 25 | 26 | public SimpleAdapter(List list, LayoutInflater inflater, Listener listener) { 27 | this.libraries = list; 28 | this.inflater = inflater; 29 | this.listener = listener; 30 | } 31 | 32 | @Override 33 | public BindingRecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 34 | return new ItemViewHolder(RecyclerItemSimpleBinding.inflate(inflater, parent, false)); 35 | } 36 | 37 | @Override 38 | public void onBindViewHolder(BindingRecyclerView.ViewHolder holder, int position) { 39 | ItemViewHolder itemHolder = (ItemViewHolder) holder; 40 | itemHolder.binding.setSimple(libraries.get(position)); 41 | } 42 | 43 | @Override 44 | public int getItemCount() { 45 | return libraries.size(); 46 | } 47 | 48 | public interface Listener { 49 | void onLibraryClick(ItemViewHolder holder); 50 | } 51 | 52 | public class ItemViewHolder extends BindingRecyclerView.ViewHolder { 53 | public ItemViewHolder(RecyclerItemSimpleBinding binding) { 54 | super(binding); 55 | RxView.clickEvents(itemView) 56 | .subscribe(new Action1() { 57 | @Override 58 | public void call(ViewClickEvent viewClickEvent) { 59 | listener.onLibraryClick(ItemViewHolder.this); 60 | } 61 | }); 62 | } 63 | } 64 | } -------------------------------------------------------------------------------- /app/src/main/java/com/wecan/xhin/studio/adapter/UsersAdapter.java: -------------------------------------------------------------------------------- 1 | package com.wecan.xhin.studio.adapter; 2 | 3 | import android.content.Context; 4 | import android.databinding.ObservableList; 5 | import android.view.View; 6 | import android.view.ViewGroup; 7 | import android.widget.ImageView; 8 | 9 | import com.bumptech.glide.RequestManager; 10 | import com.bumptech.glide.load.engine.DiskCacheStrategy; 11 | import com.wecan.xhin.studio.R; 12 | import com.wecan.xhin.studio.bean.common.User; 13 | import com.wecan.xhin.studio.databinding.RecyclerItemUserBinding; 14 | import com.wecan.xhin.studio.reactivex.BindingRecyclerView; 15 | 16 | public class UsersAdapter extends BindingRecyclerView.ListAdapter { 17 | 18 | private Listener listener; 19 | 20 | 21 | private RequestManager requestManager; 22 | 23 | 24 | public UsersAdapter(Context context, ObservableList data, Listener listener, RequestManager requestManager) { 25 | super(context, data); 26 | this.listener = listener; 27 | this.requestManager = requestManager; 28 | setHasStableIds(true); 29 | } 30 | 31 | @Override 32 | public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 33 | return new ViewHolder(RecyclerItemUserBinding.inflate(inflater, parent, false)); 34 | } 35 | 36 | @Override 37 | public void onBindViewHolder(ViewHolder holder, int position) { 38 | User item = data.get(position); 39 | holder.binding.setUser(item); 40 | // execute the binding immediately to ensure 41 | // the original size of RatioImageView is set before layout 42 | holder.binding.executePendingBindings(); 43 | 44 | setupImage(holder.binding.ivAvatar, item.imgurl); 45 | holder.itemView.setTag(item); 46 | } 47 | 48 | private void setupImage(ImageView image, String imageUrl) { 49 | if (imageUrl == null || imageUrl.length() == 0) { 50 | image.setImageResource(R.drawable.header); 51 | return; 52 | } 53 | requestManager.load(imageUrl) 54 | .diskCacheStrategy(DiskCacheStrategy.ALL) 55 | .error(R.drawable.defimgs) 56 | .into(image); 57 | } 58 | 59 | //重载这个方法并设置 RecyclerView#setHasStableIds能大幅度提高性能 60 | @Override 61 | public long getItemId(int position) { 62 | return data.get(position).getName().hashCode(); 63 | } 64 | 65 | //一种在ViewHolder里实现点击事件的方法,绑定当前Adapter的Activity实现这个接口即可 66 | public interface Listener { 67 | void onUserItemClick(ViewHolder holder); 68 | } 69 | 70 | public class ViewHolder extends BindingRecyclerView.ViewHolder { 71 | 72 | public ViewHolder(RecyclerItemUserBinding binding) { 73 | super(binding); 74 | itemView.setOnClickListener(new View.OnClickListener() { 75 | @Override 76 | public void onClick(View v) { 77 | listener.onUserItemClick(ViewHolder.this); 78 | } 79 | }); 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /app/src/main/java/com/wecan/xhin/studio/api/Api.java: -------------------------------------------------------------------------------- 1 | 2 | package com.wecan.xhin.studio.api; 3 | 4 | 5 | import com.wecan.xhin.studio.bean.common.User; 6 | import com.wecan.xhin.studio.bean.down.BaseData; 7 | import com.wecan.xhin.studio.bean.down.UsersData; 8 | import com.wecan.xhin.studio.bean.up.RegisterBody; 9 | import com.wecan.xhin.studio.bean.up.SignBody; 10 | 11 | import retrofit.http.Body; 12 | import retrofit.http.DELETE; 13 | import retrofit.http.GET; 14 | import retrofit.http.POST; 15 | import retrofit.http.PUT; 16 | import retrofit.http.Path; 17 | import retrofit.http.Query; 18 | import rx.Observable; 19 | 20 | public interface Api { 21 | 22 | String BASE_URL = "http://121.42.209.19/RestfulApi/index.php/"; 23 | 24 | @GET("api/users") 25 | Observable login(@Query("name") String name, @Query("phone") String phone); 26 | 27 | @POST("api/users") 28 | Observable register(@Body RegisterBody registerUser); 29 | 30 | @PUT("api/users") 31 | Observable updateUser(@Body User updateUser); 32 | 33 | @POST("api/sign") 34 | Observable sign(@Body SignBody user); 35 | 36 | @DELETE("api/sign") 37 | Observable unSign(@Query("name") String name); 38 | 39 | @GET("api/message_all") 40 | Observable getAllUser(); 41 | 42 | @GET("api/message") 43 | Observable getSignedUser(); 44 | 45 | @GET("api/addplease/{code}") 46 | Observable addCode(@Path("code") String code); 47 | 48 | } 49 | -------------------------------------------------------------------------------- /app/src/main/java/com/wecan/xhin/studio/bean/GitRepository.java: -------------------------------------------------------------------------------- 1 | package com.wecan.xhin.studio.bean; 2 | 3 | /** 4 | * Created by xhinliang on 15-11-23. 5 | * xhinliang@gmail.com 6 | */ 7 | public class GitRepository { 8 | public String author; 9 | public String name; 10 | public String url; 11 | 12 | public GitRepository(String author, String name, String url) { 13 | this.author = author; 14 | this.name = name; 15 | this.url = url; 16 | } 17 | 18 | 19 | @Override 20 | public String toString() { 21 | return String.format("%s / %s", author, name); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/src/main/java/com/wecan/xhin/studio/bean/Simple.java: -------------------------------------------------------------------------------- 1 | package com.wecan.xhin.studio.bean; 2 | 3 | /** 4 | * Created by xhinliang on 15-11-24. 5 | * xhinliang@gmail.com 6 | */ 7 | public class Simple { 8 | public String title; 9 | public String content; 10 | 11 | public Simple(String title, String content) { 12 | this.title = title; 13 | this.content = content; 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /app/src/main/java/com/wecan/xhin/studio/bean/common/User.java: -------------------------------------------------------------------------------- 1 | package com.wecan.xhin.studio.bean.common; 2 | 3 | import android.databinding.BaseObservable; 4 | import android.os.Parcel; 5 | import android.os.Parcelable; 6 | 7 | /** 8 | * Created by xhinliang on 15-11-18. 9 | * xhinliang@gmail.com 10 | */ 11 | public class User extends BaseObservable implements Parcelable { 12 | public int position; 13 | public int group_name; 14 | public int id; 15 | public int sex; 16 | public int status; 17 | 18 | public String phone; 19 | public String sign_date; 20 | 21 | 22 | public String name; 23 | public String imgurl; 24 | public String description; 25 | 26 | public static final String[] groups = { 27 | "组别", "前端", "后台", "移动", "产品", "设计", "YOU KNOW NOTHING" 28 | }; 29 | 30 | public static final String[] positions = { 31 | "职位", "组员", "组长", "室长", "John Snow" 32 | }; 33 | 34 | public static final String[] sexs = { 35 | "性别", "男", "女" 36 | }; 37 | public static final int VALUE_STATUS_SIGN = 1; 38 | public static final int VALUE_STATUS_UNSIGN = 0; 39 | 40 | public String getName() { 41 | return name; 42 | } 43 | 44 | public static String getGroupName(int group) { 45 | return groups[group]; 46 | } 47 | 48 | public static String getPositionName(int position) { 49 | return positions[position]; 50 | } 51 | 52 | public static String getSexName(int sex) { 53 | return sexs[sex]; 54 | } 55 | 56 | @Override 57 | public int describeContents() { 58 | return 0; 59 | } 60 | 61 | @Override 62 | public void writeToParcel(Parcel dest, int flags) { 63 | dest.writeInt(this.position); 64 | dest.writeInt(this.group_name); 65 | dest.writeInt(this.id); 66 | dest.writeInt(this.sex); 67 | dest.writeInt(this.status); 68 | dest.writeString(this.phone); 69 | dest.writeString(this.sign_date); 70 | dest.writeString(this.name); 71 | dest.writeString(this.imgurl); 72 | dest.writeString(this.description); 73 | } 74 | 75 | public User() { 76 | } 77 | 78 | protected User(Parcel in) { 79 | this.position = in.readInt(); 80 | this.group_name = in.readInt(); 81 | this.id = in.readInt(); 82 | this.sex = in.readInt(); 83 | this.status = in.readInt(); 84 | this.phone = in.readString(); 85 | this.sign_date = in.readString(); 86 | this.name = in.readString(); 87 | this.imgurl = in.readString(); 88 | this.description = in.readString(); 89 | } 90 | 91 | public static final Creator CREATOR = new Creator() { 92 | public User createFromParcel(Parcel source) { 93 | return new User(source); 94 | } 95 | 96 | public User[] newArray(int size) { 97 | return new User[size]; 98 | } 99 | }; 100 | } 101 | -------------------------------------------------------------------------------- /app/src/main/java/com/wecan/xhin/studio/bean/down/BaseData.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Drakeet 3 | * 4 | * This file is part of Meizhi 5 | * 6 | * Meizhi is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * Meizhi is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with Meizhi. If not, see . 18 | */ 19 | 20 | package com.wecan.xhin.studio.bean.down; 21 | 22 | public class BaseData { 23 | public int status; 24 | public String message; 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/java/com/wecan/xhin/studio/bean/down/UsersData.java: -------------------------------------------------------------------------------- 1 | package com.wecan.xhin.studio.bean.down; 2 | 3 | import com.wecan.xhin.studio.bean.common.User; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * Created by xhinliang on 15-11-19. 9 | * xhinliang@gmail.com 10 | */ 11 | public class UsersData extends BaseData { 12 | public List data; 13 | } 14 | -------------------------------------------------------------------------------- /app/src/main/java/com/wecan/xhin/studio/bean/up/RegisterBody.java: -------------------------------------------------------------------------------- 1 | package com.wecan.xhin.studio.bean.up; 2 | 3 | /** 4 | * Created by xhinliang on 15-11-23. 5 | * xhinliang@gmail.com 6 | */ 7 | public class RegisterBody { 8 | 9 | private int position; 10 | private int group_name; 11 | private int sex; 12 | private String phone; 13 | private String name; 14 | private String imgurl; 15 | private String code; 16 | private String description; 17 | 18 | public RegisterBody(int position, int group_name, String phone, int sex, String name, String code) { 19 | this.position = position; 20 | this.group_name = group_name; 21 | this.phone = phone; 22 | this.sex = sex; 23 | this.name = name; 24 | this.code = code; 25 | this.imgurl = ""; 26 | this.description = ""; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/src/main/java/com/wecan/xhin/studio/bean/up/SignBody.java: -------------------------------------------------------------------------------- 1 | package com.wecan.xhin.studio.bean.up; 2 | 3 | /** 4 | * Created by xhinliang on 15-11-23. 5 | * xhinliang@gmail.com 6 | */ 7 | public class SignBody { 8 | public String name; 9 | 10 | public SignBody(String name) { 11 | this.name = name; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /app/src/main/java/com/wecan/xhin/studio/fragment/AllUserFragment.java: -------------------------------------------------------------------------------- 1 | package com.wecan.xhin.studio.fragment; 2 | 3 | import com.wecan.xhin.studio.api.Api; 4 | import com.wecan.xhin.studio.bean.down.UsersData; 5 | 6 | import rx.Observable; 7 | 8 | /** 9 | * Created by xhinliang on 15-11-20. 10 | * xhinliang@gmail.com 11 | */ 12 | public class AllUserFragment extends UsersFragment { 13 | 14 | public static AllUserFragment newInstance() { 15 | return new AllUserFragment(); 16 | } 17 | 18 | @Override 19 | protected Observable getUserApi(Api api) { 20 | return api.getAllUser(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/src/main/java/com/wecan/xhin/studio/fragment/BooksFragment.java: -------------------------------------------------------------------------------- 1 | package com.wecan.xhin.studio.fragment; 2 | 3 | import com.wecan.xhin.baselib.fragment.BaseFragment; 4 | 5 | /** 6 | * Created by xhinliang on 15-11-24. 7 | * xhinliang@gmail.com 8 | */ 9 | public class BooksFragment extends BaseFragment { 10 | } 11 | -------------------------------------------------------------------------------- /app/src/main/java/com/wecan/xhin/studio/fragment/RxBindingFragment.java: -------------------------------------------------------------------------------- 1 | package com.wecan.xhin.studio.fragment; 2 | 3 | import android.databinding.ViewDataBinding; 4 | import android.os.Bundle; 5 | import android.support.annotation.Nullable; 6 | import android.view.LayoutInflater; 7 | import android.view.View; 8 | import android.view.ViewGroup; 9 | 10 | import com.jakewharton.rxbinding.view.RxView; 11 | import com.jakewharton.rxbinding.view.ViewClickEvent; 12 | import com.trello.rxlifecycle.components.support.RxFragment; 13 | 14 | import java.util.concurrent.TimeUnit; 15 | 16 | import rx.Observable; 17 | 18 | public class RxBindingFragment extends RxFragment { 19 | 20 | protected V binding; 21 | 22 | @Nullable 23 | public V onCreateBinding(LayoutInflater inflater, @Nullable ViewGroup container, 24 | @Nullable Bundle savedInstanceState) { 25 | return null; 26 | } 27 | 28 | @Nullable 29 | @Override 30 | public final View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, 31 | @Nullable Bundle savedInstanceState) { 32 | binding = onCreateBinding(inflater, container, savedInstanceState); 33 | return binding == null ? null : binding.getRoot(); 34 | } 35 | 36 | protected Observable setRxView(View view) { 37 | return RxView.clickEvents(view) 38 | .compose(this.bindToLifecycle()) 39 | .throttleFirst(500, TimeUnit.MILLISECONDS); 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /app/src/main/java/com/wecan/xhin/studio/fragment/SignedUserFragment.java: -------------------------------------------------------------------------------- 1 | package com.wecan.xhin.studio.fragment; 2 | 3 | import android.app.ProgressDialog; 4 | import android.os.Bundle; 5 | import android.view.View; 6 | 7 | import com.jakewharton.rxbinding.view.ViewClickEvent; 8 | import com.wecan.xhin.baselib.rx.RxNetworking; 9 | import com.wecan.xhin.studio.R; 10 | import com.wecan.xhin.studio.api.Api; 11 | import com.wecan.xhin.studio.bean.common.User; 12 | import com.wecan.xhin.studio.bean.down.BaseData; 13 | import com.wecan.xhin.studio.bean.down.UsersData; 14 | import com.wecan.xhin.studio.bean.up.SignBody; 15 | 16 | import rx.Observable; 17 | import rx.android.schedulers.AndroidSchedulers; 18 | import rx.functions.Action1; 19 | import rx.functions.Func0; 20 | import rx.functions.Func1; 21 | import rx.schedulers.Schedulers; 22 | 23 | /** 24 | * Created by xhinliang on 15-11-20. 25 | * xhinliang@gmail.com 26 | */ 27 | public class SignedUserFragment extends UsersFragment { 28 | 29 | public static final String KEY_USER = "user"; 30 | 31 | private User user; 32 | private Observable observableSign; 33 | private Observable.Transformer networkingIndicator; 34 | 35 | public static SignedUserFragment newInstance(User user) { 36 | SignedUserFragment fragment = new SignedUserFragment(); 37 | Bundle bundle = new Bundle(); 38 | bundle.putParcelable(KEY_USER, user); 39 | fragment.setArguments(bundle); 40 | return fragment; 41 | } 42 | 43 | @Override 44 | public void onViewCreated(View view, Bundle savedInstanceState) { 45 | super.onViewCreated(view, savedInstanceState); 46 | ProgressDialog pd = new ProgressDialog(getActivity()); 47 | networkingIndicator = RxNetworking.bindConnecting(pd); 48 | initView(); 49 | setEvent(); 50 | } 51 | 52 | 53 | protected void setEvent() { 54 | observableSign = Observable 55 | .defer(new Func0>() { 56 | @Override 57 | public Observable call() { 58 | if (user.status == User.VALUE_STATUS_SIGN) 59 | return api.unSign(user.name); 60 | return api.sign(new SignBody(user.name)); 61 | } 62 | }) 63 | .subscribeOn(Schedulers.io()) 64 | .observeOn(AndroidSchedulers.mainThread()) 65 | .compose(networkingIndicator); 66 | 67 | setRxView(binding.fabSign) 68 | .compose(this.bindToLifecycle()) 69 | .subscribe(new Action1() { 70 | @Override 71 | public void call(ViewClickEvent event) { 72 | signOrUnsign(); 73 | } 74 | }); 75 | } 76 | 77 | private void signOrUnsign() { 78 | observableSign 79 | .flatMap(new Func1>() { 80 | @Override 81 | public Observable call(BaseData baseData) { 82 | user.status = user.status == User.VALUE_STATUS_UNSIGN ? 83 | User.VALUE_STATUS_SIGN : User.VALUE_STATUS_UNSIGN; 84 | binding.fabSign.setImageResource(user.status == User.VALUE_STATUS_SIGN 85 | ? R.drawable.ic_sign : R.drawable.ic_unsign); 86 | return observableConnect; 87 | } 88 | }) 89 | .subscribe(new Action1() { 90 | @Override 91 | public void call(UsersData baseData) { 92 | users.clear(); 93 | users.addAll(baseData.data); 94 | } 95 | }, errorAction); 96 | } 97 | 98 | private void initView() { 99 | binding.fabSign.setVisibility(View.VISIBLE); 100 | user = getArguments().getParcelable(KEY_USER); 101 | if (user == null) { 102 | return; 103 | } 104 | binding.fabSign.setImageResource(user.status == User.VALUE_STATUS_SIGN ? R.drawable.ic_sign : R.drawable.ic_unsign); 105 | } 106 | 107 | @Override 108 | protected Observable getUserApi(Api api) { 109 | return api.getSignedUser(); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /app/src/main/java/com/wecan/xhin/studio/fragment/UsersFragment.java: -------------------------------------------------------------------------------- 1 | package com.wecan.xhin.studio.fragment; 2 | 3 | import android.app.Activity; 4 | import android.content.Intent; 5 | import android.databinding.DataBindingUtil; 6 | import android.databinding.ObservableArrayList; 7 | import android.os.Bundle; 8 | import android.support.annotation.Nullable; 9 | import android.view.LayoutInflater; 10 | import android.view.View; 11 | import android.view.ViewGroup; 12 | import android.widget.Toast; 13 | 14 | import com.bumptech.glide.Glide; 15 | import com.jakewharton.rxbinding.support.v4.widget.RxSwipeRefreshLayout; 16 | import com.wecan.xhin.baselib.rx.RxNetworking; 17 | import com.wecan.xhin.studio.App; 18 | import com.wecan.xhin.studio.R; 19 | import com.wecan.xhin.studio.activity.UserDetailsActivity; 20 | import com.wecan.xhin.studio.adapter.UsersAdapter; 21 | import com.wecan.xhin.studio.api.Api; 22 | import com.wecan.xhin.studio.bean.common.User; 23 | import com.wecan.xhin.studio.bean.down.UsersData; 24 | import com.wecan.xhin.studio.databinding.FragmentUsersBinding; 25 | 26 | import rx.Observable; 27 | import rx.android.schedulers.AndroidSchedulers; 28 | import rx.functions.Action1; 29 | import rx.functions.Func0; 30 | import rx.functions.Func1; 31 | import rx.schedulers.Schedulers; 32 | 33 | /** 34 | * Created by xhinliang on 15-11-18. 35 | * xhinliang@gmail.com 36 | */ 37 | public abstract class UsersFragment extends RxBindingFragment 38 | implements UsersAdapter.Listener { 39 | 40 | protected ObservableArrayList users; 41 | protected Action1 errorAction; 42 | protected Observable observableConnect; 43 | protected Api api; 44 | 45 | @Override 46 | public void onAttach(Activity activity) { 47 | super.onAttach(activity); 48 | api = App.from(activity).createApi(Api.class); 49 | } 50 | 51 | @Nullable 52 | @Override 53 | public FragmentUsersBinding onCreateBinding(LayoutInflater inflater, 54 | @Nullable ViewGroup container, 55 | @Nullable Bundle savedInstanceState) { 56 | return DataBindingUtil.inflate(inflater, R.layout.fragment_users, container, false); 57 | } 58 | 59 | @Override 60 | public void onViewCreated(final View v, Bundle savedInstanceState) { 61 | super.onViewCreated(v, savedInstanceState); 62 | users = new ObservableArrayList<>(); 63 | binding.rvUsers.setAdapter(new UsersAdapter(getActivity(), users, this, Glide.with(getActivity()))); 64 | Observable.Transformer networkingIndicator = 65 | RxNetworking.bindRefreshing(binding.srlRefresh); 66 | 67 | errorAction = new Action1() { 68 | @Override 69 | public void call(Throwable throwable) { 70 | Toast.makeText(getActivity(), throwable.getMessage(), Toast.LENGTH_SHORT).show(); 71 | } 72 | }; 73 | 74 | observableConnect = Observable 75 | .defer(new Func0>() { 76 | @Override 77 | public Observable call() { 78 | return getUserApi(api); 79 | } 80 | }) 81 | .subscribeOn(Schedulers.io()) 82 | .observeOn(AndroidSchedulers.mainThread()) 83 | .compose(networkingIndicator); 84 | 85 | RxSwipeRefreshLayout.refreshes(binding.srlRefresh) 86 | .flatMap(new Func1>() { 87 | @Override 88 | public Observable call(Void aVoid) { 89 | return observableConnect; 90 | } 91 | }) 92 | .compose(this.bindToLifecycle()) 93 | .subscribe(new Action1() { 94 | @Override 95 | public void call(UsersData usersData) { 96 | users.clear(); 97 | users.addAll(usersData.data); 98 | } 99 | }); 100 | 101 | observableConnect.subscribe(new Action1() { 102 | @Override 103 | public void call(UsersData usersData) { 104 | users.clear(); 105 | users.addAll(usersData.data); 106 | } 107 | }); 108 | 109 | } 110 | 111 | protected abstract Observable getUserApi(Api api); 112 | 113 | @Override 114 | public void onUserItemClick(UsersAdapter.ViewHolder holder) { 115 | User user = users.get(holder.getAdapterPosition()); 116 | startActivity(new Intent(getActivity(), UserDetailsActivity.class).putExtra(UserDetailsActivity.KEY_USER, user)); 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /app/src/main/java/com/wecan/xhin/studio/net/OkHttpGlideModule.java: -------------------------------------------------------------------------------- 1 | package com.wecan.xhin.studio.net; 2 | 3 | import android.content.Context; 4 | 5 | import com.bumptech.glide.Glide; 6 | import com.bumptech.glide.GlideBuilder; 7 | import com.bumptech.glide.integration.okhttp.OkHttpUrlLoader; 8 | import com.bumptech.glide.load.model.GlideUrl; 9 | import com.bumptech.glide.module.GlideModule; 10 | import com.wecan.xhin.studio.App; 11 | 12 | import java.io.InputStream; 13 | 14 | public class OkHttpGlideModule implements GlideModule { 15 | 16 | @Override 17 | public void applyOptions(Context context, GlideBuilder builder) { 18 | } 19 | 20 | @Override 21 | public void registerComponents(Context context, Glide glide) { 22 | glide.register(GlideUrl.class, InputStream.class, 23 | new OkHttpUrlLoader.Factory(App.from(context).getHttpClient())); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/java/com/wecan/xhin/studio/reactivex/BindingRecyclerView.java: -------------------------------------------------------------------------------- 1 | 2 | package com.wecan.xhin.studio.reactivex; 3 | 4 | import android.content.Context; 5 | import android.databinding.DataBindingUtil; 6 | import android.databinding.ObservableList; 7 | import android.databinding.ViewDataBinding; 8 | import android.support.annotation.LayoutRes; 9 | import android.support.v7.widget.RecyclerView; 10 | import android.view.LayoutInflater; 11 | import android.view.ViewGroup; 12 | 13 | import java.util.concurrent.atomic.AtomicInteger; 14 | 15 | public class BindingRecyclerView { 16 | 17 | public static abstract class ListAdapter extends RecyclerView.Adapter { 18 | 19 | protected final LayoutInflater inflater; 20 | protected final ObservableList data; 21 | 22 | private final AtomicInteger refs = new AtomicInteger(); 23 | 24 | private final ObservableList.OnListChangedCallback> callback = 25 | new ObservableList.OnListChangedCallback>() { 26 | @Override 27 | public void onChanged(ObservableList sender) { 28 | notifyDataSetChanged(); 29 | } 30 | 31 | @Override 32 | public void onItemRangeChanged(ObservableList sender, 33 | int positionStart, int itemCount) { 34 | notifyItemRangeChanged(positionStart, itemCount); 35 | } 36 | 37 | @Override 38 | public void onItemRangeInserted(ObservableList sender, 39 | int positionStart, int itemCount) { 40 | notifyItemRangeInserted(positionStart, itemCount); 41 | } 42 | 43 | @Override 44 | public void onItemRangeMoved(ObservableList sender, 45 | int fromPosition, int toPosition, int itemCount) { 46 | for (int i = 0; i < itemCount; i++) { 47 | notifyItemMoved(fromPosition + i, toPosition + i); 48 | } 49 | } 50 | 51 | @Override 52 | public void onItemRangeRemoved(ObservableList sender, 53 | int positionStart, int itemCount) { 54 | notifyItemRangeRemoved(positionStart, itemCount); 55 | } 56 | }; 57 | 58 | public ListAdapter(Context context, ObservableList data) { 59 | this.inflater = LayoutInflater.from(context); 60 | this.data = data; 61 | } 62 | 63 | @Override 64 | public int getItemCount() { 65 | return data.size(); 66 | } 67 | 68 | @Override 69 | public void onAttachedToRecyclerView(RecyclerView recyclerView) { 70 | if (refs.getAndIncrement() == 0) { 71 | data.addOnListChangedCallback(callback); 72 | } 73 | } 74 | 75 | @Override 76 | public void onDetachedFromRecyclerView(RecyclerView recyclerView) { 77 | if (refs.decrementAndGet() == 0) { 78 | data.removeOnListChangedCallback(callback); 79 | } 80 | } 81 | 82 | } 83 | 84 | public static class ViewHolder extends RecyclerView.ViewHolder { 85 | 86 | public final V binding; 87 | 88 | public ViewHolder(LayoutInflater inflater, @LayoutRes int layoutId, ViewGroup parent) { 89 | this(DataBindingUtil.inflate(inflater, layoutId, parent, false)); 90 | } 91 | 92 | public ViewHolder(V binding) { 93 | super(binding.getRoot()); 94 | this.binding = binding; 95 | } 96 | 97 | } 98 | 99 | } 100 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/defimgs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XhinLiang/Studio/656a82dde75ae8bb6d477d3e976cd2211e3cbfc6/app/src/main/res/drawable-hdpi/defimgs.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/header.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XhinLiang/Studio/656a82dde75ae8bb6d477d3e976cd2211e3cbfc6/app/src/main/res/drawable-hdpi/header.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/umeng_update_btn_check_off_focused_holo_light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XhinLiang/Studio/656a82dde75ae8bb6d477d3e976cd2211e3cbfc6/app/src/main/res/drawable-hdpi/umeng_update_btn_check_off_focused_holo_light.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/umeng_update_btn_check_off_holo_light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XhinLiang/Studio/656a82dde75ae8bb6d477d3e976cd2211e3cbfc6/app/src/main/res/drawable-hdpi/umeng_update_btn_check_off_holo_light.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/umeng_update_btn_check_off_pressed_holo_light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XhinLiang/Studio/656a82dde75ae8bb6d477d3e976cd2211e3cbfc6/app/src/main/res/drawable-hdpi/umeng_update_btn_check_off_pressed_holo_light.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/umeng_update_btn_check_on_focused_holo_light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XhinLiang/Studio/656a82dde75ae8bb6d477d3e976cd2211e3cbfc6/app/src/main/res/drawable-hdpi/umeng_update_btn_check_on_focused_holo_light.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/umeng_update_btn_check_on_holo_light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XhinLiang/Studio/656a82dde75ae8bb6d477d3e976cd2211e3cbfc6/app/src/main/res/drawable-hdpi/umeng_update_btn_check_on_holo_light.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/umeng_update_btn_check_on_pressed_holo_light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XhinLiang/Studio/656a82dde75ae8bb6d477d3e976cd2211e3cbfc6/app/src/main/res/drawable-hdpi/umeng_update_btn_check_on_pressed_holo_light.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/umeng_update_close_bg_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XhinLiang/Studio/656a82dde75ae8bb6d477d3e976cd2211e3cbfc6/app/src/main/res/drawable-hdpi/umeng_update_close_bg_normal.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/umeng_update_close_bg_tap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XhinLiang/Studio/656a82dde75ae8bb6d477d3e976cd2211e3cbfc6/app/src/main/res/drawable-hdpi/umeng_update_close_bg_tap.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_sign.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XhinLiang/Studio/656a82dde75ae8bb6d477d3e976cd2211e3cbfc6/app/src/main/res/drawable-xxxhdpi/ic_sign.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_unsign.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XhinLiang/Studio/656a82dde75ae8bb6d477d3e976cd2211e3cbfc6/app/src/main/res/drawable-xxxhdpi/ic_unsign.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_material_button_lite_blue.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_menu_camera.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_menu_gallery.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_menu_manage.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_menu_send.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_menu_share.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_menu_slideshow.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/tb_munion_icon.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 8 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/tb_munion_item_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/umeng_common_gradient_green.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/umeng_common_gradient_orange.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/umeng_common_gradient_red.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/umeng_update_button_cancel_bg_focused.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/umeng_update_button_cancel_bg_normal.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/umeng_update_button_cancel_bg_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 9 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/umeng_update_button_cancel_bg_tap.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/umeng_update_button_check_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 9 | 10 | 13 | 16 | 17 | 20 | 23 | 24 | 27 | 30 | 31 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/umeng_update_button_close_bg_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 9 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/umeng_update_button_ok_bg_focused.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/umeng_update_button_ok_bg_normal.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/umeng_update_button_ok_bg_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 8 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/umeng_update_button_ok_bg_tap.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/umeng_update_dialog_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/umeng_update_title_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 9 | 10 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/umeng_update_wifi_disable.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XhinLiang/Studio/656a82dde75ae8bb6d477d3e976cd2211e3cbfc6/app/src/main/res/drawable/umeng_update_wifi_disable.png -------------------------------------------------------------------------------- /app/src/main/res/layout-v9/umeng_common_download_notification.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 14 | 15 | 20 | 21 | 28 | 29 | 30 | 37 | 38 | 50 | 51 |