yanyi 8 лет назад
Сommit
71c8954b55
100 измененных файлов с 6873 добавлено и 0 удалено
  1. 10 0
      .gitignore
  2. BIN
      .idea/caches/build_file_checksums.ser
  3. 29 0
      .idea/codeStyles/Project.xml
  4. 19 0
      .idea/gradle.xml
  5. 36 0
      .idea/inspectionProfiles/Project_Default.xml
  6. 34 0
      .idea/misc.xml
  7. 12 0
      .idea/runConfigurations.xml
  8. 6 0
      .idea/vcs.xml
  9. 57 0
      README.md
  10. 1 0
      app/.gitignore
  11. 30 0
      app/build.gradle
  12. 21 0
      app/proguard-rules.pro
  13. 26 0
      app/src/androidTest/java/com/mylove/basejava/ExampleInstrumentedTest.java
  14. 22 0
      app/src/main/AndroidManifest.xml
  15. 27 0
      app/src/main/java/com/mylove/basejava/MainActivity.java
  16. 34 0
      app/src/main/res/drawable-v24/ic_launcher_foreground.xml
  17. 170 0
      app/src/main/res/drawable/ic_launcher_background.xml
  18. 15 0
      app/src/main/res/layout/main_activity.xml
  19. 5 0
      app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
  20. 5 0
      app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
  21. BIN
      app/src/main/res/mipmap-hdpi/ic_launcher.png
  22. BIN
      app/src/main/res/mipmap-hdpi/ic_launcher_round.png
  23. BIN
      app/src/main/res/mipmap-mdpi/ic_launcher.png
  24. BIN
      app/src/main/res/mipmap-mdpi/ic_launcher_round.png
  25. BIN
      app/src/main/res/mipmap-xhdpi/ic_launcher.png
  26. BIN
      app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
  27. BIN
      app/src/main/res/mipmap-xxhdpi/ic_launcher.png
  28. BIN
      app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
  29. BIN
      app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
  30. BIN
      app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
  31. 6 0
      app/src/main/res/values/colors.xml
  32. 3 0
      app/src/main/res/values/strings.xml
  33. 11 0
      app/src/main/res/values/styles.xml
  34. 17 0
      app/src/test/java/com/mylove/basejava/ExampleUnitTest.java
  35. 1 0
      baselib/.gitignore
  36. 55 0
      baselib/build.gradle
  37. BIN
      baselib/libs/pinyin4j-2.5.0.jar
  38. 21 0
      baselib/proguard-rules.pro
  39. 26 0
      baselib/src/androidTest/java/com/mylove/baselib/ExampleInstrumentedTest.java
  40. 2 0
      baselib/src/main/AndroidManifest.xml
  41. 216 0
      baselib/src/main/java/com/mylove/baselib/activity/BaseActivity.java
  42. 338 0
      baselib/src/main/java/com/mylove/baselib/activity/BaseActivityLoad.java
  43. 94 0
      baselib/src/main/java/com/mylove/baselib/activity/permission/BasePermissionsActivity.java
  44. 81 0
      baselib/src/main/java/com/mylove/baselib/activity/permission/PermissionBean.java
  45. 91 0
      baselib/src/main/java/com/mylove/baselib/activity/permission/PermissionType.java
  46. 288 0
      baselib/src/main/java/com/mylove/baselib/adapter/CommonRecyclerAdapter.java
  47. 40 0
      baselib/src/main/java/com/mylove/baselib/adapter/TabStripPagerAdapter.java
  48. 55 0
      baselib/src/main/java/com/mylove/baselib/db/DBHelper.java
  49. 202 0
      baselib/src/main/java/com/mylove/baselib/db/DBUtil.java
  50. 163 0
      baselib/src/main/java/com/mylove/baselib/fragment/BaseFragment.java
  51. 367 0
      baselib/src/main/java/com/mylove/baselib/fragment/BaseFragmentLoad.java
  52. 118 0
      baselib/src/main/java/com/mylove/baselib/grobal/AppManager.java
  53. 10 0
      baselib/src/main/java/com/mylove/baselib/listener/CommonListener.java
  54. 25 0
      baselib/src/main/java/com/mylove/baselib/utils/AndroidUtil.java
  55. 35 0
      baselib/src/main/java/com/mylove/baselib/utils/ArrayUtil.java
  56. 526 0
      baselib/src/main/java/com/mylove/baselib/utils/DateUtil.java
  57. 36 0
      baselib/src/main/java/com/mylove/baselib/utils/DpAndPxUtil.java
  58. 39 0
      baselib/src/main/java/com/mylove/baselib/utils/ImageUtil.java
  59. 116 0
      baselib/src/main/java/com/mylove/baselib/utils/InternetUtil.java
  60. 22 0
      baselib/src/main/java/com/mylove/baselib/utils/OnClickTime.java
  61. 76 0
      baselib/src/main/java/com/mylove/baselib/utils/PingYinUtil.java
  62. 364 0
      baselib/src/main/java/com/mylove/baselib/utils/SharedUtil.java
  63. 189 0
      baselib/src/main/java/com/mylove/baselib/utils/StatusBarUtil.java
  64. 350 0
      baselib/src/main/java/com/mylove/baselib/utils/StringUtil.java
  65. 75 0
      baselib/src/main/java/com/mylove/baselib/utils/StringsUtil.java
  66. 167 0
      baselib/src/main/java/com/mylove/baselib/utils/file/FileSizeUtil.java
  67. 15 0
      baselib/src/main/java/com/mylove/baselib/utils/file/SizeType.java
  68. 66 0
      baselib/src/main/java/com/mylove/baselib/utils/toast/ShowMsg.java
  69. 80 0
      baselib/src/main/java/com/mylove/baselib/utils/toast/ShowToast.java
  70. 21 0
      baselib/src/main/java/com/mylove/baselib/utils/toast/ToastType.java
  71. 226 0
      baselib/src/main/java/com/mylove/baselib/viewholder/RecyclerHolder.java
  72. 69 0
      baselib/src/main/java/com/mylove/baselib/widget/BaseView.java
  73. 119 0
      baselib/src/main/java/com/mylove/baselib/widget/FullyGridLayoutManager.java
  74. 98 0
      baselib/src/main/java/com/mylove/baselib/widget/FullyLinearLayoutManager.java
  75. 77 0
      baselib/src/main/java/com/mylove/baselib/widget/GridRecyclerView.java
  76. 60 0
      baselib/src/main/java/com/mylove/baselib/widget/RecyclerViewAnimation.java
  77. 52 0
      baselib/src/main/java/com/mylove/baselib/widget/ScrollForRecycler.java
  78. 40 0
      baselib/src/main/java/com/mylove/baselib/widget/ScrollTextView.java
  79. 263 0
      baselib/src/main/java/com/mylove/baselib/widget/TouchImageView.java
  80. 96 0
      baselib/src/main/java/com/mylove/baselib/widget/VerticalScrollLayout.java
  81. 283 0
      baselib/src/main/java/com/mylove/baselib/widget/VerticalScrollTextView.java
  82. 11 0
      baselib/src/main/res/anim/anim_scroll_in.xml
  83. 11 0
      baselib/src/main/res/anim/anim_scroll_out.xml
  84. 10 0
      baselib/src/main/res/anim/grid_layout_animation_from_bottom.xml
  85. 24 0
      baselib/src/main/res/anim/item_animation_fall_down.xml
  86. 17 0
      baselib/src/main/res/anim/item_animation_from_bottom.xml
  87. 8 0
      baselib/src/main/res/anim/layout_animation_fall_down.xml
  88. 17 0
      baselib/src/main/res/layout/comm_refresh.xml
  89. 9 0
      baselib/src/main/res/layout/comm_toolbar.xml
  90. 42 0
      baselib/src/main/res/layout/item_foot.xml
  91. BIN
      baselib/src/main/res/mipmap-xxxhdpi/shuju_no.png
  92. 45 0
      baselib/src/main/res/values-sw240dp-land/dimens.xml
  93. 45 0
      baselib/src/main/res/values-sw480dp-land/dimens.xml
  94. 45 0
      baselib/src/main/res/values-sw600dp-land/dimens.xml
  95. 45 0
      baselib/src/main/res/values-sw720dp-land/dimens.xml
  96. 45 0
      baselib/src/main/res/values-sw800dp-land/dimens.xml
  97. 45 0
      baselib/src/main/res/values-w820dp/dimens.xml
  98. 19 0
      baselib/src/main/res/values/attrs.xml
  99. 30 0
      baselib/src/main/res/values/colors.xml
  100. 56 0
      baselib/src/main/res/values/dimens.xml

+ 10 - 0
.gitignore

@@ -0,0 +1,10 @@
+*.iml
+.gradle
+/local.properties
+/.idea/libraries
+/.idea/modules.xml
+/.idea/workspace.xml
+.DS_Store
+/build
+/captures
+.externalNativeBuild

BIN
.idea/caches/build_file_checksums.ser


+ 29 - 0
.idea/codeStyles/Project.xml

@@ -0,0 +1,29 @@
+<component name="ProjectCodeStyleConfiguration">
+  <code_scheme name="Project" version="173">
+    <Objective-C-extensions>
+      <file>
+        <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Import" />
+        <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Macro" />
+        <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Typedef" />
+        <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Enum" />
+        <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Constant" />
+        <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Global" />
+        <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Struct" />
+        <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="FunctionPredecl" />
+        <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Function" />
+      </file>
+      <class>
+        <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Property" />
+        <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Synthesize" />
+        <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InitMethod" />
+        <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="StaticMethod" />
+        <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InstanceMethod" />
+        <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="DeallocMethod" />
+      </class>
+      <extensions>
+        <pair source="cpp" header="h" fileNamingConvention="NONE" />
+        <pair source="c" header="h" fileNamingConvention="NONE" />
+      </extensions>
+    </Objective-C-extensions>
+  </code_scheme>
+</component>

+ 19 - 0
.idea/gradle.xml

@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="GradleSettings">
+    <option name="linkedExternalProjectsSettings">
+      <GradleProjectSettings>
+        <option name="distributionType" value="DEFAULT_WRAPPED" />
+        <option name="externalProjectPath" value="$PROJECT_DIR$" />
+        <option name="modules">
+          <set>
+            <option value="$PROJECT_DIR$" />
+            <option value="$PROJECT_DIR$/app" />
+            <option value="$PROJECT_DIR$/baselib" />
+          </set>
+        </option>
+        <option name="resolveModulePerSourceSet" value="false" />
+      </GradleProjectSettings>
+    </option>
+  </component>
+</project>

+ 36 - 0
.idea/inspectionProfiles/Project_Default.xml

@@ -0,0 +1,36 @@
+<component name="InspectionProjectProfileManager">
+  <profile version="1.0">
+    <option name="myName" value="Project Default" />
+    <inspection_tool class="JavaDoc" enabled="true" level="WARNING" enabled_by_default="true">
+      <option name="TOP_LEVEL_CLASS_OPTIONS">
+        <value>
+          <option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
+          <option name="REQUIRED_TAGS" value="" />
+        </value>
+      </option>
+      <option name="INNER_CLASS_OPTIONS">
+        <value>
+          <option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
+          <option name="REQUIRED_TAGS" value="" />
+        </value>
+      </option>
+      <option name="METHOD_OPTIONS">
+        <value>
+          <option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
+          <option name="REQUIRED_TAGS" value="@return@param@throws or @exception" />
+        </value>
+      </option>
+      <option name="FIELD_OPTIONS">
+        <value>
+          <option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
+          <option name="REQUIRED_TAGS" value="" />
+        </value>
+      </option>
+      <option name="IGNORE_DEPRECATED" value="false" />
+      <option name="IGNORE_JAVADOC_PERIOD" value="true" />
+      <option name="IGNORE_DUPLICATED_THROWS" value="false" />
+      <option name="IGNORE_POINT_TO_ITSELF" value="false" />
+      <option name="myAdditionalJavadocTags" value="date" />
+    </inspection_tool>
+  </profile>
+</component>

+ 34 - 0
.idea/misc.xml

@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="NullableNotNullManager">
+    <option name="myDefaultNullable" value="android.support.annotation.Nullable" />
+    <option name="myDefaultNotNull" value="android.support.annotation.NonNull" />
+    <option name="myNullables">
+      <value>
+        <list size="5">
+          <item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
+          <item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
+          <item index="2" class="java.lang.String" itemvalue="javax.annotation.CheckForNull" />
+          <item index="3" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
+          <item index="4" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
+        </list>
+      </value>
+    </option>
+    <option name="myNotNulls">
+      <value>
+        <list size="4">
+          <item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
+          <item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
+          <item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
+          <item index="3" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
+        </list>
+      </value>
+    </option>
+  </component>
+  <component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
+    <output url="file://$PROJECT_DIR$/build/classes" />
+  </component>
+  <component name="ProjectType">
+    <option name="id" value="Android" />
+  </component>
+</project>

+ 12 - 0
.idea/runConfigurations.xml

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="RunConfigurationProducerService">
+    <option name="ignoredProducers">
+      <set>
+        <option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
+        <option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
+        <option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
+      </set>
+    </option>
+  </component>
+</project>

+ 6 - 0
.idea/vcs.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="VcsDirectoryMappings">
+    <mapping directory="$PROJECT_DIR$" vcs="Git" />
+  </component>
+</project>

+ 57 - 0
README.md

@@ -0,0 +1,57 @@
+# BaseJava
+java底层封装(本着能使开发android项目更简单、方便)
+
+ [推荐kotlin项目使用java项目底层](https://github.com/love-yanyi/BaseKotlin)
+
+<br/>
+
+## 使用方法
+
+#### module 下添加
+
+     compile 'com.github.BenYanYi:BaseJava:1.0.1'
+
+ #### project 下添加
+
+    allprojects {
+        repositories {
+            jcenter()
+            maven {
+                url 'https://jitpack.io'
+            }
+        }
+    }
+
+#### 介绍
+
+* 由于使用了butterknife,所以还需要自己引用butterknife
+* 普通的activity继承BaseActivity
+* 普通的fragment继承BaseFragment
+* 提供网络请求方法OkHttpUtil
+* 里面提供了sqlite的封装类,使用时只需要调用DBUtil.getInstance(Context,tabName,dbName,fieldMap,version),
+      调用其中的增删查改方法,其中fieldMap是你要创建的表的表字段,其中的增删查改时出传入的map的key均应填写要均
+      表示表字段,mMap的value表示插入的值,oMap的value表示条件的值,sMap的value表示更改后的值
+* 里面封装了LOG类,使用前需要在Application中初始化,JLog.init(true),默认为false,不显示log,
+      该封装类提供了json显示和xml显示,并能显示类、方法、行号
+* 提供了轻量级存储封装方法SharedUtil,保存方法为save方法,取出方法为get方法,支持基本数据类型,Set<String>和list
+* 2017/11/15更新 添加时间工具类DateUtil,设备工具类AndroidUtil,数组工具类ArrayUtil,装换工具类DpAndPxUtil,
+                     图片工具类ImageUtil,连续点击判断OnClickTime,拼音工具类PinYinUtil,文件大小工具类FileSizeUtil
+                     1.0.8版本之前数据判断方法为StringUtil,1.0.8版本之后更改为FormatUtil
+* 2017/11/24更新 添加权限activity父类
+* 2018/03/07更新 添加[时间选择器](https://github.com/BenYanYi/DateSelect),在父类activity中添加Toolbar
+* 2018/03/07更新 添加颜色资源
+* 2018/04/16更新 优化viewpager中使用带下拉刷新上拉加载的fragment是否在显示当前页面时请求数据,优化RecyclerView的请求动画,
+                  在下拉基类中可以通过设置animationID来设置RecyclerView的动画,添加动画工具类RecyclerViewAnimation,使用时
+                  不设置animationID则会使用默认的RecyclerView动画。
+* 2018/4/27更新 优化一些细节
+* 2018/4/28更新 添加activity是否需要双击退出判断,更改设置布局的方式,添加页面布局中需要设置为layoutID,添加状态栏工具类StatusBarUtil
+* 2018/05/08更新 正式提交开源
+* ........
+
+<br/>
+
+作者:演绎
+
+QQ:1541612424
+
+email: work@yanyi.red

+ 1 - 0
app/.gitignore

@@ -0,0 +1 @@
+/build

+ 30 - 0
app/build.gradle

@@ -0,0 +1,30 @@
+apply plugin: 'com.android.application'
+
+android {
+    compileSdkVersion 27
+    defaultConfig {
+        applicationId "com.mylove.basejava"
+        minSdkVersion 15
+        targetSdkVersion 27
+        versionCode 1
+        versionName "1.0"
+        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
+    }
+    buildTypes {
+        release {
+            minifyEnabled false
+            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+        }
+    }
+}
+
+dependencies {
+    implementation fileTree(include: ['*.jar'], dir: 'libs')
+    implementation 'com.android.support:appcompat-v7:27.1.1'
+    testImplementation 'junit:junit:4.12'
+    androidTestImplementation 'com.android.support.test:runner:1.0.2'
+    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
+    implementation 'com.jakewharton:butterknife:8.8.1'
+    annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'
+    implementation project(':baselib')
+}

+ 21 - 0
app/proguard-rules.pro

@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile

+ 26 - 0
app/src/androidTest/java/com/mylove/basejava/ExampleInstrumentedTest.java

@@ -0,0 +1,26 @@
+package com.mylove.basejava;
+
+import android.content.Context;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
+ */
+@RunWith(AndroidJUnit4.class)
+public class ExampleInstrumentedTest {
+    @Test
+    public void useAppContext() {
+        // Context of the app under test.
+        Context appContext = InstrumentationRegistry.getTargetContext();
+
+        assertEquals("com.mylove.basejava", appContext.getPackageName());
+    }
+}

+ 22 - 0
app/src/main/AndroidManifest.xml

@@ -0,0 +1,22 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.mylove.basejava">
+    <!--用于写入缓存数据到扩展存储卡-->
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.INTERNET" />
+    <!-- 在SDCard中创建与删除文件权限 --><!--STORAGE-->
+    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+    <application
+        android:allowBackup="true"
+        android:icon="@mipmap/ic_launcher"
+        android:label="@string/app_name"
+        android:roundIcon="@mipmap/ic_launcher_round"
+        android:supportsRtl="true"
+        android:theme="@style/AppTheme">
+        <activity android:name=".MainActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>

+ 27 - 0
app/src/main/java/com/mylove/basejava/MainActivity.java

@@ -0,0 +1,27 @@
+package com.mylove.basejava;
+
+import com.mylove.baselib.activity.permission.BasePermissionsActivity;
+import com.mylove.baselib.activity.permission.PermissionType;
+
+/**
+ * @author myLove
+ * @date 2018-05-08 15:04
+ * @e-mail love@yanyi.red
+ * @overview
+ */
+public class MainActivity extends BasePermissionsActivity {
+    @Override
+    protected String[] setPermissions() {
+        return new String[]{PermissionType.STORAGE};
+    }
+
+    @Override
+    protected void setDate() {
+
+    }
+
+    @Override
+    protected int setLayoutID() {
+        return R.layout.main_activity;
+    }
+}

+ 34 - 0
app/src/main/res/drawable-v24/ic_launcher_foreground.xml

@@ -0,0 +1,34 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:aapt="http://schemas.android.com/aapt"
+    android:width="108dp"
+    android:height="108dp"
+    android:viewportHeight="108"
+    android:viewportWidth="108">
+    <path
+        android:fillType="evenOdd"
+        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"
+        android:strokeColor="#00000000"
+        android:strokeWidth="1">
+        <aapt:attr name="android:fillColor">
+            <gradient
+                android:endX="78.5885"
+                android:endY="90.9159"
+                android:startX="48.7653"
+                android:startY="61.0927"
+                android:type="linear">
+                <item
+                    android:color="#44000000"
+                    android:offset="0.0" />
+                <item
+                    android:color="#00000000"
+                    android:offset="1.0" />
+            </gradient>
+        </aapt:attr>
+    </path>
+    <path
+        android:fillColor="#FFFFFF"
+        android:fillType="nonZero"
+        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"
+        android:strokeColor="#00000000"
+        android:strokeWidth="1" />
+</vector>

+ 170 - 0
app/src/main/res/drawable/ic_launcher_background.xml

@@ -0,0 +1,170 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="108dp"
+    android:height="108dp"
+    android:viewportHeight="108"
+    android:viewportWidth="108">
+    <path
+        android:fillColor="#26A69A"
+        android:pathData="M0,0h108v108h-108z" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M9,0L9,108"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,0L19,108"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M29,0L29,108"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M39,0L39,108"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M49,0L49,108"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M59,0L59,108"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M69,0L69,108"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M79,0L79,108"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M89,0L89,108"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M99,0L99,108"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,9L108,9"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,19L108,19"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,29L108,29"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,39L108,39"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,49L108,49"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,59L108,59"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,69L108,69"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,79L108,79"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,89L108,89"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,99L108,99"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,29L89,29"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,39L89,39"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,49L89,49"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,59L89,59"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,69L89,69"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,79L89,79"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M29,19L29,89"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M39,19L39,89"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M49,19L49,89"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M59,19L59,89"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M69,19L69,89"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M79,19L79,89"
+        android:strokeColor="#33FFFFFF"
+        android:strokeWidth="0.8" />
+</vector>

+ 15 - 0
app/src/main/res/layout/main_activity.xml

@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical">
+
+    <include layout="@layout/comm_toolbar" />
+
+    <TextView
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:gravity="center"
+        android:text="Hello World" />
+</LinearLayout>

+ 5 - 0
app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+    <background android:drawable="@drawable/ic_launcher_background" />
+    <foreground android:drawable="@drawable/ic_launcher_foreground" />
+</adaptive-icon>

+ 5 - 0
app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+    <background android:drawable="@drawable/ic_launcher_background" />
+    <foreground android:drawable="@drawable/ic_launcher_foreground" />
+</adaptive-icon>

BIN
app/src/main/res/mipmap-hdpi/ic_launcher.png


BIN
app/src/main/res/mipmap-hdpi/ic_launcher_round.png


BIN
app/src/main/res/mipmap-mdpi/ic_launcher.png


BIN
app/src/main/res/mipmap-mdpi/ic_launcher_round.png


BIN
app/src/main/res/mipmap-xhdpi/ic_launcher.png


BIN
app/src/main/res/mipmap-xhdpi/ic_launcher_round.png


BIN
app/src/main/res/mipmap-xxhdpi/ic_launcher.png


BIN
app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png


BIN
app/src/main/res/mipmap-xxxhdpi/ic_launcher.png


BIN
app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png


+ 6 - 0
app/src/main/res/values/colors.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <color name="colorPrimary">#3F51B5</color>
+    <color name="colorPrimaryDark">#303F9F</color>
+    <color name="colorAccent">#FF4081</color>
+</resources>

+ 3 - 0
app/src/main/res/values/strings.xml

@@ -0,0 +1,3 @@
+<resources>
+    <string name="app_name">BaseJava</string>
+</resources>

+ 11 - 0
app/src/main/res/values/styles.xml

@@ -0,0 +1,11 @@
+<resources>
+
+    <!-- Base application theme. -->
+    <style name="AppTheme" parent="MyAppTheme">
+        <!-- Customize your theme here. -->
+        <item name="colorPrimary">@color/colorPrimary</item>
+        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
+        <item name="colorAccent">@color/colorAccent</item>
+    </style>
+
+</resources>

+ 17 - 0
app/src/test/java/com/mylove/basejava/ExampleUnitTest.java

@@ -0,0 +1,17 @@
+package com.mylove.basejava;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
+ */
+public class ExampleUnitTest {
+    @Test
+    public void addition_isCorrect() {
+        assertEquals(4, 2 + 2);
+    }
+}

+ 1 - 0
baselib/.gitignore

@@ -0,0 +1 @@
+/build

+ 55 - 0
baselib/build.gradle

@@ -0,0 +1,55 @@
+apply plugin: 'com.android.library'
+
+apply plugin: 'com.github.dcendents.android-maven'
+
+group='com.github.BenYanYi'
+
+android {
+    compileSdkVersion 27
+
+
+
+    defaultConfig {
+        minSdkVersion 15
+        targetSdkVersion 27
+        versionCode 1
+        versionName "1.0"
+
+        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
+
+    }
+
+    buildTypes {
+        release {
+            minifyEnabled false
+            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+        }
+    }
+
+}
+
+dependencies {
+    implementation fileTree(dir: 'libs', include: ['*.jar'])
+
+    implementation 'com.android.support:appcompat-v7:27.1.1'
+    testImplementation 'junit:junit:4.12'
+    androidTestImplementation 'com.android.support.test:runner:1.0.2'
+    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
+    implementation 'com.jakewharton:butterknife:8.8.1'
+    annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'
+    api 'com.github.bumptech.glide:glide:4.3.1'
+    annotationProcessor 'com.github.bumptech.glide:compiler:4.3.1'
+    implementation 'com.android.support:recyclerview-v7:27.1.1'
+    api 'com.google.code.gson:gson:2.8.2'
+    implementation 'com.squareup.retrofit2:retrofit:2.3.0'
+    implementation 'com.squareup.retrofit2:converter-gson:2.3.0'
+    implementation 'com.squareup.retrofit2:adapter-rxjava:2.3.0'
+    implementation files('libs/pinyin4j-2.5.0.jar')
+    //okhttp
+    api 'com.github.BenYanYi:OkHttp:1.1.6'
+    //log
+    api 'com.github.BenYanYi:Logger:1.0.1'
+    api 'com.github.BenYanYi:DateSelect:1.0.1'
+    implementation 'com.didikee:permissionsHelper:0.1.8'
+    api 'com.readystatesoftware.systembartint:systembartint:1.0.3'
+}

BIN
baselib/libs/pinyin4j-2.5.0.jar


+ 21 - 0
baselib/proguard-rules.pro

@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile

+ 26 - 0
baselib/src/androidTest/java/com/mylove/baselib/ExampleInstrumentedTest.java

@@ -0,0 +1,26 @@
+package com.mylove.baselib;
+
+import android.content.Context;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
+ */
+@RunWith(AndroidJUnit4.class)
+public class ExampleInstrumentedTest {
+    @Test
+    public void useAppContext() {
+        // Context of the app under test.
+        Context appContext = InstrumentationRegistry.getTargetContext();
+
+        assertEquals("com.mylove.baselib.test", appContext.getPackageName());
+    }
+}

+ 2 - 0
baselib/src/main/AndroidManifest.xml

@@ -0,0 +1,2 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.mylove.baselib" />

+ 216 - 0
baselib/src/main/java/com/mylove/baselib/activity/BaseActivity.java

@@ -0,0 +1,216 @@
+package com.mylove.baselib.activity;
+
+import android.annotation.SuppressLint;
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.support.annotation.Nullable;
+import android.support.v7.app.ActionBar;
+import android.support.v7.app.AppCompatActivity;
+import android.support.v7.widget.Toolbar;
+import android.view.KeyEvent;
+import android.view.MenuItem;
+import android.view.Window;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.TextView;
+
+import com.google.gson.Gson;
+import com.mylove.baselib.R;
+import com.mylove.baselib.grobal.AppManager;
+import com.mylove.baselib.utils.toast.ShowToast;
+
+import butterknife.ButterKnife;
+
+/**
+ * @author myLove
+ * @time 2018/1/8 13:55
+ * @e-mail love@yanyi.red
+ * @overview
+ */
+
+public abstract class BaseActivity extends AppCompatActivity {
+    public Context mContext;
+    public Activity mActivity;
+    public Gson gson = new Gson();
+    public TextView rightTv;
+    protected Toolbar mToolbar;
+
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        this.requestWindowFeature(Window.FEATURE_NO_TITLE);
+        if ((getIntent().getFlags() & Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT) != 0) {
+            finish();
+            return;
+        }
+        AppManager.getInstance().addActivity(this);
+        setContentView(setLayoutID());
+        mContext = this;
+        mActivity = this;
+        mToolbar = findViewById(R.id.toolbar);
+        if (mToolbar != null) {
+            setSupportActionBar(mToolbar);
+            //设置是否有返回箭头
+            if (callback()) {
+                ActionBar actionBar = getSupportActionBar();
+                if (actionBar != null) {
+                    //设置ActionBar一个返回箭头,主界面没有,次级界面有
+                    actionBar.setDisplayHomeAsUpEnabled(true);
+                }
+            }
+        }
+        ButterKnife.bind(this);
+        init();
+    }
+
+    /**
+     * 设置页面
+     *
+     * @return 页面
+     */
+    protected abstract int setLayoutID();
+
+    /**
+     * 逻辑代码
+     */
+    protected abstract void init();
+
+    /**
+     * 是否需要返回键
+     *
+     * @return false
+     */
+    public boolean callback() {
+        return false;
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+        if (item.getItemId() == android.R.id.home) {
+            onBackPressed();
+        }
+        return super.onOptionsItemSelected(item);
+    }
+
+    /**
+     * 关闭软键盘
+     */
+    public void hintKbTwo() {
+        InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
+        if (imm.isActive() && getCurrentFocus() != null) {
+            if (getCurrentFocus().getWindowToken() != null) {
+                imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
+            }
+        }
+    }
+
+    /**
+     * 页面跳转
+     *
+     * @param cls 需要跳转的页面
+     */
+    public void startAct(Class cls) {
+        Intent intent = new Intent(mContext, cls);
+        startActivity(intent);
+    }
+
+    /**
+     * 页面跳转
+     *
+     * @param cls    需要跳转的页面
+     * @param bundle 传递的参数
+     */
+    public void startAct(Class cls, Bundle bundle) {
+        Intent intent = new Intent(mContext, cls);
+        if (bundle != null) {
+            intent.putExtras(bundle);
+        }
+        startActivity(intent);
+    }
+
+    /**
+     * 带返回的跳转页面
+     *
+     * @param cls         需要跳转的页面
+     * @param requestCode 请求的下标
+     */
+    public void startAct(Class cls, int requestCode) {
+        Intent intent = new Intent(mContext, cls);
+        startActivityForResult(intent, requestCode);
+    }
+
+    /**
+     * 带返回的跳转页面
+     *
+     * @param cls         需要跳转的页面
+     * @param bundle      传递的参数
+     * @param requestCode 请求的下标
+     */
+    public void startAct(Class cls, Bundle bundle, int requestCode) {
+        Intent intent = new Intent(mContext, cls);
+        if (bundle != null) {
+            intent.putExtras(bundle);
+        }
+        startActivityForResult(intent, requestCode);
+    }
+
+    public void toast(Object obj) {
+        ShowToast.getInstance(mContext).show(obj);
+    }
+
+    public void toastTest() {
+        ShowToast.getInstance(mContext).show("功能有待开发");
+    }
+
+    /**
+     * 是否双击退出应用
+     *
+     * @return 默认false
+     */
+    public boolean isExit() {
+        return false;
+    }
+
+    /**
+     * 标记是否退出
+     */
+    private boolean isExit;
+
+    /**
+     * 重写onKeyDown方法
+     */
+    @Override
+    public boolean onKeyDown(int keyCode, KeyEvent event) {
+        if (keyCode == KeyEvent.KEYCODE_BACK && isExit()) {
+            exit();
+            return false;
+        } else {
+            return super.onKeyDown(keyCode, event);
+        }
+    }
+
+    /**
+     * 退出方法
+     */
+    private void exit() {
+        if (!isExit) {
+            isExit = true;
+            toast("再按一次退出程序");
+            mHandler.sendEmptyMessageDelayed(0, 2000);
+        } else {
+            AppManager.getInstance().AppExit(mContext);
+        }
+    }
+
+    @SuppressLint("HandlerLeak")
+    Handler mHandler = new Handler() {
+        @Override
+        public void handleMessage(Message msg) {
+            super.handleMessage(msg);
+            isExit = false;
+        }
+    };
+}

+ 338 - 0
baselib/src/main/java/com/mylove/baselib/activity/BaseActivityLoad.java

@@ -0,0 +1,338 @@
+package com.mylove.baselib.activity;
+
+import android.os.Handler;
+import android.support.v4.widget.SwipeRefreshLayout;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.mylove.baselib.R;
+import com.mylove.baselib.adapter.CommonRecyclerAdapter;
+import com.mylove.baselib.utils.StringUtil;
+import com.mylove.baselib.viewholder.RecyclerHolder;
+import com.mylove.baselib.widget.RecyclerViewAnimation;
+import com.mylove.loglib.JLog;
+import com.mylove.okhttp.ResultMsg;
+import com.mylove.okhttp.onOkHttpListener;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author myLove
+ * @time 2018-01-10 15:05
+ * @e-mail love@yanyi.red
+ * @overview
+ */
+
+public abstract class BaseActivityLoad<T> extends BaseActivity implements onOkHttpListener {
+    public RecyclerView commRecycler;
+    public SwipeRefreshLayout commSwipe;
+    public LinearLayout footLinear;
+    public LinearLayout footLoading;
+    public TextView footPrompt;
+    public CommonRecyclerAdapter<T> mAdapter;
+    public List<T> oList = new ArrayList<>();
+    public Handler handler = new Handler();
+    /**
+     * 下拉刷新的标识
+     */
+    public int REFRESH = 0;
+    /**
+     * 上拉加载更多的标识
+     */
+    public int LOAD = 1;
+    /**
+     * 判断是否没有数据可加载
+     */
+    private boolean boo = true;
+    /**
+     * 每页加载的条数
+     */
+    public int pageSize = 10;
+    public int page = 1;
+    public int sumSize = 0;
+    public int what = REFRESH;
+
+    public boolean NoData = false;
+
+    private int animationID = 0;
+
+    @Override
+    protected void init() {
+        commRecycler = findViewById(R.id.recycler);
+        commSwipe = findViewById(R.id.swipe_refresh);
+        commSwipe.setColorSchemeColors(getResources().getColor(R.color.comm_blue),
+                getResources().getColor(R.color.comm_green), getResources().getColor(R.color.comm_red));
+        setAdapter();
+        setHeader();
+        setFooter();
+        refreshData();
+    }
+
+    /**
+     * 设置适配器
+     */
+    public void setAdapter() {
+        if (setLayoutManager() == null) {
+            throw new NullPointerException("RecyclerView样式不能为空");
+        }
+        if (setItemLayout() == 0) {
+            throw new NullPointerException("adapter需要设置item布局");
+        }
+        oList.clear();
+        commRecycler.setLayoutManager(setLayoutManager());
+        mAdapter = new CommonRecyclerAdapter<T>(mContext, oList, setItemLayout()) {
+            @Override
+            public void convert(RecyclerHolder mHolder, T item, int position, boolean isScrolling) {
+                adapterConvert(mHolder, item, position, isScrolling);
+            }
+        };
+        commRecycler.setAdapter(mAdapter);
+        notifyData(oList);
+//        if (isListAnimation()) {
+//            RecyclerViewAnimation.runLayoutAnimation(commRecycler, oList);
+//        } else {
+//            mAdapter.notifyDataSetChanged(oList);
+//        }
+    }
+
+    protected abstract RecyclerView.LayoutManager setLayoutManager();
+
+    /**
+     * 设置适配器
+     */
+    protected abstract int setItemLayout();
+
+    /**
+     * item设置参数
+     *
+     * @param mHolder
+     * @param item
+     * @param position
+     * @param isScrolling
+     */
+    protected abstract void adapterConvert(RecyclerHolder mHolder, T item, int position, boolean isScrolling);
+
+    /**
+     * 设置头部
+     */
+    public void setHeader() {
+    }
+
+    protected void setFooter() {
+        View footer = LayoutInflater.from(mContext).inflate(R.layout.item_foot, commRecycler, false);
+        footLinear = footer.findViewById(R.id.foot_linear);
+        footLoading = footer.findViewById(R.id.foot_loading);
+        footPrompt = footer.findViewById(R.id.foot_prompt);
+        mAdapter.addFooterView(footer);
+    }
+
+    /**
+     * 刷新以及加载更多
+     */
+    private void refreshData() {
+        dataInit();
+        //下拉刷新
+        commSwipe.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
+            @Override
+            public void onRefresh() {
+                handler.post(new Runnable() {
+                    @Override
+                    public void run() {
+                        dataInit();
+                    }
+                });
+            }
+        });
+        commRecycler.addOnScrollListener(new RecyclerView.OnScrollListener() {
+            int lastVisibleItem = 0;
+            //在屏幕上可见的item数量
+            private int visibleItemCount = 0;
+            //已经加载出来的Item的数量
+            private int totalItemCount = 0;
+            //在屏幕可见的Item中的第一个
+            private int firstVisibleItem = 0;
+//            //是否正在上拉数据
+//            private boolean loading = true;
+//            //主要用来存储上一个totalItemCount
+//            private int previousTotal = 0;
+
+            private int viewSize = 0;
+
+            /**
+             * 滚动中调用
+             */
+            @Override
+            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
+                super.onScrollStateChanged(recyclerView, newState);
+                LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
+                viewSize = 0;
+                boolean footerView = mAdapter.haveFootView();
+                boolean headerView = mAdapter.haveHeaderView();
+                if (footerView) {
+                    viewSize++;
+                }
+                if (headerView) {
+                    viewSize++;
+                }
+                visibleItemCount = recyclerView.getChildCount();
+                totalItemCount = layoutManager.getItemCount();
+                firstVisibleItem = layoutManager.findFirstVisibleItemPosition();
+                if (boo && totalItemCount >= (pageSize * page)
+                        && totalItemCount == (oList.size() + viewSize)
+                        && (lastVisibleItem + viewSize) == totalItemCount
+                        && (footLoading.getVisibility()) == View.VISIBLE) {
+                    page++;
+                    what = LOAD;
+                    loadResultData();
+                }
+            }
+
+            /**
+             * 滚动停止后调用
+             */
+            @Override
+            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
+                super.onScrolled(recyclerView, dx, dy);
+                LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
+//                //最后一个可见的item
+                lastVisibleItem = layoutManager.findLastVisibleItemPosition();
+                if (boo && lastVisibleItem + viewSize == oList.size()) {
+                    //显示加载中进度条
+                    handler.post(new Runnable() {
+                        @Override
+                        public void run() {
+                            footLinear.setVisibility(View.VISIBLE);
+                            footLoading.setVisibility(View.VISIBLE);
+                        }
+                    });
+                }
+            }
+        });
+    }
+
+    /**
+     * 请求数据的方法
+     */
+    protected abstract void loadResultData();
+
+    public void notifyData(List<T> list) {
+        oList = list;
+        if (isListAnimation()) {
+            RecyclerViewAnimation.getInstance(animationID).runLayoutAnimation(commRecycler, oList);
+        } else {
+            mAdapter.notifyDataSetChanged(oList);
+        }
+    }
+
+    /**
+     * 刷新页面
+     */
+    public void notifyUi() {
+        dataInit();
+    }
+
+    public void cleanAdapter() {
+        oList.clear();
+        notifyData(oList);
+    }
+
+    private void dataInit() {
+        cleanAdapter();
+        NoData = false;
+        footLinear.setVisibility(View.VISIBLE);
+        footLoading.setVisibility(View.VISIBLE);
+        footPrompt.setText(getResources().getString(R.string.loading));
+        page = 1;
+        pageSize = 10;
+        what = REFRESH;
+        loadResultData();
+    }
+
+    /**
+     * 状态改变
+     */
+    private void status() {
+        if (StringUtil.isListNotEmpty(oList)) {
+            JLog.v(oList);
+        }
+        handler.postDelayed(new Runnable() {
+            @Override
+            public void run() {
+                boo = true;
+                footLoading.setVisibility(View.GONE);
+                commSwipe.setRefreshing(false);
+                if (StringUtil.isListEmpty(oList)) {
+                    JLog.v();
+                    boo = false;
+                    footLinear.setVisibility(View.VISIBLE);
+                    footPrompt.setText("暂无数据");
+                    footPrompt.setVisibility(View.VISIBLE);
+                } else if ((oList.size() == sumSize && NoData) || oList.size() % pageSize != 0) {
+                    JLog.v();
+                    boo = false;
+                    footLinear.setVisibility(View.VISIBLE);
+                    footPrompt.setVisibility(View.VISIBLE);
+                    footPrompt.setText("已加载全部数据");
+                } else {
+                    JLog.v();
+                    footLinear.setVisibility(View.GONE);
+                    footPrompt.setVisibility(View.GONE);
+                }
+                sumSize = oList.size();
+                notifyData(oList);
+            }
+        }, 500);
+    }
+
+    @Override
+    public void onSuccess(ResultMsg resultMsg) {
+        disposeResultData(resultMsg.getResult());
+        status();
+    }
+
+    @Override
+    public void onCompleted() {
+
+    }
+
+    @Override
+    public void onFailure(Throwable t) {
+        JLog.e(t.getMessage());
+        oList.clear();
+        status();
+    }
+
+    /**
+     * 数据处理
+     *
+     * @param json 网络数据
+     */
+    protected abstract void disposeResultData(String json);
+
+    /**
+     * 是否显示RecyclerView动画
+     *
+     * @return
+     */
+    public boolean isListAnimation() {
+        return true;
+    }
+
+    /**
+     * 设置动画ID
+     *
+     * @param animationID
+     */
+    public void setAnimationID(int animationID) {
+        this.animationID = animationID;
+    }
+
+    public int getAnimationID() {
+        return animationID;
+    }
+}

+ 94 - 0
baselib/src/main/java/com/mylove/baselib/activity/permission/BasePermissionsActivity.java

@@ -0,0 +1,94 @@
+package com.mylove.baselib.activity.permission;
+
+import android.content.Intent;
+import android.support.annotation.NonNull;
+
+import com.mylove.baselib.activity.BaseActivity;
+import com.mylove.loglib.JLog;
+
+import didikee.com.permissionshelper.PermissionsHelper;
+import didikee.com.permissionshelper.info.DialogInfo;
+
+/**
+ * @author myLove
+ * @time 2017/11/24 16:33
+ * @e-mail mylove.520.y@gmail.com
+ * @overview 获取权限activity
+ */
+
+public abstract class BasePermissionsActivity extends BaseActivity {
+    private PermissionsHelper permissionsHelper;
+
+//    protected abstract PermissionType[] setPermissions();
+
+    protected abstract String[] setPermissions();
+
+    @Override
+    protected void init() {
+//        permissionsHelper = new PermissionsHelper(mActivity, permissions(), true);
+//        if (permissionsHelper.checkAllPermissions(permissions())) {
+        permissionsHelper = new PermissionsHelper(mActivity, setPermissions(), true);
+        if (permissionsHelper.checkAllPermissions(setPermissions())) {
+            permissionsHelper.onDestroy();
+            setDate();
+        } else {
+            //申请权限
+            permissionsHelper.startRequestNeedPermissions();
+            permissionsHelper.setParams(setDialogInfo(new DialogInfo()));
+        }
+        permissionsHelper.setonAllNeedPermissionsGrantedListener(new PermissionsHelper.onAllNeedPermissionsGrantedListener() {
+            //全部许可了,已经获得了所有权限
+            @Override
+            public void onAllNeedPermissionsGranted() {
+                //做原先的业务代码
+                setDate();
+            }
+
+            //被拒绝了,只要有一个权限被拒绝那么就会调用
+            @Override
+            public void onPermissionsDenied() {
+                //拒绝了,如何处理?(视情况而定)
+                JLog.d();
+                permissionsHelper.setParams(null);
+            }
+
+            //用户已经永久的拒绝了
+            @Override
+            public void hasLockForever() {
+                JLog.i("hasLockForever");
+                permissionsHelper.setParams(null);
+            }
+
+            //被拒绝后,在最后一次申请权限之前
+            @Override
+            public void onBeforeRequestFinalPermissions(PermissionsHelper helper) {
+                JLog.i();
+                helper.continueRequestPermissions();
+            }
+        });
+    }
+
+    protected abstract void setDate();
+
+    private DialogInfo setDialogInfo(DialogInfo dialogInfo) {
+        dialogInfo.setTitle("权限不足");
+        dialogInfo.setContent("需要必须的权限才能正常使用本应用");
+        dialogInfo.setPositiveButtonText("去设置");
+        dialogInfo.setNegativeButtonText("取消");
+        dialogInfo.showDialog(true);
+        return dialogInfo;
+    }
+
+    @Override
+    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
+                                           @NonNull int[] grantResults) {
+        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
+        permissionsHelper.onRequestPermissionsResult(requestCode, permissions, grantResults);
+    }
+
+    @Override
+    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+        super.onActivityResult(requestCode, resultCode, data);
+        permissionsHelper.onActivityResult(requestCode, resultCode, data);
+    }
+}

+ 81 - 0
baselib/src/main/java/com/mylove/baselib/activity/permission/PermissionBean.java

@@ -0,0 +1,81 @@
+package com.mylove.baselib.activity.permission;
+
+import android.Manifest;
+
+/**
+ * @author myLove
+ * @time 2017/11/24 16:51
+ * @e-mail mylove.520.y@gmail.com
+ * @overview 危险权限
+ */
+
+final class PermissionBean {
+    /*
+   *   permission group : PHONE
+   * 	READ_PHONE_STATE
+   *   CALL_PHONE
+   *   READ_CALL_LOG
+   *   WRITE_CALL_LOG
+   *   ADD_VOICEMAIL
+   *   USE_SIP
+   *   PROCESS_OUTGOING_CALLS
+   */
+    static final String PHONE = Manifest.permission.READ_PHONE_STATE;
+
+    /**
+     * permission group : CALENDAR
+     * READ_CALENDAR
+     * WRITE_CALENDAR
+     */
+    static final String CALENDAR = Manifest.permission.READ_CALENDAR;
+
+    /**
+     * permission group : CAMERA
+     * CAMERA
+     */
+    static final String CAMERA = Manifest.permission.CAMERA;
+
+    /**
+     * permission group : CONTACTS
+     * READ_CONTACTS
+     * WRITE_CONTACTS
+     * GET_ACCOUNTS
+     */
+    static final String CONTACTS = Manifest.permission.READ_CONTACTS;
+
+    /**
+     * permission group : LOCATION
+     * ACCESS_FINE_LOCATION
+     * ACCESS_COARSE_LOCATION
+     */
+    static final String LOCATION = Manifest.permission.ACCESS_FINE_LOCATION;
+
+    /**
+     * permission group : MICROPHONE
+     * RECORD_AUDIO
+     */
+    static final String MICROPHONE = Manifest.permission.RECORD_AUDIO;
+
+    /**
+     * permission group : SENSORS
+     * BODY_SENSORS
+     */
+    static final String SENSORS = Manifest.permission.BODY_SENSORS;
+
+    /**
+     * permission group : SMS
+     * SEND_SMS
+     * RECEIVE_SMS
+     * READ_SMS
+     * RECEIVE_WAP_PUSH
+     * RECEIVE_MMS
+     */
+    static final String SMS = Manifest.permission.SEND_SMS;
+
+    /**
+     * permission group : STORAGE
+     * READ_EXTERNAL_STORAGE
+     * WRITE_EXTERNAL_STORAGE
+     */
+    static final String STORAGE = Manifest.permission.WRITE_EXTERNAL_STORAGE;
+}

+ 91 - 0
baselib/src/main/java/com/mylove/baselib/activity/permission/PermissionType.java

@@ -0,0 +1,91 @@
+package com.mylove.baselib.activity.permission;
+
+import android.Manifest;
+
+/**
+ * @author myLove
+ * @time 2017/11/24 16:51
+ * @e-mail mylove.520.y@gmail.com
+ * @overview
+ */
+public final class PermissionType {
+    /*
+ *   permission group : PHONE
+ * 	READ_PHONE_STATE
+ *   CALL_PHONE
+ *   READ_CALL_LOG
+ *   WRITE_CALL_LOG
+ *   ADD_VOICEMAIL
+ *   USE_SIP
+ *   PROCESS_OUTGOING_CALLS
+ */
+    public static final String PHONE = Manifest.permission.READ_PHONE_STATE;
+
+    /**
+     * permission group : CALENDAR
+     * READ_CALENDAR
+     * WRITE_CALENDAR
+     */
+    public static final String CALENDAR = Manifest.permission.READ_CALENDAR;
+
+    /**
+     * permission group : CAMERA
+     * CAMERA
+     */
+    public static final String CAMERA = Manifest.permission.CAMERA;
+
+    /**
+     * permission group : CONTACTS
+     * READ_CONTACTS
+     * WRITE_CONTACTS
+     * GET_ACCOUNTS
+     */
+    public static final String CONTACTS = Manifest.permission.READ_CONTACTS;
+
+    /**
+     * permission group : LOCATION
+     * ACCESS_FINE_LOCATION
+     * ACCESS_COARSE_LOCATION
+     */
+    public static final String LOCATION = Manifest.permission.ACCESS_FINE_LOCATION;
+
+    /**
+     * permission group : MICROPHONE
+     * RECORD_AUDIO
+     */
+    public static final String MICROPHONE = Manifest.permission.RECORD_AUDIO;
+
+    /**
+     * permission group : SENSORS
+     * BODY_SENSORS
+     */
+    public static final String SENSORS = Manifest.permission.BODY_SENSORS;
+
+    /**
+     * permission group : SMS
+     * SEND_SMS
+     * RECEIVE_SMS
+     * READ_SMS
+     * RECEIVE_WAP_PUSH
+     * RECEIVE_MMS
+     */
+    public static final String SMS = Manifest.permission.SEND_SMS;
+
+    /**
+     * permission group : STORAGE
+     * READ_EXTERNAL_STORAGE
+     * WRITE_EXTERNAL_STORAGE
+     */
+    public static final String STORAGE = Manifest.permission.WRITE_EXTERNAL_STORAGE;
+}
+//public enum PermissionType {
+//    PHONE,
+//    CALENDAR,
+//    CAMERA,
+//    CONTACTS,
+//    LOCATION,
+//    MICROPHONE,
+//    SENSORS,
+//    SMS,
+//    STORAGE
+//}

+ 288 - 0
baselib/src/main/java/com/mylove/baselib/adapter/CommonRecyclerAdapter.java

@@ -0,0 +1,288 @@
+package com.mylove.baselib.adapter;
+
+import android.content.Context;
+import android.support.v7.widget.GridLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.mylove.baselib.viewholder.RecyclerHolder;
+
+import java.util.List;
+
+/**
+ * @author LYjw
+ * @time 2017/3/20 14:23
+ * @e-mail love@yanyi.red
+ * @overview
+ */
+
+public abstract class CommonRecyclerAdapter<T> extends RecyclerView.Adapter<RecyclerHolder> {
+    /**
+     * 上下文
+     */
+    private Context context;
+    /**
+     * 数据源
+     */
+    private List<T> list;
+    /**
+     * 布局器
+     */
+    private LayoutInflater inflater;
+    /**
+     * 布局id
+     */
+    private int itemLayoutId;
+    /**
+     * 是否在滚动
+     */
+    private boolean isScrolling;
+    /**
+     * 点击事件监听器
+     */
+    private OnItemClickListener listener;
+    /**
+     * 长按监听器
+     */
+    private OnItemLongClickListener longClickListener;
+    private RecyclerView recyclerView;
+    /**
+     * 说明是带有Header的
+     */
+    private int TYPE_HEADER = 0;
+    /**
+     * 说明是带有Footer的
+     */
+    private int TYPE_FOOTER = 1;
+    /**
+     * 说明是不带有header和footer的
+     */
+    private int TYPE_NORMAL = 2;
+    private View mHeaderView;
+    private View mFooterView;
+
+    public CommonRecyclerAdapter(Context context, List<T> list, int itemLayoutId) {
+        this.context = context;
+        this.list = list;
+        this.itemLayoutId = itemLayoutId;
+        this.inflater = LayoutInflater.from(context);
+    }
+
+    public View getHeaderView() {
+        return mHeaderView;
+    }
+
+    public void addHeaderView(View headerView) {
+        if (haveHeaderView()) {
+            throw new IllegalStateException("headerView has already exists!");
+        } else {
+            ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
+            headerView.setLayoutParams(params);
+            this.mHeaderView = headerView;
+            ifGridLayoutManager();
+            notifyItemInserted(0);
+        }
+    }
+
+    public View getFooterView() {
+        return mFooterView;
+    }
+
+    public void addFooterView(View footerView) {
+        if (haveFootView()) {
+            throw new IllegalStateException("footerView has already exists!");
+        } else {
+            ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
+            footerView.setLayoutParams(params);
+            this.mFooterView = footerView;
+            ifGridLayoutManager();
+            notifyItemInserted(getItemCount() - 1);
+        }
+    }
+
+    public boolean haveHeaderView() {
+        return mHeaderView != null;
+    }
+
+    public boolean haveFootView() {
+        return mFooterView != null;
+    }
+
+    private boolean isHeaderView(int position) {
+        return haveHeaderView() && position == 0;
+    }
+
+    private boolean isFooterView(int position) {
+        return haveFootView() && position == getItemCount() - 1;
+    }
+
+    /**
+     * 重写这个方法,是加入Header和Footer的关键,我们通过判断item的类型,从而绑定不同的view
+     */
+    @Override
+    public int getItemViewType(int position) {
+        if (mHeaderView == null && mFooterView == null) {
+            return TYPE_NORMAL;
+        } else if (isHeaderView(position)) {
+            return TYPE_HEADER;
+        } else if (isFooterView(position)) {
+            return TYPE_FOOTER;
+        } else {
+            return TYPE_NORMAL;
+        }
+    }
+
+    /**
+     * 在RecyclerView提供数据的时候调用
+     */
+    @Override
+    public void onAttachedToRecyclerView(RecyclerView recyclerView) {
+        try {
+            if (this.recyclerView == null && this.recyclerView != recyclerView) {
+                this.recyclerView = recyclerView;
+            }
+            ifGridLayoutManager();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        this.recyclerView = recyclerView;
+    }
+
+    @Override
+    public void onDetachedFromRecyclerView(RecyclerView recyclerView) {
+        super.onDetachedFromRecyclerView(recyclerView);
+        this.recyclerView = null;
+    }
+
+    private void ifGridLayoutManager() {
+        if (recyclerView == null) {
+            return;
+        }
+        final RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
+        if (layoutManager instanceof GridLayoutManager) {
+            GridLayoutManager.SpanSizeLookup spanSizeLookup = ((GridLayoutManager) layoutManager).getSpanSizeLookup();
+            ((GridLayoutManager) layoutManager).setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
+                @Override
+                public int getSpanSize(int position) {
+                    return (isHeaderView(position) || isFooterView(position)) ? ((GridLayoutManager) layoutManager).getSpanCount() : 1;
+                }
+            });
+        }
+    }
+
+    /**
+     * 定义一个点击事件接口回调
+     */
+    public interface OnItemClickListener {
+        void onItemClick(RecyclerView parent, View view, int position);
+    }
+
+    interface OnItemLongClickListener {
+        boolean onItemLongClick(RecyclerView parent, View view, int position);
+    }
+
+    /**
+     * 插入一项
+     *
+     * @param item
+     * @param position
+     */
+    public void insert(T item, int position) {
+        list.add(position, item);
+        notifyItemInserted(position);
+    }
+
+    /**
+     * 删除一项
+     *
+     * @param position 删除位置
+     */
+    public void remove(int position) {
+        list.remove(position);
+        notifyItemRemoved(position);
+    }
+
+    public void notifyDataSetChanged(List<T> list) {
+        this.list = list;
+        notifyDataSetChanged();
+    }
+
+    /**
+     * 创建view
+     */
+    @Override
+    public RecyclerHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+        if (mHeaderView != null && viewType == TYPE_HEADER) {
+            return RecyclerHolder.getRecyclerHolder(context, mHeaderView);
+        } else if (mFooterView != null && viewType == TYPE_FOOTER) {
+            return RecyclerHolder.getRecyclerHolder(context, mFooterView);
+        } else {
+            View view = inflater.inflate(itemLayoutId, parent, false);
+            return RecyclerHolder.getRecyclerHolder(context, view);
+        }
+    }
+
+    @Override
+    public void onBindViewHolder(RecyclerHolder holder, int position) {
+        holder.itemView.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                if (listener != null && v != null && recyclerView != null) {
+                    int i = recyclerView.getChildAdapterPosition(v);
+                    listener.onItemClick(recyclerView, v, i);
+                }
+            }
+        });
+        holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
+            @Override
+            public boolean onLongClick(View v) {
+                if (longClickListener != null && v != null && recyclerView != null) {
+                    int i = recyclerView.getChildAdapterPosition(v);
+                    longClickListener.onItemLongClick(recyclerView, v, i);
+                    return true;
+                }
+                return false;
+            }
+        });
+        if (!isHeaderView(position) && !isFooterView(position)) {
+            if (haveHeaderView()) {
+                position--;
+            }
+            if (position < list.size()) {
+                convert(holder, list.get(position), position, isScrolling);
+            }
+        }
+    }
+
+    @Override
+    public int getItemCount() {
+        int count = list == null ? 0 : list.size();
+        if (mHeaderView != null) {
+            count++;
+        }
+        if (mFooterView != null) {
+            count++;
+        }
+        return count;
+    }
+
+    public void setOnItemClickListener(OnItemClickListener listener) {
+        this.listener = listener;
+    }
+
+    public void setOnItemLongClickListener(OnItemLongClickListener longClickListener) {
+        this.longClickListener = longClickListener;
+    }
+
+    /**
+     * 填充RecyclerView适配器的方法,子类需要重写
+     *
+     * @param mHolder     ViewHolder
+     * @param item        子项
+     * @param position    位置
+     * @param isScrolling 是否在滑动
+     */
+    public abstract void convert(RecyclerHolder mHolder, T item, int position, boolean isScrolling);
+}

+ 40 - 0
baselib/src/main/java/com/mylove/baselib/adapter/TabStripPagerAdapter.java

@@ -0,0 +1,40 @@
+package com.mylove.baselib.adapter;
+
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentManager;
+import android.support.v4.app.FragmentPagerAdapter;
+
+import java.util.List;
+
+/**
+ * @author myLove
+ * @time 2018-01-15 15:29
+ * @e-mail love@yanyi.red
+ * @overview
+ */
+
+public class TabStripPagerAdapter extends FragmentPagerAdapter {
+    private String[] titles;
+    private List<Fragment> oList;
+
+    public TabStripPagerAdapter(FragmentManager fm, String[] titles, List<Fragment> list) {
+        super(fm);
+        this.titles = titles;
+        this.oList = list;
+    }
+
+    @Override
+    public CharSequence getPageTitle(int position) {
+        return titles[position];
+    }
+
+    @Override
+    public Fragment getItem(int position) {
+        return oList.get(position);
+    }
+
+    @Override
+    public int getCount() {
+        return titles.length;
+    }
+}

+ 55 - 0
baselib/src/main/java/com/mylove/baselib/db/DBHelper.java

@@ -0,0 +1,55 @@
+package com.mylove.baselib.db;
+
+import android.content.Context;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+
+import com.mylove.loglib.JLog;
+
+import java.util.Map;
+
+/**
+ * @author myLove
+ * @time 2017/10/31 13:46
+ * @e-mail mylove.520.y@gmail.com
+ * @overview
+ */
+
+class DBHelper extends SQLiteOpenHelper {
+
+    private String tabName;
+    private Map<String, String> fieldMap;
+
+    @Override
+    public void onCreate(SQLiteDatabase db) {
+        StringBuilder field = new StringBuilder();
+        for (Map.Entry<String, String> entry : fieldMap.entrySet()) {
+            field.append(entry.getKey()).append(" ").append(entry.getValue()).append(",");
+        }
+        field = field.deleteCharAt(field.length() - 1);
+//        String sql = "create table " + tabName + " (id integer primary key autoincrement," + field + ")";//有主键
+        String sql = "create table " + tabName + " (" + field + ")";
+        JLog.d("sql-->>" + sql);
+        db.execSQL(sql);
+    }
+
+    @Override
+    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+        String sql = "DROP TABLE IF EXISTS " + tabName;
+        db.execSQL(sql);
+        onCreate(db);
+    }
+
+    /**
+     * @param context  上下文
+     * @param tabName  tab名
+     * @param fieldMap 表字段
+     * @param name     db名
+     * @param version  版本号
+     */
+    DBHelper(Context context, String tabName, Map<String, String> fieldMap, String name, int version) {
+        super(context, name, null, version);
+        this.tabName = tabName;
+        this.fieldMap = fieldMap;
+    }
+}

+ 202 - 0
baselib/src/main/java/com/mylove/baselib/db/DBUtil.java

@@ -0,0 +1,202 @@
+package com.mylove.baselib.db;
+
+import android.content.ContentValues;
+import android.content.Context;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+import android.util.Log;
+
+import com.google.gson.Gson;
+import com.mylove.baselib.utils.StringUtil;
+
+import org.json.JSONArray;
+import org.json.JSONObject;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author myLove
+ * @time 2017/10/31 14:00
+ * @e-mail mylove.520.y@gmail.com
+ * @overview sqlite工具类
+ */
+
+public class DBUtil {
+    private static DBUtil instance;
+    private String tName;
+    private SQLiteDatabase db;
+
+    private DBUtil(String tabName, DBHelper dbHelper) {
+        this.tName = tabName;
+        //创建数据库
+        this.db = dbHelper.getWritableDatabase();
+    }
+
+    /**
+     * 单例模式
+     *
+     * @param mContext 上下文
+     * @param tabName  tab名
+     * @param dbName   db名
+     * @param fieldMap 表字段
+     * @param version  版本号
+     * @return this
+     */
+    public static DBUtil getInstance(Context mContext, String tabName, String dbName, Map<String, String> fieldMap, int version) {
+//        if (instance == null) {
+//            synchronized (DBUtil.class) {
+        DBHelper dbHelper = new DBHelper(mContext, tabName, fieldMap, dbName, version);
+        instance = new DBUtil(tabName, dbHelper);
+//            }
+//        }
+        return instance;
+    }
+
+    /**
+     * 插入数据
+     *
+     * @param oMap 要插入数据的key和value
+     */
+    public long insert(Map<String, String> oMap) {
+        return db.insert(tName, null, values(oMap));
+    }
+
+    /**
+     * 查询全部语句
+     *
+     * @return 返回结果
+     */
+    public Cursor query() {
+        return db.query(tName, null, null, null, null, null, null);
+    }
+
+    /**
+     * 查询全部语句
+     *
+     * @return 返回结果
+     */
+    public <T> List<T> query(Class<T> tClass) {
+        List<T> oList = new ArrayList<>();
+        JSONArray array = getCursor(db.query(tName, null, null, null, null, null, null));
+        Gson gson = new Gson();
+        if (StringUtil.isJSONArrayNotEmpty(array)) {
+            try {
+                for (int i = 0; i < array.length(); i++) {
+                    String s = array.getJSONObject(i).toString();
+                    oList.add(gson.fromJson(s, tClass));
+                }
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+        return oList;
+    }
+
+    /**
+     * 根据条件查询数据
+     *
+     * @param oMap 查询条件的key和value
+     * @return 返回结果
+     */
+    public Cursor query(Map<String, String> oMap) {
+        return db.query(tName, null, selection(oMap), arr(oMap), null, null, null);
+    }
+
+    /**
+     * 根据条件查询数据
+     *
+     * @param oMap 查询条件的key和value
+     * @return 返回结果
+     */
+    public <T> List<T> query(Map<String, String> oMap, Class<T> tClass) {
+        List<T> oList = new ArrayList<>();
+        JSONArray array = getCursor(db.query(tName, null, selection(oMap), arr(oMap), null, null, null));
+        Gson gson = new Gson();
+        if (StringUtil.isJSONArrayNotEmpty(array)) {
+            try {
+                for (int i = 0; i < array.length(); i++) {
+                    String s = array.getJSONObject(i).toString();
+                    oList.add(gson.fromJson(s, tClass));
+                }
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+        return oList;
+    }
+
+    /**
+     * 修改数据
+     *
+     * @param oMap 修改条件key和value
+     * @param sMap 修改后的内容key和value
+     * @return 修改条数
+     */
+    public int update(Map<String, String> oMap, Map<String, String> sMap) {
+        return db.update(tName, values(oMap), selection(sMap), arr(sMap));
+    }
+
+    /**
+     * 删除数据
+     *
+     * @param oMap 删除的条件key和value
+     * @return 删除的数量
+     */
+    public int delete(Map<String, String> oMap) {
+        return db.delete(tName, selection(oMap), arr(oMap));
+    }
+
+    private ContentValues values(Map<String, String> map) {
+        ContentValues values = new ContentValues();
+        for (Map.Entry<String, String> entry : map.entrySet()) {
+            values.put(entry.getKey(), entry.getValue());
+        }
+        return values;
+    }
+
+    private String selection(Map<String, String> map) {
+        StringBuilder selection = new StringBuilder();
+        for (Map.Entry<String, String> entry : map.entrySet()) {
+            selection.append(entry.getKey()).append("=? and ");
+        }
+        selection = selection.delete(selection.length() - 4, selection.length());
+        return selection.toString();
+    }
+
+    private String[] arr(Map<String, String> map) {
+        int i = 0;
+        String[] arr = new String[map.size()];
+        for (Map.Entry<String, String> entry : map.entrySet()) {
+            arr[i] = entry.getValue();
+            i++;
+        }
+        return arr;
+    }
+
+    private JSONArray getCursor(Cursor cursor) {
+        JSONArray resultSet = new JSONArray();
+        cursor.moveToFirst();
+        while (!cursor.isAfterLast()) {
+            int totalColumn = cursor.getColumnCount();
+            JSONObject rowObject = new JSONObject();
+            for (int i = 0; i < totalColumn; i++) {
+                if (cursor.getColumnName(i) != null) {
+                    try {
+                        if (cursor.getString(i) != null) {
+                            rowObject.put(cursor.getColumnName(i), cursor.getString(i));
+                        } else {
+                            rowObject.put(cursor.getColumnName(i), "");
+                        }
+                    } catch (Exception e) {
+                        Log.d("TAG_NAME", e.getMessage());
+                    }
+                }
+            }
+            resultSet.put(rowObject);
+            cursor.moveToNext();
+        }
+        return resultSet;
+    }
+}

+ 163 - 0
baselib/src/main/java/com/mylove/baselib/fragment/BaseFragment.java

@@ -0,0 +1,163 @@
+package com.mylove.baselib.fragment;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.v4.app.Fragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.inputmethod.InputMethodManager;
+
+import com.mylove.baselib.utils.toast.ShowToast;
+
+import butterknife.ButterKnife;
+import butterknife.Unbinder;
+
+/**
+ * @author myLove
+ * @time 2017/11/1 14:16
+ * @e-mail mylove.520.y@gmail.com
+ * @overview
+ */
+
+public abstract class BaseFragment extends Fragment {
+    public View mView;
+    public Context mContext;
+    public Activity mActivity;
+    Unbinder unbinder;
+
+    @Nullable
+    @Override
+    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
+        if (mView == null) {
+            mView = inflater.inflate(setLayoutID(), null);
+        }
+        mContext = getActivity();
+        mActivity = getActivity();
+        unbinder = ButterKnife.bind(this, mView);
+        if (!isVisibleHidden()) {
+            visibleInit();
+        }
+        return mView;
+    }
+
+    protected abstract int setLayoutID();
+
+    protected abstract void init();
+
+    /**
+     * 显示当前界面时页面操作
+     */
+    public void visibleInit() {
+    }
+
+    public boolean isVisibleHidden() {
+        return false;
+    }
+
+    /**
+     * 页面跳转
+     *
+     * @param cls 需要跳转的页面
+     */
+    public void startAct(Class cls) {
+        Intent intent = new Intent(mContext, cls);
+        startActivity(intent);
+    }
+
+    /**
+     * 页面跳转
+     *
+     * @param cls    需要跳转的页面
+     * @param bundle 传递的参数
+     */
+    public void startAct(Class cls, Bundle bundle) {
+        Intent intent = new Intent(mContext, cls);
+        if (bundle != null) {
+            intent.putExtras(bundle);
+        }
+        startActivity(intent);
+    }
+
+    /**
+     * 带返回的跳转页面
+     *
+     * @param cls         需要跳转的页面
+     * @param requestCode 请求的下标
+     */
+    public void startAct(Class cls, int requestCode) {
+        Intent intent = new Intent(mContext, cls);
+        startActivityForResult(intent, requestCode);
+    }
+
+    /**
+     * 带返回的跳转页面
+     *
+     * @param cls         需要跳转的页面
+     * @param bundle      传递的参数
+     * @param requestCode 请求的下标
+     */
+    public void startAct(Class cls, Bundle bundle, int requestCode) {
+        Intent intent = new Intent(mContext, cls);
+        if (bundle != null) {
+            intent.putExtras(bundle);
+        }
+        startActivityForResult(intent, requestCode);
+    }
+
+    /**
+     * 关闭软键盘
+     */
+    public void hintKbTwo() {
+        InputMethodManager imm = (InputMethodManager) mActivity.getSystemService(Context.INPUT_METHOD_SERVICE);
+        if (imm.isActive() && mActivity.getCurrentFocus() != null) {
+            if (mActivity.getCurrentFocus().getWindowToken() != null) {
+                imm.hideSoftInputFromWindow(mActivity.getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
+            }
+        }
+    }
+
+    public void toast(Object obj) {
+        ShowToast.getInstance(mContext).show(obj);
+    }
+
+    public void toastTest() {
+        ShowToast.getInstance(mContext).show("功能有待开发");
+    }
+
+    @Override
+    public void setUserVisibleHint(boolean isVisibleToUser) {
+        super.setUserVisibleHint(isVisibleToUser);
+        if (isVisibleHidden()) {
+            if (isVisibleToUser && isResumed()) {
+                onResume();
+            } else {
+                onPause();
+            }
+        }
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        if (getUserVisibleHint() && isVisibleHidden()) {
+            visibleInit();
+        }
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+    }
+
+    @Override
+    public void onDestroyView() {
+        super.onDestroyView();
+        unbinder.unbind();
+    }
+
+}

+ 367 - 0
baselib/src/main/java/com/mylove/baselib/fragment/BaseFragmentLoad.java

@@ -0,0 +1,367 @@
+package com.mylove.baselib.fragment;
+
+import android.os.Handler;
+import android.support.v4.widget.SwipeRefreshLayout;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.mylove.baselib.R;
+import com.mylove.baselib.adapter.CommonRecyclerAdapter;
+import com.mylove.baselib.utils.StringUtil;
+import com.mylove.baselib.viewholder.RecyclerHolder;
+import com.mylove.baselib.widget.RecyclerViewAnimation;
+import com.mylove.loglib.JLog;
+import com.mylove.okhttp.ResultMsg;
+import com.mylove.okhttp.onOkHttpListener;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author myLove
+ * @time 2018-01-16 09:26
+ * @e-mail love@yanyi.red
+ * @overview
+ */
+
+public abstract class BaseFragmentLoad<T> extends BaseFragment implements onOkHttpListener {
+    public RecyclerView commRecycler;
+    public SwipeRefreshLayout commSwipe;
+    public LinearLayout footLinear;
+    public LinearLayout footLoading;
+    public TextView footPrompt;
+    public CommonRecyclerAdapter<T> mAdapter;
+    public List<T> oList = new ArrayList<>();
+    public Handler handler = new Handler();
+    /**
+     * 下拉刷新的标识
+     */
+    public int REFRESH = 0;
+    /**
+     * 上拉加载更多的标识
+     */
+    public int LOAD = 1;
+    /**
+     * 判断是否没有数据可加载
+     */
+    private boolean boo = true;
+    /**
+     * 每页加载的条数
+     */
+    public int pageSize = 10;
+    public int page = 1;
+    public int sumSize = 0;
+    public int what = REFRESH;
+
+    public boolean NoData = false;
+
+    private int animationID = 0;
+
+    @Override
+    protected void init() {
+        commRecycler = mView.findViewById(R.id.recycler);
+        commSwipe = mView.findViewById(R.id.swipe_refresh);
+        commSwipe.setColorSchemeColors(getResources().getColor(R.color.comm_blue),
+                getResources().getColor(R.color.comm_green), getResources().getColor(R.color.comm_red));
+        setAdapter();
+        setHeader();
+        setFooter();
+        refreshData();
+    }
+
+    public void setAdapter() {
+        if (setLayoutManager() == null) {
+            throw new NullPointerException("RecyclerView样式不能为空");
+        }
+        if (setItemLayout() == 0) {
+            throw new NullPointerException("adapter需要设置item布局");
+        }
+        oList.clear();
+        commRecycler.setLayoutManager(setLayoutManager());
+        mAdapter = new CommonRecyclerAdapter<T>(mContext, oList, setItemLayout()) {
+            @Override
+            public void convert(RecyclerHolder mHolder, T item, int position, boolean isScrolling) {
+                adapterConvert(mHolder, item, position, isScrolling);
+            }
+        };
+        commRecycler.setAdapter(mAdapter);
+        notifyData(oList);
+    }
+
+    protected abstract RecyclerView.LayoutManager setLayoutManager();
+
+    /**
+     * 设置适配器
+     */
+    protected abstract int setItemLayout();
+
+    /**
+     * item设置参数
+     *
+     * @param mHolder
+     * @param item
+     * @param position
+     * @param isScrolling
+     */
+    protected abstract void adapterConvert(RecyclerHolder mHolder, T item, int position, boolean isScrolling);
+
+    /**
+     * 设置头部
+     */
+    public void setHeader() {
+    }
+
+    protected void setFooter() {
+        View footer = LayoutInflater.from(mContext).inflate(R.layout.item_foot, commRecycler, false);
+        footLinear = footer.findViewById(R.id.foot_linear);
+        footLoading = footer.findViewById(R.id.foot_loading);
+        footPrompt = footer.findViewById(R.id.foot_prompt);
+        mAdapter.addFooterView(footer);
+    }
+
+    /**
+     * 刷新以及加载更多
+     */
+    private void refreshData() {
+        if (!ifHidden()) {
+            dataInit();
+        }
+        //下拉刷新
+        commSwipe.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
+            @Override
+            public void onRefresh() {
+                handler.post(new Runnable() {
+                    @Override
+                    public void run() {
+                        dataInit();
+                    }
+                });
+            }
+        });
+        commRecycler.addOnScrollListener(new RecyclerView.OnScrollListener() {
+            int lastVisibleItem = 0;
+            //在屏幕上可见的item数量
+            private int visibleItemCount = 0;
+            //已经加载出来的Item的数量
+            private int totalItemCount = 0;
+            //在屏幕可见的Item中的第一个
+            private int firstVisibleItem = 0;
+//            //是否正在上拉数据
+//            private boolean loading = true;
+//            //主要用来存储上一个totalItemCount
+//            private int previousTotal = 0;
+
+            private int viewSize = 0;
+
+            /**
+             * 滚动中调用
+             */
+            @Override
+            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
+                super.onScrollStateChanged(recyclerView, newState);
+                LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
+                viewSize = 0;
+                boolean footerView = mAdapter.haveFootView();
+                boolean headerView = mAdapter.haveHeaderView();
+                if (footerView) {
+                    viewSize++;
+                }
+                if (headerView) {
+                    viewSize++;
+                }
+                visibleItemCount = recyclerView.getChildCount();
+                totalItemCount = layoutManager.getItemCount();
+                firstVisibleItem = layoutManager.findFirstVisibleItemPosition();
+                if (boo && totalItemCount >= (pageSize * page)
+                        && totalItemCount == (oList.size() + viewSize)
+                        && (lastVisibleItem + viewSize) == totalItemCount
+                        && (footLoading.getVisibility()) == View.VISIBLE) {
+                    page++;
+                    what = LOAD;
+                    loadResultData();
+                }
+            }
+
+            /**
+             * 滚动停止后调用
+             */
+            @Override
+            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
+                super.onScrolled(recyclerView, dx, dy);
+                LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
+//                //最后一个可见的item
+                lastVisibleItem = layoutManager.findLastVisibleItemPosition();
+                if (boo && lastVisibleItem + viewSize == oList.size()) {
+                    //显示加载中进度条
+                    handler.post(new Runnable() {
+                        @Override
+                        public void run() {
+                            footLinear.setVisibility(View.VISIBLE);
+                            footLoading.setVisibility(View.VISIBLE);
+                        }
+                    });
+                }
+            }
+        });
+    }
+
+    /**
+     * 请求数据的方法
+     */
+    protected abstract void loadResultData();
+
+    public void notifyData(List<T> list) {
+        oList = list;
+        if (isListAnimation()) {
+            RecyclerViewAnimation.getInstance(animationID).runLayoutAnimation(commRecycler, oList);
+        } else {
+            mAdapter.notifyDataSetChanged(oList);
+        }
+    }
+
+    /**
+     * 刷新页面
+     */
+    public void notifyUi() {
+        dataInit();
+    }
+
+    public void cleanAdapter() {
+        oList.clear();
+        notifyData(oList);
+    }
+
+    private void dataInit() {
+        cleanAdapter();
+        NoData = false;
+        footLinear.setVisibility(View.VISIBLE);
+        footLoading.setVisibility(View.VISIBLE);
+        footPrompt.setText(getResources().getString(R.string.loading));
+        page = 1;
+        pageSize = 10;
+        what = REFRESH;
+        loadResultData();
+    }
+
+    /**
+     * 状态改变
+     */
+    private void status() {
+        if (StringUtil.isListNotEmpty(oList)) {
+            JLog.v(oList);
+        }
+        handler.postDelayed(new Runnable() {
+            @Override
+            public void run() {
+                boo = true;
+                footLoading.setVisibility(View.GONE);
+                commSwipe.setRefreshing(false);
+                if (StringUtil.isListEmpty(oList)) {
+                    JLog.v();
+                    boo = false;
+                    footLinear.setVisibility(View.VISIBLE);
+                    footPrompt.setText("暂无数据");
+                    footPrompt.setVisibility(View.VISIBLE);
+                } else if ((oList.size() == sumSize && NoData) || oList.size() % pageSize != 0) {
+                    JLog.v();
+                    boo = false;
+                    footLinear.setVisibility(View.VISIBLE);
+                    footPrompt.setVisibility(View.VISIBLE);
+                    footPrompt.setText("已加载全部数据");
+                } else {
+                    JLog.v();
+                    footLinear.setVisibility(View.GONE);
+                    footPrompt.setVisibility(View.GONE);
+                }
+                sumSize = oList.size();
+                notifyData(oList);
+            }
+        }, 500);
+    }
+
+    @Override
+    public void onSuccess(ResultMsg resultMsg) {
+        disposeResultData(resultMsg.getResult());
+        status();
+    }
+
+    @Override
+    public void onCompleted() {
+
+    }
+
+    @Override
+    public void onFailure(Throwable t) {
+        JLog.e(t.getMessage());
+        oList.clear();
+        status();
+    }
+
+    /**
+     * 数据处理
+     *
+     * @param json 网络数据
+     */
+    protected abstract void disposeResultData(String json);
+
+    @Override
+    public void setUserVisibleHint(boolean isVisibleToUser) {
+        super.setUserVisibleHint(isVisibleToUser);
+        if (ifHidden()) {
+            if (isVisibleToUser && isResumed()) {
+                onResume();
+            } else {
+                onPause();
+            }
+        }
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        if (getUserVisibleHint() && ifHidden()) {
+            visibleInit();
+            dataInit();
+        }
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+    }
+
+    /**
+     * 判断是否需要判断可视
+     *
+     * @return
+     */
+    public boolean ifHidden() {
+        return false;
+    }
+
+    @Override
+    public boolean isVisibleHidden() {
+        return ifHidden();
+    }
+
+    /**
+     * 是否显示RecyclerView动画
+     *
+     * @return
+     */
+    public boolean isListAnimation() {
+        return true;
+    }
+
+    public void setAnimationID(int animationID) {
+        this.animationID = animationID;
+    }
+
+    public int getAnimationID() {
+        return animationID;
+    }
+}

+ 118 - 0
baselib/src/main/java/com/mylove/baselib/grobal/AppManager.java

@@ -0,0 +1,118 @@
+package com.mylove.baselib.grobal;
+
+import android.app.Activity;
+import android.app.ActivityManager;
+import android.content.Context;
+
+import java.util.Stack;
+
+/**
+ * @author myLove
+ * @time 2017/10/31 12:18
+ * @e-mail mylove.520.y@gmail.com
+ * @overview 应用程序Activity管理类:用于Activity管理和应用程序退出
+ */
+
+public class AppManager {
+    private static Stack<Activity> activityStack;
+
+    private static AppManager instance;
+
+    /**
+     * 单一实例
+     *
+     * @return
+     */
+    public static AppManager getInstance() {
+        if (instance == null) {
+            synchronized (AppManager.class){
+                instance = new AppManager();
+            }
+        }
+        return instance;
+    }
+    /**
+     * 添加Activity到堆栈
+     *
+     * @param activity
+     */
+    public void addActivity(Activity activity) {
+        if (activityStack == null) {
+            activityStack = new Stack<Activity>();
+        }
+        activityStack.add(activity);
+    }
+
+    /**
+     * 获取当前Activity(堆栈中最后一个压入的)
+     *
+     * @return
+     */
+    public Activity currentActivity() {
+        Activity activity = activityStack.lastElement();
+        return activity;
+    }
+
+    /**
+     * 结束当前Activity(堆栈中最后一个压入的)
+     */
+    public void finishActivity() {
+        Activity activity = activityStack.lastElement();
+        finishActivity(activity);
+    }
+
+    /**
+     * 结束指定的Activity
+     *
+     * @param activity
+     */
+    public void finishActivity(Activity activity) {
+        if (activity != null) {
+            activityStack.remove(activity);
+            activity.finish();
+            activity = null;
+        }
+    }
+
+    /**
+     * 结束指定类名的Activity
+     *
+     * @param cls
+     */
+    public void finishActivity(Class<?> cls) {
+        for (Activity activity : activityStack) {
+            if (activity.getClass().equals(cls)) {
+                finishActivity(activity);
+            }
+        }
+    }
+
+    /**
+     * 结束所有Activity
+     */
+    public void finishAllActivity() {
+        for (int i = 0, size = activityStack.size(); i < size; i++) {
+            if (null != activityStack.get(i)) {
+                activityStack.get(i).finish();
+            }
+        }
+        activityStack.clear();
+    }
+
+    /**
+     * 退出应用程序
+     *
+     * @param context
+     */
+    @SuppressWarnings("deprecation")
+    public void AppExit(Context context) {
+        try {
+            finishAllActivity();
+            ActivityManager activityMgr = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+            activityMgr.restartPackage(context.getPackageName());
+            System.exit(0);
+            // Process.killProcess(Process.myPid());
+        } catch (Exception e) {
+        }
+    }
+}

+ 10 - 0
baselib/src/main/java/com/mylove/baselib/listener/CommonListener.java

@@ -0,0 +1,10 @@
+package com.mylove.baselib.listener;
+
+import android.view.View;
+
+/**
+ * @author LYjw
+ */
+public interface CommonListener {
+    void commonListener(View view, int position);
+}

+ 25 - 0
baselib/src/main/java/com/mylove/baselib/utils/AndroidUtil.java

@@ -0,0 +1,25 @@
+package com.mylove.baselib.utils;
+
+import android.content.Context;
+
+/**
+ * @author myLove
+ * @time 2017/11/15 9:51
+ * @e-mail mylove.520.y@gmail.com
+ * @overview
+ */
+
+public class AndroidUtil {
+    /**
+     * 获取当前版本名称
+     */
+    private static String getVersionName(Context context) {
+        String str = "";
+        try {
+            str = context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionName;
+        } catch (Exception e) {
+            e.fillInStackTrace();
+        }
+        return str;
+    }
+}

+ 35 - 0
baselib/src/main/java/com/mylove/baselib/utils/ArrayUtil.java

@@ -0,0 +1,35 @@
+package com.mylove.baselib.utils;
+
+import java.util.Arrays;
+
+/**
+ * @author myLove
+ * @time 2017/11/15 9:37
+ * @e-mail mylove.520.y@gmail.com
+ * @overview
+ */
+
+public class ArrayUtil {
+
+    /**
+     * 将多个数组合并成一个数组
+     *
+     * @param first
+     * @param rest
+     * @param <T>
+     * @return
+     */
+    public static <T> T[] concatAll(T[] first, T[]... rest) {
+        int totalLength = first.length;
+        for (T[] t : rest) {
+            totalLength += t.length;
+        }
+        T[] result = Arrays.copyOf(first, totalLength);
+        int offset = first.length;
+        for (T[] array : rest) {
+            System.arraycopy(array, 0, result, offset, array.length);
+            offset += array.length;
+        }
+        return result;
+    }
+}

+ 526 - 0
baselib/src/main/java/com/mylove/baselib/utils/DateUtil.java

@@ -0,0 +1,526 @@
+package com.mylove.baselib.utils;
+
+import android.annotation.SuppressLint;
+
+import java.text.DateFormat;
+import java.text.ParsePosition;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+
+/**
+ * @author myLove
+ * @time 2017/11/15 10:15
+ * @e-mail mylove.520.y@gmail.com
+ * @overview
+ */
+
+public class DateUtil {
+    /**
+     * 时间戳转换成日期格式字符串
+     *
+     * @param seconds 精确到秒的字符串
+     * @param
+     * @return
+     */
+    public static String timeStamp2Date(String seconds, String format) {
+        if (seconds == null || seconds.isEmpty() || seconds.equals("null")) {
+            return "";
+        }
+        if (StringUtil.isEmpty(format))
+            format = "yyyy-MM-dd HH:mm:ss";
+        SimpleDateFormat sdf = new SimpleDateFormat(format);
+        return sdf.format(new Date(Long.valueOf(seconds + "000")));
+    }
+
+    /**
+     * 计算两个日期型的时间相差多少时间
+     *
+     * @param
+     * @return
+     */
+    @SuppressLint("SimpleDateFormat")
+    public static String twoDateDistance(String endDates) {
+        endDates = timeStamp2Date(endDates, "yyyy-MM-dd HH:mm:ss");
+        SimpleDateFormat dfs = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        String date = dfs.format(new Date());
+        Date startDate = null;
+        try {
+            startDate = dfs.parse(date);
+            Date endDate = dfs.parse(endDates);
+            if (startDate == null || endDate == null) {
+                return null;
+            }
+            long timeLong = (endDate.getTime() - startDate.getTime()) / -1000;// 单位毫秒,除以1000转换成秒
+            // 单位秒
+            long month = 60 * 60 * 24 * 7 * 4;// 月
+            long week = 60 * 60 * 24 * 7;// 周
+            long day = 60 * 60 * 24;// 天
+            long hour = 60 * 60;// 小时
+            long minute = 60; // 分钟
+            long second = 1; // 秒
+
+            if (timeLong < minute) {
+                return timeLong / second + "秒前";
+            } else if (timeLong < hour) {
+                timeLong = timeLong / minute;
+                return timeLong + "分钟前";
+            } else if (timeLong < day) {
+                timeLong = timeLong / hour;
+                return timeLong + "小时前";
+            } else if (timeLong < week) {
+                timeLong = timeLong / day;
+                return timeLong + "天前";
+            } else if (timeLong < month) {
+                timeLong = timeLong / week;
+                return timeLong + "周前";
+            } else {
+                // 如果超过几周则显示日期
+                String str = new String(endDates);
+                String date1[] = str.split(" ");
+                return date1[0];
+            }
+        } catch (Exception e) {//
+            e.printStackTrace();
+        }
+        return dfs.format(startDate);
+
+    }
+
+    public static boolean timeCompare(String startTime, String endTime) {
+        try {
+            DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm");
+            Date startDate = df.parse(startTime);
+            Date endDate = df.parse(endTime);
+            long diff = endDate.getTime() - startDate.getTime();
+            long min = diff / (1000 * 60);
+            if (min < 1)
+                return false;
+            else
+                return true;
+        } catch (Exception e) {
+        }
+        return true;
+    }
+
+    /**
+     * 时间戳转换成日期格式字符串
+     *
+     * @param seconds 精确到秒的字符串
+     * @return
+     */
+    public static String timeStamp2Date(String seconds) {
+        if (seconds == null || seconds.isEmpty() || seconds.equals("null")) {
+            return "";
+        }
+        String format = "yyyy-MM-dd";
+        SimpleDateFormat sdf = new SimpleDateFormat(format);
+        return sdf.format(new Date(Long.valueOf(seconds + "000")));
+    }
+
+    /**
+     * 日期格式字符串转换成时间戳
+     *
+     * @param
+     * @param format 如:yyyy-MM-dd HH:mm:ss
+     * @return
+     */
+    public static String date2TimeStamp(String date_str, String format) {
+        // 2016-03-13 03:29:00
+        try {
+            SimpleDateFormat sdf = new SimpleDateFormat(format);
+            return String.valueOf(sdf.parse(date_str).getTime() / 1000);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return "";
+    }
+
+    /**
+     * 取得当前时间戳(精确到秒)
+     *
+     * @return
+     */
+    public static String timeStamp() {
+        long time = System.currentTimeMillis();
+        String t = String.valueOf(time / 1000);
+        return t;
+    }
+
+    /**
+     * 得到当前的时间
+     *
+     * @return 例如:2015-01-06 22:56
+     */
+    public static String getStringDate() {
+        Date currentTime = new Date();
+        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        String dateString = formatter.format(currentTime);
+        return dateString;
+    }
+
+    /**
+     * 得到当前的时间
+     *
+     * @param format
+     * @return
+     */
+    public static String getStringDate(String format) {
+        Date currentTime = new Date();
+        SimpleDateFormat formatter = new SimpleDateFormat(format);
+        String dateString = formatter.format(currentTime);
+        return dateString;
+    }
+
+    /**
+     * 计算时间差
+     *
+     * @param startTime
+     * @param endTime
+     * @param format
+     * @return
+     */
+    public static String TimeDifference(String startTime, String endTime, String format) {
+        String str = "";
+        try {
+            SimpleDateFormat sd = new SimpleDateFormat(format);
+            long nd = 1000 * 24 * 60 * 60;// 一天的毫秒数
+            long nh = 1000 * 60 * 60;// 一小时的毫秒数
+            long nm = 1000 * 60;// 一分钟的毫秒数
+            long ns = 1000;// 一秒钟的毫秒数long diff;try {
+            // 获得两个时间的毫秒时间差异
+            long diff = sd.parse(endTime).getTime() - sd.parse(startTime).getTime();
+            long day = diff / nd;// 计算差多少天
+            long hour = diff % nd / nh;// 计算差多少小时
+            long min = diff % nd % nh / nm;// 计算差多少分钟
+            long sec = diff % nd % nh % nm / ns;// 计算差多少秒//输出结果
+            if (day > 0) {
+                str += day + "天";
+            }
+            if (hour > 0) {
+                str += hour + "小时";
+            }
+            if (min > 0) {
+                str += min + "分钟";
+            }
+            if (sec > 0) {
+                str += sec + "秒";
+            }
+        } catch (Exception e) {
+        }
+        return str;
+    }
+
+    /**
+     * 计算时间差
+     *
+     * @param startTime
+     * @param endTime
+     * @return
+     */
+    public static String TimeDifference(String startTime, String endTime) {
+        String str = "剩余";
+        try {
+            SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+            long nd = 1000 * 24 * 60 * 60;// 一天的毫秒数
+            long nh = 1000 * 60 * 60;// 一小时的毫秒数
+            long nm = 1000 * 60;// 一分钟的毫秒数
+            long ns = 1000;// 一秒钟的毫秒数
+            // 获得两个时间的毫秒时间差异
+            Date start = new Date();
+            Date end = new Date();
+            start = sd.parse(timeStamp2Date(startTime, ""));
+            end = sd.parse(timeStamp2Date(endTime, ""));
+            long diff = end.getTime() - start.getTime();
+            long day = diff / nd;// 计算差多少天
+            long hour = diff % nd / nh;// 计算差多少小时
+            long min = diff % nd % nh / nm;// 计算差多少分钟
+            long sec = diff % nd % nh % nm / ns;// 计算差多少秒
+            if (day > 0) {
+                str += day + "天";
+            }
+            if (hour > 0) {
+                str += hour + "小时";
+            }
+            if (min > 0) {
+                str += min + "分钟";
+            }
+            if (sec > 0) {
+                str += sec + "秒";
+            }
+            if (diff < 0) {
+                str = "已过期";
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return str;
+    }
+
+    /**
+     * 结束日期是否大于开始日期
+     *
+     * @param startTime 开始时间 为时间戳类型
+     * @param endTime   结束时间 为时间戳类型
+     * @return true 表示为真
+     */
+    public static boolean TimeComparison(String startTime, String endTime) {
+        boolean mAfter = true;
+        try {
+            SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+            long nd = 1000 * 24 * 60 * 60;// 一天的毫秒数
+            long nh = 1000 * 60 * 60;// 一小时的毫秒数
+            long nm = 1000 * 60;// 一分钟的毫秒数
+            long ns = 1000;// 一秒钟的毫秒数
+            // 获得两个时间的毫秒时间差异
+            Date start = new Date();
+            Date end = new Date();
+            start = sd.parse(timeStamp2Date(startTime, ""));
+            end = sd.parse(timeStamp2Date(endTime, ""));
+            long diff = end.getTime() - start.getTime();
+            long sec = diff % nd % nh % nm / ns;// 计算差多少秒
+            if (sec < 0) {
+                mAfter = false;
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return mAfter;
+    }
+
+    public static String TimeDifferenceDay(String startTime, String endTime) {
+        String str = "";
+        try {
+            SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd:mm:ss");
+            long nd = 1000 * 24 * 60 * 60;// 一天的毫秒数
+            long nh = 1000 * 60 * 60;// 一小时的毫秒数
+            // 获得两个时间的毫秒时间差异
+            long diff = sd.parse(endTime).getTime() - sd.parse(startTime).getTime();
+            long day = diff / nd;// 计算差多少天
+            long hour = diff % nd / nh;// 计算差多少小时
+            if (day > 0) {
+                str += day + "天";
+            }
+            if (hour > 0) {
+                str += hour + "小时";
+            }
+            if (diff < 0) {
+                str = "已过期";
+            }
+        } catch (Exception e) {
+        }
+        return str;
+    }
+
+    /**
+     * 获取现在时间
+     *
+     * @return 返回短时间字符串格式yyyy-MM-dd
+     */
+    public static String getStringDateShort() {
+        Date currentTime = new Date();
+        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
+        String dateString = formatter.format(currentTime);
+        return dateString;
+    }
+
+    /**
+     * 获取时间 小时:分;秒 HH:mm:ss
+     *
+     * @return
+     */
+    public static String getTimeShort() {
+        SimpleDateFormat formatter = new SimpleDateFormat("HH:mm:ss");
+        Date currentTime = new Date();
+        String dateString = formatter.format(currentTime);
+        return dateString;
+    }
+
+    /**
+     * 将长时间格式字符串转换为时间 yyyy-MM-dd HH:mm:ss
+     *
+     * @param strDate
+     * @return
+     */
+    public static Date strToDateLong(String strDate) {
+        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        ParsePosition pos = new ParsePosition(0);
+        Date strtodate = formatter.parse(strDate, pos);
+        return strtodate;
+    }
+
+    /**
+     * 将长时间格式时间转换为字符串 yyyy-MM-dd HH:mm:ss
+     *
+     * @param dateDate
+     * @return
+     */
+    public static String dateToStrLong(Date dateDate) {
+        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        String dateString = formatter.format(dateDate);
+        return dateString;
+    }
+
+    /**
+     * 将短时间格式时间转换为字符串 yyyy-MM-dd
+     *
+     * @param dateDate
+     * @param
+     * @return
+     */
+    public static String dateToStr(Date dateDate) {
+        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
+        String dateString = formatter.format(dateDate);
+        return dateString;
+    }
+
+    /**
+     * 将短时间格式字符串转换为时间 yyyy-MM-dd
+     *
+     * @param strDate
+     * @return
+     */
+    public static Date strToDate(String strDate) {
+        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
+        ParsePosition pos = new ParsePosition(0);
+        Date strtodate = formatter.parse(strDate, pos);
+        return strtodate;
+    }
+
+    /**
+     * 得到现在时间
+     *
+     * @return
+     */
+    public static Date getNow() {
+        Date currentTime = new Date();
+        return currentTime;
+    }
+
+    /**
+     * 提取一个月中的最后一天
+     *
+     * @param day
+     * @return
+     */
+    public static Date getLastDate(long day) {
+        Date date = new Date();
+        long date_3_hm = date.getTime() - 3600000 * 34 * day;
+        Date date_3_hm_date = new Date(date_3_hm);
+        return date_3_hm_date;
+    }
+
+    /**
+     * 得到现在时间
+     *
+     * @return 字符串 yyyyMMdd HHmmss
+     */
+    public static String getStringToday() {
+        Date currentTime = new Date();
+        SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMdd HHmmss");
+        String dateString = formatter.format(currentTime);
+        return dateString;
+    }
+
+    /**
+     * 得到现在小时
+     */
+    public static String getHour() {
+        Date currentTime = new Date();
+        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        String dateString = formatter.format(currentTime);
+        String hour;
+        hour = dateString.substring(11, 13);
+        return hour;
+    }
+
+    /**
+     * 得到现在分钟
+     *
+     * @return
+     */
+    public static String getTime() {
+        Date currentTime = new Date();
+        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        String dateString = formatter.format(currentTime);
+        String min;
+        min = dateString.substring(14, 16);
+        return min;
+    }
+
+    /**
+     * 根据用户传入的时间表示格式,返回当前时间的格式 如果是yyyyMMdd,注意字母y不能大写。
+     *
+     * @param sformat yyyyMMddhhmmss
+     * @return
+     */
+    public static String getUserDate(String sformat) {
+        Date currentTime = new Date();
+        SimpleDateFormat formatter = new SimpleDateFormat(sformat);
+        String dateString = formatter.format(currentTime);
+        return dateString;
+    }
+
+    /**
+     * @param strDate 当前时间
+     * @param pattern 时间格式
+     * @return
+     */
+    public static Date strToDate(String strDate, String pattern) {
+        SimpleDateFormat formatter = new SimpleDateFormat(pattern);
+        ParsePosition pos = new ParsePosition(0);
+        Date strtodate = formatter.parse(strDate, pos);
+        return strtodate;
+    }
+
+    /**
+     * @param strDate 时间
+     * @param pattern 时间格式
+     * @return
+     */
+    public static String getDate(String strDate, String pattern) {
+        Date currentTime = strToDate(strDate, pattern);
+        SimpleDateFormat format1 = new SimpleDateFormat(pattern);
+        String dateString = format1.format(currentTime);
+        return dateString;
+    }
+
+    /**
+     * 判断星期几
+     * @param date
+     * @return
+     */
+    public static String getWeek(String date) {
+        String week = "";
+        @SuppressLint("SimpleDateFormat")
+        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
+        Calendar c = Calendar.getInstance();
+        try {
+            c.setTime(format.parse(date));
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        if (c.get(Calendar.DAY_OF_WEEK) == 1) {
+            week += "天";
+        }
+        if (c.get(Calendar.DAY_OF_WEEK) == 2) {
+            week += "一";
+        }
+        if (c.get(Calendar.DAY_OF_WEEK) == 3) {
+            week += "二";
+        }
+        if (c.get(Calendar.DAY_OF_WEEK) == 4) {
+            week += "三";
+        }
+        if (c.get(Calendar.DAY_OF_WEEK) == 5) {
+            week += "四";
+        }
+        if (c.get(Calendar.DAY_OF_WEEK) == 6) {
+            week += "五";
+        }
+        if (c.get(Calendar.DAY_OF_WEEK) == 7) {
+            week += "六";
+        }
+        return week;
+    }
+}

+ 36 - 0
baselib/src/main/java/com/mylove/baselib/utils/DpAndPxUtil.java

@@ -0,0 +1,36 @@
+package com.mylove.baselib.utils;
+
+import android.content.Context;
+
+/**
+ * @author myLove
+ * @time 2017/11/15 9:45
+ * @e-mail mylove.520.y@gmail.com
+ * @overview
+ */
+
+public class DpAndPxUtil {
+    /**
+     * sp转px
+     *
+     * @param context
+     * @param spValue
+     * @return
+     */
+    public static int sp2px(Context context, Float spValue) {
+        float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
+        return (int) (spValue * fontScale + 0.5f);
+    }
+
+    /**
+     * dp转px
+     *
+     * @param context
+     * @param dipValue
+     * @return
+     */
+    public static int dip2px(Context context, Float dipValue) {
+        float scale = context.getResources().getDisplayMetrics().density;
+        return (int) (dipValue * scale + 0.5f);
+    }
+}

+ 39 - 0
baselib/src/main/java/com/mylove/baselib/utils/ImageUtil.java

@@ -0,0 +1,39 @@
+package com.mylove.baselib.utils;
+
+import android.graphics.Bitmap;
+
+/**
+ * @author myLove
+ * @time 2017/11/15 9:57
+ * @e-mail mylove.520.y@gmail.com
+ * @overview
+ */
+
+public class ImageUtil {
+    /**
+     * 计较两张图片是否一样
+     *
+     * @param b1
+     * @param b2
+     * @return
+     */
+    public boolean isEquals(Bitmap b1, Bitmap b2) {
+        //先判断宽高是否一致,不一致直接返回false
+        if (b1.getWidth() == b2.getWidth()
+                && b1.getHeight() == b2.getHeight()) {
+            int xCount = b1.getWidth();
+            int yCount = b1.getHeight();
+            for (int x = 0; x < xCount; x++) {
+                for (int y = 0; y < yCount; y++) {
+                    //比较每个像素点颜色
+                    if (b1.getPixel(x, y) != b2.getPixel(x, y)) {
+                        return false;
+                    }
+                }
+            }
+            return true;
+        } else {
+            return false;
+        }
+    }
+}

+ 116 - 0
baselib/src/main/java/com/mylove/baselib/utils/InternetUtil.java

@@ -0,0 +1,116 @@
+package com.mylove.baselib.utils;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.net.wifi.WifiInfo;
+import android.net.wifi.WifiManager;
+
+/**
+ * @author myLove
+ * @time 2017/11/7 16:08
+ * @e-mail mylove.520.y@gmail.com
+ * @overview 网络工具类
+ */
+
+public class InternetUtil {
+    /**
+     * 判断是否有网络连接
+     */
+    public static boolean isNetWorkConnected(Context context) {
+        ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
+        NetworkInfo networkInfo = null;
+        if (connectivityManager != null) {
+            networkInfo = connectivityManager.getActiveNetworkInfo();
+        }
+        return networkInfo != null && networkInfo.isAvailable();
+    }
+
+    /**
+     * 判断WIFI网络是否可用
+     *
+     * @msg 测试没用
+     */
+    public static boolean isWifiConnected(Context context) {
+        ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
+        NetworkInfo networkInfo = null;
+        if (connectivityManager != null) {
+            networkInfo = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
+        }
+        return networkInfo != null && networkInfo.isAvailable();
+    }
+
+    /**
+     * 判断MOBILE网络是否可用
+     *
+     * @msg 测试没用
+     */
+    public static boolean isMobileConnected(Context context) {
+        ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
+        NetworkInfo networkInfo = null;
+        if (connectivityManager != null) {
+            networkInfo = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
+        }
+        return networkInfo != null && networkInfo.isAvailable();
+    }
+
+    /**
+     * 获取当前网络连接的类型信息
+     */
+    public static int getConnectedType(Context context) {
+        int i = -1;
+        ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
+        NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
+        if (networkInfo != null) {
+            if (networkInfo.isAvailable()) {
+                i = networkInfo.getType();
+//                int type = networkInfo.getType();
+//                if (type == ConnectivityManager.TYPE_MOBILE) {
+//                    JLog.d(networkInfo.getExtraInfo());
+//                    if (networkInfo.getExtraInfo().toLowerCase() == "cmnet") {
+//                        JLog.d("CMNET");
+//                    } else {
+//                        JLog.d("CMWAP");
+//                    }
+//                } else if (type == ConnectivityManager.TYPE_WIFI) {
+//                    JLog.d("WIFI");
+//                }
+            }
+        }
+        return i;
+    }
+
+    /**
+     * 获取当前ip地址
+     *
+     * @param context
+     * @return
+     */
+    public static String getLocalIpAddress(Context context) {
+        try {
+            WifiManager wifiManager = (WifiManager) context.getApplicationContext()
+                    .getSystemService(Context.WIFI_SERVICE);
+            @SuppressLint("MissingPermission")
+            WifiInfo wifiInfo = wifiManager.getConnectionInfo();
+            int i = wifiInfo.getIpAddress();
+            return int2ip(i);
+        } catch (Exception ex) {
+            return " 获取IP出错!!!!请保证是WIFI,或者请重新打开网络!\n" + ex.getMessage();
+        }
+        // return null;
+    }
+
+    /**
+     * 将ip的整数形式转换成ip形式
+     *
+     * @param ipInt
+     * @return
+     */
+    private static String int2ip(int ipInt) {
+        return String.valueOf(ipInt & 0xFF) + "." +
+                ((ipInt >> 8) & 0xFF) + "." +
+                ((ipInt >> 16) & 0xFF) + "." +
+                ((ipInt >> 24) & 0xFF);
+    }
+}

+ 22 - 0
baselib/src/main/java/com/mylove/baselib/utils/OnClickTime.java

@@ -0,0 +1,22 @@
+package com.mylove.baselib.utils;
+
+/**
+ * @author myLove
+ * @time 2017/11/15 9:54
+ * @e-mail mylove.520.y@gmail.com
+ * @overview 用于判断是否点击两次
+ */
+
+public class OnClickTime {
+    private static long lastClickTime;
+
+    public static boolean isFastDoubleClick() {
+        long time = System.currentTimeMillis();
+        long timeD = time - lastClickTime;
+        if (0 < timeD && timeD < 600) {
+            return true;
+        }
+        lastClickTime = time;
+        return false;
+    }
+}

+ 76 - 0
baselib/src/main/java/com/mylove/baselib/utils/PingYinUtil.java

@@ -0,0 +1,76 @@
+package com.mylove.baselib.utils;
+
+import net.sourceforge.pinyin4j.PinyinHelper;
+import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;
+import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
+import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;
+import net.sourceforge.pinyin4j.format.HanyuPinyinVCharType;
+import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * @author myLove
+ * @time 2017/11/15 10:19
+ * @e-mail mylove.520.y@gmail.com
+ * @overview
+ */
+
+public class PingYinUtil {
+
+    /**
+     * 将字符串中的中文转化为拼音,其他字符不变
+     */
+    public static String getPingYin(String inputString) {
+        HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();
+        format.setCaseType(HanyuPinyinCaseType.LOWERCASE);
+        format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
+        format.setVCharType(HanyuPinyinVCharType.WITH_V);
+
+        Pattern p = Pattern.compile("^[\u4E00-\u9FA5A-Za-z_]+$");
+        Matcher matcher = p.matcher(inputString.substring(0, 1));
+        if (matcher.find()) {
+            char[] input = inputString.trim().toCharArray();
+            StringBuilder output = new StringBuilder();
+            try {
+                for (char anInput : input) {
+                    if (Character.toString(anInput).matches(
+                            "[\\u4E00-\\u9FA5]+")) {
+                        String[] temp = PinyinHelper.toHanyuPinyinStringArray(
+                                anInput, format);
+                        output.append(temp[0]);
+                    } else
+                        output.append(Character.toString(anInput));
+                }
+            } catch (BadHanyuPinyinOutputFormatCombination e) {
+                e.printStackTrace();
+            }
+            return output.toString();
+        } else {
+            return "";
+        }
+    }
+
+    public static String converterToFirstSpell(String chines) {
+        StringBuilder pinyinName = new StringBuilder();
+        char[] nameChar = chines.toCharArray();
+        HanyuPinyinOutputFormat defaultFormat = new HanyuPinyinOutputFormat();
+        defaultFormat.setCaseType(HanyuPinyinCaseType.UPPERCASE);
+        defaultFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
+        for (char aNameChar : nameChar) {
+            if (aNameChar > 128) {
+                try {
+                    pinyinName.append(PinyinHelper.toHanyuPinyinStringArray(
+                            aNameChar, defaultFormat)[0].charAt(0));
+                } catch (BadHanyuPinyinOutputFormatCombination e) {
+                    e.printStackTrace();
+                }
+            } else {
+                pinyinName.append(aNameChar);
+            }
+        }
+        return pinyinName.toString();
+    }
+
+}

+ 364 - 0
baselib/src/main/java/com/mylove/baselib/utils/SharedUtil.java

@@ -0,0 +1,364 @@
+package com.mylove.baselib.utils;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.content.SharedPreferences;
+
+import com.google.gson.Gson;
+import com.google.gson.reflect.TypeToken;
+
+import org.json.JSONArray;
+
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author myLove
+ * @time 2017/10/24 9:47
+ * @overview
+ */
+
+public class SharedUtil {
+    @SuppressLint("StaticFieldLeak")
+    private static SharedUtil instance;
+    private SharedPreferences sha;
+    private SharedPreferences.Editor oEditor;
+    private String name;
+    private Context mContext;
+
+    private SharedUtil(String name, Context context) {
+        this.name = name;
+        this.mContext = context;
+    }
+
+    public static SharedUtil getInstance(String name, Context context) {
+        if (instance == null) {
+            synchronized (SharedUtil.class) {
+                if (instance == null) {
+                    instance = new SharedUtil(name, context);
+
+                }
+            }
+        }
+        return instance;
+    }
+
+    /**
+     * 数据保存本地
+     *
+     * @param key    保存的key值
+     * @param values 保存的values
+     */
+    public void saveShaString(String key, String values) {
+        sha = mContext.getSharedPreferences(name, Context.MODE_PRIVATE);
+        oEditor = sha.edit();
+        oEditor.putString(key, values);
+        oEditor.apply();
+    }
+
+    /**
+     * 数据保存本地
+     *
+     * @param key    保存的key值
+     * @param values 保存的values
+     */
+    public void saveShaBoolean(String key, boolean values) {
+        sha = mContext.getSharedPreferences(name, Context.MODE_PRIVATE);
+        oEditor = sha.edit();
+        oEditor.putBoolean(key, values);
+        oEditor.apply();
+    }
+
+    /**
+     * 数据保存本地
+     *
+     * @param key    保存的key值
+     * @param values 保存的values
+     */
+    public void saveShaInt(String key, int values) {
+        sha = mContext.getSharedPreferences(name, Context.MODE_PRIVATE);
+        oEditor = sha.edit();
+        oEditor.putInt(key, values);
+        oEditor.apply();
+    }
+
+    /**
+     * 数据保存本地
+     *
+     * @param key    保存的key值
+     * @param values 保存的values
+     */
+    public void saveShaLong(String key, long values) {
+        sha = mContext.getSharedPreferences(name, Context.MODE_PRIVATE);
+        oEditor = sha.edit();
+        oEditor.putLong(key, values);
+        oEditor.apply();
+    }
+
+    /**
+     * 数据保存本地
+     *
+     * @param key    保存的key值
+     * @param values 保存的values
+     */
+    public void saveShaFloat(String key, float values) {
+        sha = mContext.getSharedPreferences(name, Context.MODE_PRIVATE);
+        oEditor = sha.edit();
+        oEditor.putFloat(key, values);
+        oEditor.apply();
+    }
+
+    /**
+     * 数据保存本地
+     *
+     * @param key 保存的key值
+     * @param set 保存的数组
+     */
+    public void saveShaSet(String key, Set<String> set) {
+        sha = mContext.getSharedPreferences(name, Context.MODE_PRIVATE);
+        oEditor = sha.edit();
+        oEditor.putStringSet(key, set);
+        oEditor.apply();
+    }
+
+    /**
+     * 数据保存本地
+     *
+     * @param key  保存的key值
+     * @param list 保存的集合
+     */
+    public <T> void saveShaList(String key, List<T> list) {
+        sha = mContext.getSharedPreferences(name, Context.MODE_PRIVATE);
+        oEditor = sha.edit();
+        Gson gson = new Gson();
+        String str = gson.toJson(list);
+        oEditor.putString(key, str);
+//        oEditor.putStringSet(key, set);
+        oEditor.apply();
+    }
+
+    /**
+     * 从本地获取数据
+     *
+     * @param key 保存的key值
+     * @return 值
+     */
+    public Set<String> getShaSet(String key) {
+        sha = mContext.getSharedPreferences(name, Context.MODE_PRIVATE);
+        Set<String> set = sha.getStringSet(key, new HashSet<String>());
+        return set;
+    }
+
+    /**
+     * 从本地获取数据
+     *
+     * @param key 保存的key值
+     * @return 值
+     */
+    public String getShaString(String key) {
+        sha = mContext.getSharedPreferences(name, Context.MODE_PRIVATE);
+        return sha.getString(key, "");
+    }
+
+    /**
+     * 从本地获取数据
+     *
+     * @param key        保存的key值
+     * @param defaultStr 取值失败返回的值
+     * @return 值
+     */
+    public String getShaString(String key, String defaultStr) {
+        sha = mContext.getSharedPreferences(name, Context.MODE_PRIVATE);
+        return sha.getString(key, defaultStr);
+    }
+
+    /**
+     * 从本地获取数据
+     *
+     * @param key 保存的key值
+     * @return 值
+     */
+    public boolean getShaBoolean(String key) {
+        sha = mContext.getSharedPreferences(name, Context.MODE_PRIVATE);
+        return sha.getBoolean(key, false);
+    }
+
+    /**
+     * 从本地获取数据
+     *
+     * @param key        保存的key值
+     * @param defaultStr 取值失败返回的值
+     * @return 值
+     */
+    public boolean getShaBoolean(String key, boolean defaultStr) {
+        sha = mContext.getSharedPreferences(name, Context.MODE_PRIVATE);
+        return sha.getBoolean(key, defaultStr);
+    }
+
+    /**
+     * 从本地获取数据
+     *
+     * @param key 保存的key值
+     * @return 值
+     */
+    public int getShaInt(String key) {
+        sha = mContext.getSharedPreferences(name, Context.MODE_PRIVATE);
+        return sha.getInt(key, -1);
+    }
+
+    /**
+     * 从本地获取数据
+     *
+     * @param key        保存的key值
+     * @param defaultStr 取值失败返回的值
+     * @return 值
+     */
+    public int getShaInt(String key, int defaultStr) {
+        sha = mContext.getSharedPreferences(name, Context.MODE_PRIVATE);
+        return sha.getInt(key, defaultStr);
+    }
+
+    /**
+     * 从本地获取数据
+     *
+     * @param key 保存的key值
+     * @return 值
+     */
+    public float getShaFloat(String key) {
+        sha = mContext.getSharedPreferences(name, Context.MODE_PRIVATE);
+        return sha.getFloat(key, -1f);
+    }
+
+    /**
+     * 从本地获取数据
+     *
+     * @param key        保存的key值
+     * @param defaultStr 取值失败返回的值
+     * @return 值
+     */
+    public float getShaFloat(String key, float defaultStr) {
+        sha = mContext.getSharedPreferences(name, Context.MODE_PRIVATE);
+        return sha.getFloat(key, defaultStr);
+    }
+
+    /**
+     * 从本地获取数据
+     *
+     * @param key 保存的key值
+     * @return 值
+     */
+    public long getShaLong(String key) {
+        sha = mContext.getSharedPreferences(name, Context.MODE_PRIVATE);
+        return sha.getLong(key, -1L);
+    }
+
+    /**
+     * 从本地获取数据
+     *
+     * @param key        保存的key值
+     * @param defaultStr 取值失败返回的值
+     * @return 值
+     */
+    public long getShaLong(String key, long defaultStr) {
+        sha = mContext.getSharedPreferences(name, Context.MODE_PRIVATE);
+        return sha.getLong(key, defaultStr);
+    }
+
+    /**
+     * 从本地获取数据
+     *
+     * @param key 保存的key值
+     * @return 值
+     */
+    @Deprecated
+    public <T> List<T> getShaList(String key) {
+        sha = mContext.getSharedPreferences(name, Context.MODE_PRIVATE);
+        String str = sha.getString(key, "");
+        if (StringUtil.isNotEmpty(str)) {
+            Gson gson = new Gson();
+            Type type = new TypeToken<List<T>>() {
+            }.getType();
+            return gson.fromJson(str, type);
+        } else {
+            return new ArrayList<>();
+        }
+    }
+
+    /**
+     * 从本地获取数据
+     *
+     * @param key 保存的key值
+     * @return 值
+     */
+    public <T> List<T> getShaList(String key, Class<T> tClass) {
+        sha = mContext.getSharedPreferences(name, Context.MODE_PRIVATE);
+        String str = sha.getString(key, "");
+        List<T> oList = new ArrayList<>();
+        if (StringUtil.isNotEmpty(str)) {
+            Gson gson = new Gson();
+            try {
+                JSONArray array = new JSONArray(str);
+                for (int i = 0; i < array.length(); i++) {
+                    String s = array.getJSONObject(i).toString();
+                    oList.add(gson.fromJson(s, tClass));
+                }
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+        return oList;
+    }
+
+    /**
+     * 从本地获取数据
+     *
+     * @param key        保存的key值
+     * @param defaultStr 取值失败返回的值
+     * @return 值
+     */
+    @Deprecated
+    public <T> List<T> getShaList(String key, List<T> defaultStr) {
+        sha = mContext.getSharedPreferences(name, Context.MODE_PRIVATE);
+        String str = sha.getString(key, "");
+        if (StringUtil.isNotEmpty(str)) {
+            Gson gson = new Gson();
+            Type type = new TypeToken<List<T>>() {
+            }.getType();
+            return gson.fromJson(str, type);
+        } else {
+            return defaultStr;
+        }
+    }
+
+    /**
+     * 从本地获取数据
+     *
+     * @param key 保存的key值
+     * @return 值
+     */
+    public <T> List<T> getShaList(String key, Class<T> tClass, List<T> defaultList) {
+        sha = mContext.getSharedPreferences(name, Context.MODE_PRIVATE);
+        String str = sha.getString(key, "");
+        List<T> oList = new ArrayList<>();
+        if (StringUtil.isNotEmpty(str)) {
+            Gson gson = new Gson();
+            try {
+                JSONArray array = new JSONArray(str);
+                for (int i = 0; i < array.length(); i++) {
+                    String s = array.getJSONObject(i).toString();
+                    oList.add(gson.fromJson(s, tClass));
+                }
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+        if (StringUtil.isListNotEmpty(oList)) {
+            return oList;
+        } else {
+            return defaultList;
+        }
+    }
+}

+ 189 - 0
baselib/src/main/java/com/mylove/baselib/utils/StatusBarUtil.java

@@ -0,0 +1,189 @@
+package com.mylove.baselib.utils;
+
+import android.annotation.TargetApi;
+import android.app.Activity;
+import android.graphics.Color;
+import android.os.Build;
+import android.view.View;
+import android.view.Window;
+import android.view.WindowManager;
+
+import com.readystatesoftware.systembartint.SystemBarTintManager;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+/**
+ * @author myLove
+ * @date 2018-04-28 13:13
+ * @e-mail love@yanyi.red
+ * @overview 管理手机状态栏
+ */
+public class StatusBarUtil {
+    /**
+     * 修改状态栏为全透明
+     *
+     * @param activity
+     */
+    @TargetApi(19)
+    public static void transparencyBar(Activity activity) {
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+            Window window = activity.getWindow();
+            window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
+                    | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
+            window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
+                    | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
+                    | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
+            window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
+            //api21新增接口
+            window.setStatusBarColor(Color.TRANSPARENT);
+            window.setNavigationBarColor(Color.TRANSPARENT);
+        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
+            Window window = activity.getWindow();
+            window.setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS,
+                    WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
+        }
+    }
+
+    /**
+     * 修改状态栏颜色,支持4.4以上版本
+     *
+     * @param activity
+     * @param colorId
+     */
+    public static void setStatusBarColor(Activity activity, int colorId) {
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+            Window window = activity.getWindow();
+            window.setStatusBarColor(activity.getResources().getColor(colorId));
+        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
+            //使用SystemBarTint库使4.4版本状态栏变色,需要先将状态栏设置为透明
+            transparencyBar(activity);
+            SystemBarTintManager tintManager = new SystemBarTintManager(activity);
+            tintManager.setStatusBarTintEnabled(true);
+            tintManager.setStatusBarTintResource(colorId);
+        }
+    }
+
+    /**
+     * 设置状态栏黑色字体图标,
+     * 适配4.4以上版本MIUIV、Flyme和6.0以上版本其他Android
+     *
+     * @param activity
+     * @return 1:MIUUI 2:Flyme 3:android6.0
+     */
+    public static int statusBarLightMode(Activity activity) {
+        int result = 0;
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
+            if (MIUISetStatusBarLightMode(activity.getWindow(), true)) {
+                result = 1;
+            } else if (FlymeSetStatusBarLightMode(activity.getWindow(), true)) {
+                result = 2;
+            } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+                activity.getWindow().getDecorView().
+                        setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
+                                | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
+                result = 3;
+            }
+        }
+        return result;
+    }
+
+    /**
+     * 已知系统类型时,设置状态栏黑色字体图标。
+     * 适配4.4以上版本MIUIV、Flyme和6.0以上版本其他Android
+     *
+     * @param activity
+     * @param type     1:MIUUI 2:Flyme 3:android6.0
+     */
+    public static void statusBarLightMode(Activity activity, int type) {
+        if (type == 1) {
+            MIUISetStatusBarLightMode(activity.getWindow(), true);
+        } else if (type == 2) {
+            FlymeSetStatusBarLightMode(activity.getWindow(), true);
+        } else if (type == 3) {
+            activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
+        }
+
+    }
+
+    /**
+     * 清除MIUI或flyme或6.0以上版本状态栏黑色字体
+     */
+    public static void statusBarDarkMode(Activity activity, int type) {
+        if (type == 1) {
+            MIUISetStatusBarLightMode(activity.getWindow(), false);
+        } else if (type == 2) {
+            FlymeSetStatusBarLightMode(activity.getWindow(), false);
+        } else if (type == 3) {
+            activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
+        }
+
+    }
+
+
+    /**
+     * 设置状态栏图标为深色和魅族特定的文字风格
+     * 可以用来判断是否为Flyme用户
+     *
+     * @param window 需要设置的窗口
+     * @param dark   是否把状态栏字体及图标颜色设置为深色
+     * @return boolean 成功执行返回true
+     */
+    private static boolean FlymeSetStatusBarLightMode(Window window, boolean dark) {
+        boolean result = false;
+        if (window != null) {
+            try {
+                WindowManager.LayoutParams lp = window.getAttributes();
+                Field darkFlag = WindowManager.LayoutParams.class
+                        .getDeclaredField("MEIZU_FLAG_DARK_STATUS_BAR_ICON");
+                Field meizuFlags = WindowManager.LayoutParams.class
+                        .getDeclaredField("meizuFlags");
+                darkFlag.setAccessible(true);
+                meizuFlags.setAccessible(true);
+                int bit = darkFlag.getInt(null);
+                int value = meizuFlags.getInt(lp);
+                if (dark) {
+                    value |= bit;
+                } else {
+                    value &= ~bit;
+                }
+                meizuFlags.setInt(lp, value);
+                window.setAttributes(lp);
+                result = true;
+            } catch (Exception e) {
+
+            }
+        }
+        return result;
+    }
+
+    /**
+     * 设置状态栏字体图标为深色,需要MIUIV6以上
+     *
+     * @param window 需要设置的窗口
+     * @param dark   是否把状态栏字体及图标颜色设置为深色
+     * @return boolean 成功执行返回true
+     */
+    private static boolean MIUISetStatusBarLightMode(Window window, boolean dark) {
+        boolean result = false;
+        if (window != null) {
+            Class clazz = window.getClass();
+            try {
+                int darkModeFlag = 0;
+                Class layoutParams = Class.forName("android.view.MiuiWindowManager$LayoutParams");
+                Field field = layoutParams.getField("EXTRA_FLAG_STATUS_BAR_DARK_MODE");
+                darkModeFlag = field.getInt(layoutParams);
+                Method extraFlagField = clazz.getMethod("setExtraFlags", int.class, int.class);
+                if (dark) {
+                    extraFlagField.invoke(window, darkModeFlag, darkModeFlag);//状态栏透明且黑色字体
+                } else {
+                    extraFlagField.invoke(window, 0, darkModeFlag);//清除黑色字体
+                }
+                result = true;
+            } catch (Exception e) {
+
+            }
+        }
+        return result;
+    }
+}

+ 350 - 0
baselib/src/main/java/com/mylove/baselib/utils/StringUtil.java

@@ -0,0 +1,350 @@
+package com.mylove.baselib.utils;
+
+import android.content.Context;
+
+import org.json.JSONArray;
+import org.json.JSONObject;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.text.SimpleDateFormat;
+import java.util.Collection;
+import java.util.Date;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * 字符串工具类
+ */
+public class StringUtil {
+
+
+    public static final String EMPTY = "";
+
+    /**
+     * 判断字符串是否为空
+     *
+     * @param str
+     * @return true 不为空, false 为空
+     */
+    public static boolean isNotEmpty(String str) {
+        return str != null && !"null".equals(str) && str.trim().length() != 0;
+    }
+
+    /**
+     * 判断字符串是否为空
+     *
+     * @param str
+     * @return true 为空,false 不为空
+     */
+    public static boolean isEmpty(String str) {
+        return str == null || "null".equals(str) || str.trim().length() == 0;
+    }
+
+    public static final SimpleDateFormat dateformat = new SimpleDateFormat("HH:mm", Locale.CHINA);
+
+    public static String getCurrentTime() {
+        return dateformat.format(new Date());
+    }
+
+    public static final SimpleDateFormat sdformat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA);
+
+    public static String formatDateTime(long millseconds) {
+        return sdformat.format(new Date(millseconds));
+    }
+
+    public static String getCurrentDateTime() {
+        return sdformat.format(new Date());
+    }
+
+    /**
+     * 判断集合是否为空
+     */
+    public static <T> boolean isCollectionsNotEmpty(Collection<T> collection) {
+        return collection != null && collection.size() > 0;
+    }
+
+    /**
+     * 判断MAP是否为空
+     */
+    public static <K, V> boolean isMapNotEmpty(Map<K, V> map) {
+        return map != null && map.size() > 0;
+    }
+
+    /**
+     * 判断List是否为空
+     */
+    public static boolean isListEmpty(List<?> array) {
+        return array != null && array.size() == 0;
+    }
+
+    /**
+     * 判断JSON数组是否为空
+     */
+    public static boolean isJSONArrayEmpty(JSONArray array) {
+        return array == null || array.length() == 0;
+    }
+
+    public static boolean isObjectNotNull(Object object) {
+        if (object != null && object.getClass().isArray()) {
+            // 如果是数组类型
+            throw new UnsupportedOperationException("isObjectNotNull not supported operation :" + object);
+        }
+        return object != null;
+    }
+
+    /**
+     * 判断JSON数据不空为
+     */
+    public static boolean isJSONArrayNotEmpty(JSONArray array) {
+        return array != null && array.length() > 0;
+    }
+
+    /**
+     * 判断JSON数组是否为空
+     */
+    public static boolean isJSONObjectEmpty(JSONObject object) {
+        return object == null || object.length() == 0;
+    }
+
+    /**
+     * 判断JSON数据不空为
+     */
+    public static boolean isJSONObjectNotEmpty(JSONObject object) {
+        return object != null && object.length() > 0;
+    }
+
+    public static boolean isIntArrayNotEmpty(int[] array) {
+        return array != null && array.length > 0;
+    }
+
+    /**
+     * 判断List数据不空为
+     */
+    public static boolean isListNotEmpty(List<?> array) {
+        return array != null && array.size() > 0;
+    }
+
+    /**
+     * 判断long数组不为空
+     *
+     * @param array
+     * @return
+     */
+    public static boolean isLongArrayNotEmpty(long[] array) {
+        return array != null && array.length > 0;
+    }
+
+    /**
+     * 判断float数组不为空
+     *
+     * @param array
+     * @return
+     */
+    public static boolean isFloatArrayNotEmpty(float[] array) {
+        return array != null && array.length > 0;
+    }
+
+    /**
+     * 判断double数组不为空
+     *
+     * @param array
+     * @return
+     */
+    public static boolean isDoubleArrayNotEmpty(double[] array) {
+        return array != null && array.length > 0;
+    }
+
+    /**
+     * 该方法主要使用正则表达式来判断字符串中是否包含字母
+     *
+     * @param cardNum
+     * @return 返回是否包含
+     */
+    public static boolean isJudge(String cardNum) {
+        String regex = ".*[a-zA-Z]+.*";
+        Matcher m = Pattern.compile(regex).matcher(cardNum);
+        return m.matches();
+    }
+
+    public static boolean isNotBlank(String str) {
+        return (str != null) && (str.length() != 0);
+    }
+
+    public static boolean isBlank(String str) {
+        return (str == null) || (str.length() == 0);
+    }
+
+    public static boolean isNotTrimBlank(String str) {
+        return (str != null) && (str.trim().length() != 0);
+    }
+
+    public static boolean isTrimBlank(String str) {
+        return (str == null) || (str.trim().length() == 0);
+    }
+
+    /**
+     * 判断是否是身份证
+     *
+     * @param idNo
+     * @return
+     */
+    public static boolean isIdNo(String idNo) {
+//        if (isTrimBlank(idNo))
+//        {
+//            return false;
+//        }
+//        Pattern p = Pattern.compile("^([1-9]\\d{7}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])\\d{3})|([1-9]\\d{5}[1-9]\\d{3}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])((\\d{4})|\\d{3}[X,x]))$");
+//        Matcher matcher = p.matcher(idNo);
+//        return matcher.find();
+        if (isTrimBlank(idNo)) {
+            return false;
+        }
+        Pattern p = Pattern.compile("^([1-9]\\d{7}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])\\d{3})|([1-9]\\d{5}[1-9]\\d{3}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])((\\d{4})|\\d{3}[X,x]))$");
+        Matcher matcher = p.matcher(idNo);
+        return !matcher.find();
+    }
+
+    /**
+     * 判断是否为手机号
+     *
+     * @param mobiles
+     * @return
+     */
+    public static boolean isNotMobileNO(String mobiles) {
+//        Pattern p = Pattern.compile("^((13[0-9])|(15[^4,\\D])|(18[0,5-9]))\\d{8}$");
+        Pattern p = Pattern.compile("^((1[358][0-9])|(14[57])|(17[0678]))\\d{8}$");
+        Matcher m = p.matcher(mobiles);
+        return !m.matches();
+    }
+
+    /**
+     * 判断是否为邮箱号
+     *
+     * @param email
+     * @return
+     */
+    public static boolean isEmail(String email) {
+        if (isTrimBlank(email)) {
+            return false;
+        }
+        String str = "^([a-zA-Z0-9]*[-_]?[a-zA-Z0-9]+)*@([a-zA-Z0-9]*[-_]?[a-zA-Z0-9]+)+[\\.][A-Za-z]{2,3}([\\.][A-Za-z]{2})?$";
+        Pattern p = Pattern.compile(str);
+        Matcher m = p.matcher(email);
+        return m.matches();
+    }
+
+    /**
+     * 在HTML特殊字符的处理
+     *
+     * @param source
+     * @return
+     */
+    public static String htmlEscapeCharsToString(String source) {
+        return StringUtil.isEmpty(source) ? source : source.replaceAll("&lt;", "<")
+                .replaceAll("&gt;", ">")
+                .replaceAll("&amp;", "&")
+                .replaceAll("&quot;", "\"")
+                .replaceAll("&copy;", "©")
+                .replaceAll("&yen;", "¥")
+                .replaceAll("&divide;", "÷")
+                .replaceAll("&times;", "×")
+                .replaceAll("&reg;", "®")
+                .replaceAll("&sect;", "§")
+                .replaceAll("&pound;", "£")
+                .replaceAll("&cent;", "¢");
+    }
+
+    /**
+     * 验证用户名是否合法
+     *
+     * @param id
+     * @return
+     */
+    public static boolean isNotUserName(String id) {
+        if (isTrimBlank(id)) {
+            return false;
+        }
+        // 字母开头,由字母,数字和下划线组成的长度为2到16的字符串
+        Pattern p = Pattern.compile("^[a-zA-Z0-9_-]{2,16}$");
+        Matcher m = p.matcher(id);
+        return !m.find();
+    }
+
+    public static boolean isNotPassWord(String password) {
+        if (isTrimBlank(password)) {
+            return false;
+        }
+        // 就是以大小写字母开头,由大小写字母,数字和下划线组成的长度为6到18的字符串
+        Pattern p = Pattern.compile("^[a-zA-Z0-9_]{6,18}$");
+        Matcher m = p.matcher(password);
+        return !m.find();
+    }
+
+    /**
+     * 判断银行卡号是否合法
+     *
+     * @param bankCard
+     * @return
+     */
+    public static boolean isNotBank(String bankCard) {
+        if (isTrimBlank(bankCard)) {
+            return false;
+        }
+        // 一共16或19位,都是数字。
+        Pattern p = Pattern.compile("^\\d{16}$|^\\d{19}$");
+        Matcher m = p.matcher(bankCard);
+        return !m.find();
+    }
+
+    /**
+     * @param context
+     * @param resId
+     * @param str
+     * @return
+     */
+    public static String isStringFormat(Context context, int resId, String str) {
+        return String.format(context.getResources().getString(resId), str);
+    }
+
+    /**
+     * 从Raw文件中读取
+     *
+     * @param context
+     * @param resId
+     * @return
+     */
+    public static String getFromRaw(Context context, int resId) {
+        try {
+            InputStreamReader inputReader = new InputStreamReader(context.getResources().openRawResource(resId));
+            BufferedReader bufReader = new BufferedReader(inputReader);
+            String line = "";
+            StringBuilder Result = new StringBuilder();
+            while ((line = bufReader.readLine()) != null)
+                Result.append(line);
+            return Result.toString();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    // 直接从assets读取
+    public static String getFromAssets(Context context, String fileName) {
+        try {
+            InputStreamReader inputReader = new InputStreamReader(context.getResources().getAssets().open(fileName));
+            BufferedReader bufReader = new BufferedReader(inputReader);
+            String line = "";
+            StringBuilder Result = new StringBuilder();
+            while ((line = bufReader.readLine()) != null)
+                Result.append(line);
+            return Result.toString();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+}

+ 75 - 0
baselib/src/main/java/com/mylove/baselib/utils/StringsUtil.java

@@ -0,0 +1,75 @@
+package com.mylove.baselib.utils;
+
+/**
+ * @author myLove
+ * @time 2017/11/15 9:34
+ * @e-mail mylove.520.y@gmail.com
+ * @overview
+ */
+
+public class StringsUtil {
+    /**
+     * byte数组转hex
+     *
+     * @param bytes
+     * @return
+     */
+    public static String bytesToHex(byte[] bytes) {
+        StringBuilder stringBuilder = new StringBuilder("");
+        if (bytes == null || bytes.length <= 0) {
+            return null;
+        }
+        for (byte aSrc : bytes) {
+            int v = aSrc & 0xFF;
+            String hv = Integer.toHexString(v);
+            if (hv.length() < 2) {
+                stringBuilder.append(0);
+            }
+            stringBuilder.append(hv);
+        }
+        return stringBuilder.toString();
+    }
+
+    /**
+     * string转hex
+     *
+     * @param str
+     * @return
+     */
+    public static String strToHex(String str) {
+        String ss;
+        int i = Integer.parseInt(str);
+        String s = Integer.toHexString(i);
+        if (s.length() < 2) {
+            ss = "0" + s;
+        } else {
+            ss = s;
+        }
+        return ss;
+    }
+
+    /**
+     * hex转byte数组
+     *
+     * @param hexString
+     * @return
+     */
+    public static byte[] hexStringToBytes(String hexString) {
+        if (hexString == null || hexString.equals("")) {
+            return null;
+        }
+        hexString = hexString.toUpperCase();
+        int length = hexString.length() / 2;
+        char[] hexChars = hexString.toCharArray();
+        byte[] d = new byte[length];
+        for (int i = 0; i < length; i++) {
+            int pos = i * 2;
+            d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));
+        }
+        return d;
+    }
+
+    private static byte charToByte(char c) {
+        return (byte) "0123456789ABCDEF".indexOf(c);
+    }
+}

+ 167 - 0
baselib/src/main/java/com/mylove/baselib/utils/file/FileSizeUtil.java

@@ -0,0 +1,167 @@
+package com.mylove.baselib.utils.file;
+
+import com.mylove.loglib.JLog;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.text.DecimalFormat;
+
+/**
+ * Created by LYjw on 2017/3/2 0002.
+ */
+
+public class FileSizeUtil {
+
+    /**
+     * 获取文件指定文件的指定单位的大小
+     *
+     * @param filePath 文件路径
+     * @param sizeType 获取大小的类型1为B、2为KB、3为MB、4为GB
+     * @return double值的大小
+     */
+    public static double getFileOrFilesSize(String filePath, SizeType sizeType) {
+        File file = new File(filePath);
+        long blockSize;
+        try {
+            if (file.isDirectory()) {
+                blockSize = getFileSizes(file);
+            } else {
+                blockSize = getFileSize(file);
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            JLog.e("获取文件大小失败!");
+            return 0;
+        }
+        return FormatFileSize(blockSize, sizeType);
+    }
+
+    /**
+     * 调用此方法自动计算指定文件或指定文件夹的大小
+     *
+     * @param filePath 文件路径
+     * @return 计算好的带B、KB、MB、GB的字符串
+     */
+    public static String getAutoFileOrFilesSize(String filePath) {
+        File file = new File(filePath);
+        long blockSize = 0;
+        try {
+            if (file.isDirectory()) {
+                blockSize = getFileSizes(file);
+            } else {
+                blockSize = getFileSize(file);
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            JLog.e("获取文件大小失败!");
+            return "获取文件大小失败";
+        }
+        return FormatFileSize(blockSize);
+    }
+
+    /**
+     * 获取指定文件大小
+     *
+     * @param file
+     * @return
+     * @throws Exception
+     */
+    public static long getFileSize(File file) {
+        long size = 0;
+        try {
+            if (file.exists()) {
+                FileInputStream fis = null;
+                fis = new FileInputStream(file);
+                size = fis.available();
+            } else {
+                file.createNewFile();
+                JLog.e("获取文件大小失败!");
+                return 0;
+            }
+        } catch (Exception e) {
+            e.fillInStackTrace();
+            size = 0;
+        }
+        return size;
+    }
+
+    /**
+     * 获取指定文件夹
+     *
+     * @param f
+     * @return
+     * @throws Exception
+     */
+    public static long getFileSizes(File f) {
+        long size = 0;
+        try {
+            File files[] = f.listFiles();
+            for (int i = 0; i < files.length; i++) {
+                if (files[i].isDirectory()) {
+                    size = size + getFileSizes(files[i]);
+                } else {
+                    size = size + getFileSize(files[i]);
+                }
+            }
+        } catch (Exception e) {
+            e.fillInStackTrace();
+            return 0;
+        }
+        return size;
+    }
+
+    /**
+     * 转换文件大小
+     *
+     * @param fileS
+     * @return
+     */
+    private static String FormatFileSize(long fileS) {
+        DecimalFormat df = new DecimalFormat("#.00");
+        String fileSizeString;
+        String wrongSize = "0B";
+        if (fileS == 0) {
+            return wrongSize;
+        }
+        if (fileS < 1024) {
+            fileSizeString = df.format((double) fileS) + "B";
+        } else if (fileS < 1048576) {
+            fileSizeString = df.format((double) fileS / 1024) + "KB";
+        } else if (fileS < 1073741824) {
+            fileSizeString = df.format((double) fileS / 1048576) + "MB";
+        } else {
+            fileSizeString = df.format((double) fileS / 1073741824) + "GB";
+        }
+        return fileSizeString;
+    }
+
+    /**
+     * 转换文件大小,指定转换的类型
+     *
+     * @param fileS
+     * @param sizeType
+     * @return
+     */
+    private static double FormatFileSize(long fileS, SizeType sizeType) {
+        DecimalFormat df = new DecimalFormat("#.00");
+        double fileSizeLong = 0;
+        switch (sizeType) {
+            case TYPE_B:
+                fileSizeLong = Double.valueOf(df.format((double) fileS));
+                break;
+            case TYPE_KB:
+                fileSizeLong = Double.valueOf(df.format((double) fileS / 1024));
+                break;
+            case TYPE_MB:
+                fileSizeLong = Double.valueOf(df.format((double) fileS / 1048576));
+                break;
+            case TYPE_GB:
+                fileSizeLong = Double.valueOf(df
+                        .format((double) fileS / 1073741824));
+                break;
+            default:
+                break;
+        }
+        return fileSizeLong;
+    }
+}

+ 15 - 0
baselib/src/main/java/com/mylove/baselib/utils/file/SizeType.java

@@ -0,0 +1,15 @@
+package com.mylove.baselib.utils.file;
+
+/**
+ * @author myLove
+ * @time 2017/11/15 10:00
+ * @e-mail mylove.520.y@gmail.com
+ * @overview
+ */
+
+public enum SizeType {
+    TYPE_B,
+    TYPE_KB,
+    TYPE_MB,
+    TYPE_GB
+}

+ 66 - 0
baselib/src/main/java/com/mylove/baselib/utils/toast/ShowMsg.java

@@ -0,0 +1,66 @@
+package com.mylove.baselib.utils.toast;
+
+import android.view.Gravity;
+import android.widget.Toast;
+
+/**
+ * @author myLove
+ * @time 2017/11/3 13:42
+ * @e-mail mylove.520.y@gmail.com
+ * @overview 吐司显示位置类
+ */
+
+class ShowMsg {
+
+    private static ShowMsg instance;
+
+    static ShowMsg getInstance() {
+        if (instance == null) {
+            synchronized (ShowMsg.class) {
+                if (instance == null) {
+                    instance = new ShowMsg();
+                }
+            }
+        }
+        return instance;
+    }
+
+    void show(Toast toast, ToastType type) {
+        if (null != type) {
+            switch (type) {
+                case TOP:
+                    toast.setGravity(Gravity.TOP, 0, 0);
+                    break;
+                case BOTTOM:
+                    toast.setGravity(Gravity.BOTTOM, 0, 0);
+                    break;
+                case LEFT:
+                    toast.setGravity(Gravity.LEFT, 0, 0);
+                    break;
+                case RIGHT:
+                    toast.setGravity(Gravity.RIGHT, 0, 0);
+                    break;
+                case CENTER:
+                    toast.setGravity(Gravity.CENTER, 0, 0);
+                    break;
+                case CENTER_HORIZONTAL:
+                    toast.setGravity(Gravity.CENTER_HORIZONTAL, 0, 0);
+                    break;
+                case CENTER_VERTICAL:
+                    toast.setGravity(Gravity.CENTER_VERTICAL, 0, 0);
+                    break;
+                case FILL_HORIZONTAL:
+                    toast.setGravity(Gravity.FILL_HORIZONTAL, 0, 0);
+                    break;
+                case FILL_VERTICAL:
+                    toast.setGravity(Gravity.FILL_VERTICAL, 0, 0);
+                    break;
+                case DEFAULT:
+                    break;
+                default:
+                    break;
+            }
+        }
+        toast.show();
+    }
+}

+ 80 - 0
baselib/src/main/java/com/mylove/baselib/utils/toast/ShowToast.java

@@ -0,0 +1,80 @@
+package com.mylove.baselib.utils.toast;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.widget.Toast;
+
+/**
+ * @author myLove
+ * @time 2017/10/31 12:24
+ * @e-mail mylove.520.y@gmail.com
+ * @overview 吐司工具类
+ */
+
+public class ShowToast {
+    @SuppressLint("StaticFieldLeak")
+    private static ShowToast instance;
+    private Context mContext;
+    private String msg;
+    private static long lastClickTime;
+    private Toast toast;
+
+    private ShowToast(Context mContext) {
+        this.mContext = mContext;
+    }
+
+    public static ShowToast getInstance(Context context) {
+        if (instance == null) {
+            synchronized (ShowToast.class) {
+                instance = new ShowToast(context);
+            }
+        }
+        return instance;
+    }
+
+    @SuppressLint("ShowToast")
+    private ShowMsg toast(Object msg) {
+        cancel();
+        toast = Toast.makeText(mContext, msg.toString(), Toast.LENGTH_SHORT);
+        return ShowMsg.getInstance();
+    }
+
+    private boolean time() {
+        long time = System.currentTimeMillis();
+        long timeD = time - lastClickTime;
+        if (0 < timeD && timeD < 2000) {
+            return true;
+        }
+        lastClickTime = time;
+        return false;
+    }
+
+    public void show(int strID) {
+        show(strID, ToastType.DEFAULT);
+    }
+
+    public void show(int strID, ToastType type) {
+        String msg = mContext.getResources().getString(strID);
+        if (!(this.msg != null && this.msg.equals(msg) && time())) {
+            toast(msg).show(toast, type);
+        }
+        this.msg = msg;
+    }
+
+    public void show(Object msg) {
+        show(msg, ToastType.DEFAULT);
+    }
+
+    public void show(Object msg, ToastType type) {
+        if (!(this.msg != null && this.msg.equals(msg.toString()) && time())) {
+            toast(msg).show(toast, type);
+        }
+        this.msg = msg.toString();
+    }
+
+    public void cancel() {
+        if (toast != null) {
+            toast.cancel();
+        }
+    }
+}

+ 21 - 0
baselib/src/main/java/com/mylove/baselib/utils/toast/ToastType.java

@@ -0,0 +1,21 @@
+package com.mylove.baselib.utils.toast;
+
+/**
+ * @author myLove
+ * @time 2017/11/1 9:47
+ * @e-mail mylove.520.y@gmail.com
+ * @overview 吐司常量
+ */
+
+public enum ToastType {
+    TOP,
+    BOTTOM,
+    LEFT,
+    RIGHT,
+    CENTER,
+    CENTER_VERTICAL,
+    FILL_VERTICAL,
+    CENTER_HORIZONTAL,
+    FILL_HORIZONTAL,
+    DEFAULT
+}

+ 226 - 0
baselib/src/main/java/com/mylove/baselib/viewholder/RecyclerHolder.java

@@ -0,0 +1,226 @@
+package com.mylove.baselib.viewholder;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.drawable.Drawable;
+import android.os.Handler;
+import android.support.v7.widget.RecyclerView;
+import android.util.SparseArray;
+import android.view.View;
+import android.widget.CheckBox;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.bumptech.glide.Glide;
+import com.mylove.baselib.listener.CommonListener;
+
+import java.util.Random;
+
+/**
+ * 万能的RecyclerView的ViewHolder
+ *
+ * @author myLove
+ * @date 2017/3/20
+ */
+
+public class RecyclerHolder extends RecyclerView.ViewHolder {
+    private SparseArray<View> views;
+    private Context context;
+
+    private RecyclerHolder(Context context, View itemView) {
+        super(itemView);
+        this.context = context;
+        //指定一个初始为8
+        views = new SparseArray<>(8);
+    }
+
+    /**
+     * 取得一个RecyclerHolder对象
+     *
+     * @param context  上下文
+     * @param itemView 子项
+     * @return 返回一个RecyclerHolder对象
+     */
+    public static RecyclerHolder getRecyclerHolder(Context context, View itemView) {
+        return new RecyclerHolder(context, itemView);
+    }
+
+    public SparseArray<View> getViews() {
+        return this.views;
+    }
+
+    /**
+     * 通过view的id获取对应的控件,如果没有则加入views中
+     *
+     * @param viewId 控件的id
+     * @return 返回一个控件
+     */
+    @SuppressWarnings("unchecked")
+    public <T extends View> T getView(int viewId) {
+        View view = views.get(viewId);
+        if (view == null) {
+            view = itemView.findViewById(viewId);
+            views.put(viewId, view);
+        }
+        return (T) view;
+    }
+
+    /**
+     * 设置字符串
+     */
+    public RecyclerHolder setText(int viewId, String text) {
+        TextView tv = getView(viewId);
+        tv.setText(text);
+        return this;
+    }
+
+    /**
+     * 设置字体文字颜色
+     *
+     * @param viewId
+     * @param colorID
+     * @return
+     */
+    public RecyclerHolder setTextColor(int viewId, int colorID) {
+        TextView textView = getView(viewId);
+        textView.setTextColor(context.getResources().getColor(colorID));
+        return this;
+    }
+
+    /**
+     * 设置控件显示隐藏
+     *
+     * @param viewID
+     * @param visibility
+     * @return
+     */
+    public RecyclerHolder setVisibility(int viewID, int visibility) {
+        getView(viewID).setVisibility(visibility);
+        return this;
+    }
+
+    /**
+     * 多个recycler嵌套设置显示隐藏
+     */
+    public RecyclerHolder setVisibility(int viewID, boolean isVisible) {
+        View view = getView(viewID);
+        LinearLayout.LayoutParams param = (LinearLayout.LayoutParams) view.getLayoutParams();
+        if (isVisible) {
+            param.height = LinearLayout.LayoutParams.WRAP_CONTENT;
+            param.width = LinearLayout.LayoutParams.MATCH_PARENT;
+            view.setVisibility(View.VISIBLE);
+        } else {
+            view.setVisibility(View.GONE);
+            param.height = 0;
+            param.width = 0;
+        }
+        view.setLayoutParams(param);
+        return this;
+    }
+
+    /**
+     * 一个recycler设置显示隐藏
+     */
+    public RecyclerHolder setVisibility2(int viewID, boolean isVisible) {
+        View view = getView(viewID);
+        RecyclerView.LayoutParams param = (RecyclerView.LayoutParams) view.getLayoutParams();
+        if (isVisible) {
+            param.height = LinearLayout.LayoutParams.WRAP_CONTENT;
+            param.width = LinearLayout.LayoutParams.MATCH_PARENT;
+            view.setVisibility(View.VISIBLE);
+        } else {
+            view.setVisibility(View.GONE);
+            param.height = 0;
+            param.width = 0;
+        }
+        view.setLayoutParams(param);
+        return this;
+    }
+
+    /**
+     * check设置选中事件
+     *
+     * @param viewID
+     * @param boo
+     * @return
+     */
+    public RecyclerHolder setCheck(int viewID, boolean boo) {
+        CheckBox cb = getView(viewID);
+        cb.setChecked(boo);
+        return this;
+    }
+
+    /**
+     * 设置图片
+     */
+    public RecyclerHolder setImageResource(int viewId, int drawableId) {
+        ImageView iv = getView(viewId);
+        iv.setImageResource(drawableId);
+        return this;
+    }
+
+    /**
+     * 设置图片
+     */
+    public RecyclerHolder setImageBitmap(int viewId, Bitmap bitmap) {
+        ImageView iv = getView(viewId);
+        iv.setImageBitmap(bitmap);
+        return this;
+    }
+
+    /**
+     * 设置图片
+     */
+    public RecyclerHolder setImageDrawable(int viewId, Drawable drawable) {
+        ImageView iv = getView(viewId);
+        iv.setImageDrawable(drawable);
+        return this;
+    }
+
+    /**
+     * 设置图片
+     */
+    public RecyclerHolder setImageByUrl(int viewId, String url) {
+        Glide.with(context).load(url).into((ImageView) getView(viewId));
+        return this;
+    }
+
+    public RecyclerHolder setImage(int viewID, String url, int width, int height){
+        Glide.with(context).load(url).into((ImageView) getView(viewID));
+        return this;
+    }
+
+    /**
+     * 设置本地图片
+     */
+    public RecyclerHolder setImageByFile(final Context mContext, final int viewId, final String url) {
+        new Handler().postDelayed(new Runnable() {
+            public void run() {
+                Glide.with(mContext).load(url).into((ImageView) getView(viewId));
+            }
+        }, new Random().nextInt(100));
+        return this;
+    }
+
+    /**
+     * 设置视频图片
+     */
+    public RecyclerHolder setVideoImageByFile(Context mContext, int viewId, String url) {
+        Glide.with(mContext).load(url).into((ImageView) getView(viewId));
+        return this;
+    }
+
+    /**
+     * 设置点击事件
+     */
+    public RecyclerHolder setOnClickListener(int viewId, final int position, final CommonListener commonListener) {
+        View iv = getView(viewId);
+        iv.setOnClickListener(new View.OnClickListener() {
+            public void onClick(View view) {
+                commonListener.commonListener(view, position);
+            }
+        });
+        return this;
+    }
+}

+ 69 - 0
baselib/src/main/java/com/mylove/baselib/widget/BaseView.java

@@ -0,0 +1,69 @@
+package com.mylove.baselib.widget;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.support.annotation.Nullable;
+import android.util.AttributeSet;
+import android.view.View;
+
+/**
+ * @author myLove
+ * @time 2017/11/15 10:37
+ * @e-mail mylove.520.y@gmail.com
+ * @overview
+ */
+
+abstract class BaseView extends View {
+    private MyThread myThread;
+
+    public BaseView(Context context) {
+        super(context);
+    }
+
+    public BaseView(Context context, @Nullable AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    protected void onDraw(Canvas canvas) {
+        super.onDraw(canvas);
+        if (myThread == null) {
+            myThread = new MyThread();
+            myThread.start();
+        } else {
+            drawSub(canvas);
+        }
+    }
+
+    /**
+     * 绘制处理
+     * 在子类中要实现的方法
+     *
+     * @param canvas
+     */
+    abstract void drawSub(Canvas canvas);
+
+    abstract void logic();
+
+    private boolean running = true;
+
+    class MyThread extends Thread {
+        public void run() {
+            super.run();
+            while (running) {
+                logic();
+                postInvalidate();//在线程中更新绘制方法
+                try {
+                    sleep(30);
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+    }
+
+    protected void onDetachedFromWindow() {
+        running = false;
+        super.onDetachedFromWindow();
+    }
+}

+ 119 - 0
baselib/src/main/java/com/mylove/baselib/widget/FullyGridLayoutManager.java

@@ -0,0 +1,119 @@
+package com.mylove.baselib.widget;
+
+import android.content.Context;
+import android.support.v7.widget.GridLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.view.View;
+import android.view.ViewGroup;
+
+/**
+ * @author myLove
+ * @time 2018-01-17 11:36
+ * @e-mail love@yanyi.red
+ * @overview 重写GridLayoutManager,解决gird样式下的recyclerView与scrollView的冲突
+ */
+
+public class FullyGridLayoutManager extends GridLayoutManager {
+    private int mwidth = 0;
+    private int mheight = 0;
+
+    public FullyGridLayoutManager(Context context, int spanCount) {
+        super(context, spanCount);
+    }
+
+    public FullyGridLayoutManager(Context context, int spanCount, int orientation, boolean reverseLayout) {
+        super(context, spanCount, orientation, reverseLayout);
+    }
+
+    private int[] mMeasuredDimension = new int[2];
+
+    public int getMwidth() {
+        return mwidth;
+    }
+
+    public void setMwidth(int mwidth) {
+        this.mwidth = mwidth;
+    }
+
+    public int getMheight() {
+        return mheight;
+    }
+
+    public void setMheight(int mheight) {
+        this.mheight = mheight;
+    }
+
+    @Override
+    public void onMeasure(RecyclerView.Recycler recycler, RecyclerView.State state, int widthSpec, int heightSpec) {
+        final int widthMode = View.MeasureSpec.getMode(widthSpec);
+        final int heightMode = View.MeasureSpec.getMode(heightSpec);
+        final int widthSize = View.MeasureSpec.getSize(widthSpec);
+        final int heightSize = View.MeasureSpec.getSize(heightSpec);
+
+        int width = 0;
+        int height = 0;
+        int count = getItemCount();
+        int span = getSpanCount();
+        for (int i = 0; i < count; i++) {
+            measureScrapChild(recycler, i,
+                    View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED),
+                    View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED),
+                    mMeasuredDimension);
+
+            if (getOrientation() == HORIZONTAL) {
+                if (i % span == 0) {
+                    width = width + mMeasuredDimension[0];
+                }
+                if (i == 0) {
+                    height = mMeasuredDimension[1];
+                }
+            } else {
+                if (i % span == 0) {
+                    height = height + mMeasuredDimension[1];
+                }
+                if (i == 0) {
+                    width = mMeasuredDimension[0];
+                }
+            }
+        }
+
+        switch (widthMode) {
+            case View.MeasureSpec.EXACTLY:
+                width = widthSize;
+            case View.MeasureSpec.AT_MOST:
+            case View.MeasureSpec.UNSPECIFIED:
+        }
+
+        switch (heightMode) {
+            case View.MeasureSpec.EXACTLY:
+                height = heightSize;
+            case View.MeasureSpec.AT_MOST:
+            case View.MeasureSpec.UNSPECIFIED:
+        }
+        setMheight(height);
+        setMwidth(width);
+        setMeasuredDimension(width, height);
+    }
+
+    private void measureScrapChild(RecyclerView.Recycler recycler, int position, int widthSpec,
+                                   int heightSpec, int[] measuredDimension) {
+        if (position < getItemCount()) {
+            try {
+                View view = recycler.getViewForPosition(0);//fix 动态添加时报IndexOutOfBoundsException
+                if (view != null) {
+                    RecyclerView.LayoutParams p = (RecyclerView.LayoutParams) view.getLayoutParams();
+                    int childWidthSpec = ViewGroup.getChildMeasureSpec(widthSpec,
+                            getPaddingLeft() + getPaddingRight(), p.width);
+                    int childHeightSpec = ViewGroup.getChildMeasureSpec(heightSpec,
+                            getPaddingTop() + getPaddingBottom(), p.height);
+                    view.measure(childWidthSpec, childHeightSpec);
+                    measuredDimension[0] = view.getMeasuredWidth() + p.leftMargin + p.rightMargin;
+                    measuredDimension[1] = view.getMeasuredHeight() + p.bottomMargin + p.topMargin;
+                    recycler.recycleView(view);
+                }
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+    }
+}

+ 98 - 0
baselib/src/main/java/com/mylove/baselib/widget/FullyLinearLayoutManager.java

@@ -0,0 +1,98 @@
+package com.mylove.baselib.widget;
+
+import android.content.Context;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.view.View;
+import android.view.ViewGroup;
+
+/**
+ * @author myLove
+ * @time 2018-01-17 11:36
+ * @e-mail love@yanyi.red
+ * @overview 重写LinearLayoutManager, 解决水平样式recyclerView与scrollView的冲突
+ */
+
+public class FullyLinearLayoutManager extends LinearLayoutManager {
+    private static final String TAG = FullyLinearLayoutManager.class.getSimpleName();
+
+    public FullyLinearLayoutManager(Context context) {
+        super(context);
+    }
+
+    public FullyLinearLayoutManager(Context context, int orientation, boolean reverseLayout) {
+        super(context, orientation, reverseLayout);
+    }
+
+    private int[] mMeasuredDimension = new int[2];
+
+    @Override
+    public void onMeasure(RecyclerView.Recycler recycler, RecyclerView.State state,
+                          int widthSpec, int heightSpec) {
+
+        final int widthMode = View.MeasureSpec.getMode(widthSpec);
+        final int heightMode = View.MeasureSpec.getMode(heightSpec);
+        final int widthSize = View.MeasureSpec.getSize(widthSpec);
+        final int heightSize = View.MeasureSpec.getSize(heightSpec);
+        int width = 0;
+        int height = 0;
+        for (int i = 0; i < getItemCount(); i++) {
+            measureScrapChild(recycler, i,
+                    View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED),
+                    View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED),
+                    mMeasuredDimension);
+
+            if (getOrientation() == HORIZONTAL) {
+                width = width + mMeasuredDimension[0];
+                if (i == 0) {
+                    height = mMeasuredDimension[1];
+                }
+            } else {
+                height = height + mMeasuredDimension[1];
+                if (i == 0) {
+                    width = mMeasuredDimension[0];
+                }
+            }
+        }
+        switch (widthMode) {
+            case View.MeasureSpec.EXACTLY:
+                width = widthSize;
+            case View.MeasureSpec.AT_MOST:
+            case View.MeasureSpec.UNSPECIFIED:
+        }
+
+        switch (heightMode) {
+            case View.MeasureSpec.EXACTLY:
+                height = heightSize;
+            case View.MeasureSpec.AT_MOST:
+            case View.MeasureSpec.UNSPECIFIED:
+        }
+
+        setMeasuredDimension(width, height);
+    }
+
+    private void measureScrapChild(RecyclerView.Recycler recycler, int position, int widthSpec,
+                                   int heightSpec, int[] measuredDimension) {
+        try {
+            View view = recycler.getViewForPosition(0);//fix 动态添加时报IndexOutOfBoundsException
+
+            if (view != null) {
+                RecyclerView.LayoutParams p = (RecyclerView.LayoutParams) view.getLayoutParams();
+
+                int childWidthSpec = ViewGroup.getChildMeasureSpec(widthSpec,
+                        getPaddingLeft() + getPaddingRight(), p.width);
+
+                int childHeightSpec = ViewGroup.getChildMeasureSpec(heightSpec,
+                        getPaddingTop() + getPaddingBottom(), p.height);
+
+                view.measure(childWidthSpec, childHeightSpec);
+                measuredDimension[0] = view.getMeasuredWidth() + p.leftMargin + p.rightMargin;
+                measuredDimension[1] = view.getMeasuredHeight() + p.bottomMargin + p.topMargin;
+                recycler.recycleView(view);
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        } finally {
+        }
+    }
+}

+ 77 - 0
baselib/src/main/java/com/mylove/baselib/widget/GridRecyclerView.java

@@ -0,0 +1,77 @@
+package com.mylove.baselib.widget;
+
+import android.content.Context;
+import android.support.v7.widget.GridLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.animation.GridLayoutAnimationController;
+
+/**
+ * @author myLove
+ * @time 2018-01-12 09:49
+ * @e-mail love@yanyi.red
+ * @overview 解决RecyclerView设置成grid的情况下添加动画问题
+ */
+
+public class GridRecyclerView extends RecyclerView {
+    /**
+     * @see View#View(Context)
+     */
+    public GridRecyclerView(Context context) {
+        super(context);
+    }
+
+    /**
+     * @see View#View(Context, AttributeSet)
+     */
+    public GridRecyclerView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    /**
+     * @see View#View(Context, AttributeSet, int)
+     */
+    public GridRecyclerView(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+    }
+
+    @Override
+    protected void attachLayoutAnimationParameters(View child, ViewGroup.LayoutParams params,
+                                                   int index, int count) {
+        final LayoutManager layoutManager = getLayoutManager();
+        if (getAdapter() != null && layoutManager instanceof GridLayoutManager) {
+
+            GridLayoutAnimationController.AnimationParameters animationParams =
+                    (GridLayoutAnimationController.AnimationParameters) params.layoutAnimationParameters;
+
+            if (animationParams == null) {
+                // If there are no animation parameters, create new once and attach them to
+                // the LayoutParams.
+                animationParams = new GridLayoutAnimationController.AnimationParameters();
+                params.layoutAnimationParameters = animationParams;
+            }
+
+            // Next we are updating the parameters
+
+            // Set the number of items in the RecyclerView and the index of this item
+            animationParams.count = count;
+            animationParams.index = index;
+
+            // Calculate the number of columns and rows in the grid
+            final int columns = ((GridLayoutManager) layoutManager).getSpanCount();
+            animationParams.columnsCount = columns;
+            animationParams.rowsCount = count / columns;
+
+            // Calculate the column/row position in the grid
+            final int invertedIndex = count - 1 - index;
+            animationParams.column = columns - 1 - (invertedIndex % columns);
+            animationParams.row = animationParams.rowsCount - 1 - invertedIndex / columns;
+
+        } else {
+            // Proceed as normal if using another type of LayoutManager
+            super.attachLayoutAnimationParameters(child, params, index, count);
+        }
+    }
+}

+ 60 - 0
baselib/src/main/java/com/mylove/baselib/widget/RecyclerViewAnimation.java

@@ -0,0 +1,60 @@
+package com.mylove.baselib.widget;
+
+import android.content.Context;
+import android.support.v7.widget.RecyclerView;
+import android.view.animation.AnimationUtils;
+import android.view.animation.LayoutAnimationController;
+
+import com.mylove.baselib.R;
+import com.mylove.baselib.adapter.CommonRecyclerAdapter;
+
+import java.util.List;
+
+/**
+ * @author myLove
+ * @date 2018-04-12 10:10
+ * @e-mail love@yanyi.red
+ * @overview RecyclerView动画
+ */
+public class RecyclerViewAnimation {
+
+    private int animationID;
+
+    private static RecyclerViewAnimation instance;
+
+    private RecyclerViewAnimation(int animationID) {
+        this.animationID = animationID;
+    }
+
+    public static RecyclerViewAnimation getInstance(int animationID) {
+        instance = new RecyclerViewAnimation(animationID);
+        return instance;
+    }
+
+    public static RecyclerViewAnimation getInstance() {
+        instance = new RecyclerViewAnimation(0);
+        return instance;
+    }
+
+    /**
+     * @param recyclerView 当前recyclerView
+     * @param list         集合
+     * @param <T>          数据类型
+     */
+    public <T> void runLayoutAnimation(RecyclerView recyclerView, List<T> list) {
+        Context context = recyclerView.getContext();
+        LayoutAnimationController controller;
+        if (animationID == 0) {
+            controller = AnimationUtils.loadLayoutAnimation(context, R.anim.layout_animation_fall_down);
+        } else {
+            controller = AnimationUtils.loadLayoutAnimation(context, animationID);
+        }
+        recyclerView.setLayoutAnimation(controller);
+        if (recyclerView.getAdapter().getClass().isInstance(CommonRecyclerAdapter.class)) {
+            ((CommonRecyclerAdapter<T>) recyclerView.getAdapter()).notifyDataSetChanged(list);
+        } else {
+            recyclerView.getAdapter().notifyDataSetChanged();
+        }
+        recyclerView.scheduleLayoutAnimation();
+    }
+}

+ 52 - 0
baselib/src/main/java/com/mylove/baselib/widget/ScrollForRecycler.java

@@ -0,0 +1,52 @@
+package com.mylove.baselib.widget;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.ViewConfiguration;
+import android.widget.ScrollView;
+
+/**
+ * @author myLove
+ * @time 2018-01-16 16:38
+ * @e-mail love@yanyi.red
+ * @overview
+ */
+
+public class ScrollForRecycler extends ScrollView {
+    private int downX;
+    private int downY;
+    private int mTouchSlop;
+
+    public ScrollForRecycler(Context context) {
+        super(context);
+        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
+    }
+
+    public ScrollForRecycler(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
+    }
+
+    public ScrollForRecycler(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
+    }
+
+    @Override
+    public boolean onInterceptTouchEvent(MotionEvent e) {
+        int action = e.getAction();
+        switch (action) {
+            case MotionEvent.ACTION_DOWN:
+                downX = (int) e.getRawX();
+                downY = (int) e.getRawY();
+                break;
+            case MotionEvent.ACTION_MOVE:
+                int moveY = (int) e.getRawY();
+                if (Math.abs(moveY - downY) > mTouchSlop) {
+                    return true;
+                }
+        }
+        return super.onInterceptTouchEvent(e);
+    }
+}

+ 40 - 0
baselib/src/main/java/com/mylove/baselib/widget/ScrollTextView.java

@@ -0,0 +1,40 @@
+package com.mylove.baselib.widget;
+
+import android.content.Context;
+import android.support.v7.widget.AppCompatTextView;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+
+/**
+ * @author myLove
+ * @time 2017/11/15 11:13
+ * @e-mail mylove.520.y@gmail.com
+ * @overview 横向自动滚动的文字
+ */
+
+public class ScrollTextView extends AppCompatTextView {
+    public ScrollTextView(Context context) {
+        super(context);
+        initView();
+    }
+
+    public ScrollTextView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        initView();
+    }
+
+    public ScrollTextView(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+        initView();
+    }
+
+    private void initView() {
+        setEllipsize(TextUtils.TruncateAt.MARQUEE);
+        setMarqueeRepeatLimit(-1);
+        setSingleLine(true);
+    }
+
+    public boolean isFocused() {
+        return true;
+    }
+}

+ 263 - 0
baselib/src/main/java/com/mylove/baselib/widget/TouchImageView.java

@@ -0,0 +1,263 @@
+package com.mylove.baselib.widget;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.graphics.Matrix;
+import android.graphics.PointF;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.MotionEvent;
+import android.view.ScaleGestureDetector;
+import android.widget.ImageView;
+
+/**
+ * @author myLove
+ * @time 2017/11/21 10:16
+ * @e-mail mylove.520.y@gmail.com
+ * @overview 图片手势旋转与缩放
+ */
+
+@SuppressLint("AppCompatCustomView")
+public class TouchImageView extends ImageView {
+    private static final float MIN_POINT_DISTINCT = 10F;
+    private Matrix matrix;
+    private Matrix cacheMatrix;  //缓存的matrix ,同时记录上一次滑动的位置
+    private float mPointDistinct = 1f;
+    private float mDegree;
+    private float rotate = 0F;// 旋转的角度
+
+    // We can be in one of these 3 states
+    float minScale = 1f;
+    float maxScale = 3f;
+    float[] m;
+
+
+    int viewWidth, viewHeight;
+    static final int CLICK = 3;
+    float saveScale = 1f;
+    protected float origWidth, origHeight;
+    int oldMeasuredWidth, oldMeasuredHeight;
+
+
+    ScaleGestureDetector mScaleDetector;
+
+    Context context;
+
+    enum Mode {
+        NONE, DOWN, MOVE
+    }
+
+    private Mode mode; //当前mode
+    private Context mContext;
+
+    private PointF mStart = new PointF();
+    private PointF mEnd = new PointF();
+
+    public TouchImageView(Context context) {
+        this(context, null);
+    }
+
+    public TouchImageView(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public TouchImageView(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+        this.mContext = context;
+        init();
+    }
+
+    private void init() {
+        matrix = new Matrix();
+        cacheMatrix = new Matrix();
+        mode = Mode.NONE;
+
+//        mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
+        m = new float[9];
+        setImageMatrix(matrix);
+        setScaleType(ScaleType.MATRIX);
+    }
+
+    private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
+        @Override
+        public boolean onScaleBegin(ScaleGestureDetector detector) {
+//            mode = ZOOM;
+            return true;
+        }
+
+        @Override
+        public boolean onScale(ScaleGestureDetector detector) {
+            float mScaleFactor = detector.getScaleFactor();
+            float origScale = saveScale;
+            saveScale *= mScaleFactor;
+            if (saveScale > maxScale) {
+                saveScale = maxScale;
+                mScaleFactor = maxScale / origScale;
+            } else if (saveScale < minScale) {
+                saveScale = minScale;
+                mScaleFactor = minScale / origScale;
+            }
+
+            if (origWidth * saveScale <= viewWidth || origHeight * saveScale <= viewHeight)
+                matrix.postScale(mScaleFactor, mScaleFactor, viewWidth / 2, viewHeight / 2);
+            else
+                matrix.postScale(mScaleFactor, mScaleFactor, detector.getFocusX(), detector.getFocusY());
+
+            fixTrans();
+            return true;
+        }
+    }
+
+    @SuppressLint("ClickableViewAccessibility")
+    @Override
+    public boolean onTouchEvent(MotionEvent event) {
+        switch (event.getAction() & MotionEvent.ACTION_MASK) {
+            case MotionEvent.ACTION_DOWN:
+                cacheMatrix.set(matrix); //先拷贝一份到缓存
+                mode = Mode.DOWN;
+                mStart.set(event.getX(), event.getY());
+                break;
+            case MotionEvent.ACTION_POINTER_DOWN:
+                mPointDistinct = calSpacing(event);
+                if (mPointDistinct > MIN_POINT_DISTINCT) {
+                    cacheMatrix.set(matrix); //先拷贝一份到缓存
+                    calPoint(mEnd, event);
+                    mode = Mode.MOVE;
+                }
+                mDegree = calRotation(event);
+                break;
+            case MotionEvent.ACTION_MOVE:
+                //单点触控的时候
+                if (mode == Mode.DOWN) {
+                    matrix.set(cacheMatrix);
+                    matrix.postTranslate(event.getX() - mStart.x, event.getY() - mStart.y);
+                } else if (mode == Mode.MOVE && event.getPointerCount() == 2) {  //只能2只手
+                    matrix.set(cacheMatrix);
+                    float move = calSpacing(event);
+                    if (move > MIN_POINT_DISTINCT) {
+                        float scale = move / mPointDistinct;
+                        matrix.postScale(scale, scale, mEnd.x, mEnd.y);
+
+                    }
+                    rotate = calRotation(event);
+                    float r = rotate - mDegree;
+                    matrix.postRotate(r, getMeasuredWidth() / 2, getMeasuredHeight() / 2);
+                }
+
+                break;
+            case MotionEvent.ACTION_UP:
+            case MotionEvent.ACTION_POINTER_UP:
+            case MotionEvent.ACTION_CANCEL:
+                mode = Mode.NONE;
+                break;
+
+        }
+
+        setImageMatrix(matrix);
+        return true;
+    }
+
+
+    private float calSpacing(MotionEvent event) {
+        float x = event.getX(0) - event.getX(1);
+        float y = event.getY(0) - event.getY(1);
+        return (float) Math.sqrt(x * x + y * y);
+    }
+
+    private void calPoint(PointF point, MotionEvent event) {
+        float x = event.getX(0) + event.getX(1);
+        float y = event.getY(0) + event.getY(1);
+        point.set(x / 2, y / 2);
+    }
+
+    private float calRotation(MotionEvent event) {
+        double deltaX = (event.getX(0) - event.getX(1));
+        double deltaY = (event.getY(0) - event.getY(1));
+        double radius = Math.atan2(deltaY, deltaX);
+        return (float) Math.toDegrees(radius);
+    }
+
+    public void reset() {
+        matrix.reset();
+        cacheMatrix.reset();
+        setImageMatrix(matrix);
+        invalidate();
+    }
+
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+        viewWidth = MeasureSpec.getSize(widthMeasureSpec);
+        viewHeight = MeasureSpec.getSize(heightMeasureSpec);
+
+        //
+        // Rescales image on rotation
+        //
+        if (oldMeasuredHeight == viewWidth && oldMeasuredHeight == viewHeight
+                || viewWidth == 0 || viewHeight == 0)
+            return;
+        oldMeasuredHeight = viewHeight;
+        oldMeasuredWidth = viewWidth;
+
+        if (saveScale == 1) {
+            //Fit to screen.
+            float scale;
+
+            Drawable drawable = getDrawable();
+            if (drawable == null || drawable.getIntrinsicWidth() == 0 || drawable.getIntrinsicHeight() == 0)
+                return;
+            int bmWidth = drawable.getIntrinsicWidth();
+            int bmHeight = drawable.getIntrinsicHeight();
+
+            Log.d("bmSize", "bmWidth: " + bmWidth + " bmHeight : " + bmHeight);
+
+            float scaleX = (float) viewWidth / (float) bmWidth;
+            float scaleY = (float) viewHeight / (float) bmHeight;
+            scale = Math.min(scaleX, scaleY);
+            matrix.setScale(scale, scale);
+
+            // Center the image
+            float redundantYSpace = (float) viewHeight - (scale * (float) bmHeight);
+            float redundantXSpace = (float) viewWidth - (scale * (float) bmWidth);
+            redundantYSpace /= (float) 2;
+            redundantXSpace /= (float) 2;
+
+            matrix.postTranslate(redundantXSpace, redundantYSpace);
+
+            origWidth = viewWidth - 2 * redundantXSpace;
+            origHeight = viewHeight - 2 * redundantYSpace;
+            setImageMatrix(matrix);
+        }
+        fixTrans();
+    }
+
+    void fixTrans() {
+        matrix.getValues(m);
+        float transX = m[Matrix.MTRANS_X];
+        float transY = m[Matrix.MTRANS_Y];
+
+        float fixTransX = getFixTrans(transX, viewWidth, origWidth * saveScale);
+        float fixTransY = getFixTrans(transY, viewHeight, origHeight * saveScale);
+
+        if (fixTransX != 0 || fixTransY != 0)
+            matrix.postTranslate(fixTransX, fixTransY);
+    }
+
+    float getFixTrans(float trans, float viewSize, float contentSize) {
+        float minTrans, maxTrans;
+
+        if (contentSize <= viewSize) {
+            minTrans = 0;
+            maxTrans = viewSize - contentSize;
+        } else {
+            minTrans = viewSize - contentSize;
+            maxTrans = 0;
+        }
+
+        if (trans < minTrans)
+            return -trans + minTrans;
+        if (trans > maxTrans)
+            return -trans + maxTrans;
+        return 0;
+    }
+}

+ 96 - 0
baselib/src/main/java/com/mylove/baselib/widget/VerticalScrollLayout.java

@@ -0,0 +1,96 @@
+package com.mylove.baselib.widget;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.database.DataSetObserver;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.animation.Animation;
+import android.view.animation.AnimationUtils;
+import android.widget.ListAdapter;
+import android.widget.ViewFlipper;
+
+import com.mylove.baselib.R;
+
+/**
+ * @author myLove
+ * @time 2017/11/15 11:21
+ * @e-mail mylove.520.y@gmail.com
+ * @overview 自动滚动布局
+ */
+
+public class VerticalScrollLayout extends ViewFlipper {
+    private ListAdapter mAdapter;
+    private int interval = 2000;
+    /**
+     * 动画时间
+     */
+    private int animDuration = 500;
+
+    public VerticalScrollLayout(Context context) {
+        this(context, null);
+    }
+
+    public VerticalScrollLayout(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        init(attrs);
+    }
+
+    private void init(AttributeSet attrs) {
+        TypedArray array = getContext().obtainStyledAttributes(attrs, R.styleable.VerticalScrollLayout);
+        animDuration = array.getInt(R.styleable.VerticalScrollLayout_VAnimDuration, animDuration);
+        boolean isSetAnimDuration = array.getBoolean(R.styleable.VerticalScrollLayout_VIsCusDuration, false);
+        interval = array.getInt(R.styleable.VerticalScrollLayout_VSleepTime, interval);
+        array.recycle();
+        setFlipInterval(interval);
+        Animation animIn = AnimationUtils.loadAnimation(getContext(), R.anim.anim_scroll_in);
+        Animation animOut = AnimationUtils.loadAnimation(getContext(), R.anim.anim_scroll_out);
+        if (isSetAnimDuration) {
+            animIn.setDuration(animDuration);
+            animOut.setDuration(animDuration);
+        }
+        setInAnimation(animIn);
+        setOutAnimation(animOut);
+    }
+
+    private DataSetObserver mDataObserver = new DataSetObserver() {
+
+        @Override
+        public void onChanged() {
+            setupChildren();
+        }
+
+        @Override
+        public void onInvalidated() {
+            setupChildren();
+        }
+
+    };
+
+    public void setAdapter(ListAdapter adapter) {
+        if (mAdapter != null) {
+            mAdapter.unregisterDataSetObserver(mDataObserver);
+        }
+
+        mAdapter = adapter;
+
+        if (mAdapter != null) {
+            mAdapter.registerDataSetObserver(mDataObserver);
+        }
+        setupChildren();
+    }
+
+    private void setupChildren() {
+        if (mAdapter == null || mAdapter.getCount() == 0) return;
+        removeAllViews();
+        for (int i = 0; i < mAdapter.getCount(); i++) {
+            View child = mAdapter.getView(i, null, this);
+            if (child == null) {
+                throw new NullPointerException("View can't be null");
+            } else {
+                addView(child);
+            }
+        }
+        startFlipping();
+    }
+}

+ 283 - 0
baselib/src/main/java/com/mylove/baselib/widget/VerticalScrollTextView.java

@@ -0,0 +1,283 @@
+package com.mylove.baselib.widget;
+
+import android.animation.ObjectAnimator;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Color;
+import android.os.Handler;
+import android.os.Message;
+import android.support.annotation.IntRange;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import android.util.TypedValue;
+import android.view.ViewGroup;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+
+import com.mylove.baselib.R;
+
+import java.lang.ref.WeakReference;
+import java.util.List;
+
+/**
+ * @author myLove
+ * @time 2017/11/15 11:16
+ * @e-mail mylove.520.y@gmail.com
+ * @overview 竖直方向自动滚动文字
+ */
+
+public class VerticalScrollTextView extends RelativeLayout {
+    /**
+     * 默认轮播时间间隔:3s
+     */
+    private final static int SLEEP_TIME = 3000;
+
+    /**
+     * 默认动画执行时间:1s
+     */
+    private final static int ANIM_DURATION = 1000;
+
+    /**
+     * 轮播时间间隔
+     */
+    private int sleepTime = SLEEP_TIME;
+
+    /**
+     * 动画执行时间
+     */
+    private int animDuration = ANIM_DURATION;
+    private boolean mSingleLine;
+    private int mTextColor;
+    private int mTextSize;
+    /**
+     * 滚动方向
+     */
+    private int scrollOrientation;
+
+    private List<String> mDataSource;
+
+    private TextView mTvContentTop;
+
+    private TextView mTvContentBottom;
+
+    /**
+     * 是否运行轮播图
+     */
+    protected boolean mIsRun;
+
+    /**
+     * 自动轮播使用的handler
+     */
+    private Handler mHandler;
+
+    /**
+     * 当前轮播的项索引
+     */
+    private int mCurrentItemIndex;
+    private int heightSize;
+
+    public VerticalScrollTextView(Context context) {
+        super(context);
+
+        init(context);
+    }
+
+    public VerticalScrollTextView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+
+        TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.VerticalScrollTextView);
+        sleepTime = array.getInt(R.styleable.VerticalScrollTextView_sleepTime, SLEEP_TIME);
+        animDuration = array.getInt(R.styleable.VerticalScrollTextView_animDuration, ANIM_DURATION);
+        scrollOrientation = array.getInt(R.styleable.VerticalScrollTextView_scrollOrientation, 0);
+        mTextSize = array.getDimensionPixelSize(R.styleable.VerticalScrollTextView_textSize,
+                (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
+                        12, getResources().getDisplayMetrics()));
+        mTextColor = array.getColor(R.styleable.VerticalScrollTextView_textColor, Color.BLACK);
+        mSingleLine = array.getBoolean(R.styleable.VerticalScrollTextView_singleLine, true);
+        array.recycle();
+
+        init(context);
+    }
+
+    private void init(Context context) {
+        initTextView(context);
+        RelativeLayout.LayoutParams lp1 = new RelativeLayout.LayoutParams
+                (ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
+        lp1.addRule(RelativeLayout.CENTER_VERTICAL);
+
+        addView(mTvContentTop, lp1);
+        addView(mTvContentBottom, lp1);
+
+        mHandler = new SliderScrollHandler(this);
+    }
+
+    private void initTextView(Context context) {
+        mTvContentTop = new TextView(context);
+        mTvContentTop.setTextColor(mTextColor);
+        mTvContentTop.setTextSize(TypedValue.COMPLEX_UNIT_PX, mTextSize);
+        mTvContentTop.setSingleLine(mSingleLine);
+
+        mTvContentBottom = new TextView(context);
+        mTvContentBottom.setTextColor(mTextColor);
+        mTvContentBottom.setTextSize(TypedValue.COMPLEX_UNIT_PX, mTextSize);
+        mTvContentBottom.setSingleLine(mSingleLine);
+        if (mSingleLine) {
+            mTvContentTop.setEllipsize(TextUtils.TruncateAt.END);
+
+            mTvContentBottom.setEllipsize(TextUtils.TruncateAt.END);
+        }
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+        heightSize = getMeasuredHeight();
+    }
+
+    /**
+     * 重置
+     */
+    private void resetData() {
+        if (mDataSource == null || mDataSource.size() == 0) {
+            return;
+        }
+
+        String normal = mDataSource.get(0);
+
+        if (normal != null) {
+            mTvContentTop.setText(normal);
+        }
+    }
+
+    /**
+     * 滚动
+     */
+    private void autoSlider() {
+        if (mDataSource == null || mDataSource.size() < 2) {
+            return;
+        }
+
+        String normal = mDataSource.get(mCurrentItemIndex);
+
+        if (normal != null) {
+            mTvContentTop.setText(normal);
+        }
+
+        if (mCurrentItemIndex == mDataSource.size() - 1) {
+            mCurrentItemIndex = 0;
+        } else {
+            mCurrentItemIndex = mCurrentItemIndex + 1;
+        }
+
+        String next = mDataSource.get(mCurrentItemIndex);
+
+        if (next != null) {
+            mTvContentBottom.setText(next);
+        }
+        startTopAnim();
+        startBottomAnim();
+    }
+
+    private void startTopAnim() {
+        int value = -heightSize;  //默认朝上
+        if (scrollOrientation != 0) {
+            //朝下
+            value = heightSize;
+        }
+
+        ObjectAnimator.ofFloat(mTvContentTop, "translationY", 0F, value)
+                // 设置执行时间(1000ms)
+                .setDuration(animDuration)
+                // 开始动画
+                .start();
+    }
+
+    private void startBottomAnim() {
+        int value = heightSize;  //默认朝上
+        if (scrollOrientation != 0) {
+            //朝下
+            value = -heightSize;
+        }
+
+        ObjectAnimator.ofFloat(mTvContentBottom, "translationY", value, 0F)
+                // 设置执行时间(1000ms)
+                .setDuration(animDuration)
+                // 开始动画
+                .start();
+    }
+
+    /**
+     * 轮播滚动Handler
+     */
+    private static class SliderScrollHandler extends Handler {
+        private WeakReference<VerticalScrollTextView> mSliderView;
+
+        SliderScrollHandler(VerticalScrollTextView sliderView) {
+            mSliderView = new WeakReference<>(sliderView);
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            super.handleMessage(msg);
+            switch (msg.what) {
+                case 0:
+                    VerticalScrollTextView sliderView = mSliderView.get();
+                    if (sliderView != null && mSliderView.get().mIsRun) {
+                        sliderView.autoSlider();
+                        //重复
+                        this.sendEmptyMessageDelayed(0, mSliderView.get().sleepTime);
+                    }
+                    break;
+            }
+        }
+    }
+
+    public void setDataSource(List<String> dataSource) {
+        this.mDataSource = dataSource;
+        mCurrentItemIndex = 0;
+        resetData();
+    }
+
+    /**
+     * Description: 开始轮播
+     */
+    public void startPlay() {
+        if (mHandler != null) {
+            mIsRun = true;
+            mHandler.removeCallbacksAndMessages(null);
+            mHandler.sendEmptyMessageDelayed(0, sleepTime);
+        }
+    }
+
+    /**
+     * Description: 暂停轮播
+     */
+    public void stopPlay() {
+        if (mHandler != null) {
+            mIsRun = false;
+            mHandler.removeCallbacksAndMessages(null);
+        }
+    }
+
+    /**
+     * 设置轮播的间隔时间
+     *
+     * @param sleepTime 单位:毫秒
+     */
+    public void setSleepTime(int sleepTime) {
+        this.sleepTime = sleepTime;
+    }
+
+    /**
+     * 设置动画执行时间
+     *
+     * @param animDuration 单位:毫秒
+     */
+    public void setAnimDuration(int animDuration) {
+        this.animDuration = animDuration;
+    }
+
+    public void setScrollOrientation(@IntRange(from = 0, to = 1) int scrollOrientation) {
+        this.scrollOrientation = scrollOrientation;
+    }
+}

+ 11 - 0
baselib/src/main/res/anim/anim_scroll_in.xml

@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+    <translate
+        android:duration="300"
+        android:fromYDelta="100%p"
+        android:toYDelta="0"/>
+    <alpha
+        android:duration="500"
+        android:fromAlpha="0.0"
+        android:toAlpha="1.0"/>
+</set>

+ 11 - 0
baselib/src/main/res/anim/anim_scroll_out.xml

@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+    <translate
+        android:duration="400"
+        android:fromYDelta="0"
+        android:toYDelta="-100%p"/>
+    <alpha
+        android:duration="500"
+        android:fromAlpha="1.0"
+        android:toAlpha="0.0"/>
+</set>

+ 10 - 0
baselib/src/main/res/anim/grid_layout_animation_from_bottom.xml

@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<gridLayoutAnimation
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:animation="@anim/item_animation_from_bottom"
+    android:animationOrder="normal"
+    android:startOffset="700"
+    android:columnDelay="15%"
+    android:rowDelay="15%"
+    android:direction="top_to_bottom|left_to_right"
+    />

+ 24 - 0
baselib/src/main/res/anim/item_animation_fall_down.xml

@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+    android:duration="@integer/anim_duration_medium">
+    <!--在动画开始前,把view向下移动自身高度的20%,然后让他下降到自己最终的位置。-->
+    <translate
+        android:fromYDelta="-20%"
+        android:interpolator="@android:anim/decelerate_interpolator"
+        android:toYDelta="0" />
+    <!--从完全不可见慢慢过渡到完全可见。-->
+    <alpha
+        android:fromAlpha="0"
+        android:interpolator="@android:anim/decelerate_interpolator"
+        android:toAlpha="1" />
+    <!--放大到105%,然后缩小的实际大小-->
+    <scale
+        android:fromXScale="105%"
+        android:fromYScale="105%"
+        android:interpolator="@android:anim/decelerate_interpolator"
+        android:pivotX="50%"
+        android:pivotY="50%"
+        android:toXScale="100%"
+        android:toYScale="100%" />
+
+</set>

+ 17 - 0
baselib/src/main/res/anim/item_animation_from_bottom.xml

@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+     android:duration="@integer/anim_duration_long">
+
+    <translate
+        android:interpolator="@android:anim/accelerate_decelerate_interpolator"
+        android:fromYDelta="50%p"
+        android:toYDelta="0"
+        />
+
+    <alpha
+        android:fromAlpha="0"
+        android:toAlpha="1"
+        android:interpolator="@android:anim/accelerate_decelerate_interpolator"
+        />
+
+</set>

+ 8 - 0
baselib/src/main/res/anim/layout_animation_fall_down.xml

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
+    android:animation="@anim/item_animation_fall_down"
+    android:animationOrder="normal"
+    android:delay="15%" />
+    <!--定义item运行的动画(资源)。-->
+    <!--动画顺序 Normal是按照布局的自然顺序( vertical: top to bottom, horizontal: left to right),Reverse跟Normal是相反的,Random则按照随即的顺序-->
+    <!--为每个item动画添加一个延时-->

+ 17 - 0
baselib/src/main/res/layout/comm_refresh.xml

@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical">
+
+    <android.support.v4.widget.SwipeRefreshLayout
+        android:id="@+id/swipe_refresh"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
+
+        <android.support.v7.widget.RecyclerView
+            android:id="@+id/recycler"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent" />
+    </android.support.v4.widget.SwipeRefreshLayout>
+</LinearLayout>

+ 9 - 0
baselib/src/main/res/layout/comm_toolbar.xml

@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:id="@+id/toolbar"
+    android:layout_width="match_parent"
+    android:layout_height="?android:attr/actionBarSize"
+    android:background="?attr/colorPrimary"
+    app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
+    app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" />

+ 42 - 0
baselib/src/main/res/layout/item_foot.xml

@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/foot_linear"
+    android:layout_width="match_parent"
+    android:layout_height="@dimen/length35"
+    android:gravity="center"
+    android:orientation="vertical">
+
+    <LinearLayout
+        android:id="@+id/foot_loading"
+        android:layout_width="match_parent"
+        android:layout_height="@dimen/length35"
+        android:gravity="center"
+        android:orientation="horizontal">
+
+        <ProgressBar
+            android:id="@+id/progressBar"
+            style="?android:attr/progressBarStyleSmall"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center"
+            android:layout_marginRight="@dimen/padding5" />
+
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center"
+            android:text="@string/loading"
+            android:textColor="@color/comm_gray"
+            android:textSize="@dimen/size14" />
+    </LinearLayout>
+
+    <TextView
+        android:id="@+id/foot_prompt"
+        android:layout_width="match_parent"
+        android:layout_height="@dimen/length35"
+        android:gravity="center"
+        android:text="@string/isBottom"
+        android:textColor="@color/comm_gray"
+        android:textSize="@dimen/size14"
+        android:visibility="gone" />
+</LinearLayout>

BIN
baselib/src/main/res/mipmap-xxxhdpi/shuju_no.png


+ 45 - 0
baselib/src/main/res/values-sw240dp-land/dimens.xml

@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <dimen name="title_height">33.75dp</dimen>
+    <dimen name="drawer_width">180.0dp</dimen>
+    <dimen name="padding1">0.75dp</dimen>
+    <dimen name="padding2">1.5dp</dimen>
+    <dimen name="padding3">2.25dp</dimen>
+    <dimen name="padding5">3.75dp</dimen>
+    <dimen name="padding7">5.25dp</dimen>
+    <dimen name="padding8">6.0dp</dimen>
+    <dimen name="padding10">7.5dp</dimen>
+    <dimen name="padding13">9.75dp</dimen>
+    <dimen name="padding15">11.25dp</dimen>
+    <dimen name="padding20">15.0dp</dimen>
+    <dimen name="padding30">22.5dp</dimen>
+    <dimen name="height5">3.75dp</dimen>
+    <dimen name="length16">12.0dp</dimen>
+    <dimen name="length20">15.0dp</dimen>
+    <dimen name="length25">18.75dp</dimen>
+    <dimen name="length30">22.5dp</dimen>
+    <dimen name="length35">26.25dp</dimen>
+    <dimen name="length40">30.0dp</dimen>
+    <dimen name="length50">37.5dp</dimen>
+    <dimen name="length60">45.0dp</dimen>
+    <dimen name="length70">52.5dp</dimen>
+    <dimen name="length80">60.0dp</dimen>
+    <dimen name="length100">75.0dp</dimen>
+    <dimen name="length120">90.0dp</dimen>
+    <dimen name="length150">112.5dp</dimen>
+    <dimen name="length160">120.0dp</dimen>
+    <dimen name="length180">135.0dp</dimen>
+    <dimen name="length240">180.0dp</dimen>
+    <dimen name="size8">6.0sp</dimen>
+    <dimen name="size10">7.5sp</dimen>
+    <dimen name="size12">9.0sp</dimen>
+    <dimen name="size13">9.75sp</dimen>
+    <dimen name="size14">10.5sp</dimen>
+    <dimen name="size15">11.25sp</dimen>
+    <dimen name="size16">12.0sp</dimen>
+    <dimen name="size18">13.5sp</dimen>
+    <dimen name="size20">15.0sp</dimen>
+    <dimen name="size24">18.0sp</dimen>
+    <dimen name="footer_height">45.0dp</dimen>
+    <dimen name="img_length">30.0dp</dimen>
+</resources>

+ 45 - 0
baselib/src/main/res/values-sw480dp-land/dimens.xml

@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <dimen name="title_height">67.5dp</dimen>
+    <dimen name="drawer_width">360.0dp</dimen>
+    <dimen name="padding1">1.5dp</dimen>
+    <dimen name="padding2">3.0dp</dimen>
+    <dimen name="padding3">4.5dp</dimen>
+    <dimen name="padding5">7.5dp</dimen>
+    <dimen name="padding7">10.5dp</dimen>
+    <dimen name="padding8">12.0dp</dimen>
+    <dimen name="padding10">15.0dp</dimen>
+    <dimen name="padding13">19.5dp</dimen>
+    <dimen name="padding15">22.5dp</dimen>
+    <dimen name="padding20">30.0dp</dimen>
+    <dimen name="padding30">45.0dp</dimen>
+    <dimen name="height5">7.5dp</dimen>
+    <dimen name="length16">24.0dp</dimen>
+    <dimen name="length20">30.0dp</dimen>
+    <dimen name="length25">37.5dp</dimen>
+    <dimen name="length30">45.0dp</dimen>
+    <dimen name="length35">52.5dp</dimen>
+    <dimen name="length40">60.0dp</dimen>
+    <dimen name="length50">75.0dp</dimen>
+    <dimen name="length60">90.0dp</dimen>
+    <dimen name="length70">105.0dp</dimen>
+    <dimen name="length80">120.0dp</dimen>
+    <dimen name="length100">150.0dp</dimen>
+    <dimen name="length120">180.0dp</dimen>
+    <dimen name="length150">225.0dp</dimen>
+    <dimen name="length160">240.0dp</dimen>
+    <dimen name="length180">270.0dp</dimen>
+    <dimen name="length240">360.0dp</dimen>
+    <dimen name="size8">12.0sp</dimen>
+    <dimen name="size10">15.0sp</dimen>
+    <dimen name="size12">18.0sp</dimen>
+    <dimen name="size13">19.5sp</dimen>
+    <dimen name="size14">21.0sp</dimen>
+    <dimen name="size15">22.5sp</dimen>
+    <dimen name="size16">24.0sp</dimen>
+    <dimen name="size18">27.0sp</dimen>
+    <dimen name="size20">30.0sp</dimen>
+    <dimen name="size24">36.0sp</dimen>
+    <dimen name="footer_height">90.0dp</dimen>
+    <dimen name="img_length">60.0dp</dimen>
+</resources>

+ 45 - 0
baselib/src/main/res/values-sw600dp-land/dimens.xml

@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <dimen name="title_height">84.15dp</dimen>
+    <dimen name="drawer_width">448.8dp</dimen>
+    <dimen name="padding1">1.87dp</dimen>
+    <dimen name="padding2">3.74dp</dimen>
+    <dimen name="padding3">5.61dp</dimen>
+    <dimen name="padding5">9.350000000000001dp</dimen>
+    <dimen name="padding7">13.09dp</dimen>
+    <dimen name="padding8">14.96dp</dimen>
+    <dimen name="padding10">18.700000000000003dp</dimen>
+    <dimen name="padding13">24.310000000000002dp</dimen>
+    <dimen name="padding15">28.05dp</dimen>
+    <dimen name="padding20">37.400000000000006dp</dimen>
+    <dimen name="padding30">56.1dp</dimen>
+    <dimen name="height5">9.350000000000001dp</dimen>
+    <dimen name="length16">29.92dp</dimen>
+    <dimen name="length20">37.400000000000006dp</dimen>
+    <dimen name="length25">46.75dp</dimen>
+    <dimen name="length30">56.1dp</dimen>
+    <dimen name="length35">65.45dp</dimen>
+    <dimen name="length40">74.80000000000001dp</dimen>
+    <dimen name="length50">93.5dp</dimen>
+    <dimen name="length60">112.2dp</dimen>
+    <dimen name="length70">130.9dp</dimen>
+    <dimen name="length80">149.60000000000002dp</dimen>
+    <dimen name="length100">187.0dp</dimen>
+    <dimen name="length120">224.4dp</dimen>
+    <dimen name="length150">280.5dp</dimen>
+    <dimen name="length160">299.20000000000005dp</dimen>
+    <dimen name="length180">336.6dp</dimen>
+    <dimen name="length240">448.8dp</dimen>
+    <dimen name="size8">14.96sp</dimen>
+    <dimen name="size10">18.700000000000003sp</dimen>
+    <dimen name="size12">22.44sp</dimen>
+    <dimen name="size13">24.310000000000002sp</dimen>
+    <dimen name="size14">26.18sp</dimen>
+    <dimen name="size15">28.05sp</dimen>
+    <dimen name="size16">29.92sp</dimen>
+    <dimen name="size18">33.660000000000004sp</dimen>
+    <dimen name="size20">37.400000000000006sp</dimen>
+    <dimen name="size24">44.88sp</dimen>
+    <dimen name="footer_height">112.2dp</dimen>
+    <dimen name="img_length">74.80000000000001dp</dimen>
+</resources>

+ 45 - 0
baselib/src/main/res/values-sw720dp-land/dimens.xml

@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <dimen name="title_height">101.25dp</dimen>
+    <dimen name="drawer_width">540.0dp</dimen>
+    <dimen name="padding1">2.25dp</dimen>
+    <dimen name="padding2">4.5dp</dimen>
+    <dimen name="padding3">6.75dp</dimen>
+    <dimen name="padding5">11.25dp</dimen>
+    <dimen name="padding7">15.75dp</dimen>
+    <dimen name="padding8">18.0dp</dimen>
+    <dimen name="padding10">22.5dp</dimen>
+    <dimen name="padding13">29.25dp</dimen>
+    <dimen name="padding15">33.75dp</dimen>
+    <dimen name="padding20">45.0dp</dimen>
+    <dimen name="padding30">67.5dp</dimen>
+    <dimen name="height5">11.25dp</dimen>
+    <dimen name="length16">36.0dp</dimen>
+    <dimen name="length20">45.0dp</dimen>
+    <dimen name="length25">56.25dp</dimen>
+    <dimen name="length30">67.5dp</dimen>
+    <dimen name="length35">78.75dp</dimen>
+    <dimen name="length40">90.0dp</dimen>
+    <dimen name="length50">112.5dp</dimen>
+    <dimen name="length60">135.0dp</dimen>
+    <dimen name="length70">157.5dp</dimen>
+    <dimen name="length80">180.0dp</dimen>
+    <dimen name="length100">225.0dp</dimen>
+    <dimen name="length120">270.0dp</dimen>
+    <dimen name="length150">337.5dp</dimen>
+    <dimen name="length160">360.0dp</dimen>
+    <dimen name="length180">405.0dp</dimen>
+    <dimen name="length240">540.0dp</dimen>
+    <dimen name="size8">18.0sp</dimen>
+    <dimen name="size10">22.5sp</dimen>
+    <dimen name="size12">27.0sp</dimen>
+    <dimen name="size13">29.25sp</dimen>
+    <dimen name="size14">31.5sp</dimen>
+    <dimen name="size15">33.75sp</dimen>
+    <dimen name="size16">36.0sp</dimen>
+    <dimen name="size18">40.5sp</dimen>
+    <dimen name="size20">45.0sp</dimen>
+    <dimen name="size24">54.0sp</dimen>
+    <dimen name="footer_height">135.0dp</dimen>
+    <dimen name="img_length">90.0dp</dimen>
+</resources>

+ 45 - 0
baselib/src/main/res/values-sw800dp-land/dimens.xml

@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <dimen name="title_height">112.5dp</dimen>
+    <dimen name="drawer_width">600.0dp</dimen>
+    <dimen name="padding1">2.5dp</dimen>
+    <dimen name="padding2">5.0dp</dimen>
+    <dimen name="padding3">7.5dp</dimen>
+    <dimen name="padding5">12.5dp</dimen>
+    <dimen name="padding7">17.5dp</dimen>
+    <dimen name="padding8">20.0dp</dimen>
+    <dimen name="padding10">25.0dp</dimen>
+    <dimen name="padding13">32.5dp</dimen>
+    <dimen name="padding15">37.5dp</dimen>
+    <dimen name="padding20">50.0dp</dimen>
+    <dimen name="padding30">75.0dp</dimen>
+    <dimen name="height5">12.5dp</dimen>
+    <dimen name="length16">40.0dp</dimen>
+    <dimen name="length20">50.0dp</dimen>
+    <dimen name="length25">62.5dp</dimen>
+    <dimen name="length30">75.0dp</dimen>
+    <dimen name="length35">87.5dp</dimen>
+    <dimen name="length40">100.0dp</dimen>
+    <dimen name="length50">125.0dp</dimen>
+    <dimen name="length60">150.0dp</dimen>
+    <dimen name="length70">175.0dp</dimen>
+    <dimen name="length80">200.0dp</dimen>
+    <dimen name="length100">250.0dp</dimen>
+    <dimen name="length120">300.0dp</dimen>
+    <dimen name="length150">375.0dp</dimen>
+    <dimen name="length160">400.0dp</dimen>
+    <dimen name="length180">450.0dp</dimen>
+    <dimen name="length240">600.0dp</dimen>
+    <dimen name="size8">20.0sp</dimen>
+    <dimen name="size10">25.0sp</dimen>
+    <dimen name="size12">30.0sp</dimen>
+    <dimen name="size13">32.5sp</dimen>
+    <dimen name="size14">35.0sp</dimen>
+    <dimen name="size15">37.5sp</dimen>
+    <dimen name="size16">40.0sp</dimen>
+    <dimen name="size18">45.0sp</dimen>
+    <dimen name="size20">50.0sp</dimen>
+    <dimen name="size24">60.0sp</dimen>
+    <dimen name="footer_height">150.0dp</dimen>
+    <dimen name="img_length">100.0dp</dimen>
+</resources>

+ 45 - 0
baselib/src/main/res/values-w820dp/dimens.xml

@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <dimen name="title_height">115.2dp</dimen>
+    <dimen name="drawer_width">614.4dp</dimen>
+    <dimen name="padding1">2.56dp</dimen>
+    <dimen name="padding2">5.12dp</dimen>
+    <dimen name="padding3">7.68dp</dimen>
+    <dimen name="padding5">12.8dp</dimen>
+    <dimen name="padding7">17.92dp</dimen>
+    <dimen name="padding8">20.48dp</dimen>
+    <dimen name="padding10">25.6dp</dimen>
+    <dimen name="padding13">33.28dp</dimen>
+    <dimen name="padding15">38.4dp</dimen>
+    <dimen name="padding20">51.2dp</dimen>
+    <dimen name="padding30">76.8dp</dimen>
+    <dimen name="height5">12.8dp</dimen>
+    <dimen name="length16">40.96dp</dimen>
+    <dimen name="length20">51.2dp</dimen>
+    <dimen name="length25">64.0dp</dimen>
+    <dimen name="length30">76.8dp</dimen>
+    <dimen name="length35">89.60000000000001dp</dimen>
+    <dimen name="length40">102.4dp</dimen>
+    <dimen name="length50">128.0dp</dimen>
+    <dimen name="length60">153.6dp</dimen>
+    <dimen name="length70">179.20000000000002dp</dimen>
+    <dimen name="length80">204.8dp</dimen>
+    <dimen name="length100">256.0dp</dimen>
+    <dimen name="length120">307.2dp</dimen>
+    <dimen name="length150">384.0dp</dimen>
+    <dimen name="length160">409.6dp</dimen>
+    <dimen name="length180">460.8dp</dimen>
+    <dimen name="length240">614.4dp</dimen>
+    <dimen name="size8">20.48sp</dimen>
+    <dimen name="size10">25.6sp</dimen>
+    <dimen name="size12">30.72sp</dimen>
+    <dimen name="size13">33.28sp</dimen>
+    <dimen name="size14">35.84sp</dimen>
+    <dimen name="size15">38.4sp</dimen>
+    <dimen name="size16">40.96sp</dimen>
+    <dimen name="size18">46.08sp</dimen>
+    <dimen name="size20">51.2sp</dimen>
+    <dimen name="size24">61.44sp</dimen>
+    <dimen name="footer_height">153.6dp</dimen>
+    <dimen name="img_length">102.4dp</dimen>
+</resources>

+ 19 - 0
baselib/src/main/res/values/attrs.xml

@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <declare-styleable name="VerticalScrollTextView">
+        <attr name="sleepTime" format="integer" />
+        <attr name="animDuration" format="integer" />
+        <attr name="textSize" format="dimension" />
+        <attr name="textColor" format="color" />
+        <attr name="singleLine" format="boolean" />
+        <attr name="scrollOrientation">
+            <enum name="up" value="0" />
+            <enum name="down" value="1" />
+        </attr>
+    </declare-styleable>
+    <declare-styleable name="VerticalScrollLayout">
+        <attr name="VAnimDuration" format="integer" />
+        <attr name="VSleepTime" format="integer" />
+        <attr name="VIsCusDuration" format="boolean" />
+    </declare-styleable>
+</resources>

+ 30 - 0
baselib/src/main/res/values/colors.xml

@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <color name="comm_red">#f00</color>
+    <color name="comm_blue">#00f</color>
+    <color name="comm_white">#fff</color>
+    <color name="comm_green">#0f0</color>
+    <color name="comm_gray">#aaa</color>
+
+    <color name="comm_white2">#e7e7e7</color>
+    <color name="comm_white_tr">#66ffffff</color>
+    <color name="comm_black">#505050</color>
+    <color name="comm_black2">#919191</color>
+    <color name="comm_red_s">#ff2f00</color>
+    <color name="comm_green_s">#39ce08</color>
+    <color name="comm_green_b">#397B19</color>
+    <color name="comm_blue1">#2af</color>
+    <color name="comm_blue2">#22e5ff</color>
+    <color name="comm_blue_big">#26f</color>
+    <color name="comm_violet">#9A32CD</color>
+    <color name="comm_transparent">#00000000</color>
+    <color name="comm_find_gray">#d5eaeaea</color>
+    <color name="comm_light_yellow">#FDFDB3</color>
+    <color name="comm_yellow">#f5ce64</color>
+    <color name="comm_green_blue">#52dfc8</color>
+    <color name="comm_orange">#f1962d</color>
+    <color name="comm_orange_red">#ff6000</color>
+    <color name="comm_data_time">#2f19dfbb</color>
+    <color name="comm_gray_background">#60000000</color>
+    <color name="comm_light_blue">#C0E3FF</color>
+</resources>

+ 56 - 0
baselib/src/main/res/values/dimens.xml

@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+    <dimen name="title_height">45dp</dimen>
+    <dimen name="drawer_width">240dp</dimen>
+    <dimen name="padding1">1dp</dimen>
+    <dimen name="padding2">2dp</dimen>
+    <dimen name="padding3">3dp</dimen>
+    <dimen name="padding4">4dp</dimen>
+    <dimen name="padding5">5dp</dimen>
+    <dimen name="padding7">7dp</dimen>
+    <dimen name="padding8">8dp</dimen>
+    <dimen name="padding10">10dp</dimen>
+    <dimen name="padding13">13dp</dimen>
+    <dimen name="padding15">15dp</dimen>
+    <dimen name="padding20">20dp</dimen>
+    <dimen name="padding30">30dp</dimen>
+    <dimen name="height5">5dp</dimen>
+    <dimen name="small">0.5dp</dimen>
+    <dimen name="length10">10dp</dimen>
+    <dimen name="length16">16dp</dimen>
+    <dimen name="length20">20dp</dimen>
+    <dimen name="length25">25dp</dimen>
+    <dimen name="length30">30dp</dimen>
+    <dimen name="length35">35dp</dimen>
+    <dimen name="length40">40dp</dimen>
+    <dimen name="length45">45dp</dimen>
+    <dimen name="length50">50dp</dimen>
+    <dimen name="length55">55dp</dimen>
+    <dimen name="length60">60dp</dimen>
+    <dimen name="length70">70dp</dimen>
+    <dimen name="length80">80dp</dimen>
+    <dimen name="length90">90dp</dimen>
+    <dimen name="length100">100dp</dimen>
+    <dimen name="length105">105dp</dimen>
+    <dimen name="length110">110dp</dimen>
+    <dimen name="length120">120dp</dimen>
+    <dimen name="length150">150dp</dimen>
+    <dimen name="length160">160dp</dimen>
+    <dimen name="length180">180dp</dimen>
+    <dimen name="length200">200dp</dimen>
+    <dimen name="length240">240dp</dimen>
+    <dimen name="size8">8sp</dimen>
+    <dimen name="size10">10sp</dimen>
+    <dimen name="size12">12sp</dimen>
+    <dimen name="size13">13sp</dimen>
+    <dimen name="size14">14sp</dimen>
+    <dimen name="size15">15sp</dimen>
+    <dimen name="size16">16sp</dimen>
+    <dimen name="size18">18sp</dimen>
+    <dimen name="size20">20sp</dimen>
+    <dimen name="size24">24sp</dimen>
+    <dimen name="footer_height">60dp</dimen>
+    <dimen name="img_length">40dp</dimen>
+
+</resources>

Некоторые файлы не были показаны из-за большого количества измененных файлов