├── .gitignore ├── README.md ├── app ├── .gitignore ├── KeyStore │ └── release.jks ├── build.gradle ├── objectbox-models │ ├── default.json │ └── default.json.bak ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── lai │ │ └── mtc │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── assets │ │ ├── data.json │ │ └── jump_loader.json │ ├── java │ │ └── com │ │ │ └── lai │ │ │ └── mtc │ │ │ ├── MTC.java │ │ │ ├── MainActivity.java │ │ │ ├── TestMainActivity.java │ │ │ ├── api │ │ │ └── ComicApi.java │ │ │ ├── bean │ │ │ ├── ComicCategories.java │ │ │ ├── ComicListDetail.java │ │ │ ├── ComicListInfo.java │ │ │ ├── ComicPreView.java │ │ │ └── ComicTypeInfo.java │ │ │ ├── comm │ │ │ ├── ApiException.java │ │ │ ├── CommonAdapter.java │ │ │ ├── ExceptionEngine.java │ │ │ ├── HttpRxObserver.java │ │ │ ├── ImageAutoLoadScrollListener.java │ │ │ ├── OnItemTouchListener.java │ │ │ ├── Parameter.java │ │ │ ├── SpaceItemDecoration.java │ │ │ ├── dialog │ │ │ │ ├── CommDialog.java │ │ │ │ └── LoadingDialog.java │ │ │ └── widget │ │ │ │ ├── BookView.java │ │ │ │ ├── BookViewLayout.java │ │ │ │ ├── InterceptAppBarLayout.java │ │ │ │ ├── InterceptCoordinatorLayout.java │ │ │ │ ├── MotionEventRecyclerView.java │ │ │ │ ├── PreCacheLayoutManager.java │ │ │ │ └── TouchRecyclerView.java │ │ │ ├── dao │ │ │ ├── BaseDao.java │ │ │ ├── CollectionDao.java │ │ │ ├── RecordDao.java │ │ │ ├── SearchRecordDao.java │ │ │ └── bean │ │ │ │ ├── Group.java │ │ │ │ ├── MyCollection.java │ │ │ │ ├── Record.java │ │ │ │ └── SearchRecord.java │ │ │ ├── di │ │ │ ├── component │ │ │ │ └── AppComponent.java │ │ │ └── module │ │ │ │ ├── ApiModule.java │ │ │ │ ├── AppModule.java │ │ │ │ ├── BuildersModule.java │ │ │ │ ├── DaoModule.java │ │ │ │ └── NetModule.java │ │ │ └── mvp │ │ │ ├── base │ │ │ ├── IModel.java │ │ │ ├── IPresenter.java │ │ │ ├── IView.java │ │ │ └── impl │ │ │ │ ├── BaseActivity.java │ │ │ │ ├── BaseFragment.java │ │ │ │ ├── BaseModel.java │ │ │ │ ├── BaseMvpActivity.java │ │ │ │ ├── BaseMvpFragment.java │ │ │ │ └── BasePresenter.java │ │ │ ├── contract │ │ │ ├── ComicsContract.java │ │ │ ├── ComicsListDetailContract.java │ │ │ ├── ComicsPreviewContract.java │ │ │ ├── ComicsSearchContract.java │ │ │ └── SimpleContract.java │ │ │ ├── http │ │ │ ├── JsonTest.java │ │ │ └── RetrofitHelper.java │ │ │ ├── presenter │ │ │ ├── ComicsListDetailPresenter.java │ │ │ ├── ComicsPresenter.java │ │ │ ├── ComicsPreviewPresenter.java │ │ │ ├── ComicsSearchPresenter.java │ │ │ └── SimplePresenter.java │ │ │ ├── scope │ │ │ ├── ActivityScope.java │ │ │ └── FragmentScope.java │ │ │ ├── ui │ │ │ ├── cartoon │ │ │ │ └── fragment │ │ │ │ │ └── CartoonMainFragment.java │ │ │ └── comics │ │ │ │ ├── activity │ │ │ │ ├── ComicListDetailActivity.java │ │ │ │ ├── ComicPreviewActivity.java │ │ │ │ └── ComicSearchActivity.java │ │ │ │ ├── adapter │ │ │ │ ├── ChapterAdapter.java │ │ │ │ ├── ChapterDetailAdapter.java │ │ │ │ ├── MultiNumberAdapter.java │ │ │ │ └── PreviewAdapter.java │ │ │ │ ├── dialog │ │ │ │ ├── ModuleDialog.java │ │ │ │ └── SearchDialog.java │ │ │ │ ├── fragment │ │ │ │ └── ComicsMainFragment.java │ │ │ │ └── pop │ │ │ │ └── WindowLightPop.java │ │ │ └── utlis │ │ │ ├── ActivityUtils.java │ │ │ ├── CommonUtil.java │ │ │ ├── DensityUtil.java │ │ │ ├── FragmentUtils.java │ │ │ ├── IPopMenu.java │ │ │ ├── KeyBoardUtils.java │ │ │ ├── ListUtils.java │ │ │ ├── PopupMenuUtil.java │ │ │ ├── Preconditions.java │ │ │ ├── RxUtlis.java │ │ │ ├── SPUtils.java │ │ │ ├── ScreenUtils.java │ │ │ ├── StringUtils.java │ │ │ ├── ViewUtils.java │ │ │ ├── glide │ │ │ ├── GlideCacheUtil.java │ │ │ ├── ImageUtils.java │ │ │ ├── MyAppGlideModule.java │ │ │ ├── RoundCornersTransformation.java │ │ │ └── UnsafeOkHttpClient.java │ │ │ └── share │ │ │ ├── ShareElementInfo.java │ │ │ └── ShareElementUtils.java │ └── res │ │ ├── drawable-hdpi │ │ ├── ic_action_back.png │ │ ├── ic_action_clean.png │ │ ├── ic_brightness.png │ │ ├── ic_change.png │ │ ├── ic_label_outline_black_24dp.png │ │ ├── ic_menu.png │ │ ├── ic_module.png │ │ ├── ic_search.png │ │ └── ic_sort.png │ │ ├── drawable-mdpi │ │ ├── ic_action_back.png │ │ ├── ic_action_clean.png │ │ ├── ic_brightness.png │ │ ├── ic_change.png │ │ ├── ic_label_outline_black_24dp.png │ │ ├── ic_menu.png │ │ ├── ic_module.png │ │ ├── ic_search.png │ │ └── ic_sort.png │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable-xhdpi │ │ ├── ic_action_back.png │ │ ├── ic_action_clean.png │ │ ├── ic_brightness.png │ │ ├── ic_change.png │ │ ├── ic_dashboard_black_24dp.png │ │ ├── ic_label_outline_black_24dp.png │ │ ├── ic_line_weight_black_24dp.png │ │ ├── ic_menu.png │ │ ├── ic_module.png │ │ ├── ic_round.png │ │ ├── ic_search.png │ │ ├── ic_sort.png │ │ └── img_cover_default.9.png │ │ ├── drawable-xxhdpi │ │ ├── bg_shadow2.png │ │ ├── ic_action_back.png │ │ ├── ic_action_clean.png │ │ ├── ic_brightness.png │ │ ├── ic_change.png │ │ ├── ic_dashboard_black_24dp.png │ │ ├── ic_label_outline_black_24dp.png │ │ ├── ic_line_weight_black_24dp.png │ │ ├── ic_menu.png │ │ ├── ic_module.png │ │ ├── ic_search.png │ │ ├── ic_sort.png │ │ └── img_shelf_other.png │ │ ├── drawable-xxxhdpi │ │ ├── ic_label_outline_black_24dp.png │ │ └── ic_label_outline_white_24dp.png │ │ ├── drawable │ │ ├── bg_item_1.xml │ │ ├── ic_launcher_background.xml │ │ ├── seek_thumb.xml │ │ ├── seekbar_progress_drawable.xml │ │ └── shape_pop_checkaddshelf_bg.xml │ │ ├── layout │ │ ├── activity_main.xml │ │ ├── base_title.xml │ │ ├── book_layout_item.xml │ │ ├── comic_activity_list_detail.xml │ │ ├── comic_activity_preview.xml │ │ ├── comic_activity_preview_bottom_menu.xml │ │ ├── comic_activity_preview_left_menu.xml │ │ ├── comic_activity_search.xml │ │ ├── comic_dialog_search.xml │ │ ├── comic_item_bottom.xml │ │ ├── comic_item_bottom2.xml │ │ ├── comic_item_detail_list.xml │ │ ├── comic_item_list.xml │ │ ├── comic_item_list2.xml │ │ ├── comic_item_main_list.xml │ │ ├── comic_item_preview.xml │ │ ├── comic_item_preview2.xml │ │ ├── comic_item_preview_left.xml │ │ ├── comic_item_search_list.xml │ │ ├── comm_loading.xml │ │ ├── comm_loadmore.xml │ │ ├── comm_recyclerview.xml │ │ ├── fragment_comics.xml │ │ ├── include_title.xml │ │ ├── include_title_search.xml │ │ ├── menu_title.xml │ │ ├── menu_title_like.xml │ │ ├── pop_module.xml │ │ ├── pop_windowlight.xml │ │ ├── test.xml │ │ └── test_activity.xml │ │ ├── menu │ │ ├── action_changes.xml │ │ ├── action_like_source.xml │ │ └── action_search.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_author.png │ │ ├── ic_lable.png │ │ ├── ic_launcher.png │ │ ├── ic_launcher_round.png │ │ ├── ic_tag.png │ │ └── ic_user.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_round.png │ │ └── ic_place_holder.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ └── values │ │ ├── attrs.xml │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── lai │ └── mtc │ └── ExampleUnitTest.java ├── build.gradle ├── config.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── screenshot ├── Collection.png ├── des.png ├── des2.png ├── find.png ├── find2.png ├── home.png ├── home2.png ├── list.png └── search.png └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | .externalNativeBuild 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |

Comic-MTC

4 |

5 | 版本:v1.2.0 | 大小:4.1 M | 2018/6/28 6 |
7 | 点击下载体验 8 | 9 |
10 | 11 | ## 注意 12 | 13 | 接口的服务器已挂!!!!!!!!!,不过里面的代码倒是可以借鉴一下,注释完整。首页的列表做法不需要看,这种嵌套做法不好 14 |
15 | 16 | 如果想学MVVM可以看最新的漫画项目 ComicMTC_V2: Kotlin+MVVM+LiveData+协程+Retrofit 17 | 欢迎start 😜 18 | 19 | 20 | ## 简介 21 |  在线漫画阅读器,项目采用 MVP + RxJava + Retrofit + Dagger2+rxlifecycle .功能上现在只是简单的基本功能。 22 | 23 | 后期会优化更新加上,以及详细的注释会更新上 24 | 点我查看更新日志 25 | 26 |  如有更好的做法或意见欢迎 提交Issues 27 | 28 | 如果对你有帮助不妨start支持一下.感谢ヽ( ̄ω ̄( ̄ω ̄〃)ゝ 29 | 30 | ## 相关文章 31 | - 强力推荐!项目讲解 32 | - 常见的MVP与封装 提供DEMO 33 | - Dagger2搭建 34 | - recycleView 性能优化 35 | 36 | 37 | ## 应用截图 38 |

39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 |

47 | 48 |

49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 |

57 | 58 | ## 计划进度 59 | 上班太忙了,-v-.更新会慢!...一直没有更新感觉对不起这几位start的兄弟TVT,近期我抽点时间优化优化!!
60 | 61 | 62 | ![Progress](http://progressed.io/bar/80?title=代码注释 )
63 | ![Progress](http://progressed.io/bar/4?scale=4&title=更新文章&suffix=个)
64 | ![Progress](http://progressed.io/bar/20?title=后期优化 )
65 | ![Progress](http://progressed.io/bar/0?title=接入动漫视频模块)
66 | ![Progress](http://progressed.io/bar/0?title=自定义首页标签 )
67 | ![Progress](http://progressed.io/bar/0?title=收藏夹分类 )
68 |
69 | 70 | 71 | ## 声明 72 |  本项目部分API来自酷克漫画,个人练手学习项目,此开源项目仅做学习交流使用, 不涉及任何商业用途,有如侵权,立即删除。 73 | 74 | License 75 | ======= 76 | 77 | Copyright 2018 LaiShuJie 78 | 79 | 80 | Licensed under the Apache License, Version 2.0 (the "License"); 81 | you may not use this file except in compliance with the License. 82 | You may obtain a copy of the License at 83 | 84 | http://www.apache.org/licenses/LICENSE-2.0 85 | 86 | Unless required by applicable law or agreed to in writing, software 87 | distributed under the License is distributed on an "AS IS" BASIS, 88 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 89 | See the License for the specific language governing permissions and 90 | limitations under the License. 91 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/KeyStore/release.jks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laishujie/Comic-MTC/91eb78a262971506fdf2cd819550c56cef24350a/app/KeyStore/release.jks -------------------------------------------------------------------------------- /app/objectbox-models/default.json: -------------------------------------------------------------------------------- 1 | { 2 | "_note1": "KEEP THIS FILE! Check it into a version control system (VCS) like git.", 3 | "_note2": "ObjectBox manages crucial IDs for your object model. See docs for details.", 4 | "_note3": "If you have VCS merge conflicts, you must resolve them according to ObjectBox docs.", 5 | "entities": [ 6 | { 7 | "id": "1:8699208959836505960", 8 | "lastPropertyId": "7:3513099458287364368", 9 | "name": "MyCollection", 10 | "properties": [ 11 | { 12 | "id": "1:3232490684014233646", 13 | "name": "id" 14 | }, 15 | { 16 | "id": "2:4366486312038453007", 17 | "name": "desc" 18 | }, 19 | { 20 | "id": "3:1103162751011811333", 21 | "name": "cover" 22 | }, 23 | { 24 | "id": "4:3373144502925877325", 25 | "name": "time" 26 | }, 27 | { 28 | "id": "5:3948644640204751108", 29 | "name": "name" 30 | }, 31 | { 32 | "id": "6:1459824881156873142", 33 | "name": "status" 34 | }, 35 | { 36 | "id": "7:3513099458287364368", 37 | "name": "author" 38 | } 39 | ], 40 | "relations": [] 41 | }, 42 | { 43 | "id": "2:8552152959484337979", 44 | "lastPropertyId": "1:7488042863955490049", 45 | "name": "Group", 46 | "properties": [ 47 | { 48 | "id": "1:7488042863955490049", 49 | "name": "id" 50 | } 51 | ], 52 | "relations": [ 53 | { 54 | "id": "1:4616418119470173040", 55 | "name": "myCollections" 56 | } 57 | ] 58 | }, 59 | { 60 | "id": "3:4595820373387229180", 61 | "lastPropertyId": "5:3331453447220174531", 62 | "name": "Record", 63 | "properties": [ 64 | { 65 | "id": "1:7035471328799773174", 66 | "name": "id" 67 | }, 68 | { 69 | "id": "3:8065163283146521735", 70 | "name": "index" 71 | }, 72 | { 73 | "id": "4:7106674055854488768", 74 | "name": "name" 75 | }, 76 | { 77 | "id": "5:3331453447220174531", 78 | "name": "position" 79 | } 80 | ], 81 | "relations": [] 82 | }, 83 | { 84 | "id": "4:2505861390255239478", 85 | "lastPropertyId": "2:963871367083939489", 86 | "name": "SearchRecord", 87 | "properties": [ 88 | { 89 | "id": "1:4053382632414738928", 90 | "name": "id" 91 | }, 92 | { 93 | "id": "2:963871367083939489", 94 | "name": "inputName" 95 | } 96 | ], 97 | "relations": [] 98 | } 99 | ], 100 | "lastEntityId": "4:2505861390255239478", 101 | "lastIndexId": "0:0", 102 | "lastRelationId": "1:4616418119470173040", 103 | "lastSequenceId": "0:0", 104 | "modelVersion": 4, 105 | "modelVersionParserMinimum": 4, 106 | "retiredEntityUids": [], 107 | "retiredIndexUids": [], 108 | "retiredPropertyUids": [ 109 | 4922162759775071244 110 | ], 111 | "retiredRelationUids": [], 112 | "version": 1 113 | } -------------------------------------------------------------------------------- /app/objectbox-models/default.json.bak: -------------------------------------------------------------------------------- 1 | { 2 | "_note1": "KEEP THIS FILE! Check it into a version control system (VCS) like git.", 3 | "_note2": "ObjectBox manages crucial IDs for your object model. See docs for details.", 4 | "_note3": "If you have VCS merge conflicts, you must resolve them according to ObjectBox docs.", 5 | "entities": [ 6 | { 7 | "id": "1:8699208959836505960", 8 | "lastPropertyId": "7:3513099458287364368", 9 | "name": "MyCollection", 10 | "properties": [ 11 | { 12 | "id": "1:3232490684014233646", 13 | "name": "id" 14 | }, 15 | { 16 | "id": "2:4366486312038453007", 17 | "name": "desc" 18 | }, 19 | { 20 | "id": "3:1103162751011811333", 21 | "name": "cover" 22 | }, 23 | { 24 | "id": "4:3373144502925877325", 25 | "name": "time" 26 | }, 27 | { 28 | "id": "5:3948644640204751108", 29 | "name": "name" 30 | }, 31 | { 32 | "id": "6:1459824881156873142", 33 | "name": "status" 34 | }, 35 | { 36 | "id": "7:3513099458287364368", 37 | "name": "author" 38 | } 39 | ], 40 | "relations": [] 41 | }, 42 | { 43 | "id": "2:8552152959484337979", 44 | "lastPropertyId": "1:7488042863955490049", 45 | "name": "Group", 46 | "properties": [ 47 | { 48 | "id": "1:7488042863955490049", 49 | "name": "id" 50 | } 51 | ], 52 | "relations": [ 53 | { 54 | "id": "1:4616418119470173040", 55 | "name": "myCollections" 56 | } 57 | ] 58 | }, 59 | { 60 | "id": "3:4595820373387229180", 61 | "lastPropertyId": "5:3331453447220174531", 62 | "name": "Record", 63 | "properties": [ 64 | { 65 | "id": "1:7035471328799773174", 66 | "name": "id" 67 | }, 68 | { 69 | "id": "3:8065163283146521735", 70 | "name": "index" 71 | }, 72 | { 73 | "id": "4:7106674055854488768", 74 | "name": "name" 75 | }, 76 | { 77 | "id": "5:3331453447220174531", 78 | "name": "position" 79 | } 80 | ], 81 | "relations": [] 82 | }, 83 | { 84 | "id": "4:2505861390255239478", 85 | "lastPropertyId": "2:963871367083939489", 86 | "name": "SearchRecord", 87 | "properties": [ 88 | { 89 | "id": "1:4053382632414738928", 90 | "name": "id" 91 | }, 92 | { 93 | "id": "2:963871367083939489", 94 | "name": "inputName" 95 | } 96 | ], 97 | "relations": [] 98 | } 99 | ], 100 | "lastEntityId": "4:2505861390255239478", 101 | "lastIndexId": "0:0", 102 | "lastRelationId": "1:4616418119470173040", 103 | "lastSequenceId": "0:0", 104 | "modelVersion": 4, 105 | "modelVersionParserMinimum": 4, 106 | "retiredEntityUids": [], 107 | "retiredIndexUids": [], 108 | "retiredPropertyUids": [ 109 | 4922162759775071244 110 | ], 111 | "retiredRelationUids": [], 112 | "version": 1 113 | } -------------------------------------------------------------------------------- /app/src/androidTest/java/com/lai/mtc/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.lai.mtc; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumented test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() throws Exception { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.lai.mtc", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/java/com/lai/mtc/MTC.java: -------------------------------------------------------------------------------- 1 | package com.lai.mtc; 2 | 3 | import android.app.Activity; 4 | import android.app.Application; 5 | 6 | import com.lai.mtc.dao.bean.MyObjectBox; 7 | import com.lai.mtc.di.component.DaggerAppComponent; 8 | import com.lai.mtc.mvp.http.RetrofitHelper; 9 | 10 | import javax.inject.Inject; 11 | 12 | import dagger.android.AndroidInjector; 13 | import dagger.android.DispatchingAndroidInjector; 14 | import dagger.android.HasActivityInjector; 15 | import io.objectbox.BoxStore; 16 | 17 | /** 18 | * @author Lai 19 | * @time 2017/12/12 16:21 20 | * @describe describe 21 | */ 22 | 23 | public class MTC extends Application implements HasActivityInjector { 24 | 25 | public static MTC getApp() { 26 | return mMTC; 27 | } 28 | 29 | public static MTC mMTC; 30 | 31 | private static BoxStore boxStore; 32 | 33 | @Inject 34 | DispatchingAndroidInjector dispatchingActivityInjector; 35 | 36 | public static BoxStore getBoxStore() { 37 | return boxStore; 38 | } 39 | 40 | public static void setBoxStore(BoxStore boxStore) { 41 | MTC.boxStore = boxStore; 42 | } 43 | 44 | @Override 45 | public void onCreate() { 46 | super.onCreate(); 47 | mMTC = this; 48 | setBoxStore(MyObjectBox.builder().androidContext(this).build()); 49 | DaggerAppComponent.builder().application(this).baseUrl(RetrofitHelper.BASE_URL).build().inject(this); 50 | } 51 | 52 | 53 | @Override 54 | public AndroidInjector activityInjector() { 55 | return dispatchingActivityInjector; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /app/src/main/java/com/lai/mtc/TestMainActivity.java: -------------------------------------------------------------------------------- 1 | package com.lai.mtc; 2 | 3 | import android.os.Bundle; 4 | import android.util.Log; 5 | import android.view.View; 6 | import android.widget.ImageView; 7 | 8 | import com.lai.mtc.bean.ComicListDetail; 9 | import com.lai.mtc.bean.ComicPreView; 10 | import com.lai.mtc.mvp.base.impl.BaseMvpActivity; 11 | import com.lai.mtc.mvp.contract.ComicsPreviewContract; 12 | import com.lai.mtc.mvp.presenter.ComicsPreviewPresenter; 13 | import com.lai.mtc.mvp.utlis.ScreenUtils; 14 | import com.lai.mtc.mvp.utlis.glide.GlideCacheUtil; 15 | import com.lai.mtc.mvp.utlis.glide.ImageUtils; 16 | 17 | import butterknife.BindView; 18 | 19 | public class TestMainActivity extends BaseMvpActivity implements ComicsPreviewContract.View{ 20 | 21 | @BindView(R.id.iv_cover) 22 | ImageView mImageView; 23 | String url = "http://images.720rs.com/manhuatuku/106/comicdata_ss_ss008081917_1219139525268_1219139531883.jpg"; 24 | @Override 25 | public void init(Bundle savedInstanceState) { 26 | 27 | findViewById(R.id.btn_1).setOnClickListener(new View.OnClickListener() { 28 | @Override 29 | public void onClick(View v) { 30 | int[] imageWidthHeight = ScreenUtils.getImageWidthHeight(url); 31 | Log.w("1111","ima"); 32 | //mPresenter.testList(TestMainActivity.this); 33 | } 34 | }); 35 | findViewById(R.id.btn_2).setOnClickListener(new View.OnClickListener() { 36 | @Override 37 | public void onClick(View v) { 38 | ImageUtils.loadByModule(TestMainActivity.this,url,mImageView,0); 39 | } 40 | }); 41 | 42 | findViewById(R.id.btn_3).setOnClickListener(new View.OnClickListener() { 43 | @Override 44 | public void onClick(View v) { 45 | GlideCacheUtil.getInstance().clearImageAllCache(TestMainActivity.this); 46 | } 47 | }); 48 | } 49 | 50 | @Override 51 | public int getLayoutResId(Bundle savedInstanceState) { 52 | return R.layout.test_activity; 53 | } 54 | 55 | @Override 56 | public View getTitleBar() { 57 | return null; 58 | } 59 | 60 | public void showPreview(ComicPreView comicPreView) { 61 | 62 | } 63 | 64 | 65 | public void showInfo(ComicListDetail comicListDetail) { 66 | 67 | } 68 | 69 | @Override 70 | public void showPreview(ComicPreView comicPreView, boolean isRefresh) { 71 | 72 | } 73 | 74 | //@Inject 75 | // Retrofit mComicApi; 76 | 77 | 78 | 79 | } 80 | -------------------------------------------------------------------------------- /app/src/main/java/com/lai/mtc/api/ComicApi.java: -------------------------------------------------------------------------------- 1 | package com.lai.mtc.api; 2 | 3 | 4 | import com.lai.mtc.bean.ComicCategories; 5 | import com.lai.mtc.bean.ComicListDetail; 6 | import com.lai.mtc.bean.ComicListInfo; 7 | import com.lai.mtc.bean.ComicPreView; 8 | 9 | import java.util.List; 10 | 11 | import io.reactivex.Observable; 12 | import retrofit2.Response; 13 | import retrofit2.http.GET; 14 | import retrofit2.http.Path; 15 | import retrofit2.http.Query; 16 | 17 | /** 18 | * @author Lai 19 | * @time 2017/9/5 11:55 20 | * @describe 动漫API管理类 21 | */ 22 | 23 | public interface ComicApi { 24 | 25 | /** 26 | * 根据传入的类型来获取数据 27 | * 28 | * @param area 29 | * @return 30 | */ 31 | @GET("/comics?page=1") 32 | Observable getTypeComics(@Query("q[area_eq]") String area); 33 | //http://api.cookacg.com/comics?q%5Btags_id_eq%5D=2&page=1&package_name=com.vjson.anime&version_code=77&version_name=1.0.7.7&channel=coolapk&sign=dcf692dc1d4cead44ce1d5d1b9409e26&platform=android 34 | 35 | @GET("/comics") 36 | Observable> getTypeComicsById(@Query("q[tags_id_eq]") int id, @Query("page") int page); 37 | 38 | @GET("/comics") 39 | Observable> getTypeComicsByResponseId(@Query("q[tags_id_eq]") int id, @Query("page") int page, @Query("name") String name); 40 | 41 | @GET("/comics/categories") 42 | Observable> getComicCategories(); 43 | 44 | @GET("/comics") 45 | Observable> getAllComic(@Query("page") int page); 46 | 47 | @GET("/comics/{id}") 48 | Observable getComicById(@Path("id") int id); 49 | 50 | @GET("/comics/{id}/{index}") 51 | Observable getComicPreViewById(@Path("id") int id, @Path("index") int index); 52 | 53 | @GET("/comics") 54 | Observable getComicsByName(@Query("q[name_cont]") String name, @Query("page") int page); 55 | 56 | } 57 | -------------------------------------------------------------------------------- /app/src/main/java/com/lai/mtc/bean/ComicCategories.java: -------------------------------------------------------------------------------- 1 | package com.lai.mtc.bean; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * @author Lai 7 | * @time 2017/12/1 15:51 8 | * @describe describe 9 | */ 10 | 11 | public class ComicCategories implements Serializable { 12 | 13 | /** 14 | * name : 热血 15 | * cover : http://img.1whour.com/xpic/hy47.jpg 16 | * track_url : http://comic.kukudm.com/comiclist/3/index.htm 17 | * query : /comics?q%5Btags_id_eq%5D=2 18 | */ 19 | private int id; 20 | 21 | public ComicCategories() { 22 | 23 | } 24 | 25 | public ComicCategories(int id, String name) { 26 | this.id = id; 27 | this.name = name; 28 | } 29 | 30 | public int getId() { 31 | return id; 32 | } 33 | 34 | public void setId(int id) { 35 | this.id = id; 36 | } 37 | 38 | private String name; 39 | private String cover; 40 | private String track_url; 41 | private String query; 42 | 43 | public String getName() { 44 | return name; 45 | } 46 | 47 | public void setName(String name) { 48 | this.name = name; 49 | } 50 | 51 | public String getCover() { 52 | return cover; 53 | } 54 | 55 | public void setCover(String cover) { 56 | this.cover = cover; 57 | } 58 | 59 | public String getTrack_url() { 60 | return track_url; 61 | } 62 | 63 | public void setTrack_url(String track_url) { 64 | this.track_url = track_url; 65 | } 66 | 67 | public String getQuery() { 68 | return query; 69 | } 70 | 71 | public void setQuery(String query) { 72 | this.query = query; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /app/src/main/java/com/lai/mtc/bean/ComicTypeInfo.java: -------------------------------------------------------------------------------- 1 | package com.lai.mtc.bean; 2 | 3 | import com.chad.library.adapter.base.entity.MultiItemEntity; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | /** 9 | * @author Lai 10 | * @time 2017/10/5 16:16 11 | * @describe describe 12 | */ 13 | public class ComicTypeInfo implements MultiItemEntity { 14 | //Top type 15 | public static final int Head = 1; 16 | //list type 17 | public static final int List = 0; 18 | //current type 19 | public int currType; 20 | //Title 21 | private String title; 22 | 23 | public String getTitle() { 24 | return title; 25 | } 26 | 27 | public void setTitle(String title) { 28 | this.title = title; 29 | } 30 | 31 | public ComicTypeInfo(int currType, String title) { 32 | this.currType = currType; 33 | this.title = title; 34 | } 35 | 36 | public ComicTypeInfo(String title) { 37 | this.title = title; 38 | } 39 | 40 | public static List getmComicListInfos() { 41 | return mComicListInfos; 42 | } 43 | public static List getmComicListInfos2() { 44 | return mComicListInfos2; 45 | } 46 | public static void setmComicListInfos(List mComicListInfos) { 47 | ComicTypeInfo.mComicListInfos = mComicListInfos; 48 | } 49 | 50 | private static List mComicListInfos; 51 | private static List mComicListInfos2; 52 | 53 | static { 54 | if (mComicListInfos == null) { 55 | mComicListInfos = new ArrayList<>(); 56 | mComicListInfos2 = new ArrayList<>(); 57 | mComicListInfos.add(new ComicTypeInfo(Head, "今日推荐|Chinese Comics")); 58 | mComicListInfos.add(new ComicTypeInfo("随机推荐|Chinese Comics")); 59 | mComicListInfos2.addAll(mComicListInfos); 60 | mComicListInfos2.addAll(mComicListInfos); 61 | mComicListInfos2.addAll(mComicListInfos); 62 | } 63 | } 64 | 65 | 66 | @Override 67 | public int getItemType() { 68 | return currType; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /app/src/main/java/com/lai/mtc/comm/ApiException.java: -------------------------------------------------------------------------------- 1 | package com.lai.mtc.comm; 2 | 3 | /** 4 | * @author Lai 5 | * @time 2017/9/19 11:10 6 | * @describe describe 7 | */ 8 | 9 | public class ApiException extends Exception { 10 | private int code;//错误码 11 | private String msg;//错误信息 12 | 13 | public ApiException(Throwable throwable, int code) { 14 | super(throwable); 15 | this.code = code; 16 | } 17 | 18 | public ApiException(int code, String msg) { 19 | this.code = code; 20 | this.msg = msg; 21 | } 22 | 23 | public int getCode() { 24 | return code; 25 | } 26 | 27 | public void setCode(int code) { 28 | this.code = code; 29 | } 30 | 31 | public String getMsg() { 32 | return msg; 33 | } 34 | 35 | public void setMsg(String msg) { 36 | this.msg = msg; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /app/src/main/java/com/lai/mtc/comm/CommonAdapter.java: -------------------------------------------------------------------------------- 1 | package com.lai.mtc.comm; 2 | 3 | import android.support.annotation.LayoutRes; 4 | import android.support.annotation.Nullable; 5 | 6 | import com.chad.library.adapter.base.BaseQuickAdapter; 7 | import com.chad.library.adapter.base.BaseViewHolder; 8 | 9 | import java.util.List; 10 | 11 | 12 | public abstract class CommonAdapter extends BaseQuickAdapter { 13 | 14 | public CommonAdapter(@LayoutRes int layoutResId, @Nullable List data) { 15 | super(layoutResId, data); 16 | } 17 | 18 | public CommonAdapter(@Nullable List data) { 19 | super(data); 20 | } 21 | 22 | public CommonAdapter(@LayoutRes int layoutResId) { 23 | super(layoutResId); 24 | } 25 | 26 | @Override 27 | protected void convert(BaseViewHolder baseViewHolder, T t) { 28 | convert(baseViewHolder, t, baseViewHolder.getLayoutPosition()); 29 | } 30 | 31 | /***为了方便使用,将当前item的position返回*/ 32 | protected abstract void convert(BaseViewHolder baseViewHolder, T t, int position); 33 | 34 | /***判断是否是刷新,添加数据*/ 35 | public void setData(boolean isRefresh, List data) { 36 | if (isRefresh) { 37 | setNewData(data); 38 | } else { 39 | addData(data); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /app/src/main/java/com/lai/mtc/comm/ExceptionEngine.java: -------------------------------------------------------------------------------- 1 | package com.lai.mtc.comm; 2 | 3 | import android.net.ParseException; 4 | 5 | import com.google.gson.JsonParseException; 6 | import com.google.gson.stream.MalformedJsonException; 7 | 8 | import org.json.JSONException; 9 | 10 | import java.net.ConnectException; 11 | import java.net.SocketTimeoutException; 12 | import java.net.UnknownHostException; 13 | 14 | import retrofit2.HttpException; 15 | 16 | 17 | /** 18 | * @author Lai 19 | * @time 2017/9/19 11:11 20 | * @describe describe 21 | */ 22 | 23 | public class ExceptionEngine { 24 | public static final int UN_KNOWN_ERROR = 1000;//未知错误 25 | public static final int ANALYTIC_SERVER_DATA_ERROR = 1001;//解析(服务器)数据错误 26 | public static final int ANALYTIC_CLIENT_DATA_ERROR = 1002;//解析(客户端)数据错误 27 | public static final int CONNECT_ERROR = 1003;//网络连接错误 28 | public static final int TIME_OUT_ERROR = 1004;//网络连接超时 29 | 30 | public static ApiException handleException(Throwable e) { 31 | ApiException ex; 32 | if (e instanceof HttpException) { //HTTP错误 33 | HttpException httpExc = (HttpException) e; 34 | ex = new ApiException(e, httpExc.code()); 35 | ex.setMsg("网络错误"); //均视为网络错误 36 | return ex; 37 | } else if (e instanceof JsonParseException 38 | || e instanceof JSONException 39 | || e instanceof ParseException || e instanceof MalformedJsonException) { //解析数据错误 40 | ex = new ApiException(e, ANALYTIC_SERVER_DATA_ERROR); 41 | ex.setMsg("解析错误"); 42 | return ex; 43 | } else if (e instanceof ConnectException || e instanceof UnknownHostException) {//连接网络错误 44 | ex = new ApiException(e, CONNECT_ERROR); 45 | ex.setMsg("连接失败"); 46 | return ex; 47 | } else if (e instanceof SocketTimeoutException) {//网络超时 48 | ex = new ApiException(e, TIME_OUT_ERROR); 49 | ex.setMsg("网络超时"); 50 | return ex; 51 | } else { //未知错误 52 | ex = new ApiException(e, UN_KNOWN_ERROR); 53 | ex.setMsg("未知错误"); 54 | return ex; 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /app/src/main/java/com/lai/mtc/comm/HttpRxObserver.java: -------------------------------------------------------------------------------- 1 | package com.lai.mtc.comm; 2 | 3 | 4 | import io.reactivex.Observer; 5 | import io.reactivex.annotations.NonNull; 6 | import io.reactivex.disposables.Disposable; 7 | 8 | /** 9 | * @author Lai 10 | * @time 2017/9/19 11:23 11 | * @describe describe 12 | */ 13 | 14 | public class HttpRxObserver implements Observer { 15 | 16 | IResult mIResult; 17 | 18 | public HttpRxObserver(IResult IResult) { 19 | mIResult = IResult; 20 | } 21 | 22 | @Override 23 | public void onSubscribe(@NonNull Disposable d) { 24 | //mIResult.onStart(); 25 | } 26 | 27 | @Override 28 | public void onNext(@NonNull T t) { 29 | mIResult.onSuccess(t); 30 | } 31 | 32 | @Override 33 | public void onError(@NonNull Throwable e) { 34 | e.printStackTrace(); 35 | if (e instanceof ApiException) { 36 | mIResult.onError((ApiException) e); 37 | } else { 38 | mIResult.onError(new ApiException(e, ExceptionEngine.UN_KNOWN_ERROR)); 39 | } 40 | } 41 | 42 | @Override 43 | public void onComplete() { 44 | 45 | } 46 | 47 | public interface IResult { 48 | void onSuccess(T t); 49 | 50 | void onError(ApiException e); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /app/src/main/java/com/lai/mtc/comm/ImageAutoLoadScrollListener.java: -------------------------------------------------------------------------------- 1 | package com.lai.mtc.comm; 2 | 3 | import android.content.Context; 4 | import android.support.v7.widget.RecyclerView; 5 | 6 | import com.lai.mtc.mvp.utlis.glide.GlideApp; 7 | 8 | import static android.support.v7.widget.RecyclerView.SCROLL_STATE_DRAGGING; 9 | import static android.support.v7.widget.RecyclerView.SCROLL_STATE_IDLE; 10 | import static android.support.v7.widget.RecyclerView.SCROLL_STATE_SETTLING; 11 | 12 | /** 13 | * @author Lai 14 | * @time 2018/2/19 21:02 15 | * @describe 监听滚动来对图片加载进行判断处理 16 | */ 17 | public class ImageAutoLoadScrollListener extends RecyclerView.OnScrollListener { 18 | private Context mContext; 19 | 20 | public ImageAutoLoadScrollListener(Context mContext) { 21 | this.mContext = mContext; 22 | } 23 | 24 | @Override 25 | public void onScrolled(RecyclerView recyclerView, int dx, int dy) { 26 | super.onScrolled(recyclerView, dx, dy); 27 | } 28 | 29 | @Override 30 | public void onScrollStateChanged(RecyclerView recyclerView, int newState) { 31 | super.onScrollStateChanged(recyclerView, newState); 32 | switch (newState) { 33 | case SCROLL_STATE_IDLE: // The RecyclerView is not currently scrolling. 34 | //当屏幕停止滚动,加载图片 35 | try { 36 | if (mContext != null) GlideApp.with(mContext).resumeRequests(); 37 | } catch (Exception e) { 38 | e.printStackTrace(); 39 | } 40 | break; 41 | case SCROLL_STATE_DRAGGING: // The RecyclerView is currently being dragged by outside input such as user touch input. 42 | //当屏幕滚动且用户使用的触碰或手指还在屏幕上,停止加载图片 43 | try { 44 | if (mContext != null) GlideApp.with(mContext).pauseRequests(); 45 | } catch (Exception e) { 46 | e.printStackTrace(); 47 | } 48 | break; 49 | case SCROLL_STATE_SETTLING: // The RecyclerView is currently animating to a final position while not under outside control. 50 | //由于用户的操作,屏幕产生惯性滑动,停止加载图片 51 | try { 52 | if (mContext != null) GlideApp.with(mContext).pauseRequests(); 53 | } catch (Exception e) { 54 | e.printStackTrace(); 55 | } 56 | break; 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /app/src/main/java/com/lai/mtc/comm/OnItemTouchListener.java: -------------------------------------------------------------------------------- 1 | package com.lai.mtc.comm; 2 | 3 | import android.support.v4.view.GestureDetectorCompat; 4 | import android.support.v7.widget.RecyclerView; 5 | import android.view.GestureDetector; 6 | import android.view.MotionEvent; 7 | import android.view.View; 8 | 9 | /** 10 | * @author Lai 11 | * @time 2018/2/20 15:55 12 | * @describe describe 13 | */ 14 | public abstract class OnItemTouchListener implements RecyclerView.OnItemTouchListener { 15 | 16 | private GestureDetectorCompat mGestureDetectorCompat; 17 | private RecyclerView mRecyclerView; 18 | 19 | public OnItemTouchListener(RecyclerView recyclerView) { 20 | mRecyclerView = recyclerView; 21 | mGestureDetectorCompat = new GestureDetectorCompat(mRecyclerView.getContext(), new MyGestureListener()); 22 | } 23 | 24 | @Override 25 | public void onTouchEvent(RecyclerView rv, MotionEvent e) { 26 | mGestureDetectorCompat.onTouchEvent(e); 27 | } 28 | 29 | @Override 30 | public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) { 31 | mGestureDetectorCompat.onTouchEvent(e); 32 | return false; 33 | } 34 | 35 | @Override 36 | public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) { 37 | 38 | } 39 | 40 | private class MyGestureListener extends GestureDetector.SimpleOnGestureListener { 41 | @Override 42 | public boolean onSingleTapUp(MotionEvent e) { 43 | View childe = mRecyclerView.findChildViewUnder(e.getX(), e.getY()); 44 | if (childe != null) { 45 | RecyclerView.ViewHolder VH = mRecyclerView.getChildViewHolder(childe); 46 | onItemClick(VH, VH.getAdapterPosition(),e); 47 | } 48 | return true; 49 | } 50 | 51 | @Override 52 | public void onLongPress(MotionEvent e) { 53 | /* View childe = mOutRecyclerView.findChildViewUnder(e.getX(), e.getY()); 54 | if (childe != null) { 55 | RecyclerView.ViewHolder VH = mOutRecyclerView.getChildViewHolder(childe); 56 | }*/ 57 | } 58 | } 59 | 60 | public abstract void onItemClick(RecyclerView.ViewHolder vh, int position,MotionEvent e); 61 | 62 | } 63 | -------------------------------------------------------------------------------- /app/src/main/java/com/lai/mtc/comm/Parameter.java: -------------------------------------------------------------------------------- 1 | package com.lai.mtc.comm; 2 | 3 | //常见参数 4 | public class Parameter { 5 | 6 | //配置 7 | public static final String SP_CONFIG = "config"; 8 | //预览模式 9 | public static final String SP_PREVIEW_MODE = "module"; 10 | //集数分页标准 11 | public static final int PAGING_STANDARD = 52; 12 | //提前加载多少页 13 | public static final int MAX_PRELOAD = 4; 14 | } 15 | -------------------------------------------------------------------------------- /app/src/main/java/com/lai/mtc/comm/SpaceItemDecoration.java: -------------------------------------------------------------------------------- 1 | package com.lai.mtc.comm; 2 | 3 | import android.graphics.Rect; 4 | import android.support.v7.widget.RecyclerView; 5 | import android.view.View; 6 | 7 | /** 8 | * @author Lai 9 | * @time 2017/9/28 18:50 10 | * @describe GridlayoutManager 上下左右间距 11 | */ 12 | 13 | public class SpaceItemDecoration extends RecyclerView.ItemDecoration { 14 | private int spanCount; 15 | private int spacing; 16 | private boolean includeEdge; 17 | 18 | public SpaceItemDecoration(int spanCount, int spacing, boolean includeEdge) { 19 | this.spanCount = spanCount; 20 | this.spacing = spacing; 21 | this.includeEdge = includeEdge; 22 | } 23 | 24 | @Override 25 | public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { 26 | int position = parent.getChildAdapterPosition(view); // item position 27 | int column = position % spanCount; // item column 28 | 29 | if (includeEdge) { 30 | outRect.left = spacing - column * spacing / spanCount; // spacing - column * ((1f / spanCount) * spacing) 31 | outRect.right = (column + 1) * spacing / spanCount; // (column + 1) * ((1f / spanCount) * spacing) 32 | 33 | if (position < spanCount) { // top edge 34 | outRect.top = spacing; 35 | } 36 | outRect.bottom = spacing; // item bottom 37 | } else { 38 | outRect.left = column * spacing / spanCount; // column * ((1f / spanCount) * spacing) 39 | outRect.right = spacing - (column + 1) * spacing / spanCount; // spacing - (column + 1) * ((1f / spanCount) * spacing) 40 | if (position >= spanCount) { 41 | outRect.top = spacing; // item top 42 | } 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /app/src/main/java/com/lai/mtc/comm/dialog/CommDialog.java: -------------------------------------------------------------------------------- 1 | package com.lai.mtc.comm.dialog; 2 | 3 | import android.app.Dialog; 4 | import android.content.Context; 5 | import android.os.Bundle; 6 | import android.support.annotation.NonNull; 7 | import android.view.Gravity; 8 | import android.view.LayoutInflater; 9 | import android.view.View; 10 | import android.view.Window; 11 | import android.view.WindowManager; 12 | 13 | import com.lai.mtc.R; 14 | import com.lai.mtc.mvp.utlis.DensityUtil; 15 | 16 | 17 | public class CommDialog extends Dialog { 18 | private View dialogView; 19 | private Context context; 20 | private int height, width; 21 | private boolean cancelTouchout; 22 | 23 | private Context mContext; 24 | 25 | public CommDialog(@NonNull Builder builder) { 26 | super(builder.context, R.style.commonDialogNoBackground); 27 | this.mContext = builder.context; 28 | height = builder.height; 29 | width = builder.width; 30 | cancelTouchout = builder.cancelTouchout; 31 | dialogView = builder.view; 32 | 33 | } 34 | 35 | @Override 36 | protected void onCreate(Bundle savedInstanceState) { 37 | super.onCreate(savedInstanceState); 38 | setCanceledOnTouchOutside(cancelTouchout); 39 | 40 | Window win = getWindow(); 41 | if (win != null) { 42 | WindowManager.LayoutParams lp = win.getAttributes(); 43 | lp.gravity = Gravity.CENTER; 44 | lp.height = height; 45 | lp.width = width; 46 | win.setAttributes(lp); 47 | } 48 | 49 | setContentView(dialogView); 50 | setCancelable(false); 51 | 52 | } 53 | 54 | public static final class Builder { 55 | 56 | private Context context; 57 | private int height, width; 58 | private boolean cancelTouchout; 59 | private View view; 60 | private int resStyle = -1; 61 | 62 | public CommDialog build() { 63 | return new CommDialog(this); 64 | } 65 | 66 | public Builder(Context context) { 67 | this.context = context; 68 | } 69 | 70 | public Builder view(int resView) { 71 | view = LayoutInflater.from(context).inflate(resView, null); 72 | return this; 73 | } 74 | 75 | public Builder heightpx(int val) { 76 | height = val; 77 | return this; 78 | } 79 | 80 | public Builder widthpx(int val) { 81 | width = val; 82 | return this; 83 | } 84 | 85 | public Builder heightdp(int val) { 86 | height = (int) DensityUtil.px2dp(context,val); 87 | return this; 88 | } 89 | 90 | public Builder widthdp(int val) { 91 | width = DensityUtil.dp2px(context,val); 92 | return this; 93 | } 94 | 95 | public Builder heightDimenRes(int dimenRes) { 96 | height = context.getResources().getDimensionPixelOffset(dimenRes); 97 | return this; 98 | } 99 | 100 | public Builder widthDimenRes(int dimenRes) { 101 | width = context.getResources().getDimensionPixelOffset(dimenRes); 102 | return this; 103 | } 104 | 105 | public Builder style(int resStyle) { 106 | this.resStyle = resStyle; 107 | return this; 108 | } 109 | 110 | public Builder cancelTouchout(boolean val) { 111 | cancelTouchout = val; 112 | return this; 113 | } 114 | 115 | public Builder addViewOnclick(int viewRes, View.OnClickListener listener) { 116 | view.findViewById(viewRes).setOnClickListener(listener); 117 | return this; 118 | } 119 | 120 | 121 | } 122 | 123 | 124 | /** 125 | * 向外提供获取view的方法 126 | * 127 | * @param viewId viewId 128 | * @return view 129 | */ 130 | public View getView(int viewId) { 131 | return dialogView.findViewById(viewId); 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /app/src/main/java/com/lai/mtc/comm/dialog/LoadingDialog.java: -------------------------------------------------------------------------------- 1 | package com.lai.mtc.comm.dialog; 2 | 3 | import android.app.Dialog; 4 | import android.content.Context; 5 | import android.os.Bundle; 6 | import android.support.annotation.IntDef; 7 | import android.support.annotation.NonNull; 8 | import android.view.Gravity; 9 | import android.view.LayoutInflater; 10 | import android.view.View; 11 | import android.view.Window; 12 | import android.view.WindowManager; 13 | 14 | import com.airbnb.lottie.LottieAnimationView; 15 | import com.lai.mtc.R; 16 | import com.lai.mtc.mvp.utlis.DensityUtil; 17 | 18 | /** 19 | * @author Lai 20 | * @time 2018/1/23 15:27 21 | * @describe describe 22 | */ 23 | 24 | public class LoadingDialog extends Dialog { 25 | private View dialogView; 26 | private Context mContext; 27 | private LottieAnimationView mLottieAnimationView; 28 | 29 | //跳水 30 | public static final int JUMP = 1; 31 | //普通加载方式 32 | public static final int NORMAL = 2; 33 | 34 | @IntDef({JUMP, NORMAL}) 35 | public @interface MODE { 36 | } 37 | 38 | 39 | @LoadingDialog.MODE 40 | private int currMode = NORMAL; 41 | 42 | public void setCurrMode(@LoadingDialog.MODE int currMode) { 43 | this.currMode = currMode; 44 | } 45 | 46 | 47 | public LoadingDialog(@NonNull Context context) { 48 | super(context, R.style.commonDialogNoBackground); 49 | mContext = context; 50 | } 51 | 52 | 53 | @Override 54 | protected void onCreate(Bundle savedInstanceState) { 55 | super.onCreate(savedInstanceState); 56 | dialogView = LayoutInflater.from(mContext).inflate(R.layout.comm_loading, null); 57 | 58 | setContentView(dialogView); 59 | //setCancelable(false); 60 | 61 | Window win = getWindow(); 62 | if (win != null) { 63 | WindowManager.LayoutParams lp = win.getAttributes(); 64 | lp.gravity = Gravity.CENTER; 65 | lp.height = DensityUtil.dp2px(mContext, 150); 66 | lp.width = DensityUtil.dp2px(mContext, 150); 67 | win.setAttributes(lp); 68 | } 69 | 70 | mLottieAnimationView = dialogView.findViewById(R.id.animation_view); 71 | 72 | playMode(); 73 | 74 | } 75 | 76 | private void playMode() { 77 | String file = "data.json"; 78 | if (currMode == JUMP) { 79 | file = "jump_loader.json"; 80 | } 81 | mLottieAnimationView.setAnimation(file); 82 | mLottieAnimationView.loop(true); 83 | } 84 | 85 | @Override 86 | protected void onStart() { 87 | super.onStart(); 88 | mLottieAnimationView.playAnimation(); 89 | } 90 | 91 | @Override 92 | protected void onStop() { 93 | super.onStop(); 94 | mLottieAnimationView.cancelAnimation(); 95 | } 96 | 97 | /** 98 | * 向外提供获取view的方法 99 | * 100 | * @param viewId viewId 101 | * @return view 102 | */ 103 | public View getView(int viewId) { 104 | return dialogView.findViewById(viewId); 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /app/src/main/java/com/lai/mtc/comm/widget/BookView.java: -------------------------------------------------------------------------------- 1 | package com.lai.mtc.comm.widget; 2 | 3 | import android.content.Context; 4 | import android.graphics.Canvas; 5 | import android.graphics.drawable.GradientDrawable; 6 | import android.support.v7.widget.CardView; 7 | import android.util.AttributeSet; 8 | 9 | /** 10 | * @author Lai 11 | * @time 2017/8/31 14:28 12 | * @describe describe 13 | */ 14 | 15 | public class BookView extends CardView { 16 | GradientDrawable gradientDrawable; 17 | 18 | public BookView(Context context) { 19 | this(context,null); 20 | } 21 | 22 | public BookView(Context context, AttributeSet attrs) { 23 | this(context, attrs,0); 24 | } 25 | 26 | public BookView(Context context, AttributeSet attrs, int defStyleAttr) { 27 | super(context,attrs,defStyleAttr); 28 | init(); 29 | } 30 | 31 | private void init() { 32 | gradientDrawable = new GradientDrawable(); 33 | //左上 右上 右下 左下 34 | gradientDrawable.setCornerRadii(new float[]{0,5,5,0}); 35 | } 36 | 37 | @Override 38 | protected void onDraw(Canvas canvas) { 39 | super.onDraw(canvas); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /app/src/main/java/com/lai/mtc/comm/widget/InterceptAppBarLayout.java: -------------------------------------------------------------------------------- 1 | package com.lai.mtc.comm.widget; 2 | 3 | import android.content.Context; 4 | import android.support.design.widget.AppBarLayout; 5 | import android.util.AttributeSet; 6 | import android.view.MotionEvent; 7 | 8 | /** 9 | * @author Lai 10 | * @time 2018/1/19 14:53 11 | * @describe describe 12 | */ 13 | 14 | public class InterceptAppBarLayout extends AppBarLayout { 15 | 16 | public InterceptAppBarLayout(Context context) { 17 | super(context); 18 | } 19 | 20 | public InterceptAppBarLayout(Context context, AttributeSet attrs) { 21 | super(context, attrs); 22 | } 23 | 24 | public boolean isIntercept() { 25 | return isIntercept; 26 | } 27 | 28 | public void setIntercept(boolean intercept) { 29 | isIntercept = intercept; 30 | } 31 | 32 | private boolean isIntercept; 33 | 34 | @Override 35 | public boolean dispatchTouchEvent(MotionEvent ev) { 36 | return isIntercept || super.dispatchTouchEvent(ev); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /app/src/main/java/com/lai/mtc/comm/widget/InterceptCoordinatorLayout.java: -------------------------------------------------------------------------------- 1 | package com.lai.mtc.comm.widget; 2 | 3 | import android.content.Context; 4 | import android.support.annotation.NonNull; 5 | import android.support.annotation.Nullable; 6 | import android.support.design.widget.CoordinatorLayout; 7 | import android.util.AttributeSet; 8 | import android.view.MotionEvent; 9 | 10 | /** 11 | * @author Lai 12 | * @time 2018/1/19 14:53 13 | * @describe describe 14 | */ 15 | 16 | public class InterceptCoordinatorLayout extends CoordinatorLayout { 17 | 18 | 19 | public boolean isInterceptBehavior() { 20 | return isInterceptBehavior; 21 | } 22 | 23 | public void setInterceptBehavior(boolean interceptBehavior) { 24 | isInterceptBehavior = interceptBehavior; 25 | } 26 | 27 | private boolean isInterceptBehavior; 28 | 29 | public InterceptCoordinatorLayout(@NonNull Context context) { 30 | super(context); 31 | } 32 | 33 | public InterceptCoordinatorLayout(@NonNull Context context, @Nullable AttributeSet attrs) { 34 | super(context, attrs); 35 | } 36 | 37 | public InterceptCoordinatorLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { 38 | super(context, attrs, defStyleAttr); 39 | } 40 | 41 | @Override 42 | public boolean onInterceptTouchEvent(MotionEvent ev) { 43 | 44 | return super.onInterceptTouchEvent(ev)||isInterceptBehavior; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /app/src/main/java/com/lai/mtc/comm/widget/MotionEventRecyclerView.java: -------------------------------------------------------------------------------- 1 | package com.lai.mtc.comm.widget; 2 | 3 | import android.content.Context; 4 | import android.support.v7.widget.RecyclerView; 5 | import android.util.AttributeSet; 6 | import android.view.MotionEvent; 7 | 8 | /** 9 | * @author Lai 10 | * @time 2018/1/19 14:53 11 | * @describe describe 12 | */ 13 | 14 | public class MotionEventRecyclerView extends RecyclerView { 15 | 16 | public boolean isInterceptTouch() { 17 | return isInterceptTouch; 18 | } 19 | 20 | public void setInterceptTouch(boolean interceptTouch) { 21 | isInterceptTouch = interceptTouch; 22 | } 23 | 24 | boolean isInterceptTouch; 25 | 26 | public MotionEventRecyclerView(Context context) { 27 | this(context, null); 28 | } 29 | 30 | public MotionEventRecyclerView(Context context, AttributeSet attrs) { 31 | super(context, attrs); 32 | } 33 | 34 | 35 | @Override 36 | public boolean onInterceptTouchEvent(MotionEvent e) { 37 | return super.onInterceptTouchEvent(e); 38 | } 39 | 40 | @Override 41 | public boolean dispatchTouchEvent(MotionEvent ev) { 42 | return super.dispatchTouchEvent(ev); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /app/src/main/java/com/lai/mtc/comm/widget/PreCacheLayoutManager.java: -------------------------------------------------------------------------------- 1 | package com.lai.mtc.comm.widget; 2 | 3 | import android.content.Context; 4 | import android.support.v7.widget.LinearLayoutManager; 5 | import android.support.v7.widget.RecyclerView; 6 | 7 | /** 8 | * @author Lai 9 | * @time 2018/2/6 18:05 10 | * @describe 预加载的LayoutManager 11 | * getExtraLayoutSpace(),增加不可见View的缓存的空间 12 | *

13 | * http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0209/2452.html 14 | */ 15 | 16 | public class PreCacheLayoutManager extends LinearLayoutManager { 17 | 18 | public int getExtraSpace() { 19 | return mExtraSpace; 20 | } 21 | 22 | private int mExtraSpace = 0; 23 | 24 | 25 | public PreCacheLayoutManager(Context context) { 26 | super(context); 27 | } 28 | 29 | 30 | public void setExtraSpace(int extraSpace) { 31 | mExtraSpace = extraSpace; 32 | } 33 | 34 | //getExtraLayoutSpace(),增加不可见View的缓存的空间 35 | @Override 36 | protected int getExtraLayoutSpace(RecyclerView.State state) { 37 | if (mExtraSpace > 0) { 38 | if (getOrientation() == LinearLayoutManager.HORIZONTAL) { 39 | return mExtraSpace * getWidth(); 40 | } else { 41 | return mExtraSpace * getHeight(); 42 | } 43 | } 44 | return 0; 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /app/src/main/java/com/lai/mtc/comm/widget/TouchRecyclerView.java: -------------------------------------------------------------------------------- 1 | package com.lai.mtc.comm.widget; 2 | 3 | import android.content.Context; 4 | import android.support.annotation.Nullable; 5 | import android.support.v7.widget.RecyclerView; 6 | import android.util.AttributeSet; 7 | import android.view.MotionEvent; 8 | import android.view.ViewConfiguration; 9 | 10 | /** 11 | * @author Lai 12 | * @time 2018/1/29 21:40 13 | * @describe 触摸相关的RecyclerView. 14 | * 具体的作用:只要点击事件。滑动的话不算 15 | */ 16 | 17 | public class TouchRecyclerView extends RecyclerView { 18 | 19 | private int touchSlop; 20 | private float startX = -1; 21 | private float startY = -1; 22 | 23 | 24 | public void setITouchCallBack(ITouchCallBack IMiddleCallBack) { 25 | mIMiddleCallBack = IMiddleCallBack; 26 | } 27 | 28 | private ITouchCallBack mIMiddleCallBack; 29 | 30 | public TouchRecyclerView(Context context) { 31 | this(context, null); 32 | } 33 | 34 | public TouchRecyclerView(Context context, @Nullable AttributeSet attrs) { 35 | this(context, attrs, 0); 36 | } 37 | 38 | public TouchRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) { 39 | super(context, attrs, defStyle); 40 | touchSlop = ViewConfiguration.get(context).getScaledTouchSlop(); 41 | 42 | //addOnScrollListener(new ImageAutoLoadScrollListener()); 43 | } 44 | 45 | 46 | 47 | @Override 48 | public boolean onTouchEvent(MotionEvent event) { 49 | int action = event.getAction(); 50 | switch (action) { 51 | case MotionEvent.ACTION_DOWN: 52 | startX = event.getX(); 53 | startY = event.getY(); 54 | break; 55 | case MotionEvent.ACTION_UP: 56 | if (Math.abs(event.getX() - startX) > touchSlop) 57 | startX = -1; 58 | if (Math.abs(event.getY() - startY) > touchSlop) 59 | startX = -1; 60 | 61 | if (startX != -1) { 62 | if (mIMiddleCallBack != null) 63 | mIMiddleCallBack.click(); 64 | } 65 | break; 66 | default: 67 | break; 68 | } 69 | return super.onTouchEvent(event); 70 | } 71 | 72 | public interface ITouchCallBack { 73 | void click(); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /app/src/main/java/com/lai/mtc/dao/BaseDao.java: -------------------------------------------------------------------------------- 1 | package com.lai.mtc.dao; 2 | 3 | import com.lai.mtc.MTC; 4 | 5 | import java.lang.reflect.ParameterizedType; 6 | import java.util.List; 7 | 8 | import io.objectbox.Box; 9 | 10 | /** 11 | * @author Lai 12 | * @time 2018/2/10 17:36 13 | * @describe 增删改查基类 14 | */ 15 | public class BaseDao { 16 | 17 | public Box getBox() { 18 | return mBox; 19 | } 20 | 21 | protected Box mBox; 22 | 23 | private Class mTClass; 24 | 25 | protected BaseDao() { 26 | //获取 T.class 27 | mTClass = (Class) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]; 28 | 29 | mBox = MTC.getBoxStore().boxFor(mTClass); 30 | } 31 | 32 | /** 33 | * 根据Id查找 34 | * 35 | * @param id 36 | * @return 37 | */ 38 | public T getById(long id) { 39 | return getBox().get(id); 40 | } 41 | 42 | /** 43 | * 是否存在 44 | * 45 | * @param id id 46 | * @return 是否 47 | */ 48 | public boolean isCollection(int id) { 49 | return getById(id) != null; 50 | } 51 | 52 | /** 53 | * 取得所有的集合 54 | * 55 | * @return 56 | */ 57 | public List getAll() { 58 | return mBox.getAll(); 59 | } 60 | 61 | /** 62 | * 根据Id删除 63 | * 64 | * @param id 65 | */ 66 | public void delete(int id) { 67 | mBox.remove(id); 68 | } 69 | 70 | public void deleteAll() { 71 | mBox.removeAll(); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /app/src/main/java/com/lai/mtc/dao/CollectionDao.java: -------------------------------------------------------------------------------- 1 | package com.lai.mtc.dao; 2 | 3 | import com.lai.mtc.bean.ComicListInfo; 4 | import com.lai.mtc.dao.bean.MyCollection; 5 | 6 | import java.util.Date; 7 | 8 | /** 9 | * @author Lai 10 | * @time 2018/2/1 19:25 11 | * @describe describe 12 | */ 13 | 14 | public class CollectionDao extends BaseDao{ 15 | 16 | /** 17 | * 添加收藏。 18 | * 19 | * @param entriesBean 实体类 20 | * @return id 21 | */ 22 | public void addCollection(ComicListInfo.EntriesBean entriesBean) { 23 | //long start = System.currentTimeMillis(); 24 | 25 | MyCollection collection = new MyCollection(); 26 | collection.setId(entriesBean.getId()); 27 | collection.setCover(entriesBean.getCover()); 28 | collection.setDesc(entriesBean.getDescription()); 29 | collection.setTime(new Date()); 30 | collection.setStatus(entriesBean.getStatus()); 31 | collection.setAuthor(entriesBean.getAuthor()); 32 | collection.setName(entriesBean.getName()); 33 | mBox.put(collection); 34 | //更新组件信息 35 | /* List all = mGroupBox.getAll(); 36 | //是否为空 37 | if (!ListUtils.isEmpty(all)) { 38 | Group group = all.get(all.size() - 1); 39 | //查看最后一组的列表是否 40 | if (group.getMyCollections().size() == 3) { 41 | //满了就建立一个新的组 42 | newGroup(collection); 43 | } else { 44 | //没满则添加 45 | group.getMyCollections().add(collection); 46 | //更新 47 | mGroupBox.put(group); 48 | } 49 | } else { 50 | //第一次直接新建 51 | newGroup(collection); 52 | }*/ 53 | //long time = System.currentTimeMillis() - start; 54 | //Log.w("11111", "时间为" + time + " ms"); 55 | } 56 | 57 | 58 | } 59 | -------------------------------------------------------------------------------- /app/src/main/java/com/lai/mtc/dao/RecordDao.java: -------------------------------------------------------------------------------- 1 | package com.lai.mtc.dao; 2 | 3 | import com.lai.mtc.dao.bean.Record; 4 | 5 | /** 6 | * @author Lai 7 | * @time 2018/2/7 17:11 8 | * @describe 集数记录 9 | */ 10 | 11 | public class RecordDao extends BaseDao { 12 | 13 | public void updateRecord(long id, String name, int index, int position) { 14 | Record record = new Record(); 15 | record.setId(id); 16 | record.setName(name); 17 | record.setIndex(index); 18 | record.setPosition(position); 19 | mBox.put(record); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/src/main/java/com/lai/mtc/dao/SearchRecordDao.java: -------------------------------------------------------------------------------- 1 | package com.lai.mtc.dao; 2 | 3 | import com.lai.mtc.dao.bean.SearchRecord; 4 | import com.lai.mtc.dao.bean.SearchRecord_; 5 | 6 | import io.objectbox.query.QueryBuilder; 7 | 8 | /** 9 | * @author Lai 10 | * @time 2018/2/10 17:35 11 | * @describe 搜索记录 12 | */ 13 | 14 | public class SearchRecordDao extends BaseDao { 15 | 16 | public void addSearch(String str) { 17 | SearchRecord searchRecord = new SearchRecord(); 18 | searchRecord.setInputName(str); 19 | mBox.put(searchRecord); 20 | } 21 | 22 | public boolean hasData(String str) { 23 | QueryBuilder equal = mBox.query().equal(SearchRecord_.inputName, str); 24 | SearchRecord unique = equal.build().findUnique(); 25 | return unique != null; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/src/main/java/com/lai/mtc/dao/bean/Group.java: -------------------------------------------------------------------------------- 1 | package com.lai.mtc.dao.bean; 2 | 3 | import io.objectbox.annotation.Entity; 4 | import io.objectbox.annotation.Id; 5 | import io.objectbox.relation.ToMany; 6 | 7 | /** 8 | * @author Lai 9 | * @time 2018/2/1 20:19 10 | * @describe 组。一组默认三个本书 11 | */ 12 | @Entity 13 | public class Group { 14 | @Id 15 | private long id; 16 | public ToMany myCollections; 17 | 18 | public long getId() { 19 | return id; 20 | } 21 | 22 | public void setId(long id) { 23 | this.id = id; 24 | } 25 | 26 | public ToMany getMyCollections() { 27 | return myCollections; 28 | } 29 | 30 | public void setMyCollections(ToMany myCollections) { 31 | this.myCollections = myCollections; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /app/src/main/java/com/lai/mtc/dao/bean/MyCollection.java: -------------------------------------------------------------------------------- 1 | package com.lai.mtc.dao.bean; 2 | 3 | import java.io.Serializable; 4 | import java.util.Date; 5 | 6 | import io.objectbox.annotation.Entity; 7 | import io.objectbox.annotation.Id; 8 | 9 | /** 10 | * @author Lai 11 | * @time 2018/2/1 16:26 12 | * @describe 我的收藏 13 | */ 14 | @Entity 15 | public class MyCollection implements Serializable { 16 | public long getId() { 17 | return id; 18 | } 19 | 20 | public void setId(long id) { 21 | this.id = id; 22 | } 23 | 24 | @Id(assignable = true) 25 | public long id; 26 | private String desc; 27 | private String cover; 28 | private String name; 29 | 30 | public String getStatus() { 31 | return status; 32 | } 33 | 34 | public void setStatus(String status) { 35 | this.status = status; 36 | } 37 | 38 | private String status; 39 | 40 | public String getAuthor() { 41 | return author; 42 | } 43 | 44 | public void setAuthor(String author) { 45 | this.author = author; 46 | } 47 | 48 | private String author; 49 | 50 | 51 | public String getName() { 52 | return name; 53 | } 54 | 55 | public void setName(String name) { 56 | this.name = name; 57 | } 58 | 59 | public Date getTime() { 60 | return time; 61 | } 62 | 63 | public void setTime(Date time) { 64 | this.time = time; 65 | } 66 | 67 | private Date time; 68 | 69 | 70 | public String getDesc() { 71 | return desc; 72 | } 73 | 74 | public void setDesc(String desc) { 75 | this.desc = desc; 76 | } 77 | 78 | public String getCover() { 79 | return cover; 80 | } 81 | 82 | public void setCover(String cover) { 83 | this.cover = cover; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /app/src/main/java/com/lai/mtc/dao/bean/Record.java: -------------------------------------------------------------------------------- 1 | package com.lai.mtc.dao.bean; 2 | 3 | import java.io.Serializable; 4 | 5 | import io.objectbox.annotation.Entity; 6 | import io.objectbox.annotation.Id; 7 | 8 | /** 9 | * @author Lai 10 | * @time 2018/2/7 17:07 11 | * @describe 当前漫画的点击记录 12 | */ 13 | @Entity 14 | public class Record implements Serializable { 15 | 16 | @Id(assignable = true) 17 | private long id; 18 | 19 | public int getPosition() { 20 | return position; 21 | } 22 | 23 | public void setPosition(int position) { 24 | this.position = position; 25 | } 26 | 27 | private int position; 28 | private int index; 29 | 30 | public String getName() { 31 | return name; 32 | } 33 | 34 | public int getIndex() { 35 | return index; 36 | } 37 | 38 | public void setIndex(int index) { 39 | this.index = index; 40 | } 41 | 42 | public void setName(String name) { 43 | this.name = name; 44 | } 45 | 46 | private String name; 47 | 48 | public long getId() { 49 | return id; 50 | } 51 | 52 | public void setId(long id) { 53 | this.id = id; 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /app/src/main/java/com/lai/mtc/dao/bean/SearchRecord.java: -------------------------------------------------------------------------------- 1 | package com.lai.mtc.dao.bean; 2 | 3 | import io.objectbox.annotation.Entity; 4 | import io.objectbox.annotation.Id; 5 | 6 | /** 7 | * @author Lai 8 | * @time 2018/2/10 17:34 9 | * @describe 搜索记录 10 | */ 11 | @Entity 12 | public class SearchRecord { 13 | @Id 14 | private long id; 15 | private String inputName; 16 | 17 | public long getId() { 18 | return id; 19 | } 20 | 21 | public void setId(long id) { 22 | this.id = id; 23 | } 24 | 25 | public String getInputName() { 26 | return inputName; 27 | } 28 | 29 | public void setInputName(String inputName) { 30 | this.inputName = inputName; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/src/main/java/com/lai/mtc/di/component/AppComponent.java: -------------------------------------------------------------------------------- 1 | package com.lai.mtc.di.component; 2 | 3 | import com.lai.mtc.MTC; 4 | import com.lai.mtc.di.module.ApiModule; 5 | import com.lai.mtc.di.module.AppModule; 6 | import com.lai.mtc.di.module.BuildersModule; 7 | import com.lai.mtc.di.module.NetModule; 8 | 9 | import javax.inject.Singleton; 10 | 11 | import dagger.BindsInstance; 12 | import dagger.Component; 13 | import dagger.android.AndroidInjector; 14 | import dagger.android.support.AndroidSupportInjectionModule; 15 | 16 | /** 17 | * @author Lai 18 | * @time 2017/12/12 16:52 19 | * @describe describe 20 | */ 21 | @Component(modules = { 22 | AppModule.class, 23 | BuildersModule.class, 24 | NetModule.class, 25 | ApiModule.class, 26 | AndroidSupportInjectionModule.class 27 | }) 28 | @Singleton 29 | public interface AppComponent extends AndroidInjector { 30 | 31 | @Component.Builder 32 | interface Builder { 33 | @BindsInstance 34 | Builder application(MTC application); 35 | 36 | @BindsInstance 37 | Builder baseUrl(String url); 38 | 39 | AppComponent build(); 40 | } 41 | 42 | void inject(MTC app); 43 | } 44 | -------------------------------------------------------------------------------- /app/src/main/java/com/lai/mtc/di/module/ApiModule.java: -------------------------------------------------------------------------------- 1 | package com.lai.mtc.di.module; 2 | 3 | 4 | import com.lai.mtc.api.ComicApi; 5 | 6 | import javax.inject.Singleton; 7 | 8 | import dagger.Module; 9 | import dagger.Provides; 10 | import retrofit2.Retrofit; 11 | 12 | /** 13 | * @author Lai 14 | * @time 2017/12/12 15:11 15 | * @describe 专门提供api仓库 16 | */ 17 | @Module 18 | public class ApiModule { 19 | 20 | 21 | @Provides 22 | @Singleton 23 | ComicApi provideComicApi(Retrofit retrofit) { 24 | return retrofit.create(ComicApi.class); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/java/com/lai/mtc/di/module/AppModule.java: -------------------------------------------------------------------------------- 1 | package com.lai.mtc.di.module; 2 | 3 | import android.app.Application; 4 | 5 | import com.lai.mtc.MTC; 6 | 7 | import javax.inject.Singleton; 8 | 9 | import dagger.Module; 10 | import dagger.Provides; 11 | 12 | /** 13 | * @author Lai 14 | * @time 2017/12/11 11:43 15 | * @describe 将会提供Application 的context引用 16 | */ 17 | @Module 18 | public class AppModule { 19 | @Provides 20 | @Singleton 21 | Application provideContext(MTC application) { 22 | return application; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/java/com/lai/mtc/di/module/BuildersModule.java: -------------------------------------------------------------------------------- 1 | package com.lai.mtc.di.module; 2 | 3 | import com.lai.mtc.TestMainActivity; 4 | import com.lai.mtc.MainActivity; 5 | import com.lai.mtc.mvp.scope.ActivityScope; 6 | import com.lai.mtc.mvp.ui.comics.activity.ComicListDetailActivity; 7 | import com.lai.mtc.mvp.ui.comics.activity.ComicPreviewActivity; 8 | import com.lai.mtc.mvp.ui.comics.activity.ComicSearchActivity; 9 | 10 | import dagger.Module; 11 | import dagger.android.ContributesAndroidInjector; 12 | 13 | /** 14 | * @author Lai 15 | * @time 2017/12/12 16:54 16 | * @describe Activity 统一注入 17 | */ 18 | @Module 19 | public abstract class BuildersModule { 20 | 21 | @ContributesAndroidInjector(modules = DaoModule.class) 22 | @ActivityScope 23 | abstract MainActivity mainActivityInjector(); 24 | 25 | @ContributesAndroidInjector 26 | @ActivityScope 27 | abstract TestMainActivity bmainActivityInjector(); 28 | 29 | @ContributesAndroidInjector(modules = DaoModule.class) 30 | @ActivityScope 31 | abstract ComicListDetailActivity comicListDetailActivityInject(); 32 | 33 | @ContributesAndroidInjector(modules = DaoModule.class) 34 | @ActivityScope 35 | abstract ComicPreviewActivity cmicPreviewActivityInject(); 36 | 37 | @ContributesAndroidInjector(modules = DaoModule.class) 38 | @ActivityScope 39 | abstract ComicSearchActivity comicSearchActivityActivityInject(); 40 | } 41 | -------------------------------------------------------------------------------- /app/src/main/java/com/lai/mtc/di/module/DaoModule.java: -------------------------------------------------------------------------------- 1 | package com.lai.mtc.di.module; 2 | 3 | import com.lai.mtc.dao.CollectionDao; 4 | import com.lai.mtc.dao.RecordDao; 5 | import com.lai.mtc.dao.SearchRecordDao; 6 | import com.lai.mtc.mvp.scope.ActivityScope; 7 | 8 | import dagger.Module; 9 | import dagger.Provides; 10 | 11 | /** 12 | * @author Lai 13 | * @time 2018/2/1 19:43 14 | * @describe 数据库管理仓库 15 | */ 16 | @Module 17 | public class DaoModule { 18 | 19 | @Provides 20 | @ActivityScope 21 | CollectionDao provideCollectionDao() { 22 | return new CollectionDao(); 23 | } 24 | 25 | @Provides 26 | @ActivityScope 27 | RecordDao provideRecordDao() { 28 | return new RecordDao(); 29 | } 30 | 31 | @Provides 32 | @ActivityScope 33 | SearchRecordDao provideSearchRecordDao() { 34 | return new SearchRecordDao(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /app/src/main/java/com/lai/mtc/mvp/base/IModel.java: -------------------------------------------------------------------------------- 1 | package com.lai.mtc.mvp.base; 2 | 3 | /** 4 | * @author Lai 5 | * @time 2017/12/10 16:13 6 | * @describe describe 7 | */ 8 | 9 | public interface IModel { 10 | void onDestroy(); 11 | } 12 | -------------------------------------------------------------------------------- /app/src/main/java/com/lai/mtc/mvp/base/IPresenter.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017 JessYan 3 | *

4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | *

8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | *

10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.lai.mtc.mvp.base; 17 | 18 | import android.app.Activity; 19 | 20 | import io.reactivex.Observable; 21 | 22 | /** 23 | * P层封装。 24 | * @param View 25 | * @see com.lai.mtc.mvp.presenter.SimplePresenter 26 | */ 27 | public interface IPresenter { 28 | 29 | /** 30 | * 做一些初始化操作 31 | */ 32 | void onStart(); 33 | 34 | /** 35 | * 在框架中 {@link Activity#onDestroy()} 时会默认调用 {@link IPresenter#onDestroy()} 36 | */ 37 | void onDestroy(); 38 | 39 | void attachView(T view); 40 | 41 | T getView(); 42 | 43 | } 44 | -------------------------------------------------------------------------------- /app/src/main/java/com/lai/mtc/mvp/base/IView.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017 JessYan 3 | *

4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | *

8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | *

10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.lai.mtc.mvp.base; 17 | 18 | import android.support.v7.widget.Toolbar; 19 | 20 | import com.lai.mtc.comm.ApiException; 21 | import com.lai.mtc.comm.dialog.LoadingDialog; 22 | import com.trello.rxlifecycle2.LifecycleTransformer; 23 | 24 | /** 25 | * View层公共封装 26 | * 27 | * @see com.lai.mtc.mvp.presenter.SimplePresenter 28 | */ 29 | public interface IView { 30 | 31 | /** 32 | * 显示加载 33 | */ 34 | void showLoading(); 35 | 36 | void showLoading(@LoadingDialog.MODE int mode); 37 | 38 | /** 39 | * 隐藏加载 40 | */ 41 | void hideLoading(); 42 | 43 | /** 44 | * 显示信息 45 | */ 46 | void showMessage(String message); 47 | 48 | LifecycleTransformer bindToLifecycle(); 49 | 50 | void setToolBar(Toolbar toolBar, String title, boolean needBackButton); 51 | 52 | void handleError(ApiException e); 53 | } 54 | -------------------------------------------------------------------------------- /app/src/main/java/com/lai/mtc/mvp/base/impl/BaseModel.java: -------------------------------------------------------------------------------- 1 | package com.lai.mtc.mvp.base.impl; 2 | 3 | import android.arch.lifecycle.Lifecycle; 4 | import android.arch.lifecycle.LifecycleObserver; 5 | import android.arch.lifecycle.LifecycleOwner; 6 | import android.arch.lifecycle.OnLifecycleEvent; 7 | 8 | import com.lai.mtc.mvp.base.IModel; 9 | 10 | /** 11 | * @author Lai 12 | * @time 2017/12/10 16:16 13 | * @describe describe 14 | */ 15 | 16 | public class BaseModel implements IModel, LifecycleObserver { 17 | @Override 18 | public void onDestroy() { 19 | 20 | } 21 | 22 | @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY) 23 | void onDestroy(LifecycleOwner owner) { 24 | owner.getLifecycle().removeObserver(this); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/java/com/lai/mtc/mvp/base/impl/BaseMvpActivity.java: -------------------------------------------------------------------------------- 1 | package com.lai.mtc.mvp.base.impl; 2 | 3 | import android.os.Bundle; 4 | 5 | import com.lai.mtc.mvp.base.IPresenter; 6 | import com.lai.mtc.mvp.base.IView; 7 | 8 | import javax.inject.Inject; 9 | 10 | /** 11 | * @author Lai 12 | * @time 2017/12/10 17:18 13 | * @describe MVP Activity 14 | */ 15 | 16 | public abstract class BaseMvpActivity

extends BaseActivity implements IView { 17 | //实例化P.桥梁,辅助activity和model之间的交互 18 | @Inject 19 | protected P mPresenter; 20 | 21 | 22 | @Override 23 | public void initData(Bundle savedInstanceState) { 24 | //和View绑定 25 | if (mPresenter != null) { 26 | mPresenter.attachView(this); 27 | } 28 | init(savedInstanceState); 29 | bindEvent(); 30 | } 31 | 32 | protected void bindEvent(){ 33 | 34 | } 35 | 36 | public abstract void init(Bundle savedInstanceState); 37 | 38 | @Override 39 | protected void onDestroy() { 40 | //把所有的数据销毁掉 41 | super.onDestroy(); 42 | if (mPresenter != null) 43 | mPresenter.onDestroy();//释放资源 44 | this.mPresenter = null; 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /app/src/main/java/com/lai/mtc/mvp/base/impl/BaseMvpFragment.java: -------------------------------------------------------------------------------- 1 | package com.lai.mtc.mvp.base.impl; 2 | 3 | import android.os.Bundle; 4 | 5 | import com.lai.mtc.mvp.base.IPresenter; 6 | 7 | import javax.inject.Inject; 8 | 9 | /** 10 | * @author Lai 11 | * @time 2017/9/1 9:53 12 | * @describe MVP Fragment 封装 13 | */ 14 | 15 | public abstract class BaseMvpFragment

extends BaseFragment { 16 | 17 | @Inject 18 | protected P mPresenter; 19 | 20 | @Override 21 | public void finishCreateView(Bundle state) { 22 | if (mPresenter != null) { 23 | mPresenter.attachView(this); 24 | } 25 | init(state); 26 | bindEvent(); 27 | } 28 | 29 | public abstract void init(Bundle state); 30 | 31 | @Override 32 | public void onDestroy() { 33 | super.onDestroy(); 34 | if (mPresenter != null) mPresenter.onDestroy();//释放资源 35 | this.mPresenter = null; 36 | } 37 | 38 | public void bindEvent() { 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /app/src/main/java/com/lai/mtc/mvp/base/impl/BasePresenter.java: -------------------------------------------------------------------------------- 1 | package com.lai.mtc.mvp.base.impl; 2 | 3 | import android.arch.lifecycle.Lifecycle; 4 | import android.arch.lifecycle.LifecycleObserver; 5 | import android.arch.lifecycle.LifecycleOwner; 6 | import android.arch.lifecycle.OnLifecycleEvent; 7 | 8 | import com.lai.mtc.comm.ExceptionEngine; 9 | import com.lai.mtc.mvp.base.IPresenter; 10 | import com.lai.mtc.mvp.base.IView; 11 | 12 | import io.reactivex.Observable; 13 | import io.reactivex.annotations.NonNull; 14 | import io.reactivex.functions.Function; 15 | 16 | /** 17 | * @author Lai 18 | * @time 2017/12/10 16:32 19 | * @describe 公共P层 20 | */ 21 | 22 | public class BasePresenter implements IPresenter, LifecycleObserver { 23 | 24 | //Model数据 25 | // protected M mModel; 26 | //View 显示回显的接口 27 | protected V mRootView; 28 | 29 | public BasePresenter() { 30 | onStart(); 31 | } 32 | 33 | @Override 34 | public void onStart() { 35 | //mRootView一定是activity的实现类。所有通过getLifecycle().addObserver(this);方法可以将activity的生命周期监听 36 | if (mRootView != null && mRootView instanceof LifecycleOwner) { 37 | ((LifecycleOwner) mRootView).getLifecycle().addObserver(this); 38 | } 39 | } 40 | 41 | //监听activity的销毁事件,当他销毁的时候会自动调用该方法取消生命周期的订阅 42 | @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY) 43 | void onDestroy(LifecycleOwner owner) { 44 | owner.getLifecycle().removeObserver(this); 45 | } 46 | 47 | @Override 48 | public void onDestroy() { 49 | this.mRootView = null; 50 | } 51 | 52 | @Override 53 | public void attachView(V view) { 54 | this.mRootView = view; 55 | } 56 | 57 | @Override 58 | public V getView() { 59 | return mRootView; 60 | } 61 | 62 | 63 | public class HttpResultFunction implements Function> { 64 | @Override 65 | public Observable apply(@NonNull Throwable throwable) throws Exception { 66 | //打印具体错误 67 | return Observable.error(ExceptionEngine.handleException(throwable)); 68 | } 69 | } 70 | 71 | 72 | } 73 | -------------------------------------------------------------------------------- /app/src/main/java/com/lai/mtc/mvp/contract/ComicsContract.java: -------------------------------------------------------------------------------- 1 | package com.lai.mtc.mvp.contract; 2 | 3 | 4 | import com.lai.mtc.bean.ComicListInfo; 5 | import com.lai.mtc.mvp.base.IModel; 6 | import com.lai.mtc.mvp.base.IView; 7 | import com.lai.mtc.mvp.presenter.ComicsPresenter; 8 | 9 | import java.util.List; 10 | 11 | /** 12 | * @author Lai 13 | * @time 2017/12/11 17:01 14 | * @describe 漫画契约类 15 | */ 16 | 17 | public class ComicsContract { 18 | //对于经常使用的关于UI的方法可以定义到IView中,如显示隐藏进度条,和显示文字消息 19 | public interface View extends IView { 20 | void showRequestHome(List mInfoList); 21 | 22 | void showChange(ComicListInfo mInfoList, int position); 23 | } 24 | 25 | //Model层定义接口,外部只需关心Model返回的数据,无需关心内部细节,如是否使用缓存 26 | public interface Model extends IModel { 27 | void requestHome(@ComicsPresenter.MODE int mode); 28 | 29 | void change(@ComicsPresenter.MODE int mode, int pager, int position, int id,String name); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /app/src/main/java/com/lai/mtc/mvp/contract/ComicsListDetailContract.java: -------------------------------------------------------------------------------- 1 | package com.lai.mtc.mvp.contract; 2 | 3 | 4 | import com.lai.mtc.bean.ComicListDetail; 5 | import com.lai.mtc.mvp.base.IModel; 6 | import com.lai.mtc.mvp.base.IView; 7 | 8 | /** 9 | * @author Lai 10 | * @time 2017/12/11 17:01 11 | * @describe 漫画契约类 12 | */ 13 | 14 | public class ComicsListDetailContract { 15 | //对于经常使用的关于UI的方法可以定义到IView中,如显示隐藏进度条,和显示文字消息 16 | public interface View extends IView { 17 | void showDetail(ComicListDetail comicListDetail); 18 | void reverse(ComicListDetail comicListDetail); 19 | } 20 | 21 | //Model层定义接口,外部只需关心Model返回的数据,无需关心内部细节,如是否使用缓存 22 | public interface Model extends IModel { 23 | void getComicById(int id); 24 | void reverse(ComicListDetail comicListDetail); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/java/com/lai/mtc/mvp/contract/ComicsPreviewContract.java: -------------------------------------------------------------------------------- 1 | package com.lai.mtc.mvp.contract; 2 | 3 | 4 | import android.content.Context; 5 | 6 | import com.lai.mtc.bean.ComicListDetail; 7 | import com.lai.mtc.bean.ComicPreView; 8 | import com.lai.mtc.mvp.base.IModel; 9 | import com.lai.mtc.mvp.base.IView; 10 | 11 | /** 12 | * @author Lai 13 | * @time 2017/12/11 17:01 14 | * @describe 模版 15 | */ 16 | 17 | public class ComicsPreviewContract { 18 | //对于经常使用的关于UI的方法可以定义到IView中,如显示隐藏进度条,和显示文字消息 19 | public interface View extends IView { 20 | void showPreview(ComicPreView comicPreView, boolean isRefresh); 21 | } 22 | 23 | //Model层定义接口,外部只需关心Model返回的数据,无需关心内部细节,如是否使用缓存 24 | public interface Model extends IModel { 25 | void requestPreview(int id, int cid, Context context, boolean isRefresh); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/src/main/java/com/lai/mtc/mvp/contract/ComicsSearchContract.java: -------------------------------------------------------------------------------- 1 | package com.lai.mtc.mvp.contract; 2 | 3 | 4 | import com.lai.mtc.bean.ComicListInfo; 5 | import com.lai.mtc.mvp.base.IModel; 6 | import com.lai.mtc.mvp.base.IView; 7 | 8 | /** 9 | * @author Lai 10 | * @time 2017/12/11 17:01 11 | * @describe 模版 12 | */ 13 | 14 | public class ComicsSearchContract { 15 | //对于经常使用的关于UI的方法可以定义到IView中,如显示隐藏进度条,和显示文字消息 16 | public interface View extends IView { 17 | void showList(ComicListInfo comicListInfo); 18 | } 19 | 20 | //Model层定义接口,外部只需关心Model返回的数据,无需关心内部细节,如是否使用缓存 21 | public interface Model extends IModel { 22 | void search(String name, int pager, boolean isFresh); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/java/com/lai/mtc/mvp/contract/SimpleContract.java: -------------------------------------------------------------------------------- 1 | package com.lai.mtc.mvp.contract; 2 | 3 | 4 | import com.lai.mtc.mvp.base.IModel; 5 | import com.lai.mtc.mvp.base.IView; 6 | 7 | /** 8 | * @author Lai 9 | * @time 2017/12/11 17:01 10 | * @describe 模版 11 | * 契约类。统一写可减少回调 12 | */ 13 | 14 | public class SimpleContract { 15 | //对于经常使用的关于UI的方法可以定义到IView中,如显示隐藏进度条,和显示文字消息 16 | public interface View extends IView { 17 | } 18 | 19 | //Model层定义接口,外部只需关心Model返回的数据,无需关心内部细节,如是否使用缓存 20 | public interface Model extends IModel { 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/src/main/java/com/lai/mtc/mvp/http/RetrofitHelper.java: -------------------------------------------------------------------------------- 1 | package com.lai.mtc.mvp.http; 2 | 3 | 4 | import com.lai.mtc.MTC; 5 | import com.lai.mtc.mvp.utlis.CommonUtil; 6 | 7 | import java.io.IOException; 8 | 9 | import okhttp3.CacheControl; 10 | import okhttp3.HttpUrl; 11 | import okhttp3.Interceptor; 12 | import okhttp3.Request; 13 | import okhttp3.Response; 14 | 15 | /** 16 | * @author Lai 17 | * @time 2017/9/5 10:23 18 | * @describe describe 19 | */ 20 | 21 | public class RetrofitHelper { 22 | public static String BASE_URL = "http://api.cookacg.com/"; 23 | 24 | 25 | 26 | 27 | } -------------------------------------------------------------------------------- /app/src/main/java/com/lai/mtc/mvp/presenter/ComicsSearchPresenter.java: -------------------------------------------------------------------------------- 1 | package com.lai.mtc.mvp.presenter; 2 | 3 | import com.lai.mtc.api.ComicApi; 4 | import com.lai.mtc.bean.ComicListInfo; 5 | import com.lai.mtc.comm.ApiException; 6 | import com.lai.mtc.comm.HttpRxObserver; 7 | import com.lai.mtc.mvp.base.impl.BasePresenter; 8 | import com.lai.mtc.mvp.contract.ComicsSearchContract; 9 | import com.lai.mtc.mvp.utlis.RxUtlis; 10 | 11 | import javax.inject.Inject; 12 | 13 | /** 14 | * @author Lai 15 | * @time 2018/1/23 16:37 16 | * @describe 搜索P 17 | * @see SimplePresenter 18 | */ 19 | 20 | public class ComicsSearchPresenter extends BasePresenter implements ComicsSearchContract.Model { 21 | 22 | private ComicApi mComicApi; 23 | 24 | @Inject 25 | ComicsSearchPresenter(ComicApi mComicApi) { 26 | this.mComicApi = mComicApi; 27 | } 28 | 29 | @Override 30 | public void search(String name, int pager, final boolean isFresh) { 31 | if (isFresh) { 32 | pager = 1;//下拉刷新默认只请求第一页 33 | mRootView.showLoading(); 34 | } 35 | 36 | mComicApi.getComicsByName(name, pager) 37 | .compose(mRootView.bindToLifecycle()) 38 | .compose(RxUtlis.toMain()) 39 | .onErrorResumeNext(new HttpResultFunction()) 40 | .subscribe(new HttpRxObserver<>(new HttpRxObserver.IResult() { 41 | @Override 42 | public void onSuccess(ComicListInfo comicListInfo) { 43 | if (isFresh) 44 | mRootView.hideLoading(); 45 | mRootView.showList(comicListInfo); 46 | } 47 | 48 | @Override 49 | public void onError(ApiException e) { 50 | mRootView.handleError(e); 51 | } 52 | })); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /app/src/main/java/com/lai/mtc/mvp/presenter/SimplePresenter.java: -------------------------------------------------------------------------------- 1 | package com.lai.mtc.mvp.presenter; 2 | 3 | import com.lai.mtc.mvp.base.impl.BasePresenter; 4 | import com.lai.mtc.mvp.contract.SimpleContract; 5 | 6 | import javax.inject.Inject; 7 | 8 | /** 9 | * @author Lai 10 | * @time 2018/1/23 16:37 11 | * @describe 12 | * 13 | * 如果不懂可以先看看我的关于MVp的文章: 14 | * 15 | * http://blog.csdn.net/a8688555/article/details/79383270 16 | * 17 | * 项目当架构 18 | * 19 | * 关于P层,按照规范来说这里应该还需要实例化一个Model层。通过Model在请求请求或处理数据 20 | * 21 | * 然后Model的实体类可以通过dagger2去管理实例会添加很多的仓库Module。因为有很多的model仅仅只是做网络请求的操作,不太复杂 22 | * 23 | * 我觉得写的东西太多了,所以我这边的就直接省去了M层。直接在P层实现了M的方法。 24 | * 25 | * 如果你举得需要Model层 26 | * 27 | * 你可以参考一下MVPArms开源项目: https://github.com/JessYanCoding/MVPArms 28 | * 29 | * MVPArms项目实例 30 | * https://github.com/GitLqr/LQRBiliBlili 31 | * 32 | */ 33 | 34 | public class SimplePresenter extends BasePresenter implements SimpleContract.Model { 35 | 36 | @Inject 37 | SimplePresenter() { 38 | 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /app/src/main/java/com/lai/mtc/mvp/scope/ActivityScope.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2015 Fernando Cejas Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | /** 17 | * Copyright 2017 JessYan 18 | * 19 | * Licensed under the Apache License, Version 2.0 (the "License"); 20 | * you may not use this file except in compliance with the License. 21 | * You may obtain a copy of the License at 22 | * 23 | * http://www.apache.org/licenses/LICENSE-2.0 24 | * 25 | * Unless required by applicable law or agreed to in writing, software 26 | * distributed under the License is distributed on an "AS IS" BASIS, 27 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 28 | * See the License for the specific language governing permissions and 29 | * limitations under the License. 30 | */ 31 | package com.lai.mtc.mvp.scope; 32 | 33 | import java.lang.annotation.Documented; 34 | import java.lang.annotation.Retention; 35 | 36 | import javax.inject.Scope; 37 | 38 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 39 | 40 | /** 41 | * A scoping annotation to permit objects whose lifetime should 42 | * conform to the life of the activity to be memorized in the 43 | * correct component. 44 | */ 45 | @Scope 46 | @Documented 47 | @Retention(RUNTIME) 48 | public @interface ActivityScope {} 49 | -------------------------------------------------------------------------------- /app/src/main/java/com/lai/mtc/mvp/scope/FragmentScope.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2015 Fernando Cejas Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | /** 17 | * Copyright 2017 JessYan 18 | * 19 | * Licensed under the Apache License, Version 2.0 (the "License"); 20 | * you may not use this file except in compliance with the License. 21 | * You may obtain a copy of the License at 22 | * 23 | * http://www.apache.org/licenses/LICENSE-2.0 24 | * 25 | * Unless required by applicable law or agreed to in writing, software 26 | * distributed under the License is distributed on an "AS IS" BASIS, 27 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 28 | * See the License for the specific language governing permissions and 29 | * limitations under the License. 30 | */ 31 | package com.lai.mtc.mvp.scope; 32 | 33 | import java.lang.annotation.Documented; 34 | import java.lang.annotation.Retention; 35 | 36 | import javax.inject.Scope; 37 | 38 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 39 | 40 | /** 41 | * A scoping annotation to permit objects whose lifetime should 42 | * conform to the life of the fragment to be memorized in the 43 | * correct component. 44 | */ 45 | @Scope 46 | @Documented 47 | @Retention(RUNTIME) 48 | public @interface FragmentScope {} 49 | -------------------------------------------------------------------------------- /app/src/main/java/com/lai/mtc/mvp/ui/cartoon/fragment/CartoonMainFragment.java: -------------------------------------------------------------------------------- 1 | package com.lai.mtc.mvp.ui.cartoon.fragment; 2 | 3 | import android.os.Bundle; 4 | 5 | import com.lai.mtc.mvp.base.impl.BaseFragment; 6 | 7 | /** 8 | * @author Lai 9 | * @time 2018/1/14 15:44 10 | * @describe 主页动漫fragment 11 | */ 12 | 13 | public class CartoonMainFragment extends BaseFragment { 14 | 15 | 16 | @Override 17 | public int getLayoutResId() { 18 | return 0; 19 | } 20 | 21 | @Override 22 | public void finishCreateView(Bundle state) { 23 | 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/java/com/lai/mtc/mvp/ui/comics/adapter/ChapterAdapter.java: -------------------------------------------------------------------------------- 1 | package com.lai.mtc.mvp.ui.comics.adapter; 2 | 3 | import android.support.annotation.Nullable; 4 | import android.support.v4.content.ContextCompat; 5 | import android.util.SparseIntArray; 6 | import android.view.View; 7 | 8 | import com.chad.library.adapter.base.BaseQuickAdapter; 9 | import com.chad.library.adapter.base.BaseViewHolder; 10 | import com.lai.mtc.R; 11 | import com.lai.mtc.bean.ComicListDetail; 12 | import com.lai.mtc.comm.CommonAdapter; 13 | import com.lai.mtc.mvp.utlis.StringUtils; 14 | 15 | import java.util.List; 16 | 17 | /** 18 | * @author Lai 19 | * @time 2018/1/28 16:51 20 | * @describe 漫画预览集数adapter 21 | */ 22 | 23 | public class ChapterAdapter extends CommonAdapter { 24 | 25 | public void setLastPosition(int lastPosition) { 26 | this.lastPosition = lastPosition; 27 | } 28 | 29 | public int getLastPosition() { 30 | return lastPosition; 31 | } 32 | 33 | private int lastPosition = -1; 34 | 35 | public void setIndex(int index) { 36 | this.index = index; 37 | } 38 | 39 | private int index; 40 | 41 | public void setItemClickListener(OnItemClickListener itemClickListener) { 42 | mItemClickListener = itemClickListener; 43 | } 44 | 45 | private OnItemClickListener mItemClickListener; 46 | 47 | public ChapterAdapter(@Nullable List data) { 48 | super(R.layout.comic_item_preview_left, data); 49 | setOnItemChildClickListener(new OnItemChildClickListener() { 50 | @Override 51 | public void onItemChildClick(BaseQuickAdapter adapter, View view, int position) { 52 | view.setBackgroundColor(ContextCompat.getColor(mContext, R.color.colorEEE)); 53 | if (lastPosition != -1 && lastPosition != position) { 54 | View viewByPosition = adapter.getViewByPosition(lastPosition, R.id.tv_name); 55 | if (viewByPosition != null) 56 | viewByPosition.setBackgroundColor(ContextCompat.getColor(mContext, R.color.white)); 57 | ComicListDetail.ChaptersBean item = getItem(position); 58 | if (item != null) { 59 | index = item.getIndex(); 60 | mItemClickListener.onItemClick(adapter, view, position); 61 | } 62 | } 63 | lastPosition = position; 64 | } 65 | }); 66 | } 67 | 68 | @Override 69 | protected void convert(BaseViewHolder baseViewHolder, ComicListDetail.ChaptersBean chaptersBean, int position) { 70 | baseViewHolder.setText(R.id.tv_name, StringUtils.isNull(chaptersBean.getName())) 71 | .addOnClickListener(R.id.tv_name); 72 | if (index == chaptersBean.getIndex()) { 73 | lastPosition = position; 74 | baseViewHolder.setBackgroundColor(R.id.tv_name, ContextCompat.getColor(mContext, R.color.colorEEE)); 75 | } else if (lastPosition != -1 && lastPosition == position) { 76 | baseViewHolder.setBackgroundColor(R.id.tv_name, ContextCompat.getColor(mContext, R.color.colorEEE)); 77 | } else { 78 | baseViewHolder.setBackgroundColor(R.id.tv_name, ContextCompat.getColor(mContext, R.color.white)); 79 | } 80 | } 81 | 82 | /** 83 | * 更新单选 84 | * 85 | * @param currPosition 当前位置 86 | * @param index 位置索引 87 | */ 88 | public void updatePosition(int currPosition, int index) { 89 | View lastView = getViewByPosition(lastPosition, R.id.tv_name); 90 | if (lastView != null) 91 | lastView.setBackgroundColor(ContextCompat.getColor(mContext, R.color.white)); 92 | this.lastPosition = currPosition; 93 | this.index = index; 94 | View currView = getViewByPosition(lastPosition, R.id.tv_name); 95 | if (currView != null) 96 | currView.setBackgroundColor(ContextCompat.getColor(mContext, R.color.colorEEE)); 97 | } 98 | 99 | 100 | } 101 | -------------------------------------------------------------------------------- /app/src/main/java/com/lai/mtc/mvp/ui/comics/adapter/ChapterDetailAdapter.java: -------------------------------------------------------------------------------- 1 | package com.lai.mtc.mvp.ui.comics.adapter; 2 | 3 | import android.content.Intent; 4 | import android.support.annotation.Nullable; 5 | import android.view.View; 6 | 7 | import com.chad.library.adapter.base.BaseQuickAdapter; 8 | import com.chad.library.adapter.base.BaseViewHolder; 9 | import com.lai.library.ButtonStyle; 10 | import com.lai.mtc.R; 11 | import com.lai.mtc.bean.ComicListDetail; 12 | import com.lai.mtc.comm.CommonAdapter; 13 | import com.lai.mtc.dao.RecordDao; 14 | import com.lai.mtc.mvp.ui.comics.activity.ComicPreviewActivity; 15 | import com.lai.mtc.mvp.utlis.StringUtils; 16 | 17 | import java.util.List; 18 | 19 | /** 20 | * @author Lai 21 | * @time 2018/1/28 16:51 22 | * @describe 漫画详情集数adapter 23 | */ 24 | 25 | public class ChapterDetailAdapter extends CommonAdapter { 26 | 27 | private int lastPosition; 28 | 29 | public int getIndex() { 30 | return index; 31 | } 32 | 33 | public void setIndex(int index) { 34 | this.index = index; 35 | } 36 | 37 | private int index; 38 | private RecordDao mRecordDao; 39 | 40 | public void setComicListDetail(ComicListDetail comicListDetail) { 41 | mComicListDetail = comicListDetail; 42 | } 43 | 44 | private ComicListDetail mComicListDetail; 45 | 46 | public ChapterDetailAdapter(@Nullable List data, RecordDao mDao) { 47 | super(R.layout.comic_item_detail_list, data); 48 | init(); 49 | mRecordDao = mDao; 50 | updateOnItemChildClickListener(); 51 | } 52 | 53 | private void updateOnItemChildClickListener() { 54 | setOnItemChildClickListener(new OnItemChildClickListener() { 55 | @Override 56 | public void onItemChildClick(BaseQuickAdapter adapter, View view, int position) { 57 | ButtonStyle buttonStyle = (ButtonStyle) adapter.getViewByPosition(position, R.id.list_item); 58 | if (buttonStyle != null) 59 | buttonStyle.setNormalColor(R.color.colorEEE); 60 | 61 | if (lastPosition != -1 && lastPosition != position) { 62 | ButtonStyle viewByPosition = (ButtonStyle) adapter.getViewByPosition(lastPosition, R.id.list_item); 63 | if (viewByPosition != null) 64 | viewByPosition.setNormalColor(R.color.white); 65 | } 66 | lastPosition = position; 67 | ComicListDetail.ChaptersBean item = getItem(position); 68 | if (item != null) { 69 | mRecordDao.updateRecord(item.getComic_id(), item.getName(), item.getIndex(), position); 70 | Intent intent = new Intent(mContext, ComicPreviewActivity.class); 71 | intent.putExtra("index", item.getIndex()); 72 | intent.putExtra("comicListDetail", mComicListDetail); 73 | mContext.startActivity(intent); 74 | } 75 | } 76 | }); 77 | } 78 | 79 | public void init() { 80 | lastPosition = -1; 81 | index = -1; 82 | } 83 | 84 | @Override 85 | protected void convert(BaseViewHolder baseViewHolder, ComicListDetail.ChaptersBean chaptersBean, int position) { 86 | baseViewHolder.addOnClickListener(R.id.list_item); 87 | ButtonStyle buttonStyle = baseViewHolder.getView(R.id.list_item); 88 | /*if (lastPosition != -1 && lastPosition == position) { 89 | buttonStyle.setNormalColor(R.color.colorEEE); 90 | } else */if (index == chaptersBean.getIndex()) { 91 | lastPosition = position; 92 | buttonStyle.setNormalColor(R.color.colorEEE); 93 | } else { 94 | buttonStyle.setNormalColor(R.color.white); 95 | } 96 | buttonStyle.setText(StringUtils.isNull(chaptersBean.getName())); 97 | } 98 | 99 | /** 100 | * 更新单选 101 | * 102 | * @param index 位置索引 103 | */ 104 | public void updatePosition(int currPosition, int index) { 105 | ButtonStyle lastView = (ButtonStyle) getViewByPosition(lastPosition, R.id.list_item); 106 | if (lastView != null) 107 | lastView.setNormalColor(R.color.white); 108 | this.index = index; 109 | lastPosition = -1; 110 | notifyItemChanged(currPosition); 111 | if (currPosition != 0) { 112 | notifyItemChanged(currPosition - 1); 113 | } 114 | } 115 | 116 | 117 | } 118 | -------------------------------------------------------------------------------- /app/src/main/java/com/lai/mtc/mvp/ui/comics/adapter/MultiNumberAdapter.java: -------------------------------------------------------------------------------- 1 | package com.lai.mtc.mvp.ui.comics.adapter; 2 | 3 | import android.support.annotation.Nullable; 4 | 5 | import com.chad.library.adapter.base.BaseQuickAdapter; 6 | import com.chad.library.adapter.base.BaseViewHolder; 7 | import com.chad.library.adapter.base.util.MultiTypeDelegate; 8 | import com.lai.mtc.R; 9 | import com.lai.mtc.bean.ComicListDetail; 10 | 11 | import java.util.List; 12 | 13 | /** 14 | * @author Lai 15 | * @time 2018/1/24 15:24 16 | * @describe describe 17 | */ 18 | 19 | public class MultiNumberAdapter extends BaseQuickAdapter { 20 | 21 | public MultiNumberAdapter(int layoutResId, @Nullable List data) { 22 | super(layoutResId, data); 23 | 24 | setMultiTypeDelegate(new MultiTypeDelegate() { 25 | @Override 26 | protected int getItemType(ComicListDetail.ChaptersBean entity) { 27 | //根据你的实体类来判断布局类型 28 | return entity.getItemType(); 29 | } 30 | }); 31 | //Step.2 32 | getMultiTypeDelegate() 33 | .registerItemType(ComicListDetail.ChaptersBean.NORMAL, R.layout.comic_item_detail_list) 34 | .registerItemType(ComicListDetail.ChaptersBean.BOTTOM, R.layout.comic_item_detail_list); 35 | } 36 | 37 | @Override 38 | protected void convert(BaseViewHolder helper, ComicListDetail.ChaptersBean item) { 39 | 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /app/src/main/java/com/lai/mtc/mvp/ui/comics/dialog/ModuleDialog.java: -------------------------------------------------------------------------------- 1 | package com.lai.mtc.mvp.ui.comics.dialog; 2 | 3 | import android.app.Dialog; 4 | import android.content.Context; 5 | import android.os.Bundle; 6 | import android.support.annotation.NonNull; 7 | import android.view.LayoutInflater; 8 | import android.view.View; 9 | import android.widget.RadioButton; 10 | 11 | import com.lai.mtc.R; 12 | import com.lai.mtc.comm.Parameter; 13 | import com.lai.mtc.mvp.utlis.SPUtils; 14 | 15 | /** 16 | * @author Lai 17 | * @time 2018/1/29 22:44 18 | * @describe describe 19 | */ 20 | 21 | public class ModuleDialog extends Dialog { 22 | 23 | private Context mContext; 24 | private View mView; 25 | private RadioButton mCbPull; 26 | private RadioButton mCbPager; 27 | 28 | public void setOnClickListener(View.OnClickListener onClickListener) { 29 | mOnClickListener = onClickListener; 30 | } 31 | 32 | private View.OnClickListener mOnClickListener; 33 | 34 | public ModuleDialog(@NonNull Context context) { 35 | super(context); 36 | mContext = context; 37 | } 38 | 39 | @Override 40 | protected void onCreate(Bundle savedInstanceState) { 41 | super.onCreate(savedInstanceState); 42 | mView = LayoutInflater.from(mContext).inflate(R.layout.pop_module, null); 43 | setContentView(mView); 44 | mCbPull = mView.findViewById(R.id.rb_pull); 45 | mCbPager = mView.findViewById(R.id.rb_pager); 46 | init(); 47 | } 48 | 49 | private void init() { 50 | int module = SPUtils.getInstance(Parameter.SP_CONFIG).getInt(Parameter.SP_PREVIEW_MODE, 0); 51 | if (module == 0) 52 | mCbPull.setChecked(true); 53 | else 54 | mCbPager.setChecked(true); 55 | 56 | mView.findViewById(R.id.btn_no).setOnClickListener(new View.OnClickListener() { 57 | @Override 58 | public void onClick(View v) { 59 | dismiss(); 60 | } 61 | }); 62 | mView.findViewById(R.id.btn_yes).setOnClickListener(new View.OnClickListener() { 63 | @Override 64 | public void onClick(View v) { 65 | int module = mCbPager.isChecked() ? 1 : 0; 66 | SPUtils.getInstance(Parameter.SP_CONFIG).put(Parameter.SP_PREVIEW_MODE, module); 67 | if (mOnClickListener != null) 68 | mOnClickListener.onClick(v); 69 | dismiss(); 70 | } 71 | }); 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /app/src/main/java/com/lai/mtc/mvp/utlis/ActivityUtils.java: -------------------------------------------------------------------------------- 1 | package com.lai.mtc.mvp.utlis; 2 | 3 | import android.app.Activity; 4 | import android.support.annotation.NonNull; 5 | import android.support.v4.app.Fragment; 6 | import android.support.v4.app.FragmentManager; 7 | import android.support.v4.app.FragmentTransaction; 8 | 9 | import java.util.LinkedList; 10 | import java.util.List; 11 | 12 | /** 13 | * 与Activity的基本操作相关的工具类 14 | */ 15 | public class ActivityUtils { 16 | 17 | private static List mActivities = new LinkedList<>(); 18 | 19 | /** 20 | * 将Fragment附加到Activity中 21 | * @NonNull:指明一个参数,字段或者方法的返回值不可以为null; 22 | */ 23 | public static void addFragmentToActivity(@NonNull FragmentManager fragmentManager, 24 | @NonNull Fragment fragment, int frameId) { 25 | checkNotNull(fragmentManager); 26 | checkNotNull(fragment); 27 | FragmentTransaction transaction = fragmentManager.beginTransaction(); 28 | transaction.add(frameId, fragment); 29 | transaction.commit(); 30 | } 31 | 32 | public static void showFragmentOfActivity(@NonNull FragmentManager fragmentManager, 33 | @NonNull Fragment fragment) { 34 | checkNotNull(fragmentManager); 35 | checkNotNull(fragment); 36 | FragmentTransaction transaction = fragmentManager.beginTransaction(); 37 | transaction.show(fragment); 38 | transaction.commit(); 39 | } 40 | 41 | public static void hideFragmentOfActivity(@NonNull FragmentManager fragmentManager, 42 | @NonNull Fragment fragment) { 43 | checkNotNull(fragmentManager); 44 | checkNotNull(fragment); 45 | FragmentTransaction transaction = fragmentManager.beginTransaction(); 46 | transaction.hide(fragment); 47 | transaction.commit(); 48 | } 49 | 50 | /** 51 | * 添加Activity到自己的任务管理栈中 52 | * 53 | * @param activity 被压入栈的activity 54 | */ 55 | public static void addActivity(@NonNull Activity activity) { 56 | if (mActivities == null) { 57 | mActivities = new LinkedList<>(); 58 | } 59 | mActivities.add(activity); 60 | } 61 | 62 | /** 63 | * 弹出任务管理栈中的Activity 64 | */ 65 | public static void removeActivity(@NonNull Activity activity) { 66 | if (mActivities != null && mActivities.contains(activity)) { 67 | mActivities.remove(activity); 68 | } 69 | } 70 | 71 | /** 72 | * 结束所有的Activity,退出程序 73 | */ 74 | public static void removeAllActivity() { 75 | if (mActivities != null) { 76 | synchronized (ActivityUtils.class) { 77 | for (Activity activity : mActivities) { 78 | activity.finish(); 79 | } 80 | } 81 | mActivities.clear(); 82 | } 83 | } 84 | 85 | /** 86 | * 默认的判断引用非空方法 87 | * 88 | * @param reference 89 | * @param 90 | * @return 91 | */ 92 | public static T checkNotNull(T reference) { 93 | if (reference == null) { 94 | throw new NullPointerException(); 95 | } 96 | return reference; 97 | } 98 | 99 | } 100 | -------------------------------------------------------------------------------- /app/src/main/java/com/lai/mtc/mvp/utlis/CommonUtil.java: -------------------------------------------------------------------------------- 1 | package com.lai.mtc.mvp.utlis; 2 | 3 | import android.content.Context; 4 | import android.net.ConnectivityManager; 5 | import android.net.NetworkInfo; 6 | 7 | import com.lai.mtc.comm.Parameter; 8 | 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | 12 | /** 13 | * Created by hcc on 16/8/4 21:18 14 | * 100332338@qq.com 15 | *

16 | * 通用工具类 17 | */ 18 | public class CommonUtil { 19 | 20 | /** 21 | * 检查是否有网络 22 | */ 23 | public static boolean isNetworkAvailable(Context context) { 24 | NetworkInfo info = getNetworkInfo(context); 25 | return info != null && info.isAvailable(); 26 | } 27 | 28 | 29 | /** 30 | * 检查是否是WIFI 31 | */ 32 | public static boolean isWifi(Context context) { 33 | NetworkInfo info = getNetworkInfo(context); 34 | if (info != null) { 35 | if (info.getType() == ConnectivityManager.TYPE_WIFI) { 36 | return true; 37 | } 38 | } 39 | return false; 40 | } 41 | 42 | 43 | /** 44 | * 检查是否是移动网络 45 | */ 46 | public static boolean isMobile(Context context) { 47 | NetworkInfo info = getNetworkInfo(context); 48 | if (info != null) { 49 | if (info.getType() == ConnectivityManager.TYPE_MOBILE) { 50 | return true; 51 | } 52 | } 53 | return false; 54 | } 55 | 56 | private static NetworkInfo getNetworkInfo(Context context) { 57 | ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); 58 | return cm.getActiveNetworkInfo(); 59 | } 60 | 61 | 62 | /** 63 | * 以52为分页标准,切割最后 64 | * 65 | * @param list 66 | * @return 67 | */ 68 | public static List transformationLastList(List list) { 69 | if (!ListUtils.isEmpty(list) && list.size() > Parameter.PAGING_STANDARD) { 70 | return new ArrayList<>(list.subList(Parameter.PAGING_STANDARD, list.size())); 71 | } 72 | return null; 73 | } 74 | 75 | /** 76 | * 以52为分页标准,切割最前 77 | * 78 | * @param list 79 | * @return 80 | */ 81 | public static List transformationStartList(List list) { 82 | if (!ListUtils.isEmpty(list) && list.size() > Parameter.PAGING_STANDARD) { 83 | return new ArrayList<>(list.subList(0, Parameter.PAGING_STANDARD)); 84 | } 85 | return null; 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /app/src/main/java/com/lai/mtc/mvp/utlis/DensityUtil.java: -------------------------------------------------------------------------------- 1 | package com.lai.mtc.mvp.utlis; 2 | 3 | import android.content.Context; 4 | import android.util.TypedValue; 5 | 6 | /** 7 | * @author Lai 8 | * @time 2018/1/23 15:38 9 | * @describe describe 10 | */ 11 | 12 | public class DensityUtil { 13 | private DensityUtil() { 14 | throw new UnsupportedOperationException("cannot be instantiated"); 15 | } 16 | 17 | /** 18 | * dp转px 19 | */ 20 | public static int dp2px(Context context, float dpVal) { 21 | return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 22 | dpVal, context.getResources().getDisplayMetrics()); 23 | } 24 | 25 | /** 26 | * sp转px 27 | */ 28 | public static int sp2px(Context context, float spVal) { 29 | return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 30 | spVal, context.getResources().getDisplayMetrics()); 31 | } 32 | 33 | /** 34 | * px转dp 35 | */ 36 | public static float px2dp(Context context, float pxVal) { 37 | final float scale = context.getResources().getDisplayMetrics().density; 38 | return (pxVal / scale); 39 | } 40 | 41 | /** 42 | * px转sp 43 | */ 44 | public static float px2sp(Context context, float pxVal) { 45 | return (pxVal / context.getResources().getDisplayMetrics().scaledDensity); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /app/src/main/java/com/lai/mtc/mvp/utlis/IPopMenu.java: -------------------------------------------------------------------------------- 1 | package com.lai.mtc.mvp.utlis; 2 | 3 | /** 4 | * @author Lai 5 | * @time 2018/1/23 22:26 6 | * @describe describe 7 | */ 8 | public interface IPopMenu { 9 | String getName(); 10 | 11 | int getId(); 12 | } 13 | -------------------------------------------------------------------------------- /app/src/main/java/com/lai/mtc/mvp/utlis/KeyBoardUtils.java: -------------------------------------------------------------------------------- 1 | package com.lai.mtc.mvp.utlis; 2 | 3 | import android.content.Context; 4 | import android.view.inputmethod.InputMethodManager; 5 | import android.widget.EditText; 6 | 7 | /** 8 | * @author Lai 9 | * @time 2018/2/10 18:49 10 | * @describe describe 11 | */ 12 | 13 | public class KeyBoardUtils { 14 | public static void openKeyboard(Context context, EditText editText) { 15 | InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE); 16 | if (imm != null && editText != null) { 17 | imm.showSoftInput(editText, InputMethodManager.RESULT_SHOWN); 18 | imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, InputMethodManager.HIDE_IMPLICIT_ONLY); 19 | } 20 | } 21 | 22 | public static void closeKeyboard(Context context, EditText editText) { 23 | InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE); 24 | if (imm != null && editText != null && editText.getWindowToken() != null) 25 | imm.hideSoftInputFromWindow(editText.getWindowToken(), 0); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/src/main/java/com/lai/mtc/mvp/utlis/ListUtils.java: -------------------------------------------------------------------------------- 1 | package com.lai.mtc.mvp.utlis; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * List相关的辅助类 7 | * Created by chenmingzhen on 16-6-1. 8 | */ 9 | public class ListUtils { 10 | /** 11 | * 获取list大小 12 | * 13 | * @param sourceList 14 | * @return sourceList 返回list的大小, 若是null或者空的话返回 0 15 | */ 16 | public static int getSize(List sourceList) { 17 | return null == sourceList ? 0 : sourceList.size(); 18 | } 19 | 20 | /** 21 | * 判断list是否为空 22 | * 23 | * @param sourceList 24 | * @return 是否为空 25 | */ 26 | public static boolean isEmpty(List sourceList) { 27 | return (null == sourceList || 0 == sourceList.size()); 28 | } 29 | 30 | 31 | /** 32 | * 返回不多于最大数限制的列表元素个数 33 | * 34 | * @param list 35 | * @param maxNum 36 | * @param 37 | * @return 38 | */ 39 | public static List atMost(List list, int maxNum) { 40 | if (ListUtils.isEmpty(list)) { 41 | return null; 42 | } 43 | if (list.size() > maxNum) { 44 | return list.subList(0, maxNum); 45 | } else { 46 | return list; 47 | } 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /app/src/main/java/com/lai/mtc/mvp/utlis/PopupMenuUtil.java: -------------------------------------------------------------------------------- 1 | package com.lai.mtc.mvp.utlis; 2 | 3 | import android.content.Context; 4 | import android.support.v7.widget.PopupMenu; 5 | import android.view.Menu; 6 | import android.view.View; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * @author Lai 12 | * @time 2018/1/23 22:16 13 | * @describe describe 14 | */ 15 | 16 | public class PopupMenuUtil { 17 | 18 | 19 | public static void showPopupMenuList(Context context, List data, View tagView, PopupMenu.OnMenuItemClickListener listener) { 20 | // 这里的view代表popupMenu需要依附的view 21 | PopupMenu popupMenu = new PopupMenu(context, tagView); 22 | for (int i = 0; i < data.size(); i++) 23 | popupMenu.getMenu().add(Menu.NONE, data.get(i).getId(), i, data.get(i).getName()); 24 | // popupMenu.getMenuInflater().inflate(R.menu.sample_menu, popupMenu.getMenu()); 25 | popupMenu.show(); 26 | // 通过上面这几行代码,就可以把控件显示出来了 27 | popupMenu.setOnMenuItemClickListener(listener); 28 | 29 | popupMenu.setOnDismissListener(new PopupMenu.OnDismissListener() { 30 | @Override 31 | public void onDismiss(PopupMenu menu) { 32 | // 控件消失时的事件 33 | 34 | } 35 | }); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /app/src/main/java/com/lai/mtc/mvp/utlis/RxUtlis.java: -------------------------------------------------------------------------------- 1 | package com.lai.mtc.mvp.utlis; 2 | 3 | import android.support.v4.app.Fragment; 4 | 5 | import com.trello.rxlifecycle2.LifecycleProvider; 6 | import com.trello.rxlifecycle2.LifecycleTransformer; 7 | import com.trello.rxlifecycle2.android.ActivityEvent; 8 | 9 | import org.reactivestreams.Publisher; 10 | 11 | import io.reactivex.Flowable; 12 | import io.reactivex.FlowableTransformer; 13 | import io.reactivex.Observable; 14 | import io.reactivex.ObservableSource; 15 | import io.reactivex.ObservableTransformer; 16 | import io.reactivex.android.schedulers.AndroidSchedulers; 17 | import io.reactivex.schedulers.Schedulers; 18 | 19 | /** 20 | * @author Lai 21 | * @time 2017/9/18 17:32 22 | * @describe describe 23 | */ 24 | 25 | public class RxUtlis { 26 | /** 27 | * 统一线程处理 28 | * 29 | * @param 30 | * @return 31 | */ 32 | public static ObservableTransformer bind(final Fragment mLifecycleProvider) { 33 | final LifecycleProvider lifecycleProvider = (LifecycleProvider) mLifecycleProvider; 34 | return new ObservableTransformer() { 35 | @Override 36 | public ObservableSource apply(Observable upstream) { 37 | return upstream.subscribeOn(Schedulers.io()) 38 | .observeOn(AndroidSchedulers.mainThread()).compose(lifecycleProvider.bindToLifecycle()); 39 | } 40 | }; 41 | } 42 | 43 | public static ObservableTransformer toMain() { 44 | return new ObservableTransformer() { 45 | @Override 46 | public ObservableSource apply(Observable upstream) { 47 | return upstream.subscribeOn(Schedulers.io()) 48 | .observeOn(AndroidSchedulers.mainThread()); 49 | } 50 | }; 51 | } 52 | 53 | 54 | public static FlowableTransformer toFlowableMain() { 55 | 56 | return new FlowableTransformer() { 57 | 58 | @Override 59 | public Publisher apply(Flowable upstream) { 60 | return upstream.subscribeOn(Schedulers.io()) 61 | .observeOn(AndroidSchedulers.mainThread()); 62 | } 63 | }; 64 | } 65 | 66 | public interface Lifecycle{ 67 | LifecycleTransformer bindToLifecycle(); 68 | } 69 | 70 | public static ObservableTransformer handler(final Lifecycle lifecycle) { 71 | return new ObservableTransformer() { 72 | @Override 73 | public ObservableSource apply(Observable upstream) { 74 | return upstream.compose(RxUtlis.toMain()).compose(lifecycle.bindToLifecycle()); 75 | } 76 | }; 77 | } 78 | 79 | 80 | 81 | 82 | 83 | } 84 | -------------------------------------------------------------------------------- /app/src/main/java/com/lai/mtc/mvp/utlis/StringUtils.java: -------------------------------------------------------------------------------- 1 | package com.lai.mtc.mvp.utlis; 2 | 3 | import android.text.TextUtils; 4 | 5 | /** 6 | * @author Lai 7 | * @time 2018/1/15 16:00 8 | * @describe describe 9 | */ 10 | 11 | public class StringUtils { 12 | /** 13 | * 为空返回空字符串 14 | * @param src 字符串 15 | * @return 为空返回空字符串 16 | */ 17 | public static String isNull(String src) { 18 | return TextUtils.isEmpty(src) ? "" : src; 19 | } 20 | 21 | 22 | /** 23 | * 为空返回自定义字符串 24 | * @param src 字符串 25 | * @param defaultStr 为空返回的字符串 26 | * @return 27 | */ 28 | public static String isNull(String src,String defaultStr) { 29 | return TextUtils.isEmpty(src) ? defaultStr : src; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /app/src/main/java/com/lai/mtc/mvp/utlis/glide/GlideCacheUtil.java: -------------------------------------------------------------------------------- 1 | package com.lai.mtc.mvp.utlis.glide; 2 | 3 | import android.content.Context; 4 | import android.os.Looper; 5 | import android.text.TextUtils; 6 | 7 | import java.io.File; 8 | 9 | /** 10 | * @author Lai 11 | * @time 2018/2/2 23:09 12 | * @describe describe 13 | */ 14 | 15 | public class GlideCacheUtil { 16 | private static GlideCacheUtil inst; 17 | 18 | public static GlideCacheUtil getInstance() { 19 | if (inst == null) { 20 | inst = new GlideCacheUtil(); 21 | } 22 | return inst; 23 | } 24 | 25 | /** 26 | * 清除图片磁盘缓存 27 | */ 28 | public void clearImageDiskCache(final Context context) { 29 | try { 30 | if (Looper.myLooper() == Looper.getMainLooper()) { 31 | new Thread(new Runnable() { 32 | @Override 33 | public void run() { 34 | GlideApp.get(context).clearDiskCache(); 35 | } 36 | }).start(); 37 | } else { 38 | GlideApp.get(context).clearDiskCache(); 39 | } 40 | } catch (Exception e) { 41 | e.printStackTrace(); 42 | } 43 | } 44 | 45 | /** 46 | * 清除图片内存缓存 47 | */ 48 | public void clearImageMemoryCache(Context context) { 49 | try { 50 | if (Looper.myLooper() == Looper.getMainLooper()) { //只能在主线程执行 51 | GlideApp.get(context).clearMemory(); 52 | } 53 | } catch (Exception e) { 54 | e.printStackTrace(); 55 | } 56 | } 57 | 58 | /** 59 | * 清除图片所有缓存 60 | */ 61 | public void clearImageAllCache(Context context) { 62 | clearImageDiskCache(context); 63 | clearImageMemoryCache(context); 64 | } 65 | /** 66 | * 删除指定目录下的文件,这里用于缓存的删除 67 | * 68 | * @param filePath filePath 69 | * @param deleteThisPath deleteThisPath 70 | */ 71 | private void deleteFolderFile(String filePath, boolean deleteThisPath) { 72 | if (!TextUtils.isEmpty(filePath)) { 73 | try { 74 | File file = new File(filePath); 75 | if (file.isDirectory()) { 76 | File files[] = file.listFiles(); 77 | for (File file1 : files) { 78 | deleteFolderFile(file1.getAbsolutePath(), true); 79 | } 80 | } 81 | if (deleteThisPath) { 82 | if (!file.isDirectory()) { 83 | file.delete(); 84 | } else { 85 | if (file.listFiles().length == 0) { 86 | file.delete(); 87 | } 88 | } 89 | } 90 | } catch (Exception e) { 91 | e.printStackTrace(); 92 | } 93 | } 94 | } 95 | 96 | } 97 | -------------------------------------------------------------------------------- /app/src/main/java/com/lai/mtc/mvp/utlis/glide/MyAppGlideModule.java: -------------------------------------------------------------------------------- 1 | package com.lai.mtc.mvp.utlis.glide; 2 | 3 | import android.content.Context; 4 | 5 | import com.bumptech.glide.Glide; 6 | import com.bumptech.glide.GlideBuilder; 7 | import com.bumptech.glide.Registry; 8 | import com.bumptech.glide.annotation.GlideModule; 9 | import com.bumptech.glide.integration.okhttp3.OkHttpUrlLoader; 10 | import com.bumptech.glide.load.DecodeFormat; 11 | import com.bumptech.glide.load.model.GlideUrl; 12 | import com.bumptech.glide.module.AppGlideModule; 13 | import com.bumptech.glide.request.RequestOptions; 14 | 15 | import java.io.InputStream; 16 | 17 | import okhttp3.OkHttpClient; 18 | 19 | /** 20 | * @author Lai 21 | * @time 2018/1/17 15:09 22 | * @describe describe 23 | */ 24 | 25 | @GlideModule 26 | public final class MyAppGlideModule extends AppGlideModule { 27 | @Override 28 | public void applyOptions(Context context, GlideBuilder builder) { 29 | super.applyOptions(context, builder); 30 | /* * Glide也能使用ARGB_8888的图片格式 * 虽然图片质量变好了,但同时内存开销也会明显增大 */ 31 | RequestOptions defaultRequestOptions = new RequestOptions().format(DecodeFormat.PREFER_ARGB_8888); 32 | builder.setDefaultRequestOptions(defaultRequestOptions); 33 | } 34 | 35 | @Override 36 | public void registerComponents(Context context, Glide glide, Registry registry) { 37 | OkHttpClient client = UnsafeOkHttpClient.getUnsafeOkHttpClient(); 38 | registry.replace(GlideUrl.class, InputStream.class, new OkHttpUrlLoader.Factory(client)); 39 | } 40 | } -------------------------------------------------------------------------------- /app/src/main/java/com/lai/mtc/mvp/utlis/glide/UnsafeOkHttpClient.java: -------------------------------------------------------------------------------- 1 | package com.lai.mtc.mvp.utlis.glide; 2 | 3 | import java.io.IOException; 4 | import java.security.cert.CertificateException; 5 | import java.util.concurrent.TimeUnit; 6 | 7 | import javax.net.ssl.HostnameVerifier; 8 | import javax.net.ssl.SSLContext; 9 | import javax.net.ssl.SSLSession; 10 | import javax.net.ssl.SSLSocketFactory; 11 | import javax.net.ssl.TrustManager; 12 | import javax.net.ssl.X509TrustManager; 13 | 14 | import okhttp3.Interceptor; 15 | import okhttp3.OkHttpClient; 16 | import okhttp3.Request; 17 | import okhttp3.Response; 18 | 19 | /** 20 | * @author Lai 21 | * @time 2018/1/31 15:55 22 | * @describe describe 23 | */ 24 | 25 | public class UnsafeOkHttpClient { 26 | public static OkHttpClient getUnsafeOkHttpClient() { 27 | try { 28 | // Create a trust manager that does not validate certificate chains 29 | final TrustManager[] trustAllCerts = new TrustManager[]{ 30 | new X509TrustManager() { 31 | @Override 32 | public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException { 33 | } 34 | 35 | @Override 36 | public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException { 37 | } 38 | 39 | @Override 40 | public java.security.cert.X509Certificate[] getAcceptedIssuers() { 41 | return new java.security.cert.X509Certificate[]{}; 42 | } 43 | } 44 | }; 45 | 46 | // Install the all-trusting trust manager 47 | final SSLContext sslContext = SSLContext.getInstance("SSL"); 48 | sslContext.init(null, trustAllCerts, new java.security.SecureRandom()); 49 | 50 | // Create an ssl socket factory with our all-trusting manager 51 | final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory(); 52 | 53 | OkHttpClient.Builder builder = new OkHttpClient.Builder(); 54 | builder.sslSocketFactory(sslSocketFactory, (X509TrustManager) trustAllCerts[0]); 55 | builder.hostnameVerifier(new HostnameVerifier() { 56 | @Override 57 | public boolean verify(String hostname, SSLSession session) { 58 | return true; 59 | } 60 | }); 61 | 62 | builder.connectTimeout(20, TimeUnit.SECONDS); 63 | builder.readTimeout(20,TimeUnit.SECONDS); 64 | builder.addInterceptor(new Interceptor() { 65 | @Override 66 | public Response intercept(Chain chain) throws IOException { 67 | Request originalRequest = chain.request(); 68 | 69 | Request authorised = originalRequest.newBuilder() 70 | .header("Referer", " http://manhua.dmzj.com/zhiyoushenzhidao/27751.shtml") 71 | .build(); 72 | return chain.proceed(authorised); 73 | } 74 | }); 75 | OkHttpClient okHttpClient = builder.build(); 76 | return okHttpClient; 77 | } catch (Exception e) { 78 | throw new RuntimeException(e); 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_action_back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laishujie/Comic-MTC/91eb78a262971506fdf2cd819550c56cef24350a/app/src/main/res/drawable-hdpi/ic_action_back.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_action_clean.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laishujie/Comic-MTC/91eb78a262971506fdf2cd819550c56cef24350a/app/src/main/res/drawable-hdpi/ic_action_clean.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_brightness.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laishujie/Comic-MTC/91eb78a262971506fdf2cd819550c56cef24350a/app/src/main/res/drawable-hdpi/ic_brightness.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_change.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laishujie/Comic-MTC/91eb78a262971506fdf2cd819550c56cef24350a/app/src/main/res/drawable-hdpi/ic_change.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_label_outline_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laishujie/Comic-MTC/91eb78a262971506fdf2cd819550c56cef24350a/app/src/main/res/drawable-hdpi/ic_label_outline_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laishujie/Comic-MTC/91eb78a262971506fdf2cd819550c56cef24350a/app/src/main/res/drawable-hdpi/ic_menu.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_module.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laishujie/Comic-MTC/91eb78a262971506fdf2cd819550c56cef24350a/app/src/main/res/drawable-hdpi/ic_module.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laishujie/Comic-MTC/91eb78a262971506fdf2cd819550c56cef24350a/app/src/main/res/drawable-hdpi/ic_search.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_sort.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laishujie/Comic-MTC/91eb78a262971506fdf2cd819550c56cef24350a/app/src/main/res/drawable-hdpi/ic_sort.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_action_back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laishujie/Comic-MTC/91eb78a262971506fdf2cd819550c56cef24350a/app/src/main/res/drawable-mdpi/ic_action_back.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_action_clean.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laishujie/Comic-MTC/91eb78a262971506fdf2cd819550c56cef24350a/app/src/main/res/drawable-mdpi/ic_action_clean.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_brightness.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laishujie/Comic-MTC/91eb78a262971506fdf2cd819550c56cef24350a/app/src/main/res/drawable-mdpi/ic_brightness.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_change.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laishujie/Comic-MTC/91eb78a262971506fdf2cd819550c56cef24350a/app/src/main/res/drawable-mdpi/ic_change.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_label_outline_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laishujie/Comic-MTC/91eb78a262971506fdf2cd819550c56cef24350a/app/src/main/res/drawable-mdpi/ic_label_outline_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laishujie/Comic-MTC/91eb78a262971506fdf2cd819550c56cef24350a/app/src/main/res/drawable-mdpi/ic_menu.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_module.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laishujie/Comic-MTC/91eb78a262971506fdf2cd819550c56cef24350a/app/src/main/res/drawable-mdpi/ic_module.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laishujie/Comic-MTC/91eb78a262971506fdf2cd819550c56cef24350a/app/src/main/res/drawable-mdpi/ic_search.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_sort.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laishujie/Comic-MTC/91eb78a262971506fdf2cd819550c56cef24350a/app/src/main/res/drawable-mdpi/ic_sort.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_action_back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laishujie/Comic-MTC/91eb78a262971506fdf2cd819550c56cef24350a/app/src/main/res/drawable-xhdpi/ic_action_back.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_action_clean.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laishujie/Comic-MTC/91eb78a262971506fdf2cd819550c56cef24350a/app/src/main/res/drawable-xhdpi/ic_action_clean.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_brightness.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laishujie/Comic-MTC/91eb78a262971506fdf2cd819550c56cef24350a/app/src/main/res/drawable-xhdpi/ic_brightness.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_change.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laishujie/Comic-MTC/91eb78a262971506fdf2cd819550c56cef24350a/app/src/main/res/drawable-xhdpi/ic_change.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_dashboard_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laishujie/Comic-MTC/91eb78a262971506fdf2cd819550c56cef24350a/app/src/main/res/drawable-xhdpi/ic_dashboard_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_label_outline_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laishujie/Comic-MTC/91eb78a262971506fdf2cd819550c56cef24350a/app/src/main/res/drawable-xhdpi/ic_label_outline_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_line_weight_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laishujie/Comic-MTC/91eb78a262971506fdf2cd819550c56cef24350a/app/src/main/res/drawable-xhdpi/ic_line_weight_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laishujie/Comic-MTC/91eb78a262971506fdf2cd819550c56cef24350a/app/src/main/res/drawable-xhdpi/ic_menu.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_module.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laishujie/Comic-MTC/91eb78a262971506fdf2cd819550c56cef24350a/app/src/main/res/drawable-xhdpi/ic_module.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laishujie/Comic-MTC/91eb78a262971506fdf2cd819550c56cef24350a/app/src/main/res/drawable-xhdpi/ic_round.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laishujie/Comic-MTC/91eb78a262971506fdf2cd819550c56cef24350a/app/src/main/res/drawable-xhdpi/ic_search.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_sort.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laishujie/Comic-MTC/91eb78a262971506fdf2cd819550c56cef24350a/app/src/main/res/drawable-xhdpi/ic_sort.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/img_cover_default.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laishujie/Comic-MTC/91eb78a262971506fdf2cd819550c56cef24350a/app/src/main/res/drawable-xhdpi/img_cover_default.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/bg_shadow2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laishujie/Comic-MTC/91eb78a262971506fdf2cd819550c56cef24350a/app/src/main/res/drawable-xxhdpi/bg_shadow2.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_action_back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laishujie/Comic-MTC/91eb78a262971506fdf2cd819550c56cef24350a/app/src/main/res/drawable-xxhdpi/ic_action_back.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_action_clean.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laishujie/Comic-MTC/91eb78a262971506fdf2cd819550c56cef24350a/app/src/main/res/drawable-xxhdpi/ic_action_clean.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_brightness.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laishujie/Comic-MTC/91eb78a262971506fdf2cd819550c56cef24350a/app/src/main/res/drawable-xxhdpi/ic_brightness.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_change.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laishujie/Comic-MTC/91eb78a262971506fdf2cd819550c56cef24350a/app/src/main/res/drawable-xxhdpi/ic_change.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_dashboard_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laishujie/Comic-MTC/91eb78a262971506fdf2cd819550c56cef24350a/app/src/main/res/drawable-xxhdpi/ic_dashboard_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_label_outline_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laishujie/Comic-MTC/91eb78a262971506fdf2cd819550c56cef24350a/app/src/main/res/drawable-xxhdpi/ic_label_outline_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_line_weight_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laishujie/Comic-MTC/91eb78a262971506fdf2cd819550c56cef24350a/app/src/main/res/drawable-xxhdpi/ic_line_weight_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laishujie/Comic-MTC/91eb78a262971506fdf2cd819550c56cef24350a/app/src/main/res/drawable-xxhdpi/ic_menu.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_module.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laishujie/Comic-MTC/91eb78a262971506fdf2cd819550c56cef24350a/app/src/main/res/drawable-xxhdpi/ic_module.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laishujie/Comic-MTC/91eb78a262971506fdf2cd819550c56cef24350a/app/src/main/res/drawable-xxhdpi/ic_search.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_sort.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laishujie/Comic-MTC/91eb78a262971506fdf2cd819550c56cef24350a/app/src/main/res/drawable-xxhdpi/ic_sort.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/img_shelf_other.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laishujie/Comic-MTC/91eb78a262971506fdf2cd819550c56cef24350a/app/src/main/res/drawable-xxhdpi/img_shelf_other.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_label_outline_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laishujie/Comic-MTC/91eb78a262971506fdf2cd819550c56cef24350a/app/src/main/res/drawable-xxxhdpi/ic_label_outline_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_label_outline_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/laishujie/Comic-MTC/91eb78a262971506fdf2cd819550c56cef24350a/app/src/main/res/drawable-xxxhdpi/ic_label_outline_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_item_1.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/seek_thumb.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/seekbar_progress_drawable.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/shape_pop_checkaddshelf_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 17 | 18 | 24 | 25 | 37 | 38 | 39 | 44 | 45 | 52 | 53 | 54 | 55 | 60 | 61 | 72 | 73 | 79 | 80 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /app/src/main/res/layout/base_title.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 13 | 14 | 25 | 26 | 27 | 32 | 33 | 37 | 38 | 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /app/src/main/res/layout/book_layout_item.xml: -------------------------------------------------------------------------------- 1 | 9 | 10 | 22 | 23 | 29 | 30 | 31 | 39 | 40 | 47 | 48 | 49 | 55 | 56 | 61 | 62 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 84 | 85 | 95 | -------------------------------------------------------------------------------- /app/src/main/res/layout/comic_activity_preview.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | 14 | 15 | 16 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 43 | 44 | -------------------------------------------------------------------------------- /app/src/main/res/layout/comic_activity_preview_bottom_menu.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 15 | 16 | 23 | 24 | 31 | 38 | 39 | 45 | 46 | 47 | 48 | 52 | 53 | 64 | 65 | 76 | 77 | 89 | 90 | 101 | 102 | 103 | 104 | 105 | -------------------------------------------------------------------------------- /app/src/main/res/layout/comic_activity_preview_left_menu.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 14 | 15 | 28 | 29 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /app/src/main/res/layout/comic_activity_search.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 11 | 19 | 20 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /app/src/main/res/layout/comic_dialog_search.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 15 | 16 | 25 | -------------------------------------------------------------------------------- /app/src/main/res/layout/comic_item_bottom.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 15 | 16 | 19 | 20 | 25 | 26 | 27 | 32 | 33 | 37 | 38 | 44 | 45 | 49 | 50 | 56 | 57 | 61 | 62 | 68 | 69 | 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /app/src/main/res/layout/comic_item_bottom2.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | 14 | 17 | 18 | 23 | 24 | 25 | 31 | 32 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /app/src/main/res/layout/comic_item_detail_list.xml: -------------------------------------------------------------------------------- 1 | 2 | 15 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/layout/comic_item_list.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/src/main/res/layout/comic_item_list2.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 | 15 | 16 | 27 | 28 | 38 | 39 | -------------------------------------------------------------------------------- /app/src/main/res/layout/comic_item_main_list.xml: -------------------------------------------------------------------------------- 1 | 2 | 13 | 14 | 19 | 20 | 26 | 27 | 35 | 36 | 37 | 45 | 46 | 58 | 59 | 65 | 66 | -------------------------------------------------------------------------------- /app/src/main/res/layout/comic_item_preview.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 11 | 12 | 17 | -------------------------------------------------------------------------------- /app/src/main/res/layout/comic_item_preview2.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/layout/comic_item_preview_left.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/layout/comic_item_search_list.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 17 | 18 | 24 | 25 | 31 | 32 | 41 | 42 | 50 | 51 | 57 | 58 | 72 | 73 | 74 | 78 | 79 | -------------------------------------------------------------------------------- /app/src/main/res/layout/comm_loading.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/res/layout/comm_loadmore.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 13 | 14 | 21 | 22 | 30 | 31 | 32 | 37 | 38 | 39 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /app/src/main/res/layout/comm_recyclerview.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_comics.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 16 | 17 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/res/layout/include_title.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 17 | 18 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /app/src/main/res/layout/include_title_search.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 16 | 17 | 22 | 23 | 38 | 39 | 47 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /app/src/main/res/layout/menu_title.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/src/main/res/layout/menu_title_like.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/src/main/res/layout/pop_module.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 17 | 18 | 23 | 24 | 28 | 29 | 38 | 39 | 45 | 46 | 50 | 51 | 60 | 61 | 67 | 68 | 72 | 73 | 74 | 81 | 82 | 92 | 93 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /app/src/main/res/layout/pop_windowlight.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 11 | 12 | 19 | 20 | 29 | 30 | 38 | 39 | 45 | 46 | 55 | 56 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /app/src/main/res/layout/test.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/layout/test_activity.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 12 | 13 |