├── .gitignore ├── .idea ├── .gitignore ├── compiler.xml ├── deploymentTargetDropDown.xml ├── gradle.xml ├── kotlinc.xml ├── migrations.xml └── misc.xml ├── app ├── .gitignore ├── build.gradle.kts ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── pzj │ │ └── android_mvp_kotlin │ │ └── ExampleInstrumentedTest.kt │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── pzj │ │ │ └── android_mvp_kotlin │ │ │ ├── MainActivity.kt │ │ │ ├── app │ │ │ └── App.kt │ │ │ ├── base │ │ │ ├── BaseActivity.kt │ │ │ ├── BaseBean.kt │ │ │ ├── BaseException.kt │ │ │ ├── BaseFragment.kt │ │ │ ├── BaseObserver.kt │ │ │ ├── BasePresenter.kt │ │ │ └── BaseView.kt │ │ │ ├── bean │ │ │ ├── Article.kt │ │ │ ├── Banner.kt │ │ │ ├── Collect.kt │ │ │ ├── Hotkey.kt │ │ │ ├── Navi.kt │ │ │ ├── Project.kt │ │ │ ├── ProjectChild.kt │ │ │ ├── Tree.kt │ │ │ └── User.kt │ │ │ ├── common │ │ │ └── MyConfig.kt │ │ │ ├── http │ │ │ ├── API.kt │ │ │ ├── RetrofitService.kt │ │ │ └── interceptor │ │ │ │ ├── AddCookiesInterceptor.kt │ │ │ │ └── ReceivedCookiesInterceptor.kt │ │ │ └── utils │ │ │ └── GlideImageLoader.kt │ └── res │ │ ├── drawable │ │ ├── ic_down.png │ │ ├── ic_home.png │ │ ├── ic_launcher_background.xml │ │ ├── ic_launcher_foreground.xml │ │ ├── ic_like_checked.png │ │ ├── ic_like_normal.png │ │ ├── ic_menu_exit.xml │ │ ├── ic_menu_favorite.xml │ │ ├── ic_menu_info.xml │ │ ├── ic_menu_search.xml │ │ ├── ic_menu_share.xml │ │ ├── ic_navi.png │ │ ├── ic_project.png │ │ ├── ic_share_black_24dp.xml │ │ ├── ic_tree.png │ │ ├── ic_up.png │ │ ├── selector_primary_oval.xml │ │ ├── shape_border_primary_oval.xml │ │ ├── shape_eaeaea_oval.xml │ │ ├── shape_oval_primary.xml │ │ └── side_nav_bar.xml │ │ ├── layout │ │ ├── activity_about.xml │ │ ├── activity_collect.xml │ │ ├── activity_detail.xml │ │ ├── activity_login.xml │ │ ├── activity_main.xml │ │ ├── activity_register.xml │ │ ├── activity_search.xml │ │ ├── activity_splash.xml │ │ ├── activity_tree_child.xml │ │ ├── app_bar_main.xml │ │ ├── content_about.xml │ │ ├── content_main.xml │ │ ├── fragment_home.xml │ │ ├── fragment_navi.xml │ │ ├── fragment_project.xml │ │ ├── fragment_project_child.xml │ │ ├── fragment_tree.xml │ │ ├── item_article.xml │ │ ├── item_navi.xml │ │ ├── item_project_child.xml │ │ ├── item_tree.xml │ │ ├── item_tree_item.xml │ │ ├── layout_badge_view.xml │ │ └── nav_header_main.xml │ │ ├── menu │ │ ├── activity_main_drawer.xml │ │ ├── bottom_navigation.xml │ │ ├── main_toolbar.xml │ │ └── menu_search.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.webp │ │ ├── ic_launcher_round.webp │ │ └── ic_logo.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.webp │ │ ├── ic_launcher_round.webp │ │ └── ic_logo.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.webp │ │ ├── ic_launcher_round.webp │ │ └── ic_logo.png │ │ ├── values-night │ │ └── themes.xml │ │ ├── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ ├── styles.xml │ │ └── themes.xml │ │ └── xml │ │ ├── backup_rules.xml │ │ └── data_extraction_rules.xml │ └── test │ └── java │ └── com │ └── pzj │ └── android_mvp_kotlin │ └── ExampleUnitTest.kt ├── build.gradle.kts ├── gradle.properties ├── gradle ├── libs.versions.toml └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── library └── verticaltablayout │ ├── .gitignore │ ├── build.gradle.kts │ ├── proguard-rules.pro │ └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── pzj │ │ └── verticaltablayout │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ └── res │ │ ├── drawable │ │ ├── ic_launcher_background.xml │ │ ├── ic_launcher_foreground.xml │ │ ├── man_01_none.png │ │ ├── man_01_pressed.png │ │ ├── man_02_none.png │ │ ├── man_02_pressed.png │ │ ├── man_03_none.png │ │ ├── man_03_pressed.png │ │ ├── man_04_none.png │ │ └── man_04_pressed.png │ │ ├── layout │ │ └── item_qtabview.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── values-night │ │ └── themes.xml │ │ └── values │ │ ├── attrs.xml │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── themes.xml │ └── test │ └── java │ └── com │ └── pzj │ └── verticaltablayout │ └── ExampleUnitTest.java └── settings.gradle.kts /.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 | .cxx 15 | local.properties 16 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/deploymentTargetDropDown.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 20 | 21 | -------------------------------------------------------------------------------- /.idea/kotlinc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /.idea/migrations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 10 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /app/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | alias(libs.plugins.androidApplication) 3 | alias(libs.plugins.jetbrainsKotlinAndroid) 4 | } 5 | 6 | android { 7 | namespace = "com.pzj.android_mvp_kotlin" 8 | compileSdk = 34 9 | 10 | defaultConfig { 11 | applicationId = "com.pzj.android_mvp_kotlin" 12 | minSdk = 24 13 | targetSdk = 34 14 | versionCode = 1 15 | versionName = "1.0" 16 | multiDexEnabled = true 17 | 18 | testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" 19 | } 20 | 21 | buildTypes { 22 | release { 23 | isMinifyEnabled = false 24 | proguardFiles( 25 | getDefaultProguardFile("proguard-android-optimize.txt"), 26 | "proguard-rules.pro" 27 | ) 28 | } 29 | } 30 | compileOptions { 31 | sourceCompatibility = JavaVersion.VERSION_1_8 32 | targetCompatibility = JavaVersion.VERSION_1_8 33 | } 34 | kotlinOptions { 35 | jvmTarget = "1.8" 36 | } 37 | 38 | viewBinding{ 39 | enable=true 40 | } 41 | } 42 | 43 | dependencies { 44 | 45 | implementation(libs.androidx.core.ktx) 46 | implementation(libs.androidx.appcompat) 47 | implementation(libs.material) 48 | implementation(libs.androidx.activity) 49 | implementation(libs.androidx.constraintlayout) 50 | testImplementation(libs.junit) 51 | androidTestImplementation(libs.androidx.junit) 52 | androidTestImplementation(libs.androidx.espresso.core) 53 | 54 | 55 | implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0") 56 | implementation("q.rorbin:VerticalTabLayout:1.2.5") 57 | 58 | /*material*/ 59 | implementation("com.google.android.material:material:1.2.1") 60 | 61 | /*YUtils*/ 62 | implementation(libs.yechaoaYUtils) 63 | 64 | /*retrofit、rxjava*/ 65 | implementation(libs.retrofit) 66 | implementation(libs.adapter.rxjava2) 67 | implementation(libs.converter.gson) 68 | implementation(libs.rxandroid) 69 | implementation(libs.logging.interceptor) 70 | 71 | /*BRVAH*/ 72 | implementation(libs.baseRecyclerViewAdapterHelper) 73 | 74 | /*banner*/ 75 | implementation(libs.banner) 76 | 77 | /*glide*/ 78 | implementation(libs.glide) 79 | implementation(libs.compiler) 80 | 81 | /*agentWeb*/ 82 | implementation(libs.agentweb) 83 | 84 | /*VerticalTabLayout*/ 85 | /*implementation(libs.verticalTabLayout)*/ 86 | 87 | /*FlowLayout*/ 88 | implementation(libs.flowlayout.lib) 89 | 90 | 91 | } -------------------------------------------------------------------------------- /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 -------------------------------------------------------------------------------- /app/src/androidTest/java/com/pzj/android_mvp_kotlin/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package com.pzj.android_mvp_kotlin 2 | 3 | import androidx.test.platform.app.InstrumentationRegistry 4 | import androidx.test.ext.junit.runners.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.getInstrumentation().targetContext 22 | assertEquals("com.pzj.android_mvp_kotlin", appContext.packageName) 23 | } 24 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 20 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /app/src/main/java/com/pzj/android_mvp_kotlin/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.pzj.android_mvp_kotlin 2 | 3 | import android.os.Bundle 4 | import android.os.PersistableBundle 5 | import androidx.appcompat.app.AppCompatActivity 6 | import com.pzj.android_mvp_kotlin.databinding.ActivityMainBinding 7 | 8 | /** 9 | *Created by JeffPeng on 2024/03/19 10 | */ 11 | class MainActivity: AppCompatActivity() { 12 | 13 | private lateinit var binding: ActivityMainBinding 14 | 15 | override fun onCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) { 16 | super.onCreate(savedInstanceState, persistentState) 17 | 18 | binding = ActivityMainBinding.inflate(layoutInflater) 19 | 20 | setContentView(binding.root) 21 | 22 | 23 | } 24 | } -------------------------------------------------------------------------------- /app/src/main/java/com/pzj/android_mvp_kotlin/app/App.kt: -------------------------------------------------------------------------------- 1 | package com.pzj.android_mvp_kotlin.app 2 | 3 | import android.app.Application 4 | import com.yechaoa.yutilskt.ActivityUtil 5 | import com.yechaoa.yutilskt.LogUtil 6 | import com.yechaoa.yutilskt.YUtils 7 | 8 | /** 9 | *Created by JeffPeng on 2024/03/20 10 | */ 11 | class App:Application() { 12 | override fun onCreate() { 13 | super.onCreate() 14 | YUtils.init(this) 15 | LogUtil.setIsLog(true) 16 | registerActivityLifecycleCallbacks(ActivityUtil.activityLifecycleCallbacks) 17 | } 18 | } -------------------------------------------------------------------------------- /app/src/main/java/com/pzj/android_mvp_kotlin/base/BaseActivity.kt: -------------------------------------------------------------------------------- 1 | package com.pzj.android_mvp_kotlin.base 2 | 3 | import android.content.pm.ActivityInfo 4 | import android.os.Bundle 5 | import android.view.LayoutInflater 6 | import android.view.MenuItem 7 | import androidx.appcompat.app.AppCompatActivity 8 | import com.pzj.android_mvp_kotlin.base.BaseView 9 | import com.yechaoa.yutilskt.YUtils 10 | 11 | /** 12 | * Created by JeffPeng on 2020/1/3/003. 13 | * Describe : 14 | */ 15 | abstract class BaseActivity : AppCompatActivity(), BaseView { 16 | 17 | // protected var presenter: P? = null 18 | protected abstract fun createPresenter() 19 | 20 | override fun onCreate(savedInstanceState: Bundle?) { 21 | super.onCreate(savedInstanceState) 22 | 23 | //竖屏 24 | requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT 25 | 26 | setContentView(LayoutInflater.from(this).inflate(getLayoutId(), null)) 27 | 28 | // presenter = createPresenter() 29 | // presenter?.attachView(this) 30 | 31 | createPresenter() 32 | 33 | initView() 34 | } 35 | 36 | protected fun setMyTitle(title: String) { 37 | supportActionBar?.title = title 38 | } 39 | 40 | protected abstract fun getLayoutId(): Int 41 | 42 | protected abstract fun initView() 43 | 44 | override fun showLoading() { 45 | YUtils.showLoading(this, "加载中") 46 | } 47 | 48 | override fun hideLoading() { 49 | YUtils.hideLoading() 50 | } 51 | 52 | override fun onErrorCode(bean: BaseBean) { 53 | 54 | } 55 | 56 | /** 57 | * 统一处理返回键 58 | */ 59 | protected fun setBackEnabled() { 60 | supportActionBar?.apply { 61 | setHomeButtonEnabled(true) 62 | setDisplayHomeAsUpEnabled(true) 63 | } 64 | } 65 | 66 | /** 67 | * 返回键 68 | */ 69 | override fun onOptionsItemSelected(item: MenuItem): Boolean { 70 | val id = item.itemId 71 | if (id == android.R.id.home) { 72 | finish() 73 | return true 74 | } 75 | return super.onOptionsItemSelected(item) 76 | } 77 | 78 | override fun onDestroy() { 79 | super.onDestroy() 80 | // presenter?.detachView() 81 | } 82 | 83 | } 84 | -------------------------------------------------------------------------------- /app/src/main/java/com/pzj/android_mvp_kotlin/base/BaseBean.kt: -------------------------------------------------------------------------------- 1 | package com.pzj.android_mvp_kotlin.base 2 | 3 | /** 4 | * Created by JeffPeng on 2020/1/8/008. 5 | * Describe : 6 | */ 7 | 8 | data class BaseBean( 9 | val errorMsg: String, 10 | val errorCode: Int, 11 | val data: T 12 | ) 13 | -------------------------------------------------------------------------------- /app/src/main/java/com/pzj/android_mvp_kotlin/base/BaseException.kt: -------------------------------------------------------------------------------- 1 | package com.pzj.android_mvp_kotlin.base 2 | 3 | import java.io.IOException 4 | 5 | /** 6 | * Created by JeffPeng on 2020/1/9/009. 7 | * Describe : 8 | */ 9 | class BaseException : IOException() { 10 | 11 | companion object { 12 | /** 13 | * 解析数据失败 14 | */ 15 | val PARSE_ERROR_MSG = "解析数据失败" 16 | /** 17 | * 网络问题 18 | */ 19 | val BAD_NETWORK_MSG = "网络问题" 20 | /** 21 | * 连接错误 22 | */ 23 | val CONNECT_ERROR_MSG = "连接错误" 24 | /** 25 | * 连接超时 26 | */ 27 | val CONNECT_TIMEOUT_MSG = "连接超时" 28 | /** 29 | * 未知错误 30 | */ 31 | val OTHER_MSG = "未知错误" 32 | } 33 | 34 | private var errorMsg: String? = null 35 | private var errorCode = 0 36 | 37 | fun getErrorMsg(): String? { 38 | return errorMsg 39 | } 40 | 41 | fun getErrorCode(): Int { 42 | return errorCode 43 | } 44 | 45 | fun BaseException(message: String?) { 46 | errorMsg = message 47 | } 48 | 49 | fun BaseException(errorCode: Int, message: String?) { 50 | errorMsg = message 51 | this.errorCode = errorCode 52 | } 53 | 54 | } -------------------------------------------------------------------------------- /app/src/main/java/com/pzj/android_mvp_kotlin/base/BaseFragment.kt: -------------------------------------------------------------------------------- 1 | package com.pzj.android_mvp_kotlin.base 2 | 3 | import android.content.Context 4 | import android.os.Bundle 5 | import android.view.LayoutInflater 6 | import android.view.View 7 | import android.view.ViewGroup 8 | import androidx.fragment.app.Fragment 9 | import com.yechaoa.yutilskt.ActivityUtil 10 | import com.yechaoa.yutilskt.YUtils 11 | 12 | /** 13 | * Created by JeffPeng on 2020/1/13/013. 14 | * Describe : 15 | */ 16 | abstract class BaseFragment : Fragment(), BaseView { 17 | 18 | protected lateinit var mContext: Context 19 | 20 | override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { 21 | val view: View = inflater.inflate(getLayoutId(), container, false) 22 | mContext = ActivityUtil.currentActivity!! 23 | createPresenter() 24 | return view 25 | } 26 | 27 | /** 28 | * 初始化方法要放在onViewCreated或者onActivityCreated方法里,不然找不到控件 29 | */ 30 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) { 31 | super.onViewCreated(view, savedInstanceState) 32 | initView() 33 | initData() 34 | } 35 | 36 | /** 37 | * 懒加载,当Fragment显示的时候再请求数据 38 | * 如果数据不需要每次都刷新,可以先判断数据是否存在 39 | * 不存在 -> 请求数据,存在 -> 什么都不做 40 | */ 41 | override fun onHiddenChanged(hidden: Boolean) { 42 | super.onHiddenChanged(hidden) 43 | // if (hidden) initData() 44 | } 45 | 46 | protected abstract fun createPresenter() 47 | 48 | protected abstract fun getLayoutId(): Int 49 | 50 | protected abstract fun initView() 51 | 52 | protected abstract fun initData() 53 | 54 | override fun showLoading() { 55 | YUtils.showLoading(ActivityUtil.currentActivity!!, "加载中") 56 | } 57 | 58 | override fun hideLoading() { 59 | YUtils.hideLoading() 60 | } 61 | 62 | override fun onErrorCode(bean: BaseBean) { 63 | 64 | } 65 | } -------------------------------------------------------------------------------- /app/src/main/java/com/pzj/android_mvp_kotlin/base/BaseObserver.kt: -------------------------------------------------------------------------------- 1 | package com.pzj.android_mvp_kotlin.base 2 | 3 | import io.reactivex.observers.DisposableObserver 4 | 5 | /** 6 | * Created by JeffPeng on 2020/1/9/009. 7 | * Describe : 8 | */ 9 | abstract class BaseObserver : DisposableObserver { 10 | 11 | protected var view: BaseView? 12 | private var isShowDialog = false 13 | 14 | constructor(view: BaseView?) { 15 | this.view = view 16 | } 17 | 18 | constructor(view: BaseView?, isShowDialog: Boolean) { 19 | this.view = view 20 | this.isShowDialog = isShowDialog 21 | } 22 | 23 | override fun onStart() { 24 | if (view != null && isShowDialog) { 25 | view!!.showLoading() 26 | } 27 | } 28 | 29 | override fun onNext(o: T) { 30 | onSuccess(o) 31 | } 32 | 33 | override fun onError(e: Throwable) { 34 | if (view != null && isShowDialog) { 35 | view!!.hideLoading() 36 | } 37 | // val be: BaseException 38 | // if (e != null) { //自定义异常 39 | // if (e is BaseException) { 40 | // be = e 41 | // //回调到view层 处理 或者根据项目情况处理 42 | // if (view != null) { // 处理登录失效 更新 43 | //// view!!.onErrorCode(BaseBean(be.getErrorCode(), be.getErrorMsg())) 44 | // } else { 45 | // onError(be.getErrorMsg()) 46 | // } 47 | // //系统异常 48 | // } else { 49 | // be = if (e is HttpException) { //HTTP错误 50 | // BaseException(BaseException.BAD_NETWORK_MSG) 51 | // } else if (e is ConnectException || e is UnknownHostException) { //连接错误 52 | // BaseException(BaseException.CONNECT_ERROR_MSG, e) 53 | // } else if (e is InterruptedIOException) { //连接超时 54 | // BaseException(BaseException.CONNECT_TIMEOUT_MSG, e) 55 | // } else if (e is JsonParseException || e is JSONException || e is ParseException) { //解析错误 56 | // BaseException(BaseException.PARSE_ERROR_MSG, e) 57 | // } else { 58 | // BaseException(BaseException.OTHER_MSG, e) 59 | // } 60 | // } 61 | // } else { 62 | // be = BaseException(BaseException.OTHER_MSG) 63 | // } 64 | // onError(be.getErrorMsg()) 65 | 66 | onError("出现错误") 67 | } 68 | 69 | override fun onComplete() { 70 | if (view != null && isShowDialog) { 71 | view!!.hideLoading() 72 | } 73 | } 74 | 75 | abstract fun onSuccess(o: T) 76 | abstract fun onError(msg: String?) 77 | } -------------------------------------------------------------------------------- /app/src/main/java/com/pzj/android_mvp_kotlin/base/BasePresenter.kt: -------------------------------------------------------------------------------- 1 | package com.pzj.android_mvp_kotlin.base 2 | 3 | import com.pzj.android_mvp_kotlin.http.API 4 | import com.pzj.android_mvp_kotlin.http.RetrofitService 5 | import io.reactivex.Observable 6 | import io.reactivex.android.schedulers.AndroidSchedulers 7 | import io.reactivex.disposables.CompositeDisposable 8 | import io.reactivex.schedulers.Schedulers 9 | 10 | 11 | /** 12 | * Created by JeffPeng on 2020/1/9/009. 13 | * Describe : 14 | */ 15 | open class BasePresenter { 16 | 17 | private var compositeDisposable: CompositeDisposable? = null 18 | var mBaseView: V? = null 19 | protected var apiServer: API.WAZApi = RetrofitService.getApiService() 20 | 21 | /** 22 | * 绑定 23 | */ 24 | fun attachView(baseView: V) { 25 | mBaseView = baseView 26 | } 27 | 28 | /** 29 | * 解除绑定 30 | */ 31 | fun detachView() { 32 | mBaseView = null 33 | removeDisposable() 34 | } 35 | 36 | /** 37 | * 返回 view 38 | */ 39 | fun getBaseView(): V? { 40 | return mBaseView 41 | } 42 | 43 | fun addDisposable(observable: Observable<*>, observer: BaseObserver) { 44 | if (compositeDisposable == null) { 45 | compositeDisposable = CompositeDisposable() 46 | } 47 | compositeDisposable!! 48 | .add( 49 | observable.subscribeOn(Schedulers.io()) 50 | .observeOn(AndroidSchedulers.mainThread()) 51 | .subscribeWith(observer) 52 | ) 53 | } 54 | 55 | private fun removeDisposable() { 56 | if (compositeDisposable != null) { 57 | compositeDisposable!!.dispose() 58 | } 59 | } 60 | 61 | } -------------------------------------------------------------------------------- /app/src/main/java/com/pzj/android_mvp_kotlin/base/BaseView.kt: -------------------------------------------------------------------------------- 1 | package com.pzj.android_mvp_kotlin.base 2 | 3 | 4 | /** 5 | * Created by JeffPeng on 2020/1/9/009. 6 | * Describe : 7 | */ 8 | interface BaseView { 9 | 10 | fun showLoading() 11 | 12 | fun hideLoading() 13 | 14 | fun onErrorCode(bean: BaseBean) 15 | 16 | } -------------------------------------------------------------------------------- /app/src/main/java/com/pzj/android_mvp_kotlin/bean/Article.kt: -------------------------------------------------------------------------------- 1 | package com.pzj.android_mvp_kotlin.bean 2 | 3 | /** 4 | * Created by JeffPeng on 2020/1/17/017. 5 | * Describe : 6 | */ 7 | 8 | data class Article( 9 | val curPage: Int, 10 | val datas: MutableList, 11 | val offset: Int, 12 | val over: Boolean, 13 | val pageCount: Int, 14 | val size: Int, 15 | val total: Int 16 | ) 17 | 18 | data class ArticleDetail( 19 | val apkLink: String, 20 | val audit: Int, 21 | val author: String, 22 | val chapterId: Int, 23 | val chapterName: String, 24 | var collect: Boolean, 25 | val courseId: Int, 26 | val desc: String, 27 | val envelopePic: String, 28 | val fresh: Boolean, 29 | val id: Int, 30 | val link: String, 31 | val niceDate: String, 32 | val niceShareDate: String, 33 | val origin: String, 34 | val prefix: String, 35 | val projectLink: String, 36 | val publishTime: Long, 37 | val selfVisible: Int, 38 | val shareDate: Long, 39 | val shareUser: String, 40 | val superChapterId: Int, 41 | val superChapterName: String, 42 | val tags: List, 43 | val title: String, 44 | val type: Int, 45 | val userId: Int, 46 | val visible: Int, 47 | val zan: Int 48 | ) 49 | 50 | data class Tag( 51 | val name: String, 52 | val url: String 53 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/pzj/android_mvp_kotlin/bean/Banner.kt: -------------------------------------------------------------------------------- 1 | package com.pzj.android_mvp_kotlin.bean 2 | 3 | /** 4 | * Created by JeffPeng on 2020/1/19/019. 5 | * Describe : 6 | */ 7 | data class Banner( 8 | val desc: String, 9 | val id: Int, 10 | val imagePath: String, 11 | val isVisible: Int, 12 | val order: Int, 13 | val title: String, 14 | val type: Int, 15 | val url: String 16 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/pzj/android_mvp_kotlin/bean/Collect.kt: -------------------------------------------------------------------------------- 1 | package com.pzj.android_mvp_kotlin.bean 2 | 3 | 4 | data class Collect( 5 | val curPage: Int, 6 | val datas: MutableList, 7 | val offset: Int, 8 | val over: Boolean, 9 | val pageCount: Int, 10 | val size: Int, 11 | val total: Int 12 | ) 13 | 14 | data class CollectDetail( 15 | val author: String, 16 | val chapterId: Int, 17 | val chapterName: String, 18 | val courseId: Int, 19 | val desc: String, 20 | val envelopePic: String, 21 | val id: Int, 22 | val link: String, 23 | val niceDate: String, 24 | val origin: String, 25 | val originId: Int, 26 | val publishTime: Long, 27 | val title: String, 28 | val userId: Int, 29 | val visible: Int, 30 | val zan: Int 31 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/pzj/android_mvp_kotlin/bean/Hotkey.kt: -------------------------------------------------------------------------------- 1 | package com.pzj.android_mvp_kotlin.bean 2 | 3 | data class Hotkey( 4 | val id: Int, 5 | val link: String, 6 | val name: String, 7 | val order: Int, 8 | val visible: Int 9 | ) 10 | -------------------------------------------------------------------------------- /app/src/main/java/com/pzj/android_mvp_kotlin/bean/Navi.kt: -------------------------------------------------------------------------------- 1 | package com.pzj.android_mvp_kotlin.bean 2 | 3 | /** 4 | * Created by JeffPeng on 2020/1/19/019. 5 | * Describe : 6 | */ 7 | data class Navi( 8 | val articles: MutableList, 9 | val cid: Int, 10 | val name: String 11 | ) 12 | 13 | data class ArticleX( 14 | val apkLink: String, 15 | val audit: Int, 16 | val author: String, 17 | val chapterId: Int, 18 | val chapterName: String, 19 | val collect: Boolean, 20 | val courseId: Int, 21 | val desc: String, 22 | val envelopePic: String, 23 | val fresh: Boolean, 24 | val id: Int, 25 | val link: String, 26 | val niceDate: String, 27 | val niceShareDate: String, 28 | val origin: String, 29 | val prefix: String, 30 | val projectLink: String, 31 | val publishTime: Long, 32 | val selfVisible: Int, 33 | val shareDate: Long, 34 | val shareUser: String, 35 | val superChapterId: Int, 36 | val superChapterName: String, 37 | val tags: List, 38 | val title: String, 39 | val type: Int, 40 | val userId: Int, 41 | val visible: Int, 42 | val zan: Int 43 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/pzj/android_mvp_kotlin/bean/Project.kt: -------------------------------------------------------------------------------- 1 | package com.pzj.android_mvp_kotlin.bean 2 | 3 | /** 4 | * Created by JeffPeng on 2020/1/20/020. 5 | * Describe : 6 | */ 7 | data class Project( 8 | val children: List, 9 | val courseId: Int, 10 | val id: Int, 11 | val name: String, 12 | val order: Int, 13 | val parentChapterId: Int, 14 | val userControlSetTop: Boolean, 15 | val visible: Int 16 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/pzj/android_mvp_kotlin/bean/ProjectChild.kt: -------------------------------------------------------------------------------- 1 | package com.pzj.android_mvp_kotlin.bean 2 | 3 | /** 4 | * Created by JeffPeng on 2020/1/20/020. 5 | * Describe : 6 | */ 7 | data class ProjectChild( 8 | val curPage: Int, 9 | val datas: MutableList, 10 | val offset: Int, 11 | val over: Boolean, 12 | val pageCount: Int, 13 | val size: Int, 14 | val total: Int 15 | ) 16 | 17 | data class DataX( 18 | val apkLink: String, 19 | val audit: Int, 20 | val author: String, 21 | val chapterId: Int, 22 | val chapterName: String, 23 | val collect: Boolean, 24 | val courseId: Int, 25 | val desc: String, 26 | val envelopePic: String, 27 | val fresh: Boolean, 28 | val id: Int, 29 | val link: String, 30 | val niceDate: String, 31 | val niceShareDate: String, 32 | val origin: String, 33 | val prefix: String, 34 | val projectLink: String, 35 | val publishTime: Long, 36 | val selfVisible: Int, 37 | val shareDate: Long, 38 | val shareUser: String, 39 | val superChapterId: Int, 40 | val superChapterName: String, 41 | val tags: List, 42 | val title: String, 43 | val type: Int, 44 | val userId: Int, 45 | val visible: Int, 46 | val zan: Int 47 | ) 48 | 49 | data class TagX( 50 | val name: String, 51 | val url: String 52 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/pzj/android_mvp_kotlin/bean/Tree.kt: -------------------------------------------------------------------------------- 1 | package com.pzj.android_mvp_kotlin.bean 2 | 3 | import java.io.Serializable 4 | 5 | /** 6 | * Created by JeffPeng on 2020/1/19/019. 7 | * Describe : 8 | */ 9 | 10 | data class Tree( 11 | val children: ArrayList, 12 | var isShow: Boolean, 13 | val courseId: Int, 14 | val id: Int, 15 | val name: String, 16 | val order: Int, 17 | val parentChapterId: Int, 18 | val userControlSetTop: Boolean, 19 | val visible: Int 20 | ) : Serializable 21 | 22 | 23 | data class Children( 24 | val children: ArrayList, 25 | val courseId: Int, 26 | val id: Int, 27 | val name: String, 28 | val order: Int, 29 | val parentChapterId: Int, 30 | val userControlSetTop: Boolean, 31 | val visible: Int 32 | ) : Serializable -------------------------------------------------------------------------------- /app/src/main/java/com/pzj/android_mvp_kotlin/bean/User.kt: -------------------------------------------------------------------------------- 1 | package com.pzj.android_mvp_kotlin.bean 2 | 3 | data class User( 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 publicName: String, 13 | val token: String, 14 | val type: Int, 15 | val username: String 16 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/pzj/android_mvp_kotlin/common/MyConfig.kt: -------------------------------------------------------------------------------- 1 | package com.pzj.android_mvp_kotlin.common 2 | 3 | /** 4 | * Created by JeffPeng on 2020/1/8/008. 5 | * Describe : 6 | */ 7 | class MyConfig{ 8 | 9 | companion object{ 10 | 11 | const val IS_LOGIN="isLogin" 12 | 13 | const val COOKIE="cookie" 14 | 15 | } 16 | 17 | } -------------------------------------------------------------------------------- /app/src/main/java/com/pzj/android_mvp_kotlin/http/API.kt: -------------------------------------------------------------------------------- 1 | package com.pzj.android_mvp_kotlin.http 2 | 3 | import com.pzj.android_mvp_kotlin.base.BaseBean 4 | import com.pzj.android_mvp_kotlin.bean.* 5 | import io.reactivex.Observable 6 | import retrofit2.http.* 7 | 8 | /** 9 | * Created by JeffPeng on 2020/1/8/008. 10 | * Describe : 11 | */ 12 | class API { 13 | 14 | companion object { 15 | const val BASE_URL = "https://www.wanandroid.com/" 16 | } 17 | 18 | interface WAZApi { 19 | 20 | //-----------------------【登录注册】---------------------- 21 | 22 | //登录 23 | @FormUrlEncoded 24 | @POST("user/login") 25 | fun login( 26 | @Field("username") username: String?, 27 | @Field("password") password: String? 28 | ): Observable> 29 | 30 | //注册 31 | @FormUrlEncoded 32 | @POST("user/register") 33 | fun register( 34 | @Field("username") username: String?, 35 | @Field("password") password: String?, 36 | @Field("repassword") repassword: String? 37 | ): Observable> 38 | 39 | 40 | //-----------------------【首页相关】---------------------- 41 | 42 | //首页文章列表 43 | @GET("article/list/{page}/json") 44 | fun getArticleList(@Path("page") page: Int): Observable> 45 | 46 | //首页banner 47 | @GET("banner/json") 48 | fun getBanner(): Observable>> 49 | 50 | 51 | //-----------------------【 体系 】---------------------- 52 | 53 | //体系数据 54 | @GET("tree/json") 55 | fun getTree(): Observable>> 56 | 57 | //知识体系下的文章 58 | @GET("article/list/{page}/json?") 59 | fun getTreeChild( 60 | @Path("page") page: Int, 61 | @Query("cid") cid: Int 62 | ): Observable> 63 | 64 | //-----------------------【 导航 】---------------------- 65 | 66 | //导航数据 67 | @GET("navi/json") 68 | fun getNavi(): Observable>> 69 | 70 | 71 | //-----------------------【 项目 】---------------------- 72 | 73 | //项目分类 74 | @GET("project/tree/json") 75 | fun getProject(): Observable>> 76 | 77 | //项目列表数据 78 | @GET("project/list/{page}/json?") 79 | fun getProjectChild( 80 | @Path("page") page: Int, 81 | @Query("cid") cid: Int 82 | ): Observable> 83 | 84 | 85 | //-----------------------【 搜索 】---------------------- 86 | 87 | //搜索 88 | @FormUrlEncoded 89 | @POST("article/query/{page}/json?") 90 | fun getSearchList( 91 | @Path("page") page: Int, 92 | @Field("k") k: String 93 | ): Observable> 94 | 95 | //搜索热词 96 | @GET("hotkey/json") 97 | fun getHotkey(): Observable>> 98 | 99 | //-----------------------【 收藏 】---------------------- 100 | 101 | //收藏文章列表 102 | @GET("lg/collect/list/{page}/json?") 103 | fun getCollectList(@Path("page") page: Int): Observable> 104 | 105 | //收藏站内文章 106 | @POST("lg/collect/{id}/json") 107 | fun collect(@Path("id") id: Int): Observable> 108 | 109 | //取消收藏(文章列表) 110 | @POST("lg/uncollect_originId/{id}/json") 111 | fun unCollect(@Path("id") id: Int): Observable> 112 | 113 | //取消收藏(我的收藏页面) 114 | @FormUrlEncoded 115 | @POST("lg/uncollect/{id}/json") 116 | fun unCollect1( 117 | @Path("id") id: Int, 118 | @Field("originId") originId: Int 119 | ): Observable> 120 | 121 | } 122 | 123 | } -------------------------------------------------------------------------------- /app/src/main/java/com/pzj/android_mvp_kotlin/http/RetrofitService.kt: -------------------------------------------------------------------------------- 1 | package com.pzj.android_mvp_kotlin.http 2 | 3 | import com.pzj.android_mvp_kotlin.http.interceptor.AddCookiesInterceptor 4 | import com.pzj.android_mvp_kotlin.http.interceptor.ReceivedCookiesInterceptor 5 | import okhttp3.OkHttpClient 6 | import okhttp3.logging.HttpLoggingInterceptor 7 | import retrofit2.Retrofit 8 | import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory 9 | import retrofit2.converter.gson.GsonConverterFactory 10 | import java.util.concurrent.TimeUnit 11 | 12 | /** 13 | * Created by JeffPeng on 2020/1/8/008. 14 | * Describe : 15 | */ 16 | object RetrofitService { 17 | 18 | private var apiServer: API.WAZApi 19 | 20 | fun getApiService(): API.WAZApi { 21 | return apiServer 22 | } 23 | 24 | //初始化retrofit 25 | init { 26 | val httpLoggingInterceptor = HttpLoggingInterceptor() 27 | httpLoggingInterceptor.level = HttpLoggingInterceptor.Level.BODY 28 | 29 | val okHttpClient = OkHttpClient.Builder() 30 | .addInterceptor(httpLoggingInterceptor) 31 | .addInterceptor(AddCookiesInterceptor()) 32 | .addInterceptor(ReceivedCookiesInterceptor()) 33 | .connectTimeout(15, TimeUnit.SECONDS) 34 | .build() 35 | 36 | //关联okhttp并加上rxjava和gson的配置和baseurl 37 | val retrofit = Retrofit.Builder() 38 | .client(okHttpClient) 39 | .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) 40 | .addConverterFactory(GsonConverterFactory.create()) 41 | .baseUrl(API.BASE_URL) 42 | .build() 43 | 44 | apiServer = retrofit.create(API.WAZApi::class.java) 45 | } 46 | 47 | } -------------------------------------------------------------------------------- /app/src/main/java/com/pzj/android_mvp_kotlin/http/interceptor/AddCookiesInterceptor.kt: -------------------------------------------------------------------------------- 1 | package com.pzj.android_mvp_kotlin.http.interceptor 2 | 3 | import com.pzj.android_mvp_kotlin.common.MyConfig 4 | import com.yechaoa.yutilskt.SpUtil 5 | import okhttp3.Interceptor 6 | import okhttp3.Request 7 | import okhttp3.Response 8 | import java.io.IOException 9 | 10 | /** 11 | * Created by JeffPeng on 2020/3/10/010. 12 | * Describe : 从响应头里拿到cookie并存起来,后面的每次请求再添加到请求头里 13 | */ 14 | class AddCookiesInterceptor : Interceptor { 15 | @Throws(IOException::class) 16 | override fun intercept(chain: Interceptor.Chain): Response { 17 | val builder: Request.Builder = chain.request().newBuilder() 18 | val stringSet = SpUtil.getStringSet(MyConfig.COOKIE) 19 | for (cookie in stringSet) { 20 | builder.addHeader("Cookie", cookie) 21 | } 22 | return chain.proceed(builder.build()) 23 | } 24 | } -------------------------------------------------------------------------------- /app/src/main/java/com/pzj/android_mvp_kotlin/http/interceptor/ReceivedCookiesInterceptor.kt: -------------------------------------------------------------------------------- 1 | package com.pzj.android_mvp_kotlin.http.interceptor 2 | 3 | import com.pzj.android_mvp_kotlin.common.MyConfig 4 | import com.yechaoa.yutilskt.SpUtil 5 | import okhttp3.Interceptor 6 | import okhttp3.Response 7 | import java.io.IOException 8 | 9 | 10 | /** 11 | * Created by JeffPeng on 2020/3/10/010. 12 | * Describe : 从响应头里拿到cookie并存起来,后面的每次请求再添加到请求头里 13 | */ 14 | class ReceivedCookiesInterceptor : Interceptor { 15 | @Throws(IOException::class) 16 | override fun intercept(chain: Interceptor.Chain): Response { 17 | val originalResponse: Response = chain.proceed(chain.request()) 18 | if (originalResponse.headers("Set-Cookie").isNotEmpty()) { 19 | val cookies: HashSet = HashSet() 20 | for (header in originalResponse.headers("Set-Cookie")) { 21 | cookies.add(header) 22 | } 23 | SpUtil.setStringSet(MyConfig.COOKIE, cookies) 24 | } 25 | return originalResponse 26 | } 27 | } -------------------------------------------------------------------------------- /app/src/main/java/com/pzj/android_mvp_kotlin/utils/GlideImageLoader.kt: -------------------------------------------------------------------------------- 1 | package com.pzj.android_mvp_kotlin.utils 2 | 3 | import android.content.Context 4 | import android.widget.ImageView 5 | import com.bumptech.glide.Glide 6 | 7 | /** 8 | * Created by JeffPeng on 2020/1/19/019. 9 | * Describe : 10 | */ 11 | class GlideImageLoader{ 12 | /** 13 | * 注意: 14 | * 1.图片加载器由自己选择,这里不限制,只是提供几种使用方法 15 | * 2.返回的图片路径为Object类型,由于不能确定你到底使用的那种图片加载器, 16 | * 传输的到的是什么格式,那么这种就使用Object接收和返回,你只需要强转成你传输的类型就行, 17 | * 切记不要胡乱强转! 18 | */ 19 | fun displayImage(context: Context?, path: Any?, imageView: ImageView?) { 20 | //Glide 加载图片简单用法 21 | Glide.with(context!!).load(path).into(imageView!!) 22 | } 23 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pengzhijing/android_mvp_kotlin/da4ea2f3efe134d0f5aa9e1044e8e75f0883f1cf/app/src/main/res/drawable/ic_down.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pengzhijing/android_mvp_kotlin/da4ea2f3efe134d0f5aa9e1044e8e75f0883f1cf/app/src/main/res/drawable/ic_home.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 15 | 18 | 21 | 22 | 23 | 24 | 30 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_like_checked.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pengzhijing/android_mvp_kotlin/da4ea2f3efe134d0f5aa9e1044e8e75f0883f1cf/app/src/main/res/drawable/ic_like_checked.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_like_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pengzhijing/android_mvp_kotlin/da4ea2f3efe134d0f5aa9e1044e8e75f0883f1cf/app/src/main/res/drawable/ic_like_normal.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_menu_exit.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_menu_favorite.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_menu_info.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_menu_search.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_menu_share.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_navi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pengzhijing/android_mvp_kotlin/da4ea2f3efe134d0f5aa9e1044e8e75f0883f1cf/app/src/main/res/drawable/ic_navi.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_project.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pengzhijing/android_mvp_kotlin/da4ea2f3efe134d0f5aa9e1044e8e75f0883f1cf/app/src/main/res/drawable/ic_project.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_share_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pengzhijing/android_mvp_kotlin/da4ea2f3efe134d0f5aa9e1044e8e75f0883f1cf/app/src/main/res/drawable/ic_tree.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pengzhijing/android_mvp_kotlin/da4ea2f3efe134d0f5aa9e1044e8e75f0883f1cf/app/src/main/res/drawable/ic_up.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/selector_primary_oval.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/shape_border_primary_oval.xml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/shape_eaeaea_oval.xml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/shape_oval_primary.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 10 | 13 | 14 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/side_nav_bar.xml: -------------------------------------------------------------------------------- 1 | 3 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_about.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 15 | 16 | 24 | 25 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_collect.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 15 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_detail.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_login.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 16 | 17 | 24 | 25 | 30 | 31 | 39 | 40 | 51 | 52 | 53 | 54 | 55 | 56 | 64 | 65 | 70 | 71 | 79 | 80 | 92 | 93 | 94 | 95 | 96 | 97 |