瀏覽代碼

B端首次提交

ZhangXinYu 6 年之前
當前提交
8e9564c5db
共有 100 個文件被更改,包括 4978 次插入0 次删除
  1. 11 0
      .gitignore
  2. 29 0
      .idea/codeStyles/Project.xml
  3. 19 0
      .idea/gradle.xml
  4. 38 0
      .idea/misc.xml
  5. 12 0
      .idea/runConfigurations.xml
  6. 6 0
      .idea/vcs.xml
  7. 1 0
      app/.gitignore
  8. 87 0
      app/build.gradle
  9. 二進制
      app/keystore/kx.jks
  10. 21 0
      app/proguard-rules.pro
  11. 2 0
      app/server_url.properties
  12. 4 0
      app/signing.properties
  13. 26 0
      app/src/androidTest/java/com/webrain/happywork/ExampleInstrumentedTest.java
  14. 5 0
      app/src/hwpro/res/values/strings.xml
  15. 5 0
      app/src/hwtest/res/values/strings.xml
  16. 29 0
      app/src/main/AndroidManifest.xml
  17. 36 0
      app/src/main/java/com/webrain/happywork/AppCacheManager.java
  18. 32 0
      app/src/main/java/com/webrain/happywork/MyApplication.java
  19. 29 0
      app/src/main/java/com/webrain/happywork/bean/base/ApiBaseListBean.java
  20. 4 0
      app/src/main/java/com/webrain/happywork/bean/base/ApiNormalBean.java
  21. 44 0
      app/src/main/java/com/webrain/happywork/bean/base/ApiResultBean.java
  22. 12 0
      app/src/main/java/com/webrain/happywork/callback/MvpDataCallBack.java
  23. 9 0
      app/src/main/java/com/webrain/happywork/callback/OnActionBarMenuClickListener.java
  24. 13 0
      app/src/main/java/com/webrain/happywork/callback/OnRecyclerItemClickListener.java
  25. 6 0
      app/src/main/java/com/webrain/happywork/http/Api.java
  26. 69 0
      app/src/main/java/com/webrain/happywork/http/ApiCode.java
  27. 113 0
      app/src/main/java/com/webrain/happywork/http/ApiObserver.java
  28. 19 0
      app/src/main/java/com/webrain/happywork/http/HttpAddress.java
  29. 109 0
      app/src/main/java/com/webrain/happywork/http/RetrofitHttpParams.java
  30. 43 0
      app/src/main/java/com/webrain/happywork/http/ServiceGenerator.java
  31. 128 0
      app/src/main/java/com/webrain/happywork/http/exception/ApiException.java
  32. 32 0
      app/src/main/java/com/webrain/happywork/http/exception/HttpResponseException.java
  33. 42 0
      app/src/main/java/com/webrain/happywork/http/subscribe/BaseSubscribe.java
  34. 44 0
      app/src/main/java/com/webrain/happywork/ui/activity/DemandDetailActivity.java
  35. 166 0
      app/src/main/java/com/webrain/happywork/ui/activity/LoginActivity.java
  36. 83 0
      app/src/main/java/com/webrain/happywork/ui/activity/MainActivity.java
  37. 40 0
      app/src/main/java/com/webrain/happywork/ui/activity/MineApplyListActivity.java
  38. 59 0
      app/src/main/java/com/webrain/happywork/ui/activity/MineCenterActivity.java
  39. 65 0
      app/src/main/java/com/webrain/happywork/ui/adapter/base/BaseListAdapter.java
  40. 50 0
      app/src/main/java/com/webrain/happywork/ui/adapter/listview/DemandListAdapter.java
  41. 35 0
      app/src/main/java/com/webrain/happywork/ui/adapter/listview/MineApplyListAdapter.java
  42. 79 0
      app/src/main/java/com/webrain/happywork/ui/base/BaseActionBarMenuHolder.java
  43. 193 0
      app/src/main/java/com/webrain/happywork/ui/base/BaseActivity.java
  44. 328 0
      app/src/main/java/com/webrain/happywork/ui/base/BaseActivityHolder.java
  45. 185 0
      app/src/main/java/com/webrain/happywork/ui/base/BaseFragment.java
  46. 244 0
      app/src/main/java/com/webrain/happywork/ui/base/BaseFragmentHolder.java
  47. 12 0
      app/src/main/java/com/webrain/happywork/ui/base/BaseModel.java
  48. 46 0
      app/src/main/java/com/webrain/happywork/ui/base/BasePresenter.java
  49. 51 0
      app/src/main/java/com/webrain/happywork/ui/base/BaseViewHolder.java
  50. 5 0
      app/src/main/java/com/webrain/happywork/ui/base/IPresenter.java
  51. 7 0
      app/src/main/java/com/webrain/happywork/ui/base/IView.java
  52. 15 0
      app/src/main/java/com/webrain/happywork/ui/mvp/contacts/DemandDetailContacts.java
  53. 29 0
      app/src/main/java/com/webrain/happywork/ui/mvp/contacts/LoginContacts.java
  54. 15 0
      app/src/main/java/com/webrain/happywork/ui/mvp/contacts/MainContacts.java
  55. 15 0
      app/src/main/java/com/webrain/happywork/ui/mvp/contacts/MineApplyListContacts.java
  56. 15 0
      app/src/main/java/com/webrain/happywork/ui/mvp/contacts/MineCenterContacts.java
  57. 7 0
      app/src/main/java/com/webrain/happywork/ui/mvp/model/DemandDetailModel.java
  58. 17 0
      app/src/main/java/com/webrain/happywork/ui/mvp/model/LoginModel.java
  59. 7 0
      app/src/main/java/com/webrain/happywork/ui/mvp/model/MainModel.java
  60. 7 0
      app/src/main/java/com/webrain/happywork/ui/mvp/model/MineApplyListModel.java
  61. 7 0
      app/src/main/java/com/webrain/happywork/ui/mvp/model/MineCenterModel.java
  62. 17 0
      app/src/main/java/com/webrain/happywork/ui/mvp/presenter/DemandDetailPresenter.java
  63. 80 0
      app/src/main/java/com/webrain/happywork/ui/mvp/presenter/LoginPresenter.java
  64. 17 0
      app/src/main/java/com/webrain/happywork/ui/mvp/presenter/MainPresenter.java
  65. 17 0
      app/src/main/java/com/webrain/happywork/ui/mvp/presenter/MineApplyListPresenter.java
  66. 17 0
      app/src/main/java/com/webrain/happywork/ui/mvp/presenter/MineCenterPresenter.java
  67. 33 0
      app/src/main/java/com/webrain/happywork/ui/viewholder/DemandViewHeader.java
  68. 21 0
      app/src/main/java/com/webrain/happywork/utils/AlertDialogUtils.java
  69. 144 0
      app/src/main/java/com/webrain/happywork/utils/BitmapUtils.java
  70. 249 0
      app/src/main/java/com/webrain/happywork/utils/FileUtils.java
  71. 60 0
      app/src/main/java/com/webrain/happywork/utils/LogUtils.java
  72. 62 0
      app/src/main/java/com/webrain/happywork/utils/PhotoUtils.java
  73. 34 0
      app/src/main/res/drawable-v24/ic_launcher_foreground.xml
  74. 9 0
      app/src/main/res/drawable/corners_gradient_gray_5dp.xml
  75. 9 0
      app/src/main/res/drawable/corners_gradient_purple_5dp.xml
  76. 6 0
      app/src/main/res/drawable/corners_gray_f5_5dp.xml
  77. 170 0
      app/src/main/res/drawable/ic_launcher_background.xml
  78. 5 0
      app/src/main/res/drawable/select_color_blue_gray.xml
  79. 5 0
      app/src/main/res/drawable/select_corners_blue_gray.xml
  80. 162 0
      app/src/main/res/layout/activity_demand_detail.xml
  81. 95 0
      app/src/main/res/layout/activity_login.xml
  82. 89 0
      app/src/main/res/layout/activity_main.xml
  83. 22 0
      app/src/main/res/layout/activity_mine_apply_list.xml
  84. 180 0
      app/src/main/res/layout/activity_mine_center.xml
  85. 122 0
      app/src/main/res/layout/base_activity_layout.xml
  86. 83 0
      app/src/main/res/layout/base_activity_state.xml
  87. 95 0
      app/src/main/res/layout/base_fragment_layout.xml
  88. 110 0
      app/src/main/res/layout/item_list_demand.xml
  89. 99 0
      app/src/main/res/layout/item_list_mine_apply.xml
  90. 28 0
      app/src/main/res/layout/view_action_bar_menu.xml
  91. 77 0
      app/src/main/res/layout/view_list_demand_header.xml
  92. 二進制
      app/src/main/res/mipmap-hdpi/ic_back.png
  93. 二進制
      app/src/main/res/mipmap-hdpi/ic_default_header.png
  94. 二進制
      app/src/main/res/mipmap-hdpi/ic_demand_address.png
  95. 二進制
      app/src/main/res/mipmap-hdpi/ic_demand_detail_company.png
  96. 二進制
      app/src/main/res/mipmap-hdpi/ic_demand_detail_date.png
  97. 二進制
      app/src/main/res/mipmap-hdpi/ic_demand_detail_location.png
  98. 二進制
      app/src/main/res/mipmap-hdpi/ic_demand_detail_num.png
  99. 二進制
      app/src/main/res/mipmap-hdpi/ic_demand_going.png
  100. 0 0
      app/src/main/res/mipmap-hdpi/ic_demand_num.png

+ 11 - 0
.gitignore

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

+ 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$/baselibrary" />
+          </set>
+        </option>
+        <option name="resolveModulePerSourceSet" value="false" />
+      </GradleProjectSettings>
+    </option>
+  </component>
+</project>

+ 38 - 0
.idea/misc.xml

@@ -0,0 +1,38 @@
+<?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="7">
+          <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" />
+          <item index="5" class="java.lang.String" itemvalue="androidx.annotation.Nullable" />
+          <item index="6" class="java.lang.String" itemvalue="androidx.annotation.RecentlyNullable" />
+        </list>
+      </value>
+    </option>
+    <option name="myNotNulls">
+      <value>
+        <list size="6">
+          <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" />
+          <item index="4" class="java.lang.String" itemvalue="androidx.annotation.NonNull" />
+          <item index="5" class="java.lang.String" itemvalue="androidx.annotation.RecentlyNonNull" />
+        </list>
+      </value>
+    </option>
+  </component>
+  <component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" 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>

+ 1 - 0
app/.gitignore

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

+ 87 - 0
app/build.gradle

@@ -0,0 +1,87 @@
+apply plugin: 'com.android.application'
+
+Properties props = new Properties()
+props.load(new FileInputStream(file("signing.properties")))
+
+Properties serverProps = new Properties()
+def propFile = file('server_url.properties')
+def testApiUrl, proApiUrl
+if (propFile.canRead()) {
+    serverProps.load(new FileInputStream(propFile))
+    if (serverProps != null) {
+        testApiUrl = serverProps['testApiUrl']
+        proApiUrl = serverProps['proApiUrl']
+    }
+}
+
+android {
+    compileSdkVersion rootProject.ext.compileSdkVersion
+    buildToolsVersion rootProject.ext.buildToolsVersion
+
+    defaultConfig {
+        applicationId "com.webrain.happywork"
+        minSdkVersion rootProject.ext.minSdkVersion
+        targetSdkVersion rootProject.ext.targetSdkVersion
+        multiDexEnabled true
+        versionCode 1
+        versionName "1.0"
+        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
+        flavorDimensions "versionCode"
+        ndk {
+            abiFilters "armeabi", "armeabi-v7a", "arm64-v8a", "x86", "arm64-v8a", "x86_64"
+        }
+    }
+
+    productFlavors {
+        hwpro {
+            applicationId "com.webrain.happywork"
+            buildConfigField('String', 'baseApiUrl', proApiUrl)
+        }
+        hwtest {
+            applicationId "com.webrain.happywork.test"
+            buildConfigField('String', 'baseApiUrl', testApiUrl)
+        }
+    }
+    signingConfigs {
+        debug {
+            keyAlias props['KEY_ALIAS']
+            keyPassword props['KEY_PASSWORD']
+            storeFile file(props['KEYSTORE_FILE'])
+            storePassword props['KEYSTORE_PASSWORD']
+        }
+        release {
+            keyAlias props['KEY_ALIAS']
+            keyPassword props['KEY_PASSWORD']
+            storeFile file(props['KEYSTORE_FILE'])
+            storePassword props['KEYSTORE_PASSWORD']
+        }
+    }
+    //自动生成指定名称的release发布版的 apk文件
+    android.applicationVariants.all { variant ->
+        variant.outputs.all { output ->
+            outputFileName = "happyWork_${variant.productFlavors[0].name}_${buildType.getName()}_${defaultConfig.versionName}.apk"
+        }
+    }
+    buildTypes {
+        release {
+            //混淆
+            minifyEnabled true
+            //Zipalign优化
+            zipAlignEnabled true
+            // 移除无用的resource文件
+            shrinkResources true
+            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+            signingConfig signingConfigs.release
+        }
+        debug {
+            signingConfig signingConfigs.release
+        }
+    }
+}
+
+dependencies {
+    implementation fileTree(dir: 'libs', include: ['*.jar'])
+    implementation project(':baselibrary')
+    implementation 'com.jakewharton:butterknife:8.0.1'
+    annotationProcessor 'com.jakewharton:butterknife-compiler:8.0.1'
+}

二進制
app/keystore/kx.jks


+ 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

+ 2 - 0
app/server_url.properties

@@ -0,0 +1,2 @@
+proApiUrl="https://web.hap-job.com/happyjob/"
+testApiUrl="https://kf.hap-job.com/happyjob/"

+ 4 - 0
app/signing.properties

@@ -0,0 +1,4 @@
+KEYSTORE_FILE=keystore\\kx.jks
+KEYSTORE_PASSWORD=123456
+KEY_ALIAS=kx
+KEY_PASSWORD=123456

+ 26 - 0
app/src/androidTest/java/com/webrain/happywork/ExampleInstrumentedTest.java

@@ -0,0 +1,26 @@
+package com.webrain.happywork;
+
+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.webrain.happywork", appContext.getPackageName());
+    }
+}

+ 5 - 0
app/src/hwpro/res/values/strings.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string name="app_name">开心灵工</string>
+    <string name="install_name">hwpro_install</string>
+</resources>

+ 5 - 0
app/src/hwtest/res/values/strings.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string name="app_name">开心灵工_T</string>
+    <string name="install_name">hwtest_install</string>
+</resources>

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

@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.webrain.happywork">
+
+    <application
+        android:name=".MyApplication"
+        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=".ui.activity.MainActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+        <activity android:name=".ui.activity.LoginActivity">
+
+        </activity>
+        <activity android:name=".ui.activity.MineCenterActivity" />
+        <activity android:name=".ui.activity.DemandDetailActivity" />
+        <activity android:name=".ui.activity.MineApplyListActivity" />
+
+    </application>
+
+</manifest>

+ 36 - 0
app/src/main/java/com/webrain/happywork/AppCacheManager.java

@@ -0,0 +1,36 @@
+package com.webrain.happywork;
+
+import android.text.TextUtils;
+
+import com.google.gson.Gson;
+import com.webrain.baselibrary.utils.SharedPreferencesUtils;
+
+/**
+ * APP全局数据缓存类
+ */
+public class AppCacheManager {
+    private static volatile AppCacheManager instance = null;
+
+    private AppCacheManager() {
+    }
+
+    public static AppCacheManager getInstance() {
+        if (instance == null) {
+            synchronized (AppCacheManager.class) {
+                if (instance == null) {
+                    instance = new AppCacheManager();
+                }
+            }
+        }
+        return instance;
+    }
+
+
+    /**
+     * 清除缓存
+     */
+    public void clear() {
+        SharedPreferencesUtils.clear(MyApplication.getInstance().getApplicationContext());
+    }
+
+}

+ 32 - 0
app/src/main/java/com/webrain/happywork/MyApplication.java

@@ -0,0 +1,32 @@
+package com.webrain.happywork;
+
+import android.content.Context;
+import android.support.multidex.MultiDexApplication;
+
+import com.webrain.baselibrary.utils.UIManager;
+
+
+public class MyApplication extends MultiDexApplication {//兼容21之前的Android版本dex分包
+
+
+    private static Context mContext;
+    private static MyApplication mApplication;
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+        mContext = getApplicationContext();
+        mApplication = this;
+        UIManager.getInstance().setBaseContext(getBaseContext());
+
+    }
+
+    public static MyApplication getInstance() {
+        return mApplication;
+    }
+
+    public static Context getContext() {
+        return mContext;
+    }
+
+}

+ 29 - 0
app/src/main/java/com/webrain/happywork/bean/base/ApiBaseListBean.java

@@ -0,0 +1,29 @@
+package com.webrain.happywork.bean.base;
+
+import com.google.gson.annotations.SerializedName;
+
+/**
+ * 岗位列表接口基类
+ */
+public class ApiBaseListBean {
+    @SerializedName("pageNo")
+    private int pageNum;
+    @SerializedName("isLast")
+    private boolean isLastPage;
+
+    public int getPageNum() {
+        return pageNum;
+    }
+
+    public void setPageNum(int pageNum) {
+        this.pageNum = pageNum;
+    }
+
+    public boolean isLastPage() {
+        return isLastPage;
+    }
+
+    public void setLastPage(boolean lastPage) {
+        isLastPage = lastPage;
+    }
+}

+ 4 - 0
app/src/main/java/com/webrain/happywork/bean/base/ApiNormalBean.java

@@ -0,0 +1,4 @@
+package com.webrain.happywork.bean.base;
+
+public class ApiNormalBean {
+}

+ 44 - 0
app/src/main/java/com/webrain/happywork/bean/base/ApiResultBean.java

@@ -0,0 +1,44 @@
+package com.webrain.happywork.bean.base;
+
+import com.google.gson.annotations.SerializedName;
+
+public class ApiResultBean<T> {
+    @SerializedName("errcode")
+    private int errCode;
+    @SerializedName("errmsg")
+    private String errMsg;
+    private T data;
+
+    public int getErrCode() {
+        return errCode;
+    }
+
+    public void setErrCode(int errcode) {
+        this.errCode = errcode;
+    }
+
+    public T getData() {
+        return data;
+    }
+
+    public void setData(T data) {
+        this.data = data;
+    }
+
+    public String getErrMsg() {
+        return errMsg;
+    }
+
+    public void setErrMsg(String errmsg) {
+        this.errMsg = errmsg;
+    }
+
+    @Override
+    public String toString() {
+        return "HttpResponseModel{" +
+                "errCode=" + errCode +
+                ", data=" + data +
+                ", errMsg='" + errMsg + '\'' +
+                '}';
+    }
+}

+ 12 - 0
app/src/main/java/com/webrain/happywork/callback/MvpDataCallBack.java

@@ -0,0 +1,12 @@
+package com.webrain.happywork.callback;
+
+
+import com.webrain.happywork.http.exception.ApiException;
+
+public abstract class MvpDataCallBack<T> {
+    public abstract void onData(T data);
+
+    public void onError(ApiException exception) {
+    }
+
+}

+ 9 - 0
app/src/main/java/com/webrain/happywork/callback/OnActionBarMenuClickListener.java

@@ -0,0 +1,9 @@
+package com.webrain.happywork.callback;
+
+/**
+ * actionbar 图标监听
+ */
+public interface OnActionBarMenuClickListener {
+
+    void onClick(int resId);
+}

+ 13 - 0
app/src/main/java/com/webrain/happywork/callback/OnRecyclerItemClickListener.java

@@ -0,0 +1,13 @@
+package com.webrain.happywork.callback;
+
+public interface OnRecyclerItemClickListener {
+
+    /**
+     * RecyclerView 点击回调
+     *
+     * @param position 位置
+     * @param object   对象
+     */
+    void onItemClick(int position, Object object);
+
+}

+ 6 - 0
app/src/main/java/com/webrain/happywork/http/Api.java

@@ -0,0 +1,6 @@
+package com.webrain.happywork.http;
+
+public class Api {
+
+
+}

+ 69 - 0
app/src/main/java/com/webrain/happywork/http/ApiCode.java

@@ -0,0 +1,69 @@
+package com.webrain.happywork.http;
+
+/**
+ * @Description: API Code,包含Http/Request/Response
+ * @author: <a href="http://xiaoyaoyou1212.360doc.com">DAWI</a>
+ * @date: 2016-12-30 18:11
+ */
+public class ApiCode {
+
+    public static class Http {
+        /*==========对应HTTP的状态码=================*/
+        public static final int UNAUTHORIZED = 401;
+        public static final int FORBIDDEN = 403;
+        public static final int NOT_FOUND = 404;
+        public static final int REQUEST_TIMEOUT = 408;
+        public static final int INTERNAL_SERVER_ERROR = 500;
+        public static final int BAD_GATEWAY = 502;
+        public static final int SERVICE_UNAVAILABLE = 503;
+        public static final int GATEWAY_TIMEOUT = 504;
+        /*=======================================*/
+    }
+
+    public static class Request {
+        /*===========Request请求码================*/
+        //未知错误
+        public static final String UNKNOWN = "1000";
+        //解析错误
+        public static final String PARSE_ERROR = "1001";
+        //网络错误
+        public static final String NETWORK_ERROR = "1002";
+        //协议出错
+        public static final String HTTP_ERROR = "1003";
+        //证书出错
+        public static final String SSL_ERROR = "1005";
+        //连接超时
+        public static final String TIMEOUT_ERROR = "1006";
+        //调用错误
+        public static final String UNKNOW_HOST_ERROR = "1007";
+        /*========================================*/
+    }
+
+    public static class Response {
+        /*===========Response响应码================*/
+        //HTTP请求成功状态码
+        public static final int HTTP_SUCCESS = 0;
+//        //未绑定手机
+//        public static final int HTTP_NO_BINGDING_PHONE = 1014;
+//        //简历不存在
+//        public static final int HTTP_NO_RESUME = 1015;
+//        //存在多简历信息
+//        public static final int HTTP_DOUBLE_RESUME = 2009;
+//        //AccessToken错误或已过期
+//        public static final int ACCESS_TOKEN_EXPIRED = 10001;
+//        //RefreshToken错误或已过期
+//        public static final int REFRESH_TOKEN_EXPIRED = 10002;
+//        //帐号在其它手机已登录
+//        public static final int OTHER_PHONE_LOGINED = 10003;
+//        //时间戳过期
+//        public static final int TIMESTAMP_ERROR = 10004;
+//        //缺少授权信息,没有AccessToken
+//        public static final int NO_ACCESS_TOKEN = 10005;
+//        //签名错误
+//        public static final int SIGN_ERROR = 10006;
+//        //密码错误
+//        public static final int ERR_PWD = 1020100902;
+        /*============================================*/
+    }
+
+}

+ 113 - 0
app/src/main/java/com/webrain/happywork/http/ApiObserver.java

@@ -0,0 +1,113 @@
+package com.webrain.happywork.http;
+
+import android.app.ProgressDialog;
+import android.content.Context;
+import android.text.TextUtils;
+
+
+import com.webrain.baselibrary.utils.ToastUtils;
+import com.webrain.happywork.bean.base.ApiResultBean;
+import com.webrain.happywork.http.exception.ApiException;
+import com.webrain.happywork.http.exception.HttpResponseException;
+
+import java.lang.ref.WeakReference;
+
+import io.reactivex.Observer;
+import io.reactivex.disposables.Disposable;
+
+
+/**
+ * @Description: API统一订阅者,采用弱引用管理上下文,防止内存泄漏
+ * @author: zhangxinyu
+ * @date: 2017-01-03 14:07
+ */
+public abstract class ApiObserver<T> implements Observer<ApiResultBean<T>> {
+    public WeakReference<Context> contextWeakReference;
+    public boolean isShowLoading = false;
+    public boolean isCancelable = false;
+    public boolean isShowError = true;
+    public String dialogMessage;
+    private ProgressDialog mProgressDialog;
+
+    public ApiObserver(Context context) {
+        contextWeakReference = new WeakReference<Context>(context);
+    }
+
+    public ApiObserver(Context context, boolean isShowLoading) {
+        contextWeakReference = new WeakReference<Context>(context);
+        this.isShowLoading = isShowLoading;
+    }
+
+    public ApiObserver(Context context, String dialogMessage, boolean isShowLoading, boolean isCancelable) {
+        contextWeakReference = new WeakReference<Context>(context);
+        this.dialogMessage = dialogMessage;
+        this.isShowLoading = isShowLoading;
+        this.isCancelable = isCancelable;
+    }
+
+    public ApiObserver(Context context, boolean isShowLoading, boolean isCancelable) {
+        contextWeakReference = new WeakReference<Context>(context);
+        this.isShowLoading = isShowLoading;
+        this.isCancelable = isCancelable;
+    }
+
+    public ApiObserver(Context context, boolean isShowLoading, boolean isCancelable, boolean isShowError) {
+        contextWeakReference = new WeakReference<Context>(context);
+        this.isShowLoading = isShowLoading;
+        this.isCancelable = isCancelable;
+        this.isShowError = isShowError;
+    }
+
+    public ApiObserver(Context context, String dialogMessage, boolean isShowLoading, boolean isCancelable, boolean isShowError) {
+        contextWeakReference = new WeakReference<Context>(context);
+        this.dialogMessage = dialogMessage;
+        this.isShowLoading = isShowLoading;
+        this.isCancelable = isCancelable;
+        this.isShowError = isShowError;
+    }
+
+    @Override
+    public void onSubscribe(Disposable d) {
+        if (isShowLoading) {
+            mProgressDialog = new ProgressDialog(contextWeakReference.get());
+            if (!TextUtils.isEmpty(dialogMessage))
+                mProgressDialog.setTitle(dialogMessage);
+            mProgressDialog.show();
+        }
+    }
+
+
+    @Override
+    public void onComplete() {
+        if (isShowLoading && mProgressDialog != null) {
+            mProgressDialog.dismiss();
+        }
+        onFinish();
+    }
+
+    @Override
+    public void onNext(ApiResultBean<T> apiResultBean) {
+        if (apiResultBean != null) {
+            if (apiResultBean.getErrCode() == ApiCode.Response.HTTP_SUCCESS) {
+                onSuccess(apiResultBean.getData());
+            } else {
+                onError(apiResultBean.getData(), ApiException.handleException(new HttpResponseException(apiResultBean)));
+            }
+        }
+    }
+
+    @Override
+    public void onError(Throwable e) {
+        onError(null, ApiException.handleException(e));
+        onComplete();
+    }
+
+    public abstract void onSuccess(T data);
+
+    public void onError(T data, ApiException exception) {
+        if (isShowError && exception.isNeedShowError())
+            ToastUtils.show(contextWeakReference.get(), exception.getErrorMessage());
+    }
+
+    public abstract void onFinish();
+}

+ 19 - 0
app/src/main/java/com/webrain/happywork/http/HttpAddress.java

@@ -0,0 +1,19 @@
+package com.webrain.happywork.http;
+
+
+import com.webrain.happywork.BuildConfig;
+
+/**
+ * Created by zhangxinyu on 2019/3/7.
+ */
+public class HttpAddress {
+    /**
+     * 根据环境获取不同的服务端地址,服务端地址配置在server_url.properties中
+     *
+     * @return
+     */
+    public static String getServerAddress() {
+        return BuildConfig.baseApiUrl;
+    }
+}
+

+ 109 - 0
app/src/main/java/com/webrain/happywork/http/RetrofitHttpParams.java

@@ -0,0 +1,109 @@
+package com.webrain.happywork.http;
+
+import android.content.Context;
+import android.os.Bundle;
+
+import java.io.InputStream;
+import java.util.Map;
+import java.util.TreeMap;
+
+import okhttp3.MultipartBody;
+
+/**
+ * Created by zhangxinyu on 2017/7/26.
+ */
+public class RetrofitHttpParams {
+    protected Map<String, Object> requestParams;
+
+    public RetrofitHttpParams(Context context) {
+        requestParams = new TreeMap<String, Object>();
+//        if (AppCacheManager.getInstance().isLogin()) {
+//            requestParams.put("user_id", AppCacheManager.getInstance().getUserId());
+//            requestParams.put("user_token", AppCacheManager.getInstance().getUserToken());
+//            requestParams.put("member_id", AppCacheManager.getInstance().getMemberId());
+//        }
+    }
+
+    public void put(String key, String value) {
+        requestParams.put(key, value);
+    }
+
+    public void put(String key, CharSequence value) {
+        requestParams.put(key, value);
+    }
+
+    public void put(String key, int value) {
+        requestParams.put(key, value);
+    }
+
+    public void put(String key, boolean value) {
+        requestParams.put(key, value);
+    }
+
+    public void put(String key, long value) {
+        requestParams.put(key, value);
+    }
+
+    public void put(String key, double value) {
+        requestParams.put(key, value);
+    }
+
+    public void put(String key, Object value) {
+        requestParams.put(key, value);
+    }
+
+    public void put(String key, InputStream stream) {
+        requestParams.put(key, stream);
+    }
+
+    public void put(Map<String, Object> source) {
+        if (source != null) {
+            for (Map.Entry<String, Object> entry : source.entrySet()) {
+                requestParams.put(entry.getKey(), entry.getValue());
+            }
+        }
+    }
+
+    public void put(Bundle source) {
+        if (source != null) {
+            for (String key : source.keySet()) {
+                Object o = source.get(key);
+                requestParams.put(key, o);
+            }
+        }
+    }
+
+    public boolean containsKey(String key) {
+        return requestParams.containsKey(key);
+    }
+
+    public Map<String, Object> getRequestParams() {
+        return requestParams;
+    }
+
+    public MultipartBody.Builder getRequestMultipartBody() {
+        MultipartBody.Builder builder = new MultipartBody.Builder();
+        builder.setType(MultipartBody.FORM);
+//        if (AppCacheManager.getInstance().isLogin()) {
+//            builder.addFormDataPart("user_id", AppCacheManager.getInstance().getUserId());
+//            builder.addFormDataPart("user_token", AppCacheManager.getInstance().getUserToken());
+//            builder.addFormDataPart("member_id", AppCacheManager.getInstance().getMemberId());
+//        }
+        return builder;
+    }
+
+    public void setRequestParams(Map<String, Object> params) {
+        requestParams = params;
+    }
+
+    @Override
+    public String toString() {
+        return requestParams.toString();
+    }
+
+
+    public void remove(String key) {
+        requestParams.remove(key);
+    }
+
+}

+ 43 - 0
app/src/main/java/com/webrain/happywork/http/ServiceGenerator.java

@@ -0,0 +1,43 @@
+package com.webrain.happywork.http;
+
+import android.text.TextUtils;
+
+import com.facebook.stetho.okhttp3.StethoInterceptor;
+
+import java.util.concurrent.TimeUnit;
+
+import okhttp3.OkHttpClient;
+import okhttp3.logging.HttpLoggingInterceptor;
+import retrofit2.Retrofit;
+import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
+import retrofit2.converter.gson.GsonConverterFactory;
+
+public class ServiceGenerator {
+
+    static HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
+    private static Retrofit.Builder builder =
+            new Retrofit.Builder()
+                    .baseUrl(HttpAddress.getServerAddress())
+                    .addConverterFactory(GsonConverterFactory.create())
+                    .addCallAdapterFactory(RxJava2CallAdapterFactory.create());
+
+    public static <S> S createService(Class<S> serviceClass) {
+        return createService(serviceClass, null);
+    }
+
+    public static <S> S createService(Class<S> serviceClass, String baseUrl) {
+        OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
+        httpClient.connectTimeout(20, TimeUnit.SECONDS);
+        httpClient.writeTimeout(20, TimeUnit.SECONDS);
+        httpClient.readTimeout(20, TimeUnit.SECONDS);
+        httpClient.addNetworkInterceptor(new StethoInterceptor());
+        httpClient.addInterceptor(interceptor.setLevel(HttpLoggingInterceptor.Level.BODY));
+        if (baseUrl == null || TextUtils.isEmpty(baseUrl)) {
+            builder.baseUrl(HttpAddress.getServerAddress()).client(httpClient.build());
+        } else {
+            builder.baseUrl(baseUrl).client(httpClient.build());
+        }
+        return builder.build().create(serviceClass);
+    }
+
+}

+ 128 - 0
app/src/main/java/com/webrain/happywork/http/exception/ApiException.java

@@ -0,0 +1,128 @@
+package com.webrain.happywork.http.exception;
+
+import com.google.gson.JsonParseException;
+import com.webrain.happywork.http.ApiCode;
+
+import org.json.JSONException;
+
+import java.io.IOException;
+import java.net.ConnectException;
+import java.net.SocketTimeoutException;
+import java.net.UnknownHostException;
+import java.text.ParseException;
+
+import retrofit2.HttpException;
+
+public class ApiException extends IOException {
+
+    private final String errorCode;
+    private String errorMessage;
+    private boolean isNeedShowError = true;
+
+    public ApiException(Throwable throwable, String errorCode) {
+        super(throwable);
+        this.errorCode = errorCode;
+    }
+
+
+    public static ApiException handleException(Throwable e) {
+        ApiException ex;
+        if (e instanceof HttpException) {
+            HttpException httpException = (HttpException) e;
+            ex = new ApiException(e, ApiCode.Request.HTTP_ERROR);
+            switch (httpException.code()) {
+                case ApiCode.Http.UNAUTHORIZED:
+                    ex.errorMessage = "用户未登录!";
+                    break;
+                case ApiCode.Http.FORBIDDEN:
+                    ex.errorMessage = "不需要更新";
+                    break;
+                case ApiCode.Http.NOT_FOUND:
+                    ex.errorMessage = "找不到相关接口";
+                    break;
+                case ApiCode.Http.REQUEST_TIMEOUT:
+                    ex.errorMessage = "请求超时";
+                    break;
+                case ApiCode.Http.GATEWAY_TIMEOUT:
+                    ex.errorMessage = "请求超时";
+                    break;
+                case ApiCode.Http.INTERNAL_SERVER_ERROR:
+                    ex.errorMessage = "服务器异常";
+                    break;
+                case ApiCode.Http.BAD_GATEWAY:
+                    ex.errorMessage = "无效网关";
+                    break;
+                case ApiCode.Http.SERVICE_UNAVAILABLE:
+                    ex.errorMessage = "服务器异常";
+                    break;
+                default:
+                    ex.errorMessage = "未知异常";
+                    break;
+            }
+            return ex;
+        } else if (e instanceof JsonParseException || e instanceof JSONException || e instanceof ParseException) {
+            ex = new ApiException(e, ApiCode.Request.PARSE_ERROR);
+            ex.errorMessage = "数据解析异常";
+            return ex;
+        } else if (e instanceof ConnectException) {
+            ex = new ApiException(e, ApiCode.Request.NETWORK_ERROR);
+            ex.errorMessage = "网络错误";
+            return ex;
+        } else if (e instanceof javax.net.ssl.SSLHandshakeException) {
+            ex = new ApiException(e, ApiCode.Request.SSL_ERROR);
+            ex.errorMessage = "证书出错";
+            return ex;
+        } else if (e instanceof SocketTimeoutException) {
+            ex = new ApiException(e, ApiCode.Request.TIMEOUT_ERROR);
+            ex.errorMessage = "请求超时";
+            return ex;
+        } else if (e instanceof UnknownHostException) {
+            ex = new ApiException(e, ApiCode.Request.UNKNOW_HOST_ERROR);
+            ex.errorMessage = "服务器连接异常";
+            return ex;
+        } else if (e instanceof HttpResponseException) {//请求错误返回异常
+            ex = disposeHttpResponseException((HttpResponseException) e);
+            return ex;
+        } else {
+            ex = new ApiException(e, ApiCode.Request.UNKNOWN);
+            ex.errorMessage = "未知异常";
+            return ex;
+        }
+    }
+
+    /**
+     * 全局处理http错误code异常,如果是某个具体页面或者功能需要做出逻辑操作可以在请求回调中重写OnError处理
+     */
+    private static ApiException disposeHttpResponseException(HttpResponseException e) {
+        ApiException ex = new ApiException(e, e.getErrorCode() + "");
+        ex.errorMessage = e.getErrorMessage();
+//        if (e.getErrorCode() == ApiCode.Response.HTTP_NO_BINGDING_PHONE) {//未绑定 需要绑定手机号
+//            ex.isNeedShowError = false;
+//        } else if (e.getErrorCode() == ApiCode.Response.HTTP_NO_RESUME) {//简历不存在需要填写简历
+//            ex.isNeedShowError = false;
+//        } else if (e.getErrorCode() == ApiCode.Response.HTTP_DOUBLE_RESUME) {//存在多个简历需要删选
+//            ex.isNeedShowError = false;
+//        }
+        return ex;
+    }
+
+    public String getErrorCode() {
+        return errorCode;
+    }
+
+    public String getErrorMessage() {
+        return errorMessage;
+    }
+
+    public void setErrorMessage(String message) {
+        this.errorMessage = message;
+    }
+
+    public boolean isNeedShowError() {
+        return isNeedShowError;
+    }
+
+    public void setNeedShowError(boolean needShowError) {
+        isNeedShowError = needShowError;
+    }
+}

+ 32 - 0
app/src/main/java/com/webrain/happywork/http/exception/HttpResponseException.java

@@ -0,0 +1,32 @@
+package com.webrain.happywork.http.exception;
+
+import com.webrain.happywork.bean.base.ApiResultBean;
+
+/**
+ * 请求返回错误异常
+ */
+public class HttpResponseException extends Exception {
+    private int errorCode;
+    private String errorMessage;
+
+    public HttpResponseException(ApiResultBean apiResultBean) {
+        this.errorCode = apiResultBean.getErrCode();
+        this.errorMessage = apiResultBean.getErrMsg();
+    }
+
+    public int getErrorCode() {
+        return errorCode;
+    }
+
+    public void setErrorCode(int errorCode) {
+        this.errorCode = errorCode;
+    }
+
+    public String getErrorMessage() {
+        return errorMessage;
+    }
+
+    public void setErrorMessage(String errorMessage) {
+        this.errorMessage = errorMessage;
+    }
+}

+ 42 - 0
app/src/main/java/com/webrain/happywork/http/subscribe/BaseSubscribe.java

@@ -0,0 +1,42 @@
+package com.webrain.happywork.http.subscribe;
+
+import android.app.Application;
+import android.content.Context;
+
+import com.trello.rxlifecycle2.LifecycleProvider;
+import com.trello.rxlifecycle2.android.ActivityEvent;
+
+import io.reactivex.Observable;
+import io.reactivex.Observer;
+import io.reactivex.android.schedulers.AndroidSchedulers;
+import io.reactivex.schedulers.Schedulers;
+
+public class BaseSubscribe {
+    protected Context mContext;
+
+    public BaseSubscribe(Context context) {
+        mContext = context;
+    }
+
+    protected LifecycleProvider getLifecycleProvider() {
+        LifecycleProvider provider = null;
+        if (null != mContext && mContext instanceof LifecycleProvider) {
+            provider = (LifecycleProvider) mContext;
+        }
+        return provider;
+    }
+
+    public Observable subscribe(Observable mObservable, Observer observer) {
+        if (mContext instanceof Application) {
+            mObservable.subscribeOn(Schedulers.io())
+                    .observeOn(AndroidSchedulers.mainThread())
+                    .subscribe(observer);
+        } else {
+            mObservable.subscribeOn(Schedulers.io())
+                    .observeOn(AndroidSchedulers.mainThread())
+                    .compose(getLifecycleProvider().bindUntilEvent(ActivityEvent.DESTROY))
+                    .subscribe(observer);
+        }
+        return mObservable;
+    }
+}

+ 44 - 0
app/src/main/java/com/webrain/happywork/ui/activity/DemandDetailActivity.java

@@ -0,0 +1,44 @@
+package com.webrain.happywork.ui.activity;
+
+import android.os.Bundle;
+import android.widget.TextView;
+
+import com.webrain.happywork.R;
+import com.webrain.happywork.ui.base.BaseActivity;
+import com.webrain.happywork.ui.mvp.contacts.DemandDetailContacts;
+import com.webrain.happywork.ui.mvp.presenter.DemandDetailPresenter;
+
+import butterknife.BindView;
+
+public class DemandDetailActivity extends BaseActivity<DemandDetailPresenter> implements DemandDetailContacts.IDemandDetailView {
+    @BindView(R.id.tv_price)
+    TextView tvPrice;
+    @BindView(R.id.tv_title)
+    TextView tvTitle;
+    @BindView(R.id.tv_num)
+    TextView tvNum;
+    @BindView(R.id.tv_date)
+    TextView tvDate;
+    @BindView(R.id.tv_company_name)
+    TextView tvCompanyName;
+    @BindView(R.id.tv_company_address)
+    TextView tvCompanyAddress;
+    @BindView(R.id.tv_desc)
+    TextView tvDesc;
+
+    @Override
+    public int getLayoutId() {
+        return R.layout.activity_demand_detail;
+    }
+
+    @Override
+    public DemandDetailPresenter bindPresenter() {
+        return new DemandDetailPresenter(this);
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setTitle(R.string.demand_detail);
+    }
+}

+ 166 - 0
app/src/main/java/com/webrain/happywork/ui/activity/LoginActivity.java

@@ -0,0 +1,166 @@
+package com.webrain.happywork.ui.activity;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.text.SpannableString;
+import android.text.Spanned;
+import android.text.TextPaint;
+import android.text.method.LinkMovementMethod;
+import android.text.style.ClickableSpan;
+import android.view.View;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.TextView;
+
+import com.webrain.happywork.R;
+import com.webrain.happywork.ui.base.BaseActivity;
+import com.webrain.happywork.ui.mvp.contacts.LoginContacts;
+import com.webrain.happywork.ui.mvp.presenter.LoginPresenter;
+
+import java.util.concurrent.TimeUnit;
+
+import butterknife.BindView;
+import butterknife.OnClick;
+import butterknife.OnTextChanged;
+import io.reactivex.Observable;
+import io.reactivex.Observer;
+import io.reactivex.android.schedulers.AndroidSchedulers;
+import io.reactivex.disposables.Disposable;
+import io.reactivex.functions.Consumer;
+import io.reactivex.functions.Function;
+
+public class LoginActivity extends BaseActivity<LoginPresenter> implements LoginContacts.ILoginView {
+    @BindView(R.id.et_phone)
+    EditText etPhone;
+    @BindView(R.id.et_code)
+    EditText etCode;
+    @BindView(R.id.tv_code)
+    TextView tvCode;
+    @BindView(R.id.tv_tip)
+    TextView tvTip;
+    @BindView(R.id.btn_login)
+    Button btnLogin;
+
+    boolean isCountDown;
+
+    @Override
+    public int getLayoutId() {
+        return R.layout.activity_login;
+    }
+
+    @Override
+    public LoginPresenter bindPresenter() {
+        return new LoginPresenter(this);
+    }
+
+    @Override
+    public boolean isShowActionBar() {
+        return false;
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        mvpPresenter.init();
+    }
+
+    /**
+     * 加载Spanable
+     */
+    @Override
+    public void onSpannableInit() {
+        SpannableString spannableString = new SpannableString(getResources().getString(R.string.login_tip));
+        spannableString.setSpan(new ClickableSpan() {
+            @Override
+            public void updateDrawState(TextPaint ds) {
+                super.updateDrawState(ds);
+                ds.setColor(getResources().getColor(R.color.text_blue_32));//设置颜色
+                ds.setUnderlineText(false);//去掉下划线
+            }
+
+            @Override
+            public void onClick(View widget) {
+//                startActivity(new Intent(mContext, TipsActivity.class));
+            }
+        }, spannableString.toString().length() - 8, spannableString.toString().length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
+        tvTip.setText(spannableString);
+        tvTip.setMovementMethod(LinkMovementMethod.getInstance());//必须设置才能响应点击事件
+    }
+
+    @OnClick({R.id.btn_login, R.id.tv_code})
+    void onClick(View view) {
+        switch (view.getId()) {
+            case R.id.btn_login:
+                startActivity(new Intent(mContext, MainActivity.class));
+//                if (mvpPresenter.isPhone(etPhone.getText().toString(), true) && mvpPresenter.isCode(etCode.getText().toString(), true))
+//                    mvpPresenter.httpLogin(etPhone.getText().toString(), etCode.getText().toString());
+                break;
+            case R.id.tv_code:
+                if (mvpPresenter.isPhone(etPhone.getText().toString(), true)) {
+                    mvpPresenter.getAuthCode(etPhone.getText().toString());
+                    countDown();
+                }
+        }
+    }
+
+    @OnTextChanged({R.id.et_phone, R.id.et_code})
+    public void onTextChanged(CharSequence s, int start, int before, int count) {
+        if (mvpPresenter.isPhone(etPhone.getText().toString(), false) && !isCountDown) {
+            tvCode.setEnabled(true);
+        } else {
+            tvCode.setEnabled(false);
+        }
+        if (mvpPresenter.isPhone(etPhone.getText().toString(), false) && mvpPresenter.isCode(etCode.getText().toString(), false)) {
+            btnLogin.setEnabled(true);
+        } else {
+            btnLogin.setEnabled(false);
+        }
+    }
+
+    /**
+     * 验证码倒计时
+     */
+    private void countDown() {
+        final int count = 60;
+        Observable.interval(0, 1, TimeUnit.SECONDS)
+                .take(count)
+                .map(new Function<Long, Long>() {
+                    @Override
+                    public Long apply(Long aLong) throws Exception {
+                        return count - aLong;
+                    }
+                })
+                .observeOn(AndroidSchedulers.mainThread())//ui线程中进行控件更新
+                .doOnSubscribe(new Consumer<Disposable>() {
+                    @Override
+                    public void accept(Disposable disposable) throws Exception {
+                        tvCode.setEnabled(false);
+                        isCountDown = true;
+
+                    }
+                }).subscribe(new Observer<Long>() {
+            @Override
+            public void onSubscribe(Disposable d) {
+
+            }
+
+            @Override
+            public void onNext(Long num) {
+                tvCode.setText("重新发送 " + num + "秒 ");
+            }
+
+            @Override
+            public void onError(Throwable e) {
+
+            }
+
+            @Override
+            public void onComplete() {
+                //回复原来初始状态
+                isCountDown = false;
+                tvCode.setEnabled(true);
+                tvCode.setText(getString(R.string.get_code));
+            }
+        });
+    }
+}

+ 83 - 0
app/src/main/java/com/webrain/happywork/ui/activity/MainActivity.java

@@ -0,0 +1,83 @@
+package com.webrain.happywork.ui.activity;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.support.annotation.Px;
+import android.view.View;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.webrain.baselibrary.utils.PxUtils;
+import com.webrain.baselibrary.widget.ScrollListView;
+import com.webrain.baselibrary.widget.refresh.ProgressRefreshLayout;
+import com.webrain.happywork.R;
+import com.webrain.happywork.callback.OnActionBarMenuClickListener;
+import com.webrain.happywork.ui.adapter.listview.DemandListAdapter;
+import com.webrain.happywork.ui.base.BaseActivity;
+import com.webrain.happywork.ui.mvp.contacts.MainContacts;
+import com.webrain.happywork.ui.mvp.presenter.MainPresenter;
+import com.webrain.happywork.ui.viewholder.DemandViewHeader;
+
+import butterknife.BindView;
+import butterknife.OnClick;
+
+public class MainActivity extends BaseActivity<MainPresenter> implements MainContacts.IMainView {
+    @BindView(R.id.iv_content)
+    ScrollListView ivContent;
+    @BindView(R.id.prl_refresh)
+    ProgressRefreshLayout prlRefresh;
+    @BindView(R.id.tv_area)
+    TextView tvArea;
+    @BindView(R.id.tv_business)
+    TextView tvBusiness;
+    @BindView(R.id.tv_price)
+    TextView tvPrice;
+    @BindView(R.id.ll_select)
+    LinearLayout llSelect;
+
+    DemandListAdapter mAdapter;
+
+    @Override
+    public int getLayoutId() {
+        return R.layout.activity_main;
+    }
+
+    @Override
+    public MainPresenter bindPresenter() {
+        return new MainPresenter(this);
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        initLeftTitle();
+        setTitle(R.string.need_home);
+        setActionBarMenu(onActionBarMenuClickListener, R.mipmap.ic_mine_center);
+        mAdapter = new DemandListAdapter(mContext);
+        ivContent.setAdapter(mAdapter);
+        ivContent.addHeaderView(new DemandViewHeader(mContext).getView());
+        ivContent.setOnScrollMoveListener(onScrollMoveListener);
+        ivContent.setOnItemClickListener(mAdapter);
+    }
+
+
+    ScrollListView.OnScrollMoveListener onScrollMoveListener = new ScrollListView.OnScrollMoveListener() {
+        @Override
+        public void onScrollMove(int scrollY) {
+            if (scrollY >= PxUtils.dip2px(160)) {
+                llSelect.setVisibility(View.VISIBLE);
+            } else {
+                llSelect.setVisibility(View.GONE);
+            }
+        }
+
+    };
+
+    OnActionBarMenuClickListener onActionBarMenuClickListener = new OnActionBarMenuClickListener() {
+        @Override
+        public void onClick(int resId) {
+            startActivity(new Intent(mContext, MineCenterActivity.class));
+        }
+    };
+
+}

+ 40 - 0
app/src/main/java/com/webrain/happywork/ui/activity/MineApplyListActivity.java

@@ -0,0 +1,40 @@
+package com.webrain.happywork.ui.activity;
+
+import android.os.Bundle;
+import android.widget.ListView;
+
+import com.webrain.baselibrary.widget.refresh.ProgressRefreshLayout;
+import com.webrain.happywork.R;
+import com.webrain.happywork.ui.adapter.listview.MineApplyListAdapter;
+import com.webrain.happywork.ui.base.BaseActivity;
+import com.webrain.happywork.ui.mvp.contacts.MineApplyListContacts;
+import com.webrain.happywork.ui.mvp.presenter.MineApplyListPresenter;
+
+import butterknife.BindView;
+
+public class MineApplyListActivity extends BaseActivity<MineApplyListPresenter> implements MineApplyListContacts.IMineApplyListView {
+    @BindView(R.id.iv_content)
+    ListView ivContent;
+    @BindView(R.id.prl_refresh)
+    ProgressRefreshLayout prlRefresh;
+
+    MineApplyListAdapter mAdapter;
+
+    @Override
+    public int getLayoutId() {
+        return R.layout.activity_mine_apply_list;
+    }
+
+    @Override
+    public MineApplyListPresenter bindPresenter() {
+        return new MineApplyListPresenter(this);
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setTitle(R.string.mine_apply);
+        mAdapter = new MineApplyListAdapter(mContext);
+        ivContent.setAdapter(mAdapter);
+    }
+}

+ 59 - 0
app/src/main/java/com/webrain/happywork/ui/activity/MineCenterActivity.java

@@ -0,0 +1,59 @@
+package com.webrain.happywork.ui.activity;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.webrain.happywork.R;
+import com.webrain.happywork.ui.base.BaseActivity;
+import com.webrain.happywork.ui.mvp.contacts.MineCenterContacts;
+import com.webrain.happywork.ui.mvp.presenter.MineCenterPresenter;
+
+import butterknife.BindView;
+import butterknife.OnClick;
+
+public class MineCenterActivity extends BaseActivity<MineCenterPresenter> implements MineCenterContacts.IMineCenterView {
+    @BindView(R.id.iv_header)
+    ImageView ivHeader;
+    @BindView(R.id.tv_name)
+    TextView tvName;
+    @BindView(R.id.tv_authentication)
+    TextView tvAuthentication;
+    @BindView(R.id.ll_apply)
+    LinearLayout llApply;
+    @BindView(R.id.ll_order)
+    LinearLayout llOrder;
+    @BindView(R.id.ll_payment_record)
+    LinearLayout llPaymentRecord;
+    @BindView(R.id.ll_tax)
+    LinearLayout llTax;
+
+    @Override
+    public int getLayoutId() {
+        return R.layout.activity_mine_center;
+    }
+
+    @Override
+    public MineCenterPresenter bindPresenter() {
+        return new MineCenterPresenter(this);
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setTitle(R.string.mine_center);
+    }
+
+    @OnClick(R.id.ll_apply)
+    public void onClick(View view) {
+        switch (view.getId()) {
+            case R.id.ll_apply:
+                startActivity(new Intent(mContext, MineApplyListActivity.class));
+                break;
+        }
+    }
+
+}

+ 65 - 0
app/src/main/java/com/webrain/happywork/ui/adapter/base/BaseListAdapter.java

@@ -0,0 +1,65 @@
+package com.webrain.happywork.ui.adapter.base;
+
+import android.content.Context;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+
+import com.webrain.happywork.ui.base.BaseViewHolder;
+
+import java.util.List;
+
+public abstract class BaseListAdapter<T, Z extends BaseViewHolder> extends BaseAdapter {
+    public List<T> mData;
+    public Context mContext;
+
+    public BaseListAdapter(Context mContext) {
+        this.mContext = mContext;
+    }
+
+    public BaseListAdapter(Context mContext, List<T> mData) {
+        this.mContext = mContext;
+        this.mData = mData;
+    }
+
+    /**
+     * 更新数据
+     *
+     * @param mData
+     */
+    public void updateData(List<T> mData) {
+        this.mData = mData;
+        notifyDataSetChanged();
+    }
+
+    @Override
+    public int getCount() {
+        return mData == null ? 0 : mData.size();
+    }
+
+    @Override
+    public T getItem(int position) {
+        return mData == null ? null : mData.get(position);
+    }
+
+    @Override
+    public long getItemId(int position) {
+        return 0;
+    }
+
+    @Override
+    public View getView(int position, View convertView, ViewGroup parent) {
+        Z holder = null;
+        if (convertView == null) {
+            holder = getViewHolder();
+            convertView = holder.getView();
+            convertView.setTag(holder);
+        } else {
+            holder = (Z) convertView.getTag();
+        }
+        holder.initData(getItem(position));
+        return convertView;
+    }
+
+    public abstract Z getViewHolder();
+}

+ 50 - 0
app/src/main/java/com/webrain/happywork/ui/adapter/listview/DemandListAdapter.java

@@ -0,0 +1,50 @@
+package com.webrain.happywork.ui.adapter.listview;
+
+import android.content.Context;
+import android.content.Intent;
+import android.view.View;
+import android.widget.AdapterView;
+
+import com.webrain.happywork.R;
+import com.webrain.happywork.ui.activity.DemandDetailActivity;
+import com.webrain.happywork.ui.adapter.base.BaseListAdapter;
+import com.webrain.happywork.ui.base.BaseViewHolder;
+
+public class DemandListAdapter extends BaseListAdapter<String, DemandListAdapter.DemandListViewHolder> implements AdapterView.OnItemClickListener {
+
+    public DemandListAdapter(Context mContext) {
+        super(mContext);
+    }
+
+    @Override
+    public int getCount() {
+        return 10;
+    }
+
+    @Override
+    public DemandListViewHolder getViewHolder() {
+        return new DemandListViewHolder(mContext);
+    }
+
+    @Override
+    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+        mContext.startActivity(new Intent(mContext, DemandDetailActivity.class));
+    }
+
+    class DemandListViewHolder extends BaseViewHolder<String> {
+
+        public DemandListViewHolder(Context mContext) {
+            super(mContext);
+        }
+
+        @Override
+        public int bindViewLayoutId() {
+            return R.layout.item_list_demand;
+        }
+
+        @Override
+        public void initData(String obj) {
+
+        }
+    }
+}

+ 35 - 0
app/src/main/java/com/webrain/happywork/ui/adapter/listview/MineApplyListAdapter.java

@@ -0,0 +1,35 @@
+package com.webrain.happywork.ui.adapter.listview;
+
+import android.content.Context;
+
+import com.webrain.happywork.R;
+import com.webrain.happywork.ui.adapter.base.BaseListAdapter;
+import com.webrain.happywork.ui.base.BaseViewHolder;
+
+public class MineApplyListAdapter extends BaseListAdapter<String, MineApplyListAdapter.MineApplyViewHolder> {
+    public MineApplyListAdapter(Context mContext) {
+        super(mContext);
+    }
+
+    @Override
+    public int getCount() {
+        return 10;
+    }
+
+    @Override
+    public MineApplyViewHolder getViewHolder() {
+        return new MineApplyViewHolder(mContext);
+    }
+
+    class MineApplyViewHolder extends BaseViewHolder<String> {
+
+        public MineApplyViewHolder(Context mContext) {
+            super(mContext);
+        }
+
+        @Override
+        public int bindViewLayoutId() {
+            return R.layout.item_list_mine_apply;
+        }
+    }
+}

+ 79 - 0
app/src/main/java/com/webrain/happywork/ui/base/BaseActionBarMenuHolder.java

@@ -0,0 +1,79 @@
+package com.webrain.happywork.ui.base;
+
+import android.content.Context;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.webrain.happywork.R;
+import com.webrain.happywork.callback.OnActionBarMenuClickListener;
+
+import butterknife.BindView;
+import butterknife.OnClick;
+
+public class BaseActionBarMenuHolder extends BaseViewHolder {
+    @BindView(R.id.iv_menu)
+    ImageView ivMenu;
+    @BindView(R.id.ll_menu)
+    LinearLayout llMenu;
+    @BindView(R.id.tv_menu)
+    TextView tvMenu;
+
+    private int resId;
+    private OnActionBarMenuClickListener onClickListener;
+
+    public BaseActionBarMenuHolder(Context mContext) {
+        super(mContext);
+    }
+
+    @Override
+    public int bindViewLayoutId() {
+        return R.layout.view_action_bar_menu;
+    }
+
+
+    @OnClick(R.id.ll_menu)
+    public void onClick(View view) {
+        if (resId != 0 && onClickListener != null)
+            onClickListener.onClick(resId);
+    }
+
+    /**
+     * 设置监听
+     *
+     * @param onClickListener
+     */
+    public void setOnClickListener(OnActionBarMenuClickListener onClickListener) {
+        this.onClickListener = onClickListener;
+    }
+
+    /**
+     * 设置menu图标
+     *
+     * @param resId
+     */
+    public void initMenu(int resId) {
+        if (resId != 0) {
+            this.resId = resId;
+            ivMenu.setImageResource(resId);
+            ivMenu.setVisibility(View.VISIBLE);
+            tvMenu.setVisibility(View.GONE);
+        }
+    }
+
+    /**
+     * 设置menu文本
+     *
+     * @param resId
+     */
+    public void initMenuText(int resId) {
+        if (resId != 0) {
+            this.resId = resId;
+            ivMenu.setVisibility(View.GONE);
+            tvMenu.setVisibility(View.VISIBLE);
+            tvMenu.setText(resId);
+        }
+    }
+
+}

+ 193 - 0
app/src/main/java/com/webrain/happywork/ui/base/BaseActivity.java

@@ -0,0 +1,193 @@
+package com.webrain.happywork.ui.base;
+
+import android.app.Activity;
+import android.content.Context;
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.text.TextUtils;
+import android.view.View;
+
+import com.trello.rxlifecycle2.components.support.RxAppCompatActivity;
+import com.webrain.happywork.callback.OnActionBarMenuClickListener;
+
+public abstract class BaseActivity<P extends IPresenter> extends RxAppCompatActivity implements IView {
+    public P mvpPresenter;
+    protected Context mContext;
+    private BaseActivityHolder mBaseHolder;
+
+
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        getSupportActionBar().hide();
+        mContext = this;
+        mvpPresenter = bindPresenter();
+        mBaseHolder = new BaseActivityHolder(this, isImmersion());
+        mBaseHolder.initActionBar(isShowStatusTitle(), isShowActionBar());
+        mBaseHolder.initActivityContent(getLayoutId());
+        setContentView(mBaseHolder.getView());
+
+    }
+
+    /**
+     * 获取子类activity布局layoutId
+     *
+     * @return layoutId
+     */
+    public abstract int getLayoutId();
+
+    /**
+     * 绑定Presenter
+     *
+     * @return
+     */
+    public abstract P bindPresenter();
+
+    @Override
+    protected void onDestroy() {
+        super.onDestroy();
+        //在生命周期结束时,将presenter与view之间的联系断开,防止出现内存泄露
+        if (mvpPresenter != null) {
+            mvpPresenter.detachView();
+        }
+    }
+
+    @Override
+    public Activity getSelfActivity() {
+        return this;
+    }
+
+    /**
+     * 是否显示标题栏
+     *
+     * @return
+     */
+    public boolean isShowActionBar() {
+        return true;
+    }
+
+    /**
+     * 是否显示状态栏
+     *
+     * @return
+     */
+    public boolean isShowStatusTitle() {
+        return true;
+    }
+
+    /**
+     * 是否显示沉浸式
+     *
+     * @return
+     */
+    public boolean isImmersion() {
+        return false;
+    }
+
+    /**
+     * 设置标题
+     *
+     * @param title
+     */
+    public void setTitle(String title) {
+        if (!TextUtils.isEmpty(title)) {
+            mBaseHolder.setTitle(title);
+        }
+    }
+
+    /**
+     * 设置标题
+     *
+     * @param ids
+     */
+    public void setTitle(int ids) {
+        if (ids != 0) {
+            mBaseHolder.setTitle(getString(ids));
+        }
+    }
+
+
+    /**
+     * 设置标题背景
+     *
+     * @param resource
+     */
+    public void setActionBarBackgroundResource(int resource) {
+        mBaseHolder.setActionBarBackgroundResource(resource);
+    }
+
+    /**
+     * 设置按钮
+     *
+     * @param resIds
+     * @param clickListener
+     */
+    public void setActionBarMenu(OnActionBarMenuClickListener clickListener, int... resIds) {
+        mBaseHolder.setActionBarMenu(resIds, clickListener);
+    }
+
+    /**
+     * 设置按钮
+     *
+     * @param resIds
+     * @param clickListener
+     */
+    public void setActionBarMenuText(OnActionBarMenuClickListener clickListener, int... resIds) {
+        mBaseHolder.setActionBarMenuText(resIds, clickListener);
+    }
+
+
+    /**
+     * 是否显示错误信息
+     *
+     * @param isVisible
+     */
+    public void setErrorVisible(boolean isVisible) {
+        mBaseHolder.setErrorVisible(isVisible);
+    }
+
+    /**
+     * 是否显示加载中
+     *
+     * @param isVisible
+     */
+    public void setLoadingVisible(boolean isVisible) {
+        mBaseHolder.setLoadingVisible(isVisible);
+    }
+
+    /**
+     * 设置back箭头颜色
+     *
+     * @param resId
+     */
+    public void setBackColor(int resId) {
+        if (resId != 0)
+            mBaseHolder.setBackColor(resId);
+    }
+
+    /**
+     * 设置刷新点击效果
+     *
+     * @param onRefreshClickListener
+     */
+    public void setOnRefreshClickListener(View.OnClickListener onRefreshClickListener) {
+        mBaseHolder.setOnRefreshClickListener(onRefreshClickListener);
+    }
+
+    /**
+     * 设置返回点击效果
+     *
+     * @param onRefreshClickListener
+     */
+    public void setOnBackClistener(View.OnClickListener onRefreshClickListener) {
+        mBaseHolder.setOnBackClickListener(onRefreshClickListener);
+    }
+
+    /**
+     * 设置标题置左
+     */
+    public void initLeftTitle() {
+        mBaseHolder.initLeftTitle();
+    }
+
+}

+ 328 - 0
app/src/main/java/com/webrain/happywork/ui/base/BaseActivityHolder.java

@@ -0,0 +1,328 @@
+package com.webrain.happywork.ui.base;
+
+import android.support.v4.content.ContextCompat;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+
+import com.webrain.baselibrary.utils.PxUtils;
+import com.webrain.happywork.R;
+import com.webrain.happywork.callback.OnActionBarMenuClickListener;
+
+import butterknife.BindView;
+import butterknife.ButterKnife;
+import butterknife.OnClick;
+
+public class BaseActivityHolder extends BaseViewHolder {
+    BaseActivity mContext;
+    @BindView(R.id.v_padding)
+    View vPadding;
+    @BindView(R.id.ll_back)
+    LinearLayout llBack;
+    @BindView(R.id.tv_title)
+    TextView tvTitle;
+    @BindView(R.id.ll_base_title)
+    LinearLayout llBaseTitle;
+    @BindView(R.id.ll_base_content)
+    LinearLayout llBaseConetent;
+    @BindView(R.id.ll_base_loading)
+    LinearLayout llBaseLoading;
+    @BindView(R.id.tv_base_error)
+    TextView tvBaseError;
+    @BindView(R.id.btn_base_retry)
+    Button btnBaseRetry;
+    @BindView(R.id.ll_base_error)
+    LinearLayout llBaseError;
+    @BindView(R.id.ll_base_menu)
+    LinearLayout llBaseMenu;
+    @BindView(R.id.v_immersion_padding)
+    View vImmersionPadding;
+    @BindView(R.id.tv_immersion_title)
+    TextView tvImmersionTitle;
+    @BindView(R.id.ll_menu)
+    LinearLayout llMenu;
+    @BindView(R.id.ll_immersion_title)
+    LinearLayout llImmersionTitle;
+    @BindView(R.id.iv_back)
+    ImageView ivBack;
+    @BindView(R.id.iv_immersion_back)
+    ImageView ivImmersionBack;
+    @BindView(R.id.ll_immersion_back)
+    LinearLayout llImmersionBack;
+    @BindView(R.id.v_load_padding)
+    View vLoadPadding;
+    @BindView(R.id.v_error_padding)
+    View vErrorPadding;
+
+    private boolean isImmersion;//是否未沉浸式标题
+    private View.OnClickListener onClickListener;//刷新按钮点击效果
+    private View.OnClickListener onBackClickListener;//返回按钮点击效果
+
+    public BaseActivityHolder(BaseActivity mContext, boolean isImmersion) {
+        super(mContext);
+        this.mContext = mContext;
+        this.isImmersion = isImmersion;
+    }
+
+    @Override
+    public int bindViewLayoutId() {
+        return R.layout.base_activity_layout;
+    }
+
+    @OnClick({R.id.ll_back, R.id.ll_immersion_back, R.id.btn_base_retry})
+    void onClick(View view) {
+        switch (view.getId()) {
+            case R.id.ll_back:
+                if (onBackClickListener != null) {
+                    onBackClickListener.onClick(view);
+                } else {
+                    mContext.finish();
+                }
+                break;
+            case R.id.ll_immersion_back:
+                if (onBackClickListener != null) {
+                    onBackClickListener.onClick(view);
+                } else {
+                    mContext.finish();
+                }
+                break;
+            case R.id.btn_base_retry:
+                if (onClickListener != null)
+                    onClickListener.onClick(view);
+                break;
+        }
+    }
+
+    /**
+     * 设置标题和状态栏
+     *
+     * @param isShowStatus
+     * @param isShowActionBar
+     */
+    public void initActionBar(boolean isShowStatus, boolean isShowActionBar) {
+        if (isImmersion) {
+            //设置沉浸式头部高度
+            RelativeLayout.LayoutParams p = (RelativeLayout.LayoutParams) llImmersionTitle.getLayoutParams();
+            ViewGroup.LayoutParams params = vImmersionPadding.getLayoutParams();
+            params.height = isShowStatus ? PxUtils.getStatusTitleHeight(mContext) : 0;
+            p.height = isShowActionBar ? params.height + mContext.getResources().getDimensionPixelSize(R.dimen.title_height) : params.height;
+            llImmersionTitle.setLayoutParams(p);
+            llImmersionTitle.setVisibility(View.VISIBLE);
+            llBaseTitle.setVisibility(View.GONE);
+            //设置沉浸式错误界面和loading界面头部padding
+            LinearLayout.LayoutParams errorPaddingLayoutParams = (LinearLayout.LayoutParams) vErrorPadding.getLayoutParams();
+            errorPaddingLayoutParams.height = PxUtils.getStatusTitleHeight(mContext) + mContext.getResources().getDimensionPixelSize(R.dimen.title_height);
+            vErrorPadding.setLayoutParams(errorPaddingLayoutParams);
+            LinearLayout.LayoutParams loadPaddingLayoutParams = (LinearLayout.LayoutParams) vLoadPadding.getLayoutParams();
+            loadPaddingLayoutParams.height = PxUtils.getStatusTitleHeight(mContext) + mContext.getResources().getDimensionPixelSize(R.dimen.title_height);
+            vLoadPadding.setLayoutParams(errorPaddingLayoutParams);
+        } else {
+            //设置头部高度
+            RelativeLayout.LayoutParams p = (RelativeLayout.LayoutParams) llBaseTitle.getLayoutParams();
+            ViewGroup.LayoutParams params = vPadding.getLayoutParams();
+            params.height = isShowStatus ? PxUtils.getStatusTitleHeight(mContext) : 0;
+            p.height = isShowActionBar ? params.height + mContext.getResources().getDimensionPixelSize(R.dimen.title_height) : params.height;
+            llBaseTitle.setLayoutParams(p);
+            llBaseTitle.setVisibility(View.VISIBLE);
+            llImmersionTitle.setVisibility(View.GONE);
+            //设置错误界面和loading界面头部padding
+            LinearLayout.LayoutParams errorPaddingLayoutParams = (LinearLayout.LayoutParams) vErrorPadding.getLayoutParams();
+            errorPaddingLayoutParams.height = PxUtils.getStatusTitleHeight(mContext) + mContext.getResources().getDimensionPixelSize(R.dimen.title_height) - p.height;
+            vErrorPadding.setLayoutParams(errorPaddingLayoutParams);
+            LinearLayout.LayoutParams loadPaddingLayoutParams = (LinearLayout.LayoutParams) vLoadPadding.getLayoutParams();
+            loadPaddingLayoutParams.height = PxUtils.getStatusTitleHeight(mContext) + mContext.getResources().getDimensionPixelSize(R.dimen.title_height) - p.height;
+            vLoadPadding.setLayoutParams(errorPaddingLayoutParams);
+        }
+    }
+
+    /**
+     * 设置Activity内容
+     *
+     * @param layoutId
+     */
+    public void initActivityContent(int layoutId) {
+        LayoutInflater inflater = LayoutInflater.from(mContext);
+        LinearLayout.LayoutParams param = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT);
+        View view = inflater.inflate(layoutId, null);
+        llBaseConetent.removeAllViews();
+        llBaseConetent.addView(view, param);
+        ButterKnife.bind(mContext, llBaseConetent);
+    }
+
+    /**
+     * 设置标题
+     *
+     * @param title
+     */
+    public void setTitle(String title) {
+        if (title != null)
+            if (isImmersion)
+                tvImmersionTitle.setText(title);
+            else
+                tvTitle.setText(title);
+    }
+
+    /**
+     * 设置标题字颜色
+     *
+     * @param resId
+     */
+    public void setTitleColor(int resId) {
+        if (resId != 0)
+            if (isImmersion)
+                tvImmersionTitle.setTextColor(mContext.getResources().getColorStateList(resId));
+            else
+                tvTitle.setTextColor(mContext.getResources().getColorStateList(resId));
+    }
+
+    /**
+     * 设置back箭头颜色
+     *
+     * @param resId
+     */
+    public void setBackColor(int resId) {
+        if (isImmersion) {
+            ivImmersionBack.setColorFilter(ContextCompat.getColor(mContext, resId));
+        } else {
+            ivBack.setColorFilter(ContextCompat.getColor(mContext, resId));
+        }
+    }
+
+
+    /**
+     * 设置按钮
+     *
+     * @param resIds        图标资源
+     * @param clickListener 按钮监听
+     */
+    public void setActionBarMenu(int[] resIds, OnActionBarMenuClickListener clickListener) {
+        LinearLayout linearLayout;
+        if (isImmersion) {
+            linearLayout = llMenu;
+        } else {
+            linearLayout = llBaseMenu;
+        }
+        linearLayout.removeAllViews();
+        if (resIds != null)
+            for (int res : resIds) {
+                BaseActionBarMenuHolder menuHolder = new BaseActionBarMenuHolder(mContext);
+                menuHolder.initMenu(res);
+                menuHolder.setOnClickListener(clickListener);
+                linearLayout.addView(menuHolder.getView());
+            }
+    }
+
+    /**
+     * 设置按钮
+     *
+     * @param resIds        图标资源
+     * @param clickListener 按钮监听
+     */
+    public void setActionBarMenuText(int[] resIds, OnActionBarMenuClickListener clickListener) {
+        LinearLayout linearLayout;
+        if (isImmersion) {
+            linearLayout = llMenu;
+        } else {
+            linearLayout = llBaseMenu;
+        }
+        linearLayout.removeAllViews();
+        if (resIds != null)
+            for (int res : resIds) {
+                BaseActionBarMenuHolder menuHolder = new BaseActionBarMenuHolder(mContext);
+                menuHolder.initMenuText(res);
+                menuHolder.setOnClickListener(clickListener);
+                linearLayout.addView(menuHolder.getView());
+            }
+    }
+
+    /**
+     * 设置标题背景
+     *
+     * @param resource
+     */
+    public void setActionBarBackgroundResource(int resource) {
+        llBaseTitle.setBackgroundResource(resource);
+    }
+
+
+    /**
+     * 设置刷新点击效果
+     *
+     * @param onClickListener
+     */
+    public void setOnRefreshClickListener(View.OnClickListener onClickListener) {
+        this.onClickListener = onClickListener;
+    }
+
+    /**
+     * 设置点击返回效果
+     *
+     * @param onBackClickListener
+     */
+    public void setOnBackClickListener(View.OnClickListener onBackClickListener) {
+        this.onBackClickListener = onBackClickListener;
+    }
+
+    /**
+     * 是否显示加载中
+     *
+     * @param isVisible
+     */
+    public void setLoadingVisible(boolean isVisible) {
+        if (isVisible) {
+            if (llBaseLoading.getVisibility() == View.GONE) {
+                llBaseConetent.setVisibility(View.GONE);
+                llBaseLoading.setVisibility(View.VISIBLE);
+                llBaseError.setVisibility(View.GONE);
+            }
+        } else {
+            if (llBaseLoading.getVisibility() == View.VISIBLE) {
+                llBaseConetent.setVisibility(View.VISIBLE);
+                llBaseLoading.setVisibility(View.GONE);
+                llBaseError.setVisibility(View.GONE);
+            }
+        }
+
+    }
+
+    /**
+     * 是否显示错误
+     *
+     * @param isVisible
+     */
+    public void setErrorVisible(boolean isVisible) {
+        if (isVisible) {
+            if (llBaseError.getVisibility() == View.GONE) {
+                llBaseConetent.setVisibility(View.GONE);
+                llBaseError.setVisibility(View.VISIBLE);
+                llBaseLoading.setVisibility(View.GONE);
+            }
+        } else {
+            if (llBaseError.getVisibility() == View.VISIBLE) {
+                llBaseConetent.setVisibility(View.VISIBLE);
+                llBaseLoading.setVisibility(View.GONE);
+                llBaseError.setVisibility(View.GONE);
+            }
+        }
+    }
+
+    /**
+     * 设置标题置左
+     */
+    public void initLeftTitle() {
+        llBack.setVisibility(View.GONE);
+        llImmersionBack.setVisibility(View.GONE);
+        RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) tvTitle.getLayoutParams();
+        layoutParams.removeRule(RelativeLayout.CENTER_IN_PARENT);
+        layoutParams.addRule(RelativeLayout.CENTER_VERTICAL);
+        layoutParams.setMargins(PxUtils.dip2px(20), 0, 0, 0);
+        tvTitle.setLayoutParams(layoutParams);
+
+    }
+
+}

+ 185 - 0
app/src/main/java/com/webrain/happywork/ui/base/BaseFragment.java

@@ -0,0 +1,185 @@
+package com.webrain.happywork.ui.base;
+
+import android.app.Activity;
+import android.content.Context;
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.text.TextUtils;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.trello.rxlifecycle2.components.support.RxFragment;
+import com.webrain.happywork.callback.OnActionBarMenuClickListener;
+
+import butterknife.Unbinder;
+
+public abstract class BaseFragment<P extends IPresenter> extends RxFragment implements IView {
+    public P mvpPresenter;
+    protected Context mContext;
+    private BaseFragmentHolder mBaseHolder;
+    private Unbinder unbinder;
+
+    @Override
+    public void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        mContext = getActivity();
+    }
+
+    @Override
+    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
+        super.onActivityCreated(savedInstanceState);
+        mContext = getActivity();
+    }
+
+    @Nullable
+    @Override
+    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
+        if (mBaseHolder == null) {
+            mBaseHolder = new BaseFragmentHolder(mContext, isImmersion());
+            mBaseHolder.initActionBar(isShowStatusTitle(), isShowActionBar());
+            unbinder = mBaseHolder.initFragmentContent(this, getLayoutId());
+        }
+        mvpPresenter = bindPresenter();
+        return mBaseHolder.getView();
+    }
+
+    @Override
+    public void onDestroyView() {
+        super.onDestroyView();
+        //在生命周期结束时,将presenter与view之间的联系断开,防止出现内存泄露
+        if (mvpPresenter != null) {
+            mvpPresenter.detachView();
+        }
+        unbinder.unbind();
+    }
+
+    @Override
+    public Activity getSelfActivity() {
+        return getActivity();
+    }
+
+    /**
+     * 获取子类fragment布局layoutId
+     *
+     * @return layoutId
+     */
+    protected abstract int getLayoutId();
+
+    /**
+     * 绑定Presenter
+     *
+     * @return
+     */
+    public abstract P bindPresenter();
+
+    /**
+     * 是否显示标题栏
+     *
+     * @return
+     */
+    public boolean isShowActionBar() {
+        return false;
+    }
+
+    /**
+     * 是否显示状态栏
+     *
+     * @return
+     */
+    public boolean isShowStatusTitle() {
+        return false;
+    }
+
+    /**
+     * 是否显示沉浸式
+     *
+     * @return
+     */
+    public boolean isImmersion() {
+        return false;
+    }
+
+    /**
+     * 设置标题
+     *
+     * @param title
+     */
+    public void setTitle(String title) {
+        if (!TextUtils.isEmpty(title)) {
+            mBaseHolder.setTitle(title);
+        }
+    }
+
+    /**
+     * 设置标题
+     *
+     * @param resId
+     */
+    public void setTitle(int resId) {
+        if (resId != 0) {
+            mBaseHolder.setTitle(getString(resId));
+        }
+    }
+
+    /**
+     * 设置标题字颜色
+     *
+     * @param resId
+     */
+    public void setTitleColor(int resId) {
+        if (resId != 0) {
+            mBaseHolder.setTitleColor(resId);
+        }
+    }
+
+
+    /**
+     * 设置标题背景
+     *
+     * @param resource
+     */
+    public void setActionBarBackgroundResource(int resource) {
+        mBaseHolder.setActionBarBackgroundResource(resource);
+    }
+
+    /**
+     * 设置按钮
+     *
+     * @param resIds
+     * @param clickListener
+     */
+    public void setActionBarMenu(OnActionBarMenuClickListener clickListener, int... resIds) {
+        mBaseHolder.setActionBarMenu(resIds, clickListener);
+    }
+
+    /**
+     * 是否显示错误信息
+     *
+     * @param isVisible
+     */
+    public void setErrorVisible(boolean isVisible) {
+        mBaseHolder.setErrorVisible(isVisible);
+    }
+
+    /**
+     * 是否显示加载中
+     *
+     * @param isVisible
+     */
+    public void setLoadingVisible(boolean isVisible) {
+        mBaseHolder.setLoadingVisible(isVisible);
+    }
+
+
+    /**
+     * 设置刷新点击效果
+     *
+     * @param onRefreshClickListener
+     */
+    public void setOnRefreshClickListener(View.OnClickListener onRefreshClickListener) {
+        mBaseHolder.setOnRefreshClickListener(onRefreshClickListener);
+    }
+
+}

+ 244 - 0
app/src/main/java/com/webrain/happywork/ui/base/BaseFragmentHolder.java

@@ -0,0 +1,244 @@
+package com.webrain.happywork.ui.base;
+
+import android.content.Context;
+import android.support.v4.app.Fragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.LinearLayout;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+
+import com.webrain.baselibrary.utils.PxUtils;
+import com.webrain.happywork.R;
+import com.webrain.happywork.callback.OnActionBarMenuClickListener;
+
+import butterknife.BindView;
+import butterknife.ButterKnife;
+import butterknife.OnClick;
+import butterknife.Unbinder;
+
+public class BaseFragmentHolder extends BaseViewHolder {
+    @BindView(R.id.ll_base_content)
+    LinearLayout llBaseContent;
+    @BindView(R.id.ll_base_loading)
+    LinearLayout llBaseLoading;
+    @BindView(R.id.tv_base_error)
+    TextView tvBaseError;
+    @BindView(R.id.btn_base_retry)
+    Button btnBaseRetry;
+    @BindView(R.id.ll_base_error)
+    LinearLayout llBaseError;
+    @BindView(R.id.v_padding)
+    View vPadding;
+    @BindView(R.id.tv_base_title)
+    TextView tvBaseTitle;
+    @BindView(R.id.ll_base_title)
+    LinearLayout llBaseTitle;
+    @BindView(R.id.v_immersion_padding)
+    View vImmersionPadding;
+    @BindView(R.id.tv_immersion_title)
+    TextView tvImmersionTitle;
+    @BindView(R.id.ll_immersion_title)
+    LinearLayout llImmersionTitle;
+    @BindView(R.id.ll_menu)
+    LinearLayout llMenu;
+    @BindView(R.id.ll_base_menu)
+    LinearLayout llBaseMenu;
+    @BindView(R.id.v_error_padding)
+    View vErrorPadding;
+    @BindView(R.id.v_load_padding)
+    View vLoadPadding;
+
+    private Context mContext;
+    private View.OnClickListener onClickListener;//刷新按钮点击效果
+    private boolean isImmersion;//是否未沉浸式标题
+
+    public BaseFragmentHolder(Context mContext, boolean isImmersion) {
+        super(mContext);
+        this.mContext = mContext;
+        this.isImmersion = isImmersion;
+    }
+
+    @Override
+    public int bindViewLayoutId() {
+        return R.layout.base_fragment_layout;
+    }
+
+    @OnClick(R.id.btn_base_retry)
+    public void onClick(View view) {
+        if (onClickListener != null)
+            onClickListener.onClick(view);
+    }
+
+    /**
+     * 设置标题和状态栏
+     *
+     * @param isShowStatus
+     * @param isShowActionBar
+     */
+    public void initActionBar(boolean isShowStatus, boolean isShowActionBar) {
+        if (isImmersion) {
+            //设置沉浸式头部高度
+            RelativeLayout.LayoutParams p = (RelativeLayout.LayoutParams) llImmersionTitle.getLayoutParams();
+            ViewGroup.LayoutParams params = vImmersionPadding.getLayoutParams();
+            params.height = isShowStatus ? PxUtils.getStatusTitleHeight(mContext) : 0;
+            p.height = isShowActionBar ? params.height + mContext.getResources().getDimensionPixelSize(R.dimen.title_height) : params.height;
+            llImmersionTitle.setLayoutParams(p);
+            llImmersionTitle.setVisibility(View.VISIBLE);
+            llBaseTitle.setVisibility(View.GONE);
+            //设置沉浸式错误界面和loading界面头部padding
+            LinearLayout.LayoutParams errorPaddingLayoutParams = (LinearLayout.LayoutParams) vErrorPadding.getLayoutParams();
+            errorPaddingLayoutParams.height = PxUtils.getStatusTitleHeight(mContext) + mContext.getResources().getDimensionPixelSize(R.dimen.title_height);
+            vErrorPadding.setLayoutParams(errorPaddingLayoutParams);
+            LinearLayout.LayoutParams loadPaddingLayoutParams = (LinearLayout.LayoutParams) vLoadPadding.getLayoutParams();
+            loadPaddingLayoutParams.height = PxUtils.getStatusTitleHeight(mContext) + mContext.getResources().getDimensionPixelSize(R.dimen.title_height);
+            vLoadPadding.setLayoutParams(errorPaddingLayoutParams);
+        } else {
+            //设置头部高度
+            RelativeLayout.LayoutParams p = (RelativeLayout.LayoutParams) llBaseTitle.getLayoutParams();
+            ViewGroup.LayoutParams params = vPadding.getLayoutParams();
+            params.height = isShowStatus ? PxUtils.getStatusTitleHeight(mContext) : 0;
+            p.height = isShowActionBar ? params.height + mContext.getResources().getDimensionPixelSize(R.dimen.title_height) : params.height;
+            llBaseTitle.setLayoutParams(p);
+            llBaseTitle.setVisibility(View.VISIBLE);
+            llImmersionTitle.setVisibility(View.GONE);
+            //设置错误界面和loading界面头部padding
+            LinearLayout.LayoutParams errorPaddingLayoutParams = (LinearLayout.LayoutParams) vErrorPadding.getLayoutParams();
+            errorPaddingLayoutParams.height = PxUtils.getStatusTitleHeight(mContext) + mContext.getResources().getDimensionPixelSize(R.dimen.title_height) - p.height;
+            vErrorPadding.setLayoutParams(errorPaddingLayoutParams);
+            LinearLayout.LayoutParams loadPaddingLayoutParams = (LinearLayout.LayoutParams) vLoadPadding.getLayoutParams();
+            loadPaddingLayoutParams.height = PxUtils.getStatusTitleHeight(mContext) + mContext.getResources().getDimensionPixelSize(R.dimen.title_height) - p.height;
+            vLoadPadding.setLayoutParams(errorPaddingLayoutParams);
+        }
+    }
+
+    /**
+     * 设置Fragment内容
+     *
+     * @param layoutId
+     */
+    public Unbinder initFragmentContent(Fragment fragment, int layoutId) {
+        LayoutInflater inflater = LayoutInflater.from(mContext);
+        LinearLayout.LayoutParams param = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT);
+        View view = inflater.inflate(layoutId, null);
+        llBaseContent.removeAllViews();
+        llBaseContent.addView(view, param);
+        return ButterKnife.bind(fragment, llBaseContent);
+    }
+
+    /**
+     * 设置标题
+     *
+     * @param title
+     */
+    public void setTitle(String title) {
+        if (title != null) {
+            if (isImmersion)
+                tvImmersionTitle.setText(title);
+            else
+                tvBaseTitle.setText(title);
+        }
+
+    }
+
+    /**
+     * 设置标题字颜色
+     *
+     * @param resId
+     */
+    public void setTitleColor(int resId) {
+        if (resId != 0)
+            if (isImmersion)
+                tvImmersionTitle.setTextColor(mContext.getResources().getColorStateList(resId));
+            else
+                tvBaseTitle.setTextColor(mContext.getResources().getColorStateList(resId));
+    }
+
+    /**
+     * 设置按钮
+     *
+     * @param resIds        图标资源
+     * @param clickListener 按钮监听
+     */
+    public void setActionBarMenu(int[] resIds, OnActionBarMenuClickListener clickListener) {
+        LinearLayout linearLayout;
+        if (isImmersion) {
+            linearLayout = llMenu;
+        } else {
+            linearLayout = llBaseMenu;
+        }
+        linearLayout.removeAllViews();
+        if (resIds != null)
+            for (int res : resIds) {
+                BaseActionBarMenuHolder menuHolder = new BaseActionBarMenuHolder(mContext);
+                menuHolder.initMenu(res);
+                menuHolder.setOnClickListener(clickListener);
+                linearLayout.addView(menuHolder.getView());
+            }
+
+    }
+
+    /**
+     * 设置标题背景
+     *
+     * @param resource
+     */
+    public void setActionBarBackgroundResource(int resource) {
+        llBaseTitle.setBackgroundResource(resource);
+    }
+
+    /**
+     * 是否显示加载中
+     *
+     * @param isVisible
+     */
+    public void setLoadingVisible(boolean isVisible) {
+        if (isVisible) {
+            if (llBaseLoading.getVisibility() == View.GONE) {
+                llBaseContent.setVisibility(View.GONE);
+                llBaseLoading.setVisibility(View.VISIBLE);
+                llBaseError.setVisibility(View.GONE);
+            }
+        } else {
+            if (llBaseLoading.getVisibility() == View.VISIBLE) {
+                llBaseContent.setVisibility(View.VISIBLE);
+                llBaseLoading.setVisibility(View.GONE);
+                llBaseError.setVisibility(View.GONE);
+            }
+        }
+
+    }
+
+    /**
+     * 设置刷新点击效果
+     *
+     * @param onClickListener
+     */
+    public void setOnRefreshClickListener(View.OnClickListener onClickListener) {
+        this.onClickListener = onClickListener;
+    }
+
+    /**
+     * 是否显示错误信息
+     *
+     * @param isVisible
+     */
+    public void setErrorVisible(boolean isVisible) {
+        if (isVisible) {
+            if (llBaseError.getVisibility() == View.GONE) {
+                llBaseContent.setVisibility(View.GONE);
+                llBaseError.setVisibility(View.VISIBLE);
+                llBaseLoading.setVisibility(View.GONE);
+            }
+        } else {
+            if (llBaseError.getVisibility() == View.VISIBLE) {
+                llBaseContent.setVisibility(View.VISIBLE);
+                llBaseLoading.setVisibility(View.GONE);
+                llBaseError.setVisibility(View.GONE);
+            }
+        }
+    }
+
+}

+ 12 - 0
app/src/main/java/com/webrain/happywork/ui/base/BaseModel.java

@@ -0,0 +1,12 @@
+package com.webrain.happywork.ui.base;
+
+import android.content.Context;
+
+public class BaseModel {
+    public Context mContext;
+
+    public BaseModel(Context mContext) {
+        this.mContext = mContext;
+    }
+
+}

+ 46 - 0
app/src/main/java/com/webrain/happywork/ui/base/BasePresenter.java

@@ -0,0 +1,46 @@
+package com.webrain.happywork.ui.base;
+
+import java.lang.ref.Reference;
+import java.lang.ref.WeakReference;
+
+public abstract class BasePresenter<V extends IView> implements IPresenter {
+
+    // 此处使用弱引用是因为,有时Activity关闭不一定会走onDestroy,所以这时使用弱引用可以及时回收IView
+    protected Reference<V> mvpReference;
+
+    public BasePresenter(V view) {
+        attachView(view);
+    }
+
+    private void attachView(V view) {
+        mvpReference = new WeakReference<V>(view);
+    }
+
+    protected V getView() {
+        if (mvpReference != null) {
+            return mvpReference.get();
+        }
+        return null;
+    }
+
+    /**
+     * 主要用于判断IView的生命周期是否结束,防止出现内存泄露状况
+     *
+     * @return
+     */
+    protected boolean isViewAttach() {
+        return mvpReference != null && mvpReference.get() != null;
+    }
+
+    /**
+     * Activity生命周期结束时,Presenter也清除IView对象,不在持有
+     */
+    @Override
+    public void detachView() {
+        if (mvpReference != null) {
+            mvpReference.clear();
+            mvpReference = null;
+        }
+    }
+
+}

+ 51 - 0
app/src/main/java/com/webrain/happywork/ui/base/BaseViewHolder.java

@@ -0,0 +1,51 @@
+package com.webrain.happywork.ui.base;
+
+import android.content.Context;
+import android.view.View;
+
+import butterknife.ButterKnife;
+
+/**
+ * Holder
+ */
+public abstract class BaseViewHolder<T> {
+    /**
+     * Holder所绑定的View
+     */
+    public View holderView;
+    /**
+     * 上下文
+     */
+    public Context mContext;
+
+
+    public BaseViewHolder(Context mContext) {
+        if (mContext != null) {
+            this.mContext = mContext;
+            holderView = View.inflate(mContext, bindViewLayoutId(), null);
+            ButterKnife.bind(this, holderView);
+        }
+
+    }
+
+    /**
+     * 返回View
+     *
+     * @return
+     */
+    public View getView() {
+        return holderView;
+    }
+
+    /**
+     * 获取View資源文件ID
+     *
+     * @return
+     */
+    public abstract int bindViewLayoutId();
+
+    public void initData(T obj) {
+
+    }
+
+}

+ 5 - 0
app/src/main/java/com/webrain/happywork/ui/base/IPresenter.java

@@ -0,0 +1,5 @@
+package com.webrain.happywork.ui.base;
+
+public interface IPresenter {
+    void detachView();
+}

+ 7 - 0
app/src/main/java/com/webrain/happywork/ui/base/IView.java

@@ -0,0 +1,7 @@
+package com.webrain.happywork.ui.base;
+
+import android.app.Activity;
+
+public interface IView {
+    Activity getSelfActivity();
+}

+ 15 - 0
app/src/main/java/com/webrain/happywork/ui/mvp/contacts/DemandDetailContacts.java

@@ -0,0 +1,15 @@
+package com.webrain.happywork.ui.mvp.contacts;
+
+import com.webrain.happywork.ui.base.IPresenter;
+import com.webrain.happywork.ui.base.IView;
+
+public class DemandDetailContacts {
+    public interface IDemandDetailView extends IView {
+    }
+
+    public interface IDemandDetailPresenter extends IPresenter {
+    }
+
+    public interface IDemandDetailModel {
+    }
+}

+ 29 - 0
app/src/main/java/com/webrain/happywork/ui/mvp/contacts/LoginContacts.java

@@ -0,0 +1,29 @@
+package com.webrain.happywork.ui.mvp.contacts;
+
+import com.webrain.happywork.callback.MvpDataCallBack;
+import com.webrain.happywork.ui.base.IPresenter;
+import com.webrain.happywork.ui.base.IView;
+
+public class LoginContacts {
+    public interface ILoginView extends IView {
+        void onSpannableInit();
+    }
+
+    public interface ILoginPresenter extends IPresenter {
+        void getAuthCode(String phoneNum);
+
+        void httpLogin(String phoneNum, String code);
+
+        boolean isPhone(String phoneNum, boolean isToast);
+
+        boolean isCode(String code, boolean isToast);
+
+        void init();
+    }
+
+    public interface ILoginModel {
+        void getHttpAuthCode(String phoneNum);
+
+        void httpLogin(String phoneNum, String code, String clientId, MvpDataCallBack<Boolean> mvpDataCallBack);
+    }
+}

+ 15 - 0
app/src/main/java/com/webrain/happywork/ui/mvp/contacts/MainContacts.java

@@ -0,0 +1,15 @@
+package com.webrain.happywork.ui.mvp.contacts;
+
+import com.webrain.happywork.ui.base.IPresenter;
+import com.webrain.happywork.ui.base.IView;
+
+public class MainContacts {
+    public interface IMainView extends IView {
+    }
+
+    public interface IMainPresenter extends IPresenter {
+    }
+
+    public interface IMainModel {
+    }
+}

+ 15 - 0
app/src/main/java/com/webrain/happywork/ui/mvp/contacts/MineApplyListContacts.java

@@ -0,0 +1,15 @@
+package com.webrain.happywork.ui.mvp.contacts;
+
+import com.webrain.happywork.ui.base.IPresenter;
+import com.webrain.happywork.ui.base.IView;
+
+public class MineApplyListContacts {
+    public interface IMineApplyListView extends IView {
+    }
+
+    public interface IMineApplyListPresenter extends IPresenter {
+    }
+
+    public interface IMineApplyListModel {
+    }
+}

+ 15 - 0
app/src/main/java/com/webrain/happywork/ui/mvp/contacts/MineCenterContacts.java

@@ -0,0 +1,15 @@
+package com.webrain.happywork.ui.mvp.contacts;
+
+import com.webrain.happywork.ui.base.IPresenter;
+import com.webrain.happywork.ui.base.IView;
+
+public class MineCenterContacts {
+    public interface IMineCenterView extends IView {
+    }
+
+    public interface IMineCenterPresenter extends IPresenter {
+    }
+
+    public interface IMineCenterModel {
+    }
+}

+ 7 - 0
app/src/main/java/com/webrain/happywork/ui/mvp/model/DemandDetailModel.java

@@ -0,0 +1,7 @@
+package com.webrain.happywork.ui.mvp.model;
+
+
+import com.webrain.happywork.ui.mvp.contacts.DemandDetailContacts;
+
+public class DemandDetailModel implements DemandDetailContacts.IDemandDetailModel {
+}

+ 17 - 0
app/src/main/java/com/webrain/happywork/ui/mvp/model/LoginModel.java

@@ -0,0 +1,17 @@
+package com.webrain.happywork.ui.mvp.model;
+
+
+import com.webrain.happywork.callback.MvpDataCallBack;
+import com.webrain.happywork.ui.mvp.contacts.LoginContacts;
+
+public class LoginModel implements LoginContacts.ILoginModel {
+    @Override
+    public void getHttpAuthCode(String phoneNum) {
+
+    }
+
+    @Override
+    public void httpLogin(String phoneNum, String code, String clientId, MvpDataCallBack<Boolean> mvpDataCallBack) {
+
+    }
+}

+ 7 - 0
app/src/main/java/com/webrain/happywork/ui/mvp/model/MainModel.java

@@ -0,0 +1,7 @@
+package com.webrain.happywork.ui.mvp.model;
+
+
+import com.webrain.happywork.ui.mvp.contacts.MainContacts;
+
+public class MainModel implements MainContacts.IMainModel {
+}

+ 7 - 0
app/src/main/java/com/webrain/happywork/ui/mvp/model/MineApplyListModel.java

@@ -0,0 +1,7 @@
+package com.webrain.happywork.ui.mvp.model;
+
+
+import com.webrain.happywork.ui.mvp.contacts.MineApplyListContacts;
+
+public class MineApplyListModel implements MineApplyListContacts.IMineApplyListModel {
+}

+ 7 - 0
app/src/main/java/com/webrain/happywork/ui/mvp/model/MineCenterModel.java

@@ -0,0 +1,7 @@
+package com.webrain.happywork.ui.mvp.model;
+
+
+import com.webrain.happywork.ui.mvp.contacts.MineCenterContacts;
+
+public class MineCenterModel implements MineCenterContacts.IMineCenterModel {
+}

+ 17 - 0
app/src/main/java/com/webrain/happywork/ui/mvp/presenter/DemandDetailPresenter.java

@@ -0,0 +1,17 @@
+package com.webrain.happywork.ui.mvp.presenter;
+
+
+import com.webrain.happywork.ui.activity.DemandDetailActivity;
+import com.webrain.happywork.ui.base.BasePresenter;
+import com.webrain.happywork.ui.mvp.contacts.DemandDetailContacts;
+import com.webrain.happywork.ui.mvp.model.DemandDetailModel;
+
+public class DemandDetailPresenter extends BasePresenter<DemandDetailActivity> implements DemandDetailContacts.IDemandDetailPresenter {
+    private DemandDetailModel mDemandDetailModel;
+
+    public DemandDetailPresenter(DemandDetailActivity view) {
+        super(view);
+        this.mDemandDetailModel = new DemandDetailModel();
+    }
+
+}

+ 80 - 0
app/src/main/java/com/webrain/happywork/ui/mvp/presenter/LoginPresenter.java

@@ -0,0 +1,80 @@
+package com.webrain.happywork.ui.mvp.presenter;
+
+
+import android.text.TextUtils;
+import android.widget.Toast;
+
+import com.webrain.happywork.R;
+import com.webrain.happywork.ui.activity.LoginActivity;
+import com.webrain.happywork.ui.base.BasePresenter;
+import com.webrain.happywork.ui.mvp.contacts.LoginContacts;
+import com.webrain.happywork.ui.mvp.model.LoginModel;
+
+public class LoginPresenter extends BasePresenter<LoginActivity> implements LoginContacts.ILoginPresenter {
+    private LoginModel mLoginModel;
+
+    public LoginPresenter(LoginActivity view) {
+        super(view);
+        this.mLoginModel = new LoginModel();
+    }
+
+    /**
+     * 获取验证码
+     *
+     * @param phoneNum
+     */
+    @Override
+    public void getAuthCode(String phoneNum) {
+        if (isViewAttach()) {
+            mLoginModel.getHttpAuthCode(phoneNum);
+        }
+    }
+
+    @Override
+    public void httpLogin(String phoneNum, String code) {
+
+    }
+
+    /**
+     * 判断手机号合法性
+     *
+     * @param phoneNum
+     * @return
+     */
+    @Override
+    public boolean isPhone(String phoneNum, boolean isToast) {
+        if (isViewAttach()) {
+            if (!TextUtils.isEmpty(phoneNum) && phoneNum.length() == 11) {
+                return true;
+            }
+            if (isToast)
+                Toast.makeText(mvpReference.get(), R.string.toast_please_input_phone_num, Toast.LENGTH_SHORT).show();
+        }
+        return false;
+    }
+
+    /**
+     * 判断验证码的合法性
+     *
+     * @param code
+     * @return
+     */
+    @Override
+    public boolean isCode(String code, boolean isToast) {
+        if (isViewAttach()) {
+            if (!TextUtils.isEmpty(code)) {
+                return true;
+            }
+            if (isToast)
+                Toast.makeText(mvpReference.get(), R.string.toast_please_input_code, Toast.LENGTH_SHORT).show();
+        }
+        return false;
+    }
+
+    @Override
+    public void init() {
+        if (isViewAttach()) {
+            mvpReference.get().onSpannableInit();
+        }
+    }
+}

+ 17 - 0
app/src/main/java/com/webrain/happywork/ui/mvp/presenter/MainPresenter.java

@@ -0,0 +1,17 @@
+package com.webrain.happywork.ui.mvp.presenter;
+
+
+import com.webrain.happywork.ui.activity.MainActivity;
+import com.webrain.happywork.ui.base.BasePresenter;
+import com.webrain.happywork.ui.mvp.contacts.MainContacts;
+import com.webrain.happywork.ui.mvp.model.MainModel;
+
+public class MainPresenter extends BasePresenter<MainActivity> implements MainContacts.IMainPresenter {
+    private MainModel mMainModel;
+
+    public MainPresenter(MainActivity view) {
+        super(view);
+        this.mMainModel = new MainModel();
+    }
+
+}

+ 17 - 0
app/src/main/java/com/webrain/happywork/ui/mvp/presenter/MineApplyListPresenter.java

@@ -0,0 +1,17 @@
+package com.webrain.happywork.ui.mvp.presenter;
+
+
+import com.webrain.happywork.ui.activity.MineApplyListActivity;
+import com.webrain.happywork.ui.base.BasePresenter;
+import com.webrain.happywork.ui.mvp.contacts.MineApplyListContacts;
+import com.webrain.happywork.ui.mvp.model.MineApplyListModel;
+
+public class MineApplyListPresenter extends BasePresenter<MineApplyListActivity> implements MineApplyListContacts.IMineApplyListPresenter {
+    private MineApplyListModel mMineApplyListModel;
+
+    public MineApplyListPresenter(MineApplyListActivity view) {
+        super(view);
+        this.mMineApplyListModel = new MineApplyListModel();
+    }
+
+}

+ 17 - 0
app/src/main/java/com/webrain/happywork/ui/mvp/presenter/MineCenterPresenter.java

@@ -0,0 +1,17 @@
+package com.webrain.happywork.ui.mvp.presenter;
+
+
+import com.webrain.happywork.ui.activity.MineCenterActivity;
+import com.webrain.happywork.ui.base.BasePresenter;
+import com.webrain.happywork.ui.mvp.contacts.MineCenterContacts;
+import com.webrain.happywork.ui.mvp.model.MineCenterModel;
+
+public class MineCenterPresenter extends BasePresenter<MineCenterActivity> implements MineCenterContacts.IMineCenterPresenter {
+    private MineCenterModel mMineCenterModel;
+
+    public MineCenterPresenter(MineCenterActivity view) {
+        super(view);
+        this.mMineCenterModel = new MineCenterModel();
+    }
+
+}

+ 33 - 0
app/src/main/java/com/webrain/happywork/ui/viewholder/DemandViewHeader.java

@@ -0,0 +1,33 @@
+package com.webrain.happywork.ui.viewholder;
+
+import android.content.Context;
+import android.view.View;
+import android.widget.TextView;
+
+import com.webrain.baselibrary.widget.banner.ViewPagerBanner;
+import com.webrain.happywork.R;
+import com.webrain.happywork.ui.base.BaseViewHolder;
+
+import butterknife.BindView;
+
+public class DemandViewHeader extends BaseViewHolder {
+
+    @BindView(R.id.vpb)
+    ViewPagerBanner vpb;
+    @BindView(R.id.tv_area)
+    TextView tvArea;
+    @BindView(R.id.tv_business)
+    TextView tvBusiness;
+    @BindView(R.id.tv_price)
+    TextView tvPrice;
+
+    public DemandViewHeader(Context mContext) {
+        super(mContext);
+    }
+
+    @Override
+    public int bindViewLayoutId() {
+        return R.layout.view_list_demand_header;
+    }
+
+}

+ 21 - 0
app/src/main/java/com/webrain/happywork/utils/AlertDialogUtils.java

@@ -0,0 +1,21 @@
+package com.webrain.happywork.utils;
+
+import android.content.Context;
+import android.content.DialogInterface;
+import android.support.v7.app.AlertDialog;
+
+public class AlertDialogUtils {
+
+    /**
+     * AlertDialog 选择队列
+     *
+     * @param mContext
+     * @param title
+     * @param item
+     * @param onClickListener
+     */
+    public static void itemSelectDialog(Context mContext, String title, String[] item, DialogInterface.OnClickListener onClickListener) {
+        new AlertDialog.Builder(mContext).setTitle(title).setItems(item, onClickListener).create().show();
+    }
+
+}

+ 144 - 0
app/src/main/java/com/webrain/happywork/utils/BitmapUtils.java

@@ -0,0 +1,144 @@
+package com.webrain.happywork.utils;
+
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.BitmapFactory.Options;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Matrix;
+import android.os.Build;
+import android.view.View;
+
+import com.webrain.baselibrary.utils.PxUtils;
+
+import java.io.ByteArrayOutputStream;
+
+public class BitmapUtils {
+
+    /**
+     * 截取View生成图片 并且不超过屏幕尺寸
+     *
+     * @param v
+     * @return
+     */
+    public static Bitmap createBitmapFromView(View v) {
+        int width = PxUtils.getDeviceWidth();
+        int height = PxUtils.getDeviceHeight();
+        if (width == 0 || width > v.getWidth())
+            width = v.getWidth();
+        if (height == 0 || height > v.getHeight())
+            height = v.getHeight();
+        Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
+        Canvas c = new Canvas(bmp);
+        c.drawColor(Color.TRANSPARENT);
+        v.draw(c);
+        return bmp;
+    }
+
+    /**
+     * 得到bitmap的大小
+     */
+    public static int getBitmapSize(Bitmap bitmap) {
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {    //API 19
+            return bitmap.getAllocationByteCount();
+        }
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1) {//API 12
+            return bitmap.getByteCount();
+        }
+        // 在低版本中用一行的字节x高度
+        return bitmap.getRowBytes() * bitmap.getHeight();                //earlier version
+    }
+
+    /**
+     * 质量压缩方法
+     *
+     * @param image
+     * @return
+     */
+    public static byte[] compressImage(Bitmap image) {
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        image.compress(Bitmap.CompressFormat.JPEG, 100, baos);// 质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中
+        int options = 90;
+        while (baos.toByteArray().length > 1024 * 128) { // 循环判断如果压缩后图片是否大于100kb,大于继续压缩
+            baos.reset(); // 重置baos即清空baos
+            image.compress(Bitmap.CompressFormat.JPEG, options, baos);// 这里压缩options%,把压缩后的数据存放到baos中
+            if (options > 10)
+                options -= 10;// 每次都减少10
+            else
+                options -= 2;
+        }
+        return baos.toByteArray();
+    }
+
+    /**
+     * 获得显示大图图片;
+     *
+     * @author zengbobo
+     */
+    public static Bitmap decodeShowBigBitmap(String path, float mScreenW,
+                                             float mScreenH) {
+        String pathName;
+        if (path.startsWith("file://")) {
+            pathName = path.replace("file://", "");
+        } else {
+            pathName = path;
+        }
+        try {
+            Options mOptions = decodeOptions(pathName);
+            if (mOptions == null) {
+                return null;
+            }
+            int width = mOptions.outWidth;
+            int height = mOptions.outHeight;
+            if (width >= mScreenW) {
+                width = (int) mScreenW;
+            }
+            if (height >= mScreenH) {
+                height = (int) mScreenH;
+            }
+            Bitmap bitmap = BitmapFactory.decodeFile(pathName);
+            int degree = PhotoUtils.readPictureDegree(pathName);
+            if (degree == 0) {
+                return bitmap;
+            }
+            Matrix m = new Matrix();
+            m.postRotate(degree);
+            Bitmap newBm = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
+                    bitmap.getHeight(), m, true);
+            if (bitmap != null && !bitmap.isRecycled()) {
+                bitmap.recycle();
+            }
+            return newBm;
+        } catch (OutOfMemoryError e) {
+            e.printStackTrace();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    /**
+     * 获得图片信息;
+     *
+     * @author zengbobo
+     */
+    public static Options decodeOptions(String pathName) {
+        if (!FileUtils.isFileExit(pathName)) {
+            return null;
+        }
+        Options mOptions = new Options();
+        mOptions.inJustDecodeBounds = true;
+        Bitmap tempBitmap = null;
+        try {
+            tempBitmap = BitmapFactory.decodeFile(pathName, mOptions);
+        } catch (OutOfMemoryError e) {
+            e.printStackTrace();
+        }
+        if (tempBitmap != null && !tempBitmap.isRecycled()) {
+            tempBitmap.recycle();
+        }
+        return mOptions;
+    }
+
+
+}

+ 249 - 0
app/src/main/java/com/webrain/happywork/utils/FileUtils.java

@@ -0,0 +1,249 @@
+package com.webrain.happywork.utils;
+
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.net.Uri;
+import android.os.Environment;
+import android.provider.MediaStore;
+import android.text.TextUtils;
+import android.view.View;
+
+import com.webrain.happywork.BuildConfig;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+public class FileUtils {
+    /**
+     * 判断文件是否存在
+     *
+     * @param pathName
+     * @return
+     */
+    public static boolean isFileExit(String pathName) {
+        if (pathName == null || TextUtils.isEmpty(pathName.trim())) {
+            return false;
+        }
+        File file = new File(pathName);
+        return file.exists() && file.isFile();
+    }
+
+    /**
+     * 根据地址获取文件
+     *
+     * @param pathName
+     * @return
+     */
+    public static File getFileFromPath(String pathName) {
+        if (pathName == null || TextUtils.isEmpty(pathName.trim())) {
+            return null;
+        }
+        File file = new File(pathName);
+        if (file.exists() && file.isFile())
+            return file;
+        return null;
+    }
+
+    /**
+     * 获取图片缓存地址
+     *
+     * @return
+     */
+    public static String getCaChePicturePath() {
+        File file = new File(new File(getSDPath(), getCacheRoot()), "picture");
+        if (!file.exists()) {
+            boolean flag = file.mkdirs();
+            LogUtils.d("flag --- " + flag);
+        }
+        return file.getAbsolutePath();
+    }
+
+    /**
+     * 保存Bitmap图片
+     *
+     * @param bitamp
+     * @param fileName
+     * @return
+     */
+    public static boolean saveBitmap(Bitmap bitamp, String fileName) {
+        if (bitamp != null) {
+            File file = new File(fileName);
+            if (!file.exists()) {
+                try {
+                    file.createNewFile();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+            FileOutputStream outputStream = null;
+            try {
+                outputStream = new FileOutputStream(file.getAbsolutePath());
+                bitamp.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
+            } catch (FileNotFoundException e) {
+                e.printStackTrace();
+                return false;
+            } finally {
+                if (outputStream != null) {
+                    try {
+                        outputStream.close();
+                    } catch (Exception ignored) {
+                    }
+                }
+            }
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * 保存bitmap到相册
+     *
+     * @param context
+     * @param bitmap
+     * @param fileName
+     * @return
+     */
+    public static boolean saveBitmapToAlbum(Context context, Bitmap bitmap, String fileName) {
+        if (bitmap != null) {
+            File file = new File(fileName);
+            if (!file.exists()) {
+                try {
+                    file.createNewFile();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+            FileOutputStream outputStream = null;
+            try {
+                outputStream = new FileOutputStream(file.getAbsolutePath());
+                bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
+
+                //把文件插入到系统图库
+                MediaStore.Images.Media.insertImage(context.getContentResolver(), file.getAbsolutePath(), fileName, null);
+                //保存图片后发送广播通知更新数据库
+                Uri uri = Uri.fromFile(file);
+                context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, uri));
+            } catch (FileNotFoundException e) {
+                e.printStackTrace();
+                return false;
+            } finally {
+                if (outputStream != null) {
+                    try {
+                        outputStream.close();
+                    } catch (Exception ignored) {
+                    }
+                }
+            }
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * 获取根目录
+     *
+     * @return
+     */
+    public static String getSDPath() {
+        boolean hasSDCard = Environment.getExternalStorageState().equals(
+                Environment.MEDIA_MOUNTED);
+        // 如果有sd卡,则返回sd卡的目录
+        if (hasSDCard) {
+            return Environment.getExternalStorageDirectory().getPath();
+        } else {
+            // 如果没有sd卡,则返回存储目录
+            return Environment.getDownloadCacheDirectory().getPath();
+        }
+    }
+
+
+    /**
+     * 获取缓存根目录
+     *
+     * @return
+     */
+    private static String getCacheRoot() {
+        String root = BuildConfig.FLAVOR + File.separator + "cache";
+        return root;
+    }
+
+    /**
+     * 删除文件夹内的文件
+     *
+     * @param dir
+     * @param delRoot
+     * @return
+     */
+    public static boolean deleteDir(File dir, boolean delRoot) {
+        if (dir.isDirectory()) {
+            String[] children = dir.list();
+            if (children != null && children.length > 0) {
+                //递归删除目录中的子目录下
+                for (int i = 0; i < children.length; i++) {
+                    boolean success = deleteDir(new File(dir, children[i]), true);
+                    if (!success) {
+                        return false;
+                    }
+                }
+            } else {
+                delRoot = true;
+            }
+        }
+        // 目录此时为空,可以删除
+        if (delRoot) {
+            return dir.delete();
+        }
+
+        return true;
+    }
+
+    /**
+     * 将文件转换成byte数组
+     *
+     * @param tradeFile
+     * @return
+     */
+    public static byte[] File2byte(File tradeFile) {
+        byte[] buffer = null;
+        try {
+            FileInputStream fis = new FileInputStream(tradeFile);
+            ByteArrayOutputStream bos = new ByteArrayOutputStream();
+            byte[] b = new byte[1024];
+            int n;
+            while ((n = fis.read(b)) != -1) {
+                bos.write(b, 0, n);
+            }
+            fis.close();
+            bos.close();
+            buffer = bos.toByteArray();
+        } catch (FileNotFoundException e) {
+            e.printStackTrace();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return buffer;
+    }
+
+
+    /**
+     * 获取截屏图片给微信使用
+     * <p>
+     * 大小不超过128KB
+     *
+     * @param view
+     * @return
+     */
+    public static byte[] getScreenshotToWeChat(View view) {
+        Bitmap bitmap = BitmapUtils.createBitmapFromView(view);
+        if (bitmap != null) {
+            return BitmapUtils.compressImage(bitmap);
+        }
+        return null;
+    }
+
+}

+ 60 - 0
app/src/main/java/com/webrain/happywork/utils/LogUtils.java

@@ -0,0 +1,60 @@
+package com.webrain.happywork.utils;
+
+import android.util.Log;
+
+import com.webrain.happywork.BuildConfig;
+
+public class LogUtils {
+    private static final String LOG_TAG = "log_tag";
+    //生产false 测试true
+    public static boolean debug = BuildConfig.DEBUG;
+
+    public static void d(String tag, String msg) {
+        if (debug) {
+            Log.d(tag, msg);
+        }
+    }
+
+    public static void d(String msg) {
+        if (debug) {
+            Log.d(LOG_TAG, msg);
+        }
+    }
+
+    public static void e(String tag, String msg) {
+        if (debug) {
+            Log.e(tag, msg);
+        }
+    }
+
+    public static void e(String msg) {
+        if (debug) {
+            Log.e(LOG_TAG, msg);
+        }
+    }
+
+    public static void i(String tag, String msg) {
+        if (debug) {
+            Log.i(tag, msg);
+        }
+    }
+
+    public static void i(String msg) {
+        if (debug) {
+            Log.i(LOG_TAG, msg);
+        }
+    }
+
+    public static void w(String tag, String msg) {
+        if (debug) {
+            Log.w(tag, msg);
+        }
+    }
+
+
+    public static void w(String msg) {
+        if (debug) {
+            Log.w(LOG_TAG, msg);
+        }
+    }
+}

+ 62 - 0
app/src/main/java/com/webrain/happywork/utils/PhotoUtils.java

@@ -0,0 +1,62 @@
+package com.webrain.happywork.utils;
+
+import android.content.Context;
+import android.media.ExifInterface;
+import android.net.Uri;
+import android.text.TextUtils;
+
+import com.webrain.baselibrary.utils.DateUtils;
+import com.webrain.baselibrary.utils.SharedPreferencesUtils;
+
+import java.io.File;
+import java.io.IOException;
+
+public class PhotoUtils {
+    /**
+     * 读取图片属性:旋转的角度
+     *
+     * @param path 图片绝对路径
+     * @return degree旋转的角度
+     */
+    public static int readPictureDegree(String path) {
+        if (TextUtils.isEmpty(path)) {
+            return 0;
+        }
+        int degree = 0;
+        try {
+            ExifInterface exifInterface = new ExifInterface(path.replace("file://", ""));
+            int orientation = exifInterface.getAttributeInt(
+                    ExifInterface.TAG_ORIENTATION,
+                    ExifInterface.ORIENTATION_NORMAL);
+            switch (orientation) {
+                case ExifInterface.ORIENTATION_ROTATE_90:
+                    degree = 90;
+                    break;
+                case ExifInterface.ORIENTATION_ROTATE_180:
+                    degree = 180;
+                    break;
+                case ExifInterface.ORIENTATION_ROTATE_270:
+                    degree = 270;
+                    break;
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return degree;
+    }
+
+    /**
+     * 获取照片缓存路径
+     * @param context
+     * @return
+     */
+    public static Uri getCameraStrImgCachePathUri(Context context) {
+        String fileName = DateUtils.getFormatDateFileName();
+        String picFilePath = FileUtils.getCaChePicturePath() + File.separator + "HappyJob_" + fileName + ".jpg";
+        File file = new File(picFilePath);
+        String path = file.getAbsolutePath();
+        SharedPreferencesUtils.setCameraImageFile(context, path.startsWith("file://") ? path : ("file://" + path));
+        return Uri.fromFile(file);
+    }
+
+}

File diff suppressed because it is too large
+ 34 - 0
app/src/main/res/drawable-v24/ic_launcher_foreground.xml


+ 9 - 0
app/src/main/res/drawable/corners_gradient_gray_5dp.xml

@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <corners android:radius="5dp" />
+    <!--圆角半径-->
+    <gradient
+        android:angle="0"
+        android:endColor="#E4E2E7"
+        android:startColor="#ECF0F3" />
+</shape>

+ 9 - 0
app/src/main/res/drawable/corners_gradient_purple_5dp.xml

@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <corners android:radius="5dp" />
+    <!--圆角半径-->
+    <gradient
+        android:angle="0"
+        android:endColor="#823BFF"
+        android:startColor="#5568F0" />
+</shape>

+ 6 - 0
app/src/main/res/drawable/corners_gray_f5_5dp.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <!--圆角半径-->
+    <corners android:radius="5dp" />
+    <solid android:color="@color/bg_gray_f5" />
+</shape>

+ 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:viewportWidth="108"
+    android:viewportHeight="108">
+    <path
+        android:fillColor="#008577"
+        android:pathData="M0,0h108v108h-108z" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M9,0L9,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,0L19,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M29,0L29,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M39,0L39,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M49,0L49,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M59,0L59,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M69,0L69,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M79,0L79,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M89,0L89,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M99,0L99,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,9L108,9"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,19L108,19"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,29L108,29"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,39L108,39"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,49L108,49"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,59L108,59"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,69L108,69"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,79L108,79"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,89L108,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,99L108,99"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,29L89,29"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,39L89,39"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,49L89,49"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,59L89,59"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,69L89,69"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,79L89,79"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M29,19L29,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M39,19L39,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M49,19L49,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M59,19L59,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M69,19L69,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M79,19L79,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+</vector>

+ 5 - 0
app/src/main/res/drawable/select_color_blue_gray.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:color="@color/text_gray_88" android:state_enabled="false" />
+    <item android:color="@color/text_blue_32" /> <!-- default -->
+</selector>

+ 5 - 0
app/src/main/res/drawable/select_corners_blue_gray.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:drawable="@drawable/corners_gradient_gray_5dp" android:state_enabled="false" />
+    <item android:drawable="@drawable/corners_gradient_purple_5dp"/>
+</selector>

+ 162 - 0
app/src/main/res/layout/activity_demand_detail.xml

@@ -0,0 +1,162 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:background="@color/bg_gray_f7"
+        android:orientation="vertical">
+
+        <RelativeLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:background="@color/white"
+            android:orientation="vertical"
+            android:paddingLeft="20dp"
+            android:paddingTop="24dp"
+            android:paddingRight="20dp"
+            android:paddingBottom="24dp">
+
+            <TextView
+                android:id="@+id/tv_price"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_alignParentRight="true"
+                android:layout_marginTop="2dp"
+                android:text="5.4K*24月"
+                android:textColor="@color/text_blue_32"
+                android:textSize="@dimen/px54_18sp" />
+
+            <TextView
+                android:id="@+id/tv_title"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_alignBottom="@id/tv_price"
+                android:layout_marginRight="5dp"
+                android:layout_toLeftOf="@id/tv_price"
+                android:singleLine="true"
+                android:text="新能源网约车服务"
+                android:textColor="@color/text_black"
+                android:textSize="@dimen/px60_20sp" />
+
+            <TextView
+                android:id="@+id/tv_num"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_below="@id/tv_price"
+                android:layout_alignParentRight="true"
+                android:layout_marginTop="2dp"
+                android:drawableLeft="@mipmap/ic_demand_detail_num"
+                android:drawablePadding="3dp"
+                android:gravity="center_vertical"
+                android:text="任务数:30"
+                android:textColor="@color/text_gray_88"
+                android:textSize="@dimen/px36_12sp" />
+
+            <TextView
+                android:id="@+id/tv_date"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_below="@id/tv_title"
+                android:layout_marginTop="2dp"
+                android:layout_marginRight="5dp"
+                android:layout_toLeftOf="@id/tv_num"
+                android:drawableLeft="@mipmap/ic_demand_detail_date"
+                android:drawablePadding="3dp"
+                android:gravity="center_vertical"
+                android:text="2019.12.12-2020.01.01"
+                android:textColor="@color/text_gray_88"
+                android:textSize="@dimen/px36_12sp" />
+
+
+        </RelativeLayout>
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="71dp"
+            android:layout_marginTop="10dp"
+            android:background="@color/white"
+            android:gravity="center_vertical"
+            android:orientation="horizontal"
+            android:paddingLeft="20dp"
+            android:paddingRight="20dp">
+
+            <View
+                android:layout_width="38dp"
+                android:layout_height="38dp"
+                android:layout_marginRight="20dp"
+                android:background="@mipmap/ic_demand_detail_company" />
+
+            <LinearLayout
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:orientation="vertical">
+
+                <TextView
+                    android:id="@+id/tv_company_name"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:text="曹操专车无锡分公司"
+                    android:textColor="@color/text_black"
+                    android:textSize="@dimen/px39_13sp" />
+
+                <TextView
+                    android:id="@+id/tv_company_address"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:layout_marginTop="5dp"
+                    android:drawableLeft="@mipmap/ic_demand_detail_location"
+                    android:drawablePadding="3dp"
+                    android:text="无锡市新吴区珠江路124号-1180"
+                    android:textColor="@color/text_gray_88"
+                    android:textSize="@dimen/px36_12sp" />
+            </LinearLayout>
+        </LinearLayout>
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="10dp"
+            android:background="@color/white"
+            android:orientation="vertical"
+            android:paddingLeft="20dp"
+            android:paddingTop="30dp"
+            android:paddingRight="20dp"
+            android:paddingBottom="30dp">
+
+            <TextView
+                android:id="@+id/tv_desc"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:lineSpacingExtra="6dp"
+                android:text="需求描述曹操专车司机,负责接送客户至网约订单目的地。 以及长途短途的订单接送。资质要求至少五年以上驾龄,25至50岁。
+相貌端正,身体健康,无不良嗜好,无犯罪史。验收标准1,完成每个月的业绩与考核; 2,顾客好评率达到验收标准; 3,无严重扣分违纪现象。"
+                android:textColor="@color/text_gray_53"
+                android:textSize="@dimen/px39_13sp" />
+        </LinearLayout>
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="10dp"
+            android:background="@color/white"
+            android:orientation="vertical">
+
+            <Button
+                android:id="@+id/btn_apply"
+                android:layout_width="match_parent"
+                android:layout_height="42dp"
+                android:layout_marginLeft="15dp"
+                android:layout_marginTop="10dp"
+                android:layout_marginRight="15dp"
+                android:layout_marginBottom="10dp"
+                android:background="@drawable/select_corners_blue_gray"
+                android:text="@string/demand_need_apply"
+                android:textColor="@color/white"
+                android:textSize="@dimen/px48_16sp" />
+        </LinearLayout>
+
+    </LinearLayout>
+</ScrollView>

+ 95 - 0
app/src/main/res/layout/activity_login.xml

@@ -0,0 +1,95 @@
+<?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:background="@color/white"
+    android:orientation="vertical"
+    android:paddingLeft="20dp"
+    android:paddingRight="20dp">
+
+    <TextView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="50dp"
+        android:text="@string/login_register"
+        android:textColor="@color/text_black"
+        android:textSize="@dimen/px60_20sp" />
+
+
+    <EditText
+        android:id="@+id/et_phone"
+        android:layout_width="match_parent"
+        android:layout_height="56dp"
+        android:layout_marginTop="24dp"
+        android:background="@null"
+        android:gravity="center_vertical"
+        android:hint="@string/hint_input_phone"
+        android:inputType="phone"
+        android:maxLength="11"
+        android:textColor="@color/text_black"
+        android:textColorHint="@color/text_gray_cd"
+        android:textSize="@dimen/px42_14sp" />
+
+    <View
+        android:layout_width="match_parent"
+        android:layout_height="1dp"
+        android:background="@color/view_line_color" />
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="56dp"
+        android:gravity="center_vertical"
+        android:orientation="horizontal">
+
+        <EditText
+            android:id="@+id/et_code"
+            android:layout_width="0dp"
+            android:layout_height="match_parent"
+            android:layout_weight="1"
+            android:background="@null"
+            android:gravity="center_vertical"
+            android:hint="@string/hint_input_code"
+            android:singleLine="true"
+            android:textColor="@color/text_black"
+            android:textColorHint="@color/text_gray_cd"
+            android:textSize="@dimen/px42_14sp" />
+
+        <TextView
+            android:id="@+id/tv_code"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:enabled="false"
+            android:gravity="center_vertical"
+            android:text="@string/get_code"
+            android:textColor="@drawable/select_color_blue_gray"
+            android:textSize="@dimen/px42_14sp" />
+    </LinearLayout>
+
+    <View
+        android:layout_width="match_parent"
+        android:layout_height="1dp"
+        android:background="@color/view_line_color" />
+
+    <TextView
+        android:id="@+id/tv_tip"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="20dp"
+        android:lineSpacingExtra="3dp"
+        android:text="@string/login_tip"
+        android:textColor="@color/text_gray_88"
+        android:textSize="@dimen/px36_12sp" />
+
+    <Button
+        android:id="@+id/btn_login"
+        android:layout_width="match_parent"
+        android:layout_height="42dp"
+        android:layout_gravity="center_horizontal"
+        android:layout_marginTop="36dp"
+        android:background="@drawable/select_corners_blue_gray"
+        android:enabled="false"
+        android:text="@string/login"
+        android:textColor="@color/white"
+        android:textSize="@dimen/px48_16sp" />
+
+</LinearLayout>

+ 89 - 0
app/src/main/res/layout/activity_main.xml

@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="@color/bg_gray_f7"
+    android:orientation="vertical">
+
+    <com.webrain.baselibrary.widget.refresh.ProgressRefreshLayout
+        android:id="@+id/prl_refresh"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
+
+        <com.webrain.baselibrary.widget.ScrollListView
+            android:id="@+id/iv_content"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:divider="@null"
+            android:dividerHeight="0px"
+            android:listSelector="@color/transparent" />
+    </com.webrain.baselibrary.widget.refresh.ProgressRefreshLayout>
+
+    <LinearLayout
+        android:id="@+id/ll_select"
+        android:layout_width="match_parent"
+        android:layout_height="57dp"
+        android:background="@color/white"
+        android:gravity="center_vertical"
+        android:orientation="horizontal"
+        android:paddingLeft="20dp"
+        android:paddingRight="20dp"
+        android:visibility="gone">
+
+        <TextView
+            android:id="@+id/tv_area"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:background="@drawable/corners_gray_f5_5dp"
+            android:drawableRight="@mipmap/ic_demand_up"
+            android:drawablePadding="5dp"
+            android:paddingLeft="10dp"
+            android:paddingTop="4dp"
+            android:paddingRight="10dp"
+            android:paddingBottom="4dp"
+            android:singleLine="true"
+            android:text="@string/all_area"
+            android:textColor="@color/text_gray_53"
+            android:textSize="@dimen/px39_13sp" />
+
+        <View
+            android:layout_width="0dp"
+            android:layout_height="1px"
+            android:layout_weight="1" />
+
+        <TextView
+            android:id="@+id/tv_business"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:background="@drawable/corners_gray_f5_5dp"
+            android:drawableRight="@mipmap/ic_demand_up_n"
+            android:drawablePadding="5dp"
+            android:paddingLeft="10dp"
+            android:paddingTop="4dp"
+            android:paddingRight="10dp"
+            android:paddingBottom="4dp"
+            android:singleLine="true"
+            android:text="@string/business"
+            android:textColor="@color/text_gray_53"
+            android:textSize="@dimen/px39_13sp" />
+
+        <TextView
+            android:id="@+id/tv_price"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginLeft="10dp"
+            android:background="@drawable/corners_gray_f5_5dp"
+            android:drawableRight="@mipmap/ic_demand_up_n"
+            android:drawablePadding="5dp"
+            android:paddingLeft="10dp"
+            android:paddingTop="4dp"
+            android:paddingRight="10dp"
+            android:paddingBottom="4dp"
+            android:singleLine="true"
+            android:text="@string/unit_price"
+            android:textColor="@color/text_gray_53"
+            android:textSize="@dimen/px39_13sp" />
+
+    </LinearLayout>
+
+</RelativeLayout>

+ 22 - 0
app/src/main/res/layout/activity_mine_apply_list.xml

@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="@color/bg_gray_f7">
+
+    <com.webrain.baselibrary.widget.refresh.ProgressRefreshLayout
+        android:id="@+id/prl_refresh"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
+
+        <ListView
+            android:id="@+id/iv_content"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:divider="@null"
+            android:dividerHeight="0px"
+            android:listSelector="@color/transparent" />
+    </com.webrain.baselibrary.widget.refresh.ProgressRefreshLayout>
+
+
+</android.support.constraint.ConstraintLayout>

+ 180 - 0
app/src/main/res/layout/activity_mine_center.xml

@@ -0,0 +1,180 @@
+<?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:background="@color/bg_gray_f7"
+    android:orientation="vertical">
+
+
+    <RelativeLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:background="@color/white">
+
+        <ImageView
+            android:id="@+id/iv_header"
+            android:layout_width="77dp"
+            android:layout_height="77dp"
+            android:layout_centerHorizontal="true"
+            android:layout_marginTop="25dp"
+            android:background="@mipmap/ic_default_header" />
+
+        <View
+            android:layout_width="20dp"
+            android:layout_height="20dp"
+            android:layout_alignRight="@id/iv_header"
+            android:layout_alignBottom="@id/iv_header"
+            android:background="@mipmap/ic_mine_setting" />
+
+        <TextView
+            android:id="@+id/tv_name"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_below="@id/iv_header"
+            android:layout_centerHorizontal="true"
+            android:layout_marginTop="14dp"
+            android:text="季明波"
+            android:textColor="@color/text_black"
+            android:textSize="@dimen/px45_15sp" />
+
+
+        <TextView
+            android:id="@+id/tv_authentication"
+            android:layout_width="56dp"
+            android:layout_height="wrap_content"
+            android:layout_below="@id/tv_name"
+            android:layout_centerHorizontal="true"
+            android:layout_marginTop="5dp"
+            android:layout_marginBottom="36dp"
+            android:background="@drawable/corners_gradient_purple_5dp"
+            android:gravity="center"
+            android:text="@string/authentication_user"
+            android:textColor="@color/white"
+            android:textSize="@dimen/px33_11sp" />
+    </RelativeLayout>
+
+    <LinearLayout
+        android:id="@+id/ll_apply"
+        android:layout_width="match_parent"
+        android:layout_height="71dp"
+        android:layout_marginTop="10dp"
+        android:background="@color/white"
+        android:gravity="center_vertical"
+        android:orientation="horizontal"
+        android:paddingLeft="20dp"
+        android:paddingRight="20dp">
+
+        <View
+            android:layout_width="33dp"
+            android:layout_height="33dp"
+            android:background="@mipmap/ic_mine_apply" />
+
+        <TextView
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_marginLeft="14dp"
+            android:layout_weight="1"
+            android:text="@string/mine_apply"
+            android:textColor="@color/text_black"
+            android:textSize="@dimen/px39_13sp" />
+
+        <View
+            android:layout_width="9dp"
+            android:layout_height="14dp"
+            android:background="@mipmap/ic_right_gray" />
+    </LinearLayout>
+
+    <LinearLayout
+        android:id="@+id/ll_order"
+        android:layout_width="match_parent"
+        android:layout_height="71dp"
+        android:layout_marginTop="2dp"
+        android:background="@color/white"
+        android:gravity="center_vertical"
+        android:orientation="horizontal"
+        android:paddingLeft="20dp"
+        android:paddingRight="20dp">
+
+        <View
+            android:layout_width="33dp"
+            android:layout_height="33dp"
+            android:background="@mipmap/ic_mine_order" />
+
+        <TextView
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_marginLeft="14dp"
+            android:layout_weight="1"
+            android:text="@string/mine_order"
+            android:textColor="@color/text_black"
+            android:textSize="@dimen/px39_13sp" />
+
+        <View
+            android:layout_width="9dp"
+            android:layout_height="14dp"
+            android:background="@mipmap/ic_right_gray" />
+    </LinearLayout>
+
+    <LinearLayout
+        android:id="@+id/ll_payment_record"
+        android:layout_width="match_parent"
+        android:layout_height="71dp"
+        android:layout_marginTop="10dp"
+        android:background="@color/white"
+        android:gravity="center_vertical"
+        android:orientation="horizontal"
+        android:paddingLeft="20dp"
+        android:paddingRight="20dp">
+
+        <View
+            android:layout_width="33dp"
+            android:layout_height="33dp"
+            android:background="@mipmap/ic_mine_payment_record" />
+
+        <TextView
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_marginLeft="14dp"
+            android:layout_weight="1"
+            android:text="@string/mine_payment_record"
+            android:textColor="@color/text_black"
+            android:textSize="@dimen/px39_13sp" />
+
+        <View
+            android:layout_width="9dp"
+            android:layout_height="14dp"
+            android:background="@mipmap/ic_right_gray" />
+    </LinearLayout>
+
+
+    <LinearLayout
+        android:id="@+id/ll_tax"
+        android:layout_width="match_parent"
+        android:layout_height="71dp"
+        android:layout_marginTop="2dp"
+        android:background="@color/white"
+        android:gravity="center_vertical"
+        android:orientation="horizontal"
+        android:paddingLeft="20dp"
+        android:paddingRight="20dp">
+
+        <View
+            android:layout_width="33dp"
+            android:layout_height="33dp"
+            android:background="@mipmap/ic_mine_tax" />
+
+        <TextView
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_marginLeft="14dp"
+            android:layout_weight="1"
+            android:text="@string/mine_tax"
+            android:textColor="@color/text_black"
+            android:textSize="@dimen/px39_13sp" />
+
+        <View
+            android:layout_width="9dp"
+            android:layout_height="14dp"
+            android:background="@mipmap/ic_right_gray" />
+    </LinearLayout>
+</LinearLayout>

+ 122 - 0
app/src/main/res/layout/base_activity_layout.xml

@@ -0,0 +1,122 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <LinearLayout
+        android:id="@+id/ll_base_title"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:background="@color/white"
+        android:orientation="vertical">
+
+        <View
+            android:id="@+id/v_padding"
+            android:layout_width="match_parent"
+            android:layout_height="0dp" />
+
+        <RelativeLayout
+            android:layout_width="match_parent"
+            android:layout_height="@dimen/title_height"
+            android:orientation="horizontal">
+
+            <LinearLayout
+                android:id="@+id/ll_back"
+                android:layout_width="51dp"
+                android:layout_height="match_parent"
+                android:gravity="center"
+                android:orientation="vertical">
+
+                <ImageView
+                    android:id="@+id/iv_back"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:src="@mipmap/ic_back" />
+            </LinearLayout>
+
+            <TextView
+                android:id="@+id/tv_title"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_centerInParent="true"
+                android:textColor="@color/text_black"
+                android:textSize="@dimen/px54_18sp" />
+
+
+            <LinearLayout
+                android:id="@+id/ll_base_menu"
+                android:layout_width="wrap_content"
+                android:layout_height="match_parent"
+                android:layout_alignParentRight="true"
+                android:orientation="horizontal"
+                android:paddingRight="10dp" />
+
+        </RelativeLayout>
+    </LinearLayout>
+
+    <LinearLayout
+        android:id="@+id/ll_base_content"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_below="@id/ll_base_title"
+        android:layout_alignParentStart="true"
+        android:layout_marginTop="0dp"
+        android:background="@color/white"
+        android:orientation="vertical" />
+
+    <include
+        layout="@layout/base_activity_state"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_below="@id/ll_base_title" />
+    <!-- 沉浸式标题栏 -->
+    <LinearLayout
+        android:id="@+id/ll_immersion_title"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="vertical"
+        android:visibility="gone">
+
+        <View
+            android:id="@+id/v_immersion_padding"
+            android:layout_width="match_parent"
+            android:layout_height="0dp" />
+
+        <RelativeLayout
+            android:layout_width="match_parent"
+            android:layout_height="@dimen/title_height"
+            android:orientation="horizontal">
+
+            <LinearLayout
+                android:id="@+id/ll_immersion_back"
+                android:layout_width="51dp"
+                android:layout_height="match_parent"
+                android:gravity="center"
+                android:orientation="vertical">
+
+                <ImageView
+                    android:id="@+id/iv_immersion_back"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:src="@mipmap/ic_launcher" />
+            </LinearLayout>
+
+            <TextView
+                android:id="@+id/tv_immersion_title"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_centerInParent="true"
+                android:textColor="@color/white"
+                android:textSize="@dimen/px51_17sp" />
+
+            <LinearLayout
+                android:id="@+id/ll_menu"
+                android:layout_width="wrap_content"
+                android:layout_height="match_parent"
+                android:layout_alignParentRight="true"
+                android:orientation="horizontal"
+                android:paddingRight="7.5dp" />
+
+        </RelativeLayout>
+    </LinearLayout>
+</RelativeLayout>

+ 83 - 0
app/src/main/res/layout/base_activity_state.xml

@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:background="@color/white">
+
+    <LinearLayout
+        android:id="@+id/ll_base_loading"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:orientation="vertical"
+        android:visibility="gone">
+
+        <View
+            android:id="@+id/v_load_padding"
+            android:layout_width="match_parent"
+            android:layout_height="0dp" />
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:gravity="center"
+            android:orientation="vertical">
+
+            <!--<RelativeLayout-->
+            <!--android:layout_width="60dp"-->
+            <!--android:layout_height="60dp"-->
+            <!--android:background="@drawable/corners_blue_30dp">-->
+
+            <!--<ProgressBar-->
+            <!--android:layout_width="31dp"-->
+            <!--android:layout_height="31dp"-->
+            <!--android:layout_centerInParent="true"-->
+            <!--android:indeterminate="true"-->
+            <!--android:indeterminateDrawable="@drawable/progress_rotate_loading_white" />-->
+            <!--</RelativeLayout>-->
+
+            <View
+                android:layout_width="40dp"
+                android:layout_height="40dp" />
+        </LinearLayout>
+
+    </LinearLayout>
+
+    <LinearLayout
+        android:id="@+id/ll_base_error"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:gravity="center_horizontal"
+        android:orientation="vertical"
+        android:visibility="gone">
+
+        <View
+            android:id="@+id/v_error_padding"
+            android:layout_width="match_parent"
+            android:layout_height="0dp" />
+
+        <ImageView
+            android:layout_width="309dp"
+            android:layout_height="225dp"
+            android:layout_marginTop="43dp"
+            />
+        <!--android:background="@mipmap/ic_error_bg" -->
+        <TextView
+            android:id="@+id/tv_base_error"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="45dp"
+            android:textSize="@dimen/px48_16sp" />
+        <!--android:text="@string/net_error"-->
+        <!--android:textColor="@color/text_light_black"-->
+        <Button
+            android:id="@+id/btn_base_retry"
+            android:layout_width="110dp"
+            android:layout_height="30dp"
+            android:layout_marginTop="27dp"
+            android:textColor="@color/white"
+            android:textSize="@dimen/px48_16sp" />
+        <!--android:background="@drawable/corners_blue_15dp"-->
+        <!--android:text="@string/try_refresh"-->
+    </LinearLayout>
+
+</RelativeLayout>

+ 95 - 0
app/src/main/res/layout/base_fragment_layout.xml

@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <LinearLayout
+        android:id="@+id/ll_base_title"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:background="@color/white"
+        android:orientation="vertical">
+
+        <View
+            android:id="@+id/v_padding"
+            android:layout_width="match_parent"
+            android:layout_height="0dp" />
+
+        <RelativeLayout
+            android:layout_width="match_parent"
+            android:layout_height="@dimen/title_height"
+            android:orientation="horizontal">
+
+            <TextView
+                android:id="@+id/tv_base_title"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_centerInParent="true"
+                android:textColor="@color/text_black"
+                android:textSize="@dimen/px51_17sp" />
+
+            <LinearLayout
+                android:id="@+id/ll_base_menu"
+                android:layout_width="wrap_content"
+                android:layout_height="match_parent"
+                android:layout_alignParentRight="true"
+                android:orientation="horizontal"
+                android:paddingRight="10dp" />
+
+        </RelativeLayout>
+    </LinearLayout>
+
+    <LinearLayout
+        android:id="@+id/ll_base_content"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_below="@id/ll_base_title"
+        android:layout_alignParentStart="true"
+        android:background="@color/white"
+        android:orientation="vertical" />
+
+    <include
+        layout="@layout/base_activity_state"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_below="@id/ll_base_title" />
+
+
+    <!-- 沉浸式标题栏 -->
+    <LinearLayout
+        android:id="@+id/ll_immersion_title"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="vertical"
+        android:visibility="gone">
+
+        <View
+            android:id="@+id/v_immersion_padding"
+            android:layout_width="match_parent"
+            android:layout_height="0dp" />
+
+        <RelativeLayout
+            android:layout_width="match_parent"
+            android:layout_height="@dimen/title_height"
+            android:orientation="horizontal">
+
+            <TextView
+                android:id="@+id/tv_immersion_title"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_centerInParent="true"
+                android:textColor="@color/white"
+                android:textSize="@dimen/px51_17sp" />
+
+            <LinearLayout
+                android:id="@+id/ll_menu"
+                android:layout_width="wrap_content"
+                android:layout_height="match_parent"
+                android:layout_alignParentRight="true"
+                android:orientation="horizontal"
+                android:paddingRight="7.5dp" />
+
+        </RelativeLayout>
+    </LinearLayout>
+
+</RelativeLayout>

+ 110 - 0
app/src/main/res/layout/item_list_demand.xml

@@ -0,0 +1,110 @@
+<?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">
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="10dp"
+        android:background="@color/white"
+        android:orientation="vertical"
+        android:paddingLeft="15dp"
+        android:paddingRight="20dp">
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="19dp"
+            android:gravity="center_vertical"
+            android:orientation="horizontal">
+
+            <TextView
+                android:id="@+id/tv_title"
+                android:layout_width="0dp"
+                android:layout_height="wrap_content"
+                android:layout_weight="1"
+                android:singleLine="true"
+                android:text="连锁餐饮门店运营"
+                android:textColor="@color/text_black"
+                android:textSize="@dimen/px48_16sp" />
+
+            <TextView
+                android:id="@+id/tv_price"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="2500元*24月"
+                android:textColor="@color/text_blue_32"
+                android:textSize="@dimen/px48_16sp" />
+        </LinearLayout>
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="5dp"
+            android:gravity="top"
+            android:orientation="horizontal">
+
+            <TextView
+                android:id="@+id/tv_company"
+                android:layout_width="0dp"
+                android:layout_height="wrap_content"
+                android:layout_weight="1"
+                android:singleLine="true"
+                android:text="无锡大饭店餐饮有限公司"
+                android:textColor="@color/text_black"
+                android:textSize="@dimen/px39_13sp" />
+
+            <TextView
+                android:id="@+id/tv_date"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="2019.12.12-2020.01.01"
+                android:textColor="@color/text_gray_88"
+                android:textSize="@dimen/px36_12sp" />
+        </LinearLayout>
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="10dp"
+            android:layout_marginBottom="25dp"
+            android:orientation="horizontal">
+
+            <TextView
+                android:id="@+id/tv_address"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:background="@drawable/corners_gray_f5_5dp"
+                android:drawableLeft="@mipmap/ic_demand_address"
+                android:drawablePadding="3dp"
+                android:paddingLeft="10dp"
+                android:paddingTop="4dp"
+                android:paddingRight="10dp"
+                android:paddingBottom="4dp"
+                android:singleLine="true"
+                android:text="无锡 梁溪区"
+                android:textColor="@color/text_gray_53"
+                android:textSize="@dimen/px36_12sp" />
+
+            <TextView
+                android:id="@+id/tv_num"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="10dp"
+                android:background="@drawable/corners_gray_f5_5dp"
+                android:drawableLeft="@mipmap/ic_demand_num"
+                android:drawablePadding="3dp"
+                android:paddingLeft="10dp"
+                android:paddingTop="4dp"
+                android:paddingRight="10dp"
+                android:paddingBottom="4dp"
+                android:singleLine="true"
+                android:text="任务数:30"
+                android:textColor="@color/text_gray_53"
+                android:textSize="@dimen/px36_12sp" />
+        </LinearLayout>
+    </LinearLayout>
+
+</LinearLayout>

+ 99 - 0
app/src/main/res/layout/item_list_mine_apply.xml

@@ -0,0 +1,99 @@
+<?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">
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="10dp"
+        android:background="@color/white"
+        android:orientation="vertical"
+        android:paddingLeft="15dp"
+        android:paddingRight="20dp">
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="19dp"
+            android:gravity="center_vertical"
+            android:orientation="horizontal">
+
+            <TextView
+                android:id="@+id/tv_title"
+                android:layout_width="0dp"
+                android:layout_height="wrap_content"
+                android:layout_weight="1"
+                android:singleLine="true"
+                android:text="连锁餐饮门店运营"
+                android:textColor="@color/text_black"
+                android:textSize="@dimen/px48_16sp" />
+
+            <TextView
+                android:id="@+id/tv_price"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="2500元*24月"
+                android:textColor="@color/text_blue_32"
+                android:textSize="@dimen/px48_16sp" />
+        </LinearLayout>
+
+
+        <TextView
+            android:id="@+id/tv_company"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="5dp"
+            android:singleLine="true"
+            android:text="无锡大饭店餐饮有限公司"
+            android:textColor="@color/text_black"
+            android:textSize="@dimen/px39_13sp" />
+
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="10dp"
+            android:layout_marginBottom="25dp"
+            android:orientation="horizontal">
+
+            <TextView
+                android:id="@+id/tv_address"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:background="@drawable/corners_gray_f5_5dp"
+                android:drawableLeft="@mipmap/ic_demand_address"
+                android:drawablePadding="3dp"
+                android:paddingLeft="10dp"
+                android:paddingTop="4dp"
+                android:paddingRight="10dp"
+                android:paddingBottom="4dp"
+                android:singleLine="true"
+                android:text="无锡 梁溪区"
+                android:textColor="@color/text_gray_53"
+                android:textSize="@dimen/px36_12sp" />
+
+            <View
+                android:layout_width="0dp"
+                android:layout_height="1px"
+                android:layout_weight="1" />
+
+            <TextView
+                android:id="@+id/tv_state"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:background="@color/text_yellow"
+                android:drawableLeft="@mipmap/ic_demand_going"
+                android:drawablePadding="5dp"
+                android:paddingLeft="7dp"
+                android:paddingTop="4dp"
+                android:paddingRight="10dp"
+                android:paddingBottom="4dp"
+                android:text="@string/demand_going"
+                android:textColor="@color/text_gold"
+                android:textSize="@dimen/px36_12sp" />
+        </LinearLayout>
+    </LinearLayout>
+
+</LinearLayout>

+ 28 - 0
app/src/main/res/layout/view_action_bar_menu.xml

@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <LinearLayout
+        android:id="@+id/ll_menu"
+        android:layout_width="wrap_content"
+        android:layout_height="@dimen/title_height"
+        android:gravity="center"
+        android:paddingLeft="10dp"
+        android:paddingRight="10dp">
+
+        <ImageView
+            android:id="@+id/iv_menu"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content" />
+
+        <TextView
+            android:id="@+id/tv_menu"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:gravity="center"
+            android:textColor="@color/text_black"
+            android:textSize="@dimen/px33_11sp"
+            android:visibility="gone" />
+    </LinearLayout>
+</android.support.constraint.ConstraintLayout>

+ 77 - 0
app/src/main/res/layout/view_list_demand_header.xml

@@ -0,0 +1,77 @@
+<?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">
+
+    <com.webrain.baselibrary.widget.banner.ViewPagerBanner
+        android:id="@+id/vpb"
+        android:layout_width="match_parent"
+        android:layout_height="160dp" />
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="57dp"
+        android:background="@color/white"
+        android:gravity="center_vertical"
+        android:orientation="horizontal"
+        android:paddingLeft="20dp"
+        android:paddingRight="20dp">
+
+        <TextView
+            android:id="@+id/tv_area"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:background="@drawable/corners_gray_f5_5dp"
+            android:drawableRight="@mipmap/ic_demand_up"
+            android:drawablePadding="5dp"
+            android:paddingLeft="10dp"
+            android:paddingTop="4dp"
+            android:paddingRight="10dp"
+            android:paddingBottom="4dp"
+            android:singleLine="true"
+            android:text="@string/all_area"
+            android:textColor="@color/text_gray_53"
+            android:textSize="@dimen/px39_13sp" />
+
+        <View
+            android:layout_width="0dp"
+            android:layout_height="1px"
+            android:layout_weight="1" />
+
+        <TextView
+            android:id="@+id/tv_business"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:background="@drawable/corners_gray_f5_5dp"
+            android:drawableRight="@mipmap/ic_demand_up_n"
+            android:drawablePadding="5dp"
+            android:paddingLeft="10dp"
+            android:paddingTop="4dp"
+            android:paddingRight="10dp"
+            android:paddingBottom="4dp"
+            android:singleLine="true"
+            android:text="@string/business"
+            android:textColor="@color/text_gray_53"
+            android:textSize="@dimen/px39_13sp" />
+
+        <TextView
+            android:id="@+id/tv_price"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginLeft="10dp"
+            android:background="@drawable/corners_gray_f5_5dp"
+            android:drawableRight="@mipmap/ic_demand_up_n"
+            android:drawablePadding="5dp"
+            android:paddingLeft="10dp"
+            android:paddingTop="4dp"
+            android:paddingRight="10dp"
+            android:paddingBottom="4dp"
+            android:singleLine="true"
+            android:text="@string/unit_price"
+            android:textColor="@color/text_gray_53"
+            android:textSize="@dimen/px39_13sp" />
+
+    </LinearLayout>
+
+</LinearLayout>

二進制
app/src/main/res/mipmap-hdpi/ic_back.png


二進制
app/src/main/res/mipmap-hdpi/ic_default_header.png


二進制
app/src/main/res/mipmap-hdpi/ic_demand_address.png


二進制
app/src/main/res/mipmap-hdpi/ic_demand_detail_company.png


二進制
app/src/main/res/mipmap-hdpi/ic_demand_detail_date.png


二進制
app/src/main/res/mipmap-hdpi/ic_demand_detail_location.png


二進制
app/src/main/res/mipmap-hdpi/ic_demand_detail_num.png


二進制
app/src/main/res/mipmap-hdpi/ic_demand_going.png


+ 0 - 0
app/src/main/res/mipmap-hdpi/ic_demand_num.png


Some files were not shown because too many files changed in this diff