├── .gitignore ├── .idea ├── codeStyles │ ├── Project.xml │ └── codeStyleConfig.xml ├── compiler.xml ├── encodings.xml ├── gradle.xml ├── inspectionProfiles │ └── Project_Default.xml ├── misc.xml ├── runConfigurations.xml └── vcs.xml ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── lxm │ │ └── wanandroid │ │ └── ExampleInstrumentedTest.kt │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── lxm │ │ │ └── wanandroid │ │ │ ├── MainActivity.kt │ │ │ ├── repository │ │ │ ├── model │ │ │ │ ├── ArticleResponse.kt │ │ │ │ ├── Banner.kt │ │ │ │ ├── HttpResponse.kt │ │ │ │ ├── Listing.kt │ │ │ │ ├── LoginBean.kt │ │ │ │ ├── Navigation.kt │ │ │ │ ├── Resource.kt │ │ │ │ ├── TreeBean.kt │ │ │ │ └── WelfareResponse.kt │ │ │ └── remote │ │ │ │ ├── LoginResposity.kt │ │ │ │ └── httpClient │ │ │ │ ├── API.kt │ │ │ │ └── RetrofitClient.kt │ │ │ ├── ui │ │ │ ├── ArticleFragment.kt │ │ │ ├── CollectActivity.kt │ │ │ ├── LoginActivity.kt │ │ │ ├── NavigationFragment.kt │ │ │ ├── ProjectFragment.kt │ │ │ ├── TagArticleActivity.kt │ │ │ ├── TreeFragment.kt │ │ │ ├── ViewBigImageActivity.kt │ │ │ ├── WelfareFragment.kt │ │ │ ├── adapter │ │ │ │ ├── ArticleAdapter.kt │ │ │ │ ├── NaviAdapter.kt │ │ │ │ ├── TreeAdapter.kt │ │ │ │ └── WelfareAdapter.kt │ │ │ └── base │ │ │ │ ├── BaseRecyclerAdapter.kt │ │ │ │ ├── BaseRecyclerViewHoder.kt │ │ │ │ ├── OnItemClickListener.kt │ │ │ │ └── OnItemLongClickListener.kt │ │ │ ├── utils │ │ │ ├── CookieUtils.kt │ │ │ ├── GlideUtil.kt │ │ │ └── webview │ │ │ │ ├── WebViewActivity.java │ │ │ │ └── config │ │ │ │ ├── FullscreenHolder.java │ │ │ │ ├── IWebPageView.java │ │ │ │ ├── ImageClickInterface.java │ │ │ │ ├── MyWebChromeClient.java │ │ │ │ └── MyWebViewClient.java │ │ │ └── viewmodel │ │ │ ├── ArticleViewModel.kt │ │ │ ├── CategoryViewModel.kt │ │ │ ├── CollectViewModel.kt │ │ │ ├── LoginViewModel.kt │ │ │ ├── NaviViewModelView.kt │ │ │ ├── ProjectViewModel.kt │ │ │ ├── TreeViewModel.kt │ │ │ └── WelfareModelView.kt │ └── res │ │ ├── drawable-hdpi │ │ ├── actionbar_more.png │ │ ├── actionbar_search.png │ │ ├── ic_about.png │ │ ├── ic_article_new.png │ │ ├── ic_collect.png │ │ ├── ic_collection.png │ │ ├── ic_launcher.png │ │ ├── ic_launcher_round.png │ │ ├── ic_login_menu.png │ │ ├── ic_logout_menu.png │ │ ├── ic_main_search.png │ │ ├── ic_photo.png │ │ ├── ic_un_collect.png │ │ └── icon_back.png │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable-xxhdpi │ │ ├── actionbar_search.png │ │ ├── ic_launcher.png │ │ ├── ic_launcher_round.png │ │ ├── icon_back.png │ │ └── photo.png │ │ ├── drawable │ │ ├── ic_launcher_background.xml │ │ ├── process_bg.xml │ │ ├── selector_bg_tree_tag.xml │ │ └── selector_collect_check.xml │ │ ├── layout │ │ ├── activity_collection.xml │ │ ├── activity_login.xml │ │ ├── activity_main.xml │ │ ├── activity_show_image.xml │ │ ├── activity_web_view.xml │ │ ├── article_banner.xml │ │ ├── article_fragment.xml │ │ ├── category_activity.xml │ │ ├── drawer_header_layout.xml │ │ ├── item_article.xml │ │ ├── item_banner.xml │ │ ├── item_image_view_pager.xml │ │ ├── item_tree.xml │ │ ├── item_tree_tag.xml │ │ ├── item_view.xml │ │ ├── item_view_welfare.xml │ │ ├── main_content.xml │ │ └── tree_fragment.xml │ │ ├── menu │ │ ├── main.xml │ │ ├── navigation.xml │ │ └── webview_menu.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_round.png │ │ └── photo.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ └── values │ │ ├── attrs_circle_view.xml │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── lxm │ └── wanandroid │ └── ExampleUnitTest.kt ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── module_library ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── lxm │ │ └── module_library │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── lxm │ │ │ └── module_library │ │ │ ├── anim │ │ │ ├── AnimManager.kt │ │ │ ├── AnimUtils.kt │ │ │ └── ToolbarAnimManager.kt │ │ │ ├── base │ │ │ ├── BaseActivity.kt │ │ │ ├── BaseFragment.kt │ │ │ ├── BaseViewModel.kt │ │ │ └── NoViewModel.java │ │ │ ├── global │ │ │ ├── AppManager.java │ │ │ └── GlobalApplication.java │ │ │ ├── helper │ │ │ ├── RetrofitCreateHelper.java │ │ │ ├── RxHelper.java │ │ │ └── okhttp │ │ │ │ ├── TrustManager.java │ │ │ │ ├── cache │ │ │ │ ├── CacheInterceptor.java │ │ │ │ └── HttpCache.java │ │ │ │ └── cookies │ │ │ │ ├── CookieManger.java │ │ │ │ ├── OkHttpCookies.java │ │ │ │ └── PersistentCookieStore.java │ │ │ ├── materialLogin │ │ │ ├── DefaultLoginView.java │ │ │ ├── DefaultRegisterView.java │ │ │ ├── MaterialLoginView.java │ │ │ └── RegisterView.java │ │ │ ├── statusbar │ │ │ ├── StatusBarUtil.java │ │ │ └── StatusBarView.java │ │ │ ├── utils │ │ │ ├── AppUtils.kt │ │ │ ├── BaseTools.java │ │ │ ├── BitmapUtils.kt │ │ │ ├── CheckNetwork.java │ │ │ ├── ClassUtil.kt │ │ │ ├── DateUtils.kt │ │ │ ├── DialogUtils.kt │ │ │ ├── DisplayUtils.kt │ │ │ ├── FileUtils.kt │ │ │ ├── HtmlUtils.kt │ │ │ ├── HttpUtils.kt │ │ │ ├── ImageUtils.kt │ │ │ ├── JsonUtils.kt │ │ │ ├── MD5Utils.kt │ │ │ ├── MyDividerItemDecoration.java │ │ │ ├── NetworkConnectionUtils.kt │ │ │ ├── PreferencesUtil.kt │ │ │ ├── RefreshHelper.kt │ │ │ ├── ResourcesUtils.kt │ │ │ ├── ScreenAdapterUtils.kt │ │ │ ├── ScreenUtils.kt │ │ │ ├── SnackbarUtils.kt │ │ │ ├── StatusBarUtils.kt │ │ │ ├── StringUtils.kt │ │ │ ├── TimestampUtils.kt │ │ │ ├── ToastUtil.java │ │ │ ├── ToastUtils.kt │ │ │ ├── UnicodeUtils.kt │ │ │ └── WifiAutoConnectManager.kt │ │ │ └── xrecycleview │ │ │ ├── BaseRefreshHeader.java │ │ │ ├── LoadingMoreFooter.java │ │ │ ├── WrapAdapter.java │ │ │ ├── XRecyclerView.java │ │ │ └── YunRefreshHeader.java │ └── res │ │ ├── drawable │ │ ├── app_loading0.png │ │ ├── app_loading1.png │ │ ├── app_loading2.png │ │ ├── app_loading3.png │ │ ├── app_loading_anim.xml │ │ ├── common_progress_cirle.xml │ │ ├── header_loading0.png │ │ ├── header_loading1.png │ │ ├── header_loading2.png │ │ ├── header_loading3.png │ │ ├── header_loading_anim.xml │ │ ├── ic_add.xml │ │ ├── ic_clear.xml │ │ ├── ic_person_add_white_24dp.png │ │ ├── icon_back.png │ │ ├── load_err.png │ │ ├── loading_image.png │ │ ├── login_back.xml │ │ └── shape_line.xml │ │ ├── layout │ │ ├── activity_base.xml │ │ ├── custom_login_view.xml │ │ ├── custom_register_view.xml │ │ ├── default_login_view.xml │ │ ├── default_register_view.xml │ │ ├── fragment_base.xml │ │ ├── layout_loading_error.xml │ │ ├── layout_loading_view.xml │ │ ├── login_layout.xml │ │ ├── login_view.xml │ │ ├── refresh_footer.xml │ │ ├── refresh_header.xml │ │ └── register_layout.xml │ │ ├── values-w600dp │ │ └── dimen.xml │ │ └── values │ │ ├── attrs.xml │ │ ├── colors.xml │ │ ├── dimen.xml │ │ ├── drawables.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── lxm │ └── module_library │ └── ExampleUnitTest.java ├── screenshots ├── 主页侧滑菜单.webp ├── 导航.webp ├── 收藏.webp ├── 注册.webp ├── 登录.webp ├── 目录.webp ├── 知识体系.webp ├── 福利.webp ├── 项目.webp └── 首页.webp └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /build 12 | /captures 13 | .externalNativeBuild 14 | -------------------------------------------------------------------------------- /.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 18 | 19 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 36 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 14 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Awesome-Kotlin-WanAndroid 2 | 3 | ## 简介 4 | 项目主要用来入门`kotlin`语言和google推荐的`MVVM`架构,使用了一些`Jetpack`组件来配合MVVM使用,采用了很多流行的开源库,`Okhttp`,`Retrofit`,`Rxjava`,`Glide`,`Livedatabus`等,代码逻辑简单易懂,仅适用入门 5 | ## 项目功能列表截图 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | ## 功能TODO List 14 | - [x] 首页 15 | - [x] 知识体系 16 | - [x] 导航 17 | - [x] 项目 18 | - [x] 福利 19 | - [x] 登录/登出 20 | - [x] 我的收藏 21 | - [ ] 欢迎页 22 | - [ ] 热门搜索 23 | - [ ] 待办清单功能 24 | - [ ] 网络层切换协程 25 | - [ ] 代码整体优化 26 | ## 使用的开源库 27 | * [Retrofit](https://github.com/square/retrofit) 28 | * [Okhttp](https://github.com/square/okhttp) 29 | * [Rxjava](https://github.com/ReactiveX/RxJava) 30 | * [Glide](https://github.com/bumptech/glide) 31 | * [LiveDataBus](https://github.com/JeremyLiao/LiveEventBus) 32 | * [glide-transformations](https://github.com/wasabeef/glide-transformations) 33 | * [toastcompat](https://github.com/PureWriter/ToastCompat) 34 | * [circleimageview](https://github.com/hdodenhof/CircleImageView) 35 | * [PhotoView](https://github.com/chrisbanes/PhotoView) 36 | * [flowlayout](https://github.com/hongyangAndroid/FlowLayout) 37 | * [MZBannerView](https://github.com/pinguo-zhouwei/MZBannerView) 38 | * [MaterialLogin](https://github.com/shem8/MaterialLogin) 39 | * [AgentWeb](https://github.com/Justson/AgentWeb) 40 | ## 非常感谢 41 | * [CloudReader](https://github.com/youlookwhat/CloudReader) 42 | * [WanAndroid Open API](https://www.wanandroid.com/blog/show/2) 43 | * [Gan Open API](https://gank.io/) 44 | * [界面参考](https://flutterchina.club/app/gm.html) 45 | * [ICON素材](https://www.iconfont.cn/) 46 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | apply plugin: 'kotlin-android' 4 | apply plugin: 'kotlin-kapt' 5 | apply plugin: 'kotlin-android-extensions' 6 | 7 | android { 8 | compileSdkVersion 28 9 | defaultConfig { 10 | applicationId "com.lxm.wanandroid" 11 | minSdkVersion 21 12 | targetSdkVersion 28 13 | versionCode 1 14 | versionName "1.0" 15 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 16 | } 17 | buildTypes { 18 | release { 19 | minifyEnabled false 20 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 21 | } 22 | } 23 | compileOptions { 24 | sourceCompatibility = '1.8' 25 | targetCompatibility = '1.8' 26 | } 27 | 28 | dataBinding { 29 | enabled = true 30 | } 31 | } 32 | 33 | dependencies { 34 | implementation fileTree(dir: 'libs', include: ['*.jar']) 35 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" 36 | implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version" 37 | implementation 'com.android.support:appcompat-v7:28.0.0' 38 | implementation 'com.android.support.constraint:constraint-layout:1.1.3' 39 | implementation 'com.android.support:design:28.0.0' 40 | testImplementation 'junit:junit:4.12' 41 | androidTestImplementation 'com.android.support.test:runner:1.0.2' 42 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' 43 | 44 | 45 | implementation project(':module_library') 46 | 47 | implementation 'com.google.android.gms:play-services-plus:15.0.1' 48 | implementation 'com.flyco.tablayout:FlycoTabLayout_Lib:2.1.2@aar' 49 | implementation 'android.arch.lifecycle:extensions:1.1.1' 50 | implementation 'com.android.support:design:28.0.0-rc01' 51 | implementation 'com.just.agentweb:agentweb:4.0.2' 52 | 53 | // Navigation 54 | def nav_version = "1.0.0-alpha06" 55 | implementation "android.arch.navigation:navigation-fragment:$nav_version" 56 | implementation "android.arch.navigation:navigation-ui:$nav_version" 57 | androidTestImplementation "android.arch.navigation:navigation-testing:$nav_version" 58 | implementation "org.jetbrains.kotlin:kotlin-reflect:1.2.60" 59 | 60 | //Room 61 | def room_version = "1.1.1" 62 | implementation "android.arch.persistence.room:runtime:$room_version" 63 | kapt "android.arch.persistence.room:compiler:$room_version" 64 | implementation "android.arch.persistence.room:rxjava2:$room_version" 65 | implementation "android.arch.persistence.room:guava:$room_version" 66 | testImplementation "android.arch.persistence.room:testing:$room_version" 67 | 68 | //首页banner 69 | implementation 'com.github.pinguo-zhouwei:MZBannerView:v2.0.2' 70 | //体系flowlayout 71 | implementation 'com.hyman:flowlayout-lib:1.1.2' 72 | //大图查看 73 | implementation 'com.github.chrisbanes:PhotoView:1.2' 74 | //圆形头像 75 | implementation 'de.hdodenhof:circleimageview:3.0.0' 76 | //livedataBus 77 | implementation 'com.jeremyliao:live-event-bus:1.4.4' 78 | 79 | 80 | 81 | } 82 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/lxm/wanandroid/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package com.lxm.wanandroid 2 | 3 | import android.support.test.InstrumentationRegistry 4 | import android.support.test.runner.AndroidJUnit4 5 | 6 | import org.junit.Test 7 | import org.junit.runner.RunWith 8 | 9 | import org.junit.Assert.* 10 | 11 | /** 12 | * Instrumented test, which will execute on an Android device. 13 | * 14 | * See [testing documentation](http://d.android.com/tools/testing). 15 | */ 16 | @RunWith(AndroidJUnit4::class) 17 | class ExampleInstrumentedTest { 18 | @Test 19 | fun useAppContext() { 20 | // Context of the app under test. 21 | val appContext = InstrumentationRegistry.getTargetContext() 22 | assertEquals("com.lxm.wanandroid", appContext.packageName) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/java/com/lxm/wanandroid/repository/model/ArticleResponse.kt: -------------------------------------------------------------------------------- 1 | package com.lxm.wanandroid.repository.model 2 | 3 | 4 | 5 | /** 6 | * curPage : 1 7 | * datas : [{"apkLink":"","author":"红橙Darren","chapterId":245,"chapterName":"集合相关","collect":false,"courseId":13,"desc":"","envelopePic":"","fresh":false,"id":3326,"link":"https://www.jianshu.com/p/9edd74769f21","niceDate":"2018-08-27","origin":"","projectLink":"","publishTime":1535372956000,"superChapterId":245,"superChapterName":"Java深入","tags":[],"title":"数据结构算法 - 栈和队列","type":0,"userId":-1,"visible":1,"zan":0}] 8 | * offset : 0 9 | * over : false 10 | * pageCount : 80 11 | * size : 20 12 | * total : 1596 13 | */ 14 | data class ArticleResponseBody(var curPage: Int = 0, 15 | var offset: Int = 0, 16 | var isOver: Boolean = false, 17 | var pageCount: Int = 0, 18 | var size: Int = 0, 19 | var total: Int = 0, 20 | var datas: List? = null) 21 | 22 | 23 | /** 24 | * apkLink : 25 | * author : 红橙Darren 26 | * chapterId : 245 27 | * chapterName : 集合相关 28 | * collect : false 29 | * courseId : 13 30 | * desc : 31 | * envelopePic : 32 | * fresh : false 33 | * id : 3326 34 | * link : https://www.jianshu.com/p/9edd74769f21 35 | * niceDate : 2018-08-27 36 | * origin : 37 | * projectLink : 38 | * publishTime : 1535372956000 39 | * superChapterId : 245 40 | * superChapterName : Java深入 41 | * tags : [] 42 | * title : 数据结构算法 - 栈和队列 43 | * type : 0 44 | * userId : -1 45 | * visible : 1 46 | * zan : 0 47 | */ 48 | data class ArticleBean(var apkLink: String? = null, 49 | var author: String? = null, 50 | var chapterId: Int = 0, 51 | var chapterName: String? = null, 52 | var collect: Boolean = false, 53 | var courseId: Int = 0, 54 | var desc: String? = null, 55 | var envelopePic: String? = null, 56 | var fresh: Boolean = false, 57 | var id: Int = 0, 58 | var link: String? = null, 59 | var niceDate: String? = null, 60 | var origin: String? = null, 61 | var originId: Int? = null, 62 | var projectLink: String? = null, 63 | var publishTime: Long = 0, 64 | var superChapterId: Int = 0, 65 | var superChapterName: String? = null, 66 | var title: String? = null, 67 | var type: Int = 0, 68 | var userId: Int = 0, 69 | var visible: Int = 0, 70 | var zan: Int = 0, 71 | var tags: List? = null) 72 | 73 | 74 | data class Project(var name:String?,var url:String?) 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /app/src/main/java/com/lxm/wanandroid/repository/model/Banner.kt: -------------------------------------------------------------------------------- 1 | package com.lxm.wanandroid.repository.model 2 | 3 | data class Banner( 4 | val desc: String, 5 | val id: Int, 6 | val imagePath: String, 7 | val isVisible: Int, 8 | val order: Int, 9 | val title: String, 10 | val type: Int, 11 | val url: String 12 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/lxm/wanandroid/repository/model/HttpResponse.kt: -------------------------------------------------------------------------------- 1 | package com.lxm.wanandroid.repository.model 2 | /** 3 | * data : {"curPage":1,"datas":[{"apkLink":"","author":"红橙Darren","chapterId":245,"chapterName":"集合相关","collect":false,"courseId":13,"desc":"","envelopePic":"","fresh":false,"id":3326,"link":"https://www.jianshu.com/p/9edd74769f21","niceDate":"2018-08-27","origin":"","projectLink":"","publishTime":1535372956000,"superChapterId":245,"superChapterName":"Java深入","tags":[],"title":"数据结构算法 - 栈和队列","type":0,"userId":-1,"visible":1,"zan":0}],"offset":0,"over":false,"pageCount":80,"size":20,"total":1596} 4 | * errorCode : 0 5 | * errorMsg : 6 | */ 7 | data class HttpResponse( 8 | var data: T? = null, 9 | var errorCode: Int = 0, 10 | var errorMsg: String? = null 11 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/lxm/wanandroid/repository/model/Listing.kt: -------------------------------------------------------------------------------- 1 | package com.lxm.wanandroid.repository.model 2 | 3 | import android.arch.lifecycle.MutableLiveData 4 | 5 | data class Listing( 6 | val pagedList: MutableLiveData, 7 | val loadStatus: MutableLiveData> 8 | ) 9 | -------------------------------------------------------------------------------- /app/src/main/java/com/lxm/wanandroid/repository/model/LoginBean.kt: -------------------------------------------------------------------------------- 1 | package com.lxm.wanandroid.repository.model 2 | 3 | data class LoginBean( 4 | val admin: Boolean, 5 | val chapterTops: List, 6 | val collectIds: List, 7 | val email: String, 8 | val icon: String, 9 | val id: Int, 10 | val nickname: String, 11 | val password: String, 12 | val token: String, 13 | val type: Int, 14 | val username: String 15 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/lxm/wanandroid/repository/model/Navigation.kt: -------------------------------------------------------------------------------- 1 | package com.lxm.wanandroid.repository.model 2 | 3 | data class Navigation( 4 | val articles: List, 5 | val cid: Int, 6 | val name: String 7 | ) 8 | -------------------------------------------------------------------------------- /app/src/main/java/com/lxm/wanandroid/repository/model/Resource.kt: -------------------------------------------------------------------------------- 1 | package com.lxm.wanandroid.repository.model 2 | 3 | /** 4 | * Created by juan on 2018/05/23. 5 | */ 6 | data class Resource(val status: Status, val data: T?, val message: String?) { 7 | companion object { 8 | fun loading(msg: String? = null, data: T? = null): Resource { 9 | return Resource(Status.LOADING, data, msg) 10 | } 11 | 12 | fun success(data: T? = null): Resource { 13 | return Resource(Status.SUCCESS, data, null) 14 | } 15 | 16 | fun error(msg: String? = null, data: T? = null): Resource { 17 | return Resource(Status.ERROR, data, msg) 18 | } 19 | } 20 | } 21 | 22 | enum class Status { 23 | SUCCESS, 24 | ERROR, 25 | LOADING 26 | } -------------------------------------------------------------------------------- /app/src/main/java/com/lxm/wanandroid/repository/model/TreeBean.kt: -------------------------------------------------------------------------------- 1 | package com.lxm.wanandroid.repository.model 2 | 3 | import java.io.Serializable 4 | 5 | data class TreeBean( 6 | val children: List, 7 | val courseId: Int, 8 | val id: Int, 9 | val name: String, 10 | val order: Int, 11 | val parentChapterId: Int, 12 | val userControlSetTop: Boolean, 13 | val visible: Int 14 | ):Serializable 15 | 16 | -------------------------------------------------------------------------------- /app/src/main/java/com/lxm/wanandroid/repository/model/WelfareResponse.kt: -------------------------------------------------------------------------------- 1 | package com.lxm.wanandroid.repository.model 2 | 3 | data class WelfareResponse( 4 | val error: Boolean, 5 | val results: List 6 | ) 7 | 8 | data class Welfare( 9 | val _id: String, 10 | val createdAt: String, 11 | val desc: String, 12 | val publishedAt: String, 13 | val source: String, 14 | val type: String, 15 | val url: String, 16 | val used: Boolean, 17 | val who: String 18 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/lxm/wanandroid/repository/remote/LoginResposity.kt: -------------------------------------------------------------------------------- 1 | package com.lxm.wanandroid.repository.remote 2 | 3 | import android.arch.lifecycle.MutableLiveData 4 | import com.lxm.module_library.helper.RxHelper 5 | import com.lxm.wanandroid.repository.model.HttpResponse 6 | import com.lxm.wanandroid.repository.model.LoginBean 7 | import com.lxm.wanandroid.repository.remote.httpClient.RetrofitClient 8 | import io.reactivex.functions.Consumer 9 | 10 | class LoginRepository { 11 | 12 | val login = MutableLiveData>() 13 | val register = MutableLiveData>() 14 | val logout = MutableLiveData>() 15 | 16 | fun login(account: String, password: String) { 17 | 18 | RetrofitClient.getInstance(RetrofitClient.WAN_BASE_URL).login(account, password) 19 | .compose(RxHelper.rxSchedulerHelper()) 20 | .subscribe(Consumer { 21 | login.value = it 22 | }, Consumer { 23 | login.value = HttpResponse(null, 500, it.message!!) 24 | }) 25 | 26 | } 27 | 28 | fun register(account: String, password: String, rPassword: String) { 29 | 30 | RetrofitClient.getInstance(RetrofitClient.WAN_BASE_URL).register(account, password, rPassword) 31 | .compose(RxHelper.rxSchedulerHelper()) 32 | .subscribe(Consumer { 33 | register.value = it 34 | }, Consumer { 35 | register.value = HttpResponse(null, 500, it.message!!) 36 | }) 37 | 38 | } 39 | 40 | fun logout() { 41 | RetrofitClient.getInstance(RetrofitClient.WAN_BASE_URL).logout() 42 | .compose(RxHelper.rxSchedulerHelper()) 43 | .subscribe(Consumer { 44 | logout.value = it 45 | }, Consumer { 46 | logout.value = HttpResponse(null, 500, it.message!!) 47 | }) 48 | 49 | } 50 | 51 | 52 | 53 | } -------------------------------------------------------------------------------- /app/src/main/java/com/lxm/wanandroid/repository/remote/httpClient/API.kt: -------------------------------------------------------------------------------- 1 | package com.lxm.wanandroid.repository.remote.httpClient 2 | 3 | import com.lxm.wanandroid.repository.model.* 4 | import io.reactivex.Observable 5 | import retrofit2.http.* 6 | 7 | 8 | interface API{ 9 | 10 | 11 | /* 12 | * 13 | * 获取首页新闻列表 14 | * 15 | * */ 16 | 17 | @GET("/article/list/{page}/json") 18 | fun getArticleList(@Path(value = "page")page:Int):Observable>> 19 | /* 20 | * 21 | * 获取首页Banner 22 | * 23 | * */ 24 | 25 | @GET("/banner/json") 26 | fun getHomeBanner():Observable>> 27 | /* 28 | * 29 | * 获取知识体系 30 | * 31 | * */ 32 | 33 | @GET("/tree/json") 34 | fun getTrees():Observable>> 35 | 36 | /* 37 | * 38 | * 获取知识体系目录 39 | * /article/list/0/json?cid=60 40 | * */ 41 | 42 | @GET("/article/list/{page}/json") 43 | fun getCategory(@Path(value = "page")page:Int,@Query(value = "cid")cid:Int):Observable>> 44 | /* 45 | * 46 | * 获取知识体系目录 47 | * /navi/json 48 | * */ 49 | 50 | @GET("/navi/json") 51 | fun getNavigation():Observable>> 52 | 53 | /* 54 | * 55 | * 获取Gan福利 56 | * /navi/json 57 | * */ 58 | @GET("/api/data/{type}/{page_size}/{page}") 59 | fun getWelfare(@Path("type") id: String, @Path("page_size") page_size: Int,@Path("page") page: Int): Observable 60 | 61 | /* 62 | * 63 | * 获取项目列表 64 | * 65 | * */ 66 | 67 | @GET("/article/listproject/{page}/json") 68 | fun getProjectList(@Path(value = "page")page:Int):Observable>> 69 | 70 | /** 71 | * 登录 72 | */ 73 | @FormUrlEncoded 74 | @POST("/user/login") 75 | fun login(@Field(value = "username")username: String, @Field(value = "password")password: String): Observable> 76 | 77 | /** 78 | * 注销 79 | * https://www.wanandroid.com/user/logout/json 80 | */ 81 | @GET("/user/logout/json") 82 | fun logout():Observable> 83 | 84 | /** 85 | * 注册 86 | */ 87 | @FormUrlEncoded 88 | @POST("/user/register") 89 | fun register(@Field(value = "username")account: String, @Field(value = "password")password: String, @Field(value = "repassword")rPassword: String): Observable> 90 | 91 | /** 92 | * 我的收藏列表 93 | * lg/collect/list/0/json 94 | */ 95 | @GET("/lg/collect/list/{page}/json") 96 | fun getCollectList(@Path(value = "page")page:Int):Observable>> 97 | 98 | /** 99 | * 收藏 100 | * https://www.wanandroid.com/lg/collect/1165/json 101 | */ 102 | @POST("/lg/collect/{id}/json") 103 | fun collect(@Path(value = "id")id:Int):Observable> 104 | 105 | /** 106 | * 取消收藏 107 | * https://www.wanandroid.com/lg/uncollect_originId/2333/json 108 | */ 109 | @POST("/lg/uncollect_originId/{id}/json") 110 | fun unCollect(@Path(value = "id")id:Int):Observable> 111 | 112 | 113 | } -------------------------------------------------------------------------------- /app/src/main/java/com/lxm/wanandroid/repository/remote/httpClient/RetrofitClient.kt: -------------------------------------------------------------------------------- 1 | package com.lxm.wanandroid.repository.remote.httpClient 2 | 3 | import com.lxm.module_library.helper.RetrofitCreateHelper 4 | 5 | 6 | object RetrofitClient { 7 | const val WAN_BASE_URL = "https://www.wanandroid.com" 8 | const val GAN_BASE_URL = "https://gank.io" 9 | 10 | private var api: API? = null 11 | fun getInstance(type: String): API { 12 | api = RetrofitCreateHelper.createApi(API::class.java, type) 13 | return api!! 14 | } 15 | } -------------------------------------------------------------------------------- /app/src/main/java/com/lxm/wanandroid/ui/CollectActivity.kt: -------------------------------------------------------------------------------- 1 | package com.lxm.wanandroid.ui 2 | 3 | import android.arch.lifecycle.Observer 4 | import android.os.Bundle 5 | import com.lxm.module_library.base.BaseActivity 6 | import com.lxm.module_library.utils.RefreshHelper 7 | import com.lxm.module_library.xrecycleview.XRecyclerView 8 | import com.lxm.wanandroid.R 9 | import com.lxm.wanandroid.repository.model.ArticleBean 10 | import com.lxm.wanandroid.repository.model.Status 11 | import com.lxm.wanandroid.ui.adapter.ArticleAdapter 12 | import com.lxm.wanandroid.ui.base.OnItemClickListener 13 | import com.lxm.wanandroid.utils.webview.WebViewActivity 14 | import com.lxm.wanandroid.viewmodel.CollectViewModel 15 | import kotlinx.android.synthetic.main.article_fragment.* 16 | 17 | 18 | class CollectActivity : BaseActivity() { 19 | 20 | private val mAdapter: ArticleAdapter by lazy { 21 | ArticleAdapter() 22 | } 23 | 24 | override fun onCreate(savedInstanceState: Bundle?) { 25 | super.onCreate(savedInstanceState) 26 | setContentView(R.layout.article_fragment) 27 | setTitle("我的收藏") 28 | initView() 29 | getCollection() 30 | } 31 | 32 | 33 | private fun initView() { 34 | swipeLayout.setOnRefreshListener { 35 | swipeLayout.isRefreshing = true 36 | viewModel.mPage = 0 37 | getCollection() 38 | } 39 | RefreshHelper.init(recyclerView, false) 40 | mAdapter.isCollectionList = true 41 | recyclerView.adapter = mAdapter 42 | recyclerView.setLoadingListener(object : XRecyclerView.LoadingListener { 43 | 44 | override fun onLoadMore() { 45 | viewModel.mPage = viewModel.mPage + 1; 46 | getCollection() 47 | } 48 | 49 | override fun onRefresh() { 50 | } 51 | }) 52 | showLoading() 53 | viewModel.loadStatus.observe(this, Observer { 54 | 55 | when (it?.status) { 56 | // Status.ERROR -> showError() 57 | Status.SUCCESS -> showContentView() 58 | } 59 | }) 60 | this.viewModel.collectionList.observe(this, Observer { 61 | swipeLayout.isRefreshing = false 62 | if (it == null) { 63 | return@Observer 64 | } 65 | if(viewModel.mPage ==0){ 66 | mAdapter.setData(it.data?.datas!!) 67 | return@Observer 68 | } 69 | mAdapter.addDataAll(it.data?.datas!!) 70 | if(it?.data?.datas?.size!! < it?.data?.size!!){ 71 | recyclerView.noMoreLoading() 72 | }else{ 73 | recyclerView.refreshComplete() 74 | } 75 | }) 76 | 77 | mAdapter.setOnItemClickListener(object : OnItemClickListener { 78 | override fun onClick(t: ArticleBean, position: Int) { 79 | WebViewActivity.loadUrl(this@CollectActivity, t.link, t.title) 80 | } 81 | }) 82 | } 83 | 84 | private fun getCollection() { 85 | viewModel.getCollect() 86 | } 87 | } 88 | 89 | -------------------------------------------------------------------------------- /app/src/main/java/com/lxm/wanandroid/ui/NavigationFragment.kt: -------------------------------------------------------------------------------- 1 | package com.lxm.wanandroid.ui 2 | 3 | import android.arch.lifecycle.Observer 4 | import android.os.Bundle 5 | import android.support.v7.widget.LinearLayoutManager 6 | import android.view.View 7 | import com.lxm.module_library.base.BaseFragment 8 | import com.lxm.module_library.xrecycleview.XRecyclerView 9 | import com.lxm.wanandroid.R 10 | import com.lxm.wanandroid.repository.model.ArticleBean 11 | import com.lxm.wanandroid.repository.model.Status 12 | import com.lxm.wanandroid.ui.adapter.NaviAdapter 13 | import com.lxm.wanandroid.utils.webview.WebViewActivity 14 | import com.lxm.wanandroid.viewmodel.NaviViewModelView 15 | import com.zhy.view.flowlayout.FlowLayout 16 | import kotlinx.android.synthetic.main.article_fragment.* 17 | 18 | class NavigationFragment : BaseFragment() { 19 | 20 | private val mAdapter: NaviAdapter by lazy { 21 | NaviAdapter(itemClickListener) 22 | } 23 | private val itemClickListener: NaviAdapter.OnItemNavigationClickListener = object : 24 | NaviAdapter.OnItemNavigationClickListener { 25 | 26 | override fun itemClick(view: View, position: Int, parent: FlowLayout, articles: List) { 27 | var article = articles[position] 28 | WebViewActivity.loadUrl(activity, article.link, article.title) 29 | } 30 | } 31 | override fun getLayoutID(): Int { 32 | return R.layout.tree_fragment 33 | } 34 | 35 | companion object { 36 | fun getInstance(): NavigationFragment { 37 | return NavigationFragment() 38 | } 39 | } 40 | 41 | override fun onActivityCreated(savedInstanceState: Bundle?) { 42 | super.onActivityCreated(savedInstanceState) 43 | showContentView() 44 | initView() 45 | } 46 | 47 | private fun initView() { 48 | swipeLayout.setOnRefreshListener { 49 | loadData() 50 | } 51 | swipeLayout.isRefreshing = true 52 | val layoutManager = LinearLayoutManager(activity) 53 | recyclerView.layoutManager = layoutManager 54 | recyclerView.setPullRefreshEnabled(false) 55 | recyclerView.setLoadingMoreEnabled(false) 56 | recyclerView.clearHeader() 57 | recyclerView.adapter = mAdapter 58 | recyclerView.setLoadingListener(object : XRecyclerView.LoadingListener { 59 | override fun onLoadMore() { 60 | getTreeList() 61 | } 62 | 63 | override fun onRefresh() { 64 | } 65 | }) 66 | viewModel.loadStatus.observe(this, Observer { 67 | 68 | when (it?.status) { 69 | Status.ERROR -> showError() 70 | } 71 | }) 72 | } 73 | 74 | override fun onRetry() { 75 | loadData() 76 | } 77 | 78 | override fun loadData() { 79 | getTreeList() 80 | } 81 | 82 | private fun getTreeList() { 83 | this.viewModel.getVavigations().observe(this@NavigationFragment, Observer { 84 | swipeLayout.isRefreshing = false 85 | recyclerView.refreshComplete() 86 | it?.let { list -> mAdapter.setData(it) } 87 | mAdapter.notifyDataSetChanged() 88 | }) 89 | } 90 | 91 | } -------------------------------------------------------------------------------- /app/src/main/java/com/lxm/wanandroid/ui/TagArticleActivity.kt: -------------------------------------------------------------------------------- 1 | package com.lxm.wanandroid.ui 2 | 3 | import android.arch.lifecycle.Observer 4 | import android.os.Bundle 5 | import com.lxm.module_library.base.BaseActivity 6 | import com.lxm.module_library.utils.RefreshHelper 7 | import com.lxm.module_library.xrecycleview.XRecyclerView 8 | import com.lxm.wanandroid.R 9 | import com.lxm.wanandroid.repository.model.ArticleBean 10 | import com.lxm.wanandroid.repository.model.Status 11 | import com.lxm.wanandroid.repository.model.TreeBean 12 | import com.lxm.wanandroid.ui.adapter.ArticleAdapter 13 | import com.lxm.wanandroid.ui.base.OnItemClickListener 14 | import com.lxm.wanandroid.utils.webview.WebViewActivity 15 | import com.lxm.wanandroid.viewmodel.CategoryViewModel 16 | import kotlinx.android.synthetic.main.article_fragment.* 17 | 18 | class TagArticleActivity: BaseActivity() { 19 | lateinit var treeBean: TreeBean 20 | private val mAdapter: ArticleAdapter by lazy { 21 | ArticleAdapter() 22 | } 23 | 24 | override fun onCreate(savedInstanceState: Bundle?) { 25 | super.onCreate(savedInstanceState) 26 | setContentView(R.layout.category_activity) 27 | initView() 28 | treeBean = intent.getSerializableExtra("TagBean") as TreeBean 29 | setTitle(treeBean.name) 30 | getCategory(treeBean.id) 31 | } 32 | 33 | 34 | private fun initView() { 35 | swipeLayout.setOnRefreshListener { 36 | swipeLayout.isRefreshing = true 37 | viewModel.mPage = 0 38 | getCategory(treeBean.id) 39 | } 40 | RefreshHelper.init(recyclerView, false) 41 | recyclerView.adapter = mAdapter 42 | recyclerView.setLoadingListener(object : XRecyclerView.LoadingListener { 43 | 44 | override fun onLoadMore() { 45 | viewModel.mPage = viewModel.mPage + 1; 46 | getCategory(treeBean.id) 47 | } 48 | 49 | override fun onRefresh() { 50 | } 51 | }) 52 | showLoading() 53 | viewModel.loadStatus.observe(this, Observer { 54 | 55 | when (it?.status) { 56 | // Status.ERROR -> showError() 57 | Status.SUCCESS -> showContentView() 58 | } 59 | }) 60 | this.viewModel.pagedList.observe(this, Observer { 61 | swipeLayout.isRefreshing = false 62 | if (it == null) { 63 | return@Observer 64 | } 65 | if(viewModel.mPage ==0){ 66 | mAdapter.setData(it.data?.datas!!) 67 | return@Observer 68 | } 69 | mAdapter.addDataAll(it.data?.datas!!) 70 | if(it?.data?.datas?.size!! < it?.data?.size!!){ 71 | recyclerView.noMoreLoading() 72 | }else{ 73 | recyclerView.refreshComplete() 74 | } 75 | }) 76 | 77 | mAdapter.setOnItemClickListener(object : OnItemClickListener { 78 | override fun onClick(t: ArticleBean, position: Int) { 79 | WebViewActivity.loadUrl(this@TagArticleActivity, t.link, t.title) 80 | } 81 | }) 82 | } 83 | 84 | private fun getCategory(id: Int) { 85 | viewModel.getCategory(id) 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /app/src/main/java/com/lxm/wanandroid/ui/TreeFragment.kt: -------------------------------------------------------------------------------- 1 | package com.lxm.wanandroid.ui 2 | 3 | import android.arch.lifecycle.Observer 4 | import android.content.Intent 5 | import android.os.Bundle 6 | import android.support.v7.widget.LinearLayoutManager 7 | import android.view.View 8 | import com.lxm.module_library.base.BaseFragment 9 | import com.lxm.module_library.xrecycleview.XRecyclerView 10 | import com.lxm.wanandroid.R 11 | import com.lxm.wanandroid.repository.model.Status 12 | import com.lxm.wanandroid.repository.model.TreeBean 13 | import com.lxm.wanandroid.ui.adapter.TreeAdapter 14 | import com.lxm.wanandroid.viewmodel.TreeViewModel 15 | import com.zhy.view.flowlayout.FlowLayout 16 | import kotlinx.android.synthetic.main.article_fragment.* 17 | 18 | class TreeFragment : BaseFragment() { 19 | 20 | private val mAdapter: TreeAdapter by lazy { 21 | TreeAdapter(itemClickListener) 22 | } 23 | private val itemClickListener: TreeAdapter.OnItemNavigationClickListener = object : 24 | TreeAdapter.OnItemNavigationClickListener { 25 | 26 | override fun itemClick(view: View, position: Int, parent: FlowLayout, children: List) { 27 | val intent = Intent(parent.context, TagArticleActivity::class.java) 28 | intent.putExtra("TagBean", children[position]) 29 | parent.context.startActivity(intent) 30 | } 31 | } 32 | override fun getLayoutID(): Int { 33 | return R.layout.tree_fragment 34 | } 35 | 36 | companion object { 37 | fun getInstance(): TreeFragment { 38 | return TreeFragment() 39 | } 40 | } 41 | 42 | override fun onActivityCreated(savedInstanceState: Bundle?) { 43 | super.onActivityCreated(savedInstanceState) 44 | showContentView() 45 | initView() 46 | } 47 | 48 | private fun initView() { 49 | swipeLayout.setOnRefreshListener { 50 | loadData() 51 | } 52 | swipeLayout.isRefreshing = true 53 | val layoutManager = LinearLayoutManager(activity) 54 | recyclerView.layoutManager = layoutManager 55 | recyclerView.setPullRefreshEnabled(false) 56 | recyclerView.setLoadingMoreEnabled(false) 57 | recyclerView.clearHeader() 58 | recyclerView.adapter = mAdapter 59 | recyclerView.setLoadingListener(object : XRecyclerView.LoadingListener { 60 | override fun onLoadMore() { 61 | getTreeList() 62 | } 63 | 64 | override fun onRefresh() { 65 | } 66 | }) 67 | viewModel.loadStatus.observe(this, Observer { 68 | 69 | when (it?.status) { 70 | Status.ERROR -> showError() 71 | } 72 | }) 73 | } 74 | 75 | override fun onRetry() { 76 | loadData() 77 | } 78 | 79 | override fun loadData() { 80 | getTreeList() 81 | } 82 | 83 | private fun getTreeList() { 84 | this.viewModel.getTrees().observe(this@TreeFragment, Observer { 85 | swipeLayout.isRefreshing = false 86 | recyclerView.refreshComplete() 87 | it?.let { list -> mAdapter.setData(list) } 88 | mAdapter.notifyDataSetChanged() 89 | }) 90 | } 91 | 92 | } -------------------------------------------------------------------------------- /app/src/main/java/com/lxm/wanandroid/ui/adapter/TreeAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.lxm.wanandroid.ui.adapter 2 | 3 | import android.graphics.Color 4 | import android.graphics.drawable.Drawable 5 | import android.graphics.drawable.GradientDrawable 6 | import android.view.LayoutInflater 7 | import android.view.View 8 | import android.view.ViewGroup 9 | import android.widget.TextView 10 | import com.lxm.wanandroid.R 11 | import com.lxm.wanandroid.repository.model.TreeBean 12 | import com.lxm.wanandroid.ui.base.BaseRecyclerAdapter 13 | import com.lxm.wanandroid.ui.base.BaseRecyclerViewHolder 14 | import com.zhy.view.flowlayout.FlowLayout 15 | import com.zhy.view.flowlayout.TagAdapter 16 | import com.zhy.view.flowlayout.TagFlowLayout 17 | import java.util.* 18 | 19 | 20 | class TreeAdapter(var itemClickListener: OnItemNavigationClickListener) : BaseRecyclerAdapter() { 21 | override fun getItemLayout(): Int { 22 | return R.layout.item_tree 23 | } 24 | 25 | override fun onBindViewHoder(holder: BaseRecyclerViewHolder, position: Int) { 26 | val treeBean = mutableList[position] 27 | val viewHolder: ViewHolder = holder as ViewHolder 28 | viewHolder.titleView?.text = treeBean.name 29 | showTag(treeBean, viewHolder.flowLayout) 30 | 31 | } 32 | 33 | private fun showTag( 34 | treeBean: TreeBean, 35 | flowLayout: TagFlowLayout? 36 | ) { 37 | flowLayout?.adapter = object : TagAdapter(treeBean.children) { 38 | override fun getView( 39 | parent: FlowLayout, 40 | position: Int, 41 | o: TreeBean 42 | ): View { 43 | val textView = View.inflate(parent.context, R.layout.item_tree_tag, null) as TextView 44 | textView.text = o.name 45 | textView.setBackgroundDrawable(getBackGround()) 46 | return textView 47 | } 48 | } 49 | flowLayout?.setOnTagClickListener { view, position, parent -> 50 | itemClickListener?.itemClick(view, position, parent,treeBean.children) 51 | true 52 | } 53 | } 54 | 55 | 56 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseRecyclerViewHolder { 57 | val item = LayoutInflater.from(parent.context).inflate(R.layout.item_tree, parent, false) 58 | return ViewHolder(item) 59 | } 60 | 61 | 62 | class ViewHolder(itemView: View) : BaseRecyclerViewHolder(itemView) { 63 | var titleView: TextView? = null 64 | var flowLayout: TagFlowLayout? = null 65 | 66 | init { 67 | titleView = itemView.findViewById(R.id.tv_tree_title) 68 | flowLayout = itemView.findViewById(R.id.fl_tree) 69 | } 70 | 71 | companion object 72 | } 73 | 74 | private fun getBackGround(): Drawable { 75 | val drawable = GradientDrawable() 76 | drawable.cornerRadius = 16f 77 | drawable.setColor(Color.rgb(Random().nextInt(255), Random().nextInt(255), Random().nextInt(255))) 78 | return drawable 79 | } 80 | 81 | interface OnItemNavigationClickListener { 82 | /** 83 | *单击事件 84 | */ 85 | fun itemClick(view: View, position: Int, parent: FlowLayout, children: List) 86 | } 87 | 88 | } -------------------------------------------------------------------------------- /app/src/main/java/com/lxm/wanandroid/ui/adapter/WelfareAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.lxm.wanandroid.ui.adapter 2 | 3 | 4 | import android.widget.ImageView 5 | import com.lxm.module_library.utils.DisplayUtils 6 | import com.lxm.wanandroid.R 7 | import com.lxm.wanandroid.repository.model.Welfare 8 | import com.lxm.wanandroid.ui.base.BaseRecyclerAdapter 9 | import com.lxm.wanandroid.ui.base.BaseRecyclerViewHolder 10 | import com.lxm.wanandroid.utils.GlideUtil 11 | 12 | class WelfareAdapter : BaseRecyclerAdapter() { 13 | 14 | override fun getItemLayout(): Int { 15 | return R.layout.item_view_welfare 16 | } 17 | 18 | override fun onBindViewHoder(holder: BaseRecyclerViewHolder, position: Int) { 19 | var welfare: Welfare = mutableList?.get(position) 20 | val imageView: ImageView = holder.getView(R.id.iv_welfare) as ImageView 21 | GlideUtil.displayCircleCorner(imageView,welfare.url) 22 | } 23 | } -------------------------------------------------------------------------------- /app/src/main/java/com/lxm/wanandroid/ui/base/BaseRecyclerAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.lxm.wanandroid.ui.base 2 | 3 | import android.content.Context 4 | import android.support.annotation.IntRange 5 | import android.support.v7.widget.RecyclerView 6 | import android.view.LayoutInflater 7 | import android.view.ViewGroup 8 | 9 | abstract class BaseRecyclerAdapter : RecyclerView.Adapter() { 10 | 11 | lateinit var context: Context 12 | var layoutRes: Int = 0 13 | var mutableList: MutableList = mutableListOf() 14 | var listener: OnItemClickListener? = null 15 | 16 | 17 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseRecyclerViewHolder { 18 | context = parent.context 19 | return BaseRecyclerViewHolder( 20 | LayoutInflater.from(context).inflate( 21 | getItemLayout(), 22 | null 23 | ) 24 | ) 25 | } 26 | 27 | 28 | fun setOnItemClickListener(listener: OnItemClickListener) { 29 | this.listener = listener 30 | } 31 | 32 | override fun onBindViewHolder(holder: BaseRecyclerViewHolder, position: Int) { 33 | onBindViewHoder(holder, position) 34 | holder.itemView.setOnClickListener { 35 | listener?.onClick(mutableList.get(position),position) 36 | } 37 | } 38 | 39 | override fun getItemCount(): Int { 40 | return mutableList.size 41 | } 42 | 43 | 44 | fun setData(items: List?) { 45 | this.mutableList = items as MutableList 46 | notifyDataSetChanged() 47 | } 48 | 49 | fun addData(@IntRange(from = 0) position: Int, data: T) { 50 | mutableList.add(position, data) 51 | notifyItemInserted(position) 52 | compatibilityDataSizeChanged(1) 53 | } 54 | 55 | fun addData(data: T) { 56 | mutableList.add(data) 57 | notifyItemInserted(mutableList?.size) 58 | } 59 | 60 | fun addDataAll(data: List) { 61 | mutableList.addAll(data) 62 | notifyDataSetChanged() 63 | } 64 | 65 | fun addAdd(data: T) { 66 | mutableList.add(data) 67 | notifyItemInserted(mutableList?.size) 68 | } 69 | 70 | 71 | fun remove(position: Int) { 72 | mutableList.removeAt(position) 73 | notifyItemRemoved(position) 74 | notifyItemRangeChanged(position, mutableList!!.size - position) 75 | } 76 | 77 | private fun compatibilityDataSizeChanged(size: Int) { 78 | val dataSize = if (mutableList == null) 0 else mutableList!!.size 79 | if (dataSize == size) { 80 | notifyDataSetChanged() 81 | } 82 | } 83 | 84 | /** 85 | * 需要重写的方法 86 | * @param holder 87 | * @param position 88 | */ 89 | abstract fun onBindViewHoder(holder: BaseRecyclerViewHolder, position: Int) 90 | 91 | abstract fun getItemLayout(): Int 92 | } 93 | 94 | -------------------------------------------------------------------------------- /app/src/main/java/com/lxm/wanandroid/ui/base/BaseRecyclerViewHoder.kt: -------------------------------------------------------------------------------- 1 | package com.lxm.wanandroid.ui.base 2 | 3 | import android.support.v7.widget.RecyclerView 4 | import android.text.TextUtils 5 | import android.view.View 6 | import android.widget.ImageView 7 | import android.widget.TextView 8 | import com.bumptech.glide.Glide 9 | import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions 10 | 11 | open class BaseRecyclerViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { 12 | 13 | private val map = mutableMapOf() 14 | fun getView(id: Int): View? { 15 | var viewId = map[id] 16 | if (viewId == null) { 17 | viewId = itemView.findViewById(id) 18 | map[id] = viewId 19 | } 20 | return viewId 21 | } 22 | 23 | 24 | fun setValue(id: Int, string: String?) { 25 | val view = getView(id) 26 | 27 | when (view) { 28 | is TextView -> view.text = string 29 | is ImageView -> showPic(view, string) 30 | } 31 | } 32 | 33 | private fun showPic(view: ImageView, string: String?) { 34 | if (TextUtils.isEmpty(string)) { 35 | view.visibility = View.GONE 36 | } else { 37 | view.visibility = View.VISIBLE 38 | Glide.with(view.context) 39 | .load(string) 40 | .transition(DrawableTransitionOptions.withCrossFade(500)) 41 | .into(view) 42 | } 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /app/src/main/java/com/lxm/wanandroid/ui/base/OnItemClickListener.kt: -------------------------------------------------------------------------------- 1 | package com.lxm.wanandroid.ui.base 2 | 3 | 4 | interface OnItemClickListener { 5 | fun onClick(t: T, position: Int) 6 | } 7 | -------------------------------------------------------------------------------- /app/src/main/java/com/lxm/wanandroid/ui/base/OnItemLongClickListener.kt: -------------------------------------------------------------------------------- 1 | package com.lxm.wanandroid.ui.base 2 | 3 | 4 | interface OnItemLongClickListener { 5 | fun onLongClick(t: T, position: Int) 6 | } 7 | -------------------------------------------------------------------------------- /app/src/main/java/com/lxm/wanandroid/utils/CookieUtils.kt: -------------------------------------------------------------------------------- 1 | package com.lxm.wanandroid.utils 2 | 3 | import android.content.Context 4 | import android.util.Log 5 | import android.webkit.CookieManager 6 | import android.webkit.CookieSyncManager 7 | import com.google.android.gms.common.util.SharedPreferencesUtils 8 | import okhttp3.Cookie 9 | 10 | 11 | object CookieUtils { 12 | 13 | /** 14 | * clear Cookie 15 | * 16 | * @param context 17 | */ 18 | fun clearCookie(context: Context) { 19 | CookieSyncManager.createInstance(context) 20 | CookieSyncManager.getInstance().startSync() 21 | CookieManager.getInstance().removeSessionCookie() 22 | } 23 | 24 | /** 25 | * Sync Cookie 26 | */ 27 | fun syncCookie(context: Context, url: String,cookies:List) { 28 | try { 29 | CookieSyncManager.createInstance(context) 30 | val cookieManager = CookieManager.getInstance() 31 | cookies.forEach { 32 | val name = it.name() 33 | val value = it.value() 34 | val cookieStr = "$name=$value" 35 | cookieManager.setCookie(url,cookieStr) 36 | } 37 | cookieManager.flush() 38 | } catch (e: Exception) { 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /app/src/main/java/com/lxm/wanandroid/utils/GlideUtil.kt: -------------------------------------------------------------------------------- 1 | package com.lxm.wanandroid.utils 2 | 3 | import android.content.Context 4 | import android.graphics.Bitmap 5 | import android.widget.ImageView 6 | import com.bumptech.glide.Glide 7 | import com.bumptech.glide.load.Transformation 8 | import com.bumptech.glide.load.resource.bitmap.CircleCrop 9 | import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions 10 | import jp.wasabeef.glide.transformations.BlurTransformation 11 | import com.bumptech.glide.request.RequestOptions 12 | import com.bumptech.glide.load.resource.bitmap.RoundedCorners 13 | 14 | 15 | 16 | 17 | object GlideUtil { 18 | 19 | private fun displayGaussian(context: Context, url: String, imageView: ImageView) { 20 | // "23":模糊度;"4":图片缩放4倍后再进行模糊 21 | Glide.with(context) 22 | .load(url) 23 | .transition(DrawableTransitionOptions.withCrossFade()) 24 | .transition(DrawableTransitionOptions.withCrossFade(500)) 25 | .transform(BlurTransformation(50, 8) as Transformation) 26 | .into(imageView) 27 | } 28 | 29 | /** 30 | * 加载圆角图,暂时用到显示头像 31 | */ 32 | fun displayCircle(imageView: ImageView, imageUrl: String) { 33 | Glide.with(imageView.context) 34 | .load(imageUrl) 35 | .transition(DrawableTransitionOptions.withCrossFade(500)) 36 | .transform(CircleCrop()) 37 | // .apply(bitmapTransform(new CircleCrop())) 38 | // .transform(new GlideCircleTransform()) 39 | // .transform(new RoundedCorners(20)) 40 | // .transform(new CenterCrop(), new RoundedCorners(20)) 41 | .into(imageView) 42 | } 43 | 44 | fun displayImage(imageView: ImageView, imageUrl: String) { 45 | Glide.with(imageView.context) 46 | .load(imageUrl) 47 | .into(imageView) 48 | } 49 | fun displayCircleCorner(imageView: ImageView, imageUrl: String){ 50 | //设置图片圆角角度 51 | val roundedCorners = RoundedCorners(6) 52 | //通过RequestOptions扩展功能,override:采样率,因为ImageView就这么大,可以压缩图片,降低内存消耗 53 | val options = RequestOptions.bitmapTransform(roundedCorners) 54 | Glide.with(imageView.context).load(imageUrl).apply(options).into(imageView) 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /app/src/main/java/com/lxm/wanandroid/utils/webview/config/FullscreenHolder.java: -------------------------------------------------------------------------------- 1 | package com.lxm.wanandroid.utils.webview.config; 2 | 3 | import android.content.Context; 4 | import android.view.MotionEvent; 5 | import android.widget.FrameLayout; 6 | 7 | /** 8 | * Created by jingbin on 2016/11/17. 9 | */ 10 | 11 | public class FullscreenHolder extends FrameLayout { 12 | 13 | public FullscreenHolder(Context ctx) { 14 | super(ctx); 15 | setBackgroundColor(ctx.getResources().getColor(android.R.color.black)); 16 | } 17 | 18 | @Override 19 | public boolean onTouchEvent(MotionEvent event) { 20 | return true; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/src/main/java/com/lxm/wanandroid/utils/webview/config/IWebPageView.java: -------------------------------------------------------------------------------- 1 | package com.lxm.wanandroid.utils.webview.config; 2 | 3 | import android.view.View; 4 | 5 | /** 6 | * Created by jingbin on 2016/11/17. 7 | */ 8 | public interface IWebPageView { 9 | 10 | // 隐藏进度条 11 | void hindProgressBar(); 12 | 13 | // 显示webview 14 | void showWebView(); 15 | 16 | // 隐藏webview 17 | void hindWebView(); 18 | 19 | /** 20 | * 进度条变化时调用 21 | */ 22 | void startProgress(int newProgress); 23 | 24 | /** 25 | * 添加js监听 26 | */ 27 | void addImageClickListener(); 28 | 29 | /** 30 | * 播放网络视频全屏调用 31 | */ 32 | void fullViewAddView(View view); 33 | 34 | void showVideoFullView(); 35 | 36 | void hindVideoFullView(); 37 | 38 | /** 39 | * 得到网页标题 40 | */ 41 | void setTitle(String title); 42 | } 43 | -------------------------------------------------------------------------------- /app/src/main/java/com/lxm/wanandroid/utils/webview/config/ImageClickInterface.java: -------------------------------------------------------------------------------- 1 | package com.lxm.wanandroid.utils.webview.config; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | import android.text.TextUtils; 6 | import android.util.Log; 7 | import android.webkit.JavascriptInterface; 8 | import android.widget.Toast; 9 | import com.lxm.wanandroid.ui.ViewBigImageActivity; 10 | 11 | /** 12 | * Created by jingbin on 2016/11/17. 13 | * js通信接口 14 | */ 15 | public class ImageClickInterface { 16 | private Context context; 17 | 18 | public ImageClickInterface(Context context) { 19 | this.context = context; 20 | } 21 | 22 | @JavascriptInterface 23 | public void imageClick(String imgUrl, String hasLink) { 24 | Toast.makeText(context, "----点击了图片", Toast.LENGTH_SHORT).show(); 25 | Intent intent = new Intent(context, ViewBigImageActivity.class); 26 | context.startActivity(intent); 27 | Log.e("----点击了图片 url: ", "" + imgUrl); 28 | } 29 | 30 | @JavascriptInterface 31 | public void textClick(String type, String item_pk) { 32 | if (!TextUtils.isEmpty(type) && !TextUtils.isEmpty(item_pk)) { 33 | Log.e("----点击了文字", ""); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /app/src/main/java/com/lxm/wanandroid/viewmodel/ArticleViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.lxm.wanandroid.viewmodel 2 | 3 | import android.arch.lifecycle.MutableLiveData 4 | import com.lxm.module_library.base.BaseViewModel 5 | import com.lxm.module_library.helper.RxHelper 6 | import com.lxm.wanandroid.repository.model.* 7 | import com.lxm.wanandroid.repository.remote.httpClient.RetrofitClient 8 | import io.reactivex.functions.Consumer 9 | 10 | class ArticleViewModel : BaseViewModel() { 11 | 12 | var mPage = 0 13 | var banner = MutableLiveData>>() 14 | val pagedList = MutableLiveData>>() 15 | val loadStatus by lazy { 16 | MutableLiveData>() 17 | } 18 | 19 | fun getHomeList(): Listing>> { 20 | loadStatus.postValue(Resource.loading()) 21 | val subscribe = RetrofitClient.getInstance(RetrofitClient.WAN_BASE_URL).getArticleList(mPage) 22 | .compose(RxHelper.rxSchedulerHelper()) 23 | .subscribe(Consumer>> { 24 | if(it.data != null){ 25 | loadStatus.postValue(Resource.success()) 26 | pagedList.value = it 27 | }else{ 28 | loadStatus.postValue(Resource.error()) 29 | } 30 | 31 | }, Consumer { 32 | if (mPage > 0) { 33 | mPage-- 34 | } 35 | loadStatus.postValue(Resource.error()) 36 | }) 37 | addDisposable(subscribe) 38 | return Listing(pagedList,loadStatus) 39 | } 40 | 41 | fun getBanners(): MutableLiveData>> { 42 | val subscribe = RetrofitClient.getInstance(RetrofitClient.WAN_BASE_URL).getHomeBanner() 43 | .compose(RxHelper.rxSchedulerHelper()) 44 | .subscribe(Consumer>>{ 45 | banner.postValue(it) 46 | }, Consumer { 47 | banner.postValue(null) 48 | }) 49 | 50 | addDisposable(subscribe) 51 | return banner 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /app/src/main/java/com/lxm/wanandroid/viewmodel/CategoryViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.lxm.wanandroid.viewmodel 2 | 3 | import android.arch.lifecycle.MutableLiveData 4 | import com.lxm.module_library.base.BaseViewModel 5 | import com.lxm.module_library.helper.RxHelper 6 | import com.lxm.wanandroid.repository.model.* 7 | import com.lxm.wanandroid.repository.remote.httpClient.RetrofitClient 8 | import io.reactivex.functions.Consumer 9 | 10 | class CategoryViewModel: BaseViewModel() { 11 | var mPage = 0 12 | val pagedList = MutableLiveData>>() 13 | val loadStatus by lazy { 14 | MutableLiveData>() 15 | } 16 | 17 | fun getCategory(id: Int): Listing>> { 18 | loadStatus.postValue(Resource.loading()) 19 | val subscribe = RetrofitClient.getInstance(RetrofitClient.WAN_BASE_URL).getCategory(mPage,id) 20 | .compose(RxHelper.rxSchedulerHelper()) 21 | .subscribe(Consumer>> { 22 | if(it.data != null){ 23 | loadStatus.postValue(Resource.success()) 24 | pagedList.value = it 25 | }else{ 26 | loadStatus.postValue(Resource.error()) 27 | } 28 | 29 | }, Consumer { 30 | if (mPage > 0) { 31 | mPage-- 32 | } 33 | loadStatus.postValue(Resource.error()) 34 | }) 35 | addDisposable(subscribe) 36 | return Listing(pagedList,loadStatus) 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /app/src/main/java/com/lxm/wanandroid/viewmodel/CollectViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.lxm.wanandroid.viewmodel 2 | 3 | import android.arch.lifecycle.MutableLiveData 4 | import com.lxm.module_library.base.BaseViewModel 5 | import com.lxm.module_library.helper.RxHelper 6 | import com.lxm.wanandroid.repository.model.* 7 | import com.lxm.wanandroid.repository.remote.httpClient.RetrofitClient 8 | import com.lxm.wanandroid.ui.adapter.ArticleAdapter 9 | import io.reactivex.functions.Consumer 10 | 11 | class CollectViewModel : BaseViewModel() { 12 | 13 | var mPage = 0 14 | val collectionList = MutableLiveData>>() 15 | val loadStatus by lazy { 16 | MutableLiveData>() 17 | } 18 | 19 | fun getCollect(): Listing>> { 20 | loadStatus.postValue(Resource.loading()) 21 | val subscribe = RetrofitClient.getInstance(RetrofitClient.WAN_BASE_URL).getCollectList(mPage) 22 | .compose(RxHelper.rxSchedulerHelper()) 23 | .subscribe(Consumer>> { 24 | if(it.data != null){ 25 | loadStatus.postValue(Resource.success()) 26 | collectionList.value = it 27 | }else{ 28 | loadStatus.postValue(Resource.error()) 29 | } 30 | 31 | }, Consumer { 32 | if (mPage > 0) { 33 | mPage-- 34 | } 35 | loadStatus.postValue(Resource.error()) 36 | }) 37 | addDisposable(subscribe) 38 | return Listing(collectionList,loadStatus) 39 | } 40 | 41 | fun collect(id:Int,collectionObserver: ArticleAdapter.CollectionObserver>) { 42 | val subscribe = RetrofitClient.getInstance(RetrofitClient.WAN_BASE_URL).collect(id) 43 | .compose(RxHelper.rxSchedulerHelper()) 44 | .subscribe(Consumer> { 45 | collectionObserver.onChanged(it) 46 | }, Consumer { 47 | collectionObserver.onChanged(null) 48 | }) 49 | addDisposable(subscribe) 50 | } 51 | fun unCollect(id:Int,collectionObserver: ArticleAdapter.CollectionObserver>) { 52 | val subscribe = RetrofitClient.getInstance(RetrofitClient.WAN_BASE_URL).unCollect(id) 53 | .compose(RxHelper.rxSchedulerHelper()) 54 | .subscribe(Consumer> { 55 | collectionObserver.onChanged(it) 56 | }, Consumer { 57 | collectionObserver.onChanged(null) 58 | }) 59 | addDisposable(subscribe) 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /app/src/main/java/com/lxm/wanandroid/viewmodel/LoginViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.lxm.wanandroid.viewmodel 2 | 3 | import android.arch.lifecycle.Transformations 4 | import com.lxm.module_library.base.BaseViewModel 5 | import com.lxm.wanandroid.repository.remote.LoginRepository 6 | 7 | class LoginViewModel(val loginRepository: LoginRepository) : BaseViewModel() { 8 | var loginStatus = Transformations.map(loginRepository.login){it} 9 | var registerStauts = Transformations.map(loginRepository.register){it} 10 | var logoutStatus = Transformations.map(loginRepository.logout){it} 11 | 12 | 13 | fun login(username:String,password:String) { 14 | loginRepository.login(username,password) 15 | } 16 | 17 | fun logout() { 18 | loginRepository.logout() 19 | } 20 | 21 | 22 | fun register(username:String,password:String,repassword:String) { 23 | loginRepository.register(username,password,repassword) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/java/com/lxm/wanandroid/viewmodel/NaviViewModelView.kt: -------------------------------------------------------------------------------- 1 | package com.lxm.wanandroid.viewmodel 2 | 3 | import android.arch.lifecycle.MutableLiveData 4 | import com.lxm.module_library.base.BaseViewModel 5 | import com.lxm.module_library.helper.RxHelper 6 | import com.lxm.wanandroid.repository.model.Navigation 7 | import com.lxm.wanandroid.repository.model.Resource 8 | import com.lxm.wanandroid.repository.remote.httpClient.RetrofitClient 9 | 10 | class NaviViewModelView : BaseViewModel() { 11 | private val naviList = MutableLiveData>() 12 | val loadStatus by lazy { 13 | MutableLiveData>() 14 | } 15 | fun getVavigations(): MutableLiveData> { 16 | RetrofitClient.getInstance(RetrofitClient.WAN_BASE_URL).getNavigation() 17 | .compose(RxHelper.rxSchedulerHelper()) 18 | .subscribe({ 19 | naviList.postValue(it.data) 20 | }, { 21 | loadStatus.postValue(Resource.error()) 22 | }) 23 | return naviList 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/java/com/lxm/wanandroid/viewmodel/ProjectViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.lxm.wanandroid.viewmodel 2 | 3 | import android.arch.lifecycle.MutableLiveData 4 | import com.lxm.module_library.base.BaseViewModel 5 | import com.lxm.module_library.helper.RxHelper 6 | import com.lxm.wanandroid.repository.model.* 7 | import com.lxm.wanandroid.repository.remote.httpClient.RetrofitClient 8 | import io.reactivex.functions.Consumer 9 | 10 | class ProjectViewModel : BaseViewModel() { 11 | 12 | var mPage = 0 13 | val pagedList = MutableLiveData>>() 14 | val loadStatus by lazy { 15 | MutableLiveData>() 16 | } 17 | 18 | fun getProjects(): Listing>> { 19 | loadStatus.postValue(Resource.loading()) 20 | val subscribe = RetrofitClient.getInstance(RetrofitClient.WAN_BASE_URL).getProjectList(mPage) 21 | .compose(RxHelper.rxSchedulerHelper()) 22 | .subscribe(Consumer>> { 23 | if(it.data != null){ 24 | loadStatus.postValue(Resource.success()) 25 | pagedList.value = it 26 | }else{ 27 | loadStatus.postValue(Resource.error()) 28 | } 29 | 30 | }, Consumer { 31 | if (mPage > 0) { 32 | mPage-- 33 | } 34 | loadStatus.postValue(Resource.error()) 35 | }) 36 | addDisposable(subscribe) 37 | return Listing(pagedList,loadStatus) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /app/src/main/java/com/lxm/wanandroid/viewmodel/TreeViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.lxm.wanandroid.viewmodel 2 | 3 | import android.arch.lifecycle.MutableLiveData 4 | import com.lxm.module_library.base.BaseViewModel 5 | import com.lxm.module_library.helper.RxHelper 6 | import com.lxm.wanandroid.repository.model.Resource 7 | import com.lxm.wanandroid.repository.model.TreeBean 8 | import com.lxm.wanandroid.repository.remote.httpClient.RetrofitClient 9 | 10 | class TreeViewModel : BaseViewModel() { 11 | private val treeList = MutableLiveData>() 12 | val loadStatus by lazy { 13 | MutableLiveData>() 14 | } 15 | fun getTrees(): MutableLiveData> { 16 | RetrofitClient.getInstance(RetrofitClient.WAN_BASE_URL).getTrees() 17 | .compose(RxHelper.rxSchedulerHelper()) 18 | .subscribe({ 19 | treeList.postValue(it.data) 20 | }, { 21 | loadStatus.postValue(Resource.error()) 22 | }) 23 | return treeList 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/java/com/lxm/wanandroid/viewmodel/WelfareModelView.kt: -------------------------------------------------------------------------------- 1 | package com.lxm.wanandroid.viewmodel 2 | 3 | import android.arch.lifecycle.MutableLiveData 4 | import com.lxm.module_library.base.BaseViewModel 5 | import com.lxm.module_library.helper.RxHelper 6 | import com.lxm.wanandroid.repository.model.Resource 7 | import com.lxm.wanandroid.repository.model.WelfareResponse 8 | import com.lxm.wanandroid.repository.remote.httpClient.RetrofitClient 9 | const val PAGE_SIZE = 20 10 | class WelfareModelView : BaseViewModel() { 11 | 12 | var mPage = 1 13 | 14 | val loadStatus by lazy { 15 | MutableLiveData>() 16 | } 17 | fun getWelfare(): MutableLiveData { 18 | val welfare = MutableLiveData() 19 | RetrofitClient.getInstance(RetrofitClient.GAN_BASE_URL).getWelfare("福利",PAGE_SIZE,mPage) 20 | .compose(RxHelper.rxSchedulerHelper()) 21 | .subscribe({ 22 | welfare.postValue(it) 23 | }, { 24 | loadStatus.postValue(Resource.error()) 25 | }) 26 | return welfare 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/actionbar_more.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/malonecoder/Awesome-Kotlin-WanAndroid/2bf7cfa3624f547d5f64c741f653b3f6ac8bf7eb/app/src/main/res/drawable-hdpi/actionbar_more.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/actionbar_search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/malonecoder/Awesome-Kotlin-WanAndroid/2bf7cfa3624f547d5f64c741f653b3f6ac8bf7eb/app/src/main/res/drawable-hdpi/actionbar_search.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_about.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/malonecoder/Awesome-Kotlin-WanAndroid/2bf7cfa3624f547d5f64c741f653b3f6ac8bf7eb/app/src/main/res/drawable-hdpi/ic_about.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_article_new.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/malonecoder/Awesome-Kotlin-WanAndroid/2bf7cfa3624f547d5f64c741f653b3f6ac8bf7eb/app/src/main/res/drawable-hdpi/ic_article_new.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_collect.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/malonecoder/Awesome-Kotlin-WanAndroid/2bf7cfa3624f547d5f64c741f653b3f6ac8bf7eb/app/src/main/res/drawable-hdpi/ic_collect.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_collection.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/malonecoder/Awesome-Kotlin-WanAndroid/2bf7cfa3624f547d5f64c741f653b3f6ac8bf7eb/app/src/main/res/drawable-hdpi/ic_collection.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/malonecoder/Awesome-Kotlin-WanAndroid/2bf7cfa3624f547d5f64c741f653b3f6ac8bf7eb/app/src/main/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/malonecoder/Awesome-Kotlin-WanAndroid/2bf7cfa3624f547d5f64c741f653b3f6ac8bf7eb/app/src/main/res/drawable-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_login_menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/malonecoder/Awesome-Kotlin-WanAndroid/2bf7cfa3624f547d5f64c741f653b3f6ac8bf7eb/app/src/main/res/drawable-hdpi/ic_login_menu.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_logout_menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/malonecoder/Awesome-Kotlin-WanAndroid/2bf7cfa3624f547d5f64c741f653b3f6ac8bf7eb/app/src/main/res/drawable-hdpi/ic_logout_menu.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_main_search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/malonecoder/Awesome-Kotlin-WanAndroid/2bf7cfa3624f547d5f64c741f653b3f6ac8bf7eb/app/src/main/res/drawable-hdpi/ic_main_search.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_photo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/malonecoder/Awesome-Kotlin-WanAndroid/2bf7cfa3624f547d5f64c741f653b3f6ac8bf7eb/app/src/main/res/drawable-hdpi/ic_photo.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_un_collect.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/malonecoder/Awesome-Kotlin-WanAndroid/2bf7cfa3624f547d5f64c741f653b3f6ac8bf7eb/app/src/main/res/drawable-hdpi/ic_un_collect.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/icon_back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/malonecoder/Awesome-Kotlin-WanAndroid/2bf7cfa3624f547d5f64c741f653b3f6ac8bf7eb/app/src/main/res/drawable-hdpi/icon_back.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-xxhdpi/actionbar_search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/malonecoder/Awesome-Kotlin-WanAndroid/2bf7cfa3624f547d5f64c741f653b3f6ac8bf7eb/app/src/main/res/drawable-xxhdpi/actionbar_search.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/malonecoder/Awesome-Kotlin-WanAndroid/2bf7cfa3624f547d5f64c741f653b3f6ac8bf7eb/app/src/main/res/drawable-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/malonecoder/Awesome-Kotlin-WanAndroid/2bf7cfa3624f547d5f64c741f653b3f6ac8bf7eb/app/src/main/res/drawable-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/icon_back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/malonecoder/Awesome-Kotlin-WanAndroid/2bf7cfa3624f547d5f64c741f653b3f6ac8bf7eb/app/src/main/res/drawable-xxhdpi/icon_back.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/photo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/malonecoder/Awesome-Kotlin-WanAndroid/2bf7cfa3624f547d5f64c741f653b3f6ac8bf7eb/app/src/main/res/drawable-xxhdpi/photo.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/process_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/selector_bg_tree_tag.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/selector_collect_check.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_collection.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 16 | 17 | 25 | 26 | 27 | 28 | 32 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_login.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 16 | 17 | 25 | 26 | 27 | 28 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 17 | 18 | 28 | 29 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_show_image.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 11 | 12 | 21 | 22 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_web_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 | 15 | 16 | 20 | 21 | 32 | 33 | 43 | 44 | 45 | 46 | 49 | 50 | 56 | 57 | 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /app/src/main/res/layout/article_banner.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/layout/article_fragment.xml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 10 | 11 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /app/src/main/res/layout/category_activity.xml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 10 | 11 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /app/src/main/res/layout/drawer_header_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 20 | 21 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_banner.xml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_image_view_pager.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 11 | 12 | 17 | 18 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_tree.xml: -------------------------------------------------------------------------------- 1 | 2 | 14 | 15 | 26 | 27 | 39 | 40 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_tree_tag.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_view_welfare.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 17 | 18 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /app/src/main/res/layout/main_content.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 15 | 16 | 21 | 22 | 35 | 36 | 37 | 38 | 39 | 44 | -------------------------------------------------------------------------------- /app/src/main/res/layout/tree_fragment.xml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 10 | 11 | 12 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/res/menu/main.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/menu/navigation.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 13 | 17 | -------------------------------------------------------------------------------- /app/src/main/res/menu/webview_menu.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 10 | 11 | 16 | 17 | 22 | 23 | 28 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/malonecoder/Awesome-Kotlin-WanAndroid/2bf7cfa3624f547d5f64c741f653b3f6ac8bf7eb/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/malonecoder/Awesome-Kotlin-WanAndroid/2bf7cfa3624f547d5f64c741f653b3f6ac8bf7eb/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/malonecoder/Awesome-Kotlin-WanAndroid/2bf7cfa3624f547d5f64c741f653b3f6ac8bf7eb/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/malonecoder/Awesome-Kotlin-WanAndroid/2bf7cfa3624f547d5f64c741f653b3f6ac8bf7eb/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/malonecoder/Awesome-Kotlin-WanAndroid/2bf7cfa3624f547d5f64c741f653b3f6ac8bf7eb/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/malonecoder/Awesome-Kotlin-WanAndroid/2bf7cfa3624f547d5f64c741f653b3f6ac8bf7eb/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/photo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/malonecoder/Awesome-Kotlin-WanAndroid/2bf7cfa3624f547d5f64c741f653b3f6ac8bf7eb/app/src/main/res/mipmap-xhdpi/photo.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/malonecoder/Awesome-Kotlin-WanAndroid/2bf7cfa3624f547d5f64c741f653b3f6ac8bf7eb/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/malonecoder/Awesome-Kotlin-WanAndroid/2bf7cfa3624f547d5f64c741f653b3f6ac8bf7eb/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/values/attrs_circle_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #008577 4 | #00574B 5 | #D81B60 6 | 7 | 8 | #343434 9 | #F1F3F4 10 | #faebeb 11 | #FFFAFA 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | WanAndroidKotlin 3 | 打开 4 | 关闭 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/test/java/com/lxm/wanandroid/ExampleUnitTest.kt: -------------------------------------------------------------------------------- 1 | package com.lxm.wanandroid 2 | 3 | import org.junit.Test 4 | 5 | import org.junit.Assert.* 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * See [testing documentation](http://d.android.com/tools/testing). 11 | */ 12 | class ExampleUnitTest { 13 | @Test 14 | fun addition_isCorrect() { 15 | assertEquals(4, 2 + 2) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | ext.kotlin_version = '1.3.21' 5 | repositories { 6 | google() 7 | jcenter() 8 | maven { url 'https://jitpack.io' } 9 | } 10 | dependencies { 11 | classpath 'com.android.tools.build:gradle:3.4.0' 12 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 13 | // NOTE: Do not place your application dependencies here; they belong 14 | // in the individual module build.gradle files 15 | } 16 | } 17 | 18 | allprojects { 19 | repositories { 20 | google() 21 | jcenter() 22 | maven { url 'https://jitpack.io' } 23 | } 24 | } 25 | 26 | task clean(type: Delete) { 27 | delete rootProject.buildDir 28 | } 29 | 30 | ext{ 31 | 32 | retrofitVersion = '2.2.0' 33 | okhttploggingVersion = '3.4.1' 34 | okhttpVersion = '3.4.1' 35 | rxjavaVersion = '2.0.1' 36 | rxandroidVersion = '2.0.1' 37 | rxbindingVersion = '2.0.0' 38 | constraintVersion = '1.1.2' 39 | butterknifeVwesion = '8.8.1' 40 | glideVersion = '4.9.0' 41 | glide_transformations = '3.0.1' 42 | } -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | # IDE (e.g. Android Studio) users: 3 | # Gradle settings configured through the IDE *will override* 4 | # any settings specified in this file. 5 | # For more details on how to configure your build environment visit 6 | # http://www.gradle.org/docs/current/userguide/build_environment.html 7 | # Specifies the JVM arguments used for the daemon process. 8 | # The setting is particularly useful for tweaking memory settings. 9 | org.gradle.jvmargs=-Xmx1536m 10 | # When configured, Gradle will run in incubating parallel mode. 11 | # This option should only be used with decoupled projects. More details, visit 12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 13 | # org.gradle.parallel=true 14 | # Kotlin code style for this project: "official" or "obsolete": 15 | kotlin.code.style=official 16 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/malonecoder/Awesome-Kotlin-WanAndroid/2bf7cfa3624f547d5f64c741f653b3f6ac8bf7eb/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Thu Jun 13 22:10:05 CST 2019 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip 7 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /module_library/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /module_library/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | apply plugin: 'kotlin-android-extensions' 3 | apply plugin: 'kotlin-android' 4 | apply plugin: 'kotlin-kapt' 5 | 6 | android { 7 | compileSdkVersion 28 8 | 9 | 10 | defaultConfig { 11 | minSdkVersion 21 12 | targetSdkVersion 28 13 | versionCode 1 14 | versionName "1.0" 15 | 16 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 17 | 18 | } 19 | 20 | buildTypes { 21 | release { 22 | minifyEnabled false 23 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 24 | } 25 | } 26 | compileOptions { 27 | sourceCompatibility = '1.8' 28 | targetCompatibility = '1.8' 29 | } 30 | 31 | } 32 | 33 | dependencies { 34 | implementation fileTree(dir: 'libs', include: ['*.jar']) 35 | //动画 36 | implementation ('com.github.ozodrukh:CircularReveal:2.0.1@aar') { 37 | transitive = true; 38 | } 39 | implementation 'com.android.support:appcompat-v7:28.0.0' 40 | implementation "com.android.support:design:28.0.0" 41 | testImplementation 'junit:junit:4.12' 42 | androidTestImplementation 'com.android.support.test:runner:1.0.2' 43 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' 44 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 45 | implementation 'com.android.support:design:28.0.0' 46 | 47 | // Retrofit & okHttp 48 | api "com.squareup.retrofit2:retrofit:$rootProject.retrofitVersion" 49 | api "com.squareup.retrofit2:converter-gson:$rootProject.retrofitVersion" 50 | api "com.squareup.retrofit2:adapter-rxjava2:$rootProject.retrofitVersion" 51 | api "com.squareup.okhttp3:logging-interceptor:$rootProject.okhttploggingVersion" 52 | api "com.squareup.okhttp3:okhttp:$rootProject.okhttpVersion" 53 | 54 | // RxBinging 55 | api "com.jakewharton.rxbinding2:rxbinding-appcompat-v7:$rootProject.rxbindingVersion" 56 | 57 | // Glide 58 | api "com.github.bumptech.glide:glide:$rootProject.glideVersion" 59 | annotationProcessor "com.github.bumptech.glide:compiler:$rootProject.glideVersion" 60 | // 高斯模糊和圆角等 61 | api 'jp.wasabeef:glide-transformations:4.0.1' 62 | 63 | //page 64 | def paging_version = "1.0.0" 65 | api "android.arch.paging:runtime:$paging_version" 66 | testImplementation "android.arch.paging:common:$paging_version" 67 | api 'android.arch.paging:rxjava2:1.0.0-rc1' 68 | 69 | //lifecycle 70 | def lifecycle_version = "1.1.1" 71 | api "android.arch.lifecycle:extensions:$lifecycle_version" 72 | api "android.arch.lifecycle:viewmodel:$lifecycle_version" 73 | api "android.arch.lifecycle:livedata:$lifecycle_version" 74 | api "android.arch.lifecycle:runtime:$lifecycle_version" 75 | annotationProcessor "android.arch.lifecycle:compiler:$lifecycle_version" 76 | api "android.arch.lifecycle:reactivestreams:$lifecycle_version" 77 | 78 | //toast 79 | implementation 'me.drakeet.support:toastcompat:1.1.0' 80 | 81 | 82 | } 83 | repositories { 84 | mavenCentral() 85 | } 86 | -------------------------------------------------------------------------------- /module_library/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /module_library/src/androidTest/java/com/lxm/module_library/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.lxm.module_library; 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() { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.lxm.module_library.test", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /module_library/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /module_library/src/main/java/com/lxm/module_library/anim/AnimManager.kt: -------------------------------------------------------------------------------- 1 | package com.lxm.module_library.anim 2 | import android.content.Context 3 | import android.os.Build 4 | import android.view.View 5 | import android.view.animation.AnimationUtils 6 | 7 | /** 8 | * Created by Horrarndoo on 2017/9/11. 9 | * 10 | * 11 | */ 12 | 13 | object AnimManager { 14 | /** 15 | * Alpha and scaleX 动画 16 | * Alpha 0->1 17 | * ScaleX 0.8->1 18 | * 19 | * @param context context 20 | * @param view view 21 | * @param startDelay 动画开始前延时(ms) 22 | * @param duration 动画持续时间(ms) 23 | */ 24 | fun animAlphaAndScaleX(context: Context, view: View, startDelay: Int, duration: Int) { 25 | view.alpha = 0f 26 | view.scaleX = 0.8f 27 | 28 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 29 | view.animate() 30 | .alpha(1f) 31 | .scaleX(1f) 32 | .setStartDelay(startDelay.toLong()) 33 | .setDuration(duration.toLong()) 34 | .setInterpolator(AnimUtils.getFastOutSlowInInterpolator(context)) 35 | .start() 36 | } else { 37 | view.animate() 38 | .alpha(1f) 39 | .scaleX(1f) 40 | .setStartDelay(startDelay.toLong()) 41 | .setDuration(duration.toLong()) 42 | .setInterpolator(AnimationUtils.loadInterpolator(context, android.R.interpolator.linear)) 43 | .start() 44 | } 45 | } 46 | 47 | /** 48 | * Alpha and scale X Y 动画 49 | * Alpha 0->1 50 | * ScaleX 0->1 51 | * ScaleY 0->1 52 | * 53 | * @param context context 54 | * @param view view 55 | * @param startDelay 动画开始前延时(ms) 56 | * @param duration 动画持续时间(ms) 57 | */ 58 | fun animAlphaAndScale(context: Context, view: View, startDelay: Int, duration: Int) { 59 | view.alpha = 0f 60 | view.scaleX = 0f 61 | view.scaleY = 0f 62 | 63 | view.animate() 64 | .alpha(1f) 65 | .scaleX(1f) 66 | .scaleY(1f) 67 | .setStartDelay(startDelay.toLong()) 68 | .setDuration(duration.toLong()) 69 | .setInterpolator(AnimationUtils.loadInterpolator(context, 70 | android.R.interpolator.overshoot)).start() 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /module_library/src/main/java/com/lxm/module_library/anim/ToolbarAnimManager.kt: -------------------------------------------------------------------------------- 1 | package com.lxm.module_library.anim 2 | 3 | import android.content.Context 4 | import android.support.v7.widget.ActionMenuView 5 | import android.support.v7.widget.Toolbar 6 | import android.widget.ImageButton 7 | import android.widget.TextView 8 | import com.lxm.module_library.anim.AnimManager 9 | 10 | /** 11 | * 12 | * @date 2017/9/11 13 | * 14 | * 15 | * Toolbar动画Manager 16 | */ 17 | 18 | object ToolbarAnimManager { 19 | /** 20 | * Toolbar 进场动画 21 | * 22 | * 23 | * ActionMenuView渐变动画 24 | * 25 | * @param context context 26 | * @param toolbar toolbar 27 | */ 28 | fun animIn(context: Context, toolbar: Toolbar) { 29 | var ibIcon: ImageButton? = null 30 | var tvTitle: TextView? = null 31 | var amvTheme: ActionMenuView? = null 32 | val childCount = toolbar.childCount 33 | for (i in 0 until childCount) { 34 | val child = toolbar.getChildAt(i) 35 | if (child is ImageButton) { 36 | ibIcon = child 37 | continue 38 | } 39 | 40 | if (child is ActionMenuView) { 41 | amvTheme = child 42 | continue 43 | } 44 | 45 | if (child is TextView) { 46 | tvTitle = child 47 | } 48 | } 49 | 50 | if (ibIcon != null) { 51 | animNavigationIcon(context, ibIcon) 52 | } 53 | 54 | if (tvTitle != null) { 55 | animTitle(context, tvTitle) 56 | } 57 | 58 | if (amvTheme != null) { 59 | animMenu(context, amvTheme) 60 | } 61 | } 62 | 63 | /** 64 | * Toolbar Title动画 65 | * 66 | * 67 | * NavigationIcon渐变动画 68 | * 69 | * @param context context 70 | * @param imageButton 执行动画的view 71 | */ 72 | private fun animNavigationIcon(context: Context, imageButton: ImageButton) { 73 | AnimManager.animAlphaAndScaleX(context, imageButton, 500, 900) 74 | } 75 | 76 | /** 77 | * Toolbar Title动画 78 | * 79 | * 80 | * ActionMenuView渐变动画 81 | * 82 | * @param context context 83 | * @param textView 执行动画的view 84 | */ 85 | private fun animTitle(context: Context, textView: TextView) { 86 | AnimManager.animAlphaAndScaleX(context, textView, 500, 900) 87 | } 88 | 89 | /** 90 | * Toolbar ActionMenuView动画 91 | * 92 | * 93 | * ActionMenuView渐变动画 94 | * 95 | * @param context context 96 | * @param avm 执行动画的view 97 | */ 98 | private fun animMenu(context: Context, avm: ActionMenuView) { 99 | AnimManager.animAlphaAndScale(context, avm, 500, 200) // filter 100 | AnimManager.animAlphaAndScale(context, avm, 700, 200) // overflow 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /module_library/src/main/java/com/lxm/module_library/base/BaseViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.lxm.module_library.base 2 | 3 | import android.arch.lifecycle.ViewModel 4 | import io.reactivex.disposables.CompositeDisposable 5 | import io.reactivex.disposables.Disposable 6 | 7 | open class BaseViewModel : ViewModel() { 8 | 9 | private var mCompositeDisposable: CompositeDisposable? = null 10 | 11 | 12 | protected fun addDisposable(disposable: Disposable) { 13 | if (this.mCompositeDisposable == null) { 14 | this.mCompositeDisposable = CompositeDisposable() 15 | } 16 | this.mCompositeDisposable?.add(disposable) 17 | } 18 | 19 | override fun onCleared() { 20 | super.onCleared() 21 | if (this.mCompositeDisposable != null && !mCompositeDisposable?.isDisposed!!) { 22 | this.mCompositeDisposable?.clear() 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /module_library/src/main/java/com/lxm/module_library/base/NoViewModel.java: -------------------------------------------------------------------------------- 1 | package com.lxm.module_library.base; 2 | 3 | import android.arch.lifecycle.ViewModel; 4 | 5 | public class NoViewModel extends ViewModel { 6 | 7 | } 8 | -------------------------------------------------------------------------------- /module_library/src/main/java/com/lxm/module_library/global/AppManager.java: -------------------------------------------------------------------------------- 1 | package com.lxm.module_library.global; 2 | 3 | import android.app.Activity; 4 | import android.app.ActivityManager; 5 | import android.content.Context; 6 | 7 | import java.util.Stack; 8 | 9 | /** 10 | * Created by Horrarndoo on 2017/4/5. 11 | *

12 | * AppManager 管理Activity栈 13 | */ 14 | 15 | public class AppManager { 16 | private static Stack activityStack; 17 | private static AppManager instance; 18 | 19 | private AppManager() { 20 | } 21 | 22 | /** 23 | * 单一实例 24 | */ 25 | public static AppManager getAppManager() { 26 | if (instance == null) { 27 | instance = new AppManager(); 28 | } 29 | return instance; 30 | } 31 | 32 | /** 33 | * 添加Activity到堆栈 34 | */ 35 | public void addActivity(Activity activity) { 36 | if (activityStack == null) { 37 | activityStack = new Stack(); 38 | } 39 | activityStack.add(activity); 40 | } 41 | 42 | /** 43 | * 获取当前Activity(堆栈中最后一个压入的) 44 | */ 45 | public Activity currentActivity() { 46 | Activity activity = activityStack.lastElement(); 47 | return activity; 48 | } 49 | 50 | /** 51 | * 结束当前Activity(堆栈中最后一个压入的) 52 | */ 53 | public void finishActivity() { 54 | Activity activity = activityStack.lastElement(); 55 | finishActivity(activity); 56 | } 57 | 58 | /** 59 | * 结束指定的Activity 60 | */ 61 | public void finishActivity(Activity activity) { 62 | if (activity != null) { 63 | activityStack.remove(activity); 64 | activity.finish(); 65 | activity = null; 66 | } 67 | } 68 | 69 | /** 70 | * 结束指定类名的Activity 71 | */ 72 | public void finishActivity(Class cls) { 73 | for (Activity activity : activityStack) { 74 | if (activity.getClass().equals(cls)) { 75 | finishActivity(activity); 76 | } 77 | } 78 | } 79 | 80 | /** 81 | * 结束所有Activity 82 | */ 83 | public void finishAllActivity() { 84 | for (int i = 0, size = activityStack.size(); i < size; i++) { 85 | if (null != activityStack.get(i)) { 86 | activityStack.get(i).finish(); 87 | } 88 | } 89 | activityStack.clear(); 90 | } 91 | 92 | /** 93 | * 退出应用程序 94 | */ 95 | public void AppExit(Context context) { 96 | try { 97 | finishAllActivity(); 98 | ActivityManager activityMgr = 99 | (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); 100 | activityMgr.killBackgroundProcesses(context.getPackageName()); 101 | System.exit(0); 102 | } catch (Exception e) { 103 | } 104 | } 105 | 106 | public boolean isAppExit() { 107 | return activityStack == null || activityStack.isEmpty(); 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /module_library/src/main/java/com/lxm/module_library/global/GlobalApplication.java: -------------------------------------------------------------------------------- 1 | package com.lxm.module_library.global; 2 | 3 | import android.app.Application; 4 | import android.content.Context; 5 | import android.os.Handler; 6 | import com.lxm.module_library.utils.PreferencesUtil; 7 | 8 | 9 | /** 10 | * Created by Horrarndoo on 2017/9/1. 11 | *

12 | * 全局Application 13 | */ 14 | 15 | public class GlobalApplication extends Application { 16 | protected static Context context; 17 | protected static Handler handler; 18 | protected static int mainThreadId; 19 | 20 | private static GlobalApplication globalApplication; 21 | 22 | public static GlobalApplication getInstance() { 23 | return globalApplication; 24 | } 25 | 26 | @Override 27 | public void onCreate() { 28 | super.onCreate(); 29 | globalApplication = this; 30 | context = getApplicationContext(); 31 | handler = new Handler(); 32 | mainThreadId = android.os.Process.myTid(); 33 | PreferencesUtil.Companion.get(this); 34 | 35 | } 36 | 37 | /** 38 | * 获取上下文对象 39 | * 40 | * @return context 41 | */ 42 | public static Context getContext() { 43 | return context; 44 | } 45 | 46 | /** 47 | * 获取全局handler 48 | * 49 | * @return 全局handler 50 | */ 51 | public static Handler getHandler() { 52 | return handler; 53 | } 54 | 55 | /** 56 | * 获取主线程id 57 | * 58 | * @return 主线程id 59 | */ 60 | public static int getMainThreadId() { 61 | return mainThreadId; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /module_library/src/main/java/com/lxm/module_library/helper/RetrofitCreateHelper.java: -------------------------------------------------------------------------------- 1 | package com.lxm.module_library.helper; 2 | 3 | import com.lxm.module_library.utils.AppUtils; 4 | import com.lxm.module_library.helper.okhttp.TrustManager; 5 | import com.lxm.module_library.helper.okhttp.cache.CacheInterceptor; 6 | import com.lxm.module_library.helper.okhttp.cache.HttpCache; 7 | import com.lxm.module_library.helper.okhttp.cookies.CookieManger; 8 | import okhttp3.OkHttpClient; 9 | import okhttp3.logging.HttpLoggingInterceptor; 10 | import retrofit2.Retrofit; 11 | import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory; 12 | import retrofit2.converter.gson.GsonConverterFactory; 13 | 14 | import java.util.concurrent.TimeUnit; 15 | 16 | /** 17 | * Created by Horrarndoo on 2017/9/7. 18 | *

19 | */ 20 | 21 | public class RetrofitCreateHelper { 22 | private static final int TIMEOUT_READ = 5; 23 | private static final int TIMEOUT_CONNECTION = 5; 24 | private static final HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor() 25 | .setLevel(HttpLoggingInterceptor.Level.BODY); 26 | private static CacheInterceptor cacheInterceptor = new CacheInterceptor(); 27 | private static OkHttpClient okHttpClient = new OkHttpClient.Builder() 28 | //SSL证书 29 | .sslSocketFactory(TrustManager.getUnsafeOkHttpClient()) 30 | .hostnameVerifier(org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER) 31 | //打印日志 32 | .addInterceptor(interceptor) 33 | //设置Cache拦截器 34 | .addNetworkInterceptor(cacheInterceptor) 35 | .addInterceptor(cacheInterceptor) 36 | .cache(HttpCache.getCache()) 37 | // 设置 Cookie 38 | .cookieJar(new CookieManger(AppUtils.INSTANCE.getContext())) 39 | //time out 40 | .connectTimeout(TIMEOUT_CONNECTION, TimeUnit.SECONDS) 41 | .readTimeout(TIMEOUT_READ, TimeUnit.SECONDS) 42 | .writeTimeout(TIMEOUT_READ, TimeUnit.SECONDS) 43 | //失败重连 44 | .retryOnConnectionFailure(true) 45 | .build(); 46 | 47 | 48 | public static T createApi(Class clazz, String url) { 49 | Retrofit retrofit = new Retrofit.Builder() 50 | .baseUrl(url) 51 | .client(okHttpClient) 52 | .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) 53 | .addConverterFactory(GsonConverterFactory.create()) 54 | .build(); 55 | return retrofit.create(clazz); 56 | } 57 | } 58 | 59 | -------------------------------------------------------------------------------- /module_library/src/main/java/com/lxm/module_library/helper/RxHelper.java: -------------------------------------------------------------------------------- 1 | package com.lxm.module_library.helper; 2 | 3 | 4 | import io.reactivex.*; 5 | import io.reactivex.android.schedulers.AndroidSchedulers; 6 | import io.reactivex.schedulers.Schedulers; 7 | 8 | /** 9 | * Created by Horrarndoo on 2017/9/12. 10 | *

11 | */ 12 | public class RxHelper { 13 | 14 | /** 15 | * 统一线程处理 16 | *

17 | * 发布事件io线程,接收事件主线程 18 | */ 19 | public static ObservableTransformer rxSchedulerHelper() {//compose处理线程 20 | return new ObservableTransformer() { 21 | 22 | @Override 23 | public ObservableSource apply(Observable upstream) { 24 | return upstream.subscribeOn(Schedulers.io()) 25 | .observeOn(AndroidSchedulers.mainThread()); 26 | } 27 | }; 28 | } 29 | 30 | /** 31 | * 生成Flowable 32 | * 33 | * @param t 34 | * @return Flowable 35 | */ 36 | public static Flowable createFlowable(final T t) { 37 | return Flowable.create(new FlowableOnSubscribe() { 38 | @Override 39 | public void subscribe(FlowableEmitter emitter) throws Exception { 40 | try { 41 | emitter.onNext(t); 42 | emitter.onComplete(); 43 | } catch (Exception e) { 44 | emitter.onError(e); 45 | } 46 | } 47 | }, BackpressureStrategy.BUFFER); 48 | } 49 | 50 | /** 51 | * 生成Observable 52 | * 53 | * @param t 54 | * @return Flowable 55 | */ 56 | public static Observable createObservable(final T t) { 57 | return Observable.create(new ObservableOnSubscribe() { 58 | @Override 59 | public void subscribe(ObservableEmitter emitter) throws Exception { 60 | try { 61 | emitter.onNext(t); 62 | emitter.onComplete(); 63 | } catch (Exception e) { 64 | emitter.onError(e); 65 | } 66 | } 67 | }); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /module_library/src/main/java/com/lxm/module_library/helper/okhttp/TrustManager.java: -------------------------------------------------------------------------------- 1 | package com.lxm.module_library.helper.okhttp; 2 | 3 | import javax.net.ssl.SSLContext; 4 | import javax.net.ssl.SSLSocketFactory; 5 | import javax.net.ssl.X509TrustManager; 6 | import java.security.cert.CertificateException; 7 | import java.security.cert.X509Certificate; 8 | 9 | /** 10 | * Created by Horrarndoo on 2017/9/12. 11 | *

12 | */ 13 | public class TrustManager { 14 | 15 | public static SSLSocketFactory getUnsafeOkHttpClient() { 16 | try { 17 | // Create a trust manager that does not validate certificate chains 18 | final X509TrustManager[] trustAllCerts = new X509TrustManager[]{new X509TrustManager() { 19 | @Override 20 | public void checkClientTrusted( 21 | X509Certificate[] chain, 22 | String authType) throws CertificateException { 23 | } 24 | 25 | @Override 26 | public void checkServerTrusted( 27 | X509Certificate[] chain, 28 | String authType) throws CertificateException { 29 | } 30 | 31 | @Override 32 | public X509Certificate[] getAcceptedIssuers() { 33 | return new X509Certificate[0]; 34 | } 35 | }}; 36 | 37 | // Install the all-trusting trust manager 38 | final SSLContext sslContext = SSLContext.getInstance("TLS"); 39 | sslContext.init(null, trustAllCerts, 40 | new java.security.SecureRandom()); 41 | // Create an ssl socket factory with our all-trusting manager 42 | final SSLSocketFactory sslSocketFactory = sslContext 43 | .getSocketFactory(); 44 | 45 | 46 | return sslSocketFactory; 47 | } catch (Exception e) { 48 | throw new RuntimeException(e); 49 | } 50 | 51 | } 52 | } 53 | 54 | -------------------------------------------------------------------------------- /module_library/src/main/java/com/lxm/module_library/helper/okhttp/cache/CacheInterceptor.java: -------------------------------------------------------------------------------- 1 | package com.lxm.module_library.helper.okhttp.cache; 2 | 3 | 4 | import com.lxm.module_library.utils.AppUtils; 5 | import com.lxm.module_library.utils.HttpUtils; 6 | import com.lxm.module_library.utils.NetworkConnectionUtils; 7 | import okhttp3.CacheControl; 8 | import okhttp3.Interceptor; 9 | import okhttp3.Request; 10 | import okhttp3.Response; 11 | 12 | import java.io.IOException; 13 | 14 | 15 | /** 16 | * Created by Horrarndoo on 2017/9/12. 17 | *

18 | * CacheInterceptor 19 | */ 20 | public class CacheInterceptor implements Interceptor { 21 | 22 | @Override 23 | public Response intercept(Chain chain) throws IOException { 24 | Request request = chain.request(); 25 | if (NetworkConnectionUtils.INSTANCE.isNetworkConnected(AppUtils.INSTANCE.getContext())) { 26 | // 有网络时, 缓存60s 27 | int maxAge = 10 ; 28 | request = request.newBuilder() 29 | .removeHeader("User-Agent") 30 | .header("User-Agent", HttpUtils.INSTANCE.getUserAgent()) 31 | .build(); 32 | 33 | Response response = chain.proceed(request); 34 | return response.newBuilder() 35 | .removeHeader("Pragma") 36 | .removeHeader("Cache-Control") 37 | .header("Cache-Control", "public, max-age=" + maxAge) 38 | .build(); 39 | } else { 40 | // 无网络时,缓存为4周 41 | int maxStale = 60 * 60 * 24 * 28; 42 | request = request.newBuilder() 43 | .cacheControl(CacheControl.FORCE_CACHE) 44 | .removeHeader("User-Agent") 45 | .header("User-Agent", HttpUtils.INSTANCE.getUserAgent()) 46 | .build(); 47 | 48 | Response response = chain.proceed(request); 49 | return response.newBuilder() 50 | .removeHeader("Pragma") 51 | .removeHeader("Cache-Control") 52 | .header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale) 53 | .build(); 54 | } 55 | 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /module_library/src/main/java/com/lxm/module_library/helper/okhttp/cache/HttpCache.java: -------------------------------------------------------------------------------- 1 | package com.lxm.module_library.helper.okhttp.cache; 2 | 3 | import com.lxm.module_library.utils.AppUtils; 4 | import okhttp3.Cache; 5 | 6 | import java.io.File; 7 | 8 | /** 9 | * Created by Horrarndoo on 2017/9/12. 10 | *

11 | */ 12 | public class HttpCache { 13 | 14 | private static final int HTTP_RESPONSE_DISK_CACHE_MAX_SIZE = 50 * 1024 * 1024; 15 | 16 | public static Cache getCache() { 17 | return new Cache(new File(AppUtils.INSTANCE.getContext().getExternalCacheDir().getAbsolutePath() + File 18 | .separator + "data/NetCache"), 19 | HTTP_RESPONSE_DISK_CACHE_MAX_SIZE); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /module_library/src/main/java/com/lxm/module_library/helper/okhttp/cookies/CookieManger.java: -------------------------------------------------------------------------------- 1 | package com.lxm.module_library.helper.okhttp.cookies; 2 | 3 | import android.content.Context; 4 | import okhttp3.Cookie; 5 | import okhttp3.CookieJar; 6 | import okhttp3.HttpUrl; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * Created by CoderLengary 12 | */ 13 | 14 | 15 | public class CookieManger implements CookieJar { 16 | 17 | 18 | private static Context mContext; 19 | 20 | private static PersistentCookieStore cookieStore; 21 | 22 | public CookieManger(Context context) { 23 | mContext = context; 24 | if (cookieStore == null) { 25 | cookieStore = new PersistentCookieStore(mContext); 26 | } 27 | 28 | } 29 | 30 | 31 | @Override 32 | public void saveFromResponse(HttpUrl url, List cookies) { 33 | if (cookies != null && cookies.size() > 0) { 34 | for (Cookie item : cookies) { 35 | cookieStore.add(url, item); 36 | } 37 | } 38 | } 39 | 40 | @Override 41 | public List loadForRequest(HttpUrl url) { 42 | List cookies = cookieStore.get(url); 43 | return cookies; 44 | } 45 | 46 | public static void clearAllCookies() { 47 | cookieStore.removeAll(); 48 | } 49 | 50 | 51 | } -------------------------------------------------------------------------------- /module_library/src/main/java/com/lxm/module_library/helper/okhttp/cookies/OkHttpCookies.java: -------------------------------------------------------------------------------- 1 | package com.lxm.module_library.helper.okhttp.cookies; 2 | 3 | import okhttp3.Cookie; 4 | 5 | import java.io.IOException; 6 | import java.io.ObjectInputStream; 7 | import java.io.ObjectOutputStream; 8 | import java.io.Serializable; 9 | 10 | 11 | public class OkHttpCookies implements Serializable { 12 | 13 | private transient final Cookie cookies; 14 | private transient Cookie clientCookies; 15 | 16 | public OkHttpCookies(Cookie cookies) { 17 | this.cookies = cookies; 18 | } 19 | 20 | public Cookie getCookies() { 21 | Cookie bestCookies = cookies; 22 | if (clientCookies != null) { 23 | bestCookies = clientCookies; 24 | } 25 | return bestCookies; 26 | } 27 | 28 | private void writeObject(ObjectOutputStream out) throws IOException { 29 | out.writeObject(cookies.name()); 30 | out.writeObject(cookies.value()); 31 | out.writeLong(cookies.expiresAt()); 32 | out.writeObject(cookies.domain()); 33 | out.writeObject(cookies.path()); 34 | out.writeBoolean(cookies.secure()); 35 | out.writeBoolean(cookies.httpOnly()); 36 | out.writeBoolean(cookies.hostOnly()); 37 | out.writeBoolean(cookies.persistent()); 38 | } 39 | 40 | private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { 41 | String name = (String) in.readObject(); 42 | String value = (String) in.readObject(); 43 | long expiresAt = in.readLong(); 44 | String domain = (String) in.readObject(); 45 | String path = (String) in.readObject(); 46 | boolean secure = in.readBoolean(); 47 | boolean httpOnly = in.readBoolean(); 48 | boolean hostOnly = in.readBoolean(); 49 | Cookie.Builder builder = new Cookie.Builder(); 50 | builder = builder.name(name); 51 | builder = builder.value(value); 52 | builder = builder.expiresAt(expiresAt); 53 | builder = hostOnly ? builder.hostOnlyDomain(domain) : builder.domain(domain); 54 | builder = builder.path(path); 55 | builder = secure ? builder.secure() : builder; 56 | builder = httpOnly ? builder.httpOnly() : builder; 57 | clientCookies = builder.build(); 58 | } 59 | } -------------------------------------------------------------------------------- /module_library/src/main/java/com/lxm/module_library/materialLogin/RegisterView.java: -------------------------------------------------------------------------------- 1 | package com.lxm.module_library.materialLogin; 2 | 3 | import android.view.View; 4 | 5 | /** 6 | * Created by shem on 16/09/2016. 7 | */ 8 | public interface RegisterView { 9 | 10 | View getCancelRegisterView(); 11 | } 12 | -------------------------------------------------------------------------------- /module_library/src/main/java/com/lxm/module_library/statusbar/StatusBarView.java: -------------------------------------------------------------------------------- 1 | package com.lxm.module_library.statusbar; 2 | 3 | import android.content.Context; 4 | import android.util.AttributeSet; 5 | import android.view.View; 6 | 7 | /** 8 | * Created by Jaeger on 16/6/8. 9 | * 10 | * Email: chjie.jaeger@gmail.com 11 | * GitHub: https://github.com/laobie 12 | */ 13 | public class StatusBarView extends View { 14 | public StatusBarView(Context context, AttributeSet attrs) { 15 | super(context, attrs); 16 | } 17 | 18 | public StatusBarView(Context context) { 19 | super(context); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /module_library/src/main/java/com/lxm/module_library/utils/CheckNetwork.java: -------------------------------------------------------------------------------- 1 | package com.lxm.module_library.utils; 2 | 3 | import android.content.Context; 4 | import android.net.ConnectivityManager; 5 | import android.net.NetworkInfo; 6 | 7 | /** 8 | * 用于判断是不是联网状态 9 | * 10 | * @author Dzy 11 | */ 12 | public class CheckNetwork { 13 | 14 | /** 15 | * 判断网络是否连通 16 | */ 17 | public static boolean isNetworkConnected(Context context) { 18 | try { 19 | if(context!=null){ 20 | @SuppressWarnings("static-access") 21 | ConnectivityManager cm = (ConnectivityManager) context 22 | .getSystemService(context.CONNECTIVITY_SERVICE); 23 | NetworkInfo info = cm.getActiveNetworkInfo(); 24 | return info != null && info.isConnected(); 25 | }else{ 26 | /**如果context为空,就返回false,表示网络未连接*/ 27 | return false; 28 | } 29 | }catch (Exception e){ 30 | e.printStackTrace(); 31 | return false; 32 | } 33 | 34 | 35 | } 36 | 37 | public static boolean isWifiConnected(Context context) { 38 | if (context != null) { 39 | ConnectivityManager cm = (ConnectivityManager) context 40 | .getSystemService(context.CONNECTIVITY_SERVICE); 41 | NetworkInfo info = cm.getActiveNetworkInfo(); 42 | return info != null && (info.getType() == ConnectivityManager.TYPE_WIFI); 43 | } else { 44 | /**如果context为null就表示为未连接*/ 45 | return false; 46 | } 47 | 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /module_library/src/main/java/com/lxm/module_library/utils/ClassUtil.kt: -------------------------------------------------------------------------------- 1 | package com.lxm.module_library.utils 2 | 3 | import android.arch.lifecycle.AndroidViewModel 4 | import android.arch.lifecycle.ViewModel 5 | import com.lxm.module_library.base.NoViewModel 6 | import java.lang.reflect.ParameterizedType 7 | 8 | 9 | object ClassUtil { 10 | 11 | /** 12 | * 获取泛型ViewModel的class对象 13 | */ 14 | fun getViewModel(obj: Any): Class? { 15 | val currentClass = obj.javaClass 16 | val tClass = getGenericClass(currentClass, ViewModel::class.java) 17 | return if (tClass == null || tClass == AndroidViewModel::class.java || tClass == NoViewModel::class.java) { 18 | null 19 | } else tClass 20 | } 21 | 22 | private fun getGenericClass(klass: Class<*>, filterClass: Class<*>): Class? { 23 | val type = klass.genericSuperclass 24 | if (type == null || type !is ParameterizedType) return null 25 | val types = type.actualTypeArguments 26 | for (t in types) { 27 | val tClass = t as Class 28 | if (filterClass.isAssignableFrom(tClass)) { 29 | return tClass 30 | } 31 | } 32 | return null 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /module_library/src/main/java/com/lxm/module_library/utils/DialogUtils.kt: -------------------------------------------------------------------------------- 1 | package com.lxm.module_library.utils 2 | 3 | import android.app.Dialog 4 | import android.content.Context 5 | import android.content.DialogInterface 6 | import android.support.v7.app.AlertDialog 7 | 8 | 9 | /** 10 | * Created by Horrarndoo on 2017/8/31. 11 | * 12 | * 对话框工具类, 提供常用对话框显示, 使用support.v7包内的AlertDialog样式 13 | */ 14 | object DialogUtils { 15 | 16 | 17 | fun showCommonDialog(context: Context, message: String, positiveText: String, 18 | negativeText: String, listener: DialogInterface.OnClickListener): Dialog { 19 | return AlertDialog.Builder(context) 20 | .setMessage(message) 21 | .setPositiveButton(positiveText, listener) 22 | .setNegativeButton(negativeText, null) 23 | .show() 24 | } 25 | 26 | fun showConfirmDialog(context: Context, message: String, positiveText: String, 27 | listener: DialogInterface.OnClickListener): Dialog { 28 | return AlertDialog.Builder(context) 29 | .setMessage(message) 30 | .setPositiveButton(positiveText, listener) 31 | .show() 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /module_library/src/main/java/com/lxm/module_library/utils/HtmlUtils.kt: -------------------------------------------------------------------------------- 1 | package com.lxm.module_library.utils 2 | 3 | /** 4 | * Created by Horrarndoo on 2017/8/31. 5 | * 6 | * Html工具类 7 | */ 8 | object HtmlUtils { 9 | 10 | /** 11 | * css样式,隐藏header 12 | */ 13 | private const val HIDE_HEADER_STYLE = "" 14 | 15 | /** 16 | * css style tag,需要格式化 17 | */ 18 | private const val NEEDED_FORMAT_CSS_TAG = "" 19 | 20 | /** 21 | * js script tag,需要格式化 22 | */ 23 | private const val NEEDED_FORMAT_JS_TAG = "" 24 | 25 | val MIME_TYPE = "text/html; charset=utf-8" 26 | 27 | val ENCODING = "utf-8" 28 | 29 | /** 30 | * 根据css链接生成Link标签 31 | * 32 | * @param url String 33 | * @return String 34 | */ 35 | fun createCssTag(url: String): String { 36 | 37 | return String.format(NEEDED_FORMAT_CSS_TAG, url) 38 | } 39 | 40 | /** 41 | * 根据多个css链接生成Link标签 42 | * 43 | * @param urls List 44 | * @return String 45 | */ 46 | fun createCssTag(urls: List): String { 47 | 48 | val sb = StringBuilder() 49 | for (url in urls) { 50 | sb.append(createCssTag(url)) 51 | } 52 | return sb.toString() 53 | } 54 | 55 | /** 56 | * 根据js链接生成Script标签 57 | * 58 | * @param url String 59 | * @return String 60 | */ 61 | fun createJsTag(url: String): String { 62 | 63 | return String.format(NEEDED_FORMAT_JS_TAG, url) 64 | } 65 | 66 | /** 67 | * 根据多个js链接生成Script标签 68 | * 69 | * @param urls List 70 | * @return String 71 | */ 72 | fun createJsTag(urls: List): String { 73 | 74 | val sb = StringBuilder() 75 | for (url in urls) { 76 | sb.append(createJsTag(url)) 77 | } 78 | return sb.toString() 79 | } 80 | 81 | /** 82 | * 根据样式标签,html字符串,js标签 83 | * 生成完整的HTML文档 84 | */ 85 | 86 | fun createHtmlData(html: String, cssList: List, jsList: List): String { 87 | val css = HtmlUtils.createCssTag(cssList) 88 | val js = HtmlUtils.createJsTag(jsList) 89 | return css + HIDE_HEADER_STYLE + html + js 90 | } 91 | } 92 | 93 | -------------------------------------------------------------------------------- /module_library/src/main/java/com/lxm/module_library/utils/HttpUtils.kt: -------------------------------------------------------------------------------- 1 | package com.lxm.module_library.utils 2 | 3 | import android.os.Build 4 | import android.webkit.WebSettings 5 | import java.util.* 6 | import java.util.regex.Pattern 7 | 8 | /** 9 | * 10 | * HttpUtils 主要用于获取UserAgent 11 | */ 12 | 13 | object HttpUtils { 14 | /** 15 | * 获取UserAgent 16 | * 17 | * @return UserAgent 18 | */ 19 | val userAgent: String 20 | get() { 21 | var userAgent: String 22 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { 23 | try { 24 | userAgent = WebSettings.getDefaultUserAgent(AppUtils.context) 25 | } catch (e: Exception) { 26 | userAgent = System.getProperty("http.agent") 27 | } 28 | 29 | } else { 30 | userAgent = System.getProperty("http.agent") 31 | } 32 | val sb = StringBuffer() 33 | var i = 0 34 | val length = userAgent.length 35 | while (i < length) { 36 | val c = userAgent[i] 37 | if (c <= '\u001f' || c >= '\u007f') { 38 | sb.append(String.format("\\u%04x", c.toInt())) 39 | } else { 40 | sb.append(c) 41 | } 42 | i++ 43 | } 44 | return sb.toString() 45 | } 46 | 47 | fun makeUA(): String { 48 | return Build.BRAND + "/" + Build.MODEL + "/" + Build.VERSION.RELEASE 49 | } 50 | 51 | fun returnImageUrlsFromHtml(html: String): Array? { 52 | val imageSrcList = ArrayList() 53 | val p = Pattern.compile("]*\\bsrc\\b\\s*=\\s*('|\")?([^'\"\n\rf>]+(\\" + 54 | ".jpg|\\.bmp|\\.eps|\\.gif|\\.mif|\\.miff|\\.png|\\.tif|\\.tiff|\\.svg|\\.wmf|\\" + 55 | ".jpe|\\.jpeg|\\.dib|\\.ico|\\.tga|\\.cut|\\.pic|\\b)\\b)[^>]*>", Pattern 56 | .CASE_INSENSITIVE) 57 | val m = p.matcher(html) 58 | var quote: String 59 | var src: String 60 | while (m.find()) { 61 | quote = m.group(1) 62 | src = if (quote == null || quote.trim { it <= ' ' }.isEmpty()) 63 | m.group(2).split("//s+".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()[0] 64 | else 65 | m 66 | .group(2) 67 | imageSrcList.add(src) 68 | } 69 | return if (imageSrcList.size == 0) { 70 | null 71 | } else imageSrcList.toTypedArray() 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /module_library/src/main/java/com/lxm/module_library/utils/JsonUtils.kt: -------------------------------------------------------------------------------- 1 | package com.lxm.module_library.utils 2 | 3 | import com.google.gson.Gson 4 | import com.google.gson.JsonObject 5 | import com.google.gson.JsonSyntaxException 6 | 7 | import java.lang.reflect.Type 8 | 9 | /** 10 | * 11 | * Json转换工具类 12 | */ 13 | object JsonUtils { 14 | 15 | private val mGson = Gson() 16 | 17 | /** 18 | * 将对象准换为json字符串 19 | * 20 | * @param object 21 | * @param 22 | * @return 23 | */ 24 | fun serialize(`object`: T): String { 25 | return mGson.toJson(`object`) 26 | } 27 | 28 | /** 29 | * 将json字符串转换为对象 30 | * 31 | * @param json 32 | * @param clz 33 | * @param 34 | * @return 35 | */ 36 | @Throws(JsonSyntaxException::class) 37 | fun deserialize(json: String, clz: Class): T { 38 | return mGson.fromJson(json, clz) 39 | } 40 | 41 | /** 42 | * 将json对象转换为实体对象 43 | * 44 | * @param json 45 | * @param clz 46 | * @param 47 | * @return 48 | * @throws JsonSyntaxException 49 | */ 50 | @Throws(JsonSyntaxException::class) 51 | fun deserialize(json: JsonObject, clz: Class): T { 52 | return mGson.fromJson(json, clz) 53 | } 54 | 55 | /** 56 | * 将json字符串转换为对象 57 | * 58 | * @param json 59 | * @param type 60 | * @param 61 | * @return 62 | */ 63 | @Throws(JsonSyntaxException::class) 64 | fun deserialize(json: String, type: Type): T { 65 | return mGson.fromJson(json, type) 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /module_library/src/main/java/com/lxm/module_library/utils/MD5Utils.kt: -------------------------------------------------------------------------------- 1 | package com.lxm.module_library.utils 2 | 3 | import java.security.MessageDigest 4 | 5 | /** 6 | * 7 | * MD5加密工具类 8 | */ 9 | object MD5Utils { 10 | /** 11 | * MD5加密,32位 12 | */ 13 | fun getMD5(str: String): String { 14 | val md5: MessageDigest 15 | try { 16 | md5 = MessageDigest.getInstance("MD5") 17 | } catch (e: Exception) { 18 | e.printStackTrace() 19 | return "" 20 | } 21 | 22 | val charArray = str.toCharArray() 23 | val byteArray = ByteArray(charArray.size) 24 | for (i in charArray.indices) { 25 | byteArray[i] = charArray[i].toByte() 26 | } 27 | val md5Bytes = md5.digest(byteArray) 28 | val hexValue = StringBuffer() 29 | for (i in md5Bytes.indices) { 30 | val `val` = md5Bytes[i].toInt() and 0xff 31 | if (`val` < 16) { 32 | hexValue.append("0") 33 | } 34 | hexValue.append(Integer.toHexString(`val`)) 35 | } 36 | return hexValue.toString() 37 | } 38 | } -------------------------------------------------------------------------------- /module_library/src/main/java/com/lxm/module_library/utils/PreferencesUtil.kt: -------------------------------------------------------------------------------- 1 | package com.lxm.module_library.utils 2 | 3 | 4 | import android.content.Context 5 | import android.content.SharedPreferences 6 | import kotlin.properties.ReadWriteProperty 7 | import kotlin.reflect.KProperty 8 | 9 | /** 10 | * SharedPreferences工具类封装 委托调用 11 | */ 12 | class PreferencesUtil(val key: String, val default: T) : ReadWriteProperty { 13 | 14 | companion object { 15 | lateinit var preferences: SharedPreferences 16 | private var mPreferencesName = "share_preference_default" 17 | public fun get(context: Context) { 18 | preferences = context.getSharedPreferences(context.packageName + mPreferencesName, Context.MODE_PRIVATE) 19 | } 20 | } 21 | 22 | override fun getValue(thisRef: Any?, property: KProperty<*>): T = findPreferences() 23 | 24 | override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) = setPreferences(value) 25 | 26 | private fun findPreferences(): T { 27 | return with(preferences) { 28 | val res: Any = when (default) { 29 | is Int -> getInt(key, default) 30 | is Boolean -> getBoolean(key, default) 31 | is Float -> getFloat(key, default) 32 | is String -> getString(key, default) 33 | is Long -> getLong(key, default) 34 | else -> throw IllegalArgumentException("This type can be saved into Preferences") 35 | } 36 | res as T 37 | } 38 | } 39 | 40 | private fun setPreferences(value: T) = with(preferences.edit()) { 41 | when (value) { 42 | is Int -> putInt(key, value) 43 | is Boolean -> putBoolean(key, value) 44 | is Float -> putFloat(key, value) 45 | is String -> putString(key, value) 46 | is Long -> putLong(key, value) 47 | else -> throw IllegalArgumentException("This type can be saved into Preferences") 48 | }.apply() 49 | } 50 | 51 | /** 52 | * 设置preferencesName 53 | * 54 | * @param preferencesName preferencesName 55 | */ 56 | private fun setPreferencesName(preferencesName: String) { 57 | mPreferencesName = preferencesName 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /module_library/src/main/java/com/lxm/module_library/utils/RefreshHelper.kt: -------------------------------------------------------------------------------- 1 | package com.lxm.module_library.utils 2 | 3 | import android.support.v4.content.ContextCompat 4 | import android.support.v7.widget.DividerItemDecoration 5 | import android.support.v7.widget.LinearLayoutManager 6 | import com.lxm.module_library.R 7 | import com.lxm.module_library.xrecycleview.XRecyclerView 8 | 9 | object RefreshHelper { 10 | 11 | /** 12 | * 默认不显示最后一个item的分割线 13 | * 14 | * @param isShowFirstDivider 第一个item是否显示分割线 15 | * @param isShowSecondDivider 第二个item是否显示分割线 16 | */ 17 | @JvmOverloads 18 | fun init(recyclerView: XRecyclerView, isShowFirstDivider: Boolean = true, isShowSecondDivider: Boolean = true) { 19 | recyclerView.layoutManager = LinearLayoutManager(recyclerView.context) 20 | recyclerView.setPullRefreshEnabled(false) 21 | recyclerView.clearHeader() 22 | // val itemDecoration = MyDividerItemDecoration( 23 | // recyclerView.context, 24 | // DividerItemDecoration.VERTICAL, 25 | // false, 26 | // isShowFirstDivider, 27 | // isShowSecondDivider 28 | // ) 29 | // itemDecoration.setDrawable(ContextCompat.getDrawable(recyclerView.context, R.drawable.shape_line)!!) 30 | // recyclerView.addItemDecoration(itemDecoration) 31 | } 32 | } 33 | 34 | -------------------------------------------------------------------------------- /module_library/src/main/java/com/lxm/module_library/utils/ResourcesUtils.kt: -------------------------------------------------------------------------------- 1 | package com.lxm.module_library.utils 2 | 3 | import android.content.res.ColorStateList 4 | import android.graphics.drawable.Drawable 5 | import android.view.View 6 | 7 | /** 8 | * 9 | * 资源工具类-加载资源文件 10 | */ 11 | 12 | object ResourcesUtils { 13 | /** 14 | * 获取strings.xml资源文件字符串 15 | * 16 | * @param id 资源文件id 17 | * @return 资源文件对应字符串 18 | */ 19 | fun getString(id: Int): String { 20 | return AppUtils.context.resources.getString(id) 21 | } 22 | 23 | /** 24 | * 获取strings.xml资源文件字符串数组 25 | * 26 | * @param id 资源文件id 27 | * @return 资源文件对应字符串数组 28 | */ 29 | fun getStringArray(id: Int): Array { 30 | return AppUtils.context.resources.getStringArray(id) 31 | } 32 | 33 | /** 34 | * 获取drawable资源文件图片 35 | * 36 | * @param id 资源文件id 37 | * @return 资源文件对应图片 38 | */ 39 | fun getDrawable(id: Int): Drawable { 40 | return AppUtils.context.resources.getDrawable(id) 41 | } 42 | 43 | /** 44 | * 获取colors.xml资源文件颜色 45 | * 46 | * @param id 资源文件id 47 | * @return 资源文件对应颜色值 48 | */ 49 | fun getColor(id: Int): Int { 50 | return AppUtils.context.resources.getColor(id) 51 | } 52 | 53 | /** 54 | * 获取颜色的状态选择器 55 | * 56 | * @param id 资源文件id 57 | * @return 资源文件对应颜色状态 58 | */ 59 | fun getColorStateList(id: Int): ColorStateList? { 60 | return AppUtils.context.resources.getColorStateList(id) 61 | } 62 | 63 | /** 64 | * 获取dimens资源文件中具体像素值 65 | * 66 | * @param id 资源文件id 67 | * @return 资源文件对应像素值 68 | */ 69 | fun getDimen(id: Int): Int { 70 | return AppUtils.context.resources.getDimensionPixelSize(id) 71 | } 72 | 73 | /** 74 | * 加载布局文件 75 | * 76 | * @param id 布局文件id 77 | * @return 布局view 78 | */ 79 | fun inflate(id: Int): View { 80 | return View.inflate(AppUtils.context, id, null) 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /module_library/src/main/java/com/lxm/module_library/utils/ScreenAdapterUtils.kt: -------------------------------------------------------------------------------- 1 | package com.lxm.module_library.utils 2 | 3 | import android.app.Activity 4 | import android.content.res.Resources 5 | 6 | /** 7 | *屏幕适配相关 8 | * 9 | */ 10 | object ScreenAdapterUtils { 11 | /** 12 | * Return whether adapt screen. 13 | * 14 | * @return `true`: yes

`false`: no 15 | */ 16 | val isAdaptScreen: Boolean 17 | get() { 18 | val systemDm = Resources.getSystem().displayMetrics 19 | val appDm = AppUtils.context.resources.displayMetrics 20 | return systemDm.density != appDm.density 21 | } 22 | 23 | /** 24 | * Adapt the screen for vertical slide. 25 | * 26 | * @param activity The activity. 27 | * @param designWidthInPx The size of design diagram's width, in pixel. 28 | */ 29 | fun adaptScreen4VerticalSlide(activity: Activity, 30 | designWidthInPx: Int) { 31 | adaptScreen(activity, designWidthInPx, true) 32 | } 33 | 34 | /** 35 | * Adapt the screen for horizontal slide. 36 | * 37 | * @param activity The activity. 38 | * @param designHeightInPx The size of design diagram's height, in pixel. 39 | */ 40 | fun adaptScreen4HorizontalSlide(activity: Activity, 41 | designHeightInPx: Int) { 42 | adaptScreen(activity, designHeightInPx, false) 43 | } 44 | 45 | /** 46 | * Reference from: https://mp.weixin.qq.com/s/d9QCoBP6kV9VSWvVldVVwA 47 | */ 48 | private fun adaptScreen(activity: Activity, 49 | sizeInPx: Int, 50 | isVerticalSlide: Boolean) { 51 | val systemDm = Resources.getSystem().displayMetrics 52 | val appDm = AppUtils.context.resources.displayMetrics 53 | val activityDm = activity.resources.displayMetrics 54 | if (isVerticalSlide) { 55 | activityDm.density = activityDm.widthPixels / sizeInPx.toFloat() 56 | } else { 57 | activityDm.density = activityDm.heightPixels / sizeInPx.toFloat() 58 | } 59 | activityDm.scaledDensity = activityDm.density * (systemDm.scaledDensity / systemDm.density) 60 | activityDm.densityDpi = (160 * activityDm.density).toInt() 61 | appDm.density = activityDm.density 62 | appDm.scaledDensity = activityDm.scaledDensity 63 | appDm.densityDpi = activityDm.densityDpi 64 | } 65 | 66 | /** 67 | * Cancel adapt the screen. 68 | * 69 | * @param activity The activity. 70 | */ 71 | fun cancelAdaptScreen(activity: Activity) { 72 | val systemDm = Resources.getSystem().displayMetrics 73 | val appDm = AppUtils.context.resources.displayMetrics 74 | val activityDm = activity.resources.displayMetrics 75 | activityDm.density = systemDm.density 76 | activityDm.scaledDensity = systemDm.scaledDensity 77 | activityDm.densityDpi = systemDm.densityDpi 78 | appDm.density = systemDm.density 79 | appDm.scaledDensity = systemDm.scaledDensity 80 | appDm.densityDpi = systemDm.densityDpi 81 | } 82 | 83 | } 84 | -------------------------------------------------------------------------------- /module_library/src/main/java/com/lxm/module_library/utils/StatusBarUtils.kt: -------------------------------------------------------------------------------- 1 | package com.lxm.module_library.utils 2 | 3 | import android.app.Activity 4 | import android.graphics.Color 5 | import android.os.Build 6 | import android.support.annotation.ColorInt 7 | import android.support.v7.widget.Toolbar 8 | import android.view.View 9 | import android.view.ViewGroup 10 | import android.view.WindowManager 11 | 12 | 13 | /** 14 | * 15 | * StatusBar工具类 16 | * 17 | */ 18 | object StatusBarUtils { 19 | 20 | /** 21 | * 设置状态栏颜色 22 | * 23 | * @param activity 需要设置的 activity 24 | * @param color 状态栏颜色值 25 | */ 26 | private fun setColor(activity: Activity, @ColorInt color: Int) { 27 | setBarColor(activity, color) 28 | } 29 | 30 | /** 31 | * 设置状态栏背景色 32 | * 4.4以下不处理 33 | * 4.4使用默认沉浸式状态栏 34 | * 35 | * @param color 要为状态栏设置的颜色值 36 | */ 37 | private fun setBarColor(activity: Activity, color: Int) { 38 | val win = activity.window 39 | val decorView = win.decorView 40 | //沉浸式状态栏(4.4-5.0透明,5.0以上半透明) 41 | win.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) 42 | //android5.0以上设置透明效果 43 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 44 | 45 | //让应用的主体内容占用系统状态栏的空间 46 | val option = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_STABLE 47 | decorView.systemUiVisibility = decorView.systemUiVisibility or option 48 | win.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) 49 | //设置状态栏背景色 50 | win.statusBarColor = color 51 | } 52 | } 53 | 54 | /** 55 | * 设置状态栏全透明 56 | * 57 | * @param activity 需要设置的activity 58 | */ 59 | fun setTransparent(activity: Activity) { 60 | setColor(activity, Color.LTGRAY) 61 | } 62 | 63 | /** 64 | * 修正 Toolbar 的位置 65 | * 在 Android 4.4 版本下无法显示内容在 StatusBar 下,所以无需修正 Toolbar 的位置 66 | * 67 | * @param toolbar Toolbar 68 | */ 69 | fun fixToolbar(toolbar: Toolbar, activity: Activity) { 70 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { 71 | val statusHeight = ScreenUtils.getStatusBarHeight(activity) 72 | val layoutParams = toolbar.layoutParams as ViewGroup.MarginLayoutParams 73 | layoutParams.setMargins(0, statusHeight, 0, 0) 74 | } 75 | } 76 | 77 | 78 | } 79 | -------------------------------------------------------------------------------- /module_library/src/main/java/com/lxm/module_library/utils/TimestampUtils.kt: -------------------------------------------------------------------------------- 1 | package com.lxm.module_library.utils 2 | 3 | import java.text.SimpleDateFormat 4 | import java.util.* 5 | 6 | object TimestampUtils { 7 | /** 8 | * 获取当前的时间戳,时区为北京 9 | * 10 | * @return 11 | */ 12 | //时间戳的格式必须为 yyyy-MM-dd HH:mm:ss 13 | val currentTimestamp: String? 14 | get() { 15 | var timestamp: String? = null 16 | val format = SimpleDateFormat.getDateTimeInstance() 17 | timestamp = format.format(Date()) 18 | return timestamp 19 | } 20 | 21 | /** 22 | * 获取当前的时间戳,时区为北京 23 | * 24 | * @return 25 | */ 26 | fun getCurrentTime(times: Long): String { 27 | //时间戳的格式必须为 yyyy-MM-dd HH:mm:ss 28 | val date = Date(java.lang.Long.valueOf(times)) 29 | val format = SimpleDateFormat.getDateTimeInstance() 30 | val time = format.format(date) 31 | SimpleDateFormat.getDateTimeInstance() 32 | .format(Date()) 33 | 34 | return time 35 | } 36 | 37 | //法国时间:东一区 38 | fun getDateTimeByGMT(timeZone: Int): String { 39 | val dff = SimpleDateFormat.getDateTimeInstance() 40 | when (timeZone) { 41 | 1 -> dff.timeZone = TimeZone.getTimeZone("GMT+1") 42 | 8 -> dff.timeZone = TimeZone.getTimeZone("GMT+8") 43 | } 44 | 45 | return dff.format(Date()) 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /module_library/src/main/java/com/lxm/module_library/utils/ToastUtil.java: -------------------------------------------------------------------------------- 1 | package com.lxm.module_library.utils; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.text.TextUtils; 5 | import android.widget.Toast; 6 | import com.lxm.module_library.global.GlobalApplication; 7 | import me.drakeet.support.toast.ToastCompat; 8 | 9 | /** 10 | * Created by jingbin on 2016/12/14. 11 | * 单例Toast,兼容索尼部分手机不弹提示的问题,和vivo7.1.1部分手机崩溃问题 12 | * An Android library to hook and fix Toast BadTokenException 13 | * https://github.com/PureWriter/ToastCompat 14 | */ 15 | 16 | public class ToastUtil { 17 | 18 | private static ToastCompat mToast; 19 | 20 | @SuppressLint("ShowToast") 21 | public static void showToast(String text) { 22 | if (!TextUtils.isEmpty(text)) { 23 | if (mToast == null) { 24 | mToast = ToastCompat.makeText(GlobalApplication.getInstance(), text, Toast.LENGTH_SHORT); 25 | } else { 26 | mToast.cancel(); 27 | mToast = ToastCompat.makeText(GlobalApplication.getInstance(), text, Toast.LENGTH_SHORT); 28 | } 29 | mToast.setDuration(Toast.LENGTH_SHORT); 30 | mToast.setText(text); 31 | mToast.show(); 32 | } 33 | } 34 | 35 | @SuppressLint("ShowToast") 36 | public static void showToastLong(String text) { 37 | if (!TextUtils.isEmpty(text)) { 38 | if (mToast == null) { 39 | mToast = ToastCompat.makeText(GlobalApplication.getInstance(), text, Toast.LENGTH_LONG); 40 | } else { 41 | mToast.cancel(); 42 | mToast = ToastCompat.makeText(GlobalApplication.getInstance(), text, Toast.LENGTH_LONG); 43 | } 44 | mToast.setDuration(Toast.LENGTH_LONG); 45 | mToast.setText(text); 46 | mToast.show(); 47 | } 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /module_library/src/main/java/com/lxm/module_library/utils/ToastUtils.kt: -------------------------------------------------------------------------------- 1 | package com.lxm.module_library.utils 2 | 3 | import android.content.Context 4 | import android.widget.Toast 5 | import com.lxm.module_library.helper.RxHelper 6 | import io.reactivex.Observable 7 | 8 | /** 9 | * 10 | * toast工具类封装 11 | */ 12 | object ToastUtils { 13 | private var mToast: Toast? = null 14 | 15 | /** 16 | * 显示一个toast提示 17 | * 18 | * @param resourceId toast字符串资源id 19 | */ 20 | fun showToast(resourceId: Int) { 21 | showToast(ResourcesUtils.getString(resourceId)) 22 | } 23 | 24 | /** 25 | * 显示一个toast提示 26 | * 27 | * @param text toast字符串 28 | * @param duration toast显示时间 29 | */ 30 | @JvmOverloads 31 | fun showToast(text: String, duration: Int = Toast.LENGTH_SHORT) { 32 | showToast(AppUtils.context, text, duration) 33 | } 34 | 35 | /** 36 | * 显示一个toast提示 37 | * 38 | * @param context context 上下文对象 39 | * @param text toast字符串 40 | * @param duration toast显示时间 41 | */ 42 | fun showToast(context: Context, text: String, duration: Int) { 43 | /** 44 | * 保证运行在主线程 45 | */ 46 | val disposable = Observable.just(0) 47 | .compose(RxHelper.rxSchedulerHelper()) 48 | .subscribe { 49 | if (mToast == null) { 50 | mToast = Toast.makeText(context, text, duration) 51 | } else { 52 | mToast!!.setText(text) 53 | mToast!!.duration = duration 54 | } 55 | mToast!!.show() 56 | } 57 | } 58 | } 59 | /** 60 | * 显示一个toast提示 61 | * 62 | * @param text toast字符串 63 | */ 64 | -------------------------------------------------------------------------------- /module_library/src/main/java/com/lxm/module_library/utils/UnicodeUtils.kt: -------------------------------------------------------------------------------- 1 | package com.lxm.module_library.utils 2 | 3 | /** 4 | * Created by Horrarndoo on 2017/10/11. 5 | * 6 | */ 7 | object UnicodeUtils { 8 | /** 9 | * utf-8 转换成 unicode 10 | * 11 | * @param inStr 12 | * @return 13 | */ 14 | fun utf8ToUnicode(inStr: String): String { 15 | val myBuffer = inStr.toCharArray() 16 | 17 | val sb = StringBuffer() 18 | for (i in 0 until inStr.length) { 19 | val ub = Character.UnicodeBlock.of(myBuffer[i]) 20 | if (ub === Character.UnicodeBlock.BASIC_LATIN) { 21 | //英文及数字等 22 | sb.append(myBuffer[i]) 23 | } else if (ub === Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS) { 24 | //全角半角字符 25 | val j = myBuffer[i].toInt() - 65248 26 | sb.append(j.toChar()) 27 | } else { 28 | //汉字 29 | val s = myBuffer[i].toShort() 30 | val hexS = Integer.toHexString(s.toInt()) 31 | val unicode = "\\u$hexS" 32 | sb.append(unicode.toLowerCase()) 33 | } 34 | } 35 | return sb.toString() 36 | } 37 | 38 | /** 39 | * unicode 转换成 utf-8 40 | * 41 | * @param theString 42 | * @return 43 | */ 44 | fun unicodeToUtf8(theString: String): String { 45 | var aChar: Char 46 | val len = theString.length 47 | val outBuffer = StringBuffer(len) 48 | var x = 0 49 | while (x < len) { 50 | aChar = theString[x++] 51 | if (aChar == '\\') { 52 | aChar = theString[x++] 53 | if (aChar == 'u') { 54 | var value = 0 55 | for (i in 0..3) { 56 | aChar = theString[x++] 57 | value = when (aChar) { 58 | '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' -> (value shl 4) + aChar.toInt() - '0'.toInt() 59 | 'a', 'b', 'c', 'd', 'e', 'f' -> (value shl 4) + 10 + aChar.toInt() - 'a'.toInt() 60 | 'A', 'B', 'C', 'D', 'E', 'F' -> (value shl 4) + 10 + aChar.toInt() - 'A'.toInt() 61 | else -> throw IllegalArgumentException( 62 | "Malformed \\uxxxx encoding.") 63 | } 64 | } 65 | outBuffer.append(value.toChar()) 66 | } else { 67 | if (aChar == 't') { 68 | aChar = '\t' 69 | } else if (aChar == 'r') 70 | aChar = '\r' 71 | else if (aChar == 'n') 72 | aChar = '\n' 73 | else if (aChar == 'f') 74 | aChar = 'f' 75 | outBuffer.append(aChar) 76 | } 77 | } else 78 | outBuffer.append(aChar) 79 | } 80 | return outBuffer.toString() 81 | } 82 | } -------------------------------------------------------------------------------- /module_library/src/main/java/com/lxm/module_library/xrecycleview/BaseRefreshHeader.java: -------------------------------------------------------------------------------- 1 | package com.lxm.module_library.xrecycleview; 2 | 3 | /** 4 | * Created by jianghejie on 15/11/22. 5 | */ 6 | interface BaseRefreshHeader { 7 | 8 | int STATE_NORMAL = 0; 9 | int STATE_RELEASE_TO_REFRESH = 1; 10 | int STATE_REFRESHING = 2; 11 | int STATE_DONE = 3; 12 | 13 | void onMove(float delta); 14 | 15 | boolean releaseAction(); 16 | 17 | void refreshComplate(); 18 | 19 | int getVisiableHeight(); 20 | } 21 | -------------------------------------------------------------------------------- /module_library/src/main/java/com/lxm/module_library/xrecycleview/LoadingMoreFooter.java: -------------------------------------------------------------------------------- 1 | package com.lxm.module_library.xrecycleview; 2 | 3 | import android.content.Context; 4 | import android.graphics.drawable.AnimationDrawable; 5 | import android.util.AttributeSet; 6 | import android.view.LayoutInflater; 7 | import android.view.View; 8 | import android.view.ViewGroup; 9 | import android.widget.ImageView; 10 | import android.widget.LinearLayout; 11 | import android.widget.TextView; 12 | import com.lxm.module_library.R; 13 | 14 | public class LoadingMoreFooter extends LinearLayout { 15 | 16 | public final static int STATE_LOADING = 0; 17 | public final static int STATE_COMPLETE = 1; 18 | public final static int STATE_NOMORE = 2; 19 | private TextView mText; 20 | private AnimationDrawable mAnimationDrawable; 21 | private ImageView mIvProgress; 22 | 23 | public LoadingMoreFooter(Context context) { 24 | super(context); 25 | initView(context); 26 | } 27 | 28 | /** 29 | * @param context 30 | * @param attrs 31 | */ 32 | public LoadingMoreFooter(Context context, AttributeSet attrs) { 33 | super(context, attrs); 34 | initView(context); 35 | } 36 | 37 | public void initView(Context context) { 38 | LayoutInflater.from(context).inflate(R.layout.refresh_footer, this); 39 | mText = (TextView) findViewById(R.id.msg); 40 | mIvProgress = (ImageView) findViewById(R.id.iv_progress); 41 | mAnimationDrawable = (AnimationDrawable) mIvProgress.getDrawable(); 42 | if (!mAnimationDrawable.isRunning()) { 43 | mAnimationDrawable.start(); 44 | } 45 | setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); 46 | } 47 | 48 | public void setState(int state) { 49 | switch (state) { 50 | case STATE_LOADING: 51 | if (!mAnimationDrawable.isRunning()) { 52 | mAnimationDrawable.start(); 53 | } 54 | mIvProgress.setVisibility(View.VISIBLE); 55 | mText.setText(getContext().getText(R.string.listview_loading)); 56 | this.setVisibility(View.VISIBLE); 57 | break; 58 | case STATE_COMPLETE: 59 | if (mAnimationDrawable.isRunning()) { 60 | mAnimationDrawable.stop(); 61 | } 62 | mText.setText(getContext().getText(R.string.listview_loading)); 63 | this.setVisibility(View.GONE); 64 | break; 65 | case STATE_NOMORE: 66 | if (mAnimationDrawable.isRunning()) { 67 | mAnimationDrawable.stop(); 68 | } 69 | mText.setText(getContext().getText(R.string.nomore_loading)); 70 | mIvProgress.setVisibility(View.GONE); 71 | this.setVisibility(View.VISIBLE); 72 | break; 73 | } 74 | } 75 | 76 | public void reSet() { 77 | this.setVisibility(GONE); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /module_library/src/main/res/drawable/app_loading0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/malonecoder/Awesome-Kotlin-WanAndroid/2bf7cfa3624f547d5f64c741f653b3f6ac8bf7eb/module_library/src/main/res/drawable/app_loading0.png -------------------------------------------------------------------------------- /module_library/src/main/res/drawable/app_loading1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/malonecoder/Awesome-Kotlin-WanAndroid/2bf7cfa3624f547d5f64c741f653b3f6ac8bf7eb/module_library/src/main/res/drawable/app_loading1.png -------------------------------------------------------------------------------- /module_library/src/main/res/drawable/app_loading2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/malonecoder/Awesome-Kotlin-WanAndroid/2bf7cfa3624f547d5f64c741f653b3f6ac8bf7eb/module_library/src/main/res/drawable/app_loading2.png -------------------------------------------------------------------------------- /module_library/src/main/res/drawable/app_loading3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/malonecoder/Awesome-Kotlin-WanAndroid/2bf7cfa3624f547d5f64c741f653b3f6ac8bf7eb/module_library/src/main/res/drawable/app_loading3.png -------------------------------------------------------------------------------- /module_library/src/main/res/drawable/app_loading_anim.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 8 | 11 | 14 | 17 | 18 | -------------------------------------------------------------------------------- /module_library/src/main/res/drawable/common_progress_cirle.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | -------------------------------------------------------------------------------- /module_library/src/main/res/drawable/header_loading0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/malonecoder/Awesome-Kotlin-WanAndroid/2bf7cfa3624f547d5f64c741f653b3f6ac8bf7eb/module_library/src/main/res/drawable/header_loading0.png -------------------------------------------------------------------------------- /module_library/src/main/res/drawable/header_loading1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/malonecoder/Awesome-Kotlin-WanAndroid/2bf7cfa3624f547d5f64c741f653b3f6ac8bf7eb/module_library/src/main/res/drawable/header_loading1.png -------------------------------------------------------------------------------- /module_library/src/main/res/drawable/header_loading2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/malonecoder/Awesome-Kotlin-WanAndroid/2bf7cfa3624f547d5f64c741f653b3f6ac8bf7eb/module_library/src/main/res/drawable/header_loading2.png -------------------------------------------------------------------------------- /module_library/src/main/res/drawable/header_loading3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/malonecoder/Awesome-Kotlin-WanAndroid/2bf7cfa3624f547d5f64c741f653b3f6ac8bf7eb/module_library/src/main/res/drawable/header_loading3.png -------------------------------------------------------------------------------- /module_library/src/main/res/drawable/header_loading_anim.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 8 | 11 | 14 | 17 | 18 | -------------------------------------------------------------------------------- /module_library/src/main/res/drawable/ic_add.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /module_library/src/main/res/drawable/ic_clear.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /module_library/src/main/res/drawable/ic_person_add_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/malonecoder/Awesome-Kotlin-WanAndroid/2bf7cfa3624f547d5f64c741f653b3f6ac8bf7eb/module_library/src/main/res/drawable/ic_person_add_white_24dp.png -------------------------------------------------------------------------------- /module_library/src/main/res/drawable/icon_back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/malonecoder/Awesome-Kotlin-WanAndroid/2bf7cfa3624f547d5f64c741f653b3f6ac8bf7eb/module_library/src/main/res/drawable/icon_back.png -------------------------------------------------------------------------------- /module_library/src/main/res/drawable/load_err.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/malonecoder/Awesome-Kotlin-WanAndroid/2bf7cfa3624f547d5f64c741f653b3f6ac8bf7eb/module_library/src/main/res/drawable/load_err.png -------------------------------------------------------------------------------- /module_library/src/main/res/drawable/loading_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/malonecoder/Awesome-Kotlin-WanAndroid/2bf7cfa3624f547d5f64c741f653b3f6ac8bf7eb/module_library/src/main/res/drawable/loading_image.png -------------------------------------------------------------------------------- /module_library/src/main/res/drawable/login_back.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 8 | -------------------------------------------------------------------------------- /module_library/src/main/res/drawable/shape_line.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /module_library/src/main/res/layout/activity_base.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 19 | 20 | 21 | 25 | 26 | 27 | 34 | 35 | 36 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /module_library/src/main/res/layout/custom_login_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /module_library/src/main/res/layout/custom_register_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /module_library/src/main/res/layout/default_login_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /module_library/src/main/res/layout/default_register_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /module_library/src/main/res/layout/fragment_base.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 11 | 12 | 13 | 19 | 20 | 21 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /module_library/src/main/res/layout/layout_loading_error.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 18 | 19 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /module_library/src/main/res/layout/layout_loading_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 16 | 17 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /module_library/src/main/res/layout/login_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 19 | 20 | 27 | 28 | 35 | 36 | 37 | 44 | 45 | 51 | 52 | 53 | 58 | 59 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /module_library/src/main/res/layout/login_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 10 | 15 | 20 | 21 | 22 | 27 | 33 | 34 | 35 | 44 | 45 | -------------------------------------------------------------------------------- /module_library/src/main/res/layout/refresh_footer.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 14 | 15 | 20 | 21 | 28 | 29 | -------------------------------------------------------------------------------- /module_library/src/main/res/layout/refresh_header.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 15 | 16 | 21 | 22 | 28 | 29 | -------------------------------------------------------------------------------- /module_library/src/main/res/values-w600dp/dimen.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 400dp 5 | -------------------------------------------------------------------------------- /module_library/src/main/res/values/attrs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /module_library/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | #343434 6 | #EBEBEB 7 | #D4D4D4 8 | #BBBBBB 9 | #FFDDDDDD 10 | #ff333333 11 | #585858 12 | #999 13 | #666 14 | #ffffffff 15 | #777D7D7D 16 | 17 | #343434 18 | #11EE69 19 | #ff5151 20 | #ffcdce 21 | #000 22 | #000 23 | 24 | -------------------------------------------------------------------------------- /module_library/src/main/res/values/dimen.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 250dp 4 | -------------------------------------------------------------------------------- /module_library/src/main/res/values/drawables.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | @drawable/abc_item_background_holo_light 4 | 5 | 6 | -------------------------------------------------------------------------------- /module_library/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | module_library 3 | 下拉刷新... 4 | 释放刷新... 5 | 努力加载中... 6 | 没有更多内容了 7 | 正在刷新... 8 | 刷新完成... 9 | 上次更新时间: 10 | 11 | 12 | 分享 13 | 复制链接 14 | 浏览器打开 15 | 刷新 16 | 添加到收藏 17 | 18 | LOGIN 19 | Name 20 | Password 21 | GO 22 | REGISTER 23 | Repeat Password 24 | NEXT 25 | 26 | 27 | -------------------------------------------------------------------------------- /module_library/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 18 | 19 | 20 | 24 | 25 | 26 | 30 | 31 | 33 | 34 | 37 | 41 | 42 | 49 | 50 | 57 | 58 | 62 | 63 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /module_library/src/test/java/com/lxm/module_library/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.lxm.module_library; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * @see Testing documentation 11 | */ 12 | public class ExampleUnitTest { 13 | @Test 14 | public void addition_isCorrect() { 15 | assertEquals(4, 2 + 2); 16 | } 17 | } -------------------------------------------------------------------------------- /screenshots/主页侧滑菜单.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/malonecoder/Awesome-Kotlin-WanAndroid/2bf7cfa3624f547d5f64c741f653b3f6ac8bf7eb/screenshots/主页侧滑菜单.webp -------------------------------------------------------------------------------- /screenshots/导航.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/malonecoder/Awesome-Kotlin-WanAndroid/2bf7cfa3624f547d5f64c741f653b3f6ac8bf7eb/screenshots/导航.webp -------------------------------------------------------------------------------- /screenshots/收藏.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/malonecoder/Awesome-Kotlin-WanAndroid/2bf7cfa3624f547d5f64c741f653b3f6ac8bf7eb/screenshots/收藏.webp -------------------------------------------------------------------------------- /screenshots/注册.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/malonecoder/Awesome-Kotlin-WanAndroid/2bf7cfa3624f547d5f64c741f653b3f6ac8bf7eb/screenshots/注册.webp -------------------------------------------------------------------------------- /screenshots/登录.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/malonecoder/Awesome-Kotlin-WanAndroid/2bf7cfa3624f547d5f64c741f653b3f6ac8bf7eb/screenshots/登录.webp -------------------------------------------------------------------------------- /screenshots/目录.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/malonecoder/Awesome-Kotlin-WanAndroid/2bf7cfa3624f547d5f64c741f653b3f6ac8bf7eb/screenshots/目录.webp -------------------------------------------------------------------------------- /screenshots/知识体系.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/malonecoder/Awesome-Kotlin-WanAndroid/2bf7cfa3624f547d5f64c741f653b3f6ac8bf7eb/screenshots/知识体系.webp -------------------------------------------------------------------------------- /screenshots/福利.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/malonecoder/Awesome-Kotlin-WanAndroid/2bf7cfa3624f547d5f64c741f653b3f6ac8bf7eb/screenshots/福利.webp -------------------------------------------------------------------------------- /screenshots/项目.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/malonecoder/Awesome-Kotlin-WanAndroid/2bf7cfa3624f547d5f64c741f653b3f6ac8bf7eb/screenshots/项目.webp -------------------------------------------------------------------------------- /screenshots/首页.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/malonecoder/Awesome-Kotlin-WanAndroid/2bf7cfa3624f547d5f64c741f653b3f6ac8bf7eb/screenshots/首页.webp -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app', ':module_library' 2 | --------------------------------------------------------------------------------