[
  {
    "path": ".gitignore",
    "content": "*.iml\n.gradle\n/local.properties\n/.idea/caches\n/.idea/libraries\n/.idea/modules.xml\n/.idea/workspace.xml\n/.idea/navEditor.xml\n/.idea/assetWizardSettings.xml\n.DS_Store\n/build\n/captures\n.externalNativeBuild\n"
  },
  {
    "path": ".idea/codeStyles/Project.xml",
    "content": "<component name=\"ProjectCodeStyleConfiguration\">\n  <code_scheme name=\"Project\" version=\"173\">\n    <JetCodeStyleSettings>\n      <option name=\"CODE_STYLE_DEFAULTS\" value=\"KOTLIN_OFFICIAL\" />\n    </JetCodeStyleSettings>\n    <codeStyleSettings language=\"XML\">\n      <arrangement>\n        <rules>\n          <section>\n            <rule>\n              <match>\n                <AND>\n                  <NAME>xmlns:android</NAME>\n                  <XML_ATTRIBUTE />\n                  <XML_NAMESPACE>^$</XML_NAMESPACE>\n                </AND>\n              </match>\n            </rule>\n          </section>\n          <section>\n            <rule>\n              <match>\n                <AND>\n                  <NAME>xmlns:.*</NAME>\n                  <XML_ATTRIBUTE />\n                  <XML_NAMESPACE>^$</XML_NAMESPACE>\n                </AND>\n              </match>\n              <order>BY_NAME</order>\n            </rule>\n          </section>\n          <section>\n            <rule>\n              <match>\n                <AND>\n                  <NAME>.*:id</NAME>\n                  <XML_ATTRIBUTE />\n                  <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>\n                </AND>\n              </match>\n            </rule>\n          </section>\n          <section>\n            <rule>\n              <match>\n                <AND>\n                  <NAME>.*:name</NAME>\n                  <XML_ATTRIBUTE />\n                  <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>\n                </AND>\n              </match>\n            </rule>\n          </section>\n          <section>\n            <rule>\n              <match>\n                <AND>\n                  <NAME>name</NAME>\n                  <XML_ATTRIBUTE />\n                  <XML_NAMESPACE>^$</XML_NAMESPACE>\n                </AND>\n              </match>\n            </rule>\n          </section>\n          <section>\n            <rule>\n              <match>\n                <AND>\n                  <NAME>style</NAME>\n                  <XML_ATTRIBUTE />\n                  <XML_NAMESPACE>^$</XML_NAMESPACE>\n                </AND>\n              </match>\n            </rule>\n          </section>\n          <section>\n            <rule>\n              <match>\n                <AND>\n                  <NAME>.*</NAME>\n                  <XML_ATTRIBUTE />\n                  <XML_NAMESPACE>^$</XML_NAMESPACE>\n                </AND>\n              </match>\n              <order>BY_NAME</order>\n            </rule>\n          </section>\n          <section>\n            <rule>\n              <match>\n                <AND>\n                  <NAME>.*</NAME>\n                  <XML_ATTRIBUTE />\n                  <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>\n                </AND>\n              </match>\n              <order>ANDROID_ATTRIBUTE_ORDER</order>\n            </rule>\n          </section>\n          <section>\n            <rule>\n              <match>\n                <AND>\n                  <NAME>.*</NAME>\n                  <XML_ATTRIBUTE />\n                  <XML_NAMESPACE>.*</XML_NAMESPACE>\n                </AND>\n              </match>\n              <order>BY_NAME</order>\n            </rule>\n          </section>\n        </rules>\n      </arrangement>\n    </codeStyleSettings>\n    <codeStyleSettings language=\"kotlin\">\n      <option name=\"CODE_STYLE_DEFAULTS\" value=\"KOTLIN_OFFICIAL\" />\n    </codeStyleSettings>\n  </code_scheme>\n</component>"
  },
  {
    "path": ".idea/codeStyles/codeStyleConfig.xml",
    "content": "<component name=\"ProjectCodeStyleConfiguration\">\n  <state>\n    <option name=\"USE_PER_PROJECT_SETTINGS\" value=\"true\" />\n  </state>\n</component>"
  },
  {
    "path": ".idea/compiler.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"CompilerConfiguration\">\n    <wildcardResourcePatterns>\n      <entry name=\"!?*.java\" />\n      <entry name=\"!?*.form\" />\n      <entry name=\"!?*.class\" />\n      <entry name=\"!?*.groovy\" />\n      <entry name=\"!?*.scala\" />\n      <entry name=\"!?*.flex\" />\n      <entry name=\"!?*.kt\" />\n      <entry name=\"!?*.clj\" />\n    </wildcardResourcePatterns>\n  </component>\n</project>"
  },
  {
    "path": ".idea/encodings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"Encoding\" addBOMForNewFiles=\"with NO BOM\">\n    <file url=\"PROJECT\" charset=\"UTF-8\" />\n  </component>\n</project>"
  },
  {
    "path": ".idea/gradle.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"GradleSettings\">\n    <option name=\"linkedExternalProjectsSettings\">\n      <GradleProjectSettings>\n        <option name=\"distributionType\" value=\"DEFAULT_WRAPPED\" />\n        <option name=\"externalProjectPath\" value=\"$PROJECT_DIR$\" />\n        <option name=\"modules\">\n          <set>\n            <option value=\"$PROJECT_DIR$\" />\n            <option value=\"$PROJECT_DIR$/app\" />\n            <option value=\"$PROJECT_DIR$/module_library\" />\n          </set>\n        </option>\n        <option name=\"resolveModulePerSourceSet\" value=\"false\" />\n      </GradleProjectSettings>\n    </option>\n  </component>\n</project>"
  },
  {
    "path": ".idea/inspectionProfiles/Project_Default.xml",
    "content": "<component name=\"InspectionProjectProfileManager\">\n  <profile version=\"1.0\">\n    <option name=\"myName\" value=\"Project Default\" />\n    <inspection_tool class=\"JavaDoc\" enabled=\"true\" level=\"WARNING\" enabled_by_default=\"true\">\n      <option name=\"TOP_LEVEL_CLASS_OPTIONS\">\n        <value>\n          <option name=\"ACCESS_JAVADOC_REQUIRED_FOR\" value=\"none\" />\n          <option name=\"REQUIRED_TAGS\" value=\"\" />\n        </value>\n      </option>\n      <option name=\"INNER_CLASS_OPTIONS\">\n        <value>\n          <option name=\"ACCESS_JAVADOC_REQUIRED_FOR\" value=\"none\" />\n          <option name=\"REQUIRED_TAGS\" value=\"\" />\n        </value>\n      </option>\n      <option name=\"METHOD_OPTIONS\">\n        <value>\n          <option name=\"ACCESS_JAVADOC_REQUIRED_FOR\" value=\"none\" />\n          <option name=\"REQUIRED_TAGS\" value=\"@return@param@throws or @exception\" />\n        </value>\n      </option>\n      <option name=\"FIELD_OPTIONS\">\n        <value>\n          <option name=\"ACCESS_JAVADOC_REQUIRED_FOR\" value=\"none\" />\n          <option name=\"REQUIRED_TAGS\" value=\"\" />\n        </value>\n      </option>\n      <option name=\"IGNORE_DEPRECATED\" value=\"false\" />\n      <option name=\"IGNORE_JAVADOC_PERIOD\" value=\"true\" />\n      <option name=\"IGNORE_DUPLICATED_THROWS\" value=\"false\" />\n      <option name=\"IGNORE_POINT_TO_ITSELF\" value=\"false\" />\n      <option name=\"myAdditionalJavadocTags\" value=\"date\" />\n    </inspection_tool>\n  </profile>\n</component>"
  },
  {
    "path": ".idea/misc.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"CMakeSettings\">\n    <configurations>\n      <configuration PROFILE_NAME=\"Debug\" CONFIG_NAME=\"Debug\" />\n    </configurations>\n  </component>\n  <component name=\"ProjectRootManager\" version=\"2\" languageLevel=\"JDK_1_8\" project-jdk-name=\"1.8\" project-jdk-type=\"JavaSDK\">\n    <output url=\"file://$PROJECT_DIR$/build/classes\" />\n  </component>\n  <component name=\"ProjectType\">\n    <option name=\"id\" value=\"Android\" />\n  </component>\n</project>"
  },
  {
    "path": ".idea/runConfigurations.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"RunConfigurationProducerService\">\n    <option name=\"ignoredProducers\">\n      <set>\n        <option value=\"org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer\" />\n        <option value=\"org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer\" />\n        <option value=\"org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer\" />\n      </set>\n    </option>\n  </component>\n</project>"
  },
  {
    "path": ".idea/vcs.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"VcsDirectoryMappings\">\n    <mapping directory=\"$PROJECT_DIR$\" vcs=\"Git\" />\n  </component>\n</project>"
  },
  {
    "path": "README.md",
    "content": "# Awesome-Kotlin-WanAndroid\n\n## 简介\n项目主要用来入门`kotlin`语言和google推荐的`MVVM`架构，使用了一些`Jetpack`组件来配合MVVM使用，采用了很多流行的开源库，`Okhttp`，`Retrofit`,`Rxjava`,`Glide`，`Livedatabus`等，代码逻辑简单易懂，仅适用入门\n## 项目功能列表截图\n<img src=\"https://raw.githubusercontent.com/malonecoder/Awesome-Kotlin-WanAndroid/master/screenshots/%E7%9B%AE%E5%BD%95.webp\" width=280 height=500 /><img src=\"https://raw.githubusercontent.com/malonecoder/Awesome-Kotlin-WanAndroid/master/screenshots/%E4%B8%BB%E9%A1%B5%E4%BE%A7%E6%BB%91%E8%8F%9C%E5%8D%95.webp\" width=280 height=500 />\n<img src=\"https://raw.githubusercontent.com/malonecoder/Awesome-Kotlin-WanAndroid/master/screenshots/%E6%B3%A8%E5%86%8C.webp\" width=280 height=500 />\n<img src=\"https://raw.githubusercontent.com/malonecoder/Awesome-Kotlin-WanAndroid/master/screenshots/%E7%9F%A5%E8%AF%86%E4%BD%93%E7%B3%BB.webp\" width=280 height=500 />\n<img src=\"https://raw.githubusercontent.com/malonecoder/Awesome-Kotlin-WanAndroid/master/screenshots/%E7%A6%8F%E5%88%A9.webp\" width=280 height=500 />\n<img src=\"https://raw.githubusercontent.com/malonecoder/Awesome-Kotlin-WanAndroid/master/screenshots/%E5%AF%BC%E8%88%AA.webp\" width=280 height=500 />  \n<img src=\"https://raw.githubusercontent.com/malonecoder/Awesome-Kotlin-WanAndroid/master/screenshots/%E9%A6%96%E9%A1%B5.webp\" width=280 height=500 />\n<img src=\"https://raw.githubusercontent.com/malonecoder/Awesome-Kotlin-WanAndroid/master/screenshots/%E6%94%B6%E8%97%8F.webp\" width=280 height=500 />  \n## 功能TODO List\n- [x] 首页\n- [x] 知识体系\n- [x] 导航\n- [x] 项目\n- [x] 福利\n- [x] 登录/登出\n- [x] 我的收藏\n- [ ] 欢迎页\n- [ ] 热门搜索\n- [ ] 待办清单功能\n- [ ] 网络层切换协程\n- [ ] 代码整体优化\n## 使用的开源库\n* [Retrofit](https://github.com/square/retrofit)\n* [Okhttp](https://github.com/square/okhttp)\n* [Rxjava](https://github.com/ReactiveX/RxJava)\n* [Glide](https://github.com/bumptech/glide)\n* [LiveDataBus](https://github.com/JeremyLiao/LiveEventBus)\n* [glide-transformations](https://github.com/wasabeef/glide-transformations)\n* [toastcompat](https://github.com/PureWriter/ToastCompat)\n* [circleimageview](https://github.com/hdodenhof/CircleImageView)\n* [PhotoView](https://github.com/chrisbanes/PhotoView)\n* [flowlayout](https://github.com/hongyangAndroid/FlowLayout)\n* [MZBannerView](https://github.com/pinguo-zhouwei/MZBannerView)\n* [MaterialLogin](https://github.com/shem8/MaterialLogin)\n* [AgentWeb](https://github.com/Justson/AgentWeb)\n## 非常感谢\n* [CloudReader](https://github.com/youlookwhat/CloudReader)\n* [WanAndroid Open API](https://www.wanandroid.com/blog/show/2)\n* [Gan Open API](https://gank.io/)\n* [界面参考](https://flutterchina.club/app/gm.html)\n* [ICON素材](https://www.iconfont.cn/)\n"
  },
  {
    "path": "app/.gitignore",
    "content": "/build\n"
  },
  {
    "path": "app/build.gradle",
    "content": "apply plugin: 'com.android.application'\n\napply plugin: 'kotlin-android'\napply plugin: 'kotlin-kapt'\napply plugin: 'kotlin-android-extensions'\n\nandroid {\n    compileSdkVersion 28\n    defaultConfig {\n        applicationId \"com.lxm.wanandroid\"\n        minSdkVersion 21\n        targetSdkVersion 28\n        versionCode 1\n        versionName \"1.0\"\n        testInstrumentationRunner \"android.support.test.runner.AndroidJUnitRunner\"\n    }\n    buildTypes {\n        release {\n            minifyEnabled false\n            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'\n        }\n    }\n    compileOptions {\n        sourceCompatibility = '1.8'\n        targetCompatibility = '1.8'\n    }\n\n    dataBinding {\n        enabled = true\n    }\n}\n\ndependencies {\n    implementation fileTree(dir: 'libs', include: ['*.jar'])\n    implementation \"org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version\"\n    implementation \"org.jetbrains.kotlin:kotlin-reflect:$kotlin_version\"\n    implementation 'com.android.support:appcompat-v7:28.0.0'\n    implementation 'com.android.support.constraint:constraint-layout:1.1.3'\n    implementation 'com.android.support:design:28.0.0'\n    testImplementation 'junit:junit:4.12'\n    androidTestImplementation 'com.android.support.test:runner:1.0.2'\n    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'\n\n\n    implementation project(':module_library')\n\n    implementation 'com.google.android.gms:play-services-plus:15.0.1'\n    implementation 'com.flyco.tablayout:FlycoTabLayout_Lib:2.1.2@aar'\n    implementation 'android.arch.lifecycle:extensions:1.1.1'\n    implementation 'com.android.support:design:28.0.0-rc01'\n    implementation 'com.just.agentweb:agentweb:4.0.2'\n\n    // Navigation\n    def nav_version = \"1.0.0-alpha06\"\n    implementation \"android.arch.navigation:navigation-fragment:$nav_version\"\n    implementation \"android.arch.navigation:navigation-ui:$nav_version\"\n    androidTestImplementation \"android.arch.navigation:navigation-testing:$nav_version\"\n    implementation \"org.jetbrains.kotlin:kotlin-reflect:1.2.60\"\n\n    //Room\n    def room_version = \"1.1.1\"\n    implementation \"android.arch.persistence.room:runtime:$room_version\"\n    kapt \"android.arch.persistence.room:compiler:$room_version\"\n    implementation \"android.arch.persistence.room:rxjava2:$room_version\"\n    implementation \"android.arch.persistence.room:guava:$room_version\"\n    testImplementation \"android.arch.persistence.room:testing:$room_version\"\n\n    //首页banner\n    implementation 'com.github.pinguo-zhouwei:MZBannerView:v2.0.2'\n    //体系flowlayout\n    implementation 'com.hyman:flowlayout-lib:1.1.2'\n    //大图查看\n    implementation 'com.github.chrisbanes:PhotoView:1.2'\n    //圆形头像\n    implementation 'de.hdodenhof:circleimageview:3.0.0'\n    //livedataBus\n    implementation 'com.jeremyliao:live-event-bus:1.4.4'\n\n\n\n}\n"
  },
  {
    "path": "app/proguard-rules.pro",
    "content": "# Add project specific ProGuard rules here.\n# You can control the set of applied configuration files using the\n# proguardFiles setting in build.gradle.\n#\n# For more details, see\n#   http://developer.android.com/guide/developing/tools/proguard.html\n\n# If your project uses WebView with JS, uncomment the following\n# and specify the fully qualified class name to the JavaScript interface\n# class:\n#-keepclassmembers class fqcn.of.javascript.interface.for.webview {\n#   public *;\n#}\n\n# Uncomment this to preserve the line number information for\n# debugging stack traces.\n#-keepattributes SourceFile,LineNumberTable\n\n# If you keep the line number information, uncomment this to\n# hide the original source file name.\n#-renamesourcefileattribute SourceFile\n"
  },
  {
    "path": "app/src/androidTest/java/com/lxm/wanandroid/ExampleInstrumentedTest.kt",
    "content": "package com.lxm.wanandroid\n\nimport android.support.test.InstrumentationRegistry\nimport android.support.test.runner.AndroidJUnit4\n\nimport org.junit.Test\nimport org.junit.runner.RunWith\n\nimport org.junit.Assert.*\n\n/**\n * Instrumented test, which will execute on an Android device.\n *\n * See [testing documentation](http://d.android.com/tools/testing).\n */\n@RunWith(AndroidJUnit4::class)\nclass ExampleInstrumentedTest {\n    @Test\n    fun useAppContext() {\n        // Context of the app under test.\n        val appContext = InstrumentationRegistry.getTargetContext()\n        assertEquals(\"com.lxm.wanandroid\", appContext.packageName)\n    }\n}\n"
  },
  {
    "path": "app/src/main/AndroidManifest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n          package=\"com.lxm.wanandroid\">\n\n    <uses-permission android:name=\"android.permission.INTERNET\" />\n    <uses-permission android:name=\"android.permission.WRITE_EXTERNAL_STORAGE\" />\n    <application\n            android:usesCleartextTraffic=\"true\"\n            android:name=\"com.lxm.module_library.global.GlobalApplication\"\n            android:allowBackup=\"true\"\n            android:icon=\"@mipmap/ic_launcher\"\n            android:label=\"@string/app_name\"\n            android:roundIcon=\"@mipmap/ic_launcher_round\"\n            android:supportsRtl=\"true\"\n            android:theme=\"@style/AppTheme\">\n        <activity android:name=\".MainActivity\">\n            <intent-filter>\n                <action android:name=\"android.intent.action.MAIN\"/>\n\n                <category android:name=\"android.intent.category.LAUNCHER\"/>\n            </intent-filter>\n        </activity>\n        <activity\n                android:configChanges=\"orientation|screenSize\"\n                android:hardwareAccelerated=\"true\"\n                android:launchMode=\"singleTask\"\n                android:screenOrientation=\"portrait\"\n                android:name=\".utils.webview.WebViewActivity\"></activity>\n        <activity android:name=\".ui.TagArticleActivity\"></activity>\n        <activity android:name=\".ui.ViewBigImageActivity\"></activity>\n        <activity android:name=\".ui.LoginActivity\"></activity>\n        <activity android:name=\".ui.CollectActivity\"></activity>\n    </application>\n\n</manifest>"
  },
  {
    "path": "app/src/main/java/com/lxm/wanandroid/MainActivity.kt",
    "content": "package com.lxm.wanandroid\n\nimport android.arch.lifecycle.Observer\nimport android.arch.lifecycle.ViewModel\nimport android.arch.lifecycle.ViewModelProvider\nimport android.arch.lifecycle.ViewModelProviders\nimport android.content.Intent\nimport android.os.Bundle\nimport android.support.v4.app.Fragment\nimport android.support.v4.app.FragmentManager\nimport android.support.v4.app.FragmentPagerAdapter\nimport android.support.v7.app.AppCompatActivity\nimport android.view.Gravity\nimport android.view.KeyEvent\nimport android.view.Menu\nimport android.view.MenuItem\nimport android.widget.TextView\nimport com.jeremyliao.liveeventbus.LiveEventBus\nimport com.lxm.module_library.helper.okhttp.cookies.CookieManger\nimport com.lxm.module_library.statusbar.StatusBarUtil\nimport com.lxm.module_library.utils.PreferencesUtil\nimport com.lxm.module_library.utils.ToastUtils\nimport com.lxm.wanandroid.repository.remote.LoginRepository\nimport com.lxm.wanandroid.ui.*\nimport com.lxm.wanandroid.viewmodel.LoginViewModel\nimport kotlinx.android.synthetic.main.activity_main.*\nimport kotlinx.android.synthetic.main.main_content.*\n\n\n\n\nconst val PHOTO_URL = \"https://cdn.duitang.com/uploads/blog/201404/22/20140422142715_8GtUk.thumb.600_0.jpeg\"\n\nclass MainActivity : AppCompatActivity() {\n\n    private val mTitles by lazy {\n        mutableListOf(\"主页\", \"知识体系\", \"导航\", \"项目\", \"福利\")\n    }\n    private val mFragments: MutableList<Fragment> by lazy {\n        mutableListOf<Fragment>()\n    }\n\n    private val mAdapter: MyPagerAdapter by lazy {\n        MyPagerAdapter(supportFragmentManager)\n    }\n\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n        setContentView(R.layout.activity_main)\n        StatusBarUtil.setColor(this, resources.getColor(R.color.colorTheme), 0)\n        setSupportActionBar(toolbar)\n        supportActionBar?.setDisplayHomeAsUpEnabled(false)\n        iv_photo.setOnClickListener {\n            drawerLayout.openDrawer(Gravity.START)\n        }\n\n        var loginViewModel = ViewModelProviders.of(this@MainActivity, object : ViewModelProvider.Factory {\n            override fun <T : ViewModel?> create(modelClass: Class<T>): T {\n                return LoginViewModel(LoginRepository()) as T\n            }\n\n        })[LoginViewModel::class.java]\n\n        var textView = navigationView.getHeaderView(0).findViewById<TextView>(R.id.tvUserName)\n        textView.text = \"萧兮易水寒\"\n        val menuItem = navigationView.menu.findItem(R.id.accout) as MenuItem\n        var isLogin: Boolean by PreferencesUtil<Boolean>(\"login\", false)\n        if (isLogin) {\n            menuItem.title = \"注销\"\n            menuItem.setIcon(R.drawable.ic_logout_menu)\n        } else {\n            menuItem.title = \"登陆\"\n            menuItem.setIcon(R.drawable.ic_login_menu)\n        }\n\n\n        LiveEventBus.get()\n            .with(LoginActivity.LOGIN_SUCCESS, String::class.java)\n            .observe(this@MainActivity, Observer {\n                menuItem.title = \"注销\"\n                menuItem.setIcon(R.drawable.ic_logout_menu)\n            })\n        navigationView.setNavigationItemSelectedListener {\n            when (it.itemId) {\n\n                R.id.colletion -> {\n                    if (isLogin) {\n                        val intent = Intent(this@MainActivity, CollectActivity::class.java)\n                        startActivity(intent)\n                    } else {\n                        val intent = Intent(this@MainActivity, LoginActivity::class.java)\n                        startActivity(intent)\n                    }\n\n                }\n                R.id.about -> {\n\n                }\n                R.id.accout -> {\n                    if (isLogin) {\n                        loginViewModel.logout()\n                        loginViewModel.logoutStatus.observe(this@MainActivity, Observer {\n                            if (it?.errorCode == 0) {\n                                //退出成功 清空cookie\n                                isLogin = false\n                                CookieManger.clearAllCookies()\n                                menuItem.title = \"登陆\"\n                                menuItem.setIcon(R.drawable.ic_login_menu)\n                                ToastUtils.showToast(\"注销成功\")\n                            }\n                        })\n                    } else {\n                        val intent = Intent(this@MainActivity, LoginActivity::class.java)\n                        startActivity(intent)\n                    }\n                }\n                else -> {\n\n                }\n            }\n            drawerLayout.closeDrawer(Gravity.START)\n            true\n        }\n\n\n        mFragments.run {\n            add(ArticleFragment.getInstance())\n            add(TreeFragment.getInstance())\n            add(NavigationFragment.getInstance())\n            add(ProjectFragment.getInstance())\n            add(WelfareFragment.getInstance())\n        }\n\n        mAdapter.setFragments(mFragments)\n        mAdapter.setTitles(mTitles)\n        view_pager.adapter = mAdapter\n        view_pager.offscreenPageLimit = 5\n        tablayout.setViewPager(view_pager)\n\n\n    }\n\n    override fun onCreateOptionsMenu(menu: Menu): Boolean {\n        menuInflater.inflate(R.menu.main, menu)\n        return true\n    }\n\n\n    override fun onOptionsItemSelected(item: MenuItem): Boolean {\n        return when (item.itemId) {\n            R.id.action_search -> {\n\n                true\n            }\n            else -> super.onOptionsItemSelected(item)\n        }\n    }\n\n    override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {\n        if (keyCode == KeyEvent.KEYCODE_BACK) {\n            if (drawerLayout.isDrawerOpen(Gravity.START)) {\n                drawerLayout.closeDrawer(Gravity.START)\n                return true\n            }\n        }\n        return super.onKeyDown(keyCode, event)\n    }\n}\n\nclass MyPagerAdapter(fragmentManager: FragmentManager) : FragmentPagerAdapter(fragmentManager) {\n\n    var fragmentList: MutableList<Fragment> = mutableListOf()\n    var titleList: MutableList<String> = mutableListOf()\n\n    override fun getCount(): Int {\n        return fragmentList.size\n    }\n\n    override fun getItem(p0: Int): Fragment {\n        return fragmentList[p0]\n    }\n\n    override fun getPageTitle(position: Int): CharSequence? {\n        return titleList[position]\n    }\n\n    fun setFragments(fragment: MutableList<Fragment>) {\n        fragmentList = fragment;\n    }\n\n    fun setTitles(mTitles: MutableList<String>) {\n        titleList = mTitles\n    }\n}\n\n"
  },
  {
    "path": "app/src/main/java/com/lxm/wanandroid/repository/model/ArticleResponse.kt",
    "content": "package com.lxm.wanandroid.repository.model\n\n\n\n/**\n * curPage : 1\n * 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}]\n * offset : 0\n * over : false\n * pageCount : 80\n * size : 20\n * total : 1596\n */\ndata class ArticleResponseBody<T>(var curPage: Int = 0,\n                                  var offset: Int = 0,\n                                  var isOver: Boolean = false,\n                                  var pageCount: Int = 0,\n                                  var size: Int = 0,\n                                  var total: Int = 0,\n                                  var datas: List<T>? = null)\n\n\n/**\n * apkLink :\n * author : 红橙Darren\n * chapterId : 245\n * chapterName : 集合相关\n * collect : false\n * courseId : 13\n * desc :\n * envelopePic :\n * fresh : false\n * id : 3326\n * link : https://www.jianshu.com/p/9edd74769f21\n * niceDate : 2018-08-27\n * origin :\n * projectLink :\n * publishTime : 1535372956000\n * superChapterId : 245\n * superChapterName : Java深入\n * tags : []\n * title : 数据结构算法 - 栈和队列\n * type : 0\n * userId : -1\n * visible : 1\n * zan : 0\n */\ndata class ArticleBean(var apkLink: String? = null,\n                       var author: String? = null,\n                       var chapterId: Int = 0,\n                       var chapterName: String? = null,\n                       var collect: Boolean = false,\n                       var courseId: Int = 0,\n                       var desc: String? = null,\n                       var envelopePic: String? = null,\n                       var fresh: Boolean = false,\n                       var id: Int = 0,\n                       var link: String? = null,\n                       var niceDate: String? = null,\n                       var origin: String? = null,\n                       var originId: Int? = null,\n                       var projectLink: String? = null,\n                       var publishTime: Long = 0,\n                       var superChapterId: Int = 0,\n                       var superChapterName: String? = null,\n                       var title: String? = null,\n                       var type: Int = 0,\n                       var userId: Int = 0,\n                       var visible: Int = 0,\n                       var zan: Int = 0,\n                       var tags: List<Project>? = null)\n\n\ndata class Project(var name:String?,var url:String?)\n\n\n\n"
  },
  {
    "path": "app/src/main/java/com/lxm/wanandroid/repository/model/Banner.kt",
    "content": "package com.lxm.wanandroid.repository.model\n\ndata class Banner(\n    val desc: String,\n    val id: Int,\n    val imagePath: String,\n    val isVisible: Int,\n    val order: Int,\n    val title: String,\n    val type: Int,\n    val url: String\n)"
  },
  {
    "path": "app/src/main/java/com/lxm/wanandroid/repository/model/HttpResponse.kt",
    "content": "package com.lxm.wanandroid.repository.model\n/**\n * 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}\n * errorCode : 0\n * errorMsg :\n */\ndata class HttpResponse<T>(\n    var data: T? = null,\n    var errorCode: Int = 0,\n    var errorMsg: String? = null\n)"
  },
  {
    "path": "app/src/main/java/com/lxm/wanandroid/repository/model/Listing.kt",
    "content": "package com.lxm.wanandroid.repository.model\n\nimport android.arch.lifecycle.MutableLiveData\n\ndata class Listing<T>(\n        val pagedList: MutableLiveData<T>,\n        val loadStatus: MutableLiveData<Resource<String>>\n        )\n"
  },
  {
    "path": "app/src/main/java/com/lxm/wanandroid/repository/model/LoginBean.kt",
    "content": "package com.lxm.wanandroid.repository.model\n\ndata class LoginBean(\n    val admin: Boolean,\n    val chapterTops: List<Any>,\n    val collectIds: List<Int>,\n    val email: String,\n    val icon: String,\n    val id: Int,\n    val nickname: String,\n    val password: String,\n    val token: String,\n    val type: Int,\n    val username: String\n)"
  },
  {
    "path": "app/src/main/java/com/lxm/wanandroid/repository/model/Navigation.kt",
    "content": "package com.lxm.wanandroid.repository.model\n\ndata class Navigation(\n    val articles: List<ArticleBean>,\n    val cid: Int,\n    val name: String\n)\n"
  },
  {
    "path": "app/src/main/java/com/lxm/wanandroid/repository/model/Resource.kt",
    "content": "package com.lxm.wanandroid.repository.model\n\n/**\n * Created by juan on 2018/05/23.\n */\ndata class Resource<out T>(val status: Status, val data: T?, val message: String?) {\n    companion object {\n        fun <T> loading(msg: String? = null, data: T? = null): Resource<T> {\n            return Resource(Status.LOADING, data, msg)\n        }\n\n        fun <T> success(data: T? = null): Resource<T> {\n            return Resource(Status.SUCCESS, data, null)\n        }\n\n        fun <T> error(msg: String? = null, data: T? = null): Resource<T> {\n            return Resource(Status.ERROR, data, msg)\n        }\n    }\n}\n\nenum class Status {\n    SUCCESS,\n    ERROR,\n    LOADING\n}"
  },
  {
    "path": "app/src/main/java/com/lxm/wanandroid/repository/model/TreeBean.kt",
    "content": "package com.lxm.wanandroid.repository.model\n\nimport java.io.Serializable\n\ndata class TreeBean(\n    val children: List<TreeBean>,\n    val courseId: Int,\n    val id: Int,\n    val name: String,\n    val order: Int,\n    val parentChapterId: Int,\n    val userControlSetTop: Boolean,\n    val visible: Int\n):Serializable\n\n"
  },
  {
    "path": "app/src/main/java/com/lxm/wanandroid/repository/model/WelfareResponse.kt",
    "content": "package com.lxm.wanandroid.repository.model\n\ndata class WelfareResponse(\n    val error: Boolean,\n    val results: List<Welfare>\n)\n\ndata class Welfare(\n    val _id: String,\n    val createdAt: String,\n    val desc: String,\n    val publishedAt: String,\n    val source: String,\n    val type: String,\n    val url: String,\n    val used: Boolean,\n    val who: String\n)"
  },
  {
    "path": "app/src/main/java/com/lxm/wanandroid/repository/remote/LoginResposity.kt",
    "content": "package com.lxm.wanandroid.repository.remote\n\nimport android.arch.lifecycle.MutableLiveData\nimport com.lxm.module_library.helper.RxHelper\nimport com.lxm.wanandroid.repository.model.HttpResponse\nimport com.lxm.wanandroid.repository.model.LoginBean\nimport com.lxm.wanandroid.repository.remote.httpClient.RetrofitClient\nimport io.reactivex.functions.Consumer\n\nclass LoginRepository {\n\n    val login = MutableLiveData<HttpResponse<LoginBean>>()\n    val register = MutableLiveData<HttpResponse<LoginBean>>()\n    val logout = MutableLiveData<HttpResponse<Any>>()\n\n    fun login(account: String, password: String) {\n\n        RetrofitClient.getInstance(RetrofitClient.WAN_BASE_URL).login(account, password)\n            .compose(RxHelper.rxSchedulerHelper())\n            .subscribe(Consumer {\n                login.value = it\n            }, Consumer {\n                login.value = HttpResponse(null, 500, it.message!!)\n            })\n\n    }\n\n    fun register(account: String, password: String, rPassword: String) {\n\n        RetrofitClient.getInstance(RetrofitClient.WAN_BASE_URL).register(account, password, rPassword)\n            .compose(RxHelper.rxSchedulerHelper())\n            .subscribe(Consumer {\n                register.value = it\n            }, Consumer {\n                register.value = HttpResponse(null, 500, it.message!!)\n            })\n\n    }\n\n    fun logout() {\n        RetrofitClient.getInstance(RetrofitClient.WAN_BASE_URL).logout()\n            .compose(RxHelper.rxSchedulerHelper())\n            .subscribe(Consumer {\n                logout.value = it\n            }, Consumer {\n                logout.value = HttpResponse(null, 500, it.message!!)\n            })\n\n    }\n\n\n\n}"
  },
  {
    "path": "app/src/main/java/com/lxm/wanandroid/repository/remote/httpClient/API.kt",
    "content": "package com.lxm.wanandroid.repository.remote.httpClient\n\nimport com.lxm.wanandroid.repository.model.*\nimport io.reactivex.Observable\nimport retrofit2.http.*\n\n\ninterface API{\n\n\n   /*\n    *\n    * 获取首页新闻列表\n    *\n    * */\n\n    @GET(\"/article/list/{page}/json\")\n    fun getArticleList(@Path(value = \"page\")page:Int):Observable<HttpResponse<ArticleResponseBody<ArticleBean>>>\n    /*\n    *\n    * 获取首页Banner\n    *\n    * */\n\n    @GET(\"/banner/json\")\n    fun getHomeBanner():Observable<HttpResponse<List<Banner>>>\n    /*\n      *\n      * 获取知识体系\n      *\n      * */\n\n    @GET(\"/tree/json\")\n    fun getTrees():Observable<HttpResponse<List<TreeBean>>>\n\n    /*\n     *\n     * 获取知识体系目录\n     * /article/list/0/json?cid=60\n     * */\n\n    @GET(\"/article/list/{page}/json\")\n    fun getCategory(@Path(value = \"page\")page:Int,@Query(value = \"cid\")cid:Int):Observable<HttpResponse<ArticleResponseBody<ArticleBean>>>\n    /*\n     *\n     * 获取知识体系目录\n     * /navi/json\n     * */\n\n    @GET(\"/navi/json\")\n    fun getNavigation():Observable<HttpResponse<List<Navigation>>>\n\n    /*\n     *\n     * 获取Gan福利\n     * /navi/json\n     * */\n    @GET(\"/api/data/{type}/{page_size}/{page}\")\n    fun getWelfare(@Path(\"type\") id: String,  @Path(\"page_size\") page_size: Int,@Path(\"page\") page: Int): Observable<WelfareResponse>\n\n    /*\n     *\n    * 获取项目列表\n    *\n    * */\n\n    @GET(\"/article/listproject/{page}/json\")\n    fun getProjectList(@Path(value = \"page\")page:Int):Observable<HttpResponse<ArticleResponseBody<ArticleBean>>>\n\n    /**\n     * 登录\n     */\n    @FormUrlEncoded\n    @POST(\"/user/login\")\n    fun login(@Field(value = \"username\")username: String, @Field(value = \"password\")password: String): Observable<HttpResponse<LoginBean>>\n\n    /**\n     * 注销\n     * https://www.wanandroid.com/user/logout/json\n     */\n    @GET(\"/user/logout/json\")\n    fun logout():Observable<HttpResponse<Any>>\n\n    /**\n     * 注册\n     */\n    @FormUrlEncoded\n    @POST(\"/user/register\")\n    fun register(@Field(value = \"username\")account: String, @Field(value = \"password\")password: String, @Field(value = \"repassword\")rPassword: String): Observable<HttpResponse<LoginBean>>\n\n    /**\n     * 我的收藏列表\n     * lg/collect/list/0/json\n     */\n    @GET(\"/lg/collect/list/{page}/json\")\n    fun getCollectList(@Path(value = \"page\")page:Int):Observable<HttpResponse<ArticleResponseBody<ArticleBean>>>\n\n    /**\n     * 收藏\n     * https://www.wanandroid.com/lg/collect/1165/json\n     */\n    @POST(\"/lg/collect/{id}/json\")\n    fun collect(@Path(value = \"id\")id:Int):Observable<HttpResponse<Any>>\n\n    /**\n     * 取消收藏\n     * https://www.wanandroid.com/lg/uncollect_originId/2333/json\n     */\n    @POST(\"/lg/uncollect_originId/{id}/json\")\n    fun unCollect(@Path(value = \"id\")id:Int):Observable<HttpResponse<Any>>\n\n\n}"
  },
  {
    "path": "app/src/main/java/com/lxm/wanandroid/repository/remote/httpClient/RetrofitClient.kt",
    "content": "package com.lxm.wanandroid.repository.remote.httpClient\n\nimport com.lxm.module_library.helper.RetrofitCreateHelper\n\n\nobject RetrofitClient {\n    const val WAN_BASE_URL = \"https://www.wanandroid.com\"\n    const val GAN_BASE_URL = \"https://gank.io\"\n\n    private var api: API? = null\n    fun getInstance(type: String): API {\n        api = RetrofitCreateHelper.createApi(API::class.java, type)\n        return api!!\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/lxm/wanandroid/ui/ArticleFragment.kt",
    "content": "package com.lxm.wanandroid.ui\n\nimport android.arch.lifecycle.Observer\nimport android.content.Context\nimport android.os.Bundle\nimport android.view.LayoutInflater\nimport android.view.View\nimport android.widget.ImageView\nimport com.lxm.module_library.base.BaseFragment\nimport com.lxm.module_library.utils.RefreshHelper\nimport com.lxm.module_library.xrecycleview.XRecyclerView\nimport com.lxm.wanandroid.R\nimport com.lxm.wanandroid.repository.model.ArticleBean\nimport com.lxm.wanandroid.repository.model.Banner\nimport com.lxm.wanandroid.repository.model.Status\nimport com.lxm.wanandroid.ui.adapter.ArticleAdapter\nimport com.lxm.wanandroid.ui.base.OnItemClickListener\nimport com.lxm.wanandroid.utils.GlideUtil\nimport com.lxm.wanandroid.utils.webview.WebViewActivity\nimport com.lxm.wanandroid.viewmodel.ArticleViewModel\nimport com.zhouwei.mzbanner.holder.MZViewHolder\nimport kotlinx.android.synthetic.main.article_banner.*\nimport kotlinx.android.synthetic.main.article_fragment.*\n\nclass ArticleFragment : BaseFragment<ArticleViewModel>() {\n\n    private lateinit var headerView: View\n    private var bannerList : List<Banner>? = null\n    private val mAdapter: ArticleAdapter by lazy {\n        ArticleAdapter()\n    }\n\n    override fun getLayoutID(): Int {\n        return R.layout.article_fragment\n    }\n\n    companion object {\n        fun getInstance(): ArticleFragment {\n            return ArticleFragment()\n        }\n    }\n\n    override fun onActivityCreated(savedInstanceState: Bundle?) {\n        super.onActivityCreated(savedInstanceState)\n        showContentView()\n        initView()\n    }\n\n    private fun initView() {\n        swipeLayout.setOnRefreshListener {\n            viewModel.mPage = 0\n            loadData()\n        }\n        swipeLayout.isRefreshing = true\n        RefreshHelper.init(recyclerView, false)\n        headerView = layoutInflater.inflate(R.layout.article_banner, null)\n        recyclerView.addHeaderView(headerView)\n        recyclerView.adapter = mAdapter\n        recyclerView.setLoadingListener(object : XRecyclerView.LoadingListener {\n\n            override fun onLoadMore() {\n                viewModel.mPage = viewModel.mPage + 1;\n                getHomeList()\n            }\n\n            override fun onRefresh() {\n            }\n        })\n        viewModel.loadStatus.observe(this, Observer {\n\n            when (it?.status) {\n                Status.ERROR -> showError()\n                Status.SUCCESS -> showContentView()\n            }\n        })\n        viewModel.pagedList.observe(this, Observer {\n            swipeLayout.isRefreshing = false\n            if (it == null) {\n                return@Observer\n            }\n            if(viewModel.mPage ==0){\n                mAdapter.setData(it.data?.datas!!)\n                return@Observer\n            }\n            mAdapter.addDataAll(it.data?.datas!!)\n            if(it?.data?.datas?.size!! < it?.data?.size!!){\n                recyclerView.noMoreLoading()\n            }else{\n                recyclerView.refreshComplete()\n            }\n        })\n\n        mAdapter.setOnItemClickListener(object : OnItemClickListener<ArticleBean> {\n            override fun onClick(t: ArticleBean, position: Int) {\n                WebViewActivity.loadUrl(activity, t.link, t.title)\n            }\n        })\n    }\n\n    private fun getBanners() {\n        viewModel.getBanners().observe(this@ArticleFragment, Observer {\n            bannerList = it?.data\n            banner.setBannerPageClickListener { view, i ->\n                WebViewActivity.loadUrl(activity, it?.data?.get(i)?.url,null)\n            }\n            banner.setPages(\n                it?.data as List<Nothing>?\n            ) {\n                BannerViewHolder()\n            }\n            banner.start()\n\n        })\n    }\n\n    class BannerViewHolder : MZViewHolder<Banner> {\n        private var mImageView: ImageView? = null\n\n        override fun createView(context: Context): View {\n            val view = LayoutInflater.from(context).inflate(R.layout.item_banner, null)\n            mImageView = view.findViewById(R.id.banner_image) as ImageView\n            return view\n        }\n\n        override fun onBind(context: Context, position: Int, data: Banner?) {\n            data?.let {\n                GlideUtil.displayCircleCorner(mImageView!!, it.imagePath)\n            }\n        }\n    }\n\n\n    override fun onRetry() {\n        loadData()\n    }\n\n    override fun loadData() {\n        getHomeList()\n        getBanners()\n    }\n\n    private fun getHomeList() {\n        this.viewModel.getHomeList()\n    }\n\n}"
  },
  {
    "path": "app/src/main/java/com/lxm/wanandroid/ui/CollectActivity.kt",
    "content": "package com.lxm.wanandroid.ui\n\nimport android.arch.lifecycle.Observer\nimport android.os.Bundle\nimport com.lxm.module_library.base.BaseActivity\nimport com.lxm.module_library.utils.RefreshHelper\nimport com.lxm.module_library.xrecycleview.XRecyclerView\nimport com.lxm.wanandroid.R\nimport com.lxm.wanandroid.repository.model.ArticleBean\nimport com.lxm.wanandroid.repository.model.Status\nimport com.lxm.wanandroid.ui.adapter.ArticleAdapter\nimport com.lxm.wanandroid.ui.base.OnItemClickListener\nimport com.lxm.wanandroid.utils.webview.WebViewActivity\nimport com.lxm.wanandroid.viewmodel.CollectViewModel\nimport kotlinx.android.synthetic.main.article_fragment.*\n\n\nclass CollectActivity : BaseActivity<CollectViewModel>() {\n\n    private val mAdapter: ArticleAdapter by lazy {\n        ArticleAdapter()\n    }\n\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n        setContentView(R.layout.article_fragment)\n        setTitle(\"我的收藏\")\n        initView()\n        getCollection()\n    }\n\n\n    private fun initView() {\n        swipeLayout.setOnRefreshListener {\n            swipeLayout.isRefreshing = true\n            viewModel.mPage = 0\n            getCollection()\n        }\n        RefreshHelper.init(recyclerView, false)\n        mAdapter.isCollectionList = true\n        recyclerView.adapter = mAdapter\n        recyclerView.setLoadingListener(object : XRecyclerView.LoadingListener {\n\n            override fun onLoadMore() {\n                viewModel.mPage = viewModel.mPage + 1;\n                getCollection()\n            }\n\n            override fun onRefresh() {\n            }\n        })\n        showLoading()\n        viewModel.loadStatus.observe(this, Observer {\n\n            when (it?.status) {\n//                Status.ERROR -> showError()\n                Status.SUCCESS -> showContentView()\n            }\n        })\n        this.viewModel.collectionList.observe(this, Observer {\n            swipeLayout.isRefreshing = false\n            if (it == null) {\n                return@Observer\n            }\n            if(viewModel.mPage ==0){\n                mAdapter.setData(it.data?.datas!!)\n                return@Observer\n            }\n            mAdapter.addDataAll(it.data?.datas!!)\n            if(it?.data?.datas?.size!! < it?.data?.size!!){\n                recyclerView.noMoreLoading()\n            }else{\n                recyclerView.refreshComplete()\n            }\n        })\n\n        mAdapter.setOnItemClickListener(object : OnItemClickListener<ArticleBean> {\n            override fun onClick(t: ArticleBean, position: Int) {\n                WebViewActivity.loadUrl(this@CollectActivity, t.link, t.title)\n            }\n        })\n    }\n\n    private fun getCollection() {\n        viewModel.getCollect()\n    }\n}\n\n"
  },
  {
    "path": "app/src/main/java/com/lxm/wanandroid/ui/LoginActivity.kt",
    "content": "package com.lxm.wanandroid.ui\n\nimport android.arch.lifecycle.Observer\nimport android.arch.lifecycle.ViewModel\nimport android.arch.lifecycle.ViewModelProvider\nimport android.arch.lifecycle.ViewModelProviders\nimport android.os.Bundle\nimport android.support.v7.app.AppCompatActivity\nimport android.text.TextUtils\nimport android.view.View\nimport android.widget.Toast\nimport com.jeremyliao.liveeventbus.LiveEventBus\nimport com.lxm.module_library.materialLogin.DefaultLoginView\nimport com.lxm.module_library.materialLogin.DefaultRegisterView\nimport com.lxm.module_library.materialLogin.MaterialLoginView\nimport com.lxm.module_library.statusbar.StatusBarUtil\nimport com.lxm.module_library.utils.PreferencesUtil\nimport com.lxm.module_library.utils.ToastUtils\nimport com.lxm.wanandroid.R\nimport com.lxm.wanandroid.repository.remote.LoginRepository\nimport com.lxm.wanandroid.viewmodel.LoginViewModel\nimport kotlinx.android.synthetic.main.main_content.*\n\n\n\nclass LoginActivity : AppCompatActivity() {\n\n    companion object{\n         const val LOGIN_SUCCESS = \"loginSuccess\"\n    }\n\n    private lateinit var model: LoginViewModel\n    private lateinit var login: MaterialLoginView\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n        setContentView(R.layout.activity_login)\n        initToolbar()\n        initView()\n        initData()\n    }\n\n    private fun initData() {\n        model = ViewModelProviders.of(this@LoginActivity, object : ViewModelProvider.Factory {\n            override fun <T : ViewModel?> create(modelClass: Class<T>): T {\n                return LoginViewModel(LoginRepository()) as T\n            }\n\n        })[LoginViewModel::class.java]\n\n        model.apply {\n            loginStatus.observe(this@LoginActivity, Observer {\n                if (it?.errorCode == 0) {\n                    //存储账号和cookie等信息\n                    ToastUtils.showToast(\"登录成功\", Toast.LENGTH_LONG)\n                    var isLogin: Boolean by PreferencesUtil<Boolean>(\"login\", false)\n                    var userName: String by PreferencesUtil<String>(\"userName\", \"Android\")\n                    var nikeName: String by PreferencesUtil<String>(\"nikeName\", \"易水寒\")\n                    isLogin = true\n                    userName = it.data?.username!!\n                    nikeName = it.data?.nickname!!\n\n                    LiveEventBus.get()\n                        .with(LOGIN_SUCCESS)\n                        .post(\"登录成功\")\n                    finish()\n                } else {\n                    ToastUtils.showToast(it?.errorMsg!!, Toast.LENGTH_LONG)\n                }\n            })\n            registerStauts.observe(this@LoginActivity, Observer {\n                if (it?.errorCode == 0) {\n                    login.animateLogin()\n                    ToastUtils.showToast(\"注册成功，请登录\", Toast.LENGTH_LONG)\n                } else {\n                    ToastUtils.showToast(it?.errorMsg!!, Toast.LENGTH_LONG)\n                }\n            })\n        }\n    }\n\n    private fun initView() {\n        login = findViewById<View>(R.id.login) as MaterialLoginView\n        (login.loginView as DefaultLoginView).setListener { loginUser, loginPass ->\n            if (!TextUtils.isEmpty(loginUser.editText?.text) && !TextUtils.isEmpty(loginPass.editText?.text)) {\n                model.login(loginUser.editText?.text.toString(), loginPass.editText?.text.toString())\n            } else {\n                ToastUtils.showToast(\"用户名和密码不能为空\", Toast.LENGTH_SHORT)\n            }\n        }\n\n        (login.registerView as DefaultRegisterView).setListener { registerUser, registerPass, registerPassRep ->\n            if (!TextUtils.isEmpty(registerUser.editText?.text) && !TextUtils.isEmpty(registerPass.editText?.text) &&\n                !TextUtils.isEmpty( registerPassRep.editText?.text)) {\n                    model.register(\n                        registerUser.editText?.text.toString(),\n                        registerPass.editText?.text.toString(),\n                        registerPassRep.editText?.text.toString()\n                    )\n                } else {\n                ToastUtils.showToast(\"用户名和密码不能为空\", Toast.LENGTH_SHORT)\n            }\n        }\n    }\n\n    private fun initToolbar() {\n        StatusBarUtil.setColor(this, resources.getColor(R.color.colorTheme), 0)\n        toolbar.setNavigationOnClickListener {\n            finish()\n        }\n    }\n}\n\n"
  },
  {
    "path": "app/src/main/java/com/lxm/wanandroid/ui/NavigationFragment.kt",
    "content": "package com.lxm.wanandroid.ui\n\nimport android.arch.lifecycle.Observer\nimport android.os.Bundle\nimport android.support.v7.widget.LinearLayoutManager\nimport android.view.View\nimport com.lxm.module_library.base.BaseFragment\nimport com.lxm.module_library.xrecycleview.XRecyclerView\nimport com.lxm.wanandroid.R\nimport com.lxm.wanandroid.repository.model.ArticleBean\nimport com.lxm.wanandroid.repository.model.Status\nimport com.lxm.wanandroid.ui.adapter.NaviAdapter\nimport com.lxm.wanandroid.utils.webview.WebViewActivity\nimport com.lxm.wanandroid.viewmodel.NaviViewModelView\nimport com.zhy.view.flowlayout.FlowLayout\nimport kotlinx.android.synthetic.main.article_fragment.*\n\nclass NavigationFragment : BaseFragment<NaviViewModelView>() {\n\n    private val mAdapter: NaviAdapter by lazy {\n        NaviAdapter(itemClickListener)\n    }\n    private val itemClickListener: NaviAdapter.OnItemNavigationClickListener = object :\n        NaviAdapter.OnItemNavigationClickListener {\n\n        override fun itemClick(view: View, position: Int, parent: FlowLayout, articles: List<ArticleBean>) {\n            var article = articles[position]\n            WebViewActivity.loadUrl(activity, article.link, article.title)\n        }\n    }\n    override fun getLayoutID(): Int {\n        return R.layout.tree_fragment\n    }\n\n    companion object {\n        fun getInstance(): NavigationFragment {\n            return NavigationFragment()\n        }\n    }\n\n    override fun onActivityCreated(savedInstanceState: Bundle?) {\n        super.onActivityCreated(savedInstanceState)\n        showContentView()\n        initView()\n    }\n\n    private fun initView() {\n        swipeLayout.setOnRefreshListener {\n            loadData()\n        }\n        swipeLayout.isRefreshing = true\n        val layoutManager = LinearLayoutManager(activity)\n        recyclerView.layoutManager = layoutManager\n        recyclerView.setPullRefreshEnabled(false)\n        recyclerView.setLoadingMoreEnabled(false)\n        recyclerView.clearHeader()\n        recyclerView.adapter = mAdapter\n        recyclerView.setLoadingListener(object : XRecyclerView.LoadingListener {\n            override fun onLoadMore() {\n                getTreeList()\n            }\n\n            override fun onRefresh() {\n            }\n        })\n        viewModel.loadStatus.observe(this, Observer {\n\n            when (it?.status) {\n                Status.ERROR -> showError()\n            }\n        })\n    }\n\n    override fun onRetry() {\n        loadData()\n    }\n\n    override fun loadData() {\n        getTreeList()\n    }\n\n    private fun getTreeList() {\n        this.viewModel.getVavigations().observe(this@NavigationFragment, Observer {\n            swipeLayout.isRefreshing = false\n            recyclerView.refreshComplete()\n            it?.let { list -> mAdapter.setData(it) }\n            mAdapter.notifyDataSetChanged()\n        })\n    }\n\n}"
  },
  {
    "path": "app/src/main/java/com/lxm/wanandroid/ui/ProjectFragment.kt",
    "content": "package com.lxm.wanandroid.ui\n\nimport android.arch.lifecycle.Observer\nimport android.os.Bundle\nimport com.lxm.module_library.base.BaseFragment\nimport com.lxm.module_library.utils.RefreshHelper\nimport com.lxm.module_library.xrecycleview.XRecyclerView\nimport com.lxm.wanandroid.R\nimport com.lxm.wanandroid.repository.model.ArticleBean\nimport com.lxm.wanandroid.repository.model.Banner\nimport com.lxm.wanandroid.repository.model.Status\nimport com.lxm.wanandroid.ui.adapter.ArticleAdapter\nimport com.lxm.wanandroid.ui.base.OnItemClickListener\nimport com.lxm.wanandroid.utils.webview.WebViewActivity\nimport com.lxm.wanandroid.viewmodel.ArticleViewModel\nimport com.lxm.wanandroid.viewmodel.ProjectViewModel\nimport kotlinx.android.synthetic.main.article_fragment.*\n\nclass ProjectFragment : BaseFragment<ProjectViewModel>() {\n\n    private val mAdapter: ArticleAdapter by lazy {\n        ArticleAdapter()\n    }\n\n    override fun getLayoutID(): Int {\n        return R.layout.article_fragment\n    }\n\n    companion object {\n        fun getInstance(): ProjectFragment {\n            return ProjectFragment()\n        }\n    }\n\n    override fun onActivityCreated(savedInstanceState: Bundle?) {\n        super.onActivityCreated(savedInstanceState)\n        showContentView()\n        initView()\n    }\n\n    private fun initView() {\n        swipeLayout.setOnRefreshListener {\n            viewModel.mPage = 0\n            loadData()\n        }\n        swipeLayout.isRefreshing = true\n        RefreshHelper.init(recyclerView, false)\n        recyclerView.adapter = mAdapter\n        recyclerView.setLoadingListener(object : XRecyclerView.LoadingListener {\n\n            override fun onLoadMore() {\n                viewModel.mPage = viewModel.mPage + 1;\n                getProjectList()\n            }\n\n            override fun onRefresh() {\n            }\n        })\n        viewModel.loadStatus.observe(this, Observer {\n\n            when (it?.status) {\n                Status.ERROR -> showError()\n                Status.SUCCESS -> showContentView()\n            }\n        })\n        this.viewModel.pagedList.observe(this, Observer {\n            swipeLayout.isRefreshing = false\n            if (it == null) {\n                return@Observer\n            }\n            if(viewModel.mPage ==0){\n                mAdapter.setData(it.data?.datas!!)\n                return@Observer\n            }\n            mAdapter.addDataAll(it.data?.datas!!)\n            if(it?.data?.datas?.size!! < it?.data?.size!!){\n                recyclerView.noMoreLoading()\n            }else{\n                recyclerView.refreshComplete()\n            }\n        })\n\n        mAdapter.setOnItemClickListener(object : OnItemClickListener<ArticleBean> {\n            override fun onClick(t: ArticleBean, position: Int) {\n                WebViewActivity.loadUrl(activity, t.link, t.title)\n            }\n        })\n    }\n\n    override fun onRetry() {\n        loadData()\n    }\n\n    override fun loadData() {\n        getProjectList()\n    }\n\n    private fun getProjectList() {\n        this.viewModel.getProjects()\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/lxm/wanandroid/ui/TagArticleActivity.kt",
    "content": "package com.lxm.wanandroid.ui\n\nimport android.arch.lifecycle.Observer\nimport android.os.Bundle\nimport com.lxm.module_library.base.BaseActivity\nimport com.lxm.module_library.utils.RefreshHelper\nimport com.lxm.module_library.xrecycleview.XRecyclerView\nimport com.lxm.wanandroid.R\nimport com.lxm.wanandroid.repository.model.ArticleBean\nimport com.lxm.wanandroid.repository.model.Status\nimport com.lxm.wanandroid.repository.model.TreeBean\nimport com.lxm.wanandroid.ui.adapter.ArticleAdapter\nimport com.lxm.wanandroid.ui.base.OnItemClickListener\nimport com.lxm.wanandroid.utils.webview.WebViewActivity\nimport com.lxm.wanandroid.viewmodel.CategoryViewModel\nimport kotlinx.android.synthetic.main.article_fragment.*\n\nclass TagArticleActivity: BaseActivity<CategoryViewModel>() {\n    lateinit var treeBean: TreeBean\n    private val mAdapter: ArticleAdapter by lazy {\n        ArticleAdapter()\n    }\n\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n        setContentView(R.layout.category_activity)\n        initView()\n        treeBean = intent.getSerializableExtra(\"TagBean\") as TreeBean\n        setTitle(treeBean.name)\n        getCategory(treeBean.id)\n    }\n\n\n    private fun initView() {\n        swipeLayout.setOnRefreshListener {\n            swipeLayout.isRefreshing = true\n            viewModel.mPage = 0\n            getCategory(treeBean.id)\n        }\n        RefreshHelper.init(recyclerView, false)\n        recyclerView.adapter = mAdapter\n        recyclerView.setLoadingListener(object : XRecyclerView.LoadingListener {\n\n            override fun onLoadMore() {\n                viewModel.mPage = viewModel.mPage + 1;\n                getCategory(treeBean.id)\n            }\n\n            override fun onRefresh() {\n            }\n        })\n        showLoading()\n        viewModel.loadStatus.observe(this, Observer {\n\n            when (it?.status) {\n//                Status.ERROR -> showError()\n                Status.SUCCESS -> showContentView()\n            }\n        })\n        this.viewModel.pagedList.observe(this, Observer {\n            swipeLayout.isRefreshing = false\n            if (it == null) {\n                return@Observer\n            }\n            if(viewModel.mPage ==0){\n                mAdapter.setData(it.data?.datas!!)\n                return@Observer\n            }\n            mAdapter.addDataAll(it.data?.datas!!)\n            if(it?.data?.datas?.size!! < it?.data?.size!!){\n                recyclerView.noMoreLoading()\n            }else{\n                recyclerView.refreshComplete()\n            }\n        })\n\n        mAdapter.setOnItemClickListener(object : OnItemClickListener<ArticleBean> {\n            override fun onClick(t: ArticleBean, position: Int) {\n                WebViewActivity.loadUrl(this@TagArticleActivity, t.link, t.title)\n            }\n        })\n    }\n\n    private fun getCategory(id: Int) {\n        viewModel.getCategory(id)\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/lxm/wanandroid/ui/TreeFragment.kt",
    "content": "package com.lxm.wanandroid.ui\n\nimport android.arch.lifecycle.Observer\nimport android.content.Intent\nimport android.os.Bundle\nimport android.support.v7.widget.LinearLayoutManager\nimport android.view.View\nimport com.lxm.module_library.base.BaseFragment\nimport com.lxm.module_library.xrecycleview.XRecyclerView\nimport com.lxm.wanandroid.R\nimport com.lxm.wanandroid.repository.model.Status\nimport com.lxm.wanandroid.repository.model.TreeBean\nimport com.lxm.wanandroid.ui.adapter.TreeAdapter\nimport com.lxm.wanandroid.viewmodel.TreeViewModel\nimport com.zhy.view.flowlayout.FlowLayout\nimport kotlinx.android.synthetic.main.article_fragment.*\n\nclass TreeFragment : BaseFragment<TreeViewModel>() {\n\n    private val mAdapter: TreeAdapter by lazy {\n        TreeAdapter(itemClickListener)\n    }\n    private val itemClickListener: TreeAdapter.OnItemNavigationClickListener = object :\n        TreeAdapter.OnItemNavigationClickListener {\n\n        override fun itemClick(view: View, position: Int, parent: FlowLayout, children: List<TreeBean>) {\n            val intent = Intent(parent.context, TagArticleActivity::class.java)\n            intent.putExtra(\"TagBean\", children[position])\n            parent.context.startActivity(intent)\n        }\n    }\n    override fun getLayoutID(): Int {\n        return R.layout.tree_fragment\n    }\n\n    companion object {\n        fun getInstance(): TreeFragment {\n            return TreeFragment()\n        }\n    }\n\n    override fun onActivityCreated(savedInstanceState: Bundle?) {\n        super.onActivityCreated(savedInstanceState)\n        showContentView()\n        initView()\n    }\n\n    private fun initView() {\n        swipeLayout.setOnRefreshListener {\n            loadData()\n        }\n        swipeLayout.isRefreshing = true\n        val layoutManager = LinearLayoutManager(activity)\n        recyclerView.layoutManager = layoutManager\n        recyclerView.setPullRefreshEnabled(false)\n        recyclerView.setLoadingMoreEnabled(false)\n        recyclerView.clearHeader()\n        recyclerView.adapter = mAdapter\n        recyclerView.setLoadingListener(object : XRecyclerView.LoadingListener {\n            override fun onLoadMore() {\n                getTreeList()\n            }\n\n            override fun onRefresh() {\n            }\n        })\n        viewModel.loadStatus.observe(this, Observer {\n\n            when (it?.status) {\n                Status.ERROR -> showError()\n            }\n        })\n    }\n\n    override fun onRetry() {\n        loadData()\n    }\n\n    override fun loadData() {\n        getTreeList()\n    }\n\n    private fun getTreeList() {\n        this.viewModel.getTrees().observe(this@TreeFragment, Observer {\n            swipeLayout.isRefreshing = false\n            recyclerView.refreshComplete()\n            it?.let { list -> mAdapter.setData(list) }\n            mAdapter.notifyDataSetChanged()\n        })\n    }\n\n}"
  },
  {
    "path": "app/src/main/java/com/lxm/wanandroid/ui/ViewBigImageActivity.kt",
    "content": "package com.lxm.wanandroid.ui\n\nimport android.content.Context\nimport android.content.Intent\nimport android.graphics.drawable.Drawable\nimport android.os.Bundle\nimport android.support.v4.app.FragmentActivity\nimport android.support.v4.view.PagerAdapter\nimport android.support.v4.view.ViewPager.OnPageChangeListener\nimport android.view.LayoutInflater\nimport android.view.View\nimport android.view.ViewGroup\nimport android.widget.ImageView\nimport android.widget.ProgressBar\nimport com.bumptech.glide.Glide\nimport com.bumptech.glide.load.DataSource\nimport com.bumptech.glide.load.engine.GlideException\nimport com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions\nimport com.bumptech.glide.request.RequestListener\nimport com.bumptech.glide.request.target.Target\nimport com.lxm.wanandroid.R\nimport kotlinx.android.synthetic.main.activity_show_image.*\nimport uk.co.senab.photoview.PhotoView\nimport uk.co.senab.photoview.PhotoViewAttacher\n\nimport java.util.ArrayList\n\n\nclass ViewBigImageActivity : FragmentActivity(), OnPageChangeListener, PhotoViewAttacher.OnPhotoTapListener {\n\n    override fun onPhotoTap(p0: View?, p1: Float, p2: Float) {\n        finish()\n    }\n\n    /**\n     * 图片集合\n     */\n    private var imageList: MutableList<String>? = null\n    /**\n     * 接收穿过来当前选择的图片的position\n     */\n    internal var position: Int = 0\n    /**\n     * 当前页数\n     */\n    private var page: Int = 0\n\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n        setContentView(R.layout.activity_show_image)\n        getIntentData()\n    }\n\n    private fun getIntentData() {\n        val bundle = intent.extras\n        if (bundle != null) {\n            position = bundle.getInt(\"code\")\n            imageList = bundle.getStringArrayList(\"imageList\")\n        }\n\n        val adapter = ViewPagerAdapter()\n        viewpager?.adapter = adapter\n        viewpager?.currentItem = position\n        page = position\n        viewpager?.addOnPageChangeListener(this)\n        viewpager?.isEnabled = false\n\n        viewpager_text?.text = (position + 1).toString() + \" / \" + imageList!!.size\n    }\n\n    /**\n     * ViewPager的适配器\n     */\n    private inner class ViewPagerAdapter internal constructor() : PagerAdapter() {\n\n        private val inflater: LayoutInflater = layoutInflater\n\n        override fun instantiateItem(container: ViewGroup, position: Int): Any {\n            val view = inflater.inflate(R.layout.item_image_view_pager, container, false)\n            val zoomImageView = view.findViewById<PhotoView>(R.id.zoom_image_view)\n            val progressBar = view.findViewById<ProgressBar>(R.id.loading)\n            // 保存网络图片的路径\n            val adapterImageEntity = getItem(position) as String\n            val imageUrl: String\n            imageUrl = adapterImageEntity\n            progressBar.visibility = View.VISIBLE\n            progressBar.isClickable = false\n\n            Glide.with(this@ViewBigImageActivity).load(imageUrl)\n                .transition(DrawableTransitionOptions.withCrossFade(700))\n                .listener(object : RequestListener<Drawable> {\n                    override fun onLoadFailed(\n                        e: GlideException?,\n                        model: Any,\n                        target: Target<Drawable>,\n                        isFirstResource: Boolean\n                    ): Boolean {\n                        return false\n                    }\n\n                    override fun onResourceReady(\n                        resource: Drawable,\n                        model: Any,\n                        target: Target<Drawable>,\n                        dataSource: DataSource,\n                        isFirstResource: Boolean\n                    ): Boolean {\n                        progressBar.visibility = View.GONE\n                        /**这里应该是加载成功后图片的高,最大为屏幕的高 */\n                        val height = resource.intrinsicHeight\n                        val wHeight = windowManager.defaultDisplay.height\n                        if (height < wHeight) {\n                            zoomImageView.scaleType = ImageView.ScaleType.FIT_CENTER\n                        } else {\n                            zoomImageView.scaleType = ImageView.ScaleType.CENTER_CROP\n                        }\n                        return false\n                    }\n                }).into(zoomImageView)\n\n            zoomImageView.setOnPhotoTapListener(this@ViewBigImageActivity)\n            container.addView(view, 0)\n            return view\n        }\n\n        override fun getCount(): Int {\n            return if (imageList == null || imageList?.size == 0) {\n                0\n            } else imageList!!.size\n        }\n\n        override fun isViewFromObject(arg0: View, arg1: Any): Boolean {\n            return arg0 === arg1\n        }\n\n        override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) {\n            val view = `object` as View\n            container.removeView(view)\n        }\n\n        private fun getItem(position: Int): Any {\n            return imageList!![position]\n        }\n    }\n\n    /**\n     * 下面是对Viewpager的监听\n     */\n    override fun onPageScrollStateChanged(arg0: Int) {}\n\n    override fun onPageScrolled(arg0: Int, arg1: Float, arg2: Int) {}\n\n    /**\n     * 本方法主要监听viewpager滑动的时候的操作\n     * 每当页数发生改变时重新设定一遍当前的页数和总页数\n     */\n    override fun onPageSelected(arg0: Int) {\n        viewpager_text?.text = (arg0 + 1).toString() + \" / \" + imageList!!.size\n        page = arg0\n    }\n\n    override fun onDestroy() {\n        imageList?.clear()\n        super.onDestroy()\n    }\n\n    companion object {\n\n        /**\n         * @param position    大图的话是第几张图片 从0开始\n         * @param imageList   图片集合\n         */\n        fun startImageList(\n            context: Context,\n            position: Int,\n            imageList: ArrayList<String>\n        ) {\n            val bundle = Bundle()\n            bundle.putInt(\"code\", position)\n            bundle.putStringArrayList(\"imageList\", imageList)\n            val intent = Intent(context, ViewBigImageActivity::class.java)\n            intent.putExtras(bundle)\n            context.startActivity(intent)\n        }\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/lxm/wanandroid/ui/WelfareFragment.kt",
    "content": "package com.lxm.wanandroid.ui\n\nimport android.arch.lifecycle.Observer\nimport android.os.Bundle\nimport android.support.v7.widget.StaggeredGridLayoutManager\nimport android.view.LayoutInflater\nimport android.view.View\nimport android.view.ViewGroup\nimport android.widget.RelativeLayout\nimport com.lxm.module_library.base.BaseFragment\nimport com.lxm.module_library.xrecycleview.XRecyclerView\nimport com.lxm.wanandroid.R\nimport com.lxm.wanandroid.repository.model.Status\nimport com.lxm.wanandroid.repository.model.Welfare\nimport com.lxm.wanandroid.ui.adapter.WelfareAdapter\nimport com.lxm.wanandroid.ui.base.OnItemClickListener\nimport com.lxm.wanandroid.viewmodel.WelfareModelView\nimport kotlinx.android.synthetic.main.article_fragment.*\n\nclass WelfareFragment : BaseFragment<WelfareModelView>() {\n\n    var imageList: ArrayList<String> = ArrayList()\n    override fun getLayoutID() = R.layout.article_fragment\n\n    private val mAdapter: WelfareAdapter by lazy {\n        WelfareAdapter()\n    }\n\n    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {\n        val ll = inflater.inflate(com.lxm.module_library.R.layout.fragment_base, null)\n        contentView = LayoutInflater.from(activity).inflate(R.layout.article_fragment, null, false)\n        val params =\n            RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)\n        contentView.layoutParams = params\n        val mContainer = ll.findViewById<RelativeLayout>(com.lxm.module_library.R.id.container)\n        mContainer.addView(contentView)\n        return ll\n    }\n\n    companion object {\n        fun getInstance(): WelfareFragment {\n            return WelfareFragment()\n        }\n    }\n\n    override fun onActivityCreated(savedInstanceState: Bundle?) {\n        super.onActivityCreated(savedInstanceState)\n        showContentView()\n        initView()\n    }\n\n    private fun initView() {\n        swipeLayout.setOnRefreshListener {\n            viewModel.mPage = 1\n            loadData()\n        }\n        swipeLayout.isRefreshing = true\n        recyclerView.layoutManager = StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL)\n        recyclerView.setPullRefreshEnabled(false)\n        recyclerView.clearHeader()\n        recyclerView.adapter = mAdapter\n        recyclerView.setLoadingListener(object : XRecyclerView.LoadingListener {\n            override fun onLoadMore() {\n                viewModel.mPage = viewModel.mPage+1\n                getWelfare()\n            }\n\n            override fun onRefresh() {\n            }\n        })\n        viewModel.loadStatus.observe(this, Observer {\n\n            when (it?.status) {\n                Status.ERROR -> showError()\n            }\n        })\n\n        mAdapter.setOnItemClickListener(object : OnItemClickListener<Welfare> {\n            override fun onClick(t: Welfare, position: Int) {\n\n                activity?.let { ViewBigImageActivity.startImageList(it, position, imageList) }\n            }\n\n        })\n    }\n\n    override fun onRetry() {\n        loadData()\n    }\n\n    override fun loadData() {\n        getWelfare()\n    }\n\n    private fun getWelfare() {\n        this.viewModel.getWelfare().observe(this@WelfareFragment, Observer {\n            if (viewModel.mPage == 1) {\n                mAdapter.setData(it?.results)\n                imageList.clear()\n                for (item in it?.results!!) {\n                    imageList.add(item.url)\n                }\n            } else {\n                mAdapter.addDataAll(it?.results!!)\n                for (item in it?.results!!) {\n                    imageList.add(item.url)\n                }\n            }\n            swipeLayout.isRefreshing = false\n            recyclerView.refreshComplete()\n            mAdapter.notifyDataSetChanged()\n        })\n    }\n\n}"
  },
  {
    "path": "app/src/main/java/com/lxm/wanandroid/ui/adapter/ArticleAdapter.kt",
    "content": "package com.lxm.wanandroid.ui.adapter\n\n\nimport android.content.Intent\nimport android.graphics.Paint\nimport android.view.View\nimport android.widget.CheckBox\nimport android.widget.ImageView\nimport android.widget.TextView\nimport com.lxm.module_library.utils.PreferencesUtil\nimport com.lxm.module_library.utils.ToastUtils\nimport com.lxm.wanandroid.R\nimport com.lxm.wanandroid.repository.model.ArticleBean\nimport com.lxm.wanandroid.repository.model.HttpResponse\nimport com.lxm.wanandroid.repository.remote.httpClient.RetrofitClient\nimport com.lxm.wanandroid.ui.LoginActivity\nimport com.lxm.wanandroid.ui.base.BaseRecyclerAdapter\nimport com.lxm.wanandroid.ui.base.BaseRecyclerViewHolder\nimport com.lxm.wanandroid.utils.webview.WebViewActivity\nimport com.lxm.wanandroid.viewmodel.CollectViewModel\n\nclass ArticleAdapter : BaseRecyclerAdapter<ArticleBean>() {\n    var isCollectionList: Boolean = false\n    private var collectionViewModel: CollectViewModel = CollectViewModel()\n    override fun getItemLayout(): Int {\n        return R.layout.item_view\n    }\n\n    override fun onBindViewHoder(holder: BaseRecyclerViewHolder, position: Int) {\n        var articleBean: ArticleBean = mutableList?.get(position)\n        with(holder){\n            setValue(R.id.tv_title, articleBean.title)\n            setValue(R.id.tv_time, articleBean.niceDate)\n            setValue(R.id.tv_author, articleBean.author)\n            setValue(R.id.iv_image, articleBean.envelopePic)\n        }\n        var tagTextView = holder.getView(R.id.tv_tag_name) as TextView\n        tagTextView.text = articleBean.chapterName\n        if (articleBean.tags != null && articleBean.tags?.size!! > 0) {\n            tagTextView.paint.flags = Paint.UNDERLINE_TEXT_FLAG; //下划线\n            tagTextView.paint.isAntiAlias = true;//抗锯齿\n            tagTextView.setOnClickListener {\n                WebViewActivity.loadUrl(\n                    tagTextView.context,\n                    RetrofitClient.WAN_BASE_URL + articleBean.tags?.get(0)?.url,\n                    articleBean.chapterName\n                )\n            }\n        }\n        val isNewImageView: ImageView = holder.getView(R.id.iv_new) as ImageView\n        if (articleBean.fresh) {\n            isNewImageView.visibility = View.VISIBLE\n        } else {\n            isNewImageView.visibility = View.GONE\n        }\n        val isCollectImage: CheckBox = holder.getView(R.id.iv_collect) as CheckBox\n        isCollectImage.isChecked = articleBean.collect\n        if(isCollectionList){\n            isCollectImage.isChecked = true\n            articleBean.id = articleBean.originId!!\n        }\n        isCollectImage.setOnClickListener {\n            var isLogin: Boolean by PreferencesUtil<Boolean>(\"login\", false)\n            if(isLogin){\n                if (isCollectImage.isChecked) {\n                    collectionViewModel.collect(articleBean.id, object : CollectionObserver<HttpResponse<Any>> {\n                        override fun onChanged(t: HttpResponse<Any>?) {\n                            if (t?.errorCode == 0) {\n                                ToastUtils.showToast(\"收藏成功\")\n                            } else {\n                                ToastUtils.showToast(\"收藏失败\")\n                            }\n                        }\n                    })\n                } else {\n                    collectionViewModel.unCollect(articleBean.id, object : CollectionObserver<HttpResponse<Any>> {\n                        override fun onChanged(t: HttpResponse<Any>?) {\n                            if (t?.errorCode == 0) {\n                                ToastUtils.showToast(\"取消收藏成功\")\n                            } else {\n                                ToastUtils.showToast(\"取消收藏失败\")\n                            }\n                        }\n                    })\n                }\n            }else{\n                val intent = Intent(context, LoginActivity::class.java)\n                context.startActivity(intent)\n            }\n\n        }\n    }\n\n    interface CollectionObserver<T> {\n        fun onChanged(t: T?)\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/lxm/wanandroid/ui/adapter/NaviAdapter.kt",
    "content": "package com.lxm.wanandroid.ui.adapter\n\nimport android.graphics.Color\nimport android.graphics.drawable.Drawable\nimport android.graphics.drawable.GradientDrawable\nimport android.view.LayoutInflater\nimport android.view.View\nimport android.view.ViewGroup\nimport android.widget.TextView\nimport com.lxm.wanandroid.R\nimport com.lxm.wanandroid.repository.model.ArticleBean\nimport com.lxm.wanandroid.repository.model.Navigation\nimport com.lxm.wanandroid.repository.model.TreeBean\nimport com.lxm.wanandroid.ui.base.BaseRecyclerAdapter\nimport com.lxm.wanandroid.ui.base.BaseRecyclerViewHolder\nimport com.zhy.view.flowlayout.FlowLayout\nimport com.zhy.view.flowlayout.TagAdapter\nimport com.zhy.view.flowlayout.TagFlowLayout\nimport java.util.*\n\n\nclass NaviAdapter(var itemClickListener: OnItemNavigationClickListener) : BaseRecyclerAdapter<Navigation>() {\n    override fun getItemLayout(): Int {\n        return R.layout.item_tree\n    }\n\n    override fun onBindViewHoder(holder: BaseRecyclerViewHolder, position: Int) {\n        val navigation = mutableList[position]\n        val viewHolder: ViewHolder = holder as ViewHolder\n        viewHolder.titleView?.text = navigation.name\n        showTag(navigation, viewHolder.flowLayout)\n\n    }\n\n    private fun showTag(\n        navigation: Navigation,\n        flowLayout: TagFlowLayout?\n    ) {\n        flowLayout?.adapter = object : TagAdapter<ArticleBean>(navigation.articles) {\n            override fun getView(\n                parent: FlowLayout,\n                position: Int,\n                articleBean: ArticleBean\n            ): View {\n                val textView = View.inflate(parent.context, R.layout.item_tree_tag, null) as TextView\n                textView.text = articleBean.title\n//                textView.textColors = Color.rgb(Random().nextInt(255), Random().nextInt(255), Random().nextInt(255))\n                return textView\n            }\n        }\n        flowLayout?.setOnTagClickListener { view, position, parent ->\n            itemClickListener?.itemClick(view, position, parent,navigation.articles)\n            true\n        }\n    }\n\n\n    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseRecyclerViewHolder {\n        val item = LayoutInflater.from(parent.context).inflate(R.layout.item_tree, parent, false)\n        return ViewHolder(item)\n    }\n\n\n    class ViewHolder(itemView: View) : BaseRecyclerViewHolder(itemView) {\n        var titleView: TextView? = null\n        var flowLayout: TagFlowLayout? = null\n\n        init {\n            titleView = itemView.findViewById<TextView>(R.id.tv_tree_title)\n            flowLayout = itemView.findViewById<TagFlowLayout>(R.id.fl_tree)\n        }\n\n        companion object\n    }\n\n    private fun getBackGround(): Drawable {\n        val drawable = GradientDrawable()\n        drawable.cornerRadius = 16f\n        drawable.setColor(Color.rgb(Random().nextInt(255), Random().nextInt(255), Random().nextInt(255)))\n        return drawable\n    }\n\n    interface OnItemNavigationClickListener {\n        /**\n         *单击事件\n         */\n        fun itemClick(view: View, position: Int, parent: FlowLayout, articles: List<ArticleBean>)\n    }\n\n}"
  },
  {
    "path": "app/src/main/java/com/lxm/wanandroid/ui/adapter/TreeAdapter.kt",
    "content": "package com.lxm.wanandroid.ui.adapter\n\nimport android.graphics.Color\nimport android.graphics.drawable.Drawable\nimport android.graphics.drawable.GradientDrawable\nimport android.view.LayoutInflater\nimport android.view.View\nimport android.view.ViewGroup\nimport android.widget.TextView\nimport com.lxm.wanandroid.R\nimport com.lxm.wanandroid.repository.model.TreeBean\nimport com.lxm.wanandroid.ui.base.BaseRecyclerAdapter\nimport com.lxm.wanandroid.ui.base.BaseRecyclerViewHolder\nimport com.zhy.view.flowlayout.FlowLayout\nimport com.zhy.view.flowlayout.TagAdapter\nimport com.zhy.view.flowlayout.TagFlowLayout\nimport java.util.*\n\n\nclass TreeAdapter(var itemClickListener: OnItemNavigationClickListener) : BaseRecyclerAdapter<TreeBean>() {\n    override fun getItemLayout(): Int {\n        return R.layout.item_tree\n    }\n\n    override fun onBindViewHoder(holder: BaseRecyclerViewHolder, position: Int) {\n        val treeBean = mutableList[position]\n        val viewHolder: ViewHolder = holder as ViewHolder\n        viewHolder.titleView?.text = treeBean.name\n        showTag(treeBean, viewHolder.flowLayout)\n\n    }\n\n    private fun showTag(\n        treeBean: TreeBean,\n        flowLayout: TagFlowLayout?\n    ) {\n        flowLayout?.adapter = object : TagAdapter<TreeBean>(treeBean.children) {\n            override fun getView(\n                parent: FlowLayout,\n                position: Int,\n                o: TreeBean\n            ): View {\n                val textView = View.inflate(parent.context, R.layout.item_tree_tag, null) as TextView\n                textView.text = o.name\n                textView.setBackgroundDrawable(getBackGround())\n                return textView\n            }\n        }\n        flowLayout?.setOnTagClickListener { view, position, parent ->\n            itemClickListener?.itemClick(view, position, parent,treeBean.children)\n            true\n        }\n    }\n\n\n    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseRecyclerViewHolder {\n        val item = LayoutInflater.from(parent.context).inflate(R.layout.item_tree, parent, false)\n        return ViewHolder(item)\n    }\n\n\n    class ViewHolder(itemView: View) : BaseRecyclerViewHolder(itemView) {\n        var titleView: TextView? = null\n        var flowLayout: TagFlowLayout? = null\n\n        init {\n            titleView = itemView.findViewById<TextView>(R.id.tv_tree_title)\n            flowLayout = itemView.findViewById<TagFlowLayout>(R.id.fl_tree)\n        }\n\n        companion object\n    }\n\n    private fun getBackGround(): Drawable {\n        val drawable = GradientDrawable()\n        drawable.cornerRadius = 16f\n        drawable.setColor(Color.rgb(Random().nextInt(255), Random().nextInt(255), Random().nextInt(255)))\n        return drawable\n    }\n\n    interface OnItemNavigationClickListener {\n        /**\n         *单击事件\n         */\n        fun itemClick(view: View, position: Int, parent: FlowLayout, children: List<TreeBean>)\n    }\n\n}"
  },
  {
    "path": "app/src/main/java/com/lxm/wanandroid/ui/adapter/WelfareAdapter.kt",
    "content": "package com.lxm.wanandroid.ui.adapter\n\n\nimport android.widget.ImageView\nimport com.lxm.module_library.utils.DisplayUtils\nimport com.lxm.wanandroid.R\nimport com.lxm.wanandroid.repository.model.Welfare\nimport com.lxm.wanandroid.ui.base.BaseRecyclerAdapter\nimport com.lxm.wanandroid.ui.base.BaseRecyclerViewHolder\nimport com.lxm.wanandroid.utils.GlideUtil\n\nclass WelfareAdapter : BaseRecyclerAdapter<Welfare>() {\n\n    override fun getItemLayout(): Int {\n        return R.layout.item_view_welfare\n    }\n\n    override fun onBindViewHoder(holder: BaseRecyclerViewHolder, position: Int) {\n        var welfare: Welfare = mutableList?.get(position)\n        val imageView: ImageView = holder.getView(R.id.iv_welfare) as ImageView\n        GlideUtil.displayCircleCorner(imageView,welfare.url)\n    }\n}"
  },
  {
    "path": "app/src/main/java/com/lxm/wanandroid/ui/base/BaseRecyclerAdapter.kt",
    "content": "package com.lxm.wanandroid.ui.base\n\nimport android.content.Context\nimport android.support.annotation.IntRange\nimport android.support.v7.widget.RecyclerView\nimport android.view.LayoutInflater\nimport android.view.ViewGroup\n\nabstract class BaseRecyclerAdapter<T> : RecyclerView.Adapter<BaseRecyclerViewHolder>() {\n\n    lateinit var context: Context\n    var layoutRes: Int = 0\n    var mutableList: MutableList<T> = mutableListOf()\n    var listener: OnItemClickListener<T>? = null\n\n\n    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseRecyclerViewHolder {\n        context = parent.context\n        return BaseRecyclerViewHolder(\n            LayoutInflater.from(context).inflate(\n                getItemLayout(),\n                null\n            )\n        )\n    }\n\n\n    fun setOnItemClickListener(listener: OnItemClickListener<T>) {\n        this.listener = listener\n    }\n\n    override fun onBindViewHolder(holder: BaseRecyclerViewHolder, position: Int) {\n        onBindViewHoder(holder, position)\n        holder.itemView.setOnClickListener {\n            listener?.onClick(mutableList.get(position),position)\n        }\n    }\n\n    override fun getItemCount(): Int {\n        return mutableList.size\n    }\n\n\n    fun setData(items: List<T>?) {\n        this.mutableList = items as MutableList<T>\n        notifyDataSetChanged()\n    }\n\n    fun addData(@IntRange(from = 0) position: Int, data: T) {\n        mutableList.add(position, data)\n        notifyItemInserted(position)\n        compatibilityDataSizeChanged(1)\n    }\n\n    fun addData(data: T) {\n        mutableList.add(data)\n        notifyItemInserted(mutableList?.size)\n    }\n\n    fun addDataAll(data: List<T>) {\n        mutableList.addAll(data)\n        notifyDataSetChanged()\n    }\n\n    fun addAdd(data: T) {\n        mutableList.add(data)\n        notifyItemInserted(mutableList?.size)\n    }\n\n\n    fun remove(position: Int) {\n        mutableList.removeAt(position)\n        notifyItemRemoved(position)\n        notifyItemRangeChanged(position, mutableList!!.size - position)\n    }\n\n    private fun compatibilityDataSizeChanged(size: Int) {\n        val dataSize = if (mutableList == null) 0 else mutableList!!.size\n        if (dataSize == size) {\n            notifyDataSetChanged()\n        }\n    }\n\n    /**\n     * 需要重写的方法\n     * @param holder\n     * @param position\n     */\n    abstract fun onBindViewHoder(holder: BaseRecyclerViewHolder, position: Int)\n\n    abstract fun getItemLayout(): Int\n}\n\n"
  },
  {
    "path": "app/src/main/java/com/lxm/wanandroid/ui/base/BaseRecyclerViewHoder.kt",
    "content": "package com.lxm.wanandroid.ui.base\n\nimport android.support.v7.widget.RecyclerView\nimport android.text.TextUtils\nimport android.view.View\nimport android.widget.ImageView\nimport android.widget.TextView\nimport com.bumptech.glide.Glide\nimport com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions\n\nopen class BaseRecyclerViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {\n\n    private val map = mutableMapOf<Int, View>()\n    fun getView(id: Int): View? {\n        var viewId = map[id]\n        if (viewId == null) {\n            viewId = itemView.findViewById(id)\n            map[id] = viewId\n        }\n        return viewId\n    }\n\n\n    fun setValue(id: Int, string: String?) {\n        val view = getView(id)\n\n        when (view) {\n            is TextView -> view.text = string\n            is ImageView -> showPic(view, string)\n        }\n    }\n\n    private fun showPic(view: ImageView, string: String?) {\n        if (TextUtils.isEmpty(string)) {\n            view.visibility = View.GONE\n        } else {\n            view.visibility = View.VISIBLE\n            Glide.with(view.context)\n                .load(string)\n                .transition(DrawableTransitionOptions.withCrossFade(500))\n                .into(view)\n        }\n    }\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/lxm/wanandroid/ui/base/OnItemClickListener.kt",
    "content": "package com.lxm.wanandroid.ui.base\n\n\ninterface OnItemClickListener<T> {\n    fun onClick(t: T, position: Int)\n}\n"
  },
  {
    "path": "app/src/main/java/com/lxm/wanandroid/ui/base/OnItemLongClickListener.kt",
    "content": "package com.lxm.wanandroid.ui.base\n\n\ninterface OnItemLongClickListener<T> {\n    fun onLongClick(t: T, position: Int)\n}\n"
  },
  {
    "path": "app/src/main/java/com/lxm/wanandroid/utils/CookieUtils.kt",
    "content": "package com.lxm.wanandroid.utils\n\nimport android.content.Context\nimport android.util.Log\nimport android.webkit.CookieManager\nimport android.webkit.CookieSyncManager\nimport com.google.android.gms.common.util.SharedPreferencesUtils\nimport okhttp3.Cookie\n\n\nobject CookieUtils {\n\n    /**\n     * clear Cookie\n     *\n     * @param context\n     */\n    fun clearCookie(context: Context) {\n        CookieSyncManager.createInstance(context)\n        CookieSyncManager.getInstance().startSync()\n        CookieManager.getInstance().removeSessionCookie()\n    }\n\n    /**\n     * Sync Cookie\n     */\n    fun syncCookie(context: Context, url: String,cookies:List<Cookie>) {\n        try {\n            CookieSyncManager.createInstance(context)\n            val cookieManager = CookieManager.getInstance()\n            cookies.forEach {\n                val name = it.name()\n                val value = it.value()\n                val cookieStr = \"$name=$value\"\n                cookieManager.setCookie(url,cookieStr)\n            }\n            cookieManager.flush()\n        } catch (e: Exception) {\n        }\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/lxm/wanandroid/utils/GlideUtil.kt",
    "content": "package com.lxm.wanandroid.utils\n\nimport android.content.Context\nimport android.graphics.Bitmap\nimport android.widget.ImageView\nimport com.bumptech.glide.Glide\nimport com.bumptech.glide.load.Transformation\nimport com.bumptech.glide.load.resource.bitmap.CircleCrop\nimport com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions\nimport jp.wasabeef.glide.transformations.BlurTransformation\nimport com.bumptech.glide.request.RequestOptions\nimport com.bumptech.glide.load.resource.bitmap.RoundedCorners\n\n\n\n\nobject GlideUtil {\n\n    private fun displayGaussian(context: Context, url: String, imageView: ImageView) {\n        // \"23\":模糊度；\"4\":图片缩放4倍后再进行模糊\n        Glide.with(context)\n            .load(url)\n            .transition(DrawableTransitionOptions.withCrossFade())\n            .transition(DrawableTransitionOptions.withCrossFade(500))\n            .transform(BlurTransformation(50, 8) as Transformation<Bitmap>)\n            .into(imageView)\n    }\n\n    /**\n     * 加载圆角图,暂时用到显示头像\n     */\n    fun displayCircle(imageView: ImageView, imageUrl: String) {\n        Glide.with(imageView.context)\n            .load(imageUrl)\n            .transition(DrawableTransitionOptions.withCrossFade(500))\n            .transform(CircleCrop())\n            //                .apply(bitmapTransform(new CircleCrop()))\n            //                .transform(new GlideCircleTransform())\n            //                .transform(new RoundedCorners(20))\n            //                .transform(new CenterCrop(), new RoundedCorners(20))\n            .into(imageView)\n    }\n\n    fun displayImage(imageView: ImageView, imageUrl: String) {\n        Glide.with(imageView.context)\n            .load(imageUrl)\n            .into(imageView)\n    }\n    fun displayCircleCorner(imageView: ImageView, imageUrl: String){\n        //设置图片圆角角度\n        val roundedCorners = RoundedCorners(6)\n//通过RequestOptions扩展功能,override:采样率,因为ImageView就这么大,可以压缩图片,降低内存消耗\n        val options = RequestOptions.bitmapTransform(roundedCorners)\n        Glide.with(imageView.context).load(imageUrl).apply(options).into(imageView)\n    }\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/lxm/wanandroid/utils/webview/WebViewActivity.java",
    "content": "package com.lxm.wanandroid.utils.webview;\n\nimport android.annotation.SuppressLint;\nimport android.content.Context;\nimport android.content.DialogInterface;\nimport android.content.Intent;\nimport android.content.pm.ActivityInfo;\nimport android.content.res.Configuration;\nimport android.content.res.Resources;\nimport android.net.Uri;\nimport android.os.Build;\nimport android.os.Bundle;\nimport android.support.v4.content.ContextCompat;\nimport android.support.v7.app.ActionBar;\nimport android.support.v7.app.AlertDialog;\nimport android.support.v7.app.AppCompatActivity;\nimport android.support.v7.widget.Toolbar;\nimport android.view.*;\nimport android.webkit.WebSettings;\nimport android.webkit.WebView;\nimport android.widget.FrameLayout;\nimport android.widget.ProgressBar;\nimport android.widget.TextView;\nimport com.lxm.module_library.statusbar.StatusBarUtil;\nimport com.lxm.module_library.utils.BaseTools;\nimport com.lxm.module_library.utils.CheckNetwork;\nimport com.lxm.module_library.utils.ToastUtil;\nimport com.lxm.wanandroid.R;\nimport com.lxm.wanandroid.utils.webview.config.*;\n\n/**\n * 网页可以处理:\n * 点击相应控件:拨打电话、发送短信、发送邮件、上传图片、播放视频\n * 进度条、返回网页上一层、显示网页标题\n * Thanks to: https://github.com/youlookwhat/WebViewStudy\n * contact me: http://www.jianshu.com/users/e43c6e979831/latest_articles\n */\npublic class WebViewActivity extends AppCompatActivity implements IWebPageView {\n\n    // 进度条\n    private ProgressBar mProgressBar;\n    private WebView webView;\n    // 全屏时视频加载view\n    private FrameLayout videoFullView;\n    private Toolbar mTitleToolBar;\n    // 加载视频相关\n    private MyWebChromeClient mWebChromeClient;\n    // title\n    private String mTitle;\n    // 网页链接\n    private String mUrl;\n    // 可滚动的title 使用简单 没有渐变效果，文字两旁有阴影\n    private TextView tvGunTitle;\n    private boolean isTitleFix;\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_web_view);\n        getIntentData();\n        initTitle();\n        initWebView();\n        webView.loadUrl(mUrl);\n        getDataFromBrowser(getIntent());\n    }\n\n    private void getIntentData() {\n        if (getIntent() != null) {\n            mTitle = getIntent().getStringExtra(\"mTitle\");\n            mUrl = getIntent().getStringExtra(\"mUrl\");\n            isTitleFix = getIntent().getBooleanExtra(\"isTitleFix\", false);\n        }\n    }\n\n    private void initTitle() {\n        StatusBarUtil.setColor(this, getResources().getColor(R.color.colorTheme), 0);\n        mProgressBar = findViewById(R.id.pb_progress);\n        webView = findViewById(R.id.webview_detail);\n        videoFullView = findViewById(R.id.video_fullView);\n        mTitleToolBar = findViewById(R.id.title_tool_bar);\n        tvGunTitle = findViewById(R.id.tv_gun_title);\n\n        initToolBar();\n    }\n\n    private void initToolBar() {\n        setSupportActionBar(mTitleToolBar);\n        ActionBar actionBar = getSupportActionBar();\n        if (actionBar != null) {\n            //去除默认Title显示\n            actionBar.setDisplayShowTitleEnabled(false);\n        }\n        mTitleToolBar.setOverflowIcon(ContextCompat.getDrawable(this, R.drawable.actionbar_more));\n        tvGunTitle.postDelayed(() -> tvGunTitle.setSelected(true), 1900);\n        tvGunTitle.setText(mTitle);\n    }\n\n    @Override\n    public boolean onCreateOptionsMenu(Menu menu) {\n        getMenuInflater().inflate(R.menu.webview_menu, menu);\n        return true;\n    }\n\n    @Override\n    public void setTitle(String mTitle) {\n        if (!isTitleFix) {\n            tvGunTitle.setText(mTitle);\n            this.mTitle = mTitle;\n        }\n    }\n\n    @Override\n    public boolean onOptionsItemSelected(MenuItem item) {\n        switch (item.getItemId()) {\n            case android.R.id.home:\n                // 返回键\n                handleFinish();\n                break;\n            case R.id.actionbar_share:\n                // 分享到\n                break;\n            case R.id.actionbar_cope:\n//                 复制链接\n                BaseTools.copy(webView.getUrl());\n                ToastUtil.showToast(\"复制成功\");\n                break;\n            case R.id.actionbar_open:\n                // 打开链接\n                BaseTools.openLink(WebViewActivity.this, webView.getUrl());\n                break;\n            case R.id.actionbar_webview_refresh:\n                // 刷新页面\n                if (webView != null) {\n                    webView.reload();\n                }\n                break;\n            default:\n                break;\n        }\n        return super.onOptionsItemSelected(item);\n    }\n\n    @SuppressLint(\"SetJavaScriptEnabled\")\n    private void initWebView() {\n        mProgressBar.setVisibility(View.VISIBLE);\n        WebSettings ws = webView.getSettings();\n        // 网页内容的宽度是否可大于WebView控件的宽度\n        ws.setLoadWithOverviewMode(false);\n        // 保存表单数据\n        ws.setSaveFormData(true);\n        // 是否应该支持使用其屏幕缩放控件和手势缩放\n        ws.setSupportZoom(true);\n        ws.setBuiltInZoomControls(true);\n        ws.setDisplayZoomControls(false);\n        // 启动应用缓存\n        ws.setAppCacheEnabled(true);\n        // 设置缓存模式\n        ws.setCacheMode(WebSettings.LOAD_DEFAULT);\n        // setDefaultZoom  api19被弃用\n        // 设置此属性，可任意比例缩放。\n        ws.setUseWideViewPort(true);\n        // 不缩放\n        webView.setInitialScale(100);\n        // 告诉WebView启用JavaScript执行。默认的是false。\n        ws.setJavaScriptEnabled(true);\n        //  页面加载好以后，再放开图片\n        ws.setBlockNetworkImage(false);\n        // 使用localStorage则必须打开\n        ws.setDomStorageEnabled(true);\n        // 排版适应屏幕\n        ws.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NARROW_COLUMNS);\n        // WebView是否新窗口打开(加了后可能打不开网页)\n//        ws.setSupportMultipleWindows(true);\n\n        // webview从5.0开始默认不允许混合模式,https中不能加载http资源,需要设置开启。\n        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {\n            ws.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);\n        }\n        /** 设置字体默认缩放大小(改变网页字体大小,setTextSize  api14被弃用)*/\n        ws.setTextZoom(100);\n\n        mWebChromeClient = new MyWebChromeClient(this);\n        webView.setWebChromeClient(mWebChromeClient);\n        // 与js交互\n        webView.addJavascriptInterface(new ImageClickInterface(this), \"injectedObject\");\n        webView.setWebViewClient(new MyWebViewClient(this));\n        webView.setOnLongClickListener(new View.OnLongClickListener() {\n            @Override\n            public boolean onLongClick(View v) {\n                return handleLongImage();\n            }\n        });\n    }\n\n    @Override\n    public void hindProgressBar() {\n        mProgressBar.setVisibility(View.GONE);\n    }\n\n    @Override\n    public void showWebView() {\n        webView.setVisibility(View.VISIBLE);\n    }\n\n    @Override\n    public void hindWebView() {\n        webView.setVisibility(View.INVISIBLE);\n    }\n\n    @Override\n    public void fullViewAddView(View view) {\n        FrameLayout decor = (FrameLayout) getWindow().getDecorView();\n        videoFullView = new FullscreenHolder(WebViewActivity.this);\n        videoFullView.addView(view);\n        decor.addView(videoFullView);\n    }\n\n    @Override\n    public void showVideoFullView() {\n        videoFullView.setVisibility(View.VISIBLE);\n    }\n\n    @Override\n    public void hindVideoFullView() {\n        videoFullView.setVisibility(View.GONE);\n    }\n\n    @Override\n    public void startProgress(int newProgress) {\n        mProgressBar.setVisibility(View.VISIBLE);\n        mProgressBar.setProgress(newProgress);\n        if (newProgress == 100) {\n            mProgressBar.setVisibility(View.GONE);\n        }\n    }\n\n    @Override\n    public void addImageClickListener() {\n//        loadImageClickJS();\n//        loadTextClickJS();\n    }\n\n    private void loadImageClickJS() {\n        // 这段js函数的功能就是，遍历所有的img节点，并添加onclick函数，函数的功能是在图片点击的时候调用本地java接口并传递url过去\n        webView.loadUrl(\"javascript:(function(){\" +\n                \"var objs = document.getElementsByTagName(\\\"img\\\");\" +\n                \"for(var i=0;i<objs.length;i++)\" +\n                \"{\" +\n                \"objs[i].onclick=function(){window.injectedObject.imageClick(this.getAttribute(\\\"src\\\"),this.getAttribute(\\\"has_link\\\"));}\" +\n                \"}\" +\n                \"})()\");\n    }\n\n    private void loadTextClickJS() {\n        // 遍历所有的a节点,将节点里的属性传递过去(属性自定义,用于页面跳转)\n        webView.loadUrl(\"javascript:(function(){\" +\n                \"var objs =document.getElementsByTagName(\\\"a\\\");\" +\n                \"for(var i=0;i<objs.length;i++)\" +\n                \"{\" +\n                \"objs[i].onclick=function(){\" +\n                \"window.injectedObject.textClick(this.getAttribute(\\\"type\\\"),this.getAttribute(\\\"item_pk\\\"));}\" +\n                \"}\" +\n                \"})()\");\n    }\n\n    public FrameLayout getVideoFullView() {\n        return videoFullView;\n    }\n\n    /**\n     * 全屏时按返加键执行退出全屏方法\n     */\n    public void hideCustomView() {\n        mWebChromeClient.onHideCustomView();\n        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);\n    }\n\n    /**\n     * 上传图片之后的回调\n     */\n    @Override\n    protected void onActivityResult(int requestCode, int resultCode, Intent intent) {\n        if (requestCode == MyWebChromeClient.FILECHOOSER_RESULTCODE) {\n            mWebChromeClient.mUploadMessage(intent, resultCode);\n        } else if (requestCode == MyWebChromeClient.FILECHOOSER_RESULTCODE_FOR_ANDROID_5) {\n            mWebChromeClient.mUploadMessageForAndroid5(intent, resultCode);\n        }\n    }\n\n    /**\n     * 使用singleTask启动模式的Activity在系统中只会存在一个实例。\n     * 如果这个实例已经存在，intent就会通过onNewIntent传递到这个Activity。\n     * 否则新的Activity实例被创建。\n     */\n    @Override\n    protected void onNewIntent(Intent intent) {\n        super.onNewIntent(intent);\n        getDataFromBrowser(intent);\n    }\n\n    /**\n     * 作为三方浏览器打开\n     * Scheme: https\n     * host: www.jianshu.com\n     * path: /p/1cbaf784c29c\n     * url = scheme + \"://\" + host + path;\n     */\n    private void getDataFromBrowser(Intent intent) {\n        Uri data = intent.getData();\n        if (data != null) {\n            try {\n                String scheme = data.getScheme();\n                String host = data.getHost();\n                String path = data.getPath();\n//                String text = \"Scheme: \" + scheme + \"\\n\" + \"host: \" + host + \"\\n\" + \"path: \" + path;\n//                Log.e(\"data\", text);\n                String url = scheme + \"://\" + host + path;\n                webView.loadUrl(url);\n            } catch (Exception e) {\n                e.printStackTrace();\n            }\n        }\n    }\n\n    /**\n     * 长按图片事件处理\n     */\n    private boolean handleLongImage() {\n        final WebView.HitTestResult hitTestResult = webView.getHitTestResult();\n        // 如果是图片类型或者是带有图片链接的类型\n        if (hitTestResult.getType() == WebView.HitTestResult.IMAGE_TYPE ||\n                hitTestResult.getType() == WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE) {\n            // 弹出保存图片的对话框\n            new AlertDialog.Builder(WebViewActivity.this)\n                    .setItems(new String[]{\"查看大图\", \"保存图片到相册\"}, new DialogInterface.OnClickListener() {\n                        @Override\n                        public void onClick(DialogInterface dialog, int which) {\n                            String picUrl = hitTestResult.getExtra();\n                            //获取图片\n//                            Log.e(\"picUrl\", picUrl);\n//                            switch (which) {\n//                                case 0:\n//                                    ViewBigImageActivity.start(WebViewActivity.this, picUrl, picUrl);\n//                                    break;\n//                                case 1:\n//                                    if (!PermissionHandler.isHandlePermission(WebViewActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {\n//                                        return;\n//                                    }\n//                                    RxSaveImage.saveImageToGallery(WebViewActivity.this, picUrl, picUrl);\n//                                    break;\n//                                default:\n//                                    break;\n//                            }\n                        }\n                    })\n                    .show();\n            return true;\n        }\n        return false;\n    }\n\n    @Override\n    public boolean onKeyDown(int keyCode, KeyEvent event) {\n        if (keyCode == KeyEvent.KEYCODE_BACK) {\n            //全屏播放退出全屏\n            if (mWebChromeClient.inCustomView()) {\n                hideCustomView();\n                return true;\n\n                //返回网页上一页\n            } else if (webView.canGoBack()) {\n                webView.goBack();\n                return true;\n\n                //退出网页\n            } else {\n                handleFinish();\n            }\n        }\n        return false;\n    }\n\n    /**\n     * 直接通过三方浏览器打开时，回退到首页\n     */\n    public void handleFinish() {\n        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {\n            finishAfterTransition();\n        } else {\n            finish();\n        }\n\n    }\n\n    @Override\n    protected void onPause() {\n        super.onPause();\n        webView.onPause();\n    }\n\n    @Override\n    protected void onResume() {\n        super.onResume();\n        webView.onResume();\n        // 支付宝网页版在打开文章详情之后,无法点击按钮下一步\n        webView.resumeTimers();\n        // 设置为横屏\n        if (getRequestedOrientation() != ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {\n            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);\n        }\n    }\n\n    @Override\n    protected void onDestroy() {\n        if (videoFullView != null) {\n            videoFullView.clearAnimation();\n            videoFullView.removeAllViews();\n        }\n        if (webView != null) {\n            webView.loadDataWithBaseURL(null, \"\", \"text/html\", \"utf-8\", null);\n            webView.clearHistory();\n            ViewGroup parent = (ViewGroup) webView.getParent();\n            if (parent != null) {\n                parent.removeView(webView);\n            }\n            webView.removeAllViews();\n            webView.stopLoading();\n            webView.setWebChromeClient(null);\n            webView.setWebViewClient(null);\n            webView.destroy();\n            webView = null;\n            mProgressBar.clearAnimation();\n            tvGunTitle.clearAnimation();\n            tvGunTitle.clearFocus();\n        }\n        super.onDestroy();\n    }\n\n    @Override\n    public void onConfigurationChanged(Configuration newConfig) {\n        super.onConfigurationChanged(newConfig);\n        if (newConfig.fontScale != 1) {\n            getResources();\n        }\n    }\n\n    /**\n     * 禁止改变字体大小\n     */\n    @Override\n    public Resources getResources() {\n        Resources res = super.getResources();\n        Configuration config = new Configuration();\n        config.setToDefaults();\n        res.updateConfiguration(config, res.getDisplayMetrics());\n        return res;\n    }\n\n    /**\n     * 打开网页:\n     *\n     * @param mContext 上下文\n     * @param mUrl     要加载的网页url\n     * @param mTitle   title\n     */\n    public static void loadUrl(Context mContext, String mUrl, String mTitle) {\n        loadUrl(mContext, mUrl, mTitle, false);\n    }\n\n    /**\n     * 打开网页:\n     *\n     * @param mContext     上下文\n     * @param mUrl         要加载的网页url\n     * @param mTitle       title\n     * @param isTitleFixed title是否固定\n     */\n    public static void loadUrl(Context mContext, String mUrl, String mTitle, boolean isTitleFixed) {\n        if (CheckNetwork.isNetworkConnected(mContext)) {\n            Intent intent = new Intent(mContext, WebViewActivity.class);\n            intent.putExtra(\"mUrl\", mUrl);\n            intent.putExtra(\"isTitleFix\", isTitleFixed);\n            intent.putExtra(\"mTitle\", mTitle == null ? \"\" : mTitle);\n            mContext.startActivity(intent);\n        } else {\n            ToastUtil.showToastLong(\"当前网络不可用，请检查你的网络设置\");\n        }\n    }\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/lxm/wanandroid/utils/webview/config/FullscreenHolder.java",
    "content": "package com.lxm.wanandroid.utils.webview.config;\n\nimport android.content.Context;\nimport android.view.MotionEvent;\nimport android.widget.FrameLayout;\n\n/**\n * Created by jingbin on 2016/11/17.\n */\n\npublic class FullscreenHolder extends FrameLayout {\n\n    public FullscreenHolder(Context ctx) {\n        super(ctx);\n        setBackgroundColor(ctx.getResources().getColor(android.R.color.black));\n    }\n\n    @Override\n    public boolean onTouchEvent(MotionEvent event) {\n        return true;\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/lxm/wanandroid/utils/webview/config/IWebPageView.java",
    "content": "package com.lxm.wanandroid.utils.webview.config;\n\nimport android.view.View;\n\n/**\n * Created by jingbin on 2016/11/17.\n */\npublic interface IWebPageView {\n\n    // 隐藏进度条\n    void hindProgressBar();\n\n    // 显示webview\n    void showWebView();\n\n    // 隐藏webview\n    void hindWebView();\n\n    /**\n     * 进度条变化时调用\n     */\n    void startProgress(int newProgress);\n\n    /**\n     * 添加js监听\n     */\n    void addImageClickListener();\n\n    /**\n     * 播放网络视频全屏调用\n     */\n    void fullViewAddView(View view);\n\n    void showVideoFullView();\n\n    void hindVideoFullView();\n\n    /**\n     * 得到网页标题\n     */\n    void setTitle(String title);\n}\n"
  },
  {
    "path": "app/src/main/java/com/lxm/wanandroid/utils/webview/config/ImageClickInterface.java",
    "content": "package com.lxm.wanandroid.utils.webview.config;\n\nimport android.content.Context;\nimport android.content.Intent;\nimport android.text.TextUtils;\nimport android.util.Log;\nimport android.webkit.JavascriptInterface;\nimport android.widget.Toast;\nimport com.lxm.wanandroid.ui.ViewBigImageActivity;\n\n/**\n * Created by jingbin on 2016/11/17.\n * js通信接口\n */\npublic class ImageClickInterface {\n    private Context context;\n\n    public ImageClickInterface(Context context) {\n        this.context = context;\n    }\n\n    @JavascriptInterface\n    public void imageClick(String imgUrl, String hasLink) {\n        Toast.makeText(context, \"----点击了图片\", Toast.LENGTH_SHORT).show();\n        Intent intent = new Intent(context, ViewBigImageActivity.class);\n        context.startActivity(intent);\n        Log.e(\"----点击了图片 url: \", \"\" + imgUrl);\n    }\n\n    @JavascriptInterface\n    public void textClick(String type, String item_pk) {\n        if (!TextUtils.isEmpty(type) && !TextUtils.isEmpty(item_pk)) {\n            Log.e(\"----点击了文字\", \"\");\n        }\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/lxm/wanandroid/utils/webview/config/MyWebChromeClient.java",
    "content": "package com.lxm.wanandroid.utils.webview.config;\n\nimport android.content.Intent;\nimport android.content.pm.ActivityInfo;\nimport android.net.Uri;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.webkit.ValueCallback;\nimport android.webkit.WebChromeClient;\nimport android.webkit.WebView;\nimport com.lxm.wanandroid.utils.webview.WebViewActivity;\n\nimport static android.app.Activity.RESULT_OK;\n\n\n/**\n * Created by jingbin on 2016/11/17.\n * - 播放网络视频配置\n * - 上传图片(兼容)\n * 点击空白区域的左边,因是公司图片,自己编辑过,所以显示不全,见谅\n */\npublic class MyWebChromeClient extends WebChromeClient {\n\n    private ValueCallback<Uri> mUploadMessage;\n    private ValueCallback<Uri[]> mUploadMessageForAndroid5;\n    public static int FILECHOOSER_RESULTCODE = 1;\n    public static int FILECHOOSER_RESULTCODE_FOR_ANDROID_5 = 2;\n\n    private View mXProgressVideo;\n    private WebViewActivity mActivity;\n    private IWebPageView mIWebPageView;\n    private View mXCustomView;\n    private CustomViewCallback mXCustomViewCallback;\n\n    public MyWebChromeClient(IWebPageView mIWebPageView) {\n        this.mIWebPageView = mIWebPageView;\n        this.mActivity = (WebViewActivity) mIWebPageView;\n    }\n\n    // 播放网络视频时全屏会被调用的方法\n    @Override\n    public void onShowCustomView(View view, CustomViewCallback callback) {\n        mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);\n        mIWebPageView.hindWebView();\n        // 如果一个视图已经存在，那么立刻终止并新建一个\n        if (mXCustomView != null) {\n            callback.onCustomViewHidden();\n            return;\n        }\n\n        mActivity.fullViewAddView(view);\n        mXCustomView = view;\n        mXCustomViewCallback = callback;\n        mIWebPageView.showVideoFullView();\n    }\n\n    // 视频播放退出全屏会被调用的\n    @Override\n    public void onHideCustomView() {\n        if (mXCustomView == null)// 不是全屏播放状态\n            return;\n        mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);\n\n        mXCustomView.setVisibility(View.GONE);\n        if (mActivity.getVideoFullView() != null) {\n            mActivity.getVideoFullView().removeView(mXCustomView);\n        }\n        mXCustomView = null;\n        mIWebPageView.hindVideoFullView();\n        mXCustomViewCallback.onCustomViewHidden();\n        mIWebPageView.showWebView();\n    }\n\n    // 视频加载时进程loading\n    @Override\n    public View getVideoLoadingProgressView() {\n        if (mXProgressVideo == null) {\n            LayoutInflater inflater = LayoutInflater.from(mActivity);\n//            mXProgressVideo = inflater.inflate(R.layout.video_loading_progress, null);\n        }\n        return mXProgressVideo;\n    }\n\n    @Override\n    public void onProgressChanged(WebView view, int newProgress) {\n        super.onProgressChanged(view, newProgress);\n        mIWebPageView.startProgress(newProgress);\n    }\n\n    /**\n     * 判断是否是全屏\n     */\n    public boolean inCustomView() {\n        return (mXCustomView != null);\n    }\n\n    @Override\n    public void onReceivedTitle(WebView view, String title) {\n        super.onReceivedTitle(view, title);\n        mIWebPageView.setTitle(title);\n//        // 设置title\n//        mActivity.setTitle(title);\n//        this.title = title;\n    }\n\n//    private String title = \"\";\n\n//    public String getTitle() {\n//        return title + \" \";\n//    }\n\n    //扩展浏览器上传文件\n    //3.0++版本\n    public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) {\n        openFileChooserImpl(uploadMsg);\n    }\n\n    //3.0--版本\n    public void openFileChooser(ValueCallback<Uri> uploadMsg) {\n        openFileChooserImpl(uploadMsg);\n    }\n\n    public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) {\n        openFileChooserImpl(uploadMsg);\n    }\n\n    // For Android > 5.0\n    @Override\n    public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> uploadMsg, FileChooserParams fileChooserParams) {\n        openFileChooserImplForAndroid5(uploadMsg);\n        return true;\n    }\n\n    private void openFileChooserImpl(ValueCallback<Uri> uploadMsg) {\n        mUploadMessage = uploadMsg;\n        Intent i = new Intent(Intent.ACTION_GET_CONTENT);\n        i.addCategory(Intent.CATEGORY_OPENABLE);\n        i.setType(\"image/*\");\n        mActivity.startActivityForResult(Intent.createChooser(i, \"文件选择\"), FILECHOOSER_RESULTCODE);\n    }\n\n    private void openFileChooserImplForAndroid5(ValueCallback<Uri[]> uploadMsg) {\n        mUploadMessageForAndroid5 = uploadMsg;\n        Intent contentSelectionIntent = new Intent(Intent.ACTION_GET_CONTENT);\n        contentSelectionIntent.addCategory(Intent.CATEGORY_OPENABLE);\n        contentSelectionIntent.setType(\"image/*\");\n\n        Intent chooserIntent = new Intent(Intent.ACTION_CHOOSER);\n        chooserIntent.putExtra(Intent.EXTRA_INTENT, contentSelectionIntent);\n        chooserIntent.putExtra(Intent.EXTRA_TITLE, \"图片选择\");\n\n        mActivity.startActivityForResult(chooserIntent, FILECHOOSER_RESULTCODE_FOR_ANDROID_5);\n    }\n\n    /**\n     * 5.0以下 上传图片成功后的回调\n     */\n    public void mUploadMessage(Intent intent, int resultCode) {\n        if (null == mUploadMessage)\n            return;\n        Uri result = intent == null || resultCode != RESULT_OK ? null : intent.getData();\n        mUploadMessage.onReceiveValue(result);\n        mUploadMessage = null;\n    }\n\n    /**\n     * 5.0以上 上传图片成功后的回调\n     */\n    public void mUploadMessageForAndroid5(Intent intent, int resultCode) {\n        if (null == mUploadMessageForAndroid5)\n            return;\n        Uri result = (intent == null || resultCode != RESULT_OK) ? null : intent.getData();\n        if (result != null) {\n            mUploadMessageForAndroid5.onReceiveValue(new Uri[]{result});\n        } else {\n            mUploadMessageForAndroid5.onReceiveValue(new Uri[]{});\n        }\n        mUploadMessageForAndroid5 = null;\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/lxm/wanandroid/utils/webview/config/MyWebViewClient.java",
    "content": "package com.lxm.wanandroid.utils.webview.config;\n\nimport android.app.Activity;\nimport android.content.Intent;\nimport android.net.Uri;\nimport android.text.TextUtils;\nimport android.webkit.WebView;\nimport android.webkit.WebViewClient;\nimport com.lxm.module_library.utils.BaseTools;\nimport com.lxm.module_library.utils.CheckNetwork;\nimport com.lxm.wanandroid.utils.webview.WebViewActivity;\n\n\n/**\n * Created by jingbin on 2016/11/17.\n * 监听网页链接:\n * - 优酷视频直接跳到自带浏览器\n * - 根据标识:打电话、发短信、发邮件\n * - 进度条的显示\n * - 添加javascript监听\n */\npublic class MyWebViewClient extends WebViewClient {\n\n    private IWebPageView mIWebPageView;\n    private WebViewActivity mActivity;\n\n    public MyWebViewClient(IWebPageView mIWebPageView) {\n        this.mIWebPageView = mIWebPageView;\n        mActivity = (WebViewActivity) mIWebPageView;\n\n    }\n\n    @SuppressWarnings(\"deprecation\")\n    @Override\n    public boolean shouldOverrideUrlLoading(WebView view, String url) {\n//        DebugUtil.error(\"----url:\"+url);\n        if (TextUtils.isEmpty(url)) {\n            return false;\n        }\n        if (url.startsWith(\"http:\") || url.startsWith(\"https:\")) {\n            // 可能有提示下载Apk文件\n            if (url.contains(\".apk\")) {\n                handleOtherwise(mActivity, url);\n                return true;\n            }\n            return false;\n        }\n\n        handleOtherwise(mActivity, url);\n        return true;\n    }\n\n    @Override\n    public void onPageFinished(WebView view, String url) {\n        if (!CheckNetwork.isNetworkConnected(mActivity)) {\n            mIWebPageView.hindProgressBar();\n        }\n        // html加载完成之后，添加监听图片的点击js函数\n        mIWebPageView.addImageClickListener();\n        super.onPageFinished(view, url);\n    }\n\n    // 视频全屏播放按返回页面被放大的问题\n    @Override\n    public void onScaleChanged(WebView view, float oldScale, float newScale) {\n        super.onScaleChanged(view, oldScale, newScale);\n        if (newScale - oldScale > 7) {\n            view.setInitialScale((int) (oldScale / newScale * 100)); //异常放大，缩回去。\n        }\n    }\n\n    /**\n     * 网页里可能唤起其他的app\n     */\n    private void handleOtherwise(Activity activity, String url) {\n        String appPackageName = \"\";\n        // 支付宝支付\n        if (url.contains(\"alipays\")) {\n            appPackageName = \"com.eg.android.AlipayGphone\";\n\n            // 微信支付\n        } else if (url.contains(\"weixin://wap/pay\")) {\n            appPackageName = \"com.tencent.mm\";\n\n            // 京东产品详情\n        } else if (url.contains(\"openapp.jdmobile\")) {\n            appPackageName = \"com.jingdong.app.mall\";\n        } else {\n            startActivity(url);\n        }\n        if (BaseTools.isApplicationAvilible(activity, appPackageName)) {\n            startActivity(url);\n        }\n    }\n\n    private void startActivity(String url) {\n        try {\n            Intent intent1 = new Intent();\n            intent1.setAction(\"android.intent.action.VIEW\");\n            Uri uri = Uri.parse(url);\n            intent1.setData(uri);\n            intent1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);\n            mActivity.startActivity(intent1);\n        } catch (Exception e) {\n            e.printStackTrace();\n        }\n    }\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/lxm/wanandroid/viewmodel/ArticleViewModel.kt",
    "content": "package com.lxm.wanandroid.viewmodel\n\nimport android.arch.lifecycle.MutableLiveData\nimport com.lxm.module_library.base.BaseViewModel\nimport com.lxm.module_library.helper.RxHelper\nimport com.lxm.wanandroid.repository.model.*\nimport com.lxm.wanandroid.repository.remote.httpClient.RetrofitClient\nimport io.reactivex.functions.Consumer\n\nclass ArticleViewModel : BaseViewModel() {\n\n    var mPage = 0\n    var banner = MutableLiveData<HttpResponse<List<Banner>>>()\n    val pagedList = MutableLiveData<HttpResponse<ArticleResponseBody<ArticleBean>>>()\n    val loadStatus by lazy {\n        MutableLiveData<Resource<String>>()\n    }\n\n    fun getHomeList(): Listing<HttpResponse<ArticleResponseBody<ArticleBean>>> {\n        loadStatus.postValue(Resource.loading())\n        val subscribe = RetrofitClient.getInstance(RetrofitClient.WAN_BASE_URL).getArticleList(mPage)\n            .compose(RxHelper.rxSchedulerHelper())\n            .subscribe(Consumer<HttpResponse<ArticleResponseBody<ArticleBean>>> {\n                if(it.data != null){\n                    loadStatus.postValue(Resource.success())\n                    pagedList.value = it\n                }else{\n                    loadStatus.postValue(Resource.error())\n                }\n\n            }, Consumer<Throwable> {\n                if (mPage > 0) {\n                    mPage--\n                }\n                loadStatus.postValue(Resource.error())\n            })\n        addDisposable(subscribe)\n        return Listing(pagedList,loadStatus)\n    }\n\n    fun getBanners(): MutableLiveData<HttpResponse<List<Banner>>> {\n        val subscribe = RetrofitClient.getInstance(RetrofitClient.WAN_BASE_URL).getHomeBanner()\n            .compose(RxHelper.rxSchedulerHelper())\n            .subscribe(Consumer<HttpResponse<List<Banner>>>{\n                banner.postValue(it)\n            }, Consumer<Throwable> {\n                banner.postValue(null)\n            })\n\n        addDisposable(subscribe)\n        return banner\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/lxm/wanandroid/viewmodel/CategoryViewModel.kt",
    "content": "package com.lxm.wanandroid.viewmodel\n\nimport android.arch.lifecycle.MutableLiveData\nimport com.lxm.module_library.base.BaseViewModel\nimport com.lxm.module_library.helper.RxHelper\nimport com.lxm.wanandroid.repository.model.*\nimport com.lxm.wanandroid.repository.remote.httpClient.RetrofitClient\nimport io.reactivex.functions.Consumer\n\nclass CategoryViewModel: BaseViewModel() {\n    var mPage = 0\n    val pagedList = MutableLiveData<HttpResponse<ArticleResponseBody<ArticleBean>>>()\n    val loadStatus by lazy {\n        MutableLiveData<Resource<String>>()\n    }\n\n    fun getCategory(id: Int): Listing<HttpResponse<ArticleResponseBody<ArticleBean>>> {\n        loadStatus.postValue(Resource.loading())\n        val subscribe = RetrofitClient.getInstance(RetrofitClient.WAN_BASE_URL).getCategory(mPage,id)\n            .compose(RxHelper.rxSchedulerHelper())\n            .subscribe(Consumer<HttpResponse<ArticleResponseBody<ArticleBean>>> {\n                if(it.data != null){\n                    loadStatus.postValue(Resource.success())\n                    pagedList.value = it\n                }else{\n                    loadStatus.postValue(Resource.error())\n                }\n\n            }, Consumer<Throwable> {\n                if (mPage > 0) {\n                    mPage--\n                }\n                loadStatus.postValue(Resource.error())\n            })\n        addDisposable(subscribe)\n        return Listing(pagedList,loadStatus)\n    }\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/lxm/wanandroid/viewmodel/CollectViewModel.kt",
    "content": "package com.lxm.wanandroid.viewmodel\n\nimport android.arch.lifecycle.MutableLiveData\nimport com.lxm.module_library.base.BaseViewModel\nimport com.lxm.module_library.helper.RxHelper\nimport com.lxm.wanandroid.repository.model.*\nimport com.lxm.wanandroid.repository.remote.httpClient.RetrofitClient\nimport com.lxm.wanandroid.ui.adapter.ArticleAdapter\nimport io.reactivex.functions.Consumer\n\nclass CollectViewModel : BaseViewModel() {\n\n    var mPage = 0\n    val collectionList = MutableLiveData<HttpResponse<ArticleResponseBody<ArticleBean>>>()\n    val loadStatus by lazy {\n        MutableLiveData<Resource<String>>()\n    }\n\n    fun getCollect(): Listing<HttpResponse<ArticleResponseBody<ArticleBean>>> {\n        loadStatus.postValue(Resource.loading())\n        val subscribe = RetrofitClient.getInstance(RetrofitClient.WAN_BASE_URL).getCollectList(mPage)\n            .compose(RxHelper.rxSchedulerHelper())\n            .subscribe(Consumer<HttpResponse<ArticleResponseBody<ArticleBean>>> {\n                if(it.data != null){\n                    loadStatus.postValue(Resource.success())\n                    collectionList.value = it\n                }else{\n                    loadStatus.postValue(Resource.error())\n                }\n\n            }, Consumer<Throwable> {\n                if (mPage > 0) {\n                    mPage--\n                }\n                loadStatus.postValue(Resource.error())\n            })\n        addDisposable(subscribe)\n        return Listing(collectionList,loadStatus)\n    }\n\n    fun collect(id:Int,collectionObserver: ArticleAdapter.CollectionObserver<HttpResponse<Any>>) {\n        val subscribe = RetrofitClient.getInstance(RetrofitClient.WAN_BASE_URL).collect(id)\n            .compose(RxHelper.rxSchedulerHelper())\n            .subscribe(Consumer<HttpResponse<Any>> {\n                collectionObserver.onChanged(it)\n            }, Consumer<Throwable> {\n                collectionObserver.onChanged(null)\n            })\n        addDisposable(subscribe)\n    }\n    fun unCollect(id:Int,collectionObserver: ArticleAdapter.CollectionObserver<HttpResponse<Any>>) {\n        val subscribe = RetrofitClient.getInstance(RetrofitClient.WAN_BASE_URL).unCollect(id)\n            .compose(RxHelper.rxSchedulerHelper())\n            .subscribe(Consumer<HttpResponse<Any>> {\n                collectionObserver.onChanged(it)\n            }, Consumer<Throwable> {\n                collectionObserver.onChanged(null)\n            })\n        addDisposable(subscribe)\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/lxm/wanandroid/viewmodel/LoginViewModel.kt",
    "content": "package com.lxm.wanandroid.viewmodel\n\nimport android.arch.lifecycle.Transformations\nimport com.lxm.module_library.base.BaseViewModel\nimport com.lxm.wanandroid.repository.remote.LoginRepository\n\nclass LoginViewModel(val loginRepository: LoginRepository) : BaseViewModel() {\n     var loginStatus = Transformations.map(loginRepository.login){it}\n     var registerStauts = Transformations.map(loginRepository.register){it}\n    var logoutStatus = Transformations.map(loginRepository.logout){it}\n\n\n    fun login(username:String,password:String) {\n        loginRepository.login(username,password)\n    }\n\n    fun logout() {\n        loginRepository.logout()\n    }\n\n\n    fun register(username:String,password:String,repassword:String) {\n        loginRepository.register(username,password,repassword)\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/lxm/wanandroid/viewmodel/NaviViewModelView.kt",
    "content": "package com.lxm.wanandroid.viewmodel\n\nimport android.arch.lifecycle.MutableLiveData\nimport com.lxm.module_library.base.BaseViewModel\nimport com.lxm.module_library.helper.RxHelper\nimport com.lxm.wanandroid.repository.model.Navigation\nimport com.lxm.wanandroid.repository.model.Resource\nimport com.lxm.wanandroid.repository.remote.httpClient.RetrofitClient\n\nclass NaviViewModelView : BaseViewModel() {\n    private val naviList = MutableLiveData<List<Navigation>>()\n    val loadStatus by lazy {\n        MutableLiveData<Resource<String>>()\n    }\n    fun getVavigations(): MutableLiveData<List<Navigation>> {\n        RetrofitClient.getInstance(RetrofitClient.WAN_BASE_URL).getNavigation()\n            .compose(RxHelper.rxSchedulerHelper())\n            .subscribe({\n                naviList.postValue(it.data)\n            }, {\n                loadStatus.postValue(Resource.error())\n            })\n        return naviList\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/lxm/wanandroid/viewmodel/ProjectViewModel.kt",
    "content": "package com.lxm.wanandroid.viewmodel\n\nimport android.arch.lifecycle.MutableLiveData\nimport com.lxm.module_library.base.BaseViewModel\nimport com.lxm.module_library.helper.RxHelper\nimport com.lxm.wanandroid.repository.model.*\nimport com.lxm.wanandroid.repository.remote.httpClient.RetrofitClient\nimport io.reactivex.functions.Consumer\n\nclass ProjectViewModel : BaseViewModel() {\n\n    var mPage = 0\n    val pagedList = MutableLiveData<HttpResponse<ArticleResponseBody<ArticleBean>>>()\n    val loadStatus by lazy {\n        MutableLiveData<Resource<String>>()\n    }\n\n    fun getProjects(): Listing<HttpResponse<ArticleResponseBody<ArticleBean>>> {\n        loadStatus.postValue(Resource.loading())\n        val subscribe = RetrofitClient.getInstance(RetrofitClient.WAN_BASE_URL).getProjectList(mPage)\n            .compose(RxHelper.rxSchedulerHelper())\n            .subscribe(Consumer<HttpResponse<ArticleResponseBody<ArticleBean>>> {\n                if(it.data != null){\n                    loadStatus.postValue(Resource.success())\n                    pagedList.value = it\n                }else{\n                    loadStatus.postValue(Resource.error())\n                }\n\n            }, Consumer<Throwable> {\n                if (mPage > 0) {\n                    mPage--\n                }\n                loadStatus.postValue(Resource.error())\n            })\n        addDisposable(subscribe)\n        return Listing(pagedList,loadStatus)\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/lxm/wanandroid/viewmodel/TreeViewModel.kt",
    "content": "package com.lxm.wanandroid.viewmodel\n\nimport android.arch.lifecycle.MutableLiveData\nimport com.lxm.module_library.base.BaseViewModel\nimport com.lxm.module_library.helper.RxHelper\nimport com.lxm.wanandroid.repository.model.Resource\nimport com.lxm.wanandroid.repository.model.TreeBean\nimport com.lxm.wanandroid.repository.remote.httpClient.RetrofitClient\n\nclass TreeViewModel : BaseViewModel() {\n    private val treeList = MutableLiveData<List<TreeBean>>()\n    val loadStatus by lazy {\n        MutableLiveData<Resource<String>>()\n    }\n    fun getTrees(): MutableLiveData<List<TreeBean>> {\n        RetrofitClient.getInstance(RetrofitClient.WAN_BASE_URL).getTrees()\n            .compose(RxHelper.rxSchedulerHelper())\n            .subscribe({\n                treeList.postValue(it.data)\n            }, {\n                loadStatus.postValue(Resource.error())\n            })\n        return treeList\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/lxm/wanandroid/viewmodel/WelfareModelView.kt",
    "content": "package com.lxm.wanandroid.viewmodel\n\nimport android.arch.lifecycle.MutableLiveData\nimport com.lxm.module_library.base.BaseViewModel\nimport com.lxm.module_library.helper.RxHelper\nimport com.lxm.wanandroid.repository.model.Resource\nimport com.lxm.wanandroid.repository.model.WelfareResponse\nimport com.lxm.wanandroid.repository.remote.httpClient.RetrofitClient\nconst val PAGE_SIZE = 20\nclass WelfareModelView : BaseViewModel() {\n\n    var mPage = 1\n\n    val loadStatus by lazy {\n        MutableLiveData<Resource<String>>()\n    }\n    fun getWelfare(): MutableLiveData<WelfareResponse> {\n        val welfare = MutableLiveData<WelfareResponse>()\n        RetrofitClient.getInstance(RetrofitClient.GAN_BASE_URL).getWelfare(\"福利\",PAGE_SIZE,mPage)\n            .compose(RxHelper.rxSchedulerHelper())\n            .subscribe({\n                welfare.postValue(it)\n            }, {\n                loadStatus.postValue(Resource.error())\n            })\n        return welfare\n    }\n}\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_launcher_background.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<vector\n        xmlns:android=\"http://schemas.android.com/apk/res/android\"\n        android:height=\"108dp\"\n        android:width=\"108dp\"\n        android:viewportHeight=\"108\"\n        android:viewportWidth=\"108\">\n    <path android:fillColor=\"#008577\"\n          android:pathData=\"M0,0h108v108h-108z\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M9,0L9,108\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M19,0L19,108\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M29,0L29,108\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M39,0L39,108\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M49,0L49,108\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M59,0L59,108\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M69,0L69,108\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M79,0L79,108\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M89,0L89,108\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M99,0L99,108\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M0,9L108,9\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M0,19L108,19\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M0,29L108,29\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M0,39L108,39\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M0,49L108,49\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M0,59L108,59\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M0,69L108,69\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M0,79L108,79\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M0,89L108,89\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M0,99L108,99\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M19,29L89,29\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M19,39L89,39\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M19,49L89,49\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M19,59L89,59\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M19,69L89,69\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M19,79L89,79\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M29,19L29,89\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M39,19L39,89\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M49,19L49,89\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M59,19L59,89\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M69,19L69,89\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n    <path android:fillColor=\"#00000000\" android:pathData=\"M79,19L79,89\"\n          android:strokeColor=\"#33FFFFFF\" android:strokeWidth=\"0.8\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable/process_bg.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layer-list xmlns:android=\"http://schemas.android.com/apk/res/android\" >\n\n    <!-- 背景  gradient是渐变,corners定义的是圆角 -->\n    <item android:id=\"@android:id/background\">\n        <shape>\n            <corners android:radius=\"10dp\" />\n\n            <solid android:color=\"#00ffffff\" />\n        </shape>\n    </item>\n    <!-- 第二条进度条颜色 -->\n    <item android:id=\"@android:id/secondaryProgress\">\n        <clip>\n            <shape>\n                <corners android:radius=\"10dip\" />\n\n                <solid android:color=\"#00ffffff\" />\n            </shape>\n        </clip>\n    </item>\n    <!-- 进度条 -->\n    <item android:id=\"@android:id/progress\">\n        <clip>\n            <shape>\n                <corners android:radius=\"10dip\" />\n                <gradient\n                    android:angle=\"180\"\n                    android:endColor=\"#FFFFFF\"\n                    android:startColor=\"#f00\" />\n            </shape>\n        </clip>\n    </item>\n\n</layer-list>"
  },
  {
    "path": "app/src/main/res/drawable/selector_bg_tree_tag.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<selector xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <item android:state_pressed=\"false\">\n        <shape android:shape=\"rectangle\">\n            <solid android:color=\"@color/colorTheme\" />\n            <corners android:radius=\"15dp\" />\n            <padding android:bottom=\"7dp\" android:left=\"16dp\" android:right=\"16dp\" android:top=\"7dp\" />\n        </shape>\n    </item>\n    <item android:state_pressed=\"true\">\n        <shape>\n            <corners android:radius=\"15dp\" />\n            <padding android:bottom=\"7dp\" android:left=\"16dp\" android:right=\"16dp\" android:top=\"7dp\" />\n            <solid android:color=\"@color/colorSmallRed\" />\n        </shape>\n    </item>\n</selector>"
  },
  {
    "path": "app/src/main/res/drawable/selector_collect_check.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<selector xmlns:android=\"http://schemas.android.com/apk/res/android\">\n\n    <item android:drawable=\"@drawable/ic_collect\" android:state_checked=\"true\" />\n    <item android:drawable=\"@drawable/ic_un_collect\" />\n\n</selector>"
  },
  {
    "path": "app/src/main/res/drawable-v24/ic_launcher_foreground.xml",
    "content": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n        xmlns:aapt=\"http://schemas.android.com/aapt\"\n        android:width=\"108dp\"\n        android:height=\"108dp\"\n        android:viewportHeight=\"108\"\n        android:viewportWidth=\"108\">\n    <path\n            android:fillType=\"evenOdd\"\n            android:pathData=\"M32,64C32,64 38.39,52.99 44.13,50.95C51.37,48.37 70.14,49.57 70.14,49.57L108.26,87.69L108,109.01L75.97,107.97L32,64Z\"\n            android:strokeColor=\"#00000000\"\n            android:strokeWidth=\"1\">\n        <aapt:attr name=\"android:fillColor\">\n            <gradient\n                    android:endX=\"78.5885\"\n                    android:endY=\"90.9159\"\n                    android:startX=\"48.7653\"\n                    android:startY=\"61.0927\"\n                    android:type=\"linear\">\n                <item\n                        android:color=\"#44000000\"\n                        android:offset=\"0.0\"/>\n                <item\n                        android:color=\"#00000000\"\n                        android:offset=\"1.0\"/>\n            </gradient>\n        </aapt:attr>\n    </path>\n    <path\n            android:fillColor=\"#FFFFFF\"\n            android:fillType=\"nonZero\"\n            android:pathData=\"M66.94,46.02L66.94,46.02C72.44,50.07 76,56.61 76,64L32,64C32,56.61 35.56,50.11 40.98,46.06L36.18,41.19C35.45,40.45 35.45,39.3 36.18,38.56C36.91,37.81 38.05,37.81 38.78,38.56L44.25,44.05C47.18,42.57 50.48,41.71 54,41.71C57.48,41.71 60.78,42.57 63.68,44.05L69.11,38.56C69.84,37.81 70.98,37.81 71.71,38.56C72.44,39.3 72.44,40.45 71.71,41.19L66.94,46.02ZM62.94,56.92C64.08,56.92 65,56.01 65,54.88C65,53.76 64.08,52.85 62.94,52.85C61.8,52.85 60.88,53.76 60.88,54.88C60.88,56.01 61.8,56.92 62.94,56.92ZM45.06,56.92C46.2,56.92 47.13,56.01 47.13,54.88C47.13,53.76 46.2,52.85 45.06,52.85C43.92,52.85 43,53.76 43,54.88C43,56.01 43.92,56.92 45.06,56.92Z\"\n            android:strokeColor=\"#00000000\"\n            android:strokeWidth=\"1\"/>\n</vector>\n"
  },
  {
    "path": "app/src/main/res/layout/activity_collection.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout\n        android:background=\"@color/colorSubtitle\"\n        xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n        xmlns:android=\"http://schemas.android.com/apk/res/android\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:orientation=\"vertical\">\n\n    <android.support.v7.widget.Toolbar\n            app:navigationIcon=\"@drawable/icon_back\"\n            android:id=\"@+id/toolbar\"\n            android:background=\"@color/colorTheme\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\">\n\n        <TextView\n                android:textSize=\"20sp\"\n                android:id=\"@+id/tv_title\"\n                android:textColor=\"@color/white\"\n                android:text=\"我的收藏\"\n                android:layout_gravity=\"center\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"/>\n\n    </android.support.v7.widget.Toolbar>\n\n    <FrameLayout\n            android:id=\"@+id/content\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"match_parent\"/>\n</LinearLayout>"
  },
  {
    "path": "app/src/main/res/layout/activity_login.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout\n        android:background=\"@color/colorSubtitle\"\n        xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n        xmlns:android=\"http://schemas.android.com/apk/res/android\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:orientation=\"vertical\">\n\n    <android.support.v7.widget.Toolbar\n            app:navigationIcon=\"@drawable/icon_back\"\n            android:id=\"@+id/toolbar\"\n            android:background=\"@color/colorTheme\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\">\n\n        <TextView\n                android:textSize=\"20sp\"\n                android:id=\"@+id/tv_title\"\n                android:textColor=\"@color/white\"\n                android:text=\"Login\"\n                android:layout_gravity=\"center\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"/>\n\n    </android.support.v7.widget.Toolbar>\n\n    <com.lxm.module_library.materialLogin.MaterialLoginView\n            android:id=\"@+id/login\"\n            app:registerIcon=\"@drawable/ic_person_add_white_24dp\"\n            app:loginView=\"@layout/custom_login_view\"\n            app:registerView=\"@layout/custom_register_view\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"match_parent\"/>\n</LinearLayout>"
  },
  {
    "path": "app/src/main/res/layout/activity_main.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<android.support.v4.widget.DrawerLayout\n        xmlns:android=\"http://schemas.android.com/apk/res/android\"\n        xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n        xmlns:tools=\"http://schemas.android.com/tools\"\n        android:id=\"@+id/drawerLayout\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        tools:context=\".MainActivity\"\n        tools:openDrawer=\"start\">\n\n    <include\n            android:id=\"@+id/mainContent\"\n            layout=\"@layout/main_content\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"match_parent\"/>\n\n    <android.support.design.widget.NavigationView\n            android:id=\"@+id/navigationView\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"match_parent\"\n            android:layout_gravity=\"start\"\n            android:fitsSystemWindows=\"true\"\n            app:headerLayout=\"@layout/drawer_header_layout\"\n            app:itemIconTint=\"@color/colorTheme\"\n            app:itemTextColor=\"@color/black\"\n            app:menu=\"@menu/navigation\"/>\n\n</android.support.v4.widget.DrawerLayout>"
  },
  {
    "path": "app/src/main/res/layout/activity_show_image.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:background=\"#000000\">\n\n    <android.support.v4.view.ViewPager\n        android:id=\"@+id/viewpager\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\" />\n\n    <TextView\n        android:id=\"@+id/viewpager_text\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_alignParentBottom=\"true\"\n        android:layout_centerHorizontal=\"true\"\n        android:layout_marginBottom=\"25dp\"\n        android:textColor=\"#fff\"\n        android:textSize=\"14sp\" />\n\n</RelativeLayout>"
  },
  {
    "path": "app/src/main/res/layout/activity_web_view.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:orientation=\"vertical\"\n    tools:context=\".utils.webview.WebViewActivity\">\n\n    <!--播放全屏视频时用-->\n    <FrameLayout\n        android:id=\"@+id/video_fullView\"\n        android:layout_width=\"fill_parent\"\n        android:layout_height=\"fill_parent\"\n        android:visibility=\"gone\" />\n\n    <LinearLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:orientation=\"vertical\">\n\n        <android.support.v7.widget.Toolbar xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n            android:id=\"@+id/title_tool_bar\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"?attr/actionBarSize\"\n            android:background=\"@color/colorTheme\"\n            app:contentInsetStartWithNavigation=\"0dp\"\n            app:layout_scrollFlags=\"enterAlways|scroll\"\n            app:navigationContentDescription=\"返回\"\n            app:navigationIcon=\"@drawable/icon_back\"\n            app:popupTheme=\"@style/ThemeOverlay.AppCompat.Light\"\n            app:theme=\"@style/ToolbarStyle\">\n\n            <TextView\n                android:id=\"@+id/tv_gun_title\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:ellipsize=\"marquee\"\n                android:singleLine=\"true\"\n                android:textColor=\"@color/colorWhite\"\n                android:textSize=\"18sp\"\n                android:visibility=\"visible\"\n                tools:text=\"@string/app_name\" />\n\n        </android.support.v7.widget.Toolbar>\n\n        <RelativeLayout\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"match_parent\">\n\n            <WebView\n                android:id=\"@+id/webview_detail\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"match_parent\"\n                android:scrollbarSize=\"3dp\"\n                android:scrollbarThumbVertical=\"@color/tabBackground\" />\n\n            <ProgressBar\n                android:id=\"@+id/pb_progress\"\n                style=\"?android:attr/progressBarStyleHorizontal\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"3dp\"\n                android:layout_alignParentTop=\"true\"\n                android:max=\"100\"\n                android:progress=\"0\"\n                android:progressDrawable=\"@drawable/process_bg\"\n                android:visibility=\"gone\" />\n\n        </RelativeLayout>\n    </LinearLayout>\n</RelativeLayout>\n"
  },
  {
    "path": "app/src/main/res/layout/article_banner.xml",
    "content": "<FrameLayout\n        xmlns:android=\"http://schemas.android.com/apk/res/android\"\n        xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n        android:layout_height=\"match_parent\"\n        android:layout_width=\"match_parent\">\n\n    <com.zhouwei.mzbanner.MZBannerView\n            android:id=\"@+id/banner\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"180dp\"\n            app:open_mz_mode=\"true\"\n            app:canLoop=\"true\"\n            app:indicatorAlign=\"center\"\n            app:indicatorPaddingLeft=\"10dp\"\n    />\n</FrameLayout>"
  },
  {
    "path": "app/src/main/res/layout/article_fragment.xml",
    "content": "<FrameLayout\n        xmlns:android=\"http://schemas.android.com/apk/res/android\"\n        android:layout_height=\"match_parent\"\n        android:layout_width=\"match_parent\">\n\n    <android.support.v4.widget.SwipeRefreshLayout\n            android:id=\"@+id/swipeLayout\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"match_parent\">\n\n        <com.lxm.module_library.xrecycleview.XRecyclerView\n                android:background=\"#EEEEEE\"\n                android:id=\"@+id/recyclerView\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"match_parent\"\n                android:scrollbarAlwaysDrawVerticalTrack=\"true\"\n                android:scrollbarFadeDuration=\"1\"\n                android:scrollbarSize=\"4dp\"\n                android:scrollbars=\"vertical\"/>\n\n    </android.support.v4.widget.SwipeRefreshLayout>\n\n</FrameLayout>"
  },
  {
    "path": "app/src/main/res/layout/category_activity.xml",
    "content": "<FrameLayout\n        xmlns:android=\"http://schemas.android.com/apk/res/android\"\n        android:layout_height=\"match_parent\"\n        android:layout_width=\"match_parent\">\n\n    <android.support.v4.widget.SwipeRefreshLayout\n            android:id=\"@+id/swipeLayout\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"match_parent\">\n\n        <com.lxm.module_library.xrecycleview.XRecyclerView\n                android:id=\"@+id/recyclerView\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"match_parent\"\n                android:scrollbarAlwaysDrawVerticalTrack=\"true\"\n                android:scrollbarFadeDuration=\"1\"\n                android:scrollbarSize=\"4dp\"\n                android:scrollbars=\"vertical\"/>\n\n    </android.support.v4.widget.SwipeRefreshLayout>\n\n</FrameLayout>"
  },
  {
    "path": "app/src/main/res/layout/drawer_header_layout.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<android.support.constraint.ConstraintLayout\n        xmlns:android=\"http://schemas.android.com/apk/res/android\"\n        xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"180dp\"\n        android:background=\"@color/colorTheme\">\n\n    <de.hdodenhof.circleimageview.CircleImageView\n            app:civ_border_width=\"2dp\"\n            app:civ_border_color=\"#FFFFFF\"\n            android:src=\"@drawable/ic_photo\"\n            android:id=\"@+id/ivHeadView\"\n            android:layout_width=\"65dp\"\n            android:layout_height=\"65dp\"\n            app:layout_constraintBottom_toBottomOf=\"parent\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toTopOf=\"parent\"/>\n\n    <TextView\n            android:id=\"@+id/tvUserName\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:text=\"username\"\n            android:textSize=\"16sp\"\n            android:textColor=\"@android:color/white\"\n            android:textStyle=\"normal\"\n            android:layout_marginTop=\"8dp\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toBottomOf=\"@+id/ivHeadView\"/>\n\n\n</android.support.constraint.ConstraintLayout>"
  },
  {
    "path": "app/src/main/res/layout/item_article.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout\n        xmlns:tools=\"http://schemas.android.com/tools\"\n        xmlns:android=\"http://schemas.android.com/apk/res/android\"\n        android:layout_height=\"wrap_content\"\n        android:paddingLeft=\"6dp\"\n        android:paddingRight=\"6dp\"\n        android:paddingBottom=\"6dp\"\n        android:layout_width=\"match_parent\">\n\n    <android.support.v7.widget.CardView\n            android:elevation=\"8dp\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:background=\"?attr/selectableItemBackground\">\n\n        <LinearLayout\n                android:id=\"@+id/ll_all\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:background=\"?attr/selectableItemBackgroundBorderless\"\n                android:orientation=\"vertical\"\n                android:paddingTop=\"12dp\">\n\n            <ImageView\n                    android:layout_alignParentLeft=\"true\"\n                    android:src=\"@drawable/ic_article_new\"\n                    android:id=\"@+id/iv_new\"\n                    android:layout_width=\"20dp\"\n                    android:layout_height=\"20dp\"\n                    android:layout_gravity=\"center_vertical\"\n                    android:layout_marginStart=\"5dp\"\n                    android:scaleType=\"centerCrop\"/>\n\n            <LinearLayout\n                    android:id=\"@+id/ll_middle\"\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_marginLeft=\"10dp\"\n                    android:layout_marginRight=\"10dp\"\n                    android:orientation=\"horizontal\">\n\n                <TextView\n                        tools:text=\"我是一堆内容\"\n                        android:id=\"@+id/tv_title\"\n                        android:layout_width=\"0dp\"\n                        android:layout_height=\"wrap_content\"\n                        android:layout_gravity=\"center_vertical\"\n                        android:layout_weight=\"1\"\n                        android:lineSpacingExtra=\"4dp\"\n                        android:textColor=\"@color/colorContent\"\n                        android:textSize=\"15sp\"/>\n\n                <ImageView\n                        android:id=\"@+id/iv_image\"\n                        android:layout_width=\"60dp\"\n                        android:layout_height=\"80dp\"\n                        android:layout_gravity=\"center_vertical\"\n                        android:layout_marginStart=\"5dp\"\n                        android:background=\"@color/colorLine\"\n                        android:scaleType=\"centerCrop\"\n                        android:visibility=\"visible\"/>\n\n            </LinearLayout>\n\n            <RelativeLayout\n                    android:layout_alignBottom=\"@+id/ll_middle\"\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_marginTop=\"8dp\"\n                    android:layout_marginBottom=\"6dp\"\n                    android:paddingLeft=\"12dp\"\n                    android:paddingRight=\"12dp\">\n\n                <TextView\n                        tools:text=\"我是作者\"\n                        android:id=\"@+id/tv_author\"\n                        android:layout_width=\"wrap_content\"\n                        android:layout_height=\"wrap_content\"\n                        android:textColor=\"@color/colorSubtitle\"\n                        android:textSize=\"12sp\"/>\n\n                <TextView\n                        android:id=\"@+id/tv_content_type\"\n                        android:layout_width=\"wrap_content\"\n                        android:layout_height=\"wrap_content\"\n                        android:layout_toRightOf=\"@+id/tv_author\"\n                        android:textColor=\"@color/colorSubtitle\"\n                        android:textSize=\"12sp\"\n                        android:visibility=\"gone\"/>\n\n                <TextView\n                        tools:text=\"我是发表时间\"\n                        android:id=\"@+id/tv_time\"\n                        android:layout_width=\"wrap_content\"\n                        android:layout_height=\"wrap_content\"\n                        android:layout_alignParentRight=\"true\"\n                        android:textColor=\"@color/colorSubtitle\"\n                        android:textSize=\"12sp\"/>\n\n            </RelativeLayout>\n\n        </LinearLayout>\n    </android.support.v7.widget.CardView>\n\n</RelativeLayout>\n"
  },
  {
    "path": "app/src/main/res/layout/item_banner.xml",
    "content": "<FrameLayout\n        xmlns:android=\"http://schemas.android.com/apk/res/android\"\n        android:layout_height=\"match_parent\"\n        android:layout_width=\"match_parent\">\n\n    <ImageView\n            android:id=\"@+id/banner_image\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"match_parent\"\n            android:scaleType=\"centerInside\"\n    />\n</FrameLayout>"
  },
  {
    "path": "app/src/main/res/layout/item_image_view_pager.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<FrameLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"fill_parent\"\n    android:layout_height=\"fill_parent\"\n    android:background=\"#ff000000\">\n\n    <uk.co.senab.photoview.PhotoView\n        android:id=\"@+id/zoom_image_view\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\" />\n\n    <ProgressBar\n        android:id=\"@+id/loading\"\n        android:layout_width=\"30dp\"\n        android:layout_height=\"30dp\"\n        android:layout_gravity=\"center\" />\n\n</FrameLayout>"
  },
  {
    "path": "app/src/main/res/layout/item_tree.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<android.support.constraint.ConstraintLayout\n        xmlns:android=\"http://schemas.android.com/apk/res/android\"\n        xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n        xmlns:tools=\"http://schemas.android.com/tools\"\n        android:id=\"@+id/ll_item_top\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:orientation=\"vertical\"\n        android:paddingLeft=\"8dp\"\n        android:paddingTop=\"8dp\"\n        android:paddingRight=\"8dp\"\n        android:paddingBottom=\"16dp\">\n\n    <TextView\n            android:layout_marginStart=\"6dp\"\n            android:id=\"@+id/tv_tree_title\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:textColor=\"@color/colorContent\"\n            android:textSize=\"17sp\"\n            android:textStyle=\"bold\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toTopOf=\"parent\"\n            tools:text=\"title\"/>\n\n    <com.zhy.view.flowlayout.TagFlowLayout\n            android:id=\"@+id/fl_tree\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginStart=\"15dp\"\n            android:layout_marginTop=\"10dp\"\n            android:layout_marginEnd=\"10dp\"\n            app:itemSpacing=\"8dp\"\n            app:layout_constraintEnd_toEndOf=\"parent\"\n            app:layout_constraintStart_toStartOf=\"parent\"\n            app:layout_constraintTop_toBottomOf=\"@+id/tv_tree_title\"\n            app:lineSpacing=\"8dp\"/>\n</android.support.constraint.ConstraintLayout>\n"
  },
  {
    "path": "app/src/main/res/layout/item_tree_tag.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<TextView xmlns:android=\"http://schemas.android.com/apk/res/android\"\n          xmlns:tools=\"http://schemas.android.com/tools\"\n          android:id=\"@+id/tv_tag\"\n          android:layout_width=\"wrap_content\"\n          android:layout_height=\"wrap_content\"\n          android:background=\"@drawable/selector_bg_tree_tag\"\n          android:textColor=\"@color/colorWhite\"\n          android:textSize=\"12sp\"\n          android:padding=\"8dp\"\n          tools:text=\"title\"/>"
  },
  {
    "path": "app/src/main/res/layout/item_view.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout\n        xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n        xmlns:tools=\"http://schemas.android.com/tools\"\n        xmlns:android=\"http://schemas.android.com/apk/res/android\"\n        android:layout_height=\"wrap_content\"\n        android:layout_width=\"match_parent\"\n        android:paddingLeft=\"6dp\"\n        android:paddingRight=\"6dp\"\n        android:paddingBottom=\"6dp\"\n>\n\n    <android.support.design.card.MaterialCardView\n            style=\"@style/AppTheme\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            app:cardCornerRadius=\"3dp\">\n\n        <android.support.constraint.ConstraintLayout\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:foreground=\"?attr/selectableItemBackgroundBorderless\"\n                android:paddingBottom=\"8dp\"\n                android:paddingRight=\"8dp\"\n                android:paddingTop=\"8dp\">\n\n            <RelativeLayout\n                    android:id=\"@+id/rl_header\"\n                    android:layout_width=\"match_parent\"\n                    android:layout_height=\"wrap_content\"\n                    app:layout_constraintStart_toStartOf=\"parent\"\n                    app:layout_constraintTop_toTopOf=\"parent\">\n\n                <ImageView\n                        android:src=\"@drawable/ic_article_new\"\n                        android:id=\"@+id/iv_new\"\n                        android:layout_width=\"40dp\"\n                        android:layout_height=\"25dp\"\n                />\n\n                <TextView\n                        android:id=\"@+id/tv_tag_name\"\n                        android:layout_width=\"wrap_content\"\n                        android:layout_height=\"wrap_content\"\n                        android:layout_alignParentEnd=\"true\"\n                        android:background=\"?selectableItemBackgroundBorderless\"\n                        android:textSize=\"13sp\"\n                        app:layout_constraintEnd_toEndOf=\"parent\"\n                        tools:text=\"技术博客\"/>\n\n            </RelativeLayout>\n\n            <ImageView\n                    android:id=\"@+id/iv_image\"\n                    android:layout_width=\"60dp\"\n                    android:layout_height=\"78dp\"\n                    android:layout_marginStart=\"8dp\"\n                    android:scaleType=\"centerCrop\"\n                    app:layout_constraintStart_toStartOf=\"parent\"\n                    app:layout_constraintTop_toBottomOf=\"@+id/rl_header\"\n                    tools:background=\"@color/colorLine\"/>\n\n            <TextView\n                    android:id=\"@+id/tv_title\"\n                    android:layout_width=\"0dp\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_marginStart=\"8dp\"\n                    android:layout_marginTop=\"8dp\"\n                    android:ellipsize=\"end\"\n                    android:lineSpacingExtra=\"4dp\"\n                    android:maxLines=\"2\"\n                    android:textSize=\"14sp\"\n                    app:layout_constraintEnd_toStartOf=\"@+id/iv_collect\"\n                    app:layout_constraintStart_toEndOf=\"@+id/iv_image\"\n                    app:layout_constraintTop_toTopOf=\"@+id/iv_image\"\n                    tools:text=\"内容展示内容展示内容展示内容展示内容展示内容展示内容展示内容展示内容展示内容展示内容展示\"/>\n\n            <CheckBox\n                    android:background=\"?selectableItemBackgroundBorderless\"\n                    android:button=\"@drawable/selector_collect_check\"\n                    app:layout_constraintStart_toEndOf=\"@+id/tv_title\"\n                    app:layout_constraintTop_toTopOf=\"@+id/tv_title\"\n                    app:layout_constraintEnd_toEndOf=\"parent\"\n                    android:src=\"@drawable/ic_un_collect\"\n                    android:id=\"@+id/iv_collect\"\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n            />\n            <TextView\n                    android:id=\"@+id/tv_time\"\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_marginTop=\"13dp\"\n                    android:textSize=\"11sp\"\n                    app:layout_constraintBottom_toBottomOf=\"parent\"\n                    app:layout_constraintEnd_toEndOf=\"parent\"\n                    tools:text=\"日期\"/>\n\n            <TextView\n                    android:id=\"@+id/tv_author\"\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:textSize=\"11sp\"\n                    app:layout_constraintStart_toStartOf=\"@+id/tv_title\"\n                    app:layout_constraintTop_toBottomOf=\"@+id/tv_title\"\n                    app:layout_constraintBottom_toBottomOf=\"parent\"\n                    tools:text=\"author\"/>\n\n\n        </android.support.constraint.ConstraintLayout>\n    </android.support.design.card.MaterialCardView>\n</RelativeLayout>"
  },
  {
    "path": "app/src/main/res/layout/item_view_welfare.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout\n        xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n        xmlns:tools=\"http://schemas.android.com/tools\"\n        xmlns:android=\"http://schemas.android.com/apk/res/android\"\n        android:layout_width=\"match_parent\"\n        android:padding=\"6dp\"\n        android:layout_height=\"wrap_content\">\n\n    <android.support.design.card.MaterialCardView\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:elevation=\"6dp\"\n            android:background=\"@color/colorWhite\"\n            app:cardCornerRadius=\"8dp\"\n            tools:targetApi=\"lollipop\">\n\n        <ImageView\n                android:id=\"@+id/iv_welfare\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"250dp\"\n                android:scaleType=\"centerCrop\"/>\n    </android.support.design.card.MaterialCardView>\n</LinearLayout>\n"
  },
  {
    "path": "app/src/main/res/layout/main_content.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n              xmlns:tl=\"http://schemas.android.com/apk/res-auto\"\n              xmlns:tools=\"http://schemas.android.com/tools\"\n              android:layout_width=\"match_parent\"\n              android:layout_height=\"match_parent\"\n              android:orientation=\"vertical\"\n              tools:context=\".MainActivity\">\n\n    <android.support.v7.widget.Toolbar\n            android:id=\"@+id/toolbar\"\n            android:background=\"@color/colorTheme\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\">\n\n        <de.hdodenhof.circleimageview.CircleImageView\n                android:src=\"@drawable/ic_photo\"\n                android:id=\"@+id/iv_photo\"\n                android:layout_width=\"36dp\"\n                android:layout_height=\"36dp\"/>\n\n        <com.flyco.tablayout.SlidingTabLayout\n                android:paddingLeft=\"10dp\"\n                android:id=\"@+id/tablayout\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"58dp\"\n                tl:tl_indicator_color=\"#FFFFFF\"\n                tl:tl_indicator_height=\"1.5dp\"\n                tl:tl_indicator_width_equal_title=\"true\"\n                tl:tl_tab_padding=\"6dp\"\n                tl:tl_textSelectColor=\"#FFFFFF\"\n                tl:tl_textUnselectColor=\"#66FFFFFF\"\n                tl:tl_underline_color=\"#1AFFFFFF\"\n                tl:tl_underline_height=\"1dp\"/>\n\n    </android.support.v7.widget.Toolbar>\n\n\n    <android.support.v4.view.ViewPager\n            android:id=\"@+id/view_pager\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"0dp\"\n            android:layout_weight=\"1\"/>\n</LinearLayout>"
  },
  {
    "path": "app/src/main/res/layout/tree_fragment.xml",
    "content": "<FrameLayout\n        xmlns:android=\"http://schemas.android.com/apk/res/android\"\n        android:layout_height=\"match_parent\"\n        android:layout_width=\"match_parent\">\n\n    <android.support.v4.widget.SwipeRefreshLayout\n            android:id=\"@+id/swipeLayout\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"match_parent\">\n\n\n        <com.lxm.module_library.xrecycleview.XRecyclerView\n                android:background=\"@color/colorKnowledge_bg\"\n                android:id=\"@+id/recyclerView\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"match_parent\"\n                android:scrollbarAlwaysDrawVerticalTrack=\"true\"\n                android:scrollbarFadeDuration=\"1\"\n                android:scrollbarSize=\"4dp\"\n                android:scrollbars=\"vertical\"/>\n\n    </android.support.v4.widget.SwipeRefreshLayout>\n\n</FrameLayout>"
  },
  {
    "path": "app/src/main/res/menu/main.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<menu xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\">\n    <item\n        android:id=\"@+id/action_search\"\n        android:icon=\"@drawable/ic_main_search\"\n        android:orderInCategory=\"100\"\n        android:title=\"搜索\"\n        app:showAsAction=\"always\" />\n</menu>"
  },
  {
    "path": "app/src/main/res/menu/navigation.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<menu xmlns:android=\"http://schemas.android.com/apk/res/android\">\n\n    <item\n            android:id=\"@+id/colletion\"\n            android:icon=\"@drawable/ic_collection\"\n            android:title=\"我的收藏\"/>\n\n    <item\n            android:id=\"@+id/about\"\n            android:icon=\"@drawable/ic_about\"\n            android:title=\"关于\"/>\n    <item\n            android:id=\"@+id/accout\"\n            android:icon=\"@drawable/ic_login_menu\"\n            android:title=\"登录\"/>\n</menu>"
  },
  {
    "path": "app/src/main/res/menu/webview_menu.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<menu xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\">\n\n    <item\n        android:id=\"@+id/actionbar_share\"\n        android:orderInCategory=\"100\"\n        android:title=\"@string/actionbar_webview_share\"\n        app:showAsAction=\"never\" />\n\n    <item\n        android:id=\"@+id/actionbar_webview_refresh\"\n        android:orderInCategory=\"100\"\n        android:title=\"@string/actionbar_webview_refresh\"\n        app:showAsAction=\"never\" />\n\n    <item\n        android:id=\"@+id/actionbar_cope\"\n        android:orderInCategory=\"100\"\n        android:title=\"@string/actionbar_webview_cope\"\n        app:showAsAction=\"never\" />\n\n    <item\n        android:id=\"@+id/actionbar_open\"\n        android:orderInCategory=\"100\"\n        android:title=\"@string/actionbar_webview_open\"\n        app:showAsAction=\"never\" />\n</menu>"
  },
  {
    "path": "app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<adaptive-icon xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <background android:drawable=\"@drawable/ic_launcher_background\"/>\n    <foreground android:drawable=\"@drawable/ic_launcher_foreground\"/>\n</adaptive-icon>"
  },
  {
    "path": "app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<adaptive-icon xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <background android:drawable=\"@drawable/ic_launcher_background\"/>\n    <foreground android:drawable=\"@drawable/ic_launcher_foreground\"/>\n</adaptive-icon>"
  },
  {
    "path": "app/src/main/res/values/attrs_circle_view.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <declare-styleable name=\"circletextview\">\n        <attr name=\"circle_color\" format=\"color\"/>\n        <attr name=\"circle_text_color\" format=\"color\"/>\n        <attr name=\"random_color\" format=\"boolean\"/>\n        <attr name=\"sub_first_character\" format=\"boolean\"/>\n    </declare-styleable>\n\n    <declare-styleable name=\"TextViewBorder\">\n        <attr name=\"tvborderColor\" format=\"color\" />\n        <attr name=\"tvBorderWidth\" format=\"integer\" />\n    </declare-styleable>\n</resources>"
  },
  {
    "path": "app/src/main/res/values/colors.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <color name=\"colorPrimary\">#008577</color>\n    <color name=\"colorPrimaryDark\">#00574B</color>\n    <color name=\"colorAccent\">#D81B60</color>\n\n    <!-- 主题色-->\n    <color name=\"colorTheme\">#343434</color>\n    <color name=\"color_page_bg\">#F1F3F4</color>\n    <color name=\"colorSmallRed\">#faebeb</color>\n    <color name=\"colorKnowledge_bg\">#FFFAFA</color>\n\n\n\n</resources>\n"
  },
  {
    "path": "app/src/main/res/values/strings.xml",
    "content": "<resources>\n    <string name=\"app_name\">WanAndroidKotlin</string>\n    <string name=\"navigation_open\">打开</string>\n    <string name=\"navigation_close\">关闭</string>\n</resources>\n"
  },
  {
    "path": "app/src/main/res/values/styles.xml",
    "content": "<resources>\n\n    <!-- Base application theme. -->\n    <style name=\"AppTheme\" parent=\"Theme.AppCompat.Light.NoActionBar\">\n        <!-- Customize your theme here. -->\n        <item name=\"colorPrimary\">@color/colorTheme</item>\n        <item name=\"colorPrimaryDark\">@color/colorTheme</item>\n        <item name=\"colorAccent\">@color/colorTheme</item>\n    </style>\n\n</resources>\n"
  },
  {
    "path": "app/src/test/java/com/lxm/wanandroid/ExampleUnitTest.kt",
    "content": "package com.lxm.wanandroid\n\nimport org.junit.Test\n\nimport org.junit.Assert.*\n\n/**\n * Example local unit test, which will execute on the development machine (host).\n *\n * See [testing documentation](http://d.android.com/tools/testing).\n */\nclass ExampleUnitTest {\n    @Test\n    fun addition_isCorrect() {\n        assertEquals(4, 2 + 2)\n    }\n}\n"
  },
  {
    "path": "build.gradle",
    "content": "// Top-level build file where you can add configuration options common to all sub-projects/modules.\n\nbuildscript {\n    ext.kotlin_version = '1.3.21'\n    repositories {\n        google()\n        jcenter()\n        maven { url 'https://jitpack.io' }\n    }\n    dependencies {\n        classpath 'com.android.tools.build:gradle:3.4.0'\n        classpath \"org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version\"\n        // NOTE: Do not place your application dependencies here; they belong\n        // in the individual module build.gradle files\n    }\n}\n\nallprojects {\n    repositories {\n        google()\n        jcenter()\n        maven { url 'https://jitpack.io' }\n    }\n}\n\ntask clean(type: Delete) {\n    delete rootProject.buildDir\n}\n\next{\n\n    retrofitVersion = '2.2.0'\n    okhttploggingVersion = '3.4.1'\n    okhttpVersion = '3.4.1'\n    rxjavaVersion = '2.0.1'\n    rxandroidVersion = '2.0.1'\n    rxbindingVersion = '2.0.0'\n    constraintVersion = '1.1.2'\n    butterknifeVwesion = '8.8.1'\n    glideVersion = '4.9.0'\n    glide_transformations = '3.0.1'\n}"
  },
  {
    "path": "gradle/wrapper/gradle-wrapper.properties",
    "content": "#Thu Jun 13 22:10:05 CST 2019\ndistributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-5.1.1-all.zip\n"
  },
  {
    "path": "gradle.properties",
    "content": "# Project-wide Gradle settings.\n# IDE (e.g. Android Studio) users:\n# Gradle settings configured through the IDE *will override*\n# any settings specified in this file.\n# For more details on how to configure your build environment visit\n# http://www.gradle.org/docs/current/userguide/build_environment.html\n# Specifies the JVM arguments used for the daemon process.\n# The setting is particularly useful for tweaking memory settings.\norg.gradle.jvmargs=-Xmx1536m\n# When configured, Gradle will run in incubating parallel mode.\n# This option should only be used with decoupled projects. More details, visit\n# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects\n# org.gradle.parallel=true\n# Kotlin code style for this project: \"official\" or \"obsolete\":\nkotlin.code.style=official\n"
  },
  {
    "path": "gradlew",
    "content": "#!/usr/bin/env sh\n\n##############################################################################\n##\n##  Gradle start up script for UN*X\n##\n##############################################################################\n\n# Attempt to set APP_HOME\n# Resolve links: $0 may be a link\nPRG=\"$0\"\n# Need this for relative symlinks.\nwhile [ -h \"$PRG\" ] ; do\n    ls=`ls -ld \"$PRG\"`\n    link=`expr \"$ls\" : '.*-> \\(.*\\)$'`\n    if expr \"$link\" : '/.*' > /dev/null; then\n        PRG=\"$link\"\n    else\n        PRG=`dirname \"$PRG\"`\"/$link\"\n    fi\ndone\nSAVED=\"`pwd`\"\ncd \"`dirname \\\"$PRG\\\"`/\" >/dev/null\nAPP_HOME=\"`pwd -P`\"\ncd \"$SAVED\" >/dev/null\n\nAPP_NAME=\"Gradle\"\nAPP_BASE_NAME=`basename \"$0\"`\n\n# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nDEFAULT_JVM_OPTS=\"\"\n\n# Use the maximum available, or set MAX_FD != -1 to use that value.\nMAX_FD=\"maximum\"\n\nwarn () {\n    echo \"$*\"\n}\n\ndie () {\n    echo\n    echo \"$*\"\n    echo\n    exit 1\n}\n\n# OS specific support (must be 'true' or 'false').\ncygwin=false\nmsys=false\ndarwin=false\nnonstop=false\ncase \"`uname`\" in\n  CYGWIN* )\n    cygwin=true\n    ;;\n  Darwin* )\n    darwin=true\n    ;;\n  MINGW* )\n    msys=true\n    ;;\n  NONSTOP* )\n    nonstop=true\n    ;;\nesac\n\nCLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar\n\n# Determine the Java command to use to start the JVM.\nif [ -n \"$JAVA_HOME\" ] ; then\n    if [ -x \"$JAVA_HOME/jre/sh/java\" ] ; then\n        # IBM's JDK on AIX uses strange locations for the executables\n        JAVACMD=\"$JAVA_HOME/jre/sh/java\"\n    else\n        JAVACMD=\"$JAVA_HOME/bin/java\"\n    fi\n    if [ ! -x \"$JAVACMD\" ] ; then\n        die \"ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nelse\n    JAVACMD=\"java\"\n    which java >/dev/null 2>&1 || die \"ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\nfi\n\n# Increase the maximum file descriptors if we can.\nif [ \"$cygwin\" = \"false\" -a \"$darwin\" = \"false\" -a \"$nonstop\" = \"false\" ] ; then\n    MAX_FD_LIMIT=`ulimit -H -n`\n    if [ $? -eq 0 ] ; then\n        if [ \"$MAX_FD\" = \"maximum\" -o \"$MAX_FD\" = \"max\" ] ; then\n            MAX_FD=\"$MAX_FD_LIMIT\"\n        fi\n        ulimit -n $MAX_FD\n        if [ $? -ne 0 ] ; then\n            warn \"Could not set maximum file descriptor limit: $MAX_FD\"\n        fi\n    else\n        warn \"Could not query maximum file descriptor limit: $MAX_FD_LIMIT\"\n    fi\nfi\n\n# For Darwin, add options to specify how the application appears in the dock\nif $darwin; then\n    GRADLE_OPTS=\"$GRADLE_OPTS \\\"-Xdock:name=$APP_NAME\\\" \\\"-Xdock:icon=$APP_HOME/media/gradle.icns\\\"\"\nfi\n\n# For Cygwin, switch paths to Windows format before running java\nif $cygwin ; then\n    APP_HOME=`cygpath --path --mixed \"$APP_HOME\"`\n    CLASSPATH=`cygpath --path --mixed \"$CLASSPATH\"`\n    JAVACMD=`cygpath --unix \"$JAVACMD\"`\n\n    # We build the pattern for arguments to be converted via cygpath\n    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`\n    SEP=\"\"\n    for dir in $ROOTDIRSRAW ; do\n        ROOTDIRS=\"$ROOTDIRS$SEP$dir\"\n        SEP=\"|\"\n    done\n    OURCYGPATTERN=\"(^($ROOTDIRS))\"\n    # Add a user-defined pattern to the cygpath arguments\n    if [ \"$GRADLE_CYGPATTERN\" != \"\" ] ; then\n        OURCYGPATTERN=\"$OURCYGPATTERN|($GRADLE_CYGPATTERN)\"\n    fi\n    # Now convert the arguments - kludge to limit ourselves to /bin/sh\n    i=0\n    for arg in \"$@\" ; do\n        CHECK=`echo \"$arg\"|egrep -c \"$OURCYGPATTERN\" -`\n        CHECK2=`echo \"$arg\"|egrep -c \"^-\"`                                 ### Determine if an option\n\n        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition\n            eval `echo args$i`=`cygpath --path --ignore --mixed \"$arg\"`\n        else\n            eval `echo args$i`=\"\\\"$arg\\\"\"\n        fi\n        i=$((i+1))\n    done\n    case $i in\n        (0) set -- ;;\n        (1) set -- \"$args0\" ;;\n        (2) set -- \"$args0\" \"$args1\" ;;\n        (3) set -- \"$args0\" \"$args1\" \"$args2\" ;;\n        (4) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" ;;\n        (5) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" ;;\n        (6) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" ;;\n        (7) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" ;;\n        (8) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" ;;\n        (9) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" \"$args8\" ;;\n    esac\nfi\n\n# Escape application args\nsave () {\n    for i do printf %s\\\\n \"$i\" | sed \"s/'/'\\\\\\\\''/g;1s/^/'/;\\$s/\\$/' \\\\\\\\/\" ; done\n    echo \" \"\n}\nAPP_ARGS=$(save \"$@\")\n\n# Collect all arguments for the java command, following the shell quoting and substitution rules\neval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS \"\\\"-Dorg.gradle.appname=$APP_BASE_NAME\\\"\" -classpath \"\\\"$CLASSPATH\\\"\" org.gradle.wrapper.GradleWrapperMain \"$APP_ARGS\"\n\n# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong\nif [ \"$(uname)\" = \"Darwin\" ] && [ \"$HOME\" = \"$PWD\" ]; then\n  cd \"$(dirname \"$0\")\"\nfi\n\nexec \"$JAVACMD\" \"$@\"\n"
  },
  {
    "path": "gradlew.bat",
    "content": "@if \"%DEBUG%\" == \"\" @echo off\n@rem ##########################################################################\n@rem\n@rem  Gradle startup script for Windows\n@rem\n@rem ##########################################################################\n\n@rem Set local scope for the variables with windows NT shell\nif \"%OS%\"==\"Windows_NT\" setlocal\n\nset DIRNAME=%~dp0\nif \"%DIRNAME%\" == \"\" set DIRNAME=.\nset APP_BASE_NAME=%~n0\nset APP_HOME=%DIRNAME%\n\n@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nset DEFAULT_JVM_OPTS=\n\n@rem Find java.exe\nif defined JAVA_HOME goto findJavaFromJavaHome\n\nset JAVA_EXE=java.exe\n%JAVA_EXE% -version >NUL 2>&1\nif \"%ERRORLEVEL%\" == \"0\" goto init\n\necho.\necho ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\necho.\necho Please set the JAVA_HOME variable in your environment to match the\necho location of your Java installation.\n\ngoto fail\n\n:findJavaFromJavaHome\nset JAVA_HOME=%JAVA_HOME:\"=%\nset JAVA_EXE=%JAVA_HOME%/bin/java.exe\n\nif exist \"%JAVA_EXE%\" goto init\n\necho.\necho ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%\necho.\necho Please set the JAVA_HOME variable in your environment to match the\necho location of your Java installation.\n\ngoto fail\n\n:init\n@rem Get command-line arguments, handling Windows variants\n\nif not \"%OS%\" == \"Windows_NT\" goto win9xME_args\n\n:win9xME_args\n@rem Slurp the command line arguments.\nset CMD_LINE_ARGS=\nset _SKIP=2\n\n:win9xME_args_slurp\nif \"x%~1\" == \"x\" goto execute\n\nset CMD_LINE_ARGS=%*\n\n:execute\n@rem Setup the command line\n\nset CLASSPATH=%APP_HOME%\\gradle\\wrapper\\gradle-wrapper.jar\n\n@rem Execute Gradle\n\"%JAVA_EXE%\" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% \"-Dorg.gradle.appname=%APP_BASE_NAME%\" -classpath \"%CLASSPATH%\" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%\n\n:end\n@rem End local scope for the variables with windows NT shell\nif \"%ERRORLEVEL%\"==\"0\" goto mainEnd\n\n:fail\nrem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\nrem the _cmd.exe /c_ return code!\nif  not \"\" == \"%GRADLE_EXIT_CONSOLE%\" exit 1\nexit /b 1\n\n:mainEnd\nif \"%OS%\"==\"Windows_NT\" endlocal\n\n:omega\n"
  },
  {
    "path": "module_library/.gitignore",
    "content": "/build\n"
  },
  {
    "path": "module_library/build.gradle",
    "content": "apply plugin: 'com.android.library'\napply plugin: 'kotlin-android-extensions'\napply plugin: 'kotlin-android'\napply plugin: 'kotlin-kapt'\n\nandroid {\n    compileSdkVersion 28\n\n\n    defaultConfig {\n        minSdkVersion 21\n        targetSdkVersion 28\n        versionCode 1\n        versionName \"1.0\"\n\n        testInstrumentationRunner \"android.support.test.runner.AndroidJUnitRunner\"\n\n    }\n\n    buildTypes {\n        release {\n            minifyEnabled false\n            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'\n        }\n    }\n    compileOptions {\n        sourceCompatibility = '1.8'\n        targetCompatibility = '1.8'\n    }\n\n}\n\ndependencies {\n    implementation fileTree(dir: 'libs', include: ['*.jar'])\n    //动画\n    implementation ('com.github.ozodrukh:CircularReveal:2.0.1@aar') {\n        transitive = true;\n    }\n    implementation 'com.android.support:appcompat-v7:28.0.0'\n    implementation \"com.android.support:design:28.0.0\"\n    testImplementation 'junit:junit:4.12'\n    androidTestImplementation 'com.android.support.test:runner:1.0.2'\n    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'\n    implementation \"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version\"\n    implementation 'com.android.support:design:28.0.0'\n\n    // Retrofit & okHttp\n    api \"com.squareup.retrofit2:retrofit:$rootProject.retrofitVersion\"\n    api \"com.squareup.retrofit2:converter-gson:$rootProject.retrofitVersion\"\n    api \"com.squareup.retrofit2:adapter-rxjava2:$rootProject.retrofitVersion\"\n    api \"com.squareup.okhttp3:logging-interceptor:$rootProject.okhttploggingVersion\"\n    api \"com.squareup.okhttp3:okhttp:$rootProject.okhttpVersion\"\n\n    // RxBinging\n    api \"com.jakewharton.rxbinding2:rxbinding-appcompat-v7:$rootProject.rxbindingVersion\"\n\n    // Glide\n    api \"com.github.bumptech.glide:glide:$rootProject.glideVersion\"\n    annotationProcessor \"com.github.bumptech.glide:compiler:$rootProject.glideVersion\"\n    // 高斯模糊和圆角等\n    api 'jp.wasabeef:glide-transformations:4.0.1'\n\n    //page\n    def paging_version = \"1.0.0\"\n    api \"android.arch.paging:runtime:$paging_version\"\n    testImplementation \"android.arch.paging:common:$paging_version\"\n    api 'android.arch.paging:rxjava2:1.0.0-rc1'\n\n    //lifecycle\n    def lifecycle_version = \"1.1.1\"\n    api \"android.arch.lifecycle:extensions:$lifecycle_version\"\n    api \"android.arch.lifecycle:viewmodel:$lifecycle_version\"\n    api \"android.arch.lifecycle:livedata:$lifecycle_version\"\n    api \"android.arch.lifecycle:runtime:$lifecycle_version\"\n    annotationProcessor \"android.arch.lifecycle:compiler:$lifecycle_version\"\n    api \"android.arch.lifecycle:reactivestreams:$lifecycle_version\"\n\n    //toast\n    implementation 'me.drakeet.support:toastcompat:1.1.0'\n\n\n}\nrepositories {\n    mavenCentral()\n}\n"
  },
  {
    "path": "module_library/proguard-rules.pro",
    "content": "# Add project specific ProGuard rules here.\n# You can control the set of applied configuration files using the\n# proguardFiles setting in build.gradle.\n#\n# For more details, see\n#   http://developer.android.com/guide/developing/tools/proguard.html\n\n# If your project uses WebView with JS, uncomment the following\n# and specify the fully qualified class name to the JavaScript interface\n# class:\n#-keepclassmembers class fqcn.of.javascript.interface.for.webview {\n#   public *;\n#}\n\n# Uncomment this to preserve the line number information for\n# debugging stack traces.\n#-keepattributes SourceFile,LineNumberTable\n\n# If you keep the line number information, uncomment this to\n# hide the original source file name.\n#-renamesourcefileattribute SourceFile\n"
  },
  {
    "path": "module_library/src/androidTest/java/com/lxm/module_library/ExampleInstrumentedTest.java",
    "content": "package com.lxm.module_library;\n\nimport android.content.Context;\nimport android.support.test.InstrumentationRegistry;\nimport android.support.test.runner.AndroidJUnit4;\n\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\n\nimport static org.junit.Assert.*;\n\n/**\n * Instrumented test, which will execute on an Android device.\n *\n * @see <a href=\"http://d.android.com/tools/testing\">Testing documentation</a>\n */\n@RunWith(AndroidJUnit4.class)\npublic class ExampleInstrumentedTest {\n    @Test\n    public void useAppContext() {\n        // Context of the app under test.\n        Context appContext = InstrumentationRegistry.getTargetContext();\n\n        assertEquals(\"com.lxm.module_library.test\", appContext.getPackageName());\n    }\n}\n"
  },
  {
    "path": "module_library/src/main/AndroidManifest.xml",
    "content": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n          package=\"com.lxm.module_library\">\n\n\n<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\" />\n<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\" />\n<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\" />\n    <uses-permission android:name=\"android.permission.KILL_BACKGROUND_PROCESSES\"/>\n    <uses-permission android:name=\"android.permission.READ_PHONE_STATE\" />\n</manifest>"
  },
  {
    "path": "module_library/src/main/java/com/lxm/module_library/anim/AnimManager.kt",
    "content": "package com.lxm.module_library.anim\nimport android.content.Context\nimport android.os.Build\nimport android.view.View\nimport android.view.animation.AnimationUtils\n\n/**\n * Created by Horrarndoo on 2017/9/11.\n *\n *\n */\n\nobject AnimManager {\n    /**\n     * Alpha and scaleX 动画\n     * Alpha 0->1\n     * ScaleX 0.8->1\n     *\n     * @param context    context\n     * @param view       view\n     * @param startDelay 动画开始前延时（ms）\n     * @param duration   动画持续时间（ms）\n     */\n    fun animAlphaAndScaleX(context: Context, view: View, startDelay: Int, duration: Int) {\n        view.alpha = 0f\n        view.scaleX = 0.8f\n\n        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {\n            view.animate()\n                    .alpha(1f)\n                    .scaleX(1f)\n                    .setStartDelay(startDelay.toLong())\n                    .setDuration(duration.toLong())\n                    .setInterpolator(AnimUtils.getFastOutSlowInInterpolator(context))\n                    .start()\n        } else {\n            view.animate()\n                    .alpha(1f)\n                    .scaleX(1f)\n                    .setStartDelay(startDelay.toLong())\n                    .setDuration(duration.toLong())\n                    .setInterpolator(AnimationUtils.loadInterpolator(context, android.R.interpolator.linear))\n                    .start()\n        }\n    }\n\n    /**\n     * Alpha and scale X Y 动画\n     * Alpha 0->1\n     * ScaleX 0->1\n     * ScaleY 0->1\n     *\n     * @param context    context\n     * @param view       view\n     * @param startDelay 动画开始前延时（ms）\n     * @param duration   动画持续时间（ms）\n     */\n    fun animAlphaAndScale(context: Context, view: View, startDelay: Int, duration: Int) {\n        view.alpha = 0f\n        view.scaleX = 0f\n        view.scaleY = 0f\n\n        view.animate()\n                .alpha(1f)\n                .scaleX(1f)\n                .scaleY(1f)\n                .setStartDelay(startDelay.toLong())\n                .setDuration(duration.toLong())\n                .setInterpolator(AnimationUtils.loadInterpolator(context,\n                        android.R.interpolator.overshoot)).start()\n    }\n}\n"
  },
  {
    "path": "module_library/src/main/java/com/lxm/module_library/anim/AnimUtils.kt",
    "content": "/*\n * Copyright 2015 Google Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.lxm.module_library.anim\n\nimport android.animation.Animator\nimport android.animation.TimeInterpolator\nimport android.content.Context\nimport android.os.Build\nimport android.support.annotation.RequiresApi\nimport android.transition.Transition\nimport android.util.ArrayMap\nimport android.util.Property\nimport android.view.animation.AnimationUtils\nimport android.view.animation.Interpolator\nimport java.util.*\n\n/**\n * Utility methods for working with animations.\n */\nobject AnimUtils {\n\n    private var fastOutSlowIn: Interpolator? = null\n    private var fastOutLinearIn: Interpolator? = null\n    private var linearOutSlowIn: Interpolator? = null\n\n    fun getFastOutSlowInInterpolator(context: Context): Interpolator? {\n        if (fastOutSlowIn == null) {\n            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {\n                fastOutSlowIn = AnimationUtils.loadInterpolator(context,\n                        android.R.interpolator.fast_out_slow_in)\n            }\n        }\n        return fastOutSlowIn\n    }\n\n    fun getFastOutLinearInInterpolator(context: Context): Interpolator? {\n        if (fastOutLinearIn == null) {\n            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {\n                fastOutLinearIn = AnimationUtils.loadInterpolator(context,\n                        android.R.interpolator.fast_out_linear_in)\n            }\n        }\n        return fastOutLinearIn\n    }\n\n    fun getLinearOutSlowInInterpolator(context: Context): Interpolator? {\n        if (linearOutSlowIn == null) {\n            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {\n                linearOutSlowIn = AnimationUtils.loadInterpolator(context,\n                        android.R.interpolator.linear_out_slow_in)\n            }\n        }\n        return linearOutSlowIn\n    }\n\n    /**\n     * Linear interpolate between a and b with parameter t.\n     */\n    fun lerp(a: Float, b: Float, t: Float): Float {\n        return a + (b - a) * t\n    }\n\n\n    /**\n     * An implementation of [Property] to be used specifically with fields of\n     * type\n     * `float`. This type-specific subclass enables performance benefit by allowing\n     * calls to a [set()][.set] function that takes the primitive\n     * `float` type and avoids autoboxing and other overhead associated with the\n     * `Float` class.\n     *\n     * @param <T> The class on which the Property is declared.\n    </T> */\n    abstract class FloatProperty<T>(name: String) : Property<T, Float>(Float::class.java, name) {\n\n        /**\n         * A type-specific override of the [.set] that is faster when dealing\n         * with fields of type `float`.\n         */\n        abstract fun setValue(`object`: T, value: Float)\n\n        override fun set(`object`: T, value: Float?) {\n            setValue(`object`, value!!)\n        }\n    }\n\n    /**\n     * An implementation of [Property] to be used specifically with fields of\n     * type\n     * `int`. This type-specific subclass enables performance benefit by allowing\n     * calls to a [set()][.set] function that takes the primitive\n     * `int` type and avoids autoboxing and other overhead associated with the\n     * `Integer` class.\n     *\n     * @param <T> The class on which the Property is declared.\n    </T> */\n    abstract class IntProperty<T>(name: String) : Property<T, Int>(Int::class.java, name) {\n\n        /**\n         * A type-specific override of the [.set] that is faster when dealing\n         * with fields of type `int`.\n         */\n        abstract fun setValue(`object`: T, value: Int)\n\n        override fun set(`object`: T, value: Int) {\n            setValue(`object`, value)\n        }\n\n    }\n\n    /**\n     * https://halfthought.wordpress.com/2014/11/07/reveal-transition/\n     *\n     *\n     * Interrupting Activity transitions can yield an OperationNotSupportedException when the\n     * transition tries to pause the animator. Yikes! We can fix this by wrapping the Animator:\n     */\n    @RequiresApi(api = Build.VERSION_CODES.KITKAT)\n    class NoPauseAnimator(private val mAnimator: Animator) : Animator() {\n        private val mListeners = ArrayMap<Animator.AnimatorListener, Animator.AnimatorListener>()\n\n        @RequiresApi(api = Build.VERSION_CODES.KITKAT)\n        override fun addListener(listener: Animator.AnimatorListener) {\n            val wrapper = AnimatorListenerWrapper(this, listener)\n            if (!mListeners.containsKey(listener)) {\n                mListeners[listener] = wrapper\n                mAnimator.addListener(wrapper)\n            }\n        }\n\n        override fun cancel() {\n            mAnimator.cancel()\n        }\n\n        override fun end() {\n            mAnimator.end()\n        }\n\n        override fun getDuration(): Long {\n            return mAnimator.duration\n        }\n\n        override fun getInterpolator(): TimeInterpolator {\n            return mAnimator.interpolator\n        }\n\n        override fun setInterpolator(timeInterpolator: TimeInterpolator) {\n            mAnimator.interpolator = timeInterpolator\n        }\n\n        override fun getListeners(): ArrayList<Animator.AnimatorListener> {\n            return ArrayList(mListeners.keys)\n        }\n\n        override fun getStartDelay(): Long {\n            return mAnimator.startDelay\n        }\n\n        override fun setStartDelay(delayMS: Long) {\n            mAnimator.startDelay = delayMS\n        }\n\n        override fun isPaused(): Boolean {\n            return mAnimator.isPaused\n        }\n\n        override fun isRunning(): Boolean {\n            return mAnimator.isRunning\n        }\n\n        override fun isStarted(): Boolean {\n            return mAnimator.isStarted\n        }\n\n        /* We don't want to override pause or resume methods because we don't want them\n         * to affect mAnimator.\n        public void pause();\n\n        public void resume();\n\n        public void addPauseListener(AnimatorPauseListener listener);\n\n        public void removePauseListener(AnimatorPauseListener listener);\n        */\n\n        override fun removeAllListeners() {\n            mListeners.clear()\n            mAnimator.removeAllListeners()\n        }\n\n        override fun removeListener(listener: Animator.AnimatorListener) {\n            val wrapper = mListeners[listener]\n            if (wrapper != null) {\n                mListeners.remove(listener)\n                mAnimator.removeListener(wrapper)\n            }\n        }\n\n        override fun setDuration(durationMS: Long): Animator {\n            mAnimator.duration = durationMS\n            return this\n        }\n\n        override fun setTarget(target: Any?) {\n            mAnimator.setTarget(target)\n        }\n\n        override fun setupEndValues() {\n            mAnimator.setupEndValues()\n        }\n\n        override fun setupStartValues() {\n            mAnimator.setupStartValues()\n        }\n\n        override fun start() {\n            mAnimator.start()\n        }\n    }\n\n    internal class AnimatorListenerWrapper(private val mAnimator: Animator, private val mListener: Animator.AnimatorListener) : Animator.AnimatorListener {\n\n        override fun onAnimationStart(animator: Animator) {\n            mListener.onAnimationStart(mAnimator)\n        }\n\n        override fun onAnimationEnd(animator: Animator) {\n            mListener.onAnimationEnd(mAnimator)\n        }\n\n        override fun onAnimationCancel(animator: Animator) {\n            mListener.onAnimationCancel(mAnimator)\n        }\n\n        override fun onAnimationRepeat(animator: Animator) {\n            mListener.onAnimationRepeat(mAnimator)\n        }\n    }\n\n    @RequiresApi(api = Build.VERSION_CODES.KITKAT)\n    class TransitionListenerAdapter : Transition.TransitionListener {\n\n        override fun onTransitionStart(transition: Transition) {\n\n        }\n\n        override fun onTransitionEnd(transition: Transition) {\n\n        }\n\n        override fun onTransitionCancel(transition: Transition) {\n\n        }\n\n        override fun onTransitionPause(transition: Transition) {\n\n        }\n\n        override fun onTransitionResume(transition: Transition) {\n\n        }\n    }\n\n}\n"
  },
  {
    "path": "module_library/src/main/java/com/lxm/module_library/anim/ToolbarAnimManager.kt",
    "content": "package com.lxm.module_library.anim\n\nimport android.content.Context\nimport android.support.v7.widget.ActionMenuView\nimport android.support.v7.widget.Toolbar\nimport android.widget.ImageButton\nimport android.widget.TextView\nimport com.lxm.module_library.anim.AnimManager\n\n/**\n *\n * @date 2017/9/11\n *\n *\n * Toolbar动画Manager\n */\n\nobject ToolbarAnimManager {\n    /**\n     * Toolbar 进场动画\n     *\n     *\n     * ActionMenuView渐变动画\n     *\n     * @param context context\n     * @param toolbar toolbar\n     */\n    fun animIn(context: Context, toolbar: Toolbar) {\n        var ibIcon: ImageButton? = null\n        var tvTitle: TextView? = null\n        var amvTheme: ActionMenuView? = null\n        val childCount = toolbar.childCount\n        for (i in 0 until childCount) {\n            val child = toolbar.getChildAt(i)\n            if (child is ImageButton) {\n                ibIcon = child\n                continue\n            }\n\n            if (child is ActionMenuView) {\n                amvTheme = child\n                continue\n            }\n\n            if (child is TextView) {\n                tvTitle = child\n            }\n        }\n\n        if (ibIcon != null) {\n            animNavigationIcon(context, ibIcon)\n        }\n\n        if (tvTitle != null) {\n            animTitle(context, tvTitle)\n        }\n\n        if (amvTheme != null) {\n            animMenu(context, amvTheme)\n        }\n    }\n\n    /**\n     * Toolbar Title动画\n     *\n     *\n     * NavigationIcon渐变动画\n     *\n     * @param context  context\n     * @param imageButton 执行动画的view\n     */\n    private fun animNavigationIcon(context: Context, imageButton: ImageButton) {\n        AnimManager.animAlphaAndScaleX(context, imageButton, 500, 900)\n    }\n\n    /**\n     * Toolbar Title动画\n     *\n     *\n     * ActionMenuView渐变动画\n     *\n     * @param context  context\n     * @param textView 执行动画的view\n     */\n    private fun animTitle(context: Context, textView: TextView) {\n        AnimManager.animAlphaAndScaleX(context, textView, 500, 900)\n    }\n\n    /**\n     * Toolbar ActionMenuView动画\n     *\n     *\n     * ActionMenuView渐变动画\n     *\n     * @param context context\n     * @param avm     执行动画的view\n     */\n    private fun animMenu(context: Context, avm: ActionMenuView) {\n        AnimManager.animAlphaAndScale(context, avm, 500, 200) // filter\n        AnimManager.animAlphaAndScale(context, avm, 700, 200) // overflow\n    }\n}\n"
  },
  {
    "path": "module_library/src/main/java/com/lxm/module_library/base/BaseActivity.kt",
    "content": "package com.lxm.module_library.base\n\nimport android.arch.lifecycle.ViewModel\nimport android.arch.lifecycle.ViewModelProviders\nimport android.content.res.Configuration\nimport android.content.res.Resources\nimport android.graphics.drawable.AnimationDrawable\nimport android.os.Build\nimport android.support.annotation.LayoutRes\nimport android.support.v7.app.AppCompatActivity\nimport android.support.v7.widget.Toolbar\nimport android.view.View\nimport android.view.ViewGroup\nimport android.view.ViewStub\nimport android.widget.ImageView\nimport android.widget.RelativeLayout\nimport com.lxm.module_library.R\nimport com.lxm.module_library.utils.ClassUtil\n\nabstract class BaseActivity<VM : ViewModel> : AppCompatActivity() {\n\n    // ViewModel\n    protected lateinit var viewModel: VM\n    // 布局view\n    protected lateinit var contentsView: View\n\n    private lateinit var errorView: View\n    private lateinit var loadingView: View\n    private lateinit var mBaseView: View\n    private var mAnimationDrawable: AnimationDrawable? = null\n\n    protected fun <T : View> getView(id: Int): T {\n        return findViewById<View>(id) as T\n    }\n\n    override fun setContentView(@LayoutRes layoutResID: Int) {\n\n        mBaseView = layoutInflater.inflate(R.layout.activity_base, null, false)\n        contentsView = layoutInflater.inflate(layoutResID, null, false)\n\n        // content\n        val params =\n            RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)\n        contentsView.layoutParams = params\n        val mContainer = mBaseView.findViewById<View>(R.id.container) as RelativeLayout\n        mContainer.addView(contentsView)\n        window.setContentView(mBaseView)\n\n\n        errorView = (findViewById<View>(R.id.vs_error_refresh) as ViewStub).inflate()\n\n        // 设置透明状态栏，兼容4.4\n        //        StatusBarUtil.setColor(this, CommonUtils.getColor(R.color.colorTheme), 0);\n        loadingView = (findViewById<View>(R.id.vs_loading) as ViewStub).inflate()\n        val img = loadingView.findViewById<ImageView>(R.id.img_progress)\n\n        // 加载动画\n        mAnimationDrawable = img.drawable as AnimationDrawable\n        // 默认进入页面就开启动画\n        if (!mAnimationDrawable!!.isRunning) {\n            mAnimationDrawable!!.start()\n        }\n\n        setToolBar()\n        contentsView.visibility = View.GONE\n        initViewModel()\n    }\n\n    /**\n     * 初始化ViewModel\n     */\n    private fun initViewModel() {\n        val viewModelClass = ClassUtil.getViewModel<VM>(this)\n        if (viewModelClass != null) {\n            this.viewModel = ViewModelProviders.of(this).get(viewModelClass)\n        }\n    }\n\n    /**\n     * 设置titlebar\n     */\n    protected fun setToolBar() {\n        setSupportActionBar(mBaseView.findViewById<View>(R.id.tool_bar) as Toolbar)\n        val actionBar = supportActionBar\n        if (actionBar != null) {\n            //去除默认Title显示\n            actionBar.setDisplayShowTitleEnabled(false)\n            actionBar.setDisplayHomeAsUpEnabled(true)\n            actionBar.setHomeAsUpIndicator(R.drawable.icon_back)\n        }\n        (mBaseView.findViewById<View>(R.id.tool_bar) as Toolbar).setNavigationOnClickListener {\n            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {\n                finishAfterTransition()\n            } else {\n                onBackPressed()\n            }\n        }\n    }\n\n    override fun setTitle(text: CharSequence) {\n        (mBaseView.findViewById<View>(R.id.tool_bar) as Toolbar).title = text\n    }\n\n    protected fun showLoading() {\n        if (loadingView != null && loadingView.visibility != View.VISIBLE) {\n            loadingView.visibility = View.VISIBLE\n        }\n        // 开始动画\n        if (!mAnimationDrawable!!.isRunning) {\n            mAnimationDrawable!!.start()\n        }\n        if (contentsView.visibility != View.GONE) {\n            contentsView.visibility = View.GONE\n        }\n        if (errorView != null) {\n            errorView.visibility = View.GONE\n        }\n    }\n\n    protected fun showContentView() {\n        if (loadingView != null && loadingView.visibility != View.GONE) {\n            loadingView.visibility = View.GONE\n        }\n        // 停止动画\n        if (mAnimationDrawable!!.isRunning) {\n            mAnimationDrawable!!.stop()\n        }\n        if (errorView != null) {\n            errorView.visibility = View.GONE\n        }\n        if (contentsView.visibility != View.VISIBLE) {\n            contentsView.visibility = View.VISIBLE\n        }\n    }\n\n    protected fun showError() {\n        if (loadingView != null && loadingView.visibility != View.GONE) {\n            loadingView.visibility = View.GONE\n        }\n        // 停止动画\n        if (mAnimationDrawable!!.isRunning) {\n            mAnimationDrawable!!.stop()\n        }\n        if (errorView != null) {\n            errorView.visibility = View.VISIBLE\n            // 点击加载失败布局\n            errorView.setOnClickListener {\n                showLoading()\n                onRetry()\n            }\n        }\n        if (contentsView.visibility != View.GONE) {\n            contentsView.visibility = View.GONE\n        }\n    }\n\n    /**\n     * 失败后点击刷新\n     */\n    protected fun onRetry() {\n\n    }\n\n\n    override fun onConfigurationChanged(newConfig: Configuration) {\n        super.onConfigurationChanged(newConfig)\n        if (newConfig.fontScale != 1f) {\n            resources\n        }\n    }\n\n    /**\n     * 禁止改变字体大小\n     */\n    override fun getResources(): Resources {\n        val res = super.getResources()\n        val config = Configuration()\n        config.setToDefaults()\n        res.updateConfiguration(config, res.displayMetrics)\n        return res\n    }\n\n    public override fun onDestroy() {\n        super.onDestroy()\n\n    }\n}\n"
  },
  {
    "path": "module_library/src/main/java/com/lxm/module_library/base/BaseFragment.kt",
    "content": "package com.lxm.module_library.base\n\nimport android.arch.lifecycle.ViewModel\nimport android.arch.lifecycle.ViewModelProviders\nimport android.graphics.drawable.AnimationDrawable\nimport android.os.Bundle\nimport android.support.v4.app.Fragment\nimport android.view.LayoutInflater\nimport android.view.View\nimport android.view.ViewGroup\nimport android.view.ViewStub\nimport android.widget.ImageView\nimport android.widget.RelativeLayout\nimport com.lxm.module_library.R\nimport com.lxm.module_library.utils.ClassUtil\nimport io.reactivex.disposables.CompositeDisposable\n\nabstract class BaseFragment<VM : ViewModel> : Fragment() {\n\n    // ViewModel\n    protected lateinit var viewModel: VM\n    // 布局view\n    protected lateinit var contentView: View\n    // fragment是否显示了\n    protected var mIsVisible = false\n    // 加载中\n    private val loadingView: View by lazy{\n        (getView<View>(R.id.vs_loading) as ViewStub).inflate()\n    }\n\n    // 加载失败\n    private val errorView: View by lazy{\n        (getView<View>(R.id.vs_error_refresh) as ViewStub).inflate()\n    }\n    // 动画\n    private var mAnimationDrawable: AnimationDrawable? = null\n\n    private var mCompositeDisposable: CompositeDisposable? = null\n\n\n    private var isViewCreated: Boolean = false // 界面是否已创建完成\n    private var isVisibleToUser: Boolean = false // 是否对用户可见\n    private var isDataLoaded: Boolean = false // 数据是否已请求, isNeedReload()返回false的时起作用\n\n    /**\n     * ViewPager场景下，判断父fragment是否可见\n     *\n     * @return\n     */\n    private val isParentVisible: Boolean\n        get() {\n            val fragment = parentFragment\n            return fragment == null || fragment is BaseFragment<*> && fragment.isVisibleToUser\n        }\n\n    /**\n     * fragment再次可见时，是否重新请求数据，默认为flase则只请求一次数据\n     *\n     * @return\n     */\n    protected val isNeedReload: Boolean\n        get() = false\n\n    /**\n     * 布局\n     */\n    protected abstract fun getLayoutID():Int\n\n    // 实现具体的数据请求逻辑\n    protected abstract fun loadData()\n\n\n    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {\n        val ll = inflater.inflate(R.layout.fragment_base, null)\n        contentView = LayoutInflater.from(activity).inflate(getLayoutID(), null, false)\n        val params =\n            RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)\n        contentView.layoutParams = params\n        val mContainer = ll.findViewById<RelativeLayout>(R.id.container)\n        mContainer.addView(contentView)\n        return ll\n    }\n\n    /**\n     * 在这里实现Fragment数据的缓加载.\n     */\n    override fun setUserVisibleHint(isVisibleToUser: Boolean) {\n        super.setUserVisibleHint(isVisibleToUser)\n        this.isVisibleToUser = isVisibleToUser\n        tryLoadData()\n    }\n\n    private fun tryLoadData() {\n        if (isViewCreated && isVisibleToUser && isParentVisible && (isNeedReload || !isDataLoaded)) {\n            loadData()\n            isDataLoaded = true\n            dispatchParentVisibleState()\n        }\n    }\n\n    /**\n     * ViewPager场景下，当前fragment可见，如果其子fragment也可见，则尝试让子fragment加载请求\n     */\n    private fun dispatchParentVisibleState() {\n        val fragmentManager = childFragmentManager\n        val fragments = fragmentManager.fragments\n        if (fragments.isEmpty()) {\n            return\n        }\n\n        for (child in fragments) {\n            if (child is BaseFragment<*> && child.isVisibleToUser) {\n                child.tryLoadData()\n            }\n        }\n    }\n\n\n    override fun onActivityCreated(savedInstanceState: Bundle?) {\n        super.onActivityCreated(savedInstanceState)\n\n        isViewCreated = true\n        initLoadView()\n        initViewModel()\n        tryLoadData()\n    }\n\n\n    private fun initLoadView() {\n        val img = loadingView.findViewById<ImageView>(R.id.img_progress)\n        // 加载动画\n        mAnimationDrawable = img.drawable as AnimationDrawable\n        // 默认进入页面就开启动画\n        if (!mAnimationDrawable?.isRunning!!) {\n            mAnimationDrawable?.start()\n        }\n        contentView.visibility = View.GONE\n    }\n\n    /**\n     * 初始化ViewModel\n     */\n    private fun initViewModel() {\n        val viewModelClass = ClassUtil.getViewModel<VM>(this)\n        if (viewModelClass != null) {\n            this.viewModel = ViewModelProviders.of(this).get(viewModelClass)\n        }\n    }\n\n    protected fun <T : View> getView(id: Int): T {\n        return view!!.findViewById<View>(id) as T\n    }\n\n    /**\n     * 加载失败后点击后的操作\n     */\n    protected abstract fun onRetry()\n\n    /**\n     * 显示加载中状态\n     */\n    protected fun showLoading() {\n        if (loadingView != null && loadingView.visibility != View.VISIBLE) {\n            loadingView.visibility = View.VISIBLE\n        }\n        // 开始动画\n        if (!mAnimationDrawable!!.isRunning) {\n            mAnimationDrawable!!.start()\n        }\n        if (contentView.visibility != View.GONE) {\n            contentView.visibility = View.GONE\n        }\n        if (errorView != null) {\n            errorView.visibility = View.GONE\n        }\n    }\n\n    /**\n     * 加载完成的状态\n     */\n    protected fun showContentView() {\n        if (loadingView != null && loadingView.visibility != View.GONE) {\n            loadingView.visibility = View.GONE\n        }\n        // 停止动画\n        if (mAnimationDrawable != null && mAnimationDrawable!!.isRunning) {\n            mAnimationDrawable!!.stop()\n        }\n        if (errorView != null) {\n            errorView.visibility = View.GONE\n        }\n        if (contentView.visibility != View.VISIBLE) {\n            contentView.visibility = View.VISIBLE\n        }\n    }\n\n    /**\n     * 加载失败点击重新加载的状态\n     */\n    protected fun showError() {\n        if (loadingView != null && loadingView.visibility != View.GONE) {\n            loadingView.visibility = View.GONE\n        }\n        // 停止动画\n        if (mAnimationDrawable != null && mAnimationDrawable!!.isRunning) {\n            mAnimationDrawable!!.stop()\n        }\n        if (errorView != null) {\n            errorView.visibility = View.VISIBLE\n            // 点击加载失败布局\n            errorView.setOnClickListener {\n                showLoading()\n                onRetry()\n            }\n        } else {\n\n        }\n        if (contentView.visibility != View.GONE) {\n            contentView.visibility = View.GONE\n        }\n    }\n\n}\n"
  },
  {
    "path": "module_library/src/main/java/com/lxm/module_library/base/BaseViewModel.kt",
    "content": "package com.lxm.module_library.base\n\nimport android.arch.lifecycle.ViewModel\nimport io.reactivex.disposables.CompositeDisposable\nimport io.reactivex.disposables.Disposable\n\nopen class BaseViewModel : ViewModel() {\n\n    private var mCompositeDisposable: CompositeDisposable? = null\n\n\n    protected fun addDisposable(disposable: Disposable) {\n        if (this.mCompositeDisposable == null) {\n            this.mCompositeDisposable = CompositeDisposable()\n        }\n        this.mCompositeDisposable?.add(disposable)\n    }\n\n    override fun onCleared() {\n        super.onCleared()\n        if (this.mCompositeDisposable != null && !mCompositeDisposable?.isDisposed!!) {\n            this.mCompositeDisposable?.clear()\n        }\n    }\n}\n"
  },
  {
    "path": "module_library/src/main/java/com/lxm/module_library/base/NoViewModel.java",
    "content": "package com.lxm.module_library.base;\n\nimport android.arch.lifecycle.ViewModel;\n\npublic class NoViewModel extends ViewModel {\n\n}\n"
  },
  {
    "path": "module_library/src/main/java/com/lxm/module_library/global/AppManager.java",
    "content": "package com.lxm.module_library.global;\n\nimport android.app.Activity;\nimport android.app.ActivityManager;\nimport android.content.Context;\n\nimport java.util.Stack;\n\n/**\n * Created by Horrarndoo on 2017/4/5.\n * <p>\n * AppManager 管理Activity栈\n */\n\npublic class AppManager {\n    private static Stack<Activity> activityStack;\n    private static AppManager instance;\n\n    private AppManager() {\n    }\n\n    /**\n     * 单一实例\n     */\n    public static AppManager getAppManager() {\n        if (instance == null) {\n            instance = new AppManager();\n        }\n        return instance;\n    }\n\n    /**\n     * 添加Activity到堆栈\n     */\n    public void addActivity(Activity activity) {\n        if (activityStack == null) {\n            activityStack = new Stack<Activity>();\n        }\n        activityStack.add(activity);\n    }\n\n    /**\n     * 获取当前Activity（堆栈中最后一个压入的）\n     */\n    public Activity currentActivity() {\n        Activity activity = activityStack.lastElement();\n        return activity;\n    }\n\n    /**\n     * 结束当前Activity（堆栈中最后一个压入的）\n     */\n    public void finishActivity() {\n        Activity activity = activityStack.lastElement();\n        finishActivity(activity);\n    }\n\n    /**\n     * 结束指定的Activity\n     */\n    public void finishActivity(Activity activity) {\n        if (activity != null) {\n            activityStack.remove(activity);\n            activity.finish();\n            activity = null;\n        }\n    }\n\n    /**\n     * 结束指定类名的Activity\n     */\n    public void finishActivity(Class<?> cls) {\n        for (Activity activity : activityStack) {\n            if (activity.getClass().equals(cls)) {\n                finishActivity(activity);\n            }\n        }\n    }\n\n    /**\n     * 结束所有Activity\n     */\n    public void finishAllActivity() {\n        for (int i = 0, size = activityStack.size(); i < size; i++) {\n            if (null != activityStack.get(i)) {\n                activityStack.get(i).finish();\n            }\n        }\n        activityStack.clear();\n    }\n\n    /**\n     * 退出应用程序\n     */\n    public void AppExit(Context context) {\n        try {\n            finishAllActivity();\n            ActivityManager activityMgr =\n                    (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);\n            activityMgr.killBackgroundProcesses(context.getPackageName());\n            System.exit(0);\n        } catch (Exception e) {\n        }\n    }\n\n    public boolean isAppExit() {\n        return activityStack == null || activityStack.isEmpty();\n    }\n}\n"
  },
  {
    "path": "module_library/src/main/java/com/lxm/module_library/global/GlobalApplication.java",
    "content": "package com.lxm.module_library.global;\n\nimport android.app.Application;\nimport android.content.Context;\nimport android.os.Handler;\nimport com.lxm.module_library.utils.PreferencesUtil;\n\n\n/**\n * Created by Horrarndoo on 2017/9/1.\n * <p>\n * 全局Application\n */\n\npublic class GlobalApplication extends Application {\n    protected static Context context;\n    protected static Handler handler;\n    protected static int mainThreadId;\n\n    private static GlobalApplication globalApplication;\n\n    public static GlobalApplication getInstance() {\n        return globalApplication;\n    }\n\n    @Override\n    public void onCreate() {\n        super.onCreate();\n        globalApplication = this;\n        context = getApplicationContext();\n        handler = new Handler();\n        mainThreadId = android.os.Process.myTid();\n        PreferencesUtil.Companion.get(this);\n\n    }\n\n    /**\n     * 获取上下文对象\n     *\n     * @return context\n     */\n    public static Context getContext() {\n        return context;\n    }\n\n    /**\n     * 获取全局handler\n     *\n     * @return 全局handler\n     */\n    public static Handler getHandler() {\n        return handler;\n    }\n\n    /**\n     * 获取主线程id\n     *\n     * @return 主线程id\n     */\n    public static int getMainThreadId() {\n        return mainThreadId;\n    }\n}\n"
  },
  {
    "path": "module_library/src/main/java/com/lxm/module_library/helper/RetrofitCreateHelper.java",
    "content": "package com.lxm.module_library.helper;\n\nimport com.lxm.module_library.utils.AppUtils;\nimport com.lxm.module_library.helper.okhttp.TrustManager;\nimport com.lxm.module_library.helper.okhttp.cache.CacheInterceptor;\nimport com.lxm.module_library.helper.okhttp.cache.HttpCache;\nimport com.lxm.module_library.helper.okhttp.cookies.CookieManger;\nimport okhttp3.OkHttpClient;\nimport okhttp3.logging.HttpLoggingInterceptor;\nimport retrofit2.Retrofit;\nimport retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;\nimport retrofit2.converter.gson.GsonConverterFactory;\n\nimport java.util.concurrent.TimeUnit;\n\n/**\n * Created by Horrarndoo on 2017/9/7.\n * <p>\n */\n\npublic class RetrofitCreateHelper {\n    private static final int TIMEOUT_READ = 5;\n    private static final int TIMEOUT_CONNECTION = 5;\n    private static final HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor()\n            .setLevel(HttpLoggingInterceptor.Level.BODY);\n    private static CacheInterceptor cacheInterceptor = new CacheInterceptor();\n    private static OkHttpClient okHttpClient = new OkHttpClient.Builder()\n            //SSL证书\n            .sslSocketFactory(TrustManager.getUnsafeOkHttpClient())\n            .hostnameVerifier(org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER)\n            //打印日志\n            .addInterceptor(interceptor)\n            //设置Cache拦截器\n            .addNetworkInterceptor(cacheInterceptor)\n            .addInterceptor(cacheInterceptor)\n            .cache(HttpCache.getCache())\n            // 设置 Cookie\n            .cookieJar(new CookieManger(AppUtils.INSTANCE.getContext()))\n            //time out\n            .connectTimeout(TIMEOUT_CONNECTION, TimeUnit.SECONDS)\n            .readTimeout(TIMEOUT_READ, TimeUnit.SECONDS)\n            .writeTimeout(TIMEOUT_READ, TimeUnit.SECONDS)\n            //失败重连\n            .retryOnConnectionFailure(true)\n            .build();\n\n\n    public static <T> T createApi(Class<T> clazz, String url) {\n        Retrofit retrofit = new Retrofit.Builder()\n                .baseUrl(url)\n                .client(okHttpClient)\n                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())\n                .addConverterFactory(GsonConverterFactory.create())\n                .build();\n        return retrofit.create(clazz);\n    }\n}\n\n"
  },
  {
    "path": "module_library/src/main/java/com/lxm/module_library/helper/RxHelper.java",
    "content": "package com.lxm.module_library.helper;\n\n\nimport io.reactivex.*;\nimport io.reactivex.android.schedulers.AndroidSchedulers;\nimport io.reactivex.schedulers.Schedulers;\n\n/**\n * Created by Horrarndoo on 2017/9/12.\n * <p>\n */\npublic class RxHelper {\n\n    /**\n     * 统一线程处理\n     * <p>\n     * 发布事件io线程，接收事件主线程\n     */\n    public static <T> ObservableTransformer<T, T> rxSchedulerHelper() {//compose处理线程\n        return new ObservableTransformer<T, T>() {\n\n            @Override\n            public ObservableSource<T> apply(Observable<T> upstream) {\n                return upstream.subscribeOn(Schedulers.io())\n                        .observeOn(AndroidSchedulers.mainThread());\n            }\n        };\n    }\n\n    /**\n     * 生成Flowable\n     *\n     * @param t\n     * @return Flowable\n     */\n    public static <T> Flowable<T> createFlowable(final T t) {\n        return Flowable.create(new FlowableOnSubscribe<T>() {\n            @Override\n            public void subscribe(FlowableEmitter<T> emitter) throws Exception {\n                try {\n                    emitter.onNext(t);\n                    emitter.onComplete();\n                } catch (Exception e) {\n                    emitter.onError(e);\n                }\n            }\n        }, BackpressureStrategy.BUFFER);\n    }\n\n    /**\n     * 生成Observable\n     *\n     * @param t\n     * @return Flowable\n     */\n    public static <T> Observable<T> createObservable(final T t) {\n        return Observable.create(new ObservableOnSubscribe<T>() {\n            @Override\n            public void subscribe(ObservableEmitter<T> emitter) throws Exception {\n                try {\n                    emitter.onNext(t);\n                    emitter.onComplete();\n                } catch (Exception e) {\n                    emitter.onError(e);\n                }\n            }\n        });\n    }\n}\n"
  },
  {
    "path": "module_library/src/main/java/com/lxm/module_library/helper/okhttp/TrustManager.java",
    "content": "package com.lxm.module_library.helper.okhttp;\n\nimport javax.net.ssl.SSLContext;\nimport javax.net.ssl.SSLSocketFactory;\nimport javax.net.ssl.X509TrustManager;\nimport java.security.cert.CertificateException;\nimport java.security.cert.X509Certificate;\n\n/**\n * Created by Horrarndoo on 2017/9/12.\n * <p>\n */\npublic class TrustManager {\n\n    public static SSLSocketFactory getUnsafeOkHttpClient() {\n        try {\n            // Create a trust manager that does not validate certificate chains\n            final X509TrustManager[] trustAllCerts = new X509TrustManager[]{new X509TrustManager() {\n                @Override\n                public void checkClientTrusted(\n                        X509Certificate[] chain,\n                        String authType) throws CertificateException {\n                }\n\n                @Override\n                public void checkServerTrusted(\n                        X509Certificate[] chain,\n                        String authType) throws CertificateException {\n                }\n\n                @Override\n                public X509Certificate[] getAcceptedIssuers() {\n                    return new X509Certificate[0];\n                }\n            }};\n\n            // Install the all-trusting trust manager\n            final SSLContext sslContext = SSLContext.getInstance(\"TLS\");\n            sslContext.init(null, trustAllCerts,\n                    new java.security.SecureRandom());\n            // Create an ssl socket factory with our all-trusting manager\n            final SSLSocketFactory sslSocketFactory = sslContext\n                    .getSocketFactory();\n\n\n            return sslSocketFactory;\n        } catch (Exception e) {\n            throw new RuntimeException(e);\n        }\n\n    }\n}\n\n"
  },
  {
    "path": "module_library/src/main/java/com/lxm/module_library/helper/okhttp/cache/CacheInterceptor.java",
    "content": "package com.lxm.module_library.helper.okhttp.cache;\n\n\nimport com.lxm.module_library.utils.AppUtils;\nimport com.lxm.module_library.utils.HttpUtils;\nimport com.lxm.module_library.utils.NetworkConnectionUtils;\nimport okhttp3.CacheControl;\nimport okhttp3.Interceptor;\nimport okhttp3.Request;\nimport okhttp3.Response;\n\nimport java.io.IOException;\n\n\n/**\n * Created by Horrarndoo on 2017/9/12.\n * <p>\n * CacheInterceptor\n */\npublic class CacheInterceptor implements Interceptor {\n\n    @Override\n    public Response intercept(Chain chain) throws IOException {\n        Request request = chain.request();\n        if (NetworkConnectionUtils.INSTANCE.isNetworkConnected(AppUtils.INSTANCE.getContext())) {\n            // 有网络时, 缓存60s\n            int maxAge = 10 ;\n            request = request.newBuilder()\n                    .removeHeader(\"User-Agent\")\n                    .header(\"User-Agent\", HttpUtils.INSTANCE.getUserAgent())\n                    .build();\n\n            Response response = chain.proceed(request);\n            return response.newBuilder()\n                    .removeHeader(\"Pragma\")\n                    .removeHeader(\"Cache-Control\")\n                    .header(\"Cache-Control\", \"public, max-age=\" + maxAge)\n                    .build();\n        } else {\n            // 无网络时，缓存为4周\n            int maxStale = 60 * 60 * 24 * 28;\n            request = request.newBuilder()\n                    .cacheControl(CacheControl.FORCE_CACHE)\n                    .removeHeader(\"User-Agent\")\n                    .header(\"User-Agent\", HttpUtils.INSTANCE.getUserAgent())\n                    .build();\n\n            Response response = chain.proceed(request);\n            return response.newBuilder()\n                    .removeHeader(\"Pragma\")\n                    .removeHeader(\"Cache-Control\")\n                    .header(\"Cache-Control\", \"public, only-if-cached, max-stale=\" + maxStale)\n                    .build();\n        }\n\n    }\n}\n"
  },
  {
    "path": "module_library/src/main/java/com/lxm/module_library/helper/okhttp/cache/HttpCache.java",
    "content": "package com.lxm.module_library.helper.okhttp.cache;\n\nimport com.lxm.module_library.utils.AppUtils;\nimport okhttp3.Cache;\n\nimport java.io.File;\n\n/**\n * Created by Horrarndoo on 2017/9/12.\n * <p>\n */\npublic class HttpCache {\n\n    private static final int HTTP_RESPONSE_DISK_CACHE_MAX_SIZE = 50 * 1024 * 1024;\n\n    public static Cache getCache() {\n        return new Cache(new File(AppUtils.INSTANCE.getContext().getExternalCacheDir().getAbsolutePath() + File\n                .separator + \"data/NetCache\"),\n                HTTP_RESPONSE_DISK_CACHE_MAX_SIZE);\n    }\n}\n"
  },
  {
    "path": "module_library/src/main/java/com/lxm/module_library/helper/okhttp/cookies/CookieManger.java",
    "content": "package com.lxm.module_library.helper.okhttp.cookies;\n\nimport android.content.Context;\nimport okhttp3.Cookie;\nimport okhttp3.CookieJar;\nimport okhttp3.HttpUrl;\n\nimport java.util.List;\n\n/**\n * Created by CoderLengary\n */\n\n\npublic class CookieManger implements CookieJar {\n\n\n    private static Context mContext;\n\n    private static PersistentCookieStore cookieStore;\n\n    public CookieManger(Context context) {\n        mContext = context;\n        if (cookieStore == null) {\n            cookieStore = new PersistentCookieStore(mContext);\n        }\n\n    }\n\n\n    @Override\n    public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {\n        if (cookies != null && cookies.size() > 0) {\n            for (Cookie item : cookies) {\n                cookieStore.add(url, item);\n            }\n        }\n    }\n\n    @Override\n    public List<Cookie> loadForRequest(HttpUrl url) {\n        List<Cookie> cookies = cookieStore.get(url);\n        return cookies;\n    }\n\n    public static void clearAllCookies() {\n        cookieStore.removeAll();\n    }\n\n\n}"
  },
  {
    "path": "module_library/src/main/java/com/lxm/module_library/helper/okhttp/cookies/OkHttpCookies.java",
    "content": "package com.lxm.module_library.helper.okhttp.cookies;\n\nimport okhttp3.Cookie;\n\nimport java.io.IOException;\nimport java.io.ObjectInputStream;\nimport java.io.ObjectOutputStream;\nimport java.io.Serializable;\n\n\npublic class OkHttpCookies implements Serializable {\n\n    private transient final Cookie cookies;\n    private transient Cookie clientCookies;\n\n    public OkHttpCookies(Cookie cookies) {\n        this.cookies = cookies;\n    }\n\n    public Cookie getCookies() {\n        Cookie bestCookies = cookies;\n        if (clientCookies != null) {\n            bestCookies = clientCookies;\n        }\n        return bestCookies;\n    }\n\n    private void writeObject(ObjectOutputStream out) throws IOException {\n        out.writeObject(cookies.name());\n        out.writeObject(cookies.value());\n        out.writeLong(cookies.expiresAt());\n        out.writeObject(cookies.domain());\n        out.writeObject(cookies.path());\n        out.writeBoolean(cookies.secure());\n        out.writeBoolean(cookies.httpOnly());\n        out.writeBoolean(cookies.hostOnly());\n        out.writeBoolean(cookies.persistent());\n    }\n\n    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {\n        String name = (String) in.readObject();\n        String value = (String) in.readObject();\n        long expiresAt = in.readLong();\n        String domain = (String) in.readObject();\n        String path = (String) in.readObject();\n        boolean secure = in.readBoolean();\n        boolean httpOnly = in.readBoolean();\n        boolean hostOnly = in.readBoolean();\n        Cookie.Builder builder = new Cookie.Builder();\n        builder = builder.name(name);\n        builder = builder.value(value);\n        builder = builder.expiresAt(expiresAt);\n        builder = hostOnly ? builder.hostOnlyDomain(domain) : builder.domain(domain);\n        builder = builder.path(path);\n        builder = secure ? builder.secure() : builder;\n        builder = httpOnly ? builder.httpOnly() : builder;\n        clientCookies = builder.build();\n    }\n}"
  },
  {
    "path": "module_library/src/main/java/com/lxm/module_library/helper/okhttp/cookies/PersistentCookieStore.java",
    "content": "package com.lxm.module_library.helper.okhttp.cookies;\n\nimport android.content.Context;\nimport android.content.SharedPreferences;\nimport android.text.TextUtils;\nimport android.util.Log;\nimport okhttp3.Cookie;\nimport okhttp3.HttpUrl;\n\nimport java.io.*;\nimport java.util.*;\nimport java.util.concurrent.ConcurrentHashMap;\n\n\npublic class PersistentCookieStore {\n\n    private static final String LOG_TAG = \"PersistentCookieStore\";\n    private static final String COOKIE_PREFS = \"Cookies_Prefs\";\n\n    private final Map<String, ConcurrentHashMap<String, Cookie>> cookies;\n    private final SharedPreferences cookiePrefs;\n\n\n    public PersistentCookieStore(Context context) {\n        cookiePrefs = context.getSharedPreferences(COOKIE_PREFS, 0);\n        cookies = new HashMap<>();\n\n        //将持久化的cookies缓存到内存中 即map cookies\n        Map<String, ?> prefsMap = cookiePrefs.getAll();\n        for (Map.Entry<String, ?> entry : prefsMap.entrySet()) {\n            String[] cookieNames = TextUtils.split((String) entry.getValue(), \",\");\n            for (String name : cookieNames) {\n                String encodedCookie = cookiePrefs.getString(name, null);\n                if (encodedCookie != null) {\n                    Cookie decodedCookie = decodeCookie(encodedCookie);\n                    if (decodedCookie != null) {\n                        if (!cookies.containsKey(entry.getKey())) {\n                            cookies.put(entry.getKey(), new ConcurrentHashMap<String, Cookie>());\n                        }\n                        cookies.get(entry.getKey()).put(name, decodedCookie);\n                    }\n                }\n            }\n        }\n    }\n\n    protected String getCookieToken(Cookie cookie) {\n        return cookie.name() + \"@\" + cookie.domain();\n    }\n\n    public void add(HttpUrl url, Cookie cookie) {\n        String name = getCookieToken(cookie);\n\n        if (!cookies.containsKey(url.host())) {\n            cookies.put(url.host(), new ConcurrentHashMap<String, Cookie>());\n        }\n        cookies.get(url.host()).put(name, cookie);\n\n        //cookies持久化到本地\n        SharedPreferences.Editor prefsWriter = cookiePrefs.edit();\n        prefsWriter.putString(url.host(), TextUtils.join(\",\", cookies.get(url.host()).keySet()));\n        prefsWriter.putString(name, encodeCookie(new OkHttpCookies(cookie)));\n        prefsWriter.apply();\n    }\n\n    public List<Cookie> get(HttpUrl url) {\n        ArrayList<Cookie> ret = new ArrayList<>();\n        if (cookies.containsKey(url.host())) {\n            ret.addAll(cookies.get(url.host()).values());\n        }\n        return ret;\n    }\n\n    public boolean removeAll() {\n        SharedPreferences.Editor prefsWriter = cookiePrefs.edit();\n        prefsWriter.clear();\n        prefsWriter.apply();\n        cookies.clear();\n        return true;\n    }\n\n\n\n\n\n    /**\n     * cookies 序列化成 string\n     *\n     * @param cookie 要序列化的cookie\n     * @return 序列化之后的string\n     */\n    protected String encodeCookie(OkHttpCookies cookie) {\n        if (cookie == null)\n            return null;\n        ByteArrayOutputStream os = new ByteArrayOutputStream();\n        try {\n            ObjectOutputStream outputStream = new ObjectOutputStream(os);\n            outputStream.writeObject(cookie);\n        } catch (IOException e) {\n            Log.d(LOG_TAG, \"IOException in encodeCookie\", e);\n            return null;\n        }\n\n        return byteArrayToHexString(os.toByteArray());\n    }\n\n    /**\n     * 将字符串反序列化成cookies\n     *\n     * @param cookieString cookies string\n     * @return cookie object\n     */\n    protected Cookie decodeCookie(String cookieString) {\n        byte[] bytes = hexStringToByteArray(cookieString);\n        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);\n        Cookie cookie = null;\n        try {\n            ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);\n            cookie = ((OkHttpCookies) objectInputStream.readObject()).getCookies();\n        } catch (IOException e) {\n            Log.d(LOG_TAG, \"IOException in decodeCookie\", e);\n        } catch (ClassNotFoundException e) {\n            Log.d(LOG_TAG, \"ClassNotFoundException in decodeCookie\", e);\n        }\n\n        return cookie;\n    }\n\n    /**\n     * 二进制数组转十六进制字符串\n     *\n     * @param bytes byte array to be converted\n     * @return string containing hex values\n     */\n    protected String byteArrayToHexString(byte[] bytes) {\n        StringBuilder sb = new StringBuilder(bytes.length * 2);\n        for (byte element : bytes) {\n            int v = element & 0xff;\n            if (v < 16) {\n                sb.append('0');\n            }\n            sb.append(Integer.toHexString(v));\n        }\n        return sb.toString().toUpperCase(Locale.US);\n    }\n\n    /**\n     * 十六进制字符串转二进制数组\n     *\n     * @param hexString string of hex-encoded values\n     * @return decoded byte array\n     */\n    protected byte[] hexStringToByteArray(String hexString) {\n        int len = hexString.length();\n        byte[] data = new byte[len / 2];\n        for (int i = 0; i < len; i += 2) {\n            data[i / 2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4) + Character.digit(hexString.charAt(i + 1), 16));\n        }\n        return data;\n    }\n\n}"
  },
  {
    "path": "module_library/src/main/java/com/lxm/module_library/materialLogin/DefaultLoginView.java",
    "content": "package com.lxm.module_library.materialLogin;\n\nimport android.annotation.TargetApi;\nimport android.content.Context;\nimport android.content.res.TypedArray;\nimport android.os.Build;\nimport android.support.design.widget.TextInputLayout;\nimport android.support.v4.content.ContextCompat;\nimport android.util.AttributeSet;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.widget.FrameLayout;\nimport android.widget.TextView;\nimport com.lxm.module_library.R;\n\n/**\n * Created by shem on 1/15/16.\n */\npublic class DefaultLoginView extends FrameLayout {\n\n    public interface DefaultLoginViewListener {\n        void onLogin(TextInputLayout loginUser, TextInputLayout loginPass);\n    }\n\n    private DefaultLoginViewListener listener;\n\n\n    public DefaultLoginView(Context context) {\n        this(context, null);\n    }\n\n    public DefaultLoginView(Context context, AttributeSet attrs) {\n        this(context, attrs, 0);\n    }\n\n    public DefaultLoginView(Context context, AttributeSet attrs, int defStyleAttr) {\n        super(context, attrs, defStyleAttr);\n        init(context, attrs);\n    }\n\n    @TargetApi(Build.VERSION_CODES.LOLLIPOP)\n    public DefaultLoginView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {\n        super(context, attrs, defStyleAttr, defStyleRes);\n        init(context, attrs);\n    }\n\n    private void init(Context context, AttributeSet attrs) {\n        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);\n        inflater.inflate(R.layout.login_layout, this, true);\n\n        TypedArray a = context.getTheme().obtainStyledAttributes(\n                attrs,\n                R.styleable.DefaultLoginView,\n                0, 0);\n\n        TextView loginTitle = (TextView) findViewById(R.id.login_title);\n        final TextInputLayout loginUser = (TextInputLayout) findViewById(R.id.login_user);\n        final TextInputLayout loginPass = (TextInputLayout) findViewById(R.id.login_pass);\n        TextView loginBtn = (TextView) findViewById(R.id.login_btn);\n\n        findViewById(R.id.login_btn).setOnClickListener(new OnClickListener() {\n            @Override\n            public void onClick(View v) {\n                if (listener != null) {\n                    listener.onLogin(loginUser, loginPass);\n                }\n            }\n        });\n        try {\n            String string = a.getString(R.styleable.DefaultLoginView_loginTitle);\n            if (string != null) {\n                loginTitle.setText(string);\n            }\n\n            string = a.getString(R.styleable.DefaultLoginView_loginHint);\n            if (string != null) {\n                loginUser.setHint(string);\n            }\n\n            string = a.getString(R.styleable.DefaultLoginView_loginPasswordHint);\n            if (string != null) {\n                loginPass.setHint(string);\n            }\n\n            string = a.getString(R.styleable.DefaultLoginView_loginActionText);\n            if (string != null) {\n                loginBtn.setText(string);\n            }\n\n            int color = a.getColor(R.styleable.DefaultLoginView_loginTextColor, ContextCompat.getColor(getContext(), R.color.material_login_login_text_color));\n            loginUser.getEditText().setTextColor(color);\n            loginPass.getEditText().setTextColor(color);\n\n        } finally {\n            a.recycle();\n        }\n    }\n\n    public void setListener(DefaultLoginViewListener listener) {\n        this.listener = listener;\n    }\n}\n"
  },
  {
    "path": "module_library/src/main/java/com/lxm/module_library/materialLogin/DefaultRegisterView.java",
    "content": "package com.lxm.module_library.materialLogin;\n\nimport android.annotation.TargetApi;\nimport android.content.Context;\nimport android.content.res.TypedArray;\nimport android.os.Build;\nimport android.support.design.widget.TextInputLayout;\nimport android.support.v4.content.ContextCompat;\nimport android.util.AttributeSet;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.widget.FrameLayout;\nimport android.widget.TextView;\nimport com.lxm.module_library.R;\n\n/**\n * Created by shem on 1/15/16.\n */\npublic class DefaultRegisterView extends FrameLayout implements RegisterView {\n\n    public interface DefaultRegisterViewListener {\n        void onRegister(TextInputLayout registerUser, TextInputLayout registerPass, TextInputLayout registerPassRep);\n    }\n\n    private DefaultRegisterViewListener listener;\n    private View registerCancel;\n\n\n    public DefaultRegisterView(Context context) {\n        this(context, null);\n    }\n\n    public DefaultRegisterView(Context context, AttributeSet attrs) {\n        this(context, attrs, 0);\n    }\n\n    public DefaultRegisterView(Context context, AttributeSet attrs, int defStyleAttr) {\n        super(context, attrs, defStyleAttr);\n        init(context, attrs);\n    }\n\n    @TargetApi(Build.VERSION_CODES.LOLLIPOP)\n    public DefaultRegisterView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {\n        super(context, attrs, defStyleAttr, defStyleRes);\n        init(context, attrs);\n    }\n\n    private void init(Context context, AttributeSet attrs) {\n        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);\n        inflater.inflate(R.layout.register_layout, this, true);\n\n        TypedArray a = context.getTheme().obtainStyledAttributes(\n                attrs,\n                R.styleable.DefaultRegisterView,\n                0, 0);\n\n        TextView registerTitle = (TextView) findViewById(R.id.register_title);\n        final TextInputLayout registerUser = (TextInputLayout) findViewById(R.id.register_user);\n        final TextInputLayout registerPass = (TextInputLayout) findViewById(R.id.register_pass);\n        final TextInputLayout registerPassRep = (TextInputLayout) findViewById(R.id.register_pass_rep);\n        TextView registerBtn = (TextView) findViewById(R.id.register_btn);\n        registerCancel = findViewById(R.id.register_cancel);\n\n\n        registerBtn.setOnClickListener(new OnClickListener() {\n            @Override\n            public void onClick(View v) {\n                listener.onRegister(registerUser,\n                        registerPass,\n                        registerPassRep);\n            }\n        });\n\n        try {\n            String string = a.getString(R.styleable.DefaultRegisterView_registerTitle);\n            if (string != null) {\n                registerTitle.setText(string);\n            }\n\n            string = a.getString(R.styleable.DefaultRegisterView_registerHint);\n            if (string != null) {\n                registerUser.setHint(string);\n            }\n\n            string = a.getString(R.styleable.DefaultRegisterView_registerPasswordHint);\n            if (string != null) {\n                registerPass.setHint(string);\n            }\n\n            string = a.getString(R.styleable.DefaultRegisterView_registerRepeatPasswordHint);\n            if (string != null) {\n                registerPassRep.setHint(string);\n            }\n\n            string = a.getString(R.styleable.DefaultRegisterView_registerActionText);\n            if (string != null) {\n                registerBtn.setText(string);\n            }\n\n            int color = a.getColor(R.styleable.DefaultRegisterView_registerTextColor, ContextCompat.getColor(getContext(), R.color.material_login_register_text_color));\n            registerUser.getEditText().setTextColor(color);\n            registerPass.getEditText().setTextColor(color);\n            registerPassRep.getEditText().setTextColor(color);\n\n        } finally {\n            a.recycle();\n        }\n    }\n\n    public void setListener(DefaultRegisterViewListener listener) {\n        this.listener = listener;\n    }\n\n    @Override\n    public View getCancelRegisterView() {\n        return registerCancel;\n    }\n}\n"
  },
  {
    "path": "module_library/src/main/java/com/lxm/module_library/materialLogin/MaterialLoginView.java",
    "content": "package com.lxm.module_library.materialLogin;\n\nimport android.animation.Animator;\nimport android.animation.AnimatorSet;\nimport android.animation.ObjectAnimator;\nimport android.annotation.SuppressLint;\nimport android.annotation.TargetApi;\nimport android.content.Context;\nimport android.content.res.TypedArray;\nimport android.graphics.Matrix;\nimport android.graphics.Path;\nimport android.graphics.PathMeasure;\nimport android.graphics.RectF;\nimport android.os.Build;\nimport android.os.Handler;\nimport android.os.Looper;\nimport android.support.design.widget.FloatingActionButton;\nimport android.support.v4.view.ViewCompat;\nimport android.util.AttributeSet;\nimport android.util.Log;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.view.animation.AccelerateInterpolator;\nimport android.view.animation.Animation;\nimport android.view.animation.Transformation;\nimport android.widget.FrameLayout;\nimport com.lxm.module_library.R;\nimport io.codetail.animation.ViewAnimationUtils;\n\n/**\n * Created by shem on 1/15/16.\n */\n@SuppressLint(\"RestrictedApi\")\npublic class MaterialLoginView extends FrameLayout {\n\n    private static final String TAG = MaterialLoginView.class.getSimpleName();\n\n    private FloatingActionButton registerFab;\n    private View registerCancel;\n    private ViewGroup loginCard;\n    private ViewGroup registerCard;\n    private View registerView;\n    private View loginView;\n\n    public MaterialLoginView(Context context) {\n        this(context, null);\n    }\n\n    public MaterialLoginView(Context context, AttributeSet attrs) {\n        this(context, attrs, 0);\n    }\n\n    public MaterialLoginView(Context context, AttributeSet attrs, int defStyleAttr) {\n        super(context, attrs, defStyleAttr);\n        init(context, attrs);\n    }\n\n    @TargetApi(Build.VERSION_CODES.LOLLIPOP)\n    public MaterialLoginView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {\n        super(context, attrs, defStyleAttr, defStyleRes);\n        init(context, attrs);\n    }\n\n    private void init(Context context, AttributeSet attrs) {\n        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);\n        inflater.inflate(R.layout.login_view, this, true);\n\n        loginCard = (ViewGroup) findViewById(R.id.login_card);\n        registerCard = (ViewGroup) findViewById(R.id.register_card);\n        registerFab = (FloatingActionButton) findViewById(R.id.register_fab);\n\n        registerFab.setOnClickListener(new OnClickListener() {\n            @Override\n            public void onClick(View v) {\n                if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {\n                    animateRegister();\n                } else {\n                    //There's a bug in support implementation of FAB, so we firing animation with little delay so it won't be override by Android\n                    new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {\n                        @Override\n                        public void run() {\n                            animateRegister();\n                        }\n                    }, 100);\n                }\n            }\n        });\n\n\n        TypedArray a = context.getTheme().obtainStyledAttributes(\n                attrs,\n                R.styleable.MaterialLoginView,\n                0, 0);\n\n        try {\n            int loginViewId = a.getResourceId(R.styleable.MaterialLoginView_loginView, R.layout.default_login_view);\n            inflate(getContext(), loginViewId, loginCard);\n            loginView = loginCard.getChildAt(0);\n\n            int registerViewId = a.getResourceId(R.styleable.MaterialLoginView_registerView, R.layout.default_register_view);\n            inflate(getContext(), registerViewId, registerCard);\n            registerView = registerCard.getChildAt(0);\n            if (registerView instanceof RegisterView) {\n                registerCancel = ((RegisterView) registerView).getCancelRegisterView();\n            }else if (registerView.findViewById(R.id.register_cancel) != null) {\n                registerCancel = registerView.findViewById(R.id.register_cancel);\n            }\n\n            if (registerCancel != null) {\n                registerCancel.setOnClickListener(new OnClickListener() {\n                    @Override\n                    public void onClick(View v) {\n                        animateLogin();\n                    }\n                });\n            } else {\n                Log.d(TAG, \"The register view should implement RegisterView interface or set a view with register_cancel id\");\n            }\n\n\n            registerFab.setImageResource(\n                    a.getResourceId(R.styleable.MaterialLoginView_registerIcon, R.drawable.ic_add));\n\n            boolean enabled = a.getBoolean(R.styleable.MaterialLoginView_registerEnabled, true);\n            registerFab.setVisibility(enabled ? View.VISIBLE : View.GONE);\n\n        } finally {\n            a.recycle();\n        }\n    }\n\n    private void animateRegister() {\n        Path path = new Path();\n        if (isRTL()) {\n            RectF rect = new RectF(-41F, -40F, 241F, 242F);\n            path.addArc(rect, -135F, -180F);\n            path.lineTo(200F, -50F);\n        } else {\n            RectF rect = new RectF(-241F, -40F, 41F, 242F);\n            path.addArc(rect, -45F, 180F);\n            path.lineTo(-0F, -50F);\n        }\n        FabAnimation fabAnimation = new FabAnimation(path);\n        fabAnimation.setDuration(400);\n        fabAnimation.setInterpolator(new AccelerateInterpolator());\n\n        fabAnimation.setAnimationListener(new Animation.AnimationListener() {\n            @Override\n            public void onAnimationStart(Animation animation) {\n                Animator animator = getCircularRevealAnimation(registerCard, isRTL() ? 250 : registerCard.getWidth() - 250, 400, 0f, 2F * registerCard.getHeight());\n                animator.setDuration(700);\n                animator.setStartDelay(200);\n                animator.addListener(new Animator.AnimatorListener() {\n                    @Override\n                    public void onAnimationStart(Animator animation) {\n                        registerCard.setVisibility(View.VISIBLE);\n                    }\n\n                    @Override\n                    public void onAnimationEnd(Animator animation) {\n                        loginCard.setVisibility(View.GONE);\n                    }\n\n                    @Override\n                    public void onAnimationCancel(Animator animation) {\n                    }\n\n                    @Override\n                    public void onAnimationRepeat(Animator animation) {\n                    }\n                });\n                animator.start();\n            }\n\n            @Override\n            public void onAnimationEnd(Animation animation) {\n                registerFab.setVisibility(View.GONE);\n            }\n\n            @Override\n            public void onAnimationRepeat(Animation animation) {\n            }\n        });\n\n        registerFab.startAnimation(fabAnimation);\n    }\n\n    private boolean isRTL() {\n        return ViewCompat.getLayoutDirection(this) == ViewCompat.LAYOUT_DIRECTION_RTL;\n    }\n\n    private Animator getCircularRevealAnimation(View view, int centerX, int centerY, float startRadius, float endRadius) {\n        return ViewAnimationUtils.createCircularReveal(\n                view, centerX, centerY, startRadius, endRadius);\n    }\n\n\n    public void animateLogin() {\n        registerCancel.animate().scaleX(0F).scaleY(0F).alpha(0F).rotation(90F).\n                setDuration(200).setInterpolator(new AccelerateInterpolator()).start();\n        Animator animator = getCircularRevealAnimation(registerCard, registerCard.getWidth() / 2, registerCard.getHeight() / 2, 1f * registerCard.getHeight(), 0F);\n        animator.setDuration(500);\n        animator.setStartDelay(100);\n        animator.addListener(new Animator.AnimatorListener() {\n            @Override\n            public void onAnimationStart(Animator animation) {\n                loginCard.setVisibility(View.VISIBLE);\n            }\n\n            @Override\n            public void onAnimationEnd(Animator animation) {\n                registerCard.setVisibility(View.GONE);\n                registerCancel.setScaleX(1F);\n                registerCancel.setScaleY(1F);\n                registerCancel.setAlpha(1F);\n                registerCancel.setRotation(0F);\n                registerFab.setVisibility(View.VISIBLE);\n\n                ObjectAnimator animX = ObjectAnimator.ofFloat(registerFab, \"scaleX\", 0F, 1F);\n                ObjectAnimator animY = ObjectAnimator.ofFloat(registerFab, \"scaleY\", 0F, 1F);\n                ObjectAnimator alpha = ObjectAnimator.ofFloat(registerFab, \"alpha\", 0F, 1F);\n                ObjectAnimator rotation = ObjectAnimator.ofFloat(registerFab, \"rotation\", 90F, 0F);\n                AnimatorSet animator = new AnimatorSet();\n                animator.playTogether(animX, animY, alpha, rotation);\n                animator.setInterpolator(new AccelerateInterpolator());\n                animator.setDuration(200);\n                animator.start();\n            }\n\n            @Override\n            public void onAnimationCancel(Animator animation) {\n\n            }\n\n            @Override\n            public void onAnimationRepeat(Animator animation) {\n\n            }\n        });\n        animator.start();\n    }\n\n    public View getLoginView() {\n        return loginView;\n    }\n\n    public View getRegisterView() {\n        return registerView;\n    }\n\n    class FabAnimation extends Animation {\n        private PathMeasure measure;\n        private float[] pos;\n\n        public FabAnimation(Path path) {\n            measure = new PathMeasure(path, false);\n            pos = new float[]{0, 0};\n        }\n\n\n        @Override\n        protected void applyTransformation(float interpolatedTime, Transformation t) {\n            measure.getPosTan(measure.getLength() * interpolatedTime, pos, null);\n            Matrix matrix = t.getMatrix();\n            matrix.setTranslate(pos[0], pos[1]);\n            matrix.preRotate(interpolatedTime * 45);\n            t.setAlpha(1 - interpolatedTime);\n        }\n    }\n}\n"
  },
  {
    "path": "module_library/src/main/java/com/lxm/module_library/materialLogin/RegisterView.java",
    "content": "package com.lxm.module_library.materialLogin;\n\nimport android.view.View;\n\n/**\n * Created by shem on 16/09/2016.\n */\npublic interface RegisterView {\n\n    View getCancelRegisterView();\n}\n"
  },
  {
    "path": "module_library/src/main/java/com/lxm/module_library/statusbar/StatusBarUtil.java",
    "content": "package com.lxm.module_library.statusbar;\n\nimport android.annotation.TargetApi;\nimport android.app.Activity;\nimport android.app.TabActivity;\nimport android.content.Context;\nimport android.graphics.Color;\nimport android.os.Build;\nimport android.support.annotation.ColorInt;\nimport android.support.v4.widget.DrawerLayout;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.view.WindowManager;\nimport android.widget.LinearLayout;\n\n/**\n * Created by Jaeger on 16/2/14.\n * <p>\n * Email: chjie.jaeger@gmail.com\n * GitHub: https://github.com/laobie\n */\npublic class StatusBarUtil {\n\n    public static final int DEFAULT_STATUS_BAR_ALPHA = 112;\n\n    /**\n     * 设置状态栏颜色\n     *\n     * @param activity 需要设置的 activity\n     * @param color    状态栏颜色值\n     */\n    public static void setColor(Activity activity, @ColorInt int color) {\n        setColor(activity, color, DEFAULT_STATUS_BAR_ALPHA);\n    }\n\n    /**\n     * 设置状态栏颜色\n     *\n     * @param activity       需要设置的activity\n     * @param color          状态栏颜色值\n     * @param statusBarAlpha 状态栏透明度\n     */\n\n    public static void setColor(Activity activity, @ColorInt int color, int statusBarAlpha) {\n        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {\n            activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);\n            activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);\n            activity.getWindow().setStatusBarColor(calculateStatusColor(color, statusBarAlpha));\n        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {\n            activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);\n            ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView();\n            int count = decorView.getChildCount();\n            if (count > 0 && decorView.getChildAt(count - 1) instanceof StatusBarView) {\n                decorView.getChildAt(count - 1).setBackgroundColor(calculateStatusColor(color, statusBarAlpha));\n            } else {\n                StatusBarView statusView = createStatusBarView(activity, color, statusBarAlpha);\n                decorView.addView(statusView);\n            }\n            setRootView(activity);\n        }\n    }\n\n    /**\n     * 设置状态栏纯色 不加半透明效果\n     *\n     * @param activity 需要设置的 activity\n     * @param color    状态栏颜色值\n     */\n    public static void setColorNoTranslucent(Activity activity, @ColorInt int color) {\n        setColor(activity, color, 0);\n    }\n\n    /**\n     * 设置状态栏颜色(5.0以下无半透明效果,不建议使用)\n     *\n     * @param activity 需要设置的 activity\n     * @param color    状态栏颜色值\n     */\n    @Deprecated\n    public static void setColorDiff(Activity activity, @ColorInt int color) {\n        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {\n            return;\n        }\n        activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);\n        // 生成一个状态栏大小的矩形\n        ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView();\n        int count = decorView.getChildCount();\n        if (count > 0 && decorView.getChildAt(count - 1) instanceof StatusBarView) {\n            decorView.getChildAt(count - 1).setBackgroundColor(color);\n        } else {\n            StatusBarView statusView = createStatusBarView(activity, color);\n            decorView.addView(statusView);\n        }\n        setRootView(activity);\n    }\n\n    /**\n     * 使状态栏半透明\n     * <p>\n     * 适用于图片作为背景的界面,此时需要图片填充到状态栏\n     *\n     * @param activity 需要设置的activity\n     */\n    public static void setTranslucent(Activity activity) {\n        setTranslucent(activity, DEFAULT_STATUS_BAR_ALPHA);\n    }\n\n    /**\n     * 使状态栏半透明\n     * <p>\n     * 适用于图片作为背景的界面,此时需要图片填充到状态栏\n     *\n     * @param activity       需要设置的activity\n     * @param statusBarAlpha 状态栏透明度\n     */\n    public static void setTranslucent(Activity activity, int statusBarAlpha) {\n        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {\n            return;\n        }\n        setTransparent(activity);\n        addTranslucentView(activity, statusBarAlpha);\n    }\n\n    /**\n     * 针对根布局是 CoordinatorLayout, 使状态栏半透明\n     * <p>\n     * 适用于图片作为背景的界面,此时需要图片填充到状态栏\n     *\n     * @param activity       需要设置的activity\n     * @param statusBarAlpha 状态栏透明度\n     */\n    public static void setTranslucentForCoordinatorLayout(Activity activity, int statusBarAlpha) {\n        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {\n            return;\n        }\n        transparentStatusBar(activity);\n        addTranslucentView(activity, statusBarAlpha);\n    }\n\n    /**\n     * 设置状态栏全透明\n     *\n     * @param activity 需要设置的activity\n     */\n    public static void setTransparent(Activity activity) {\n        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {\n            return;\n        }\n        transparentStatusBar(activity);\n        setRootView(activity);\n    }\n\n    /**\n     * 使状态栏透明(5.0以上半透明效果,不建议使用)\n     * <p>\n     * 适用于图片作为背景的界面,此时需要图片填充到状态栏\n     *\n     * @param activity 需要设置的activity\n     */\n    @Deprecated\n    public static void setTranslucentDiff(Activity activity) {\n        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {\n            // 设置状态栏透明\n            activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);\n            setRootView(activity);\n        }\n    }\n\n    /**\n     * 为DrawerLayout 布局设置状态栏变色\n     *\n     * @param activity     需要设置的activity\n     * @param drawerLayout DrawerLayout\n     * @param color        状态栏颜色值\n     */\n    public static void setColorForDrawerLayout(Activity activity, DrawerLayout drawerLayout, @ColorInt int color) {\n        setColorForDrawerLayout(activity, drawerLayout, color, DEFAULT_STATUS_BAR_ALPHA);\n    }\n\n    /**\n     * 为DrawerLayout 布局设置状态栏颜色,纯色\n     *\n     * @param activity     需要设置的activity\n     * @param drawerLayout DrawerLayout\n     * @param color        状态栏颜色值\n     */\n    public static void setColorNoTranslucentForDrawerLayout(Activity activity, DrawerLayout drawerLayout, @ColorInt int color) {\n        setColorForDrawerLayout(activity, drawerLayout, color, 0);\n    }\n\n    /**\n     * 为DrawerLayout 布局设置状态栏变色\n     *\n     * @param activity       需要设置的activity\n     * @param drawerLayout   DrawerLayout\n     * @param color          状态栏颜色值\n     * @param statusBarAlpha 状态栏透明度\n     */\n    public static void setColorForDrawerLayout(Activity activity, DrawerLayout drawerLayout, @ColorInt int color,\n                                               int statusBarAlpha) {\n        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {\n            return;\n        }\n        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {\n            activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);\n            activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);\n            activity.getWindow().setStatusBarColor(Color.TRANSPARENT);\n        } else {\n            activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);\n        }\n        // 生成一个状态栏大小的矩形\n        // 添加 statusBarView 到布局中\n        ViewGroup contentLayout = (ViewGroup) drawerLayout.getChildAt(0);\n        if (contentLayout.getChildCount() > 0 && contentLayout.getChildAt(0) instanceof StatusBarView) {\n            contentLayout.getChildAt(0).setBackgroundColor(calculateStatusColor(color, statusBarAlpha));\n        } else {\n            StatusBarView statusBarView = createStatusBarView(activity, color);\n            contentLayout.addView(statusBarView, 0);\n        }\n        // 内容布局不是 LinearLayout 时,设置padding top\n        if (!(contentLayout instanceof LinearLayout) && contentLayout.getChildAt(1) != null) {\n            contentLayout.getChildAt(1)\n                    .setPadding(contentLayout.getPaddingLeft(), getStatusBarHeight(activity) + contentLayout.getPaddingTop(),\n                            contentLayout.getPaddingRight(), contentLayout.getPaddingBottom());\n        }\n        // 设置属性\n        ViewGroup drawer = (ViewGroup) drawerLayout.getChildAt(1);\n        drawerLayout.setFitsSystemWindows(false);\n        contentLayout.setFitsSystemWindows(false);\n        contentLayout.setClipToPadding(true);\n        drawer.setFitsSystemWindows(false);\n\n        addTranslucentView(activity, statusBarAlpha);\n    }\n\n    /**\n     * 为DrawerLayout 布局设置状态栏变色(5.0以下无半透明效果,不建议使用)\n     *\n     * @param activity     需要设置的activity\n     * @param drawerLayout DrawerLayout\n     * @param color        状态栏颜色值\n     */\n    @Deprecated\n    public static void setColorForDrawerLayoutDiff(Activity activity, DrawerLayout drawerLayout, @ColorInt int color) {\n        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {\n            activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);\n            // 生成一个状态栏大小的矩形\n            ViewGroup contentLayout = (ViewGroup) drawerLayout.getChildAt(0);\n            if (contentLayout.getChildCount() > 0 && contentLayout.getChildAt(0) instanceof StatusBarView) {\n                contentLayout.getChildAt(0).setBackgroundColor(calculateStatusColor(color, DEFAULT_STATUS_BAR_ALPHA));\n            } else {\n                // 添加 statusBarView 到布局中\n                StatusBarView statusBarView = createStatusBarView(activity, color);\n                contentLayout.addView(statusBarView, 0);\n            }\n            // 内容布局不是 LinearLayout 时,设置padding top\n            if (!(contentLayout instanceof LinearLayout) && contentLayout.getChildAt(1) != null) {\n                contentLayout.getChildAt(1).setPadding(0, getStatusBarHeight(activity), 0, 0);\n            }\n            // 设置属性\n            ViewGroup drawer = (ViewGroup) drawerLayout.getChildAt(1);\n            drawerLayout.setFitsSystemWindows(false);\n            contentLayout.setFitsSystemWindows(false);\n            contentLayout.setClipToPadding(true);\n            drawer.setFitsSystemWindows(false);\n        }\n    }\n\n    /**\n     * 为 DrawerLayout 布局设置状态栏透明\n     *\n     * @param activity     需要设置的activity\n     * @param drawerLayout DrawerLayout\n     */\n    public static void setTranslucentForDrawerLayout(Activity activity, DrawerLayout drawerLayout) {\n        setTranslucentForDrawerLayout(activity, drawerLayout, DEFAULT_STATUS_BAR_ALPHA);\n    }\n\n    /**\n     * 为 DrawerLayout 布局设置状态栏透明\n     *\n     * @param activity     需要设置的activity\n     * @param drawerLayout DrawerLayout\n     */\n    public static void setTranslucentForDrawerLayout(Activity activity, DrawerLayout drawerLayout, int statusBarAlpha) {\n        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {\n            return;\n        }\n        setTransparentForDrawerLayout(activity, drawerLayout);\n        addTranslucentView(activity, statusBarAlpha);\n    }\n\n    /**\n     * 为 DrawerLayout 布局设置状态栏透明\n     *\n     * @param activity     需要设置的activity\n     * @param drawerLayout DrawerLayout\n     */\n    public static void setTransparentForDrawerLayout(Activity activity, DrawerLayout drawerLayout) {\n        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {\n            return;\n        }\n        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {\n            activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);\n            activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);\n            activity.getWindow().setStatusBarColor(Color.TRANSPARENT);\n        } else {\n            activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);\n        }\n\n        ViewGroup contentLayout = (ViewGroup) drawerLayout.getChildAt(0);\n        // 内容布局不是 LinearLayout 时,设置padding top\n        if (!(contentLayout instanceof LinearLayout) && contentLayout.getChildAt(1) != null) {\n            contentLayout.getChildAt(1).setPadding(0, getStatusBarHeight(activity), 0, 0);\n        }\n\n        // 设置属性\n        ViewGroup drawer = (ViewGroup) drawerLayout.getChildAt(1);\n        drawerLayout.setFitsSystemWindows(false);\n        contentLayout.setFitsSystemWindows(false);\n        contentLayout.setClipToPadding(true);\n        drawer.setFitsSystemWindows(false);\n    }\n\n    /**\n     * 为 DrawerLayout 布局设置状态栏透明(5.0以上半透明效果,不建议使用)\n     *\n     * @param activity     需要设置的activity\n     * @param drawerLayout DrawerLayout\n     */\n    @Deprecated\n    public static void setTranslucentForDrawerLayoutDiff(Activity activity, DrawerLayout drawerLayout) {\n        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {\n            // 设置状态栏透明\n            activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);\n            // 设置内容布局属性\n            ViewGroup contentLayout = (ViewGroup) drawerLayout.getChildAt(0);\n            contentLayout.setFitsSystemWindows(true);\n            contentLayout.setClipToPadding(true);\n            // 设置抽屉布局属性\n            ViewGroup vg = (ViewGroup) drawerLayout.getChildAt(1);\n            vg.setFitsSystemWindows(false);\n            // 设置 DrawerLayout 属性\n            drawerLayout.setFitsSystemWindows(false);\n        }\n    }\n\n    /**\n     * 为头部是 ImageView 的界面设置状态栏全透明\n     *\n     * @param activity       需要设置的activity\n     * @param needOffsetView 需要向下偏移的 View\n     */\n    public static void setTransparentForImageView(Activity activity, View needOffsetView) {\n        setTranslucentForImageView(activity, 0, needOffsetView);\n    }\n\n    /**\n     * 为头部是 ImageView 的界面设置状态栏透明(使用默认透明度)\n     *\n     * @param activity       需要设置的activity\n     * @param needOffsetView 需要向下偏移的 View\n     */\n    public static void setTranslucentForImageView(Activity activity, View needOffsetView) {\n        setTranslucentForImageView(activity, DEFAULT_STATUS_BAR_ALPHA, needOffsetView);\n    }\n\n    /**\n     * 为头部是 ImageView 的界面设置状态栏透明\n     *\n     * @param activity       需要设置的activity\n     * @param statusBarAlpha 状态栏透明度\n     * @param needOffsetView 需要向下偏移的 View\n     */\n    public static void setTranslucentForImageView(Activity activity, int statusBarAlpha, View needOffsetView) {\n        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {\n            return;\n        }\n        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {\n            activity.getWindow().setStatusBarColor(Color.TRANSPARENT);\n            activity.getWindow()\n                    .getDecorView()\n                    .setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);\n           if (activity instanceof TabActivity){\n               activity.getWindow()//兼容TabActivity\n                       .setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);\n           }\n        } else {\n            activity.getWindow()\n                    .setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);\n        }\n        addTranslucentView(activity, statusBarAlpha);\n        if (needOffsetView != null) {\n            ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) needOffsetView.getLayoutParams();\n            if (layoutParams != null) {\n                layoutParams.setMargins(0, getStatusBarHeight(activity), 0, 0);\n            }\n        }\n    }\n\n    public static void setMargin(Activity activity, View needOffsetView) {\n        if (needOffsetView != null) {\n            ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) needOffsetView.getLayoutParams();\n            if (layoutParams != null) {\n                layoutParams.setMargins(0, getStatusBarHeight(activity), 0, 0);\n            }\n        }\n    }\n\n\n    /**\n     * 为 fragment 头部是 ImageView 的设置状态栏透明\n     *\n     * @param activity       fragment 对应的 activity\n     * @param needOffsetView 需要向下偏移的 View\n     */\n    public static void setTranslucentForImageViewInFragment(Activity activity, View needOffsetView) {\n        setTranslucentForImageViewInFragment(activity, DEFAULT_STATUS_BAR_ALPHA, needOffsetView);\n    }\n\n    /**\n     * 为 fragment 头部是 ImageView 的设置状态栏透明\n     *\n     * @param activity       fragment 对应的 activity\n     * @param needOffsetView 需要向下偏移的 View\n     */\n    public static void setTransparentForImageViewInFragment(Activity activity, View needOffsetView) {\n        setTranslucentForImageViewInFragment(activity, 0, needOffsetView);\n    }\n\n    /**\n     * 为 fragment 头部是 ImageView 的设置状态栏透明\n     *\n     * @param activity       fragment 对应的 activity\n     * @param statusBarAlpha 状态栏透明度\n     * @param needOffsetView 需要向下偏移的 View\n     */\n    public static void setTranslucentForImageViewInFragment(Activity activity, int statusBarAlpha, View needOffsetView) {\n        setTranslucentForImageView(activity, statusBarAlpha, needOffsetView);\n        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {\n            clearPreviousSetting(activity);\n        }\n    }\n\n    @TargetApi(Build.VERSION_CODES.KITKAT)\n    private static void clearPreviousSetting(Activity activity) {\n        ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView();\n        int count = decorView.getChildCount();\n        if (count > 0 && decorView.getChildAt(count - 1) instanceof StatusBarView) {\n            decorView.removeViewAt(count - 1);\n            ViewGroup rootView = (ViewGroup) ((ViewGroup) activity.findViewById(android.R.id.content)).getChildAt(0);\n            rootView.setPadding(0, 0, 0, 0);\n        }\n    }\n\n    /**\n     * 添加半透明矩形条\n     *\n     * @param activity       需要设置的 activity\n     * @param statusBarAlpha 透明值\n     */\n    private static void addTranslucentView(Activity activity, int statusBarAlpha) {\n        ViewGroup contentView = (ViewGroup) activity.findViewById(android.R.id.content);\n        if (contentView.getChildCount() > 1) {\n            contentView.getChildAt(1).setBackgroundColor(Color.argb(statusBarAlpha, 0, 0, 0));\n        } else {\n            contentView.addView(createTranslucentStatusBarView(activity, statusBarAlpha));\n        }\n    }\n\n    /**\n     * 生成一个和状态栏大小相同的彩色矩形条\n     *\n     * @param activity 需要设置的 activity\n     * @param color    状态栏颜色值\n     * @return 状态栏矩形条\n     */\n    private static StatusBarView createStatusBarView(Activity activity, @ColorInt int color) {\n        // 绘制一个和状态栏一样高的矩形\n        StatusBarView statusBarView = new StatusBarView(activity);\n        LinearLayout.LayoutParams params =\n                new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getStatusBarHeight(activity));\n        statusBarView.setLayoutParams(params);\n        statusBarView.setBackgroundColor(color);\n        return statusBarView;\n    }\n\n    /**\n     * 生成一个和状态栏大小相同的半透明矩形条\n     *\n     * @param activity 需要设置的activity\n     * @param color    状态栏颜色值\n     * @param alpha    透明值\n     * @return 状态栏矩形条\n     */\n    private static StatusBarView createStatusBarView(Activity activity, @ColorInt int color, int alpha) {\n        // 绘制一个和状态栏一样高的矩形\n        StatusBarView statusBarView = new StatusBarView(activity);\n        LinearLayout.LayoutParams params =\n                new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getStatusBarHeight(activity));\n        statusBarView.setLayoutParams(params);\n        statusBarView.setBackgroundColor(calculateStatusColor(color, alpha));\n        return statusBarView;\n    }\n\n    /**\n     * 设置根布局参数\n     */\n    private static void setRootView(Activity activity) {\n        ViewGroup rootView = (ViewGroup) ((ViewGroup) activity.findViewById(android.R.id.content)).getChildAt(0);\n        rootView.setFitsSystemWindows(true);\n        rootView.setClipToPadding(true);\n    }\n\n    /**\n     * 使状态栏透明\n     */\n    @TargetApi(Build.VERSION_CODES.KITKAT)\n    private static void transparentStatusBar(Activity activity) {\n        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {\n            activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);\n            activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);\n            activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);\n            activity.getWindow().setStatusBarColor(Color.TRANSPARENT);\n        } else {\n            activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);\n        }\n    }\n\n    /**\n     * 创建半透明矩形 View\n     *\n     * @param alpha 透明值\n     * @return 半透明 View\n     */\n    private static StatusBarView createTranslucentStatusBarView(Activity activity, int alpha) {\n        // 绘制一个和状态栏一样高的矩形\n        StatusBarView statusBarView = new StatusBarView(activity);\n        LinearLayout.LayoutParams params =\n                new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getStatusBarHeight(activity));\n        statusBarView.setLayoutParams(params);\n        statusBarView.setBackgroundColor(Color.argb(alpha, 0, 0, 0));\n        return statusBarView;\n    }\n\n    /**\n     * 获取状态栏高度\n     *\n     * @param context context\n     * @return 状态栏高度\n     */\n    public static int getStatusBarHeight(Context context) {\n        // 获得状态栏高度\n        int resourceId = context.getResources().getIdentifier(\"status_bar_height\", \"dimen\", \"android\");\n        return context.getResources().getDimensionPixelSize(resourceId);\n    }\n\n    /**\n     * 计算状态栏颜色\n     *\n     * @param color color值\n     * @param alpha alpha值\n     * @return 最终的状态栏颜色\n     */\n    private static int calculateStatusColor(@ColorInt int color, int alpha) {\n        float a = 1 - alpha / 255f;\n        int red = color >> 16 & 0xff;\n        int green = color >> 8 & 0xff;\n        int blue = color & 0xff;\n        red = (int) (red * a + 0.5);\n        green = (int) (green * a + 0.5);\n        blue = (int) (blue * a + 0.5);\n        return 0xff << 24 | red << 16 | green << 8 | blue;\n    }\n\n}\n"
  },
  {
    "path": "module_library/src/main/java/com/lxm/module_library/statusbar/StatusBarView.java",
    "content": "package com.lxm.module_library.statusbar;\n\nimport android.content.Context;\nimport android.util.AttributeSet;\nimport android.view.View;\n\n/**\n * Created by Jaeger on 16/6/8.\n *\n * Email: chjie.jaeger@gmail.com\n * GitHub: https://github.com/laobie\n */\npublic class StatusBarView extends View {\n    public StatusBarView(Context context, AttributeSet attrs) {\n        super(context, attrs);\n    }\n\n    public StatusBarView(Context context) {\n        super(context);\n    }\n}\n"
  },
  {
    "path": "module_library/src/main/java/com/lxm/module_library/utils/AppUtils.kt",
    "content": "package com.lxm.module_library.utils\n\nimport android.Manifest\nimport android.annotation.SuppressLint\nimport android.content.ClipData\nimport android.content.ClipboardManager\nimport android.content.Context\nimport android.content.Intent\nimport android.content.pm.PackageManager\nimport android.net.Uri\nimport android.os.Environment\nimport android.os.Handler\nimport android.support.v4.app.ActivityCompat\nimport android.telephony.TelephonyManager\nimport android.util.Log\nimport android.view.inputmethod.InputMethodManager\nimport android.widget.EditText\nimport com.lxm.module_library.global.GlobalApplication\nimport java.io.File\n\n/**\n *\n * App工具类\n */\nobject AppUtils {\n\n    /**\n     * 获取上下文对象\n     *\n     * @return 上下文对象\n     */\n  val context: Context\n        get() = GlobalApplication.getContext()\n\n    /**\n     * 获取全局handler\n     *\n     * @return 全局handler\n     */\n    private val handler: Handler\n        get() = GlobalApplication.getHandler()\n\n    /**\n     * 获取主线程id\n     *\n     * @return 主线程id\n     */\n    private val mainThreadId: Int\n        get() = GlobalApplication.getMainThreadId()\n\n    /**\n     * 获取SD卡路径\n     *\n     * @return 如果sd卡不存在则返回null\n     */\n    private//判断sd卡是否存在\n    val sdPath: File?\n        get() {\n            var sdDir: File? = null\n            val sdCardExist = Environment.getExternalStorageState() == Environment\n                    .MEDIA_MOUNTED\n            if (sdCardExist) {\n                sdDir = Environment.getExternalStorageDirectory()\n            }\n            return sdDir\n        }\n\n    /**\n     * 判断是否运行在主线程\n     *\n     * @return true：当前线程运行在主线程\n     * fasle：当前线程没有运行在主线程\n     */\n    private// 获取当前线程id, 如果当前线程id和主线程id相同, 那么当前就是主线程\n    val isRunOnUIThread: Boolean\n        get() {\n            val myTid = android.os.Process.myTid()\n            return if (myTid == mainThreadId) {\n                true\n            } else false\n        }\n\n    /**\n     * 获取版本名称\n     */\n    private fun getAppVersionName(context: Context): String? {\n        var versionName: String? = null\n        try {\n            // ---get the package info---\n            val pm = context.packageManager\n            val pi = pm.getPackageInfo(context.packageName, 0)\n            versionName = pi.versionName\n            if (versionName == null || versionName.length <= 0) {\n                return \"\"\n            }\n        } catch (e: Exception) {\n            Log.e(\"VersionInfo\", \"Exception\", e)\n        }\n\n        return versionName\n    }\n\n    /**\n     * 获取版本号\n     */\n    private fun getAppVersionCode(context: Context): Int {\n        var versioncode = -1\n        try {\n            // ---get the package info---\n            val pm = context.packageManager\n            val pi = pm.getPackageInfo(context.packageName, 0)\n            versioncode = pi.versionCode\n        } catch (e: Exception) {\n            Log.e(\"VersionInfo\", \"Exception\", e)\n        }\n\n        return versioncode\n    }\n\n    @SuppressLint(\"MissingPermission\")\n    private fun getIMEI(context: Context): String? {\n        val tm = context.getSystemService(Context\n                .TELEPHONY_SERVICE) as TelephonyManager\n        return if (ActivityCompat.checkSelfPermission(context, Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED) {\n            tm.deviceId\n        } else null\n    }\n\n    /**\n     * 显示软键盘\n     */\n    private fun openSoftInput(et: EditText) {\n        val inputMethodManager = et.context\n                .getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager\n        inputMethodManager.showSoftInput(et, InputMethodManager.HIDE_NOT_ALWAYS)\n    }\n\n    /**\n     * 隐藏软键盘\n     */\n    private fun hideSoftInput(et: EditText) {\n        val inputMethodManager = et.context\n                .getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager\n        inputMethodManager.hideSoftInputFromWindow(et.windowToken, InputMethodManager\n                .HIDE_NOT_ALWAYS)\n    }\n\n    /**\n     * 安装文件\n     *\n     * @param data\n     */\n    private fun promptInstall(context: Context, data: Uri) {\n        val promptInstall = Intent(Intent.ACTION_VIEW)\n                .setDataAndType(data, \"application/vnd.android.package-archive\")\n        // FLAG_ACTIVITY_NEW_TASK 可以保证安装成功时可以正常打开 app\n        promptInstall.flags = Intent.FLAG_ACTIVITY_NEW_TASK\n        context.startActivity(promptInstall)\n    }\n\n    fun copy2clipboard(context: Context, text: String) {\n        val cm = context.getSystemService(Context\n                .CLIPBOARD_SERVICE) as ClipboardManager\n        val clip = ClipData.newPlainText(\"clip\", text)\n        cm.primaryClip = clip\n    }\n\n    /**\n     * 运行在主线程\n     *\n     * @param r 运行的Runnable对象\n     */\n    private fun runOnUIThread(r: Runnable) {\n        if (isRunOnUIThread) {\n            // 已经是主线程, 直接运行\n            r.run()\n        } else {\n            // 如果是子线程, 借助handler让其运行在主线程\n            handler.post(r)\n        }\n    }\n}\n"
  },
  {
    "path": "module_library/src/main/java/com/lxm/module_library/utils/BaseTools.java",
    "content": "package com.lxm.module_library.utils;\n\nimport android.app.Activity;\nimport android.app.ActivityManager;\nimport android.content.ClipData;\nimport android.content.ClipboardManager;\nimport android.content.Context;\nimport android.content.Intent;\nimport android.content.pm.PackageInfo;\nimport android.content.pm.PackageManager;\nimport android.net.Uri;\nimport android.text.TextUtils;\nimport android.util.DisplayMetrics;\nimport android.util.Log;\nimport android.view.View;\nimport android.view.WindowManager;\nimport android.view.inputmethod.InputMethodManager;\nimport android.widget.TextView;\nimport com.lxm.module_library.global.GlobalApplication;\n\nimport java.lang.reflect.Field;\nimport java.text.DecimalFormat;\nimport java.text.NumberFormat;\nimport java.util.List;\nimport java.util.Locale;\n\n/**\n * Created by jingbin on 2017/2/13.\n */\n\npublic class BaseTools {\n\n    //获取图片所在文件夹名称\n    public static String getDir(String path) {\n        String subString = path.substring(0, path.lastIndexOf('/'));\n        return subString.substring(subString.lastIndexOf('/') + 1, subString.length());\n    }\n\n    public static int getWindowWidth(Context context) {\n        // 获取屏幕分辨率\n        WindowManager wm = (WindowManager) (context\n                .getSystemService(Context.WINDOW_SERVICE));\n        DisplayMetrics dm = new DisplayMetrics();\n        wm.getDefaultDisplay().getMetrics(dm);\n        int mScreenWidth = dm.widthPixels;\n        return mScreenWidth;\n    }\n\n    public static int getWindowHeigh(Context context) {\n        // 获取屏幕分辨率\n        WindowManager wm = (WindowManager) (context\n                .getSystemService(Context.WINDOW_SERVICE));\n        DisplayMetrics dm = new DisplayMetrics();\n        wm.getDefaultDisplay().getMetrics(dm);\n        int mScreenHeigh = dm.heightPixels;\n        return mScreenHeigh;\n    }\n\n    //获得状态栏/通知栏的高度\n    public static int getStatusBarHeight(Context context) {\n        Class<?> c = null;\n        Object obj = null;\n        Field field = null;\n        int x = 0, statusBarHeight = 0;\n        try {\n            c = Class.forName(\"com.android.internal.R$dimen\");\n            obj = c.newInstance();\n            field = c.getField(\"status_bar_height\");\n            x = Integer.parseInt(field.get(obj).toString());\n            statusBarHeight = context.getResources().getDimensionPixelSize(x);\n        } catch (Exception e1) {\n            e1.printStackTrace();\n        }\n        return statusBarHeight;\n    }\n\n    /**\n     * 使用默认方式显示货币：\n     * 例如:￥12,345.46 默认保留2位小数，四舍五入\n     *\n     * @param d double\n     * @return String\n     */\n    public static String formatCurrency(double d) {\n        String s = \"\";\n        try {\n            DecimalFormat nf = (DecimalFormat) NumberFormat.getCurrencyInstance(Locale.CHINA);\n            s = nf.format(d);\n        } catch (Exception e) {\n            e.printStackTrace();\n            return \"\" + d;\n        }\n        return s;\n    }\n\n\n    /**\n     * 去掉无效小数点 \".00\"\n     */\n\n    public static String formatMoney(double d) {\n        String tmp = formatCurrency(d);\n\n        if (tmp.endsWith(\".00\")) {\n            return tmp.substring(0, tmp.length() - 3);\n        } else {\n            return tmp;\n        }\n    }\n\n\n    /**\n     * 处于栈顶的Activity名\n     */\n    public String getTopActivityName(Context context) {\n        ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);\n        List var2 = am.getRunningTasks(1);\n        return ((ActivityManager.RunningTaskInfo) var2.get(0)).topActivity.getClassName();\n    }\n\n    public static void setText(String text, TextView textView) {\n        if (textView != null) {\n            if (TextUtils.isEmpty(text)) {\n                textView.setText(\"\");\n            } else {\n                textView.setText(text);\n            }\n        }\n    }\n\n    /**\n     * 获取当前应用的版本号\n     */\n    public static String getVersionName() {\n        // 获取packagemanager的实例\n        PackageManager packageManager = GlobalApplication.getInstance().getPackageManager();\n        // getPackageName()是你当前类的包名，0代表是获取版本信息\n        PackageInfo packInfo = null;\n        try {\n            packInfo = packageManager.getPackageInfo(GlobalApplication.getInstance().getPackageName(), 0);\n            return packInfo.versionName;\n        } catch (PackageManager.NameNotFoundException e) {\n            e.printStackTrace();\n            return \"1.0\";\n        }\n    }\n\n    /**\n     * 实现文本复制功能\n     *\n     * @param content 复制的文本\n     */\n    public static void copy(String content) {\n        if (!TextUtils.isEmpty(content)) {\n            // 得到剪贴板管理器\n            ClipboardManager cmb = (ClipboardManager) GlobalApplication.getInstance().getSystemService(Context.CLIPBOARD_SERVICE);\n            cmb.setText(content.trim());\n            // 创建一个剪贴数据集，包含一个普通文本数据条目（需要复制的数据）\n            ClipData clipData = ClipData.newPlainText(null, content);\n            // 把数据集设置（复制）到剪贴板\n            cmb.setPrimaryClip(clipData);\n        }\n    }\n\n\n    /**\n     * 清空剪切板内容\n     * 加上  manager.setText(null);  不然小米3Android6.0 清空无效\n     * 因为api过期使用最新注意使用 manager.getPrimaryClip()，不然小米3Android6.0 清空无效\n     */\n    public static void clearClipboard() {\n        ClipboardManager manager = (ClipboardManager) GlobalApplication.getInstance().getSystemService(Context.CLIPBOARD_SERVICE);\n        if (manager != null) {\n            try {\n                manager.setPrimaryClip(manager.getPrimaryClip());\n                manager.setText(null);\n            } catch (Exception e) {\n            }\n        }\n    }\n\n\n    /**\n     * 使用浏览器打开链接\n     */\n    public static void openLink(Context context, String content) {\n        Uri issuesUrl = Uri.parse(content);\n        Intent intent = new Intent(Intent.ACTION_VIEW, issuesUrl);\n        context.startActivity(intent);\n    }\n\n    /**\n     * 判断手机是否安装某个应用\n     *\n     * @param context\n     * @param appPackageName 应用包名\n     * @return true：安装，false：未安装\n     */\n    public static boolean isApplicationAvilible(Context context, String appPackageName) {\n        try {\n            // 获取packagemanager\n            PackageManager packageManager = context.getPackageManager();\n            // 获取所有已安装程序的包信息\n            List<PackageInfo> pinfo = packageManager.getInstalledPackages(0);\n            if (pinfo != null) {\n                for (int i = 0; i < pinfo.size(); i++) {\n                    String pn = pinfo.get(i).packageName;\n                    if (appPackageName.equals(pn)) {\n                        return true;\n                    }\n                }\n            }\n            return false;\n        } catch (Exception ignored) {\n            return false;\n        }\n    }\n\n    /**\n     * 隐藏软键盘\n     *\n     * @param activity 要隐藏软键盘的activity\n     */\n    public static void hideSoftKeyBoard(Activity activity) {\n\n        final View v = activity.getWindow().peekDecorView();\n        if (v != null && v.getWindowToken() != null) {\n            try {\n                ((InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE)).hideSoftInputFromWindow(activity.getCurrentFocus()\n                        .getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);\n            } catch (Exception e) {\n                Log.w(\"TAG\", e.toString());\n            }\n        }\n    }\n\n    /**\n     * 显示软键盘\n     */\n    public static void showSoftKeyBoard(Activity activity, View view) {\n        ((InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE)).showSoftInput(view, 0);\n    }\n\n    /**\n     * 发起添加群流程。群号：Android 云阅交流群(727379132) 的 key 为： jSdY9xxzZ7xXG55_V8OUb8ds_YT6JjAn\n     * 调用 joinQQGroup(jSdY9xxzZ7xXG55_V8OUb8ds_YT6JjAn) 即可发起手Q客户端申请加群 Android 云阅交流群(727379132)\n     *\n     * @param key 由官网生成的key\n     */\n    public static void joinQQGroup(Context context, String key) {\n        Intent intent = new Intent();\n        intent.setData(Uri.parse(\"mqqopensdkapi://bizAgent/qm/qr?url=http%3A%2F%2Fqm.qq.com%2Fcgi-bin%2Fqm%2Fqr%3Ffrom%3Dapp%26p%3Dandroid%26k%3D\" + key));\n        // 此Flag可根据具体产品需要自定义，如设置，则在加群界面按返回，返回手Q主界面，不设置，按返回会返回到呼起产品界面    //intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)\n        try {\n            context.startActivity(intent);\n        } catch (Exception e) {\n            // 未安装手Q或安装的版本不支持\n            ToastUtil.showToastLong(\"未安装手Q或安装的版本不支持~\");\n        }\n    }\n\n    public static void joinQQChat(Context context, String qqNumber) {\n        Intent intent = new Intent();\n        intent.setData(Uri.parse(\"mqqwpa://im/chat?chat_type=wpa&uin=\" + qqNumber));\n        try {\n            context.startActivity(intent);\n        } catch (Exception e) {\n            // 未安装手Q或安装的版本不支持\n            ToastUtil.showToastLong(\"未安装手Q或安装的版本不支持~\");\n        }\n    }\n\n}\n"
  },
  {
    "path": "module_library/src/main/java/com/lxm/module_library/utils/BitmapUtils.kt",
    "content": "package com.lxm.module_library.utils\n\nimport android.content.Context\nimport android.content.res.Resources\nimport android.graphics.Bitmap\nimport android.graphics.BitmapFactory\nimport android.graphics.Canvas\nimport android.graphics.drawable.BitmapDrawable\nimport android.graphics.drawable.Drawable\nimport android.os.Build\nimport android.renderscript.Allocation\nimport android.renderscript.Element\nimport android.renderscript.RenderScript\nimport android.renderscript.ScriptIntrinsicBlur\nimport android.view.View\nimport java.io.*\n\n/**\n *\n * 图片工具类\n */\nobject BitmapUtils {\n\n    /**\n     * 将一个view转换成bitmap位图\n     *\n     * @param view 要转换的View\n     * @return view转换的bitmap\n     */\n    fun viewToBitmap(view: View): Bitmap {\n        val bitmap = Bitmap.createBitmap(view.measuredWidth, view.measuredHeight,\n                Bitmap.Config.ARGB_8888)\n        view.draw(Canvas(bitmap))\n        return bitmap\n    }\n\n    /**\n     * 获取模糊虚化的bitmap\n     *\n     * @param context\n     * @param bitmap  要模糊的图片\n     * @param radius  模糊等级 >=0 && <=25\n     * @return\n     */\n    fun getBlurBitmap(context: Context, bitmap: Bitmap, radius: Int): Bitmap {\n        return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {\n            blurBitmap(context, bitmap, radius)\n        } else bitmap\n    }\n\n    /**\n     * android系统的模糊方法\n     *\n     * @param bitmap 要模糊的图片\n     * @param radius 模糊等级 >=0 && <=25\n     */\n    private fun blurBitmap(context: Context, bitmap: Bitmap, radius: Int): Bitmap {\n        if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {\n            val outBitmap = Bitmap.createBitmap(bitmap.width, bitmap.height, Bitmap\n                    .Config.ARGB_8888)\n            val rs = RenderScript.create(context)\n            val blurScript = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs))\n\n            val allIn = Allocation.createFromBitmap(rs, bitmap)\n            val allOut = Allocation.createFromBitmap(rs, outBitmap)\n\n            blurScript.setRadius(radius.toFloat())\n            blurScript.setInput(allIn)\n            blurScript.forEach(allOut)\n            allOut.copyTo(outBitmap)\n            bitmap.recycle()\n            rs.destroy()\n            return outBitmap\n        } else {\n            return bitmap\n        }\n    }\n\n    /**\n     * 根据资源获取Bitmap\n     */\n    open fun getFitSampleBitmap(resources: Resources, id:Int, width: Int, height: Int):Bitmap{\n        var options = BitmapFactory.Options()\n        options.inJustDecodeBounds = true\n        BitmapFactory.decodeResource(resources,id,options)\n        options.inSampleSize = getFitInSampleSize(height,width,options)\n        options.inJustDecodeBounds = false\n        return BitmapFactory.decodeResource(resources,id)\n    }\n\n    /**\n     * 按图片尺寸压缩 参数是bitmap\n     * @param bitmap\n     * @param pixelW\n     * @param pixelH\n     * @return\n     */\n    fun compressImageFromBitmap(bitmap: Bitmap, pixelW: Int, pixelH: Int): Bitmap {\n        val os = ByteArrayOutputStream()\n        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, os)\n        if (os.toByteArray().size / 1024 > 512) {//判断如果图片大于0.5M,进行压缩避免在生成图片（BitmapFactory.decodeStream）时溢出\n            os.reset()\n            bitmap.compress(Bitmap.CompressFormat.JPEG, 50, os)//这里压缩50%，把压缩后的数据存放到baos中\n        }\n        var `is` = ByteArrayInputStream(os.toByteArray())\n        val options = BitmapFactory.Options()\n        options.inJustDecodeBounds = true\n        options.inPreferredConfig = Bitmap.Config.RGB_565\n        BitmapFactory.decodeStream(`is`, null, options)\n        options.inJustDecodeBounds = false\n        options.inSampleSize = getFitInSampleSize(if (pixelH > pixelW) pixelW else pixelH, pixelW * pixelH,options)\n        `is` = ByteArrayInputStream(os.toByteArray())\n        return BitmapFactory.decodeStream(`is`, null, options)\n    }\n\n    /**\n     * 根据文件路径获取Bitmap\n     */\n    private  fun getFitSampleBitmap(path: String, width: Int, height: Int):Bitmap{\n        var options = BitmapFactory.Options()\n        options.inJustDecodeBounds = true\n        BitmapFactory.decodeFile(path,options)\n        options.inSampleSize = getFitInSampleSize(height,width,options)\n        options.inJustDecodeBounds = false\n        return BitmapFactory.decodeFile(path,options)\n    }\n\n    /**\n     * 根据字节流获取Bitmap\n     */\n    fun getFitSimpleBitmap(inputStream: InputStream, filePath:String, width: Int, height: Int):Bitmap{\n        return getFitSampleBitmap(createStreamToFile(filePath,inputStream),width,height)\n    }\n\n    fun createStreamToFile(path: String,inputStream:InputStream):String{\n\n        var  file = File(path)\n        if (file.exists()){\n            file.delete()\n        }\n        file.createNewFile()\n\n        var outputStream = FileOutputStream(file)\n        var byte = ByteArray(1024)\n        var len = 0\n        while ((inputStream.read(byte))!= -1){\n            len = inputStream.read(byte)\n            outputStream.write(byte,0,len)\n        }\n\n        inputStream.close()\n        outputStream.close()\n        return path\n\n    }\n\n\n    /**\n     * 获取压缩比例\n     */\n    private fun getFitInSampleSize( height:Int,width:Int,options: BitmapFactory.Options):Int{\n        var inSampleSize = 1\n        if (options.outWidth > width || options.outHeight > height){\n            var widthRadio : Int = Math.round(options.outWidth.toFloat() / width.toFloat())\n            var heightRadio : Int = Math.round(options.outHeight.toFloat() / height.toFloat())\n            inSampleSize = Math.min(widthRadio,heightRadio)\n        }\n        return inSampleSize\n    }\n\n    /**\n     * Drawable To Bitmap\n     */\n    private fun drawableToBitamp(drawable: Drawable): Bitmap {\n        if (drawable is BitmapDrawable) {\n            return drawable.bitmap\n        }\n        val w = drawable.intrinsicWidth\n        val h = drawable.intrinsicHeight\n        val bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888)\n        val canvas = Canvas(bitmap)\n        drawable.setBounds(0, 0, w, h)\n        drawable.draw(canvas)\n        return bitmap\n    }\n\n    /**\n     * 压缩图片质量\n     */\n    fun compressImage(bitmap: Bitmap): Bitmap {\n        val baos = ByteArrayOutputStream()\n        //质量压缩方法，这里100表示不压缩，把压缩后的数据存放到baos中\n        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos)\n        var options = 100\n        //循环判断如果压缩后图片是否大于50kb,大于继续压缩\n        while (baos.toByteArray().size / 1024 > 50) {\n            baos.reset()\n            bitmap.compress(Bitmap.CompressFormat.JPEG, options, baos)\n            options -= 10//每次都减少10\n        }\n        //把压缩后的数据baos存放到ByteArrayInputStream中\n        val isBm = ByteArrayInputStream(baos.toByteArray())\n        //把ByteArrayInputStream数据生成图片\n        return BitmapFactory.decodeStream(isBm, null, null)\n    }\n}"
  },
  {
    "path": "module_library/src/main/java/com/lxm/module_library/utils/CheckNetwork.java",
    "content": "package com.lxm.module_library.utils;\n\nimport android.content.Context;\nimport android.net.ConnectivityManager;\nimport android.net.NetworkInfo;\n\n/**\n * 用于判断是不是联网状态\n *\n * @author Dzy\n */\npublic class CheckNetwork {\n\n    /**\n     * 判断网络是否连通\n     */\n    public static boolean isNetworkConnected(Context context) {\n        try {\n            if(context!=null){\n                @SuppressWarnings(\"static-access\")\n                ConnectivityManager cm = (ConnectivityManager) context\n                        .getSystemService(context.CONNECTIVITY_SERVICE);\n                NetworkInfo info = cm.getActiveNetworkInfo();\n                return info != null && info.isConnected();\n            }else{\n                /**如果context为空，就返回false，表示网络未连接*/\n                return false;\n            }\n        }catch (Exception e){\n            e.printStackTrace();\n            return false;\n        }\n\n\n    }\n\n    public static boolean isWifiConnected(Context context) {\n        if (context != null) {\n            ConnectivityManager cm = (ConnectivityManager) context\n                    .getSystemService(context.CONNECTIVITY_SERVICE);\n            NetworkInfo info = cm.getActiveNetworkInfo();\n            return info != null && (info.getType() == ConnectivityManager.TYPE_WIFI);\n        } else {\n            /**如果context为null就表示为未连接*/\n            return false;\n        }\n\n    }\n\n}\n"
  },
  {
    "path": "module_library/src/main/java/com/lxm/module_library/utils/ClassUtil.kt",
    "content": "package com.lxm.module_library.utils\n\nimport android.arch.lifecycle.AndroidViewModel\nimport android.arch.lifecycle.ViewModel\nimport com.lxm.module_library.base.NoViewModel\nimport java.lang.reflect.ParameterizedType\n\n\nobject ClassUtil {\n\n    /**\n     * 获取泛型ViewModel的class对象\n     */\n    fun <T> getViewModel(obj: Any): Class<T>? {\n        val currentClass = obj.javaClass\n        val tClass = getGenericClass<T>(currentClass, ViewModel::class.java)\n        return if (tClass == null || tClass == AndroidViewModel::class.java || tClass == NoViewModel::class.java) {\n            null\n        } else tClass\n    }\n\n    private fun <T> getGenericClass(klass: Class<*>, filterClass: Class<*>): Class<T>? {\n        val type = klass.genericSuperclass\n        if (type == null || type !is ParameterizedType) return null\n        val types = type.actualTypeArguments\n        for (t in types) {\n            val tClass = t as Class<T>\n            if (filterClass.isAssignableFrom(tClass)) {\n                return tClass\n            }\n        }\n        return null\n    }\n}\n"
  },
  {
    "path": "module_library/src/main/java/com/lxm/module_library/utils/DateUtils.kt",
    "content": "package com.lxm.module_library.utils\n\n\nimport android.annotation.SuppressLint\nimport android.text.TextUtils\nimport android.text.format.DateFormat\nimport java.text.ParseException\nimport java.text.SimpleDateFormat\nimport java.util.*\n\n/**\n * Created by Horrarndoo on 2017/8/31.\n *\n * 日期时间工具类\n */\nobject DateUtils {\n\n    private const val ONE_SECOND_MILLIONS: Long = 1000\n    private const val ONE_MINUTE_MILLIONS = 60 * ONE_SECOND_MILLIONS\n    private const val ONE_HOUR_MILLIONS = 60 * ONE_MINUTE_MILLIONS\n    private const val ONE_DAY_MILLIONS = 24 * ONE_HOUR_MILLIONS\n    private const val DAY_OF_YEAR = 365\n\n    /**\n     * 日期格式为 2016-02-03 17:04:58\n     */\n    private const val PATTERN_DATE = \"yyyy年MM月dd日\"\n    private const val PATTERN_TIME = \"HH:mm:ss\"\n    private const val PATTERN_SPLIT = \" \"\n    private const val PATTERN = PATTERN_DATE + PATTERN_SPLIT + PATTERN_TIME\n\n    fun getShortTime(dateStr: String): String {\n        val str: String\n\n        val date = str2date(dateStr)\n        val curDate = Date()\n\n        val durTime = curDate.time - date!!.time\n        val dayDiff = calculateDayDiff(date, curDate)\n\n        return if (durTime <= 10 * ONE_MINUTE_MILLIONS) {\n            \"刚刚\"\n        } else if (durTime < ONE_HOUR_MILLIONS) {\n            (durTime / ONE_MINUTE_MILLIONS).toString() + \"分钟前\"\n        } else if (dayDiff == 0) {\n            (durTime / ONE_HOUR_MILLIONS).toString() + \"小时前\"\n        } else if (dayDiff == -1) {\n            \"昨天\" + DateFormat.format(\"HH:mm\", date)\n        } else if (isSameYear(date, curDate) && dayDiff < -1) {\n            DateFormat.format(\"MM-dd\", date).toString()\n        } else {\n            DateFormat.format(\"yyyy-MM\", date).toString()\n        }\n\n    }\n\n\n    /**\n     * 获取日期 PATTERN_DATE 部分\n     */\n    fun getDate(date: String): String {\n        return if (TextUtils.isEmpty(date) || !date.contains(PATTERN_SPLIT)) {\n            \"\"\n        } else date.split(PATTERN_SPLIT.toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()[0]\n    }\n\n    /**\n     * 原有日期上累加月\n     *\n     * @return 累加后的日期 PATTERN_DATE 部分\n     */\n    fun addMonth(date: String, moonCount: Int): String {\n        var date = date\n        if (TextUtils.isEmpty(date)) {\n\n//            val df = SimpleDateFormat(PATTERN_DATE + PATTERN_SPLIT + PATTERN_TIME)\n            val df = SimpleDateFormat.getDateTimeInstance()\n            date = df.format(Date())\n        }\n        val calendar = str2calendar(date)\n        calendar!!.add(Calendar.MONTH, moonCount)\n        return getDate(calendar2str(calendar))\n    }\n\n    /**\n     * 计算天数差\n     */\n    fun calculateDayDiff(targetTime: Date, compareTime: Date): Int {\n        val sameYear = isSameYear(targetTime, compareTime)\n        if (sameYear) {\n            return calculateDayDiffOfSameYear(targetTime, compareTime)\n        } else {\n            var dayDiff = 0\n\n            // 累计年数差的整年天数\n            val yearDiff = calculateYearDiff(targetTime, compareTime)\n            dayDiff += yearDiff * DAY_OF_YEAR\n\n            // 累计同一年内的天数\n            dayDiff += calculateDayDiffOfSameYear(targetTime, compareTime)\n\n            return dayDiff\n        }\n    }\n\n    /**\n     * 计算同一年内的天数差\n     */\n    fun calculateDayDiffOfSameYear(targetTime: Date?, compareTime: Date?): Int {\n        if (targetTime == null || compareTime == null) {\n            return 0\n        }\n\n        val tarCalendar = Calendar.getInstance()\n        tarCalendar.time = targetTime\n        val tarDayOfYear = tarCalendar.get(Calendar.DAY_OF_YEAR)\n\n        val compareCalendar = Calendar.getInstance()\n        compareCalendar.time = compareTime\n        val comDayOfYear = compareCalendar.get(Calendar.DAY_OF_YEAR)\n\n        return tarDayOfYear - comDayOfYear\n    }\n\n    /**\n     * 计算年数差\n     */\n    private fun calculateYearDiff(targetTime: Date?, compareTime: Date?): Int {\n        if (targetTime == null || compareTime == null) {\n            return 0\n        }\n\n        val tarCalendar = Calendar.getInstance()\n        tarCalendar.time = targetTime\n        val tarYear = tarCalendar.get(Calendar.YEAR)\n\n        val compareCalendar = Calendar.getInstance()\n        compareCalendar.time = compareTime\n        val comYear = compareCalendar.get(Calendar.YEAR)\n\n        return tarYear - comYear\n    }\n\n    /**\n     * 计算月数差\n     *\n     * @param targetTime\n     * @param compareTime\n     * @return\n     */\n    fun calculateMonthDiff(targetTime: String, compareTime: String): Int {\n        return calculateMonthDiff(str2date(targetTime, PATTERN_DATE),\n                str2date(compareTime, PATTERN_DATE))\n    }\n\n    /**\n     * 计算月数差\n     *\n     * @param targetTime\n     * @param compareTime\n     * @return\n     */\n    fun calculateMonthDiff(targetTime: Date?, compareTime: Date?): Int {\n        val tarCalendar = Calendar.getInstance()\n        tarCalendar.time = targetTime\n        val tarYear = tarCalendar.get(Calendar.YEAR)\n        val tarMonth = tarCalendar.get(Calendar.MONTH)\n\n        val compareCalendar = Calendar.getInstance()\n        compareCalendar.time = compareTime\n        val comYear = compareCalendar.get(Calendar.YEAR)\n        val comMonth = compareCalendar.get(Calendar.MONTH)\n        return (tarYear - comYear) * 12 + tarMonth - comMonth\n\n    }\n\n    /**\n     * 是否为同一年\n     */\n    private fun isSameYear(targetTime: Date?, compareTime: Date?): Boolean {\n        if (targetTime == null || compareTime == null) {\n            return false\n        }\n\n        val tarCalendar = Calendar.getInstance()\n        tarCalendar.time = targetTime\n        val tarYear = tarCalendar.get(Calendar.YEAR)\n\n        val compareCalendar = Calendar.getInstance()\n        compareCalendar.time = compareTime\n        val comYear = compareCalendar.get(Calendar.YEAR)\n\n        return tarYear == comYear\n    }\n\n    @SuppressLint(\"SimpleDateFormat\")\n    @JvmOverloads\n    private fun str2date(str: String?, format: String = PATTERN): Date? {\n        var date: Date? = null\n        try {\n            if (str != null) {\n                val sdf = SimpleDateFormat(format)\n                date = sdf.parse(str)\n            }\n        } catch (e: ParseException) {\n            e.printStackTrace()\n        }\n\n        return date\n    }\n\n    @JvmOverloads\n    private fun date2str(date: Date, format: String = PATTERN): String {\n        val sdf = SimpleDateFormat(format, Locale.CHINA)\n        return sdf.format(date)\n    }\n\n    private fun str2calendar(str: String): Calendar? {\n        var calendar: Calendar? = null\n        val date = str2date(str)\n        if (date != null) {\n            calendar = Calendar.getInstance()\n            calendar!!.time = date\n        }\n        return calendar\n    }\n\n\n    fun str2calendar(str: String, format: String): Calendar? {\n        var calendar: Calendar? = null\n        val date = str2date(str, format)\n        if (date != null) {\n            calendar = Calendar.getInstance()\n            calendar!!.time = date\n        }\n        return calendar\n    }\n\n    private fun calendar2str(calendar: Calendar): String {\n        return date2str(calendar.time)\n    }\n\n    fun calendar2str(calendar: Calendar, format: String): String {\n        return date2str(calendar.time, format)\n    }\n}\n"
  },
  {
    "path": "module_library/src/main/java/com/lxm/module_library/utils/DialogUtils.kt",
    "content": "package com.lxm.module_library.utils\n\nimport android.app.Dialog\nimport android.content.Context\nimport android.content.DialogInterface\nimport android.support.v7.app.AlertDialog\n\n\n/**\n * Created by Horrarndoo on 2017/8/31.\n *\n * 对话框工具类, 提供常用对话框显示, 使用support.v7包内的AlertDialog样式\n */\nobject DialogUtils {\n\n\n    fun showCommonDialog(context: Context, message: String, positiveText: String,\n                         negativeText: String, listener: DialogInterface.OnClickListener): Dialog {\n        return AlertDialog.Builder(context)\n                .setMessage(message)\n                .setPositiveButton(positiveText, listener)\n                .setNegativeButton(negativeText, null)\n                .show()\n    }\n\n    fun showConfirmDialog(context: Context, message: String, positiveText: String,\n                          listener: DialogInterface.OnClickListener): Dialog {\n        return AlertDialog.Builder(context)\n                .setMessage(message)\n                .setPositiveButton(positiveText, listener)\n                .show()\n    }\n}\n"
  },
  {
    "path": "module_library/src/main/java/com/lxm/module_library/utils/DisplayUtils.kt",
    "content": "package com.lxm.module_library.utils\n\nimport android.app.Activity\nimport android.content.Context\nimport android.util.DisplayMetrics\nimport android.util.TypedValue\nimport android.view.View\nimport android.view.ViewGroup\nimport com.lxm.module_library.global.GlobalApplication\n\n/**\n * Created by Horrarndoo on 2017/8/31.\n *\n *\n * 显示相关工具类\n */\nobject DisplayUtils {\n\n    /**\n     * 将px值转换为dp值\n     */\n    fun px2dp(pxValue: Float, context: Context): Int {\n        val scale = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX, pxValue, context.resources.displayMetrics)\n\n        return scale.toInt()\n    }\n\n    /**\n     * 将dp值转换为px值\n     */\n    fun dp2px(dpValue: Float): Int {\n        val scale = GlobalApplication.getInstance().getResources().getDisplayMetrics().density\n        return (dpValue * scale + 0.5f).toInt()\n    }\n\n    /**\n     * 将px值转换为sp值\n     */\n    fun px2sp(pxValue: Float, context: Context): Int {\n        val scale = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX, pxValue, context.resources.displayMetrics)\n        return scale.toInt()\n    }\n\n    /**\n     * 将sp值转换为px值\n     */\n    fun sp2px(spValue: Float, context: Context): Int {\n        val scale = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, spValue, context.resources.displayMetrics)\n        return scale.toInt()\n    }\n\n    /**\n     * 获取屏幕宽度\n     */\n    fun getScreenWidthPixels(context: Activity): Int {\n        val metric = DisplayMetrics()\n        context.windowManager.defaultDisplay.getMetrics(metric)\n        return metric.widthPixels\n    }\n\n    /**\n     * 获取屏幕高度\n     */\n    fun getScreenHeightPixels(context: Activity): Int {\n        val metric = DisplayMetrics()\n        context.windowManager.defaultDisplay.getMetrics(metric)\n        return metric.heightPixels\n    }\n\n    /**\n     * 设置某个View的margin\n     *\n     * @param view   需要设置的view\n     * @param isDp   需要设置的数值是否为DP\n     * @param left   左边距\n     * @param right  右边距\n     * @param top    上边距\n     * @param bottom 下边距\n     * @return\n     */\n    fun setViewMargin(\n        view: View?,\n        isDp: Boolean,\n        left: Int,\n        right: Int,\n        top: Int,\n        bottom: Int\n    ): ViewGroup.LayoutParams? {\n        if (view == null) {\n            return null\n        }\n\n        var leftPx = left\n        var rightPx = right\n        var topPx = top\n        var bottomPx = bottom\n        val params = view.layoutParams\n        var marginParams: ViewGroup.MarginLayoutParams? = null\n        //获取view的margin设置参数\n        if (params is ViewGroup.MarginLayoutParams) {\n            marginParams = params\n        } else {\n            //不存在时创建一个新的参数\n            marginParams = ViewGroup.MarginLayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 250)\n        }\n\n        //根据DP与PX转换计算值\n        if (isDp) {\n            leftPx = dp2px(left.toFloat())\n            rightPx = dp2px(right.toFloat())\n            topPx = dp2px(top.toFloat())\n            bottomPx = dp2px(bottom.toFloat())\n        }\n        //设置margin\n        marginParams.setMargins(leftPx, topPx, rightPx, bottomPx)\n        view.layoutParams = marginParams\n        view.requestLayout()\n        return marginParams\n    }\n\n}\n"
  },
  {
    "path": "module_library/src/main/java/com/lxm/module_library/utils/FileUtils.kt",
    "content": "package com.lxm.module_library.utils\n\nimport android.content.ContentResolver\nimport android.content.Context\nimport android.content.Intent\nimport android.graphics.Bitmap\nimport android.net.Uri\nimport android.os.Environment\nimport android.provider.MediaStore\nimport android.text.TextUtils\nimport com.lxm.module_library.R\nimport com.lxm.module_library.helper.RxHelper\nimport io.reactivex.Observable\nimport io.reactivex.ObservableOnSubscribe\nimport java.io.*\nimport kotlin.experimental.and\n\n/**\n *\n *\n * 读取文件工具类\n */\nobject FileUtils {\n    /**\n     * Convert byte[] to hex string.将byte转换成int，\n     * 然后利用Integer.toHexString(int)来转换成16进制字符串。\n     *\n     * @param src byte[] data\n     * @return hex string\n     */\n    fun bytesToHexString(src: ByteArray?): String? {\n        val stringBuilder = StringBuilder(\"\")\n        if (src == null || src.size <= 0) {\n            return null\n        }\n        for (i in src.indices) {\n            val v = src[i] and 0xFF.toByte()\n            val hv = Integer.toHexString(v.toInt())\n            if (hv.length < 2) {\n                stringBuilder.append(0)\n            }\n            stringBuilder.append(hv)\n        }\n        return stringBuilder.toString()\n    }\n\n    /**\n     * 根据文件名称和路径，获取sd卡中的文件，以File形式返回byte\n     */\n    fun getFile(fileName: String, folder: String): File? {\n        val state = Environment.getExternalStorageState()\n        if (state == Environment.MEDIA_MOUNTED) {\n            val pathFile = File(Environment.getExternalStorageDirectory().toString() + folder)\n            // && !pathFile .isDirectory()\n            if (!pathFile.exists()) {\n                pathFile.mkdirs()\n            }\n            return File(pathFile, fileName)\n        }\n        return null\n    }\n\n    /**\n     * 根据文件名称和路径，获取sd卡中的文件，判断文件是否存在，存在返回true\n     */\n    fun checkFile(fileName: String, folder: String): Boolean {\n\n        val targetFile = getFile(fileName, folder)\n\n        return targetFile!!.exists()\n    }\n\n    /**\n     * 根据Uri返回文件绝对路径\n     * 兼容了file:///开头的 和 content://开头的情况\n     */\n    fun getRealFilePathFromUri(context: Context, uri: Uri?): String? {\n        if (null == uri) {\n            return null\n        }\n        val scheme = uri.scheme\n        var data: String? = null\n        if (scheme == null) {\n            data = uri.path\n        } else if (ContentResolver.SCHEME_FILE.equals(scheme, ignoreCase = true)) {\n            data = uri.path\n        } else if (ContentResolver.SCHEME_CONTENT.equals(scheme, ignoreCase = true)) {\n            val cursor = context.contentResolver.query(uri, arrayOf(MediaStore\n                    .Images.ImageColumns.DATA), null, null, null)\n            if (null != cursor) {\n                if (cursor.moveToFirst()) {\n                    val index = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA)\n                    if (index > -1) {\n                        data = cursor.getString(index)\n                    }\n                }\n                cursor.close()\n            }\n        }\n        return data\n    }\n\n    /**\n     * 检查文件是否存在\n     */\n    fun checkDirPath(dirPath: String): String {\n        if (TextUtils.isEmpty(dirPath)) {\n            return \"\"\n        }\n        val dir = File(dirPath)\n        if (!dir.exists()) {\n            dir.mkdirs()\n        }\n        return dirPath\n    }\n\n    fun copyFile(sourcefile: File, targetFile: File) {\n        var input: FileInputStream? = null\n        var inbuff: BufferedInputStream? = null\n        var out: FileOutputStream? = null\n        var outbuff: BufferedOutputStream? = null\n\n        try {\n\n            input = FileInputStream(sourcefile)\n            inbuff = BufferedInputStream(input)\n\n            out = FileOutputStream(targetFile)\n            outbuff = BufferedOutputStream(out)\n\n            val b = ByteArray(1024 * 5)\n            var len: Int\n            len = inbuff.read(b)\n            while (len != -1) {\n                outbuff.write(b, 0, len)\n                len = inbuff.read(b)\n            }\n            outbuff.flush()\n        } catch (ex: Exception) {\n        } finally {\n            try {\n                inbuff?.close()\n                outbuff?.close()\n                out?.close()\n                input?.close()\n            } catch (ex: Exception) {\n\n            }\n\n        }\n    }\n\n    /**\n     * 保存图片到本机\n     *\n     * @param context            context\n     * @param fileName           文件名\n     * @param file               file\n     * @param saveResultCallback 保存结果callback\n     */\n    fun saveImage(context: Context, fileName: String, file: File,\n                  saveResultCallback: SaveResultCallback) {\n        val disposable = Observable.create(ObservableOnSubscribe<File> { e ->\n            val appDir = File(Environment.getExternalStorageDirectory(), context.getString(R.string.app_name))\n            if (!appDir.exists()) {\n                appDir.mkdir()\n            }\n            var saveFileName: String\n            if (fileName.contains(\".png\") || fileName.contains(\".gif\")) {\n                val fileFormat = fileName.substring(fileName.lastIndexOf(\".\"))\n                saveFileName = MD5Utils.getMD5(fileName) + fileFormat\n            } else {\n                saveFileName = MD5Utils.getMD5(fileName) + \".png\"\n            }\n            saveFileName = saveFileName.substring(20)\n            val saveFile = File(appDir, saveFileName)\n            try {\n                val `is` = FileInputStream(file)\n                val fos = FileOutputStream(saveFile)\n                val buffer = ByteArray(1024 * 1024)\n                var count: Int\n                count = `is`.read(buffer)\n                while (count > 0) {\n                    fos.write(buffer, 0, count)\n                    count = `is`.read(buffer)\n                }\n                fos.close()\n                `is`.close()\n                e.onNext(saveFile)\n            } catch (exception: FileNotFoundException) {\n                e.onError(exception)\n\n            } catch (exception: IOException) {\n                e.onError(exception)\n            }\n        }).compose(RxHelper.rxSchedulerHelper())\n                .subscribe({ saveFile ->\n                    saveResultCallback.onSavedSuccess()\n                    val uri = Uri.fromFile(saveFile)\n                    context.sendBroadcast(Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, uri))\n                }, { throwable ->\n                    if (throwable is FileNotFoundException) {\n                        saveResultCallback.onSavedFailed()\n                        throwable.printStackTrace()\n                    } else if (throwable is IOException) {\n                        saveResultCallback.onSavedFailed()\n                        throwable.printStackTrace()\n                    }\n                })\n    }\n\n    /**\n     * 保存Bitmap到本机\n     *\n     * @param context            context\n     * @param fileName           bitmap文件名\n     * @param bmp                bitmap\n     * @param saveResultCallback 保存结果callback\n     */\n    fun saveBitmap(context: Context, fileName: String, bmp: Bitmap,\n                   saveResultCallback: SaveResultCallback) {\n        val disposable = Observable.create(ObservableOnSubscribe<File> { e ->\n            val appDir = File(Environment.getExternalStorageDirectory(), context.getString(R.string.app_name))\n            if (!appDir.exists()) {\n                appDir.mkdir()\n            }\n            // 设置以当前时间格式为图片名称\n            var saveFileName = MD5Utils.getMD5(fileName) + \".png\"\n            saveFileName = saveFileName.substring(20)\n            val file = File(appDir, saveFileName)\n            try {\n                val fos = FileOutputStream(file)\n                bmp.compress(Bitmap.CompressFormat.PNG, 100, fos)\n                fos.flush()\n                fos.close()\n                e.onNext(file)\n            } catch (exception: FileNotFoundException) {\n                e.onError(exception)\n            } catch (exception: IOException) {\n                e.onError(exception)\n            }\n        }).compose(RxHelper.rxSchedulerHelper())\n                .subscribe({ saveFile ->\n                    saveResultCallback.onSavedSuccess()\n                    val uri = Uri.fromFile(saveFile)\n                    context.sendBroadcast(Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, uri))\n                }, { throwable ->\n                    if (throwable is FileNotFoundException) {\n                        saveResultCallback.onSavedFailed()\n                        throwable.printStackTrace()\n                    } else if (throwable is IOException) {\n                        saveResultCallback.onSavedFailed()\n                        throwable.printStackTrace()\n                    }\n                })\n\n    }\n\n    interface SaveResultCallback {\n        /**\n         * 保存成功\n         */\n        fun onSavedSuccess()\n\n        /**\n         * 保存失败\n         */\n        fun onSavedFailed()\n    }\n}\n\n\n"
  },
  {
    "path": "module_library/src/main/java/com/lxm/module_library/utils/HtmlUtils.kt",
    "content": "package com.lxm.module_library.utils\n\n/**\n * Created by Horrarndoo on 2017/8/31.\n *\n * Html工具类\n */\nobject HtmlUtils {\n\n    /**\n     * css样式,隐藏header\n     */\n    private const val HIDE_HEADER_STYLE = \"<style>div.headline{display:none;}</style>\"\n\n    /**\n     * css style tag,需要格式化\n     */\n    private const val NEEDED_FORMAT_CSS_TAG = \"<link rel=\\\"stylesheet\\\" \" + \"type=\\\"text/css\\\" href=\\\"%s\\\"/>\"\n\n    /**\n     * js script tag,需要格式化\n     */\n    private const val NEEDED_FORMAT_JS_TAG = \"<script src=\\\"%s\\\"></script>\"\n\n    val MIME_TYPE = \"text/html; charset=utf-8\"\n\n    val ENCODING = \"utf-8\"\n\n    /**\n     * 根据css链接生成Link标签\n     *\n     * @param url String\n     * @return String\n     */\n    fun createCssTag(url: String): String {\n\n        return String.format(NEEDED_FORMAT_CSS_TAG, url)\n    }\n\n    /**\n     * 根据多个css链接生成Link标签\n     *\n     * @param urls List<String>\n     * @return String\n    </String> */\n    fun createCssTag(urls: List<String>): String {\n\n        val sb = StringBuilder()\n        for (url in urls) {\n            sb.append(createCssTag(url))\n        }\n        return sb.toString()\n    }\n\n    /**\n     * 根据js链接生成Script标签\n     *\n     * @param url String\n     * @return String\n     */\n    fun createJsTag(url: String): String {\n\n        return String.format(NEEDED_FORMAT_JS_TAG, url)\n    }\n\n    /**\n     * 根据多个js链接生成Script标签\n     *\n     * @param urls List<String>\n     * @return String\n    </String> */\n    fun createJsTag(urls: List<String>): String {\n\n        val sb = StringBuilder()\n        for (url in urls) {\n            sb.append(createJsTag(url))\n        }\n        return sb.toString()\n    }\n\n    /**\n     * 根据样式标签,html字符串,js标签\n     * 生成完整的HTML文档\n     */\n\n    fun createHtmlData(html: String, cssList: List<String>, jsList: List<String>): String {\n        val css = HtmlUtils.createCssTag(cssList)\n        val js = HtmlUtils.createJsTag(jsList)\n        return css + HIDE_HEADER_STYLE + html + js\n    }\n}\n\n"
  },
  {
    "path": "module_library/src/main/java/com/lxm/module_library/utils/HttpUtils.kt",
    "content": "package com.lxm.module_library.utils\n\nimport android.os.Build\nimport android.webkit.WebSettings\nimport java.util.*\nimport java.util.regex.Pattern\n\n/**\n *\n * HttpUtils 主要用于获取UserAgent\n */\n\nobject HttpUtils {\n    /**\n     * 获取UserAgent\n     *\n     * @return UserAgent\n     */\n    val userAgent: String\n        get() {\n            var userAgent: String\n            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {\n                try {\n                    userAgent = WebSettings.getDefaultUserAgent(AppUtils.context)\n                } catch (e: Exception) {\n                    userAgent = System.getProperty(\"http.agent\")\n                }\n\n            } else {\n                userAgent = System.getProperty(\"http.agent\")\n            }\n            val sb = StringBuffer()\n            var i = 0\n            val length = userAgent.length\n            while (i < length) {\n                val c = userAgent[i]\n                if (c <= '\\u001f' || c >= '\\u007f') {\n                    sb.append(String.format(\"\\\\u%04x\", c.toInt()))\n                } else {\n                    sb.append(c)\n                }\n                i++\n            }\n            return sb.toString()\n        }\n\n    fun makeUA(): String {\n        return Build.BRAND + \"/\" + Build.MODEL + \"/\" + Build.VERSION.RELEASE\n    }\n\n    fun returnImageUrlsFromHtml(html: String): Array<String>? {\n        val imageSrcList = ArrayList<String>()\n        val p = Pattern.compile(\"<img\\\\b[^>]*\\\\bsrc\\\\b\\\\s*=\\\\s*('|\\\")?([^'\\\"\\n\\rf>]+(\\\\\" +\n                \".jpg|\\\\.bmp|\\\\.eps|\\\\.gif|\\\\.mif|\\\\.miff|\\\\.png|\\\\.tif|\\\\.tiff|\\\\.svg|\\\\.wmf|\\\\\" +\n                \".jpe|\\\\.jpeg|\\\\.dib|\\\\.ico|\\\\.tga|\\\\.cut|\\\\.pic|\\\\b)\\\\b)[^>]*>\", Pattern\n                .CASE_INSENSITIVE)\n        val m = p.matcher(html)\n        var quote: String\n        var src: String\n        while (m.find()) {\n            quote = m.group(1)\n            src = if (quote == null || quote.trim { it <= ' ' }.isEmpty())\n                m.group(2).split(\"//s+\".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()[0]\n            else\n                m\n                        .group(2)\n            imageSrcList.add(src)\n        }\n        return if (imageSrcList.size == 0) {\n            null\n        } else imageSrcList.toTypedArray()\n    }\n}\n"
  },
  {
    "path": "module_library/src/main/java/com/lxm/module_library/utils/ImageUtils.kt",
    "content": "package com.lxm.module_library.utils\n\nimport android.annotation.TargetApi\nimport android.app.Activity\nimport android.content.ContentUris\nimport android.content.ContentValues\nimport android.content.Context\nimport android.content.Intent\nimport android.database.Cursor\nimport android.net.Uri\nimport android.os.Build\nimport android.os.Environment\nimport android.provider.DocumentsContract\nimport android.provider.MediaStore\nimport android.support.v7.app.AlertDialog\n\n/**\n * 图片工具类\n */\nobject ImageUtils {\n\n    /**\n     * 拍照\n     */\n    private const val REQUEST_CODE_FROM_CAMERA = 1 shl 10\n\n    /**\n     * 相册\n     */\n    private const val REQUEST_CODE_FROM_ALBUM = 1 shl 12\n\n    /**\n     * 裁剪\n     */\n    private const val REQUEST_CODE_CROP_IMAGE = 1 shl 14\n\n    /**\n     * 存放拍照图片的uri地址\n     */\n     var imageUriFromCamera: Uri? = null\n\n    /**\n     * 存放裁剪图片的uri地址\n     */\n    var cropImageUri: Uri? = null\n\n    /**\n     * 显示获取照片不同方式对话框\n     */\n    @JvmOverloads\n    fun showImagePickDialog(activity: Activity, addRequest: Int = 0) {\n        val title = \"选择获取图片方式\"\n        val items = arrayOf(\"拍照\", \"相册\")\n        AlertDialog.Builder(activity)\n                .setTitle(title)\n                .setItems(items) { dialog, which ->\n                    dialog.dismiss()\n                    when (which) {\n                        0 -> pickImageFromCamera(activity, addRequest)\n                        1 -> pickImageFromAlbum(activity, addRequest)\n                        else -> {\n                        }\n                    }\n                }\n                .setNegativeButton(\"取消\", null)\n                .show()\n    }\n\n    /**\n     * 打开相机拍照获取图片\n     */\n    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)\n    fun pickImageFromCamera(activity: Activity, addRequest: Int) {\n        // 先生成一个uri地址用于存放拍照获取的图片\n        imageUriFromCamera = createImageUri(activity)\n\n        val intent = Intent()\n        intent.action = MediaStore.ACTION_IMAGE_CAPTURE\n        intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUriFromCamera)\n        activity.startActivityForResult(intent, REQUEST_CODE_FROM_CAMERA + addRequest)\n    }\n\n    /**\n     * 打开相机拍照获取图片\n     */\n    fun pickImageFromCamera(activity: Activity) {\n        pickImageFromCamera(activity, 0)\n    }\n\n    /**\n     * 打开本地相册选取图片\n     */\n    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)\n    fun pickImageFromAlbum(activity: Activity, addRequest: Int) {\n        val intent = Intent()\n        intent.action = Intent.ACTION_GET_CONTENT\n        intent.type = \"image/*\"\n        activity.startActivityForResult(intent, REQUEST_CODE_FROM_ALBUM + addRequest)\n    }\n\n    /**\n     * 打开本地相册选取图片\n     */\n    fun pickImageFromAlbum(activity: Activity) {\n        pickImageFromAlbum(activity, 0)\n    }\n\n    /**\n     * 图片裁剪\n     */\n    fun cropImage(activity: Activity, srcUri: Uri) {\n        cropImageUri = createImageUri(activity)\n\n        val intent = Intent(\"com.android.camera.action.CROP\")\n        intent.setDataAndType(srcUri, \"image/*\")\n        intent.putExtra(\"crop\", \"true\")\n\n        ////////////////////////////////////////////////////////////////\n        // 1.宽高和比例都不设置时,裁剪框可以自行调整(比例和大小都可以随意调整)\n        ////////////////////////////////////////////////////////////////\n        // 2.只设置裁剪框宽高比(aspect)后,裁剪框比例固定不可调整,只能调整大小\n        /////////////////////////////////\n        // 3.裁剪后生成图片宽高(output)的设置和裁剪框无关,只决定最终生成图片大小\n        ////////////////////////////////////////////////////////////////\n        // 4.裁剪框宽高比例(aspect)可以和裁剪后生成图片比例(output)不同,此时,\n        //\t会以裁剪框的宽为准,按照裁剪宽高比例生成一个图片,该图和框选部分可能不同,\n        //  不同的情况可能是截取框选的一部分,也可能超出框选部分,向下延伸补足\n        ////////////////////////////////////////////////////////////////\n\n        // aspectX aspectY 是裁剪框宽高的比例\n        intent.putExtra(\"aspectX\", 1)\n        intent.putExtra(\"aspectY\", 1)\n        // outputX outputY 是裁剪后生成图片的宽高\n        //\t\tintent.putExtra(\"outputX\", 300);\n        //\t\tintent.putExtra(\"outputY\", 100);\n\n        // return-data为true时,会直接返回bitmap数据,但是大图裁剪时会出现OOM,推荐下面为false时的方式\n        // return-data为false时,不会返回bitmap,但需要指定一个MediaStore.EXTRA_OUTPUT保存图片uri\n        intent.putExtra(\"return-data\", false)\n        intent.putExtra(MediaStore.EXTRA_OUTPUT, cropImageUri)\n\n        activity.startActivityForResult(intent, REQUEST_CODE_CROP_IMAGE)\n    }\n\n    /**\n     * 创建一条图片uri,用于保存拍照后的照片\n     */\n    private fun createImageUri(context: Context): Uri? {\n        val name = \"boreImg\" + System.currentTimeMillis()\n        val values = ContentValues()\n        values.put(MediaStore.Images.Media.TITLE, name)\n        values.put(MediaStore.Images.Media.DISPLAY_NAME, \"$name.jpeg\")\n        values.put(MediaStore.Images.Media.MIME_TYPE, \"image/jpeg\")\n        return context.contentResolver.insert(MediaStore.Images.Media\n                .EXTERNAL_CONTENT_URI, values)\n    }\n\n    /**\n     * 删除一条图片\n     */\n    fun deleteImageUri(context: Context, uri: Uri) {\n        context.contentResolver.delete(uri, null, null)\n    }\n\n    /**\n     * 用第三方应用app打开图片\n     */\n    fun openImageByOtherApp(context: Context, imageUri: Uri) {\n        val intent = Intent()\n        intent.action = Intent.ACTION_VIEW\n        intent.setDataAndType(imageUri, \"image/*\")\n        context.startActivity(intent)\n    }\n\n    /**\n     * 根据Uri获取图片绝对路径，解决Android4.4以上版本Uri转换\n     */\n    fun getImageAbsolutePath19(context: Context?, imageUri: Uri?): String? {\n        if (context == null || imageUri == null)\n            return null\n        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && DocumentsContract.isDocumentUri(context, imageUri)) {\n            if (isExternalStorageDocument(imageUri)) {\n                val docId = DocumentsContract.getDocumentId(imageUri)\n                val split = docId.split(\":\".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()\n                val type = split[0]\n                if (\"primary\".equals(type, ignoreCase = true)) {\n                    return Environment.getExternalStorageDirectory().toString() + \"/\" + split[1]\n                }\n            } else if (isDownloadsDocument(imageUri)) {\n                val id = DocumentsContract.getDocumentId(imageUri)\n                val contentUri = ContentUris.withAppendedId(Uri.parse(\"content://downloads/public_downloads\"), java.lang.Long.valueOf(id))\n                return getDataColumn(context, contentUri, null, null)\n            } else if (isMediaDocument(imageUri)) {\n                val docId = DocumentsContract.getDocumentId(imageUri)\n                val split = docId.split(\":\".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()\n                val type = split[0]\n                var contentUri: Uri? = null\n                if (\"image\" == type) {\n                    contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI\n                } else if (\"video\" == type) {\n                    contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI\n                } else if (\"audio\" == type) {\n                    contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI\n                }\n                val selection = MediaStore.Images.Media._ID + \"=?\"\n                val selectionArgs = arrayOf(split[1])\n                return getDataColumn(context, contentUri, selection, selectionArgs)\n            }\n        }\n\n        // MediaStore (and general)\n        if (\"content\".equals(imageUri.scheme, ignoreCase = true)) {\n            // Return the remote address\n            return if (isGooglePhotosUri(imageUri)) imageUri.lastPathSegment else getDataColumn(context, imageUri, null, null)\n        } else if (\"file\".equals(imageUri.scheme, ignoreCase = true)) {\n            return imageUri.path\n        }// File\n        return null\n    }\n\n    private fun getDataColumn(context: Context, uri: Uri?, selection: String?, selectionArgs: Array<String>?): String? {\n        var cursor: Cursor? = null\n        val column = MediaStore.Images.Media.DATA\n        val projection = arrayOf(column)\n        try {\n            cursor = context.contentResolver.query(uri!!, projection, selection,\n                    selectionArgs, null)\n            if (cursor != null && cursor.moveToFirst()) {\n                val index = cursor.getColumnIndexOrThrow(column)\n                return cursor.getString(index)\n            }\n        } finally {\n            cursor?.close()\n        }\n        return null\n    }\n\n    /**\n     * @param uri The Uri to check.\n     * @return Whether the Uri authority is ExternalStorageProvider.\n     */\n    private fun isExternalStorageDocument(uri: Uri): Boolean {\n        return \"com.android.externalstorage.documents\" == uri.authority\n    }\n\n    /**\n     * @param uri The Uri to check.\n     * @return Whether the Uri authority is DownloadsProvider.\n     */\n    private fun isDownloadsDocument(uri: Uri): Boolean {\n        return \"com.android.providers.downloads.documents\" == uri.authority\n    }\n\n    /**\n     * @param uri The Uri to check.\n     * @return Whether the Uri authority is MediaProvider.\n     */\n    private fun isMediaDocument(uri: Uri): Boolean {\n        return \"com.android.providers.media.documents\" == uri.authority\n    }\n\n    /**\n     * @param uri The Uri to check.\n     * @return Whether the Uri authority is Google Photos.\n     */\n    private fun isGooglePhotosUri(uri: Uri): Boolean {\n        return \"com.google.android.apps.photos.content\" == uri.authority\n    }\n\n}\n\n"
  },
  {
    "path": "module_library/src/main/java/com/lxm/module_library/utils/JsonUtils.kt",
    "content": "package com.lxm.module_library.utils\n\nimport com.google.gson.Gson\nimport com.google.gson.JsonObject\nimport com.google.gson.JsonSyntaxException\n\nimport java.lang.reflect.Type\n\n/**\n *\n * Json转换工具类\n */\nobject JsonUtils {\n\n    private val mGson = Gson()\n\n    /**\n     * 将对象准换为json字符串\n     *\n     * @param object\n     * @param <T>\n     * @return\n    </T> */\n    fun <T> serialize(`object`: T): String {\n        return mGson.toJson(`object`)\n    }\n\n    /**\n     * 将json字符串转换为对象\n     *\n     * @param json\n     * @param clz\n     * @param <T>\n     * @return\n    </T> */\n    @Throws(JsonSyntaxException::class)\n    fun <T> deserialize(json: String, clz: Class<T>): T {\n        return mGson.fromJson(json, clz)\n    }\n\n    /**\n     * 将json对象转换为实体对象\n     *\n     * @param json\n     * @param clz\n     * @param <T>\n     * @return\n     * @throws JsonSyntaxException\n    </T> */\n    @Throws(JsonSyntaxException::class)\n    fun <T> deserialize(json: JsonObject, clz: Class<T>): T {\n        return mGson.fromJson(json, clz)\n    }\n\n    /**\n     * 将json字符串转换为对象\n     *\n     * @param json\n     * @param type\n     * @param <T>\n     * @return\n    </T> */\n    @Throws(JsonSyntaxException::class)\n    fun <T> deserialize(json: String, type: Type): T {\n        return mGson.fromJson(json, type)\n    }\n}\n"
  },
  {
    "path": "module_library/src/main/java/com/lxm/module_library/utils/MD5Utils.kt",
    "content": "package com.lxm.module_library.utils\n\nimport java.security.MessageDigest\n\n/**\n *\n * MD5加密工具类\n */\nobject MD5Utils {\n    /**\n     * MD5加密，32位\n     */\n    fun getMD5(str: String): String {\n        val md5: MessageDigest\n        try {\n            md5 = MessageDigest.getInstance(\"MD5\")\n        } catch (e: Exception) {\n            e.printStackTrace()\n            return \"\"\n        }\n\n        val charArray = str.toCharArray()\n        val byteArray = ByteArray(charArray.size)\n        for (i in charArray.indices) {\n            byteArray[i] = charArray[i].toByte()\n        }\n        val md5Bytes = md5.digest(byteArray)\n        val hexValue = StringBuffer()\n        for (i in md5Bytes.indices) {\n            val `val` = md5Bytes[i].toInt() and 0xff\n            if (`val` < 16) {\n                hexValue.append(\"0\")\n            }\n            hexValue.append(Integer.toHexString(`val`))\n        }\n        return hexValue.toString()\n    }\n} "
  },
  {
    "path": "module_library/src/main/java/com/lxm/module_library/utils/MyDividerItemDecoration.java",
    "content": "package com.lxm.module_library.utils;\n\n\nimport android.content.Context;\nimport android.content.res.TypedArray;\nimport android.graphics.Canvas;\nimport android.graphics.Rect;\nimport android.graphics.drawable.Drawable;\nimport android.support.annotation.NonNull;\nimport android.support.v7.widget.RecyclerView;\nimport android.util.Log;\nimport android.view.View;\nimport android.widget.LinearLayout;\n\npublic class MyDividerItemDecoration extends RecyclerView.ItemDecoration {\n\n    public static final int HORIZONTAL = LinearLayout.HORIZONTAL;\n    public static final int VERTICAL = LinearLayout.VERTICAL;\n    private static final String TAG = \"DividerItem\";\n    private static final int[] ATTRS = new int[]{android.R.attr.listDivider};\n    private Drawable mDivider;\n    private boolean mIsShowBottomDivider;\n    private boolean mIsShowFirstDivider;\n    private boolean mIsShowSecondDivider;\n    /**\n     * Current orientation. Either {@link #HORIZONTAL} or {@link #VERTICAL}.\n     */\n    private int mOrientation;\n    private final Rect mBounds = new Rect();\n\n    /**\n     * Creates a divider {@link RecyclerView.ItemDecoration} that can be used with a\n     * {@link android.support.v7.widget.LinearLayoutManager}.\n     *\n     * @param context             Current context, it will be used to access resources.\n     * @param orientation         Divider orientation. Should be {@link #HORIZONTAL} or\n     *                            {@link #VERTICAL}.\n     * @param isShowBottomDivider true show bottom divider false not show bottom divider\n     */\n    public MyDividerItemDecoration(Context context, int orientation, boolean isShowBottomDivider) {\n        this(context, orientation, isShowBottomDivider, true, true);\n    }\n\n    public MyDividerItemDecoration(Context context, int orientation,\n                                   boolean isShowBottomDivider, boolean isShowFirstDivider, boolean isShowSecondDivider) {\n        mIsShowBottomDivider = isShowBottomDivider;\n        mIsShowFirstDivider = isShowFirstDivider;\n        mIsShowSecondDivider = isShowSecondDivider;\n\n        final TypedArray a = context.obtainStyledAttributes(ATTRS);\n        mDivider = a.getDrawable(0);\n        if (mDivider == null) {\n            Log.w(TAG, \"@android:attr/listDivider was not set in the theme used for this \"\n                    + \"DividerItemDecoration. Please set that attribute all call setDrawable()\");\n        }\n        a.recycle();\n        setOrientation(orientation);\n    }\n\n    /**\n     * Sets the orientation for this divider. This should be called if\n     * {@link RecyclerView.LayoutManager} changes orientation.\n     *\n     * @param orientation {@link #HORIZONTAL} or {@link #VERTICAL}\n     */\n    public void setOrientation(int orientation) {\n        if (orientation != HORIZONTAL && orientation != VERTICAL) {\n            throw new IllegalArgumentException(\n                    \"Invalid orientation. It should be either HORIZONTAL or VERTICAL\");\n        }\n        mOrientation = orientation;\n    }\n\n    /**\n     * Sets the {@link Drawable} for this divider.\n     *\n     * @param drawable Drawable that should be used as a divider.\n     */\n    public void setDrawable(@NonNull Drawable drawable) {\n        if (drawable == null) {\n            throw new IllegalArgumentException(\"Drawable cannot be null.\");\n        }\n        mDivider = drawable;\n    }\n\n    @Override\n    public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {\n        if (parent.getLayoutManager() == null || mDivider == null) {\n            return;\n        }\n        if (mOrientation == VERTICAL) {\n            drawVertical(c, parent, state);\n        } else {\n            drawHorizontal(c, parent, state);\n        }\n    }\n\n    private void drawVertical(Canvas canvas, RecyclerView parent, RecyclerView.State state) {\n        canvas.save();\n        final int left;\n        final int right;\n        //noinspection AndroidLintNewApi - NewApi lint fails to handle overrides.\n        if (parent.getClipToPadding()) {\n            left = parent.getPaddingLeft();\n            right = parent.getWidth() - parent.getPaddingRight();\n            canvas.clipRect(left, parent.getPaddingTop(), right,\n                    parent.getHeight() - parent.getPaddingBottom());\n        } else {\n            left = 0;\n            right = parent.getWidth();\n        }\n\n        final int childCount = parent.getChildCount();\n        final int lastPosition = state.getItemCount() - 1;\n        for (int i = 0; i < childCount; i++) {\n            final View child = parent.getChildAt(i);\n            final int childRealPosition = parent.getChildAdapterPosition(child);\n            // mIsShowFirstDivider false绘制第一个view的divider\n            if (childRealPosition == 0 && !mIsShowFirstDivider) {\n                continue;\n            }\n            // mIsShowSecondDivider false绘制第二个view的divider\n            if (childRealPosition == 1 && !mIsShowSecondDivider) {\n                continue;\n            }\n            // mIsShowBottomDivider false的时候不绘制最后一个view的divider\n            if (mIsShowBottomDivider || childRealPosition < lastPosition) {\n                parent.getDecoratedBoundsWithMargins(child, mBounds);\n                final int bottom = mBounds.bottom + Math.round(child.getTranslationY());\n                final int top = bottom - mDivider.getIntrinsicHeight();\n                mDivider.setBounds(left, top, right, bottom);\n                mDivider.draw(canvas);\n            }\n        }\n        canvas.restore();\n    }\n\n    private void drawHorizontal(Canvas canvas, RecyclerView parent, RecyclerView.State state) {\n        canvas.save();\n        final int top;\n        final int bottom;\n        //noinspection AndroidLintNewApi - NewApi lint fails to handle overrides.\n        if (parent.getClipToPadding()) {\n            top = parent.getPaddingTop();\n            bottom = parent.getHeight() - parent.getPaddingBottom();\n            canvas.clipRect(parent.getPaddingLeft(), top,\n                    parent.getWidth() - parent.getPaddingRight(), bottom);\n        } else {\n            top = 0;\n            bottom = parent.getHeight();\n        }\n\n        final int childCount = parent.getChildCount();\n        final int lastPosition = state.getItemCount() - 1;\n        for (int i = 0; i < childCount; i++) {\n            final View child = parent.getChildAt(i);\n            final int childRealPosition = parent.getChildAdapterPosition(child);\n            // mIsShowFirstDivider false绘制第一个view的divider\n            if (childRealPosition == 0 && !mIsShowFirstDivider) {\n                continue;\n            }\n            // mIsShowSecondDivider false绘制第二个view的divider\n            if (childRealPosition == 1 && !mIsShowSecondDivider) {\n                continue;\n            }\n            //mIsShowBottomDivider false的时候不绘制最后一个view的divider\n            if (mIsShowBottomDivider || childRealPosition < lastPosition) {\n                parent.getLayoutManager().getDecoratedBoundsWithMargins(child, mBounds);\n                final int right = mBounds.right + Math.round(child.getTranslationX());\n                final int left = right - mDivider.getIntrinsicWidth();\n                mDivider.setBounds(left, top, right, bottom);\n                mDivider.draw(canvas);\n            }\n        }\n        canvas.restore();\n    }\n\n    @Override\n    public void getItemOffsets(Rect outRect, View view, RecyclerView parent,\n                               RecyclerView.State state) {\n        if (mDivider == null) {\n            outRect.set(0, 0, 0, 0);\n            return;\n        }\n        if (mOrientation == VERTICAL) {\n            //parent.getChildCount() 不能拿到item的总数\n            //https://stackoverflow.com/questions/29666598/android-recyclerview-finding-out-first\n            // -and-last-view-on-itemdecoration\n            int lastPosition = state.getItemCount() - 1;\n            int position = parent.getChildAdapterPosition(view);\n            if (mIsShowBottomDivider || position < lastPosition) {\n                outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());\n            } else {\n                outRect.set(0, 0, 0, 0);\n            }\n        } else {\n            int lastPosition = state.getItemCount() - 1;\n            int position = parent.getChildAdapterPosition(view);\n            if (mIsShowBottomDivider || position < lastPosition) {\n                outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);\n            } else {\n                outRect.set(0, 0, 0, 0);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "module_library/src/main/java/com/lxm/module_library/utils/NetworkConnectionUtils.kt",
    "content": "package com.lxm.module_library.utils\n\nimport android.app.Activity\nimport android.content.ComponentName\nimport android.content.Context\nimport android.content.Intent\nimport android.net.ConnectivityManager\nimport android.net.NetworkInfo\nimport android.net.wifi.WifiConfiguration\nimport android.net.wifi.WifiConfiguration.KeyMgmt\nimport android.net.wifi.WifiManager\nimport android.os.Build\nimport java.io.IOException\n\n\n/**\n *\n * Wifi连接工具类\n */\nobject NetworkConnectionUtils {\n\n    /**\n     * 连接指定\n     *\n     * @param manager\n     * @param wifiSSID\n     * @return\n     */\n    fun connectToSocketWifi(manager: WifiManager, wifiSSID: String): Boolean {\n        val wifiConfiguration = WifiConfiguration()\n        wifiConfiguration.SSID = \"\\\"\" + wifiSSID + \"\\\"\"\n        wifiConfiguration.allowedKeyManagement.set(KeyMgmt.NONE)\n        //小米手机MIUI7/华为EMUI4.1 需要webKey\n        wifiConfiguration.wepKeys[0] = \"\\\"\" + \"\\\"\"\n\n        var networkId = manager.addNetwork(wifiConfiguration)\n\n        if (networkId != -1) {\n            manager.enableNetwork(networkId, true)\n            return true\n        } else {\n            val wifiConfiguration2 = WifiConfiguration()\n            wifiConfiguration2.SSID = \"\\\"\" + wifiSSID + \"\\\"\"\n            //wifiConfiguration.wepKeys[0] = \"\\\"\" + \"\\\"\";//去掉webKey  //小米手机MIUI8不能有webKey\n            wifiConfiguration2.allowedKeyManagement.set(KeyMgmt.NONE)\n            networkId = manager.addNetwork(wifiConfiguration2)\n            if (networkId != -1) {\n                manager.enableNetwork(networkId, true)\n                return true\n            }\n        }\n        return false\n    }\n\n    /**\n     * 获取要连接的wifi节点各个配置选项的加密类型\n     *\n     * @param ssid\n     * @return wifiConfiguration\n     */\n    fun getWifiConfiguration(manager: WifiManager, ssid: String, password: String): WifiConfiguration {\n        val wifiConfiguration = WifiConfiguration()\n        wifiConfiguration.SSID = \"\\\"\" + ssid + \"\\\"\"\n\n        val list = manager.scanResults\n        for (scResult in list) {\n            if (ssid == scResult.SSID) {\n                val capabilities = scResult.capabilities\n                if (capabilities.contains(\"WEP\") || capabilities.contains(\"wep\")) {\n                    wifiConfiguration.allowedKeyManagement.set(KeyMgmt.WPA_EAP)\n                    wifiConfiguration.preSharedKey = \"\\\"\" + password + \"\\\"\"\n                } else if (capabilities.contains(\"WPA\") || capabilities.contains(\"wpa\")) {\n                    wifiConfiguration.allowedKeyManagement.set(KeyMgmt.WPA_PSK)\n                    wifiConfiguration.preSharedKey = \"\\\"\" + password + \"\\\"\"\n                } else {\n                    wifiConfiguration.allowedKeyManagement.set(KeyMgmt.NONE)\n                }\n            }\n        }\n        return wifiConfiguration\n    }\n\n    /**\n     * 给温控器成功发送联网命令后，连接温控器连接的wifi节点\n     *\n     * @param context  上下文对象\n     * @param ssid     ssid\n     * @param password 密码\n     */\n    fun connectWifiSSID(context: Context, manager: WifiManager, ssid: String, password: String) {\n        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {\n            WifiAutoConnectManager(manager).connect(ssid, password, WifiAutoConnectManager\n                    .getCipherType(context, ssid))\n        } else {\n            val networkId = manager.addNetwork(getWifiConfiguration(manager, ssid, password))\n            if (networkId != -1) {\n                manager.enableNetwork(networkId, true)\n            }\n        }\n    }\n\n    /**\n     * 格式化RouterSSID\n     *\n     * @param strRouterSSID 要格式化的当前连接的路由ssid\n     * @return 去除\"\\\"后的RouterSSID字符串\n     */\n    fun formatRouterSSID(strRouterSSID: String): String {\n        var strRouterSSID = strRouterSSID\n        if (strRouterSSID.contains(\"\\\"\")) {\n            strRouterSSID = strRouterSSID.replace(\"\\\"\".toRegex(), \"\")\n        }\n        return strRouterSSID\n    }\n\n    /**\n     * Ping\n     * 用于确定手机是否已经连接上指定设备ip地址\n     */\n    fun pingTest(IPOrDomainName: String): Boolean {\n\n        var isSuccess = false\n        val status: Int\n        var result = \"failed\"\n        val p: Process\n        try {\n            p = Runtime.getRuntime().exec(\"ping -c 1 $IPOrDomainName\")\n            // m_strForNetAddress是输入的网址或者Ip地址\n            status = p.waitFor()\n\n            if (status == 0) {\n                result = \"success\"\n                isSuccess = true\n            }\n\n        } catch (e: IOException) {\n\n        } catch (e: InterruptedException) {\n        }\n\n        return isSuccess\n    }\n\n    /**\n     * 判断网络是否连接\n     */\n    fun isConnected(context: Context): Boolean {\n        val cm = context.applicationContext.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager\n        val info = cm.activeNetworkInfo\n        if (null != info && info.isConnected) {\n            if (info.state == NetworkInfo.State.CONNECTED) {\n                return true\n            }\n        }\n        return false\n    }\n\n    /**\n     * 判断是否有网络\n     *\n     * @return 返回值\n     */\n    fun isNetworkConnected(context: Context?): Boolean {\n        if (context != null) {\n            val mConnectivityManager = context\n                    .getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager\n            val mNetworkInfo = mConnectivityManager.activeNetworkInfo\n\n            if (mNetworkInfo != null) {\n                return mNetworkInfo.isAvailable\n            }\n        }\n        return false\n    }\n\n    /**\n     * 判断是否是wifi连接\n     */\n    fun isWifi(context: Context): Boolean {\n        val cm = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager\n                ?: return false\n\n        val info = cm.activeNetworkInfo\n        if (null != info) {\n            if (info.type == ConnectivityManager.TYPE_WIFI) {\n                return true\n            }\n        }\n        return false\n\n    }\n\n\n    /**\n     * 打开网络设置界面\n     */\n    fun openSetting(activity: Activity, requestCode: Int) {\n        val intent = Intent(\"/\")\n        val cm = ComponentName(\"com.android.settings\",\n                \"com.android.settings.WirelessSettings\")\n        intent.component = cm\n        intent.action = Intent.ACTION_VIEW\n        activity.startActivityForResult(intent, requestCode)\n    }\n}\n"
  },
  {
    "path": "module_library/src/main/java/com/lxm/module_library/utils/PreferencesUtil.kt",
    "content": "package com.lxm.module_library.utils\n\n\nimport android.content.Context\nimport android.content.SharedPreferences\nimport kotlin.properties.ReadWriteProperty\nimport kotlin.reflect.KProperty\n\n/**\n * SharedPreferences工具类封装  委托调用\n */\nclass PreferencesUtil<T>(val key: String, val default: T) : ReadWriteProperty<Any?, T> {\n\n    companion object {\n        lateinit var preferences: SharedPreferences\n        private var mPreferencesName = \"share_preference_default\"\n       public fun get(context: Context) {\n            preferences = context.getSharedPreferences(context.packageName + mPreferencesName, Context.MODE_PRIVATE)\n        }\n    }\n\n    override fun getValue(thisRef: Any?, property: KProperty<*>): T = findPreferences()\n\n    override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) = setPreferences(value)\n\n    private fun findPreferences(): T {\n        return with(preferences) {\n            val res: Any = when (default) {\n                is Int -> getInt(key, default)\n                is Boolean -> getBoolean(key, default)\n                is Float -> getFloat(key, default)\n                is String -> getString(key, default)\n                is Long -> getLong(key, default)\n                else -> throw IllegalArgumentException(\"This type can be saved into Preferences\")\n            }\n            res as T\n        }\n    }\n\n    private fun<T> setPreferences(value: T) = with(preferences.edit()) {\n        when (value) {\n            is Int -> putInt(key, value)\n            is Boolean -> putBoolean(key, value)\n            is Float -> putFloat(key, value)\n            is String -> putString(key, value)\n            is Long -> putLong(key, value)\n            else -> throw IllegalArgumentException(\"This type can be saved into Preferences\")\n        }.apply()\n    }\n\n    /**\n     * 设置preferencesName\n     *\n     * @param preferencesName preferencesName\n     */\n    private fun setPreferencesName(preferencesName: String) {\n        mPreferencesName = preferencesName\n    }\n}\n"
  },
  {
    "path": "module_library/src/main/java/com/lxm/module_library/utils/RefreshHelper.kt",
    "content": "package com.lxm.module_library.utils\n\nimport android.support.v4.content.ContextCompat\nimport android.support.v7.widget.DividerItemDecoration\nimport android.support.v7.widget.LinearLayoutManager\nimport com.lxm.module_library.R\nimport com.lxm.module_library.xrecycleview.XRecyclerView\n\nobject RefreshHelper {\n\n    /**\n     * 默认不显示最后一个item的分割线\n     *\n     * @param isShowFirstDivider  第一个item是否显示分割线\n     * @param isShowSecondDivider 第二个item是否显示分割线\n     */\n    @JvmOverloads\n    fun init(recyclerView: XRecyclerView, isShowFirstDivider: Boolean = true, isShowSecondDivider: Boolean = true) {\n        recyclerView.layoutManager = LinearLayoutManager(recyclerView.context)\n        recyclerView.setPullRefreshEnabled(false)\n        recyclerView.clearHeader()\n//        val itemDecoration = MyDividerItemDecoration(\n//            recyclerView.context,\n//            DividerItemDecoration.VERTICAL,\n//            false,\n//            isShowFirstDivider,\n//            isShowSecondDivider\n//        )\n//        itemDecoration.setDrawable(ContextCompat.getDrawable(recyclerView.context, R.drawable.shape_line)!!)\n//        recyclerView.addItemDecoration(itemDecoration)\n    }\n}\n\n"
  },
  {
    "path": "module_library/src/main/java/com/lxm/module_library/utils/ResourcesUtils.kt",
    "content": "package com.lxm.module_library.utils\n\nimport android.content.res.ColorStateList\nimport android.graphics.drawable.Drawable\nimport android.view.View\n\n/**\n *\n * 资源工具类-加载资源文件\n */\n\nobject ResourcesUtils {\n    /**\n     * 获取strings.xml资源文件字符串\n     *\n     * @param id 资源文件id\n     * @return 资源文件对应字符串\n     */\n    fun getString(id: Int): String {\n        return AppUtils.context.resources.getString(id)\n    }\n\n    /**\n     * 获取strings.xml资源文件字符串数组\n     *\n     * @param id 资源文件id\n     * @return 资源文件对应字符串数组\n     */\n    fun getStringArray(id: Int): Array<String> {\n        return AppUtils.context.resources.getStringArray(id)\n    }\n\n    /**\n     * 获取drawable资源文件图片\n     *\n     * @param id 资源文件id\n     * @return 资源文件对应图片\n     */\n    fun getDrawable(id: Int): Drawable {\n        return AppUtils.context.resources.getDrawable(id)\n    }\n\n    /**\n     * 获取colors.xml资源文件颜色\n     *\n     * @param id 资源文件id\n     * @return 资源文件对应颜色值\n     */\n    fun getColor(id: Int): Int {\n        return AppUtils.context.resources.getColor(id)\n    }\n\n    /**\n     * 获取颜色的状态选择器\n     *\n     * @param id 资源文件id\n     * @return 资源文件对应颜色状态\n     */\n    fun getColorStateList(id: Int): ColorStateList? {\n        return AppUtils.context.resources.getColorStateList(id)\n    }\n\n    /**\n     * 获取dimens资源文件中具体像素值\n     *\n     * @param id 资源文件id\n     * @return 资源文件对应像素值\n     */\n    fun getDimen(id: Int): Int {\n        return AppUtils.context.resources.getDimensionPixelSize(id)\n    }\n\n    /**\n     * 加载布局文件\n     *\n     * @param id 布局文件id\n     * @return 布局view\n     */\n    fun inflate(id: Int): View {\n        return View.inflate(AppUtils.context, id, null)\n    }\n}\n"
  },
  {
    "path": "module_library/src/main/java/com/lxm/module_library/utils/ScreenAdapterUtils.kt",
    "content": "package com.lxm.module_library.utils\n\nimport android.app.Activity\nimport android.content.res.Resources\n\n/**\n *屏幕适配相关\n *\n */\nobject ScreenAdapterUtils {\n    /**\n     * Return whether adapt screen.\n     *\n     * @return `true`: yes<br></br>`false`: no\n     */\n    val isAdaptScreen: Boolean\n        get() {\n            val systemDm = Resources.getSystem().displayMetrics\n            val appDm = AppUtils.context.resources.displayMetrics\n            return systemDm.density != appDm.density\n        }\n\n    /**\n     * Adapt the screen for vertical slide.\n     *\n     * @param activity        The activity.\n     * @param designWidthInPx The size of design diagram's width, in pixel.\n     */\n    fun adaptScreen4VerticalSlide(activity: Activity,\n                                  designWidthInPx: Int) {\n        adaptScreen(activity, designWidthInPx, true)\n    }\n\n    /**\n     * Adapt the screen for horizontal slide.\n     *\n     * @param activity         The activity.\n     * @param designHeightInPx The size of design diagram's height, in pixel.\n     */\n    fun adaptScreen4HorizontalSlide(activity: Activity,\n                                    designHeightInPx: Int) {\n        adaptScreen(activity, designHeightInPx, false)\n    }\n\n    /**\n     * Reference from: https://mp.weixin.qq.com/s/d9QCoBP6kV9VSWvVldVVwA\n     */\n    private fun adaptScreen(activity: Activity,\n                            sizeInPx: Int,\n                            isVerticalSlide: Boolean) {\n        val systemDm = Resources.getSystem().displayMetrics\n        val appDm = AppUtils.context.resources.displayMetrics\n        val activityDm = activity.resources.displayMetrics\n        if (isVerticalSlide) {\n            activityDm.density = activityDm.widthPixels / sizeInPx.toFloat()\n        } else {\n            activityDm.density = activityDm.heightPixels / sizeInPx.toFloat()\n        }\n        activityDm.scaledDensity = activityDm.density * (systemDm.scaledDensity / systemDm.density)\n        activityDm.densityDpi = (160 * activityDm.density).toInt()\n        appDm.density = activityDm.density\n        appDm.scaledDensity = activityDm.scaledDensity\n        appDm.densityDpi = activityDm.densityDpi\n    }\n\n    /**\n     * Cancel adapt the screen.\n     *\n     * @param activity The activity.\n     */\n    fun cancelAdaptScreen(activity: Activity) {\n        val systemDm = Resources.getSystem().displayMetrics\n        val appDm = AppUtils.context.resources.displayMetrics\n        val activityDm = activity.resources.displayMetrics\n        activityDm.density = systemDm.density\n        activityDm.scaledDensity = systemDm.scaledDensity\n        activityDm.densityDpi = systemDm.densityDpi\n        appDm.density = systemDm.density\n        appDm.scaledDensity = systemDm.scaledDensity\n        appDm.densityDpi = systemDm.densityDpi\n    }\n\n}\n"
  },
  {
    "path": "module_library/src/main/java/com/lxm/module_library/utils/ScreenUtils.kt",
    "content": "package com.lxm.module_library.utils\n\nimport android.app.Activity\nimport android.app.ActivityGroup\nimport android.content.Context\nimport android.content.res.Resources\nimport android.graphics.Bitmap\nimport android.graphics.Rect\nimport android.os.Build\nimport android.support.v7.app.AppCompatActivity\nimport android.util.DisplayMetrics\nimport android.util.TypedValue\nimport android.view.View\nimport android.view.ViewGroup\nimport android.view.WindowManager\nimport java.lang.reflect.Field\n\n\n/**\n *\n * 屏幕相关工具类\n */\n\nclass ScreenUtils private constructor() {\n    init {\n        /* cannot be instantiated */\n        throw UnsupportedOperationException(\"cannot be instantiated\")\n    }\n\n    companion object {\n\n\n        private val mStatusHeight = -1\n\n        /**\n         * 获取屏幕的宽度\n         *\n         * @param context\n         * @return\n         */\n        fun getScreenWidth(context: Context): Int {\n            val manager = context\n                    .getSystemService(Context.WINDOW_SERVICE) as WindowManager\n            val displayMetrics = DisplayMetrics()\n            manager.defaultDisplay.getMetrics(displayMetrics)\n            return displayMetrics.widthPixels\n        }\n\n        /**\n         * 获取屏幕的高度\n         *\n         * @param context\n         * @return\n         */\n        fun getScreenHeight(context: Context): Int {\n            val manager = context\n                    .getSystemService(Context.WINDOW_SERVICE) as WindowManager\n            val displayMetrics = DisplayMetrics()\n            manager.defaultDisplay.getMetrics(displayMetrics)\n            return displayMetrics.heightPixels\n        }\n\n        /**\n         * 获取当前屏幕截图，不包含状态栏\n         *\n         * @param activity\n         * @return bp\n         */\n        fun snapShotWithoutStatusBar(activity: Activity): Bitmap? {\n            val view = activity.window.decorView\n            view.isDrawingCacheEnabled = true\n            view.buildDrawingCache()\n            val bmp = view.drawingCache ?: return null\n            val frame = Rect()\n            activity.window.decorView.getWindowVisibleDisplayFrame(frame)\n            val statusBarHeight = frame.top\n            val bp = Bitmap.createBitmap(bmp, 0, statusBarHeight, bmp.width, bmp.height - statusBarHeight)\n            view.destroyDrawingCache()\n            view.isDrawingCacheEnabled = false\n\n            return bp\n        }\n\n        /**\n         * 获取actionbar的像素高度，默认使用android官方兼容包做actionbar兼容\n         *\n         * @return\n         */\n        fun getActionBarHeight(context: Context): Int {\n            var actionBarHeight = 0\n            if (context is AppCompatActivity && context\n                            .supportActionBar != null) {\n\n                actionBarHeight = context.supportActionBar!!.height\n            } else if (context is Activity && context.actionBar != null) {\n\n                actionBarHeight = context.actionBar!!.height\n            } else if (context is ActivityGroup) {\n                if (context.currentActivity is AppCompatActivity && (context.currentActivity as AppCompatActivity)\n                                .supportActionBar != null) {\n                    actionBarHeight = (context\n                            .currentActivity as AppCompatActivity).supportActionBar!!.height\n                } else if (context.currentActivity is Activity && (context.currentActivity as Activity).actionBar != null) {\n                    actionBarHeight = (context.currentActivity as Activity)\n                            .actionBar!!.height\n                }\n            }\n            if (actionBarHeight != 0) {\n                return actionBarHeight\n            }\n            val tv = TypedValue()\n            if (context.theme.resolveAttribute(android.support.v7.appcompat.R.attr\n                            .actionBarSize, tv, true)) {\n                if (context.theme.resolveAttribute(android.support.v7.appcompat.R.attr\n                                .actionBarSize, tv, true)) {\n                    actionBarHeight = TypedValue.complexToDimensionPixelSize(tv.data, context\n                            .resources.displayMetrics)\n                }\n            } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {\n                if (context.theme.resolveAttribute(android.R.attr.actionBarSize, tv, true)) {\n                    actionBarHeight = TypedValue.complexToDimensionPixelSize(tv.data, context\n                            .resources.displayMetrics)\n                }\n            } else {\n                if (context.theme.resolveAttribute(android.support.v7.appcompat.R.attr\n                                .actionBarSize, tv, true)) {\n                    actionBarHeight = TypedValue.complexToDimensionPixelSize(tv.data, context\n                            .resources.displayMetrics)\n                }\n            }\n            return actionBarHeight\n        }\n\n        /**\n         * 反射获取\n         */\n        fun getStatusBarHeight(context: Context): Int {\n            val c: Class<*>\n            val obj: Any\n            val field: Field\n            val x: Int\n            return try {\n                c = Class.forName(\"com.android.internal.R\\$dimen\")\n                obj = c.newInstance()\n                field = c.getField(\"status_bar_height\")\n                x = Integer.parseInt(field.get(obj).toString())\n                context.resources.getDimensionPixelSize(x)\n            } catch (e1: Exception) {\n                e1.printStackTrace()\n                75\n            }\n        }\n\n        /**\n         * 获取系统状态栏高度(会随着修改displayMetrics而改变)\n         */\n        fun getStatusBarHeight(): Int {\n            val resources = AppUtils.context.resources\n            val resourceId = resources.getIdentifier(\"status_bar_height\", \"dimen\", \"android\")\n            return resources.getDimensionPixelSize(resourceId)\n        }\n\n        /**\n         * 获取系统状态栏高度（系统本身处于的状态）\n         */\n        fun getStatusBarHeightSystem(): Int {\n            val resources = Resources.getSystem()\n            val resourceId = resources.getIdentifier(\"status_bar_height\", \"dimen\", \"android\")\n            return resources.getDimensionPixelSize(resourceId)\n        }\n\n\n        /**\n         * 设置view margin\n         *\n         * @param v\n         * @param l\n         * @param t\n         * @param r\n         * @param b\n         */\n        fun setMargins(v: View, l: Int, t: Int, r: Int, b: Int) {\n            if (v.layoutParams is ViewGroup.MarginLayoutParams) {\n                val p = v.layoutParams as ViewGroup.MarginLayoutParams\n                p.setMargins(l, t, r, b)\n                v.requestLayout()\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "module_library/src/main/java/com/lxm/module_library/utils/SnackbarUtils.kt",
    "content": "package com.lxm.module_library.utils\n\nimport android.graphics.Color\nimport android.support.design.widget.Snackbar\nimport android.view.Gravity\nimport android.view.LayoutInflater\nimport android.view.View\nimport android.widget.LinearLayout\nimport android.widget.TextView\nimport com.lxm.module_library.R\n\n\n/**\n * Snackbar工具类\n */\nobject SnackbarUtils {\n\n    private const val Info = 1\n    private const val Confirm = 2\n    private const val Warning = 3\n    private const val Alert = 4\n\n\n    private var red = -0xbbcca\n    private var green = -0xb350b0\n    private var blue = -0xde6a0d\n    private var orange = -0x3ef9\n\n    /**\n     * 短显示Snackbar，自定义颜色\n     *\n     * @param view\n     * @param message\n     * @param messageColor\n     * @param backgroundColor\n     * @return\n     */\n    fun getShort(view: View, message: String, messageColor: Int, backgroundColor: Int): Snackbar {\n        val snackbar = Snackbar.make(view, message, Snackbar.LENGTH_SHORT)\n        setSnackbarColor(snackbar, messageColor, backgroundColor)\n        return snackbar\n    }\n\n    /**\n     * 长显示Snackbar，自定义颜色\n     *\n     * @param view\n     * @param message\n     * @param messageColor\n     * @param backgroundColor\n     * @return\n     */\n    fun getLong(view: View, message: String, messageColor: Int, backgroundColor: Int): Snackbar {\n        val snackbar = Snackbar.make(view, message, Snackbar.LENGTH_LONG)\n        setSnackbarColor(snackbar, messageColor, backgroundColor)\n        return snackbar\n    }\n\n    /**\n     * 自定义时常显示Snackbar，自定义颜色\n     *\n     * @param view\n     * @param message\n     * @param messageColor\n     * @param backgroundColor\n     * @return\n     */\n    fun getIndefinite(view: View, message: String, duration: Int, messageColor: Int, backgroundColor: Int): Snackbar {\n        val snackbar = Snackbar.make(view, message, Snackbar.LENGTH_INDEFINITE).setDuration(duration)\n        setSnackbarColor(snackbar, messageColor, backgroundColor)\n        return snackbar\n    }\n\n    /**\n     * 短显示Snackbar，可选预设类型\n     *\n     * @param view\n     * @param message\n     * @param type\n     * @return\n     */\n    fun getShort(view: View, message: String, type: Int): Snackbar {\n        val snackbar = Snackbar.make(view, message, Snackbar.LENGTH_SHORT)\n        switchType(snackbar, type)\n        return snackbar\n    }\n\n    /**\n     * 长显示Snackbar，可选预设类型\n     *\n     * @param view\n     * @param message\n     * @param type\n     * @return\n     */\n    fun getLong(view: View, message: String, type: Int): Snackbar {\n        val snackbar = Snackbar.make(view, message, Snackbar.LENGTH_LONG)\n        switchType(snackbar, type)\n        return snackbar\n    }\n\n    /**\n     * 自定义时常显示Snackbar，可选预设类型\n     *\n     * @param view\n     * @param message\n     * @param type\n     * @return\n     */\n    fun getIndefinite(view: View, message: String, duration: Int, type: Int): Snackbar {\n        val snackbar = Snackbar.make(view, message, Snackbar.LENGTH_INDEFINITE).setDuration(duration)\n        switchType(snackbar, type)\n        return snackbar\n    }\n\n    //选择预设类型\n    private fun switchType(snackbar: Snackbar, type: Int) {\n        when (type) {\n            Info -> setSnackbarColor(snackbar, blue)\n            Confirm -> setSnackbarColor(snackbar, green)\n            Warning -> setSnackbarColor(snackbar, orange)\n            Alert -> setSnackbarColor(snackbar, Color.YELLOW, red)\n        }\n    }\n\n    /**\n     * 设置Snackbar背景颜色\n     *\n     * @param snackbar\n     * @param backgroundColor\n     */\n    fun setSnackbarColor(snackbar: Snackbar, backgroundColor: Int) {\n        val view = snackbar.view\n        view?.setBackgroundColor(backgroundColor)\n    }\n\n    /**\n     * 设置Snackbar文字和背景颜色\n     *\n     * @param snackbar\n     * @param messageColor\n     * @param backgroundColor\n     */\n    fun setSnackbarColor(snackbar: Snackbar, messageColor: Int, backgroundColor: Int) {\n        val view = snackbar.view\n        if (view != null) {\n            view.setBackgroundColor(backgroundColor)\n            (view.findViewById<View>(R.id.snackbar_text) as TextView).setTextColor(messageColor)\n        }\n    }\n\n    /**\n     * 向Snackbar中添加view\n     *\n     * @param snackbar\n     * @param layoutId\n     * @param index    新加布局在Snackbar中的位置\n     */\n    fun addView(snackbar: Snackbar, layoutId: Int, index: Int) {\n        val snackbarview = snackbar.view\n        val snackbarLayout = snackbarview as Snackbar.SnackbarLayout\n\n        val add_view = LayoutInflater.from(snackbarview.getContext()).inflate(layoutId, null)\n\n        val p = LinearLayout.LayoutParams(LinearLayout.LayoutParams\n                .WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT)\n        p.gravity = Gravity.CENTER_VERTICAL\n\n        snackbarLayout.addView(add_view, index, p)\n    }\n}"
  },
  {
    "path": "module_library/src/main/java/com/lxm/module_library/utils/StatusBarUtils.kt",
    "content": "package com.lxm.module_library.utils\n\nimport android.app.Activity\nimport android.graphics.Color\nimport android.os.Build\nimport android.support.annotation.ColorInt\nimport android.support.v7.widget.Toolbar\nimport android.view.View\nimport android.view.ViewGroup\nimport android.view.WindowManager\n\n\n/**\n *\n * StatusBar工具类\n *\n */\nobject StatusBarUtils {\n\n    /**\n     * 设置状态栏颜色\n     *\n     * @param activity 需要设置的 activity\n     * @param color    状态栏颜色值\n     */\n    private fun setColor(activity: Activity, @ColorInt color: Int) {\n        setBarColor(activity, color)\n    }\n\n    /**\n     * 设置状态栏背景色\n     * 4.4以下不处理\n     * 4.4使用默认沉浸式状态栏\n     *\n     * @param color 要为状态栏设置的颜色值\n     */\n    private fun setBarColor(activity: Activity, color: Int) {\n        val win = activity.window\n        val decorView = win.decorView\n        //沉浸式状态栏(4.4-5.0透明，5.0以上半透明)\n        win.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)\n        //android5.0以上设置透明效果\n        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {\n\n            //让应用的主体内容占用系统状态栏的空间\n            val option = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_STABLE\n            decorView.systemUiVisibility = decorView.systemUiVisibility or option\n            win.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)\n            //设置状态栏背景色\n            win.statusBarColor = color\n        }\n    }\n\n    /**\n     * 设置状态栏全透明\n     *\n     * @param activity 需要设置的activity\n     */\n    fun setTransparent(activity: Activity) {\n        setColor(activity, Color.LTGRAY)\n    }\n\n    /**\n     * 修正 Toolbar 的位置\n     * 在 Android 4.4 版本下无法显示内容在 StatusBar 下，所以无需修正 Toolbar 的位置\n     *\n     * @param toolbar Toolbar\n     */\n    fun fixToolbar(toolbar: Toolbar, activity: Activity) {\n        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {\n            val statusHeight = ScreenUtils.getStatusBarHeight(activity)\n            val layoutParams = toolbar.layoutParams as ViewGroup.MarginLayoutParams\n            layoutParams.setMargins(0, statusHeight, 0, 0)\n        }\n    }\n\n\n}\n"
  },
  {
    "path": "module_library/src/main/java/com/lxm/module_library/utils/StringUtils.kt",
    "content": "package com.lxm.module_library.utils\n\nimport android.text.TextUtils\nimport java.util.regex.Pattern\n\n/**\n * 字符串工具类\n */\nobject StringUtils {\n    /**\n     * 判断字符串是否有值，如果为null或者是空字符串或者只有空格或者为\"null\"字符串，则返回true，否则则返回false\n     */\n    fun isEmpty(value: String?): Boolean {\n        return !(value != null && !\"\".equals(value.trim { it <= ' ' }, ignoreCase = true)\n                && !\"null\".equals(value.trim { it <= ' ' }, ignoreCase = true))\n    }\n\n    /**\n     * 判断字符串是否是邮箱\n     *\n     * @param email email\n     * @return 字符串是否是邮箱\n     */\n    fun isEmail(email: String): Boolean {\n        val str = \"^([a-zA-Z0-9_\\\\-\\\\.]+)@((\\\\[[0-9]{1,3}\\\\.[0-9]{1,3}\\\\.[0-9]{1,3}\\\\.)|(\" + \"([a-zA-Z0-9\\\\-]+\\\\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\\\\]?)$\"\n        val p = Pattern.compile(str)\n        val m = p.matcher(email)\n        return m.matches()\n    }\n\n    /**\n     * 判断手机号字符串是否合法\n     *\n     * @param phoneNumber 手机号字符串\n     * @return 手机号字符串是否合法\n     */\n    fun isPhoneNumberValid(phoneNumber: String): Boolean {\n        var isValid = false\n        val expression = \"^1[3|4|5|7|8]\\\\d{9}$\"\n        val pattern = Pattern.compile(expression)\n        val matcher = pattern.matcher(phoneNumber)\n        if (matcher.matches()) {\n            isValid = true\n        }\n        return isValid\n    }\n\n    /**\n     * 判断手机号字符串是否合法\n     *\n     * @param areaCode    区号\n     * @param phoneNumber 手机号字符串\n     * @return 手机号字符串是否合法\n     */\n    fun isPhoneNumberValid(areaCode: String, phoneNumber: String): Boolean {\n        if (TextUtils.isEmpty(phoneNumber)) {\n            return false\n        }\n\n        if (phoneNumber.length < 5) {\n            return false\n        }\n\n        if (TextUtils.equals(areaCode, \"+86\") || TextUtils.equals(areaCode, \"86\")) {\n            return isPhoneNumberValid(phoneNumber)\n        }\n\n        var isValid = false\n        val expression = \"^[0-9]*$\"\n        val pattern = Pattern.compile(expression)\n        val matcher = pattern.matcher(phoneNumber)\n        if (matcher.matches()) {\n            isValid = true\n        }\n        return isValid\n    }\n\n    /**\n     * 判断字符串是否是手机号格式\n     *\n     * @param areaCode    区号\n     * @param phoneNumber 手机号字符串\n     * @return 字符串是否是手机号格式\n     */\n    fun isPhoneFormat(areaCode: String, phoneNumber: String): Boolean {\n        if (TextUtils.isEmpty(phoneNumber)) {\n            return false\n        }\n\n        if (phoneNumber.length < 7) {\n            return false\n        }\n\n        var isValid = false\n        val expression = \"^[0-9]*$\"\n        val pattern = Pattern.compile(expression)\n        val matcher = pattern.matcher(phoneNumber)\n        if (matcher.matches()) {\n            isValid = true\n        }\n        return isValid\n    }\n\n    /**\n     * 判断字符串是否为纯数字\n     *\n     * @param str 字符串\n     * @return 是否纯数字\n     */\n    fun isNumber(str: String): Boolean {\n        for (i in 0 until str.length) {\n            if (!Character.isDigit(str[i])) {\n                return false\n            }\n        }\n        return true\n    }\n}\n"
  },
  {
    "path": "module_library/src/main/java/com/lxm/module_library/utils/TimestampUtils.kt",
    "content": "package com.lxm.module_library.utils\n\nimport java.text.SimpleDateFormat\nimport java.util.*\n\nobject TimestampUtils {\n    /**\n     * 获取当前的时间戳，时区为北京\n     *\n     * @return\n     */\n    //时间戳的格式必须为 yyyy-MM-dd HH:mm:ss\n    val currentTimestamp: String?\n        get() {\n            var timestamp: String? = null\n            val format = SimpleDateFormat.getDateTimeInstance()\n            timestamp = format.format(Date())\n            return timestamp\n        }\n\n    /**\n     * 获取当前的时间戳，时区为北京\n     *\n     * @return\n     */\n    fun getCurrentTime(times: Long): String {\n        //时间戳的格式必须为 yyyy-MM-dd HH:mm:ss\n        val date = Date(java.lang.Long.valueOf(times))\n        val format = SimpleDateFormat.getDateTimeInstance()\n        val time = format.format(date)\n        SimpleDateFormat.getDateTimeInstance()\n                .format(Date())\n\n        return time\n    }\n\n    //法国时间：东一区\n    fun getDateTimeByGMT(timeZone: Int): String {\n        val dff = SimpleDateFormat.getDateTimeInstance()\n        when (timeZone) {\n            1 -> dff.timeZone = TimeZone.getTimeZone(\"GMT+1\")\n            8 -> dff.timeZone = TimeZone.getTimeZone(\"GMT+8\")\n        }\n\n        return dff.format(Date())\n    }\n}\n"
  },
  {
    "path": "module_library/src/main/java/com/lxm/module_library/utils/ToastUtil.java",
    "content": "package com.lxm.module_library.utils;\n\nimport android.annotation.SuppressLint;\nimport android.text.TextUtils;\nimport android.widget.Toast;\nimport com.lxm.module_library.global.GlobalApplication;\nimport me.drakeet.support.toast.ToastCompat;\n\n/**\n * Created by jingbin on 2016/12/14.\n * 单例Toast，兼容索尼部分手机不弹提示的问题，和vivo7.1.1部分手机崩溃问题\n * An Android library to hook and fix Toast BadTokenException\n * https://github.com/PureWriter/ToastCompat\n */\n\npublic class ToastUtil {\n\n    private static ToastCompat mToast;\n\n    @SuppressLint(\"ShowToast\")\n    public static void showToast(String text) {\n        if (!TextUtils.isEmpty(text)) {\n            if (mToast == null) {\n                mToast = ToastCompat.makeText(GlobalApplication.getInstance(), text, Toast.LENGTH_SHORT);\n            } else {\n                mToast.cancel();\n                mToast = ToastCompat.makeText(GlobalApplication.getInstance(), text, Toast.LENGTH_SHORT);\n            }\n            mToast.setDuration(Toast.LENGTH_SHORT);\n            mToast.setText(text);\n            mToast.show();\n        }\n    }\n\n    @SuppressLint(\"ShowToast\")\n    public static void showToastLong(String text) {\n        if (!TextUtils.isEmpty(text)) {\n            if (mToast == null) {\n                mToast = ToastCompat.makeText(GlobalApplication.getInstance(), text, Toast.LENGTH_LONG);\n            } else {\n                mToast.cancel();\n                mToast = ToastCompat.makeText(GlobalApplication.getInstance(), text, Toast.LENGTH_LONG);\n            }\n            mToast.setDuration(Toast.LENGTH_LONG);\n            mToast.setText(text);\n            mToast.show();\n        }\n    }\n\n}\n"
  },
  {
    "path": "module_library/src/main/java/com/lxm/module_library/utils/ToastUtils.kt",
    "content": "package com.lxm.module_library.utils\n\nimport android.content.Context\nimport android.widget.Toast\nimport com.lxm.module_library.helper.RxHelper\nimport io.reactivex.Observable\n\n/**\n *\n * toast工具类封装\n */\nobject ToastUtils {\n    private var mToast: Toast? = null\n\n    /**\n     * 显示一个toast提示\n     *\n     * @param resourceId toast字符串资源id\n     */\n    fun showToast(resourceId: Int) {\n        showToast(ResourcesUtils.getString(resourceId))\n    }\n\n    /**\n     * 显示一个toast提示\n     *\n     * @param text     toast字符串\n     * @param duration toast显示时间\n     */\n    @JvmOverloads\n    fun showToast(text: String, duration: Int = Toast.LENGTH_SHORT) {\n        showToast(AppUtils.context, text, duration)\n    }\n\n    /**\n     * 显示一个toast提示\n     *\n     * @param context  context 上下文对象\n     * @param text     toast字符串\n     * @param duration toast显示时间\n     */\n    fun showToast(context: Context, text: String, duration: Int) {\n        /**\n         * 保证运行在主线程\n         */\n        val disposable = Observable.just(0)\n                .compose(RxHelper.rxSchedulerHelper())\n                .subscribe {\n                    if (mToast == null) {\n                        mToast = Toast.makeText(context, text, duration)\n                    } else {\n                        mToast!!.setText(text)\n                        mToast!!.duration = duration\n                    }\n                    mToast!!.show()\n                }\n    }\n}\n/**\n * 显示一个toast提示\n *\n * @param text toast字符串\n */\n"
  },
  {
    "path": "module_library/src/main/java/com/lxm/module_library/utils/UnicodeUtils.kt",
    "content": "package com.lxm.module_library.utils\n\n/**\n * Created by Horrarndoo on 2017/10/11.\n *\n */\nobject UnicodeUtils {\n    /**\n     * utf-8 转换成 unicode\n     *\n     * @param inStr\n     * @return\n     */\n    fun utf8ToUnicode(inStr: String): String {\n        val myBuffer = inStr.toCharArray()\n\n        val sb = StringBuffer()\n        for (i in 0 until inStr.length) {\n            val ub = Character.UnicodeBlock.of(myBuffer[i])\n            if (ub === Character.UnicodeBlock.BASIC_LATIN) {\n                //英文及数字等\n                sb.append(myBuffer[i])\n            } else if (ub === Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS) {\n                //全角半角字符\n                val j = myBuffer[i].toInt() - 65248\n                sb.append(j.toChar())\n            } else {\n                //汉字\n                val s = myBuffer[i].toShort()\n                val hexS = Integer.toHexString(s.toInt())\n                val unicode = \"\\\\u$hexS\"\n                sb.append(unicode.toLowerCase())\n            }\n        }\n        return sb.toString()\n    }\n\n    /**\n     * unicode 转换成 utf-8\n     *\n     * @param theString\n     * @return\n     */\n    fun unicodeToUtf8(theString: String): String {\n        var aChar: Char\n        val len = theString.length\n        val outBuffer = StringBuffer(len)\n        var x = 0\n        while (x < len) {\n            aChar = theString[x++]\n            if (aChar == '\\\\') {\n                aChar = theString[x++]\n                if (aChar == 'u') {\n                    var value = 0\n                    for (i in 0..3) {\n                        aChar = theString[x++]\n                        value = when (aChar) {\n                            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' -> (value shl 4) + aChar.toInt() - '0'.toInt()\n                            'a', 'b', 'c', 'd', 'e', 'f' -> (value shl 4) + 10 + aChar.toInt() - 'a'.toInt()\n                            'A', 'B', 'C', 'D', 'E', 'F' -> (value shl 4) + 10 + aChar.toInt() - 'A'.toInt()\n                            else -> throw IllegalArgumentException(\n                                    \"Malformed   \\\\uxxxx   encoding.\")\n                        }\n                    }\n                    outBuffer.append(value.toChar())\n                } else {\n                    if (aChar == 't') {\n                        aChar = '\\t'\n                    } else if (aChar == 'r')\n                        aChar = '\\r'\n                    else if (aChar == 'n')\n                        aChar = '\\n'\n                    else if (aChar == 'f')\n                        aChar = 'f'\n                    outBuffer.append(aChar)\n                }\n            } else\n                outBuffer.append(aChar)\n        }\n        return outBuffer.toString()\n    }\n}"
  },
  {
    "path": "module_library/src/main/java/com/lxm/module_library/utils/WifiAutoConnectManager.kt",
    "content": "package com.lxm.module_library.utils\n\nimport android.content.Context\nimport android.net.wifi.WifiConfiguration\nimport android.net.wifi.WifiManager\n\n/**\n *\n * 兼容Android 6.0以上手机连接wifi\n */\n\nclass WifiAutoConnectManager(internal var wifiManager: WifiManager) {\n\n    /**\n     * 定义几种加密方式，一种是WEP，一种是WPA，还有没有密码的情况\n     */\n    enum class WifiCipherType {\n        WIFICIPHER_WEP, WIFICIPHER_WPA, WIFICIPHER_NOPASS, WIFICIPHER_INVALID\n    }\n\n    fun connect(ssid: String, password: String, type: WifiCipherType) {\n        val thread = Thread(ConnectRunnable(ssid, password, type))\n        thread.start()\n    }\n\n    /**\n     * 查看以前是否也配置过这个网络\n     *\n     * @param SSID\n     * @return\n     */\n    private fun isExsits(SSID: String): WifiConfiguration? {\n        val existingConfigs = wifiManager\n                .configuredNetworks\n        for (existingConfig in existingConfigs) {\n            if (existingConfig.SSID == \"\\\"\" + SSID + \"\\\"\") {\n                return existingConfig\n            }\n        }\n        return null\n    }\n\n    private fun createWifiInfo(SSID: String, Password: String,\n                               Type: WifiCipherType): WifiConfiguration {\n        val config = WifiConfiguration()\n        config.allowedAuthAlgorithms.clear()\n        config.allowedGroupCiphers.clear()\n        config.allowedKeyManagement.clear()\n        config.allowedPairwiseCiphers.clear()\n        config.allowedProtocols.clear()\n        config.SSID = \"\\\"\" + SSID + \"\\\"\"\n\n        if (Type == WifiCipherType.WIFICIPHER_NOPASS) {\n            config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE)\n        }\n        if (Type == WifiCipherType.WIFICIPHER_WEP) {\n            if (!StringUtils.isEmpty(Password)) {\n                if (isHexWepKey(Password)) {\n                    config.wepKeys[0] = Password\n                } else {\n                    config.wepKeys[0] = \"\\\"\" + Password + \"\\\"\"\n                }\n            }\n            config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN)\n            config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED)\n            config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE)\n            config.wepTxKeyIndex = 0\n        }\n        // wpa\n        if (Type == WifiCipherType.WIFICIPHER_WPA) {\n            config.preSharedKey = \"\\\"\" + Password + \"\\\"\"\n            config.hiddenSSID = true\n            config.allowedAuthAlgorithms\n                    .set(WifiConfiguration.AuthAlgorithm.OPEN)\n            config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP)\n            config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK)\n            config.allowedPairwiseCiphers\n                    .set(WifiConfiguration.PairwiseCipher.TKIP)\n            config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP)\n            config.allowedPairwiseCiphers\n                    .set(WifiConfiguration.PairwiseCipher.CCMP)\n            config.status = WifiConfiguration.Status.ENABLED\n\n        }\n        return config\n    }\n\n    /**\n     * 打开wifi功能\n     * @return\n     */\n    private fun openWifi(): Boolean {\n        var bRet = true\n        if (!wifiManager.isWifiEnabled) {\n            bRet = wifiManager.setWifiEnabled(true)\n        }\n        return bRet\n    }\n\n    /**\n     * 关闭WIFI\n     */\n    private fun closeWifi() {\n        if (wifiManager.isWifiEnabled) {\n            wifiManager.isWifiEnabled = false\n        }\n    }\n\n    internal inner class ConnectRunnable(private val ssid: String, private val password: String, private val type: WifiCipherType) : Runnable {\n\n        override fun run() {\n\n            openWifi()\n            // 开启wifi功能需要一段时间(我在手机上测试一般需要1-3秒左右)，所以要等到wifi\n            // 状态变成WIFI_STATE_ENABLED的时候才能执行下面的语句\n            while (wifiManager.wifiState == WifiManager.WIFI_STATE_ENABLING) {\n                try {\n                    // 为了避免程序一直while循环，让它睡个100毫秒检测……\n                    Thread.sleep(100)\n\n                } catch (ie: InterruptedException) {\n\n                }\n\n            }\n\n            val tempConfig = isExsits(ssid)\n\n            if (tempConfig != null) {\n                val b = wifiManager.enableNetwork(tempConfig.networkId,\n                        true)\n            } else {\n                val wifiConfig = createWifiInfo(ssid, password,\n                        type) ?: return\n\n                val netID = wifiManager.addNetwork(wifiConfig)\n                val enabled = wifiManager.enableNetwork(netID, true)\n                val connected = wifiManager.reconnect()\n            }\n\n        }\n    }\n\n    companion object {\n\n        private val TAG = WifiAutoConnectManager::class.java\n                .simpleName\n\n        private fun isHexWepKey(wepKey: String): Boolean {\n            val len = wepKey.length\n\n            // WEP-40, WEP-104, and some vendors using 256-bit WEP (WEP-232?)\n            return if (len != 10 && len != 26 && len != 58) {\n                false\n            } else isHex(wepKey)\n\n        }\n\n        private fun isHex(key: String): Boolean {\n            for (i in key.length - 1 downTo 0) {\n                val c = key[i]\n                val b = !(c >= '0' && c <= '9' || c >= 'A' && c <= 'F' || c >= 'a' && c <= 'f')\n                if (b) {\n                    return false\n                }\n            }\n\n            return true\n        }\n\n        /**\n         * 获取ssid的加密方式\n         *\n         * @param context Context\n         * @param ssid    String\n         * @return\n         */\n        fun getCipherType(context: Context, ssid: String): WifiCipherType {\n            val wifiManager = context\n                    .getSystemService(Context.WIFI_SERVICE) as WifiManager\n\n            val list = wifiManager.scanResults\n\n            for (scResult in list) {\n\n                if (!StringUtils.isEmpty(scResult.SSID) && scResult.SSID == ssid) {\n                    val capabilities = scResult.capabilities\n\n                    if (!StringUtils.isEmpty(capabilities)) {\n\n                        return if (capabilities.contains(\"WPA\") || capabilities.contains(\"wpa\")) {\n                            WifiCipherType.WIFICIPHER_WPA\n                        } else if (capabilities.contains(\"WEP\") || capabilities.contains(\"wep\")) {\n                            WifiCipherType.WIFICIPHER_WEP\n                        } else {\n                            WifiCipherType.WIFICIPHER_NOPASS\n                        }\n                    }\n                }\n            }\n            return WifiCipherType.WIFICIPHER_INVALID\n        }\n    }\n}"
  },
  {
    "path": "module_library/src/main/java/com/lxm/module_library/xrecycleview/BaseRefreshHeader.java",
    "content": "package com.lxm.module_library.xrecycleview;\n\n/**\n * Created by jianghejie on 15/11/22.\n */\ninterface BaseRefreshHeader {\n\n    int STATE_NORMAL = 0;\n    int STATE_RELEASE_TO_REFRESH = 1;\n    int STATE_REFRESHING = 2;\n    int STATE_DONE = 3;\n\n    void onMove(float delta);\n\n    boolean releaseAction();\n\n    void refreshComplate();\n\n    int getVisiableHeight();\n}\n"
  },
  {
    "path": "module_library/src/main/java/com/lxm/module_library/xrecycleview/LoadingMoreFooter.java",
    "content": "package com.lxm.module_library.xrecycleview;\n\nimport android.content.Context;\nimport android.graphics.drawable.AnimationDrawable;\nimport android.util.AttributeSet;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.ImageView;\nimport android.widget.LinearLayout;\nimport android.widget.TextView;\nimport com.lxm.module_library.R;\n\npublic class LoadingMoreFooter extends LinearLayout {\n\n    public final static int STATE_LOADING = 0;\n    public final static int STATE_COMPLETE = 1;\n    public final static int STATE_NOMORE = 2;\n    private TextView mText;\n    private AnimationDrawable mAnimationDrawable;\n    private ImageView mIvProgress;\n\n    public LoadingMoreFooter(Context context) {\n        super(context);\n        initView(context);\n    }\n\n    /**\n     * @param context\n     * @param attrs\n     */\n    public LoadingMoreFooter(Context context, AttributeSet attrs) {\n        super(context, attrs);\n        initView(context);\n    }\n\n    public void initView(Context context) {\n        LayoutInflater.from(context).inflate(R.layout.refresh_footer, this);\n        mText = (TextView) findViewById(R.id.msg);\n        mIvProgress = (ImageView) findViewById(R.id.iv_progress);\n        mAnimationDrawable = (AnimationDrawable) mIvProgress.getDrawable();\n        if (!mAnimationDrawable.isRunning()) {\n            mAnimationDrawable.start();\n        }\n        setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));\n    }\n\n    public void setState(int state) {\n        switch (state) {\n            case STATE_LOADING:\n                if (!mAnimationDrawable.isRunning()) {\n                    mAnimationDrawable.start();\n                }\n                mIvProgress.setVisibility(View.VISIBLE);\n                mText.setText(getContext().getText(R.string.listview_loading));\n                this.setVisibility(View.VISIBLE);\n                break;\n            case STATE_COMPLETE:\n                if (mAnimationDrawable.isRunning()) {\n                    mAnimationDrawable.stop();\n                }\n                mText.setText(getContext().getText(R.string.listview_loading));\n                this.setVisibility(View.GONE);\n                break;\n            case STATE_NOMORE:\n                if (mAnimationDrawable.isRunning()) {\n                    mAnimationDrawable.stop();\n                }\n                mText.setText(getContext().getText(R.string.nomore_loading));\n                mIvProgress.setVisibility(View.GONE);\n                this.setVisibility(View.VISIBLE);\n                break;\n        }\n    }\n\n    public void reSet() {\n        this.setVisibility(GONE);\n    }\n}\n"
  },
  {
    "path": "module_library/src/main/java/com/lxm/module_library/xrecycleview/WrapAdapter.java",
    "content": "package com.lxm.module_library.xrecycleview;\n\nimport android.support.v7.widget.GridLayoutManager;\nimport android.support.v7.widget.RecyclerView;\nimport android.support.v7.widget.StaggeredGridLayoutManager;\nimport android.util.SparseArray;\nimport android.view.View;\nimport android.view.ViewGroup;\n\n/**\n * Created by yangcai on 2016/1/28.\n */\npublic class WrapAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {\n    private static final int TYPE_REFRESH_HEADER = -5;\n    private static final int TYPE_HEADER = -4;\n    private static final int TYPE_NORMAL = 0;\n    private static final int TYPE_FOOTER = -3;\n    private RecyclerView.Adapter adapter;\n\n    private SparseArray<View> mHeaderViews;\n\n    private SparseArray<View> mFootViews;\n\n    private int headerPosition = 1;\n\n    public WrapAdapter(SparseArray<View> headerViews, SparseArray<View> footViews, RecyclerView.Adapter adapter) {\n        this.adapter = adapter;\n        this.mHeaderViews = headerViews;\n        this.mFootViews = footViews;\n    }\n\n    @Override\n    public void onAttachedToRecyclerView(RecyclerView recyclerView) {\n        super.onAttachedToRecyclerView(recyclerView);\n        RecyclerView.LayoutManager manager = recyclerView.getLayoutManager();\n        if (manager instanceof GridLayoutManager) {\n            final GridLayoutManager gridManager = ((GridLayoutManager) manager);\n            gridManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {\n                @Override\n                public int getSpanSize(int position) {\n                    return (isHeader(position) || isFooter(position))\n                            ? gridManager.getSpanCount() : 1;\n                }\n            });\n        }\n    }\n\n    @Override\n    public void onViewAttachedToWindow(RecyclerView.ViewHolder holder) {\n        super.onViewAttachedToWindow(holder);\n        ViewGroup.LayoutParams lp = holder.itemView.getLayoutParams();\n        if (lp != null\n                && lp instanceof StaggeredGridLayoutManager.LayoutParams\n                && (isHeader(holder.getLayoutPosition()) || isFooter(holder.getLayoutPosition()))) {\n            StaggeredGridLayoutManager.LayoutParams p = (StaggeredGridLayoutManager.LayoutParams) lp;\n            p.setFullSpan(true);\n        }\n    }\n\n    public boolean isHeader(int position) {\n        return position >= 0 && position < mHeaderViews.size();\n    }\n\n    public boolean isFooter(int position) {\n        return position < getItemCount() && position >= getItemCount() - mFootViews.size();\n    }\n\n    public boolean isRefreshHeader(int position) {\n        return position == 0;\n    }\n\n    public int getHeadersCount() {\n        return mHeaderViews.size();\n    }\n\n    public int getFootersCount() {\n        return mFootViews.size();\n    }\n\n    @Override\n    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {\n        if (viewType == TYPE_REFRESH_HEADER) {\n            return new SimpleViewHolder(mHeaderViews.get(0));\n        } else if (viewType == TYPE_HEADER) {\n            return new SimpleViewHolder(mHeaderViews.get(headerPosition++));\n        } else if (viewType == TYPE_FOOTER) {\n            return new SimpleViewHolder(mFootViews.get(0));\n        }\n        return adapter.onCreateViewHolder(parent, viewType);\n    }\n\n    @Override\n    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {\n        if (isHeader(position)) {\n            return;\n        }\n        int adjPosition = position - getHeadersCount();\n        int adapterCount;\n        if (adapter != null) {\n            adapterCount = adapter.getItemCount();\n            if (adjPosition < adapterCount) {\n                adapter.onBindViewHolder(holder, adjPosition);\n            }\n        }\n    }\n\n    @Override\n    public int getItemCount() {\n        if (adapter != null) {\n            return getHeadersCount() + getFootersCount() + adapter.getItemCount();\n        } else {\n            return getHeadersCount() + getFootersCount();\n        }\n    }\n\n    @Override\n    public int getItemViewType(int position) {\n        if (isRefreshHeader(position)) {\n            return TYPE_REFRESH_HEADER;\n        }\n        if (isHeader(position)) {\n            return TYPE_HEADER;\n        }\n        if (isFooter(position)) {\n            return TYPE_FOOTER;\n        }\n        int adjPosition = position - getHeadersCount();\n        int adapterCount;\n        if (adapter != null) {\n            adapterCount = adapter.getItemCount();\n            if (adjPosition < adapterCount) {\n                return adapter.getItemViewType(adjPosition);\n            }\n        }\n        return TYPE_NORMAL;\n    }\n\n    @Override\n    public long getItemId(int position) {\n        if (adapter != null && position >= getHeadersCount()) {\n            int adjPosition = position - getHeadersCount();\n            int adapterCount = adapter.getItemCount();\n            if (adjPosition < adapterCount) {\n                return adapter.getItemId(adjPosition);\n            }\n        }\n        return -1;\n    }\n\n    @Override\n    public void unregisterAdapterDataObserver(RecyclerView.AdapterDataObserver observer) {\n        if (adapter != null) {\n            adapter.unregisterAdapterDataObserver(observer);\n        }\n    }\n\n    @Override\n    public void registerAdapterDataObserver(RecyclerView.AdapterDataObserver observer) {\n        if (adapter != null) {\n            adapter.registerAdapterDataObserver(observer);\n        }\n    }\n\n    private class SimpleViewHolder extends RecyclerView.ViewHolder {\n        public SimpleViewHolder(View itemView) {\n            super(itemView);\n        }\n    }\n}"
  },
  {
    "path": "module_library/src/main/java/com/lxm/module_library/xrecycleview/XRecyclerView.java",
    "content": "package com.lxm.module_library.xrecycleview;\n\n\nimport android.content.Context;\nimport android.net.ConnectivityManager;\nimport android.net.NetworkInfo;\nimport android.support.v7.widget.GridLayoutManager;\nimport android.support.v7.widget.LinearLayoutManager;\nimport android.support.v7.widget.RecyclerView;\nimport android.support.v7.widget.StaggeredGridLayoutManager;\nimport android.util.AttributeSet;\nimport android.util.SparseArray;\nimport android.view.MotionEvent;\nimport android.view.View;\nimport android.view.ViewGroup;\n\n/**\n * Created by jingbin on 2016/1/28.\n */\npublic class XRecyclerView extends RecyclerView {\n    private LoadingListener mLoadingListener;\n    private WrapAdapter mWrapAdapter;\n    private SparseArray<View> mHeaderViews = new SparseArray<View>();\n    private SparseArray<View> mFootViews = new SparseArray<View>();\n    private boolean pullRefreshEnabled = true;\n    private boolean loadingMoreEnabled = true;\n    private YunRefreshHeader mRefreshHeader;\n    private boolean isLoadingData;\n    public int previousTotal;\n    public boolean isnomore;\n    private float mLastY = -1;\n    private static final float DRAG_RATE = 1.75f;\n    // 是否是额外添加FooterView\n    private boolean isOther = false;\n\n    public XRecyclerView(Context context) {\n        this(context, null);\n    }\n\n    public XRecyclerView(Context context, AttributeSet attrs) {\n        this(context, attrs, 0);\n    }\n\n    public XRecyclerView(Context context, AttributeSet attrs, int defStyle) {\n        super(context, attrs, defStyle);\n        init(context);\n    }\n\n    private void init(Context context) {\n        if (pullRefreshEnabled) {\n            YunRefreshHeader refreshHeader = new YunRefreshHeader(context);\n            mHeaderViews.put(0, refreshHeader);\n            mRefreshHeader = refreshHeader;\n        }\n        LoadingMoreFooter footView = new LoadingMoreFooter(context);\n        addFootView(footView, false);\n        mFootViews.get(0).setVisibility(GONE);\n    }\n\n    /**\n     * 改为公有。供外添加view使用,使用标识\n     * 注意：使用后不能使用 上拉加载，否则添加无效\n     * 使用时 isOther 传入 true，然后调用 noMoreLoading即可。\n     */\n    public void addFootView(final View view, boolean isOther) {\n        mFootViews.clear();\n        mFootViews.put(0, view);\n        this.isOther = isOther;\n    }\n\n    /**\n     * 相当于加一个空白头布局：\n     * 只有一个目的：为了滚动条显示在最顶端\n     * 因为默认加了刷新头布局，不处理滚动条会下移。\n     * 和 setPullRefreshEnabled(false) 一块儿使用\n     * 使用下拉头时，此方法不应被使用！\n     */\n    public void clearHeader() {\n        mHeaderViews.clear();\n        ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 1);\n        View view = new View(getContext());\n        view.setLayoutParams(params);\n        mHeaderViews.put(0, view);\n    }\n\n    public void addHeaderView(View view) {\n        if (pullRefreshEnabled && !(mHeaderViews.get(0) instanceof YunRefreshHeader)) {\n            YunRefreshHeader refreshHeader = new YunRefreshHeader(getContext());\n            mHeaderViews.put(0, refreshHeader);\n            mRefreshHeader = refreshHeader;\n        }\n        mHeaderViews.put(mHeaderViews.size(), view);\n    }\n\n    private void loadMoreComplete() {\n        isLoadingData = false;\n        View footView = mFootViews.get(0);\n        if (previousTotal <= getLayoutManager().getItemCount()) {\n            if (footView instanceof LoadingMoreFooter) {\n                ((LoadingMoreFooter) footView).setState(LoadingMoreFooter.STATE_COMPLETE);\n            } else {\n                footView.setVisibility(View.GONE);\n            }\n        } else {\n            if (footView instanceof LoadingMoreFooter) {\n                ((LoadingMoreFooter) footView).setState(LoadingMoreFooter.STATE_NOMORE);\n            } else {\n                footView.setVisibility(View.GONE);\n            }\n            isnomore = true;\n        }\n        previousTotal = getLayoutManager().getItemCount();\n    }\n\n    public void noMoreLoading() {\n        isLoadingData = false;\n        final View footView = mFootViews.get(0);\n        isnomore = true;\n        if (footView instanceof LoadingMoreFooter) {\n            ((LoadingMoreFooter) footView).setState(LoadingMoreFooter.STATE_NOMORE);\n        } else {\n            footView.setVisibility(View.GONE);\n        }\n        // 额外添加的footView\n        if (isOther) {\n            footView.setVisibility(View.VISIBLE);\n        }\n    }\n\n    public void refreshComplete() {\n        //  mRefreshHeader.refreshComplate();\n        if (isLoadingData) {\n            loadMoreComplete();\n        } else {\n            mRefreshHeader.refreshComplate();\n        }\n    }\n\n    @Override\n    public void setAdapter(Adapter adapter) {\n        mWrapAdapter = new WrapAdapter(mHeaderViews, mFootViews, adapter);\n        super.setAdapter(mWrapAdapter);\n        adapter.registerAdapterDataObserver(mDataObserver);\n    }\n\n    @Override\n    public void onScrollStateChanged(int state) {\n        super.onScrollStateChanged(state);\n\n        if (state == RecyclerView.SCROLL_STATE_IDLE && mLoadingListener != null && !isLoadingData && loadingMoreEnabled) {\n            LayoutManager layoutManager = getLayoutManager();\n            int lastVisibleItemPosition;\n            if (layoutManager instanceof GridLayoutManager) {\n                lastVisibleItemPosition = ((GridLayoutManager) layoutManager).findLastVisibleItemPosition();\n            } else if (layoutManager instanceof StaggeredGridLayoutManager) {\n                int[] into = new int[((StaggeredGridLayoutManager) layoutManager).getSpanCount()];\n                ((StaggeredGridLayoutManager) layoutManager).findLastVisibleItemPositions(into);\n                lastVisibleItemPosition = findMax(into);\n            } else {\n                lastVisibleItemPosition = ((LinearLayoutManager) layoutManager).findLastVisibleItemPosition();\n            }\n            if (layoutManager.getChildCount() > 0\n                    && lastVisibleItemPosition >= layoutManager.getItemCount() - 1\n                    && layoutManager.getItemCount() > layoutManager.getChildCount()\n                    && !isnomore\n                    && mRefreshHeader.getState() < YunRefreshHeader.STATE_REFRESHING) {\n\n                View footView = mFootViews.get(0);\n                isLoadingData = true;\n                if (footView != null) {\n                    if (footView instanceof LoadingMoreFooter) {\n                        ((LoadingMoreFooter) footView).setState(LoadingMoreFooter.STATE_LOADING);\n                    } else {\n                        footView.setVisibility(View.VISIBLE);\n                    }\n                }\n                if (isNetWorkConnected(getContext())) {\n                    mLoadingListener.onLoadMore();\n                } else {\n                    postDelayed(new Runnable() {\n                        @Override\n                        public void run() {\n                            mLoadingListener.onLoadMore();\n                        }\n                    }, 1000);\n                }\n            }\n        }\n    }\n\n    @Override\n    public boolean onTouchEvent(MotionEvent ev) {\n        if (mLastY == -1) {\n            mLastY = ev.getRawY();\n        }\n        switch (ev.getAction()) {\n            case MotionEvent.ACTION_DOWN:\n                mLastY = ev.getRawY();\n                break;\n            case MotionEvent.ACTION_MOVE:\n                final float deltaY = ev.getRawY() - mLastY;\n                mLastY = ev.getRawY();\n                if (isOnTop() && pullRefreshEnabled) {\n                    mRefreshHeader.onMove(deltaY / DRAG_RATE);\n                    if (mRefreshHeader.getVisiableHeight() > 0 && mRefreshHeader.getState() < YunRefreshHeader.STATE_REFRESHING) {\n                        return false;\n                    }\n                }\n                break;\n            default:\n                mLastY = -1; // reset\n                if (isOnTop() && pullRefreshEnabled) {\n                    if (mRefreshHeader.releaseAction()) {\n                        if (mLoadingListener != null) {\n                            mLoadingListener.onRefresh();\n                            isnomore = false;\n                            previousTotal = 0;\n                            final View footView = mFootViews.get(0);\n                            if (footView instanceof LoadingMoreFooter) {\n                                if (footView.getVisibility() != View.GONE) {\n                                    footView.setVisibility(View.GONE);\n                                }\n                            }\n                        }\n                    }\n                }\n                break;\n        }\n        return super.onTouchEvent(ev);\n    }\n\n    private int findMax(int[] lastPositions) {\n        int max = lastPositions[0];\n        for (int value : lastPositions) {\n            if (value > max) {\n                max = value;\n            }\n        }\n        return max;\n    }\n\n    private int findMin(int[] firstPositions) {\n        int min = firstPositions[0];\n        for (int value : firstPositions) {\n            if (value < min) {\n                min = value;\n            }\n        }\n        return min;\n    }\n\n    public boolean isOnTop() {\n        if (mHeaderViews == null || mHeaderViews.size() == 0) {\n            return false;\n        }\n\n        View view = mHeaderViews.get(0);\n        if (view.getParent() != null) {\n            return true;\n        } else {\n            return false;\n        }\n    }\n\n    private final RecyclerView.AdapterDataObserver mDataObserver = new RecyclerView.AdapterDataObserver() {\n        @Override\n        public void onChanged() {\n            mWrapAdapter.notifyDataSetChanged();\n        }\n\n        @Override\n        public void onItemRangeInserted(int positionStart, int itemCount) {\n            mWrapAdapter.notifyItemRangeInserted(positionStart, itemCount);\n        }\n\n        @Override\n        public void onItemRangeChanged(int positionStart, int itemCount) {\n            mWrapAdapter.notifyItemRangeChanged(positionStart, itemCount);\n        }\n\n        @Override\n        public void onItemRangeChanged(int positionStart, int itemCount, Object payload) {\n            mWrapAdapter.notifyItemRangeChanged(positionStart, itemCount, payload);\n        }\n\n        @Override\n        public void onItemRangeRemoved(int positionStart, int itemCount) {\n            mWrapAdapter.notifyItemRangeRemoved(positionStart, itemCount);\n        }\n\n        @Override\n        public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) {\n            mWrapAdapter.notifyItemMoved(fromPosition, toPosition);\n        }\n    };\n\n\n    public void setLoadingListener(LoadingListener listener) {\n        mLoadingListener = listener;\n    }\n\n    public void setPullRefreshEnabled(boolean pullRefreshEnabled) {\n        this.pullRefreshEnabled = pullRefreshEnabled;\n    }\n\n    public void setLoadingMoreEnabled(boolean loadingMoreEnabled) {\n        this.loadingMoreEnabled = loadingMoreEnabled;\n        if (!loadingMoreEnabled) {\n            if (mFootViews != null) {\n                mFootViews.remove(0);\n            }\n        } else {\n            if (mFootViews != null) {\n                LoadingMoreFooter footView = new LoadingMoreFooter(getContext());\n                addFootView(footView, false);\n            }\n        }\n    }\n\n\n    public void setLoadMoreGone() {\n        if (mFootViews == null) {\n            return;\n        }\n        View footView = mFootViews.get(0);\n        if (footView != null && footView instanceof LoadingMoreFooter) {\n            mFootViews.remove(0);\n        }\n    }\n\n    public interface LoadingListener {\n\n        void onRefresh();\n\n        void onLoadMore();\n    }\n\n    /**\n     * 检测网络是否可用\n     *\n     * @param context\n     * @return\n     */\n    public static boolean isNetWorkConnected(Context context) {\n        if (context != null) {\n            ConnectivityManager mConnectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);\n            NetworkInfo mNetworkInfo = mConnectivityManager.getActiveNetworkInfo();\n            if (mNetworkInfo != null) {\n                return mNetworkInfo.isConnected();\n            }\n        }\n        return false;\n    }\n\n    public void reset() {\n        isnomore = false;\n        previousTotal = 0;\n        final View footView = mFootViews.get(0);\n        if (footView instanceof LoadingMoreFooter) {\n            ((LoadingMoreFooter) footView).reSet();\n        }\n    }\n\n    /**\n     * 是否在刷新数据\n     */\n    public boolean isLoadingData() {\n        return isLoadingData;\n    }\n}\n"
  },
  {
    "path": "module_library/src/main/java/com/lxm/module_library/xrecycleview/YunRefreshHeader.java",
    "content": "package com.lxm.module_library.xrecycleview;\n\nimport android.animation.ValueAnimator;\nimport android.content.Context;\nimport android.graphics.drawable.AnimationDrawable;\nimport android.os.Handler;\nimport android.util.AttributeSet;\nimport android.view.Gravity;\nimport android.view.LayoutInflater;\nimport android.view.ViewGroup;\nimport android.widget.ImageView;\nimport android.widget.LinearLayout;\nimport android.widget.TextView;\nimport com.lxm.module_library.R;\n\n/**\n * Created by yangcai on 2016/1/27.\n */\npublic class YunRefreshHeader extends LinearLayout implements BaseRefreshHeader {\n    private Context mContext;\n    private AnimationDrawable animationDrawable;\n    private TextView msg;\n    private int mState = STATE_NORMAL;\n    private int mMeasuredHeight;\n    private LinearLayout mContainer;\n\n    public YunRefreshHeader(Context context) {\n        this(context, null);\n    }\n\n    public YunRefreshHeader(Context context, AttributeSet attrs) {\n        this(context, attrs, 0);\n    }\n\n    public YunRefreshHeader(Context context, AttributeSet attrs, int defStyleAttr) {\n        super(context, attrs, defStyleAttr);\n        this.mContext = context;\n        initView();\n    }\n\n    private void initView() {\n        LayoutInflater.from(mContext).inflate(R.layout.refresh_header, this);\n        ImageView img = (ImageView) findViewById(R.id.img);\n\n        animationDrawable = (AnimationDrawable) img.getDrawable();\n        if (animationDrawable.isRunning()) {\n            animationDrawable.stop();\n        }\n        msg = (TextView) findViewById(R.id.msg);\n        measure(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);\n        mMeasuredHeight = getMeasuredHeight();\n        setGravity(Gravity.CENTER_HORIZONTAL);\n        mContainer = (LinearLayout) findViewById(R.id.container);\n        mContainer.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, 0));\n        this.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));\n    }\n\n\n    @Override\n    public void onMove(float delta) {\n        if (getVisiableHeight() > 0 || delta > 0) {\n            setVisiableHeight((int) delta + getVisiableHeight());\n            if (mState <= STATE_RELEASE_TO_REFRESH) { // 未处于刷新状态，更新箭头\n                if (getVisiableHeight() > mMeasuredHeight) {\n                    setState(STATE_RELEASE_TO_REFRESH);\n                } else {\n                    setState(STATE_NORMAL);\n                }\n            }\n        }\n    }\n\n    private void setState(int state) {\n        if (state == mState) return;\n        switch (state) {\n            case STATE_NORMAL:\n                if (animationDrawable.isRunning()) {\n                    animationDrawable.stop();\n                }\n                msg.setText(R.string.listview_header_hint_normal);\n                break;\n            case STATE_RELEASE_TO_REFRESH:\n                if (mState != STATE_RELEASE_TO_REFRESH) {\n                    if (!animationDrawable.isRunning()) {\n                        animationDrawable.start();\n                    }\n                    msg.setText(R.string.listview_header_hint_release);\n                }\n                break;\n            case STATE_REFRESHING:\n                msg.setText(R.string.refreshing);\n                break;\n            case STATE_DONE:\n                msg.setText(R.string.refresh_done);\n                break;\n            default:\n        }\n        mState = state;\n    }\n\n    @Override\n    public boolean releaseAction() {\n        boolean isOnRefresh = false;\n        int height = getVisiableHeight();\n        if (height == 0) // not visible.\n            isOnRefresh = false;\n\n        if (getVisiableHeight() > mMeasuredHeight && mState < STATE_REFRESHING) {\n            setState(STATE_REFRESHING);\n            isOnRefresh = true;\n        }\n        // refreshing and header isn't shown fully. do nothing.\n        if (mState == STATE_REFRESHING && height <= mMeasuredHeight) {\n            //return;\n        }\n        int destHeight = 0; // default: scroll back to dismiss header.\n        // is refreshing, just scroll back to show all the header.\n        if (mState == STATE_REFRESHING) {\n            destHeight = mMeasuredHeight;\n        }\n        smoothScrollTo(destHeight);\n\n        return isOnRefresh;\n    }\n\n    @Override\n    public void refreshComplate() {\n        setState(STATE_DONE);\n        new Handler().postDelayed(new Runnable() {\n            public void run() {\n                reset();\n            }\n        }, 500);\n    }\n\n    public void reset() {\n        smoothScrollTo(0);\n        setState(STATE_NORMAL);\n    }\n\n    private void smoothScrollTo(int destHeight) {\n        ValueAnimator animator = ValueAnimator.ofInt(getVisiableHeight(), destHeight);\n        animator.setDuration(300).start();\n        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {\n            @Override\n            public void onAnimationUpdate(ValueAnimator animation) {\n                setVisiableHeight((int) animation.getAnimatedValue());\n            }\n        });\n        animator.start();\n    }\n\n    private void setVisiableHeight(int height) {\n        if (height < 0)\n            height = 0;\n//       `\n        LayoutParams lp = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 0);\n        lp.height = height;\n        mContainer.setLayoutParams(lp);\n    }\n\n    @Override\n    public int getVisiableHeight() {\n        return mContainer.getHeight();\n    }\n\n    public int getState() {\n        return mState;\n    }\n}\n"
  },
  {
    "path": "module_library/src/main/res/drawable/app_loading_anim.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<animation-list xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:oneshot=\"false\">\n\n    <item\n        android:drawable=\"@drawable/app_loading0\"\n        android:duration=\"150\" />\n    <item\n        android:drawable=\"@drawable/app_loading1\"\n        android:duration=\"150\" />\n    <item\n        android:drawable=\"@drawable/app_loading2\"\n        android:duration=\"150\" />\n    <item\n        android:drawable=\"@drawable/app_loading3\"\n        android:duration=\"150\" />\n\n</animation-list>  "
  },
  {
    "path": "module_library/src/main/res/drawable/common_progress_cirle.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<rotate xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:drawable=\"@drawable/loading_image\"\n    android:fromDegrees=\"0\"\n    android:pivotX=\"50%\"\n    android:pivotY=\"50%\"\n    android:toDegrees=\"360\">\n\n</rotate>"
  },
  {
    "path": "module_library/src/main/res/drawable/header_loading_anim.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<animation-list xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:oneshot=\"false\">\n\n    <item\n        android:drawable=\"@drawable/header_loading0\"\n        android:duration=\"250\" />\n    <item\n        android:drawable=\"@drawable/header_loading1\"\n        android:duration=\"250\" />\n    <item\n        android:drawable=\"@drawable/header_loading2\"\n        android:duration=\"250\" />\n    <item\n        android:drawable=\"@drawable/header_loading3\"\n        android:duration=\"250\" />\n\n</animation-list>  "
  },
  {
    "path": "module_library/src/main/res/drawable/ic_add.xml",
    "content": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n        android:width=\"24dp\"\n        android:height=\"24dp\"\n        android:viewportWidth=\"24.0\"\n        android:viewportHeight=\"24.0\">\n    <path\n        android:fillColor=\"#FF000000\"\n        android:pathData=\"M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z\"/>\n</vector>\n"
  },
  {
    "path": "module_library/src/main/res/drawable/ic_clear.xml",
    "content": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n        android:width=\"24dp\"\n        android:height=\"24dp\"\n        android:viewportWidth=\"24.0\"\n        android:viewportHeight=\"24.0\">\n    <path\n        android:fillColor=\"#ffffff\"\n        android:pathData=\"M19,6.41L17.59,5 12,10.59 6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 12,13.41 17.59,19 19,17.59 13.41,12z\"/>\n</vector>\n"
  },
  {
    "path": "module_library/src/main/res/drawable/login_back.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:shape=\"rectangle\">\n    <solid android:color=\"@android:color/transparent\" />\n    <stroke\n        android:width=\"2dp\"\n        android:color=\"@color/material_login_register_color\" />\n</shape>"
  },
  {
    "path": "module_library/src/main/res/drawable/shape_line.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <size android:height=\"1px\"/>\n    <solid android:color=\"#D4D4D4\"/>\n</shape>"
  },
  {
    "path": "module_library/src/main/res/layout/activity_base.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout\n        xmlns:android=\"http://schemas.android.com/apk/res/android\"\n        android:id=\"@+id/ll_root\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:orientation=\"vertical\">\n\n    <android.support.v7.widget.Toolbar xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n                                       android:id=\"@+id/tool_bar\"\n                                       android:layout_width=\"match_parent\"\n                                       android:layout_height=\"?attr/actionBarSize\"\n                                       android:background=\"@color/colorTheme\"\n                                       app:contentInsetStart=\"0.0dp\"\n                                       app:contentInsetStartWithNavigation=\"0dp\"\n                                       app:layout_scrollFlags=\"enterAlways|scroll\"\n                                       app:theme=\"@style/ToolbarStyle\"\n                                       app:popupTheme=\"@style/ThemeOverlay.AppCompat.Light\"/>\n\n\n    <RelativeLayout\n            android:id=\"@+id/container\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"match_parent\">\n\n        <!--加载失败-->\n        <ViewStub\n                android:visibility=\"gone\"\n                android:id=\"@+id/vs_error_refresh\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:layout_centerHorizontal=\"true\"\n                android:layout=\"@layout/layout_loading_error\"/>\n\n        <!--加载中..-->\n        <ViewStub\n                android:visibility=\"gone\"\n                android:id=\"@+id/vs_loading\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:layout_centerHorizontal=\"true\"\n                android:inflatedId=\"@+id/panel_import\"\n                android:layout=\"@layout/layout_loading_view\"/>\n\n    </RelativeLayout>\n</LinearLayout>\n\n"
  },
  {
    "path": "module_library/src/main/res/layout/custom_login_view.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\n<com.lxm.module_library.materialLogin.DefaultLoginView\n        xmlns:android=\"http://schemas.android.com/apk/res/android\"\n        xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n        android:id=\"@+id/login\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        app:loginActionText=\"LOGIN\"\n        app:loginHint=\"UserName\"\n        app:loginPasswordHint=\"PassWord\"\n        app:loginTextColor=\"@color/material_login_register_color\"\n        app:loginTitle=\"login\"/>"
  },
  {
    "path": "module_library/src/main/res/layout/custom_register_view.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\n<com.lxm.module_library.materialLogin.DefaultRegisterView\n        xmlns:android=\"http://schemas.android.com/apk/res/android\"\n        xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n        android:id=\"@+id/login\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        app:registerActionText=\"SIGN UP\"\n        app:registerHint=\"UserName\"\n        app:registerIcon=\"@drawable/ic_person_add_white_24dp\"\n        app:registerPasswordHint=\"Password\"\n        app:registerRepeatPasswordHint=\"Repeat Password\"\n        app:registerTextColor=\"@color/colorWhite\"\n        app:registerTitle=\"Join us\"/>"
  },
  {
    "path": "module_library/src/main/res/layout/default_login_view.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\n<com.lxm.module_library.materialLogin.DefaultLoginView\nxmlns:android=\"http://schemas.android.com/apk/res/android\"\nandroid:id=\"@+id/login\"\nandroid:layout_width=\"match_parent\"\nandroid:layout_height=\"match_parent\"/>"
  },
  {
    "path": "module_library/src/main/res/layout/default_register_view.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\n<com.lxm.module_library.materialLogin.DefaultRegisterView\nxmlns:android=\"http://schemas.android.com/apk/res/android\"\nandroid:id=\"@+id/login\"\nandroid:layout_width=\"match_parent\"\nandroid:layout_height=\"match_parent\"/>"
  },
  {
    "path": "module_library/src/main/res/layout/fragment_base.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<FrameLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        xmlns:android=\"http://schemas.android.com/apk/res/android\">\n\n    <RelativeLayout\n        android:id=\"@+id/container\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\">\n\n        <!--加载失败-->\n        <ViewStub\n            android:id=\"@+id/vs_error_refresh\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"match_parent\"\n            android:layout_centerHorizontal=\"true\"\n            android:layout=\"@layout/layout_loading_error\" />\n\n        <!--加载中..-->\n        <ViewStub\n            android:id=\"@+id/vs_loading\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_alignParentBottom=\"true\"\n            android:layout_centerHorizontal=\"true\"\n            android:inflatedId=\"@+id/panel_import\"\n            android:layout=\"@layout/layout_loading_view\" />\n\n    </RelativeLayout>\n</FrameLayout>"
  },
  {
    "path": "module_library/src/main/res/layout/layout_loading_error.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<android.support.constraint.ConstraintLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    android:id=\"@+id/ll_progress_bar\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:gravity=\"center\">\n\n    <ImageView\n        android:id=\"@+id/img_err\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_marginBottom=\"15dp\"\n        android:src=\"@drawable/load_err\"\n        app:layout_constraintBottom_toTopOf=\"@+id/text_tip\"\n        app:layout_constraintLeft_toLeftOf=\"parent\"\n        app:layout_constraintRight_toRightOf=\"parent\" />\n\n    <TextView\n        android:id=\"@+id/text_tip\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_below=\"@+id/img_err\"\n        android:text=\"加载失败,点击重试\"\n        android:textSize=\"15sp\"\n        app:layout_constraintBottom_toBottomOf=\"parent\"\n        app:layout_constraintLeft_toLeftOf=\"parent\"\n        app:layout_constraintRight_toRightOf=\"parent\"\n        app:layout_constraintTop_toTopOf=\"parent\" />\n\n</android.support.constraint.ConstraintLayout>\n"
  },
  {
    "path": "module_library/src/main/res/layout/layout_loading_view.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<android.support.constraint.ConstraintLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    android:id=\"@+id/ll_progress_bar\"\n    android:layout_width=\"wrap_content\"\n    android:layout_height=\"wrap_content\">\n\n    <ImageView\n        android:id=\"@+id/img_progress\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_marginTop=\"50dp\"\n        android:src=\"@drawable/app_loading_anim\"\n        app:layout_constraintStart_toStartOf=\"parent\"\n        app:layout_constraintTop_toTopOf=\"parent\" />\n\n    <TextView\n        android:id=\"@+id/text_tip\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_marginLeft=\"10dp\"\n        android:layout_marginTop=\"50dp\"\n        android:text=\"努力加载中...\"\n        android:textColor=\"#585858\"\n        android:textSize=\"14sp\"\n        app:layout_constraintLeft_toRightOf=\"@+id/img_progress\"\n        app:layout_constraintTop_toTopOf=\"parent\" />\n\n</android.support.constraint.ConstraintLayout>\n"
  },
  {
    "path": "module_library/src/main/res/layout/login_layout.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n        android:layout_width=\"@dimen/dialog_width\"\n        android:layout_height=\"match_parent\"\n        android:background=\"@color/material_login_login_color\"\n        android:orientation=\"vertical\"\n        android:padding=\"20dp\">\n\n        <TextView\n            android:id=\"@+id/login_title\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginBottom=\"20dp\"\n            android:text=\"@string/login\"\n            android:textColor=\"@color/material_login_register_color\"\n            android:textSize=\"24sp\" />\n\n        <android.support.design.widget.TextInputLayout\n            android:id=\"@+id/login_user\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginBottom=\"20dp\"\n            app:errorTextAppearance=\"@style/MaterialLoginTheme.TextAppearanceLoginError\"\n            app:theme=\"@style/MaterialLoginTheme.TextAppearanceLogin\">\n\n            <AutoCompleteTextView\n                android:id=\"@+id/login_user_autocomplete\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:hint=\"@string/name\"\n                android:inputType=\"textEmailAddress\"\n                android:textSize=\"20sp\" />\n        </android.support.design.widget.TextInputLayout>\n\n        <android.support.design.widget.TextInputLayout\n            android:id=\"@+id/login_pass\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginBottom=\"20dp\"\n            app:errorTextAppearance=\"@style/MaterialLoginTheme.TextAppearanceLoginError\"\n            app:theme=\"@style/MaterialLoginTheme.TextAppearanceLogin\">\n\n            <EditText\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:hint=\"@string/password\"\n                android:inputType=\"textPassword\"\n                android:textSize=\"20sp\" />\n        </android.support.design.widget.TextInputLayout>\n\n        <FrameLayout\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_gravity=\"center_horizontal\"\n            android:background=\"@drawable/login_back\">\n\n            <TextView\n                android:id=\"@+id/login_btn\"\n                style=\"@style/MaterialLoginTheme.SelectableItemBackground\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:padding=\"10dp\"\n                android:text=\"@string/go\"\n                android:textColor=\"@color/material_login_register_color\"\n                android:textSize=\"20sp\" />\n        </FrameLayout>\n</LinearLayout>\n"
  },
  {
    "path": "module_library/src/main/res/layout/login_view.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\n<android.support.design.widget.CoordinatorLayout\nxmlns:android=\"http://schemas.android.com/apk/res/android\"\nxmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:card_view=\"http://schemas.android.com/apk/res-auto\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\">\n\n    <io.codetail.widget.RevealFrameLayout\n        android:id=\"@+id/login_window\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_gravity=\"center\">\n    <android.support.v7.widget.CardView\n        android:id=\"@+id/login_card\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        card_view:cardCornerRadius=\"10dp\"/>\n    </io.codetail.widget.RevealFrameLayout>\n\n    <io.codetail.widget.RevealFrameLayout\n        android:id=\"@+id/register_window\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_gravity=\"center\">\n    <android.support.v7.widget.CardView\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:id=\"@+id/register_card\"\n        card_view:cardCornerRadius=\"10dp\"\n        android:visibility=\"invisible\"/>\n    </io.codetail.widget.RevealFrameLayout>\n\n    <android.support.design.widget.FloatingActionButton\n        android:id=\"@+id/register_fab\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:src=\"@drawable/ic_add\"\n        android:tint=\"@color/material_login_login_color\"\n        app:backgroundTint=\"@color/material_login_register_color\"\n        app:layout_anchor=\"@id/login_window\"\n        app:layout_anchorGravity=\"right|end|top\" />\n\n</android.support.design.widget.CoordinatorLayout>"
  },
  {
    "path": "module_library/src/main/res/layout/refresh_footer.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"wrap_content\"\n    android:orientation=\"vertical\">\n\n    <LinearLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"48dp\"\n        android:gravity=\"center\"\n        android:orientation=\"horizontal\"\n        android:paddingBottom=\"10dp\"\n        android:paddingTop=\"10dp\">\n\n        <ImageView\n            android:id=\"@+id/iv_progress\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:src=\"@drawable/app_loading_anim\" />\n\n        <TextView\n            android:id=\"@+id/msg\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginLeft=\"10dp\"\n            android:text=\"@string/listview_loading\"\n            android:textColor=\"#333333\" />\n    </LinearLayout>\n</LinearLayout>"
  },
  {
    "path": "module_library/src/main/res/layout/refresh_header.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"wrap_content\"\n    android:orientation=\"vertical\">\n\n    <LinearLayout\n        android:id=\"@+id/container\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_marginTop=\"10dp\"\n        android:gravity=\"center\"\n        android:orientation=\"horizontal\"\n        android:paddingBottom=\"10dp\">\n\n        <ImageView\n            android:id=\"@+id/img\"\n            android:layout_width=\"30dp\"\n            android:layout_height=\"30dp\"\n            android:src=\"@drawable/header_loading_anim\" />\n\n        <TextView\n            android:id=\"@+id/msg\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginLeft=\"10dp\"\n            android:text=\"@string/listview_header_hint_normal\" />\n    </LinearLayout>\n</LinearLayout>"
  },
  {
    "path": "module_library/src/main/res/layout/register_layout.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\n<LinearLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    android:layout_width=\"@dimen/dialog_width\"\n        android:layout_height=\"wrap_content\"\n        android:background=\"@color/material_login_register_color\"\n        android:orientation=\"vertical\"\n        android:padding=\"20dp\">\n\n        <LinearLayout\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginBottom=\"20dp\"\n            android:orientation=\"horizontal\">\n\n            <TextView\n                android:id=\"@+id/register_title\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:layout_weight=\"1\"\n                android:text=\"@string/register\"\n                android:textColor=\"@color/material_login_login_color\"\n                android:textSize=\"24sp\" />\n\n            <ImageView\n                android:id=\"@+id/register_cancel\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:src=\"@drawable/ic_clear\"\n                android:tint=\"@color/material_login_login_color\" />\n        </LinearLayout>\n\n        <android.support.design.widget.TextInputLayout\n            android:id=\"@+id/register_user\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginBottom=\"20dp\"\n            app:errorTextAppearance=\"@style/MaterialLoginTheme.TextAppearanceRegisterError\"\n            app:theme=\"@style/MaterialLoginTheme.TextAppearanceRegister\">\n\n            <AutoCompleteTextView\n                android:id=\"@+id/register_user_autocomplete\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:hint=\"@string/name\"\n                android:textColor=\"@color/material_login_login_color\"\n                android:inputType=\"textEmailAddress\"\n                android:textSize=\"20sp\" />\n        </android.support.design.widget.TextInputLayout>\n\n        <android.support.design.widget.TextInputLayout\n            android:id=\"@+id/register_pass\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginBottom=\"20dp\"\n            app:errorTextAppearance=\"@style/MaterialLoginTheme.TextAppearanceRegisterError\"\n            app:theme=\"@style/MaterialLoginTheme.TextAppearanceRegister\">\n\n            <EditText\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:hint=\"@string/password\"\n                android:inputType=\"textPassword\"\n                android:textColor=\"@color/material_login_login_color\"\n                android:textSize=\"20sp\" />\n        </android.support.design.widget.TextInputLayout>\n\n        <android.support.design.widget.TextInputLayout\n            android:id=\"@+id/register_pass_rep\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginBottom=\"20dp\"\n            app:errorTextAppearance=\"@style/MaterialLoginTheme.TextAppearanceRegisterError\"\n            app:theme=\"@style/MaterialLoginTheme.TextAppearanceRegister\">\n\n            <EditText\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:hint=\"@string/repeat_password\"\n                android:inputType=\"textPassword\"\n                android:textColor=\"@color/material_login_login_color\"\n                android:textSize=\"20sp\" />\n        </android.support.design.widget.TextInputLayout>\n\n        <FrameLayout\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:layout_gravity=\"center_horizontal\"\n            android:background=\"@color/material_login_login_color\">\n\n            <TextView\n                android:id=\"@+id/register_btn\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:background=\"?attr/selectableItemBackground\"\n                android:gravity=\"center_horizontal\"\n                android:padding=\"10dp\"\n                android:text=\"@string/next\"\n                android:textColor=\"@color/material_login_register_color\"\n                android:textSize=\"20sp\" />\n        </FrameLayout>\n</LinearLayout>"
  },
  {
    "path": "module_library/src/main/res/values/attrs.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\n    <declare-styleable name=\"MaterialLoginView\">\n        <attr name=\"registerIcon\" format=\"reference\" />\n        <attr name=\"registerEnabled\" format=\"boolean\" />\n        <attr name=\"loginView\" format=\"reference\" />\n        <attr name=\"registerView\" format=\"reference\" />\n    </declare-styleable>\n\n\n    <declare-styleable name=\"DefaultLoginView\">\n        <attr name=\"loginTitle\" format=\"string\" />\n        <attr name=\"loginHint\" format=\"string\" />\n        <attr name=\"loginPasswordHint\" format=\"string\" />\n        <attr name=\"loginActionText\" format=\"string\" />\n        <attr name=\"loginTextColor\" format=\"reference\" />\n    </declare-styleable>\n\n    <declare-styleable name=\"DefaultRegisterView\">\n        <attr name=\"registerTitle\" format=\"string\" />\n        <attr name=\"registerHint\" format=\"string\" />\n        <attr name=\"registerPasswordHint\" format=\"string\" />\n        <attr name=\"registerRepeatPasswordHint\" format=\"string\" />\n        <attr name=\"registerActionText\" format=\"string\" />\n        <attr name=\"registerTextColor\" format=\"reference\" />\n    </declare-styleable>\n</resources>"
  },
  {
    "path": "module_library/src/main/res/values/colors.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\n\n    <color name=\"colorTheme\">#343434</color>\n    <color name=\"colorLine\">#EBEBEB</color>\n    <color name=\"colorHomeLine\">#D4D4D4</color>\n    <color name=\"colorLineDeep\">#BBBBBB</color>\n    <color name=\"colorLineItem\">#FFDDDDDD</color>\n    <color name=\"colorContent\">#ff333333</color>\n    <color name=\"colorTabText\">#585858</color>\n    <color name=\"colorSubtitle\">#999</color>\n    <color name=\"colorTitle\">#666</color>\n    <color name=\"colorWhite\">#ffffffff</color>\n    <color name=\"tabBackground\">#777D7D7D</color>\n\n    <color name=\"material_login_login_color\">#343434</color>\n    <color name=\"material_login_register_color\">#11EE69</color>\n    <color name=\"material_login_login_error_color\">#ff5151</color>\n    <color name=\"material_login_register_error_color\">#ffcdce</color>\n    <color name=\"material_login_login_text_color\">#000</color>\n    <color name=\"material_login_register_text_color\">#000</color>\n</resources>\n"
  },
  {
    "path": "module_library/src/main/res/values/dimen.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <dimen name=\"dialog_width\">250dp</dimen>\n</resources>"
  },
  {
    "path": "module_library/src/main/res/values/drawables.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <item name=\"toolbarItemBackground\" type=\"drawable\">@drawable/abc_item_background_holo_light\n    </item>\n\n</resources>"
  },
  {
    "path": "module_library/src/main/res/values/strings.xml",
    "content": "<resources>\n    <string name=\"app_name\">module_library</string>\n    <string name=\"listview_header_hint_normal\">下拉刷新...</string>\n    <string name=\"listview_header_hint_release\">释放刷新...</string>\n    <string name=\"listview_loading\">努力加载中...</string>\n    <string name=\"nomore_loading\">没有更多内容了</string>\n    <string name=\"refreshing\">正在刷新...</string>\n    <string name=\"refresh_done\">刷新完成...</string>\n    <string name=\"listview_header_last_time\">上次更新时间：</string>\n\n\n    <string name=\"actionbar_webview_share\">分享</string>\n    <string name=\"actionbar_webview_cope\">复制链接</string>\n    <string name=\"actionbar_webview_open\">浏览器打开</string>\n    <string name=\"actionbar_webview_refresh\">刷新</string>\n    <string name=\"actionbar_webview_collect\">添加到收藏</string>\n\n    <string name=\"login\">LOGIN</string>\n    <string name=\"name\">Name</string>\n    <string name=\"password\">Password</string>\n    <string name=\"go\">GO</string>\n    <string name=\"register\">REGISTER</string>\n    <string name=\"repeat_password\">Repeat Password</string>\n    <string name=\"next\">NEXT</string>\n\n</resources>\n"
  },
  {
    "path": "module_library/src/main/res/values/styles.xml",
    "content": "<resources xmlns:tools=\"http://schemas.android.com/tools\">\n\n    <!-- Base application theme. -->\n\n    <style name=\"AppTheme\" parent=\"MyThemeRed\" />\n\n\n\n    <!--titleBar样式-->\n    <style name=\"ToolbarStyle\" parent=\"@style/ThemeOverlay.AppCompat.Dark.ActionBar\">\n        <item name=\"actionBarItemBackground\">@drawable/toolbarItemBackground</item>\n        <item name=\"selectableItemBackground\">@drawable/toolbarItemBackground</item>\n        <item name=\"titleTextAppearance\">@style/ToolBar.Title</item>\n        <item name=\"subtitleTextAppearance\">@style/Toolbar.SubTitle</item>\n        <item name=\"android:windowNoTitle\">true</item>\n        <!--<item name=\"android:textSize\">18sp</item> &lt;!&ndash;  搞掂字体大小&ndash;&gt;-->\n    </style>\n\n    <!--titlebar 标题-->\n    <style name=\"ToolBar.Title\" parent=\"@style/TextAppearance.Widget.AppCompat.Toolbar.Title\">\n        <item name=\"android:textSize\">17sp</item>\n        <item name=\"android:textColor\">@color/colorWhite</item>\n    </style>\n\n    <!--titlebar 副标题-->\n    <style name=\"Toolbar.SubTitle\" parent=\"@style/TextAppearance.Widget.AppCompat.Toolbar.Subtitle\">\n        <item name=\"android:textSize\">9sp</item>\n        <item name=\"android:textColor\">#99ffffff</item>\n    </style>\n\n    <style name=\"MaterialLoginTheme\" parent=\"Theme.AppCompat.Light.DarkActionBar\">\n    </style>\n\n    <style name=\"MaterialLoginTheme.SelectableItemTheme\">\n        <item name=\"colorControlHighlight\">@color/material_login_register_color</item>\n    </style>\n    <style name=\"MaterialLoginTheme.SelectableItemBackground\">\n        <item name=\"android:theme\">@style/MaterialLoginTheme.SelectableItemTheme</item>\n        <item name=\"android:background\">?attr/selectableItemBackground</item>\n    </style>\n\n    <style name=\"MaterialLoginTheme.TextAppearanceRegister\">\n        <item name=\"android:textColor\">@color/material_login_login_color</item>\n        <item name=\"colorControlNormal\">@color/material_login_login_color</item>\n        <item name=\"android:textColorHint\">@color/material_login_login_color</item>\n        <item name=\"colorControlActivated\">@color/material_login_login_color</item>\n        <item name=\"colorControlHighlight\">@color/material_login_login_color</item>\n    </style>\n\n    <style name=\"MaterialLoginTheme.TextAppearanceLogin\">\n        <item name=\"android:textColor\">@color/material_login_register_color</item>\n        <item name=\"colorControlNormal\">@color/material_login_register_color</item>\n        <item name=\"android:textColorHint\">@color/material_login_register_color</item>\n        <item name=\"colorControlActivated\">@color/material_login_register_color</item>\n        <item name=\"colorControlHighlight\">@color/material_login_register_color</item>\n    </style>\n\n    <style name=\"MaterialLoginTheme.TextAppearanceLoginError\" parent=\"android:Widget.TextView\">\n        <item name=\"android:textColor\">@color/material_login_login_error_color</item>\n        <item name=\"android:textSize\">12sp</item>\n    </style>\n\n    <style name=\"MaterialLoginTheme.TextAppearanceRegisterError\" parent=\"android:Widget.TextView\">\n        <item name=\"android:textColor\">@color/material_login_register_error_color</item>\n        <item name=\"android:textSize\">12sp</item>\n    </style>\n\n</resources>\n"
  },
  {
    "path": "module_library/src/main/res/values-w600dp/dimen.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\n    <dimen name=\"dialog_width\">400dp</dimen>\n</resources>"
  },
  {
    "path": "module_library/src/test/java/com/lxm/module_library/ExampleUnitTest.java",
    "content": "package com.lxm.module_library;\n\nimport org.junit.Test;\n\nimport static org.junit.Assert.*;\n\n/**\n * Example local unit test, which will execute on the development machine (host).\n *\n * @see <a href=\"http://d.android.com/tools/testing\">Testing documentation</a>\n */\npublic class ExampleUnitTest {\n    @Test\n    public void addition_isCorrect() {\n        assertEquals(4, 2 + 2);\n    }\n}"
  },
  {
    "path": "settings.gradle",
    "content": "include ':app', ':module_library'\n"
  }
]