Commit 54127ffd102ed962a04324441ea77977dbc12a37

Authored by 陶汉栋
0 parents

no message

Showing 175 changed files with 13161 additions and 0 deletions   Show diff stats
.gitignore 0 → 100644
  1 +++ a/.gitignore
@@ -0,0 +1,9 @@ @@ -0,0 +1,9 @@
  1 +*.iml
  2 +.gradle
  3 +/local.properties
  4 +/.idea/workspace.xml
  5 +/.idea/libraries
  6 +.DS_Store
  7 +/build
  8 +/captures
  9 +.externalNativeBuild
.idea/gradle.xml 0 → 100644
  1 +++ a/.idea/gradle.xml
@@ -0,0 +1,19 @@ @@ -0,0 +1,19 @@
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<project version="4">
  3 + <component name="GradleSettings">
  4 + <option name="linkedExternalProjectsSettings">
  5 + <GradleProjectSettings>
  6 + <option name="distributionType" value="DEFAULT_WRAPPED" />
  7 + <option name="externalProjectPath" value="$PROJECT_DIR$" />
  8 + <option name="modules">
  9 + <set>
  10 + <option value="$PROJECT_DIR$" />
  11 + <option value="$PROJECT_DIR$/app" />
  12 + <option value="$PROJECT_DIR$/mvpsdk" />
  13 + </set>
  14 + </option>
  15 + <option name="resolveModulePerSourceSet" value="false" />
  16 + </GradleProjectSettings>
  17 + </option>
  18 + </component>
  19 +</project>
0 \ No newline at end of file 20 \ No newline at end of file
.idea/misc.xml 0 → 100644
  1 +++ a/.idea/misc.xml
@@ -0,0 +1,33 @@ @@ -0,0 +1,33 @@
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<project version="4">
  3 + <component name="NullableNotNullManager">
  4 + <option name="myDefaultNullable" value="android.support.annotation.Nullable" />
  5 + <option name="myDefaultNotNull" value="android.support.annotation.NonNull" />
  6 + <option name="myNullables">
  7 + <value>
  8 + <list size="4">
  9 + <item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
  10 + <item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
  11 + <item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
  12 + <item index="3" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
  13 + </list>
  14 + </value>
  15 + </option>
  16 + <option name="myNotNulls">
  17 + <value>
  18 + <list size="4">
  19 + <item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
  20 + <item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
  21 + <item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
  22 + <item index="3" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
  23 + </list>
  24 + </value>
  25 + </option>
  26 + </component>
  27 + <component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" project-jdk-name="1.8" project-jdk-type="JavaSDK">
  28 + <output url="file://$PROJECT_DIR$/build/classes" />
  29 + </component>
  30 + <component name="ProjectType">
  31 + <option name="id" value="Android" />
  32 + </component>
  33 +</project>
0 \ No newline at end of file 34 \ No newline at end of file
.idea/modules.xml 0 → 100644
  1 +++ a/.idea/modules.xml
@@ -0,0 +1,10 @@ @@ -0,0 +1,10 @@
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<project version="4">
  3 + <component name="ProjectModuleManager">
  4 + <modules>
  5 + <module fileurl="file://$PROJECT_DIR$/app/app.iml" filepath="$PROJECT_DIR$/app/app.iml" />
  6 + <module fileurl="file://$PROJECT_DIR$/mvpsdk/mvpsdk.iml" filepath="$PROJECT_DIR$/mvpsdk/mvpsdk.iml" />
  7 + <module fileurl="file://$PROJECT_DIR$/parentwork.iml" filepath="$PROJECT_DIR$/parentwork.iml" />
  8 + </modules>
  9 + </component>
  10 +</project>
0 \ No newline at end of file 11 \ No newline at end of file
.idea/runConfigurations.xml 0 → 100644
  1 +++ a/.idea/runConfigurations.xml
@@ -0,0 +1,12 @@ @@ -0,0 +1,12 @@
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<project version="4">
  3 + <component name="RunConfigurationProducerService">
  4 + <option name="ignoredProducers">
  5 + <set>
  6 + <option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
  7 + <option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
  8 + <option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
  9 + </set>
  10 + </option>
  11 + </component>
  12 +</project>
0 \ No newline at end of file 13 \ No newline at end of file
.idea/vcs.xml 0 → 100644
  1 +++ a/.idea/vcs.xml
@@ -0,0 +1,6 @@ @@ -0,0 +1,6 @@
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<project version="4">
  3 + <component name="VcsDirectoryMappings">
  4 + <mapping directory="$PROJECT_DIR$" vcs="Git" />
  5 + </component>
  6 +</project>
0 \ No newline at end of file 7 \ No newline at end of file
app/.gitignore 0 → 100644
  1 +++ a/app/.gitignore
@@ -0,0 +1 @@ @@ -0,0 +1 @@
  1 +/build
app/build.gradle 0 → 100644
  1 +++ a/app/build.gradle
@@ -0,0 +1,30 @@ @@ -0,0 +1,30 @@
  1 +apply plugin: 'com.android.application'
  2 +
  3 +android {
  4 + compileSdkVersion 26
  5 + defaultConfig {
  6 + applicationId "com.shunzhi.parent"
  7 + minSdkVersion 16
  8 + targetSdkVersion 26
  9 + versionCode 1
  10 + versionName "1.0"
  11 + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
  12 + }
  13 + buildTypes {
  14 + release {
  15 + minifyEnabled false
  16 + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
  17 + }
  18 + }
  19 +}
  20 +
  21 +dependencies {
  22 + implementation fileTree(include: ['*.jar'], dir: 'libs')
  23 + implementation 'com.android.support:appcompat-v7:26.1.0'
  24 + implementation 'com.android.support.constraint:constraint-layout:1.0.2'
  25 + implementation 'com.android.support:support-v4:26.1.0'
  26 + testImplementation 'junit:junit:4.12'
  27 + androidTestImplementation 'com.android.support.test:runner:1.0.1'
  28 + androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
  29 + implementation project(':mvpsdk')
  30 +}
app/proguard-rules.pro 0 → 100644
  1 +++ a/app/proguard-rules.pro
@@ -0,0 +1,21 @@ @@ -0,0 +1,21 @@
  1 +# Add project specific ProGuard rules here.
  2 +# You can control the set of applied configuration files using the
  3 +# proguardFiles setting in build.gradle.
  4 +#
  5 +# For more details, see
  6 +# http://developer.android.com/guide/developing/tools/proguard.html
  7 +
  8 +# If your project uses WebView with JS, uncomment the following
  9 +# and specify the fully qualified class name to the JavaScript interface
  10 +# class:
  11 +#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
  12 +# public *;
  13 +#}
  14 +
  15 +# Uncomment this to preserve the line number information for
  16 +# debugging stack traces.
  17 +#-keepattributes SourceFile,LineNumberTable
  18 +
  19 +# If you keep the line number information, uncomment this to
  20 +# hide the original source file name.
  21 +#-renamesourcefileattribute SourceFile
app/src/androidTest/java/com/shunzhi/parent/ExampleInstrumentedTest.java 0 → 100644
  1 +++ a/app/src/androidTest/java/com/shunzhi/parent/ExampleInstrumentedTest.java
@@ -0,0 +1,26 @@ @@ -0,0 +1,26 @@
  1 +package com.shunzhi.parent;
  2 +
  3 +import android.content.Context;
  4 +import android.support.test.InstrumentationRegistry;
  5 +import android.support.test.runner.AndroidJUnit4;
  6 +
  7 +import org.junit.Test;
  8 +import org.junit.runner.RunWith;
  9 +
  10 +import static org.junit.Assert.*;
  11 +
  12 +/**
  13 + * Instrumented test, which will execute on an Android device.
  14 + *
  15 + * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
  16 + */
  17 +@RunWith(AndroidJUnit4.class)
  18 +public class ExampleInstrumentedTest {
  19 + @Test
  20 + public void useAppContext() throws Exception {
  21 + // Context of the app under test.
  22 + Context appContext = InstrumentationRegistry.getTargetContext();
  23 +
  24 + assertEquals("com.shunzhi.parent", appContext.getPackageName());
  25 + }
  26 +}
app/src/main/AndroidManifest.xml 0 → 100644
  1 +++ a/app/src/main/AndroidManifest.xml
@@ -0,0 +1,24 @@ @@ -0,0 +1,24 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<manifest xmlns:android="http://schemas.android.com/apk/res/android"
  3 + package="com.shunzhi.parent">
  4 +
  5 + <application
  6 + android:name=".MyApplication"
  7 + android:allowBackup="true"
  8 + android:icon="@mipmap/ic_launcher"
  9 + android:label="@string/app_name"
  10 + android:roundIcon="@mipmap/ic_launcher_round"
  11 + android:supportsRtl="true"
  12 + android:theme="@style/AppTheme">
  13 + <activity android:name=".ui.MainActivity">
  14 + <intent-filter>
  15 + <action android:name="android.intent.action.MAIN" />
  16 +
  17 + <category android:name="android.intent.category.LAUNCHER" />
  18 + </intent-filter>
  19 + </activity>
  20 + <activity android:name=".ui.activity.LoginAndRegistActivity" />
  21 + <activity android:name=".ui.activity.StartActivity"></activity>
  22 + </application>
  23 +
  24 +</manifest>
0 \ No newline at end of file 25 \ No newline at end of file
app/src/main/java/com/shunzhi/parent/MyApplication.java 0 → 100644
  1 +++ a/app/src/main/java/com/shunzhi/parent/MyApplication.java
@@ -0,0 +1,17 @@ @@ -0,0 +1,17 @@
  1 +package com.shunzhi.parent;
  2 +
  3 +import com.share.mvpsdk.global.GlobalApplication;
  4 +
  5 +/**
  6 + * Created by ToaHanDong on 2018/3/2.
  7 + */
  8 +
  9 +public class MyApplication extends GlobalApplication {
  10 +
  11 +
  12 + @Override
  13 + public void onCreate() {
  14 + super.onCreate();
  15 +
  16 + }
  17 +}
app/src/main/java/com/shunzhi/parent/ui/MainActivity.java 0 → 100644
  1 +++ a/app/src/main/java/com/shunzhi/parent/ui/MainActivity.java
@@ -0,0 +1,15 @@ @@ -0,0 +1,15 @@
  1 +package com.shunzhi.parent.ui;
  2 +
  3 +import android.support.v7.app.AppCompatActivity;
  4 +import android.os.Bundle;
  5 +
  6 +import com.shunzhi.parent.R;
  7 +
  8 +public class MainActivity extends AppCompatActivity {
  9 +
  10 + @Override
  11 + protected void onCreate(Bundle savedInstanceState) {
  12 + super.onCreate(savedInstanceState);
  13 + setContentView(R.layout.activity_main);
  14 + }
  15 +}
app/src/main/java/com/shunzhi/parent/ui/activity/LoginAndRegistActivity.java 0 → 100644
  1 +++ a/app/src/main/java/com/shunzhi/parent/ui/activity/LoginAndRegistActivity.java
@@ -0,0 +1,15 @@ @@ -0,0 +1,15 @@
  1 +package com.shunzhi.parent.ui.activity;
  2 +
  3 +import android.support.v7.app.AppCompatActivity;
  4 +import android.os.Bundle;
  5 +
  6 +import com.shunzhi.parent.R;
  7 +
  8 +public class LoginAndRegistActivity extends AppCompatActivity {
  9 +
  10 + @Override
  11 + protected void onCreate(Bundle savedInstanceState) {
  12 + super.onCreate(savedInstanceState);
  13 + setContentView(R.layout.activity_regist);
  14 + }
  15 +}
app/src/main/java/com/shunzhi/parent/ui/activity/StartActivity.java 0 → 100644
  1 +++ a/app/src/main/java/com/shunzhi/parent/ui/activity/StartActivity.java
@@ -0,0 +1,15 @@ @@ -0,0 +1,15 @@
  1 +package com.shunzhi.parent.ui.activity;
  2 +
  3 +import android.support.v7.app.AppCompatActivity;
  4 +import android.os.Bundle;
  5 +
  6 +import com.shunzhi.parent.R;
  7 +
  8 +public class StartActivity extends AppCompatActivity {
  9 +
  10 + @Override
  11 + protected void onCreate(Bundle savedInstanceState) {
  12 + super.onCreate(savedInstanceState);
  13 + setContentView(R.layout.activity_start);
  14 + }
  15 +}
app/src/main/java/com/shunzhi/parent/ui/fragment/CePingFragment.java 0 → 100644
  1 +++ a/app/src/main/java/com/shunzhi/parent/ui/fragment/CePingFragment.java
@@ -0,0 +1,109 @@ @@ -0,0 +1,109 @@
  1 +package com.shunzhi.parent.ui.fragment;
  2 +
  3 +import android.content.Context;
  4 +import android.net.Uri;
  5 +import android.os.Bundle;
  6 +import android.support.v4.app.Fragment;
  7 +import android.view.LayoutInflater;
  8 +import android.view.View;
  9 +import android.view.ViewGroup;
  10 +
  11 +import com.shunzhi.parent.R;
  12 +
  13 +/**
  14 + * A simple {@link Fragment} subclass.
  15 + * Activities that contain this fragment must implement the
  16 + * {@link CePingFragment.OnFragmentInteractionListener} interface
  17 + * to handle interaction events.
  18 + * Use the {@link CePingFragment#newInstance} factory method to
  19 + * create an instance of this fragment.
  20 + */
  21 +public class CePingFragment extends Fragment {
  22 + // TODO: Rename parameter arguments, choose names that match
  23 + // the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
  24 + private static final String ARG_PARAM1 = "param1";
  25 + private static final String ARG_PARAM2 = "param2";
  26 +
  27 + // TODO: Rename and change types of parameters
  28 + private String mParam1;
  29 + private String mParam2;
  30 +
  31 + private OnFragmentInteractionListener mListener;
  32 +
  33 + public CePingFragment() {
  34 + // Required empty public constructor
  35 + }
  36 +
  37 + /**
  38 + * Use this factory method to create a new instance of
  39 + * this fragment using the provided parameters.
  40 + *
  41 + * @param param1 Parameter 1.
  42 + * @param param2 Parameter 2.
  43 + * @return A new instance of fragment CePingFragment.
  44 + */
  45 + // TODO: Rename and change types and number of parameters
  46 + public static CePingFragment newInstance(String param1, String param2) {
  47 + CePingFragment fragment = new CePingFragment();
  48 + Bundle args = new Bundle();
  49 + args.putString(ARG_PARAM1, param1);
  50 + args.putString(ARG_PARAM2, param2);
  51 + fragment.setArguments(args);
  52 + return fragment;
  53 + }
  54 +
  55 + @Override
  56 + public void onCreate(Bundle savedInstanceState) {
  57 + super.onCreate(savedInstanceState);
  58 + if (getArguments() != null) {
  59 + mParam1 = getArguments().getString(ARG_PARAM1);
  60 + mParam2 = getArguments().getString(ARG_PARAM2);
  61 + }
  62 + }
  63 +
  64 + @Override
  65 + public View onCreateView(LayoutInflater inflater, ViewGroup container,
  66 + Bundle savedInstanceState) {
  67 + // Inflate the layout for this fragment
  68 + return inflater.inflate(R.layout.fragment_ce_ping, container, false);
  69 + }
  70 +
  71 + // TODO: Rename method, update argument and hook method into UI event
  72 + public void onButtonPressed(Uri uri) {
  73 + if (mListener != null) {
  74 + mListener.onFragmentInteraction(uri);
  75 + }
  76 + }
  77 +
  78 + @Override
  79 + public void onAttach(Context context) {
  80 + super.onAttach(context);
  81 + if (context instanceof OnFragmentInteractionListener) {
  82 + mListener = (OnFragmentInteractionListener) context;
  83 + } else {
  84 + throw new RuntimeException(context.toString()
  85 + + " must implement OnFragmentInteractionListener");
  86 + }
  87 + }
  88 +
  89 + @Override
  90 + public void onDetach() {
  91 + super.onDetach();
  92 + mListener = null;
  93 + }
  94 +
  95 + /**
  96 + * This interface must be implemented by activities that contain this
  97 + * fragment to allow an interaction in this fragment to be communicated
  98 + * to the activity and potentially other fragments contained in that
  99 + * activity.
  100 + * <p>
  101 + * See the Android Training lesson <a href=
  102 + * "http://developer.android.com/training/basics/fragments/communicating.html"
  103 + * >Communicating with Other Fragments</a> for more information.
  104 + */
  105 + public interface OnFragmentInteractionListener {
  106 + // TODO: Update argument type and name
  107 + void onFragmentInteraction(Uri uri);
  108 + }
  109 +}
app/src/main/java/com/shunzhi/parent/ui/fragment/ConsultFragment.java 0 → 100644
  1 +++ a/app/src/main/java/com/shunzhi/parent/ui/fragment/ConsultFragment.java
@@ -0,0 +1,109 @@ @@ -0,0 +1,109 @@
  1 +package com.shunzhi.parent.ui.fragment;
  2 +
  3 +import android.content.Context;
  4 +import android.net.Uri;
  5 +import android.os.Bundle;
  6 +import android.support.v4.app.Fragment;
  7 +import android.view.LayoutInflater;
  8 +import android.view.View;
  9 +import android.view.ViewGroup;
  10 +
  11 +import com.shunzhi.parent.R;
  12 +
  13 +/**
  14 + * A simple {@link Fragment} subclass.
  15 + * Activities that contain this fragment must implement the
  16 + * {@link ConsultFragment.OnFragmentInteractionListener} interface
  17 + * to handle interaction events.
  18 + * Use the {@link ConsultFragment#newInstance} factory method to
  19 + * create an instance of this fragment.
  20 + */
  21 +public class ConsultFragment extends Fragment {
  22 + // TODO: Rename parameter arguments, choose names that match
  23 + // the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
  24 + private static final String ARG_PARAM1 = "param1";
  25 + private static final String ARG_PARAM2 = "param2";
  26 +
  27 + // TODO: Rename and change types of parameters
  28 + private String mParam1;
  29 + private String mParam2;
  30 +
  31 + private OnFragmentInteractionListener mListener;
  32 +
  33 + public ConsultFragment() {
  34 + // Required empty public constructor
  35 + }
  36 +
  37 + /**
  38 + * Use this factory method to create a new instance of
  39 + * this fragment using the provided parameters.
  40 + *
  41 + * @param param1 Parameter 1.
  42 + * @param param2 Parameter 2.
  43 + * @return A new instance of fragment ConsultFragment.
  44 + */
  45 + // TODO: Rename and change types and number of parameters
  46 + public static ConsultFragment newInstance(String param1, String param2) {
  47 + ConsultFragment fragment = new ConsultFragment();
  48 + Bundle args = new Bundle();
  49 + args.putString(ARG_PARAM1, param1);
  50 + args.putString(ARG_PARAM2, param2);
  51 + fragment.setArguments(args);
  52 + return fragment;
  53 + }
  54 +
  55 + @Override
  56 + public void onCreate(Bundle savedInstanceState) {
  57 + super.onCreate(savedInstanceState);
  58 + if (getArguments() != null) {
  59 + mParam1 = getArguments().getString(ARG_PARAM1);
  60 + mParam2 = getArguments().getString(ARG_PARAM2);
  61 + }
  62 + }
  63 +
  64 + @Override
  65 + public View onCreateView(LayoutInflater inflater, ViewGroup container,
  66 + Bundle savedInstanceState) {
  67 + // Inflate the layout for this fragment
  68 + return inflater.inflate(R.layout.fragment_zi_xun, container, false);
  69 + }
  70 +
  71 + // TODO: Rename method, update argument and hook method into UI event
  72 + public void onButtonPressed(Uri uri) {
  73 + if (mListener != null) {
  74 + mListener.onFragmentInteraction(uri);
  75 + }
  76 + }
  77 +
  78 + @Override
  79 + public void onAttach(Context context) {
  80 + super.onAttach(context);
  81 + if (context instanceof OnFragmentInteractionListener) {
  82 + mListener = (OnFragmentInteractionListener) context;
  83 + } else {
  84 + throw new RuntimeException(context.toString()
  85 + + " must implement OnFragmentInteractionListener");
  86 + }
  87 + }
  88 +
  89 + @Override
  90 + public void onDetach() {
  91 + super.onDetach();
  92 + mListener = null;
  93 + }
  94 +
  95 + /**
  96 + * This interface must be implemented by activities that contain this
  97 + * fragment to allow an interaction in this fragment to be communicated
  98 + * to the activity and potentially other fragments contained in that
  99 + * activity.
  100 + * <p>
  101 + * See the Android Training lesson <a href=
  102 + * "http://developer.android.com/training/basics/fragments/communicating.html"
  103 + * >Communicating with Other Fragments</a> for more information.
  104 + */
  105 + public interface OnFragmentInteractionListener {
  106 + // TODO: Update argument type and name
  107 + void onFragmentInteraction(Uri uri);
  108 + }
  109 +}
app/src/main/java/com/shunzhi/parent/ui/fragment/MineFragment.java 0 → 100644
  1 +++ a/app/src/main/java/com/shunzhi/parent/ui/fragment/MineFragment.java
@@ -0,0 +1,109 @@ @@ -0,0 +1,109 @@
  1 +package com.shunzhi.parent.ui.fragment;
  2 +
  3 +import android.content.Context;
  4 +import android.net.Uri;
  5 +import android.os.Bundle;
  6 +import android.support.v4.app.Fragment;
  7 +import android.view.LayoutInflater;
  8 +import android.view.View;
  9 +import android.view.ViewGroup;
  10 +
  11 +import com.shunzhi.parent.R;
  12 +
  13 +/**
  14 + * A simple {@link Fragment} subclass.
  15 + * Activities that contain this fragment must implement the
  16 + * {@link MineFragment.OnFragmentInteractionListener} interface
  17 + * to handle interaction events.
  18 + * Use the {@link MineFragment#newInstance} factory method to
  19 + * create an instance of this fragment.
  20 + */
  21 +public class MineFragment extends Fragment {
  22 + // TODO: Rename parameter arguments, choose names that match
  23 + // the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
  24 + private static final String ARG_PARAM1 = "param1";
  25 + private static final String ARG_PARAM2 = "param2";
  26 +
  27 + // TODO: Rename and change types of parameters
  28 + private String mParam1;
  29 + private String mParam2;
  30 +
  31 + private OnFragmentInteractionListener mListener;
  32 +
  33 + public MineFragment() {
  34 + // Required empty public constructor
  35 + }
  36 +
  37 + /**
  38 + * Use this factory method to create a new instance of
  39 + * this fragment using the provided parameters.
  40 + *
  41 + * @param param1 Parameter 1.
  42 + * @param param2 Parameter 2.
  43 + * @return A new instance of fragment MineFragment.
  44 + */
  45 + // TODO: Rename and change types and number of parameters
  46 + public static MineFragment newInstance(String param1, String param2) {
  47 + MineFragment fragment = new MineFragment();
  48 + Bundle args = new Bundle();
  49 + args.putString(ARG_PARAM1, param1);
  50 + args.putString(ARG_PARAM2, param2);
  51 + fragment.setArguments(args);
  52 + return fragment;
  53 + }
  54 +
  55 + @Override
  56 + public void onCreate(Bundle savedInstanceState) {
  57 + super.onCreate(savedInstanceState);
  58 + if (getArguments() != null) {
  59 + mParam1 = getArguments().getString(ARG_PARAM1);
  60 + mParam2 = getArguments().getString(ARG_PARAM2);
  61 + }
  62 + }
  63 +
  64 + @Override
  65 + public View onCreateView(LayoutInflater inflater, ViewGroup container,
  66 + Bundle savedInstanceState) {
  67 + // Inflate the layout for this fragment
  68 + return inflater.inflate(R.layout.fragment_mine, container, false);
  69 + }
  70 +
  71 + // TODO: Rename method, update argument and hook method into UI event
  72 + public void onButtonPressed(Uri uri) {
  73 + if (mListener != null) {
  74 + mListener.onFragmentInteraction(uri);
  75 + }
  76 + }
  77 +
  78 + @Override
  79 + public void onAttach(Context context) {
  80 + super.onAttach(context);
  81 + if (context instanceof OnFragmentInteractionListener) {
  82 + mListener = (OnFragmentInteractionListener) context;
  83 + } else {
  84 + throw new RuntimeException(context.toString()
  85 + + " must implement OnFragmentInteractionListener");
  86 + }
  87 + }
  88 +
  89 + @Override
  90 + public void onDetach() {
  91 + super.onDetach();
  92 + mListener = null;
  93 + }
  94 +
  95 + /**
  96 + * This interface must be implemented by activities that contain this
  97 + * fragment to allow an interaction in this fragment to be communicated
  98 + * to the activity and potentially other fragments contained in that
  99 + * activity.
  100 + * <p>
  101 + * See the Android Training lesson <a href=
  102 + * "http://developer.android.com/training/basics/fragments/communicating.html"
  103 + * >Communicating with Other Fragments</a> for more information.
  104 + */
  105 + public interface OnFragmentInteractionListener {
  106 + // TODO: Update argument type and name
  107 + void onFragmentInteraction(Uri uri);
  108 + }
  109 +}
app/src/main/java/com/shunzhi/parent/ui/fragment/ReportFragment.java 0 → 100644
  1 +++ a/app/src/main/java/com/shunzhi/parent/ui/fragment/ReportFragment.java
@@ -0,0 +1,109 @@ @@ -0,0 +1,109 @@
  1 +package com.shunzhi.parent.ui.fragment;
  2 +
  3 +import android.content.Context;
  4 +import android.net.Uri;
  5 +import android.os.Bundle;
  6 +import android.support.v4.app.Fragment;
  7 +import android.view.LayoutInflater;
  8 +import android.view.View;
  9 +import android.view.ViewGroup;
  10 +
  11 +import com.shunzhi.parent.R;
  12 +
  13 +/**
  14 + * A simple {@link Fragment} subclass.
  15 + * Activities that contain this fragment must implement the
  16 + * {@link ReportFragment.OnFragmentInteractionListener} interface
  17 + * to handle interaction events.
  18 + * Use the {@link ReportFragment#newInstance} factory method to
  19 + * create an instance of this fragment.
  20 + */
  21 +public class ReportFragment extends Fragment {
  22 + // TODO: Rename parameter arguments, choose names that match
  23 + // the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
  24 + private static final String ARG_PARAM1 = "param1";
  25 + private static final String ARG_PARAM2 = "param2";
  26 +
  27 + // TODO: Rename and change types of parameters
  28 + private String mParam1;
  29 + private String mParam2;
  30 +
  31 + private OnFragmentInteractionListener mListener;
  32 +
  33 + public ReportFragment() {
  34 + // Required empty public constructor
  35 + }
  36 +
  37 + /**
  38 + * Use this factory method to create a new instance of
  39 + * this fragment using the provided parameters.
  40 + *
  41 + * @param param1 Parameter 1.
  42 + * @param param2 Parameter 2.
  43 + * @return A new instance of fragment ReportFragment.
  44 + */
  45 + // TODO: Rename and change types and number of parameters
  46 + public static ReportFragment newInstance(String param1, String param2) {
  47 + ReportFragment fragment = new ReportFragment();
  48 + Bundle args = new Bundle();
  49 + args.putString(ARG_PARAM1, param1);
  50 + args.putString(ARG_PARAM2, param2);
  51 + fragment.setArguments(args);
  52 + return fragment;
  53 + }
  54 +
  55 + @Override
  56 + public void onCreate(Bundle savedInstanceState) {
  57 + super.onCreate(savedInstanceState);
  58 + if (getArguments() != null) {
  59 + mParam1 = getArguments().getString(ARG_PARAM1);
  60 + mParam2 = getArguments().getString(ARG_PARAM2);
  61 + }
  62 + }
  63 +
  64 + @Override
  65 + public View onCreateView(LayoutInflater inflater, ViewGroup container,
  66 + Bundle savedInstanceState) {
  67 + // Inflate the layout for this fragment
  68 + return inflater.inflate(R.layout.fragment_report, container, false);
  69 + }
  70 +
  71 + // TODO: Rename method, update argument and hook method into UI event
  72 + public void onButtonPressed(Uri uri) {
  73 + if (mListener != null) {
  74 + mListener.onFragmentInteraction(uri);
  75 + }
  76 + }
  77 +
  78 + @Override
  79 + public void onAttach(Context context) {
  80 + super.onAttach(context);
  81 + if (context instanceof OnFragmentInteractionListener) {
  82 + mListener = (OnFragmentInteractionListener) context;
  83 + } else {
  84 + throw new RuntimeException(context.toString()
  85 + + " must implement OnFragmentInteractionListener");
  86 + }
  87 + }
  88 +
  89 + @Override
  90 + public void onDetach() {
  91 + super.onDetach();
  92 + mListener = null;
  93 + }
  94 +
  95 + /**
  96 + * This interface must be implemented by activities that contain this
  97 + * fragment to allow an interaction in this fragment to be communicated
  98 + * to the activity and potentially other fragments contained in that
  99 + * activity.
  100 + * <p>
  101 + * See the Android Training lesson <a href=
  102 + * "http://developer.android.com/training/basics/fragments/communicating.html"
  103 + * >Communicating with Other Fragments</a> for more information.
  104 + */
  105 + public interface OnFragmentInteractionListener {
  106 + // TODO: Update argument type and name
  107 + void onFragmentInteraction(Uri uri);
  108 + }
  109 +}
app/src/main/java/com/shunzhi/parent/ui/fragment/loginandregistfragment/LoginAndRegistFragment.java 0 → 100644
  1 +++ a/app/src/main/java/com/shunzhi/parent/ui/fragment/loginandregistfragment/LoginAndRegistFragment.java
@@ -0,0 +1,109 @@ @@ -0,0 +1,109 @@
  1 +package com.shunzhi.parent.ui.fragment.loginandregistfragment;
  2 +
  3 +import android.content.Context;
  4 +import android.net.Uri;
  5 +import android.os.Bundle;
  6 +import android.support.v4.app.Fragment;
  7 +import android.view.LayoutInflater;
  8 +import android.view.View;
  9 +import android.view.ViewGroup;
  10 +
  11 +import com.shunzhi.parent.R;
  12 +
  13 +/**
  14 + * A simple {@link Fragment} subclass.
  15 + * Activities that contain this fragment must implement the
  16 + * {@link LoginAndRegistFragment.OnFragmentInteractionListener} interface
  17 + * to handle interaction events.
  18 + * Use the {@link LoginAndRegistFragment#newInstance} factory method to
  19 + * create an instance of this fragment.
  20 + */
  21 +public class LoginAndRegistFragment extends Fragment {
  22 + // TODO: Rename parameter arguments, choose names that match
  23 + // the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
  24 + private static final String ARG_PARAM1 = "param1";
  25 + private static final String ARG_PARAM2 = "param2";
  26 +
  27 + // TODO: Rename and change types of parameters
  28 + private String mParam1;
  29 + private String mParam2;
  30 +
  31 + private OnFragmentInteractionListener mListener;
  32 +
  33 + public LoginAndRegistFragment() {
  34 + // Required empty public constructor
  35 + }
  36 +
  37 + /**
  38 + * Use this factory method to create a new instance of
  39 + * this fragment using the provided parameters.
  40 + *
  41 + * @param param1 Parameter 1.
  42 + * @param param2 Parameter 2.
  43 + * @return A new instance of fragment LoginAndRegistFragment.
  44 + */
  45 + // TODO: Rename and change types and number of parameters
  46 + public static LoginAndRegistFragment newInstance(String param1, String param2) {
  47 + LoginAndRegistFragment fragment = new LoginAndRegistFragment();
  48 + Bundle args = new Bundle();
  49 + args.putString(ARG_PARAM1, param1);
  50 + args.putString(ARG_PARAM2, param2);
  51 + fragment.setArguments(args);
  52 + return fragment;
  53 + }
  54 +
  55 + @Override
  56 + public void onCreate(Bundle savedInstanceState) {
  57 + super.onCreate(savedInstanceState);
  58 + if (getArguments() != null) {
  59 + mParam1 = getArguments().getString(ARG_PARAM1);
  60 + mParam2 = getArguments().getString(ARG_PARAM2);
  61 + }
  62 + }
  63 +
  64 + @Override
  65 + public View onCreateView(LayoutInflater inflater, ViewGroup container,
  66 + Bundle savedInstanceState) {
  67 + // Inflate the layout for this fragment
  68 + return inflater.inflate(R.layout.fragment_login_and_regist, container, false);
  69 + }
  70 +
  71 + // TODO: Rename method, update argument and hook method into UI event
  72 + public void onButtonPressed(Uri uri) {
  73 + if (mListener != null) {
  74 + mListener.onFragmentInteraction(uri);
  75 + }
  76 + }
  77 +
  78 + @Override
  79 + public void onAttach(Context context) {
  80 + super.onAttach(context);
  81 + if (context instanceof OnFragmentInteractionListener) {
  82 + mListener = (OnFragmentInteractionListener) context;
  83 + } else {
  84 + throw new RuntimeException(context.toString()
  85 + + " must implement OnFragmentInteractionListener");
  86 + }
  87 + }
  88 +
  89 + @Override
  90 + public void onDetach() {
  91 + super.onDetach();
  92 + mListener = null;
  93 + }
  94 +
  95 + /**
  96 + * This interface must be implemented by activities that contain this
  97 + * fragment to allow an interaction in this fragment to be communicated
  98 + * to the activity and potentially other fragments contained in that
  99 + * activity.
  100 + * <p>
  101 + * See the Android Training lesson <a href=
  102 + * "http://developer.android.com/training/basics/fragments/communicating.html"
  103 + * >Communicating with Other Fragments</a> for more information.
  104 + */
  105 + public interface OnFragmentInteractionListener {
  106 + // TODO: Update argument type and name
  107 + void onFragmentInteraction(Uri uri);
  108 + }
  109 +}
app/src/main/res/drawable-v24/ic_launcher_foreground.xml 0 → 100644
  1 +++ a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
@@ -0,0 +1,34 @@ @@ -0,0 +1,34 @@
  1 +<vector xmlns:android="http://schemas.android.com/apk/res/android"
  2 + xmlns:aapt="http://schemas.android.com/aapt"
  3 + android:width="108dp"
  4 + android:height="108dp"
  5 + android:viewportHeight="108"
  6 + android:viewportWidth="108">
  7 + <path
  8 + android:fillType="evenOdd"
  9 + android:pathData="M32,64C32,64 38.39,52.99 44.13,50.95C51.37,48.37 70.14,49.57 70.14,49.57L108.26,87.69L108,109.01L75.97,107.97L32,64Z"
  10 + android:strokeColor="#00000000"
  11 + android:strokeWidth="1">
  12 + <aapt:attr name="android:fillColor">
  13 + <gradient
  14 + android:endX="78.5885"
  15 + android:endY="90.9159"
  16 + android:startX="48.7653"
  17 + android:startY="61.0927"
  18 + android:type="linear">
  19 + <item
  20 + android:color="#44000000"
  21 + android:offset="0.0" />
  22 + <item
  23 + android:color="#00000000"
  24 + android:offset="1.0" />
  25 + </gradient>
  26 + </aapt:attr>
  27 + </path>
  28 + <path
  29 + android:fillColor="#FFFFFF"
  30 + android:fillType="nonZero"
  31 + android:pathData="M66.94,46.02L66.94,46.02C72.44,50.07 76,56.61 76,64L32,64C32,56.61 35.56,50.11 40.98,46.06L36.18,41.19C35.45,40.45 35.45,39.3 36.18,38.56C36.91,37.81 38.05,37.81 38.78,38.56L44.25,44.05C47.18,42.57 50.48,41.71 54,41.71C57.48,41.71 60.78,42.57 63.68,44.05L69.11,38.56C69.84,37.81 70.98,37.81 71.71,38.56C72.44,39.3 72.44,40.45 71.71,41.19L66.94,46.02ZM62.94,56.92C64.08,56.92 65,56.01 65,54.88C65,53.76 64.08,52.85 62.94,52.85C61.8,52.85 60.88,53.76 60.88,54.88C60.88,56.01 61.8,56.92 62.94,56.92ZM45.06,56.92C46.2,56.92 47.13,56.01 47.13,54.88C47.13,53.76 46.2,52.85 45.06,52.85C43.92,52.85 43,53.76 43,54.88C43,56.01 43.92,56.92 45.06,56.92Z"
  32 + android:strokeColor="#00000000"
  33 + android:strokeWidth="1" />
  34 +</vector>
app/src/main/res/drawable/ic_launcher_background.xml 0 → 100644
  1 +++ a/app/src/main/res/drawable/ic_launcher_background.xml
@@ -0,0 +1,170 @@ @@ -0,0 +1,170 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<vector xmlns:android="http://schemas.android.com/apk/res/android"
  3 + android:width="108dp"
  4 + android:height="108dp"
  5 + android:viewportHeight="108"
  6 + android:viewportWidth="108">
  7 + <path
  8 + android:fillColor="#26A69A"
  9 + android:pathData="M0,0h108v108h-108z" />
  10 + <path
  11 + android:fillColor="#00000000"
  12 + android:pathData="M9,0L9,108"
  13 + android:strokeColor="#33FFFFFF"
  14 + android:strokeWidth="0.8" />
  15 + <path
  16 + android:fillColor="#00000000"
  17 + android:pathData="M19,0L19,108"
  18 + android:strokeColor="#33FFFFFF"
  19 + android:strokeWidth="0.8" />
  20 + <path
  21 + android:fillColor="#00000000"
  22 + android:pathData="M29,0L29,108"
  23 + android:strokeColor="#33FFFFFF"
  24 + android:strokeWidth="0.8" />
  25 + <path
  26 + android:fillColor="#00000000"
  27 + android:pathData="M39,0L39,108"
  28 + android:strokeColor="#33FFFFFF"
  29 + android:strokeWidth="0.8" />
  30 + <path
  31 + android:fillColor="#00000000"
  32 + android:pathData="M49,0L49,108"
  33 + android:strokeColor="#33FFFFFF"
  34 + android:strokeWidth="0.8" />
  35 + <path
  36 + android:fillColor="#00000000"
  37 + android:pathData="M59,0L59,108"
  38 + android:strokeColor="#33FFFFFF"
  39 + android:strokeWidth="0.8" />
  40 + <path
  41 + android:fillColor="#00000000"
  42 + android:pathData="M69,0L69,108"
  43 + android:strokeColor="#33FFFFFF"
  44 + android:strokeWidth="0.8" />
  45 + <path
  46 + android:fillColor="#00000000"
  47 + android:pathData="M79,0L79,108"
  48 + android:strokeColor="#33FFFFFF"
  49 + android:strokeWidth="0.8" />
  50 + <path
  51 + android:fillColor="#00000000"
  52 + android:pathData="M89,0L89,108"
  53 + android:strokeColor="#33FFFFFF"
  54 + android:strokeWidth="0.8" />
  55 + <path
  56 + android:fillColor="#00000000"
  57 + android:pathData="M99,0L99,108"
  58 + android:strokeColor="#33FFFFFF"
  59 + android:strokeWidth="0.8" />
  60 + <path
  61 + android:fillColor="#00000000"
  62 + android:pathData="M0,9L108,9"
  63 + android:strokeColor="#33FFFFFF"
  64 + android:strokeWidth="0.8" />
  65 + <path
  66 + android:fillColor="#00000000"
  67 + android:pathData="M0,19L108,19"
  68 + android:strokeColor="#33FFFFFF"
  69 + android:strokeWidth="0.8" />
  70 + <path
  71 + android:fillColor="#00000000"
  72 + android:pathData="M0,29L108,29"
  73 + android:strokeColor="#33FFFFFF"
  74 + android:strokeWidth="0.8" />
  75 + <path
  76 + android:fillColor="#00000000"
  77 + android:pathData="M0,39L108,39"
  78 + android:strokeColor="#33FFFFFF"
  79 + android:strokeWidth="0.8" />
  80 + <path
  81 + android:fillColor="#00000000"
  82 + android:pathData="M0,49L108,49"
  83 + android:strokeColor="#33FFFFFF"
  84 + android:strokeWidth="0.8" />
  85 + <path
  86 + android:fillColor="#00000000"
  87 + android:pathData="M0,59L108,59"
  88 + android:strokeColor="#33FFFFFF"
  89 + android:strokeWidth="0.8" />
  90 + <path
  91 + android:fillColor="#00000000"
  92 + android:pathData="M0,69L108,69"
  93 + android:strokeColor="#33FFFFFF"
  94 + android:strokeWidth="0.8" />
  95 + <path
  96 + android:fillColor="#00000000"
  97 + android:pathData="M0,79L108,79"
  98 + android:strokeColor="#33FFFFFF"
  99 + android:strokeWidth="0.8" />
  100 + <path
  101 + android:fillColor="#00000000"
  102 + android:pathData="M0,89L108,89"
  103 + android:strokeColor="#33FFFFFF"
  104 + android:strokeWidth="0.8" />
  105 + <path
  106 + android:fillColor="#00000000"
  107 + android:pathData="M0,99L108,99"
  108 + android:strokeColor="#33FFFFFF"
  109 + android:strokeWidth="0.8" />
  110 + <path
  111 + android:fillColor="#00000000"
  112 + android:pathData="M19,29L89,29"
  113 + android:strokeColor="#33FFFFFF"
  114 + android:strokeWidth="0.8" />
  115 + <path
  116 + android:fillColor="#00000000"
  117 + android:pathData="M19,39L89,39"
  118 + android:strokeColor="#33FFFFFF"
  119 + android:strokeWidth="0.8" />
  120 + <path
  121 + android:fillColor="#00000000"
  122 + android:pathData="M19,49L89,49"
  123 + android:strokeColor="#33FFFFFF"
  124 + android:strokeWidth="0.8" />
  125 + <path
  126 + android:fillColor="#00000000"
  127 + android:pathData="M19,59L89,59"
  128 + android:strokeColor="#33FFFFFF"
  129 + android:strokeWidth="0.8" />
  130 + <path
  131 + android:fillColor="#00000000"
  132 + android:pathData="M19,69L89,69"
  133 + android:strokeColor="#33FFFFFF"
  134 + android:strokeWidth="0.8" />
  135 + <path
  136 + android:fillColor="#00000000"
  137 + android:pathData="M19,79L89,79"
  138 + android:strokeColor="#33FFFFFF"
  139 + android:strokeWidth="0.8" />
  140 + <path
  141 + android:fillColor="#00000000"
  142 + android:pathData="M29,19L29,89"
  143 + android:strokeColor="#33FFFFFF"
  144 + android:strokeWidth="0.8" />
  145 + <path
  146 + android:fillColor="#00000000"
  147 + android:pathData="M39,19L39,89"
  148 + android:strokeColor="#33FFFFFF"
  149 + android:strokeWidth="0.8" />
  150 + <path
  151 + android:fillColor="#00000000"
  152 + android:pathData="M49,19L49,89"
  153 + android:strokeColor="#33FFFFFF"
  154 + android:strokeWidth="0.8" />
  155 + <path
  156 + android:fillColor="#00000000"
  157 + android:pathData="M59,19L59,89"
  158 + android:strokeColor="#33FFFFFF"
  159 + android:strokeWidth="0.8" />
  160 + <path
  161 + android:fillColor="#00000000"
  162 + android:pathData="M69,19L69,89"
  163 + android:strokeColor="#33FFFFFF"
  164 + android:strokeWidth="0.8" />
  165 + <path
  166 + android:fillColor="#00000000"
  167 + android:pathData="M79,19L79,89"
  168 + android:strokeColor="#33FFFFFF"
  169 + android:strokeWidth="0.8" />
  170 +</vector>
app/src/main/res/layout/activity_main.xml 0 → 100644
  1 +++ a/app/src/main/res/layout/activity_main.xml
@@ -0,0 +1,18 @@ @@ -0,0 +1,18 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3 + xmlns:app="http://schemas.android.com/apk/res-auto"
  4 + xmlns:tools="http://schemas.android.com/tools"
  5 + android:layout_width="match_parent"
  6 + android:layout_height="match_parent"
  7 + tools:context="com.shunzhi.parent.ui.MainActivity">
  8 +
  9 + <TextView
  10 + android:layout_width="wrap_content"
  11 + android:layout_height="wrap_content"
  12 + android:text="Hello World!"
  13 + app:layout_constraintBottom_toBottomOf="parent"
  14 + app:layout_constraintLeft_toLeftOf="parent"
  15 + app:layout_constraintRight_toRightOf="parent"
  16 + app:layout_constraintTop_toTopOf="parent" />
  17 +
  18 +</FrameLayout>
app/src/main/res/layout/activity_regist.xml 0 → 100644
  1 +++ a/app/src/main/res/layout/activity_regist.xml
@@ -0,0 +1,9 @@ @@ -0,0 +1,9 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3 + xmlns:app="http://schemas.android.com/apk/res-auto"
  4 + xmlns:tools="http://schemas.android.com/tools"
  5 + android:layout_width="match_parent"
  6 + android:layout_height="match_parent"
  7 + tools:context="com.shunzhi.parent.ui.activity.LoginAndRegistActivity">
  8 +
  9 +</android.support.constraint.ConstraintLayout>
app/src/main/res/layout/activity_start.xml 0 → 100644
  1 +++ a/app/src/main/res/layout/activity_start.xml
@@ -0,0 +1,9 @@ @@ -0,0 +1,9 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3 + xmlns:app="http://schemas.android.com/apk/res-auto"
  4 + xmlns:tools="http://schemas.android.com/tools"
  5 + android:layout_width="match_parent"
  6 + android:layout_height="match_parent"
  7 + tools:context="com.shunzhi.parent.ui.activity.StartActivity">
  8 +
  9 +</android.support.constraint.ConstraintLayout>
app/src/main/res/layout/fragment_ce_ping.xml 0 → 100644
  1 +++ a/app/src/main/res/layout/fragment_ce_ping.xml
@@ -0,0 +1,13 @@ @@ -0,0 +1,13 @@
  1 +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2 + xmlns:tools="http://schemas.android.com/tools"
  3 + android:layout_width="match_parent"
  4 + android:layout_height="match_parent"
  5 + tools:context="com.shunzhi.parent.ui.fragment.CePingFragment">
  6 +
  7 + <!-- TODO: Update blank fragment layout -->
  8 + <TextView
  9 + android:layout_width="match_parent"
  10 + android:layout_height="match_parent"
  11 + android:text="@string/hello_blank_fragment" />
  12 +
  13 +</FrameLayout>
app/src/main/res/layout/fragment_login_and_regist.xml 0 → 100644
  1 +++ a/app/src/main/res/layout/fragment_login_and_regist.xml
@@ -0,0 +1,13 @@ @@ -0,0 +1,13 @@
  1 +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2 + xmlns:tools="http://schemas.android.com/tools"
  3 + android:layout_width="match_parent"
  4 + android:layout_height="match_parent"
  5 + tools:context="com.shunzhi.parent.ui.fragment.loginandregistfragment.LoginAndRegistFragment">
  6 +
  7 + <!-- TODO: Update blank fragment layout -->
  8 + <TextView
  9 + android:layout_width="match_parent"
  10 + android:layout_height="match_parent"
  11 + android:text="@string/hello_blank_fragment" />
  12 +
  13 +</FrameLayout>
app/src/main/res/layout/fragment_mine.xml 0 → 100644
  1 +++ a/app/src/main/res/layout/fragment_mine.xml
@@ -0,0 +1,13 @@ @@ -0,0 +1,13 @@
  1 +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2 + xmlns:tools="http://schemas.android.com/tools"
  3 + android:layout_width="match_parent"
  4 + android:layout_height="match_parent"
  5 + tools:context="com.shunzhi.parent.ui.fragment.MineFragment">
  6 +
  7 + <!-- TODO: Update blank fragment layout -->
  8 + <TextView
  9 + android:layout_width="match_parent"
  10 + android:layout_height="match_parent"
  11 + android:text="@string/hello_blank_fragment" />
  12 +
  13 +</FrameLayout>
app/src/main/res/layout/fragment_report.xml 0 → 100644
  1 +++ a/app/src/main/res/layout/fragment_report.xml
@@ -0,0 +1,13 @@ @@ -0,0 +1,13 @@
  1 +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2 + xmlns:tools="http://schemas.android.com/tools"
  3 + android:layout_width="match_parent"
  4 + android:layout_height="match_parent"
  5 + tools:context="com.shunzhi.parent.ui.fragment.ReportFragment">
  6 +
  7 + <!-- TODO: Update blank fragment layout -->
  8 + <TextView
  9 + android:layout_width="match_parent"
  10 + android:layout_height="match_parent"
  11 + android:text="@string/hello_blank_fragment" />
  12 +
  13 +</FrameLayout>
app/src/main/res/layout/fragment_zi_xun.xml 0 → 100644
  1 +++ a/app/src/main/res/layout/fragment_zi_xun.xml
@@ -0,0 +1,13 @@ @@ -0,0 +1,13 @@
  1 +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2 + xmlns:tools="http://schemas.android.com/tools"
  3 + android:layout_width="match_parent"
  4 + android:layout_height="match_parent"
  5 + tools:context="com.shunzhi.parent.ui.fragment.ConsultFragment">
  6 +
  7 + <!-- TODO: Update blank fragment layout -->
  8 + <TextView
  9 + android:layout_width="match_parent"
  10 + android:layout_height="match_parent"
  11 + android:text="@string/hello_blank_fragment" />
  12 +
  13 +</FrameLayout>
app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml 0 → 100644
  1 +++ a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
@@ -0,0 +1,5 @@ @@ -0,0 +1,5 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
  3 + <background android:drawable="@drawable/ic_launcher_background" />
  4 + <foreground android:drawable="@drawable/ic_launcher_foreground" />
  5 +</adaptive-icon>
0 \ No newline at end of file 6 \ No newline at end of file
app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml 0 → 100644
  1 +++ a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -0,0 +1,5 @@ @@ -0,0 +1,5 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
  3 + <background android:drawable="@drawable/ic_launcher_background" />
  4 + <foreground android:drawable="@drawable/ic_launcher_foreground" />
  5 +</adaptive-icon>
0 \ No newline at end of file 6 \ No newline at end of file
app/src/main/res/mipmap-hdpi/ic_launcher.png 0 → 100644

2.98 KB

app/src/main/res/mipmap-hdpi/ic_launcher_round.png 0 → 100644

4.91 KB

app/src/main/res/mipmap-mdpi/ic_launcher.png 0 → 100644

2.05 KB

app/src/main/res/mipmap-mdpi/ic_launcher_round.png 0 → 100644

2.79 KB

app/src/main/res/mipmap-xhdpi/ic_launcher.png 0 → 100644

4.46 KB

app/src/main/res/mipmap-xhdpi/ic_launcher_round.png 0 → 100644

6.93 KB

app/src/main/res/mipmap-xxhdpi/ic_launcher.png 0 → 100644

6.31 KB

app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png 0 → 100644

10.4 KB

app/src/main/res/mipmap-xxxhdpi/ic_launcher.png 0 → 100644

9.03 KB

app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png 0 → 100644

15.2 KB

app/src/main/res/values/colors.xml 0 → 100644
  1 +++ a/app/src/main/res/values/colors.xml
@@ -0,0 +1,6 @@ @@ -0,0 +1,6 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<resources>
  3 + <color name="colorPrimary">#3F51B5</color>
  4 + <color name="colorPrimaryDark">#303F9F</color>
  5 + <color name="colorAccent">#FF4081</color>
  6 +</resources>
app/src/main/res/values/strings.xml 0 → 100644
  1 +++ a/app/src/main/res/values/strings.xml
@@ -0,0 +1,6 @@ @@ -0,0 +1,6 @@
  1 +<resources>
  2 + <string name="app_name">parent</string>
  3 +
  4 + <!-- TODO: Remove or change this placeholder text -->
  5 + <string name="hello_blank_fragment">Hello blank fragment</string>
  6 +</resources>
app/src/main/res/values/styles.xml 0 → 100644
  1 +++ a/app/src/main/res/values/styles.xml
@@ -0,0 +1,11 @@ @@ -0,0 +1,11 @@
  1 +<resources>
  2 +
  3 + <!-- Base application theme. -->
  4 + <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
  5 + <!-- Customize your theme here. -->
  6 + <item name="colorPrimary">@color/colorPrimary</item>
  7 + <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
  8 + <item name="colorAccent">@color/colorAccent</item>
  9 + </style>
  10 +
  11 +</resources>
app/src/test/java/com/shunzhi/parent/ExampleUnitTest.java 0 → 100644
  1 +++ a/app/src/test/java/com/shunzhi/parent/ExampleUnitTest.java
@@ -0,0 +1,17 @@ @@ -0,0 +1,17 @@
  1 +package com.shunzhi.parent;
  2 +
  3 +import org.junit.Test;
  4 +
  5 +import static org.junit.Assert.*;
  6 +
  7 +/**
  8 + * Example local unit test, which will execute on the development machine (host).
  9 + *
  10 + * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
  11 + */
  12 +public class ExampleUnitTest {
  13 + @Test
  14 + public void addition_isCorrect() throws Exception {
  15 + assertEquals(4, 2 + 2);
  16 + }
  17 +}
0 \ No newline at end of file 18 \ No newline at end of file
build.gradle 0 → 100644
  1 +++ a/build.gradle
@@ -0,0 +1,66 @@ @@ -0,0 +1,66 @@
  1 +// Top-level build file where you can add configuration options common to all sub-projects/modules.
  2 +
  3 +buildscript {
  4 +
  5 + repositories {
  6 + google()
  7 + jcenter()
  8 + }
  9 + dependencies {
  10 + classpath 'com.android.tools.build:gradle:3.0.1'
  11 +
  12 +
  13 + // NOTE: Do not place your application dependencies here; they belong
  14 + // in the individual module build.gradle files
  15 + }
  16 +}
  17 +
  18 +allprojects {
  19 + repositories {
  20 + google()
  21 + jcenter()
  22 + }
  23 +}
  24 +
  25 +task clean(type: Delete) {
  26 + delete rootProject.buildDir
  27 +}
  28 +
  29 +ext {
  30 + // Sdk and tools
  31 + minSdkVersion = 16
  32 + targetSdkVersion = 26
  33 + compileSdkVersion = 26
  34 + buildToolsVersion = '26.0.2'
  35 +
  36 + // App dependencies
  37 + supportLibraryVersion = '26.1.0'
  38 + guavaVersion = '18.0'
  39 + junitVersion = '4.12'
  40 + mockitoVersion = '1.10.19'
  41 + powerMockito = '1.6.2'
  42 + hamcrestVersion = '1.3'
  43 + runnerVersion = '0.4.1'
  44 + rulesVersion = '0.4.1'
  45 + espressoVersion = '2.2.1'
  46 + retrofitVersion = '2.2.0'
  47 + okhttploggingVersion = '3.4.1'
  48 + okhttpVersion = '3.4.1'
  49 + rxjavaVersion = '2.0.1'
  50 + rxandroidVersion = '2.0.1'
  51 + rxbindingVersion = '2.0.0'
  52 + rxPerssionsVersion = '0.9.4@aar'
  53 + glideVersion = '3.6.1'
  54 + glideokhttpVersion = '1.3.1'
  55 + photoviewVersion = '1.2.4'
  56 + butterknifeVersion = '8.4.0'
  57 + fragmentationVersion = '1.1.6'
  58 + loggerVersion = '1.15'
  59 + circleImageviewVersion = '2.1.0'
  60 + BaseRecyclerViewAdapterHelperVersion = '2.9.34'
  61 + SwtichButtonVersion = '1.4.6'
  62 + PhotoViewVersion = '1.4.1'
  63 + BottomSheetVersion = '1.3.0@aar'
  64 + glideTransformationVersion = '2.0.1'
  65 +}
  66 +
gradle.properties 0 → 100644
  1 +++ a/gradle.properties
@@ -0,0 +1,17 @@ @@ -0,0 +1,17 @@
  1 +# Project-wide Gradle settings.
  2 +
  3 +# IDE (e.g. Android Studio) users:
  4 +# Gradle settings configured through the IDE *will override*
  5 +# any settings specified in this file.
  6 +
  7 +# For more details on how to configure your build environment visit
  8 +# http://www.gradle.org/docs/current/userguide/build_environment.html
  9 +
  10 +# Specifies the JVM arguments used for the daemon process.
  11 +# The setting is particularly useful for tweaking memory settings.
  12 +org.gradle.jvmargs=-Xmx1536m
  13 +
  14 +# When configured, Gradle will run in incubating parallel mode.
  15 +# This option should only be used with decoupled projects. More details, visit
  16 +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
  17 +# org.gradle.parallel=true
gradle/wrapper/gradle-wrapper.jar 0 → 100644
No preview for this file type
gradle/wrapper/gradle-wrapper.properties 0 → 100644
  1 +++ a/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@ @@ -0,0 +1,6 @@
  1 +#Tue Feb 27 14:00:51 CST 2018
  2 +distributionBase=GRADLE_USER_HOME
  3 +distributionPath=wrapper/dists
  4 +zipStoreBase=GRADLE_USER_HOME
  5 +zipStorePath=wrapper/dists
  6 +distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip
gradlew 0 → 100644
  1 +++ a/gradlew
@@ -0,0 +1,160 @@ @@ -0,0 +1,160 @@
  1 +#!/usr/bin/env bash
  2 +
  3 +##############################################################################
  4 +##
  5 +## Gradle start up script for UN*X
  6 +##
  7 +##############################################################################
  8 +
  9 +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
  10 +DEFAULT_JVM_OPTS=""
  11 +
  12 +APP_NAME="Gradle"
  13 +APP_BASE_NAME=`basename "$0"`
  14 +
  15 +# Use the maximum available, or set MAX_FD != -1 to use that value.
  16 +MAX_FD="maximum"
  17 +
  18 +warn ( ) {
  19 + echo "$*"
  20 +}
  21 +
  22 +die ( ) {
  23 + echo
  24 + echo "$*"
  25 + echo
  26 + exit 1
  27 +}
  28 +
  29 +# OS specific support (must be 'true' or 'false').
  30 +cygwin=false
  31 +msys=false
  32 +darwin=false
  33 +case "`uname`" in
  34 + CYGWIN* )
  35 + cygwin=true
  36 + ;;
  37 + Darwin* )
  38 + darwin=true
  39 + ;;
  40 + MINGW* )
  41 + msys=true
  42 + ;;
  43 +esac
  44 +
  45 +# Attempt to set APP_HOME
  46 +# Resolve links: $0 may be a link
  47 +PRG="$0"
  48 +# Need this for relative symlinks.
  49 +while [ -h "$PRG" ] ; do
  50 + ls=`ls -ld "$PRG"`
  51 + link=`expr "$ls" : '.*-> \(.*\)$'`
  52 + if expr "$link" : '/.*' > /dev/null; then
  53 + PRG="$link"
  54 + else
  55 + PRG=`dirname "$PRG"`"/$link"
  56 + fi
  57 +done
  58 +SAVED="`pwd`"
  59 +cd "`dirname \"$PRG\"`/" >/dev/null
  60 +APP_HOME="`pwd -P`"
  61 +cd "$SAVED" >/dev/null
  62 +
  63 +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
  64 +
  65 +# Determine the Java command to use to start the JVM.
  66 +if [ -n "$JAVA_HOME" ] ; then
  67 + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
  68 + # IBM's JDK on AIX uses strange locations for the executables
  69 + JAVACMD="$JAVA_HOME/jre/sh/java"
  70 + else
  71 + JAVACMD="$JAVA_HOME/bin/java"
  72 + fi
  73 + if [ ! -x "$JAVACMD" ] ; then
  74 + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
  75 +
  76 +Please set the JAVA_HOME variable in your environment to match the
  77 +location of your Java installation."
  78 + fi
  79 +else
  80 + JAVACMD="java"
  81 + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
  82 +
  83 +Please set the JAVA_HOME variable in your environment to match the
  84 +location of your Java installation."
  85 +fi
  86 +
  87 +# Increase the maximum file descriptors if we can.
  88 +if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
  89 + MAX_FD_LIMIT=`ulimit -H -n`
  90 + if [ $? -eq 0 ] ; then
  91 + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
  92 + MAX_FD="$MAX_FD_LIMIT"
  93 + fi
  94 + ulimit -n $MAX_FD
  95 + if [ $? -ne 0 ] ; then
  96 + warn "Could not set maximum file descriptor limit: $MAX_FD"
  97 + fi
  98 + else
  99 + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
  100 + fi
  101 +fi
  102 +
  103 +# For Darwin, add options to specify how the application appears in the dock
  104 +if $darwin; then
  105 + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
  106 +fi
  107 +
  108 +# For Cygwin, switch paths to Windows format before running java
  109 +if $cygwin ; then
  110 + APP_HOME=`cygpath --path --mixed "$APP_HOME"`
  111 + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
  112 + JAVACMD=`cygpath --unix "$JAVACMD"`
  113 +
  114 + # We build the pattern for arguments to be converted via cygpath
  115 + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
  116 + SEP=""
  117 + for dir in $ROOTDIRSRAW ; do
  118 + ROOTDIRS="$ROOTDIRS$SEP$dir"
  119 + SEP="|"
  120 + done
  121 + OURCYGPATTERN="(^($ROOTDIRS))"
  122 + # Add a user-defined pattern to the cygpath arguments
  123 + if [ "$GRADLE_CYGPATTERN" != "" ] ; then
  124 + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
  125 + fi
  126 + # Now convert the arguments - kludge to limit ourselves to /bin/sh
  127 + i=0
  128 + for arg in "$@" ; do
  129 + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
  130 + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
  131 +
  132 + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
  133 + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
  134 + else
  135 + eval `echo args$i`="\"$arg\""
  136 + fi
  137 + i=$((i+1))
  138 + done
  139 + case $i in
  140 + (0) set -- ;;
  141 + (1) set -- "$args0" ;;
  142 + (2) set -- "$args0" "$args1" ;;
  143 + (3) set -- "$args0" "$args1" "$args2" ;;
  144 + (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
  145 + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
  146 + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
  147 + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
  148 + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
  149 + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
  150 + esac
  151 +fi
  152 +
  153 +# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
  154 +function splitJvmOpts() {
  155 + JVM_OPTS=("$@")
  156 +}
  157 +eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
  158 +JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
  159 +
  160 +exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
gradlew.bat 0 → 100644
  1 +++ a/gradlew.bat
@@ -0,0 +1,90 @@ @@ -0,0 +1,90 @@
  1 +@if "%DEBUG%" == "" @echo off
  2 +@rem ##########################################################################
  3 +@rem
  4 +@rem Gradle startup script for Windows
  5 +@rem
  6 +@rem ##########################################################################
  7 +
  8 +@rem Set local scope for the variables with windows NT shell
  9 +if "%OS%"=="Windows_NT" setlocal
  10 +
  11 +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
  12 +set DEFAULT_JVM_OPTS=
  13 +
  14 +set DIRNAME=%~dp0
  15 +if "%DIRNAME%" == "" set DIRNAME=.
  16 +set APP_BASE_NAME=%~n0
  17 +set APP_HOME=%DIRNAME%
  18 +
  19 +@rem Find java.exe
  20 +if defined JAVA_HOME goto findJavaFromJavaHome
  21 +
  22 +set JAVA_EXE=java.exe
  23 +%JAVA_EXE% -version >NUL 2>&1
  24 +if "%ERRORLEVEL%" == "0" goto init
  25 +
  26 +echo.
  27 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
  28 +echo.
  29 +echo Please set the JAVA_HOME variable in your environment to match the
  30 +echo location of your Java installation.
  31 +
  32 +goto fail
  33 +
  34 +:findJavaFromJavaHome
  35 +set JAVA_HOME=%JAVA_HOME:"=%
  36 +set JAVA_EXE=%JAVA_HOME%/bin/java.exe
  37 +
  38 +if exist "%JAVA_EXE%" goto init
  39 +
  40 +echo.
  41 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
  42 +echo.
  43 +echo Please set the JAVA_HOME variable in your environment to match the
  44 +echo location of your Java installation.
  45 +
  46 +goto fail
  47 +
  48 +:init
  49 +@rem Get command-line arguments, handling Windowz variants
  50 +
  51 +if not "%OS%" == "Windows_NT" goto win9xME_args
  52 +if "%@eval[2+2]" == "4" goto 4NT_args
  53 +
  54 +:win9xME_args
  55 +@rem Slurp the command line arguments.
  56 +set CMD_LINE_ARGS=
  57 +set _SKIP=2
  58 +
  59 +:win9xME_args_slurp
  60 +if "x%~1" == "x" goto execute
  61 +
  62 +set CMD_LINE_ARGS=%*
  63 +goto execute
  64 +
  65 +:4NT_args
  66 +@rem Get arguments from the 4NT Shell from JP Software
  67 +set CMD_LINE_ARGS=%$
  68 +
  69 +:execute
  70 +@rem Setup the command line
  71 +
  72 +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
  73 +
  74 +@rem Execute Gradle
  75 +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
  76 +
  77 +:end
  78 +@rem End local scope for the variables with windows NT shell
  79 +if "%ERRORLEVEL%"=="0" goto mainEnd
  80 +
  81 +:fail
  82 +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
  83 +rem the _cmd.exe /c_ return code!
  84 +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
  85 +exit /b 1
  86 +
  87 +:mainEnd
  88 +if "%OS%"=="Windows_NT" endlocal
  89 +
  90 +:omega
mvpsdk/.gitignore 0 → 100644
  1 +++ a/mvpsdk/.gitignore
@@ -0,0 +1 @@ @@ -0,0 +1 @@
  1 +/build
mvpsdk/build.gradle 0 → 100644
  1 +++ a/mvpsdk/build.gradle
@@ -0,0 +1,102 @@ @@ -0,0 +1,102 @@
  1 +apply plugin: 'com.android.library'
  2 +
  3 +android {
  4 + compileSdkVersion rootProject.ext.compileSdkVersion
  5 + buildToolsVersion rootProject.ext.buildToolsVersion
  6 +
  7 +
  8 + defaultConfig {
  9 + minSdkVersion rootProject.ext.minSdkVersion
  10 + targetSdkVersion rootProject.ext.targetSdkVersion
  11 + versionCode 1
  12 + versionName "1.0"
  13 +
  14 + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
  15 +
  16 + }
  17 +
  18 + buildTypes {
  19 + def BOOLEAN = "boolean"
  20 + def TRUE = "true"
  21 + def FALSE = "false"
  22 + def IS_SHOW_LOG = "IS_SHOW_LOG"
  23 +
  24 + release {
  25 + minifyEnabled false
  26 + buildConfigField BOOLEAN, IS_SHOW_LOG, FALSE
  27 + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
  28 + }
  29 + }
  30 + publishNonDefault true
  31 +}
  32 +//repositories {
  33 +// flatDir {
  34 +// dirs 'libs' //this way we can find the .aar file in libs folder
  35 +// }
  36 +// google()
  37 +//}
  38 +dependencies {
  39 + implementation fileTree(dir: 'libs', include: ['*.jar'])
  40 +
  41 + implementation 'com.android.support:appcompat-v7:26.1.0'
  42 + testImplementation 'junit:junit:4.12'
  43 + androidTestImplementation 'com.android.support.test:runner:1.0.1'
  44 + androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
  45 +
  46 + // Android support
  47 + compile "com.android.support:appcompat-v7:$rootProject.supportLibraryVersion"
  48 + compile "com.android.support:cardview-v7:$rootProject.supportLibraryVersion"
  49 + compile "com.android.support:design:$rootProject.supportLibraryVersion"
  50 + compile "com.android.support:recyclerview-v7:$rootProject.supportLibraryVersion"
  51 +
  52 + // Retrofit
  53 + compile "com.squareup.retrofit2:retrofit:$rootProject.retrofitVersion"
  54 + compile "com.squareup.retrofit2:converter-gson:$rootProject.retrofitVersion"
  55 + compile "com.squareup.retrofit2:adapter-rxjava2:$rootProject.retrofitVersion"
  56 + compile "com.squareup.okhttp3:logging-interceptor:$rootProject.okhttploggingVersion"
  57 + compile "com.squareup.okhttp3:okhttp:$rootProject.okhttpVersion"
  58 +
  59 + // RxJava
  60 + compile "io.reactivex.rxjava2:rxjava:$rootProject.rxjavaVersion"
  61 + compile "io.reactivex.rxjava2:rxandroid:$rootProject.rxandroidVersion"
  62 + compile "com.jakewharton.rxbinding2:rxbinding:$rootProject.rxbindingVersion"
  63 +
  64 + // Glide
  65 + compile "com.github.bumptech.glide:glide:$rootProject.glideVersion"
  66 + compile "com.github.bumptech.glide:okhttp-integration:$rootProject.glideokhttpVersion"
  67 + compile "jp.wasabeef:glide-transformations:$rootProject.glideTransformationVersion"
  68 +
  69 + //Butterknife
  70 + compile "com.jakewharton:butterknife:$rootProject.butterknifeVersion"
  71 + annotationProcessor 'com.jakewharton:butterknife-compiler:8.4.0'
  72 +
  73 + //fragmentation
  74 + compile "me.yokeyword:fragmentation:$rootProject.fragmentationVersion"
  75 +
  76 + //Logger
  77 + compile "com.orhanobut:logger:$rootProject.loggerVersion"
  78 +
  79 + //circle imageview
  80 + compile "de.hdodenhof:circleimageview:$rootProject.circleImageviewVersion"
  81 +
  82 + //BaseRecyclerViewAdapterHelper
  83 + compile "com.github.CymChad:BaseRecyclerViewAdapterHelper:$rootProject.BaseRecyclerViewAdapterHelperVersion"
  84 +
  85 + //SwitchButton
  86 + compile "com.kyleduo.switchbutton:library:$rootProject.SwtichButtonVersion"
  87 +
  88 + //PhotoView
  89 + compile "com.bm.photoview:library:$rootProject.PhotoViewVersion"
  90 +
  91 + compile "com.cocosw:bottomsheet:$rootProject.BottomSheetVersion"
  92 +
  93 + //permissions
  94 + compile "com.tbruyelle.rxpermissions2:rxpermissions:$rootProject.rxPerssionsVersion"
  95 +
  96 + //timber
  97 + compile 'com.jakewharton.timber:timber:4.5.1'
  98 +
  99 + //jiaozivideoplayer
  100 + compile 'cn.jzvd:jiaozivideoplayer:6.2.7'
  101 +// compile(name: 'jiaozivideoplayer-6.2.3', ext: 'aar')
  102 +}
mvpsdk/proguard-rules.pro 0 → 100644
  1 +++ a/mvpsdk/proguard-rules.pro
@@ -0,0 +1,21 @@ @@ -0,0 +1,21 @@
  1 +# Add project specific ProGuard rules here.
  2 +# You can control the set of applied configuration files using the
  3 +# proguardFiles setting in build.gradle.
  4 +#
  5 +# For more details, see
  6 +# http://developer.android.com/guide/developing/tools/proguard.html
  7 +
  8 +# If your project uses WebView with JS, uncomment the following
  9 +# and specify the fully qualified class name to the JavaScript interface
  10 +# class:
  11 +#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
  12 +# public *;
  13 +#}
  14 +
  15 +# Uncomment this to preserve the line number information for
  16 +# debugging stack traces.
  17 +#-keepattributes SourceFile,LineNumberTable
  18 +
  19 +# If you keep the line number information, uncomment this to
  20 +# hide the original source file name.
  21 +#-renamesourcefileattribute SourceFile
mvpsdk/src/androidTest/java/com/share/mvpsdk/ExampleInstrumentedTest.java 0 → 100644
  1 +++ a/mvpsdk/src/androidTest/java/com/share/mvpsdk/ExampleInstrumentedTest.java
@@ -0,0 +1,26 @@ @@ -0,0 +1,26 @@
  1 +package com.share.mvpsdk;
  2 +
  3 +import android.content.Context;
  4 +import android.support.test.InstrumentationRegistry;
  5 +import android.support.test.runner.AndroidJUnit4;
  6 +
  7 +import org.junit.Test;
  8 +import org.junit.runner.RunWith;
  9 +
  10 +import static org.junit.Assert.*;
  11 +
  12 +/**
  13 + * Instrumented test, which will execute on an Android device.
  14 + *
  15 + * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
  16 + */
  17 +@RunWith(AndroidJUnit4.class)
  18 +public class ExampleInstrumentedTest {
  19 + @Test
  20 + public void useAppContext() throws Exception {
  21 + // Context of the app under test.
  22 + Context appContext = InstrumentationRegistry.getTargetContext();
  23 +
  24 + assertEquals("com.share.mvpsdk.test", appContext.getPackageName());
  25 + }
  26 +}
mvpsdk/src/main/AndroidManifest.xml 0 → 100644
  1 +++ a/mvpsdk/src/main/AndroidManifest.xml
@@ -0,0 +1,2 @@ @@ -0,0 +1,2 @@
  1 +<manifest xmlns:android="http://schemas.android.com/apk/res/android"
  2 + package="com.share.mvpsdk" />
mvpsdk/src/main/java/com/share/mvpsdk/AppManager.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/AppManager.java
@@ -0,0 +1,111 @@ @@ -0,0 +1,111 @@
  1 +package com.share.mvpsdk;
  2 +
  3 +import android.annotation.SuppressLint;
  4 +import android.app.Activity;
  5 +import android.app.ActivityManager;
  6 +import android.content.Context;
  7 +
  8 +import java.util.Stack;
  9 +
  10 +/**
  11 + * Created by Horrarndoo on 2017/4/5.
  12 + * <p>
  13 + * AppManager 管理Activity栈
  14 + */
  15 +
  16 +public class AppManager {
  17 + private static Stack<Activity> activityStack;
  18 + private static AppManager instance;
  19 +
  20 + private AppManager() {
  21 + }
  22 +
  23 + /**
  24 + * 单一实例
  25 + */
  26 + public static AppManager getAppManager() {
  27 + if (instance == null) {
  28 + instance = new AppManager();
  29 + }
  30 + return instance;
  31 + }
  32 +
  33 + /**
  34 + * 添加Activity到堆栈
  35 + */
  36 + public void addActivity(Activity activity) {
  37 + if (activityStack == null) {
  38 + activityStack = new Stack<Activity>();
  39 + }
  40 + activityStack.add(activity);
  41 + }
  42 +
  43 + /**
  44 + * 获取当前Activity(堆栈中最后一个压入的)
  45 + */
  46 + public Activity currentActivity() {
  47 + Activity activity = activityStack.lastElement();
  48 + return activity;
  49 + }
  50 +
  51 + /**
  52 + * 结束当前Activity(堆栈中最后一个压入的)
  53 + */
  54 + public void finishActivity() {
  55 + Activity activity = activityStack.lastElement();
  56 + finishActivity(activity);
  57 + }
  58 +
  59 + /**
  60 + * 结束指定的Activity
  61 + */
  62 + public void finishActivity(Activity activity) {
  63 + if (activity != null) {
  64 + activityStack.remove(activity);
  65 + activity.finish();
  66 + activity = null;
  67 + }
  68 + }
  69 +
  70 + /**
  71 + * 结束指定类名的Activity
  72 + */
  73 + public void finishActivity(Class<?> cls) {
  74 + for (Activity activity : activityStack) {
  75 + if (activity.getClass().equals(cls)) {
  76 + finishActivity(activity);
  77 + }
  78 + }
  79 + }
  80 +
  81 + /**
  82 + * 结束所有Activity
  83 + */
  84 + public void finishAllActivity() {
  85 + for (int i = 0, size = activityStack.size(); i < size; i++) {
  86 + if (null != activityStack.get(i)) {
  87 + activityStack.get(i).finish();
  88 + }
  89 + }
  90 + activityStack.clear();
  91 + }
  92 +
  93 + /**
  94 + * 退出应用程序
  95 + */
  96 + @SuppressLint("MissingPermission")
  97 + public void AppExit(Context context) {
  98 + try {
  99 + finishAllActivity();
  100 + ActivityManager activityMgr =
  101 + (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
  102 + activityMgr.killBackgroundProcesses(context.getPackageName());
  103 + System.exit(0);
  104 + } catch (Exception e) {
  105 + }
  106 + }
  107 +
  108 + public boolean isAppExit() {
  109 + return activityStack == null || activityStack.isEmpty();
  110 + }
  111 +}
mvpsdk/src/main/java/com/share/mvpsdk/RxManager.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/RxManager.java
@@ -0,0 +1,23 @@ @@ -0,0 +1,23 @@
  1 +package com.share.mvpsdk;
  2 +
  3 +
  4 +import io.reactivex.disposables.CompositeDisposable;
  5 +import io.reactivex.disposables.Disposable;
  6 +
  7 +/**
  8 + * Created by Horrarndoo on 2017/9/12.
  9 + * <p>
  10 + * 用于管理Rxjava 注册订阅和取消订阅
  11 + */
  12 +
  13 +public class RxManager {
  14 + private CompositeDisposable mCompositeDisposable = new CompositeDisposable();// 管理订阅者者
  15 +
  16 + public void register(Disposable d) {
  17 + mCompositeDisposable.add(d);
  18 + }
  19 +
  20 + public void unSubscribe() {
  21 + mCompositeDisposable.dispose();// 取消订阅
  22 + }
  23 +}
0 \ No newline at end of file 24 \ No newline at end of file
mvpsdk/src/main/java/com/share/mvpsdk/adapter/FragmentAdapter.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/adapter/FragmentAdapter.java
@@ -0,0 +1,42 @@ @@ -0,0 +1,42 @@
  1 +package com.share.mvpsdk.adapter;
  2 +
  3 +
  4 +import android.support.v4.app.Fragment;
  5 +import android.support.v4.app.FragmentManager;
  6 +import android.support.v4.app.FragmentStatePagerAdapter;
  7 +import android.support.v4.view.PagerAdapter;
  8 +import android.view.ViewGroup;
  9 +
  10 +import java.util.List;
  11 +
  12 +/**
  13 + * Created by Horrarndoo on 2017/9/7.
  14 + * <p>
  15 + */
  16 +public class FragmentAdapter extends FragmentStatePagerAdapter {
  17 + private List<Fragment> fragments;
  18 +
  19 + public FragmentAdapter(FragmentManager fm, List<Fragment> fragments) {
  20 + super(fm);
  21 + this.fragments = fragments;
  22 + }
  23 +
  24 + @Override
  25 + public Fragment getItem(int position) {
  26 + return fragments.get(position);
  27 + }
  28 +
  29 + @Override
  30 + public int getCount() {
  31 + return fragments == null ? 0 : fragments.size();
  32 + }
  33 +
  34 + public int getItemPosition(Object object) {
  35 + return PagerAdapter.POSITION_NONE;
  36 + }
  37 +
  38 + @Override
  39 + public void destroyItem(ViewGroup container, int position, Object object) {
  40 + // super.destroyItem(container, position, object);
  41 + }
  42 +}
0 \ No newline at end of file 43 \ No newline at end of file
mvpsdk/src/main/java/com/share/mvpsdk/anim/AnimManager.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/anim/AnimManager.java
@@ -0,0 +1,75 @@ @@ -0,0 +1,75 @@
  1 +package com.share.mvpsdk.anim;
  2 +
  3 +import android.content.Context;
  4 +import android.os.Build;
  5 +import android.support.annotation.NonNull;
  6 +import android.view.View;
  7 +import android.view.animation.AnimationUtils;
  8 +
  9 +/**
  10 + * Created by Horrarndoo on 2017/9/11.
  11 + * <p>
  12 + */
  13 +
  14 +public class AnimManager {
  15 + /**
  16 + * Alpha and scaleX 动画
  17 + * Alpha 0->1
  18 + * ScaleX 0.8->1
  19 + *
  20 + * @param context context
  21 + * @param view view
  22 + * @param startDelay 动画开始前延时(ms)
  23 + * @param duration 动画持续时间(ms)
  24 + */
  25 + public static void animAlphaAndScaleX(Context context, @NonNull View view, int startDelay, int
  26 + duration) {
  27 + view.setAlpha(0f);
  28 + view.setScaleX(0.8f);
  29 +
  30 + if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
  31 + view.animate()
  32 + .alpha(1f)
  33 + .scaleX(1f)
  34 + .setStartDelay(startDelay)
  35 + .setDuration(duration)
  36 + .setInterpolator(AnimUtils.getFastOutSlowInInterpolator(context))
  37 + .start();
  38 + }else{
  39 + view.animate()
  40 + .alpha(1f)
  41 + .scaleX(1f)
  42 + .setStartDelay(startDelay)
  43 + .setDuration(duration)
  44 + .setInterpolator(AnimationUtils.loadInterpolator(context, android.R.interpolator.linear))
  45 + .start();
  46 + }
  47 + }
  48 +
  49 + /**
  50 + * Alpha and scale X Y 动画
  51 + * Alpha 0->1
  52 + * ScaleX 0->1
  53 + * ScaleY 0->1
  54 + *
  55 + * @param context context
  56 + * @param view view
  57 + * @param startDelay 动画开始前延时(ms)
  58 + * @param duration 动画持续时间(ms)
  59 + */
  60 + public static void animAlphaAndScale(Context context, @NonNull View view, int startDelay, int
  61 + duration) {
  62 + view.setAlpha(0f);
  63 + view.setScaleX(0f);
  64 + view.setScaleY(0f);
  65 +
  66 + view.animate()
  67 + .alpha(1f)
  68 + .scaleX(1f)
  69 + .scaleY(1f)
  70 + .setStartDelay(startDelay)
  71 + .setDuration(duration)
  72 + .setInterpolator(AnimationUtils.loadInterpolator(context,
  73 + android.R.interpolator.overshoot)).start();
  74 + }
  75 +}
mvpsdk/src/main/java/com/share/mvpsdk/anim/AnimUtils.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/anim/AnimUtils.java
@@ -0,0 +1,330 @@ @@ -0,0 +1,330 @@
  1 +/*
  2 + * Copyright 2015 Google Inc.
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +
  17 +package com.share.mvpsdk.anim;
  18 +
  19 +import android.animation.Animator;
  20 +import android.animation.TimeInterpolator;
  21 +import android.content.Context;
  22 +import android.os.Build;
  23 +import android.support.annotation.RequiresApi;
  24 +import android.transition.Transition;
  25 +import android.util.ArrayMap;
  26 +import android.util.Property;
  27 +import android.view.animation.AnimationUtils;
  28 +import android.view.animation.Interpolator;
  29 +
  30 +import java.util.ArrayList;
  31 +
  32 +/**
  33 + * Utility methods for working with animations.
  34 + */
  35 +public class AnimUtils {
  36 +
  37 + private AnimUtils() { }
  38 +
  39 + private static Interpolator fastOutSlowIn;
  40 + private static Interpolator fastOutLinearIn;
  41 + private static Interpolator linearOutSlowIn;
  42 +
  43 + public static Interpolator getFastOutSlowInInterpolator(Context context) {
  44 + if (fastOutSlowIn == null) {
  45 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
  46 + fastOutSlowIn = AnimationUtils.loadInterpolator(context,
  47 + android.R.interpolator.fast_out_slow_in);
  48 + }
  49 + }
  50 + return fastOutSlowIn;
  51 + }
  52 +
  53 + public static Interpolator getFastOutLinearInInterpolator(Context context) {
  54 + if (fastOutLinearIn == null) {
  55 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
  56 + fastOutLinearIn = AnimationUtils.loadInterpolator(context,
  57 + android.R.interpolator.fast_out_linear_in);
  58 + }
  59 + }
  60 + return fastOutLinearIn;
  61 + }
  62 +
  63 + public static Interpolator getLinearOutSlowInInterpolator(Context context) {
  64 + if (linearOutSlowIn == null) {
  65 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
  66 + linearOutSlowIn = AnimationUtils.loadInterpolator(context,
  67 + android.R.interpolator.linear_out_slow_in);
  68 + }
  69 + }
  70 + return linearOutSlowIn;
  71 + }
  72 +
  73 + /**
  74 + * Linear interpolate between a and b with parameter t.
  75 + */
  76 + public static float lerp(float a, float b, float t) {
  77 + return a + (b - a) * t;
  78 + }
  79 +
  80 +
  81 + /**
  82 + * An implementation of {@link Property} to be used specifically with fields of
  83 + * type
  84 + * <code>float</code>. This type-specific subclass enables performance benefit by allowing
  85 + * calls to a {@link #set(Object, Float) set()} function that takes the primitive
  86 + * <code>float</code> type and avoids autoboxing and other overhead associated with the
  87 + * <code>Float</code> class.
  88 + *
  89 + * @param <T> The class on which the Property is declared.
  90 + **/
  91 + public static abstract class FloatProperty<T> extends Property<T, Float> {
  92 + public FloatProperty(String name) {
  93 + super(Float.class, name);
  94 + }
  95 +
  96 + /**
  97 + * A type-specific override of the {@link #set(Object, Float)} that is faster when dealing
  98 + * with fields of type <code>float</code>.
  99 + */
  100 + public abstract void setValue(T object, float value);
  101 +
  102 + @Override
  103 + final public void set(T object, Float value) {
  104 + setValue(object, value);
  105 + }
  106 + }
  107 +
  108 + /**
  109 + * An implementation of {@link Property} to be used specifically with fields of
  110 + * type
  111 + * <code>int</code>. This type-specific subclass enables performance benefit by allowing
  112 + * calls to a {@link #set(Object, Integer) set()} function that takes the primitive
  113 + * <code>int</code> type and avoids autoboxing and other overhead associated with the
  114 + * <code>Integer</code> class.
  115 + *
  116 + * @param <T> The class on which the Property is declared.
  117 + */
  118 + public static abstract class IntProperty<T> extends Property<T, Integer> {
  119 +
  120 + public IntProperty(String name) {
  121 + super(Integer.class, name);
  122 + }
  123 +
  124 + /**
  125 + * A type-specific override of the {@link #set(Object, Integer)} that is faster when dealing
  126 + * with fields of type <code>int</code>.
  127 + */
  128 + public abstract void setValue(T object, int value);
  129 +
  130 + @Override
  131 + final public void set(T object, Integer value) {
  132 + setValue(object, value.intValue());
  133 + }
  134 +
  135 + }
  136 +
  137 + /**
  138 + * https://halfthought.wordpress.com/2014/11/07/reveal-transition/
  139 + * <p/>
  140 + * Interrupting Activity transitions can yield an OperationNotSupportedException when the
  141 + * transition tries to pause the animator. Yikes! We can fix this by wrapping the Animator:
  142 + */
  143 + @RequiresApi(api = Build.VERSION_CODES.KITKAT)
  144 + public static class NoPauseAnimator extends Animator {
  145 + private final Animator mAnimator;
  146 + private final ArrayMap<AnimatorListener, AnimatorListener> mListeners =
  147 + new ArrayMap<AnimatorListener, AnimatorListener>();
  148 +
  149 + public NoPauseAnimator(Animator animator) {
  150 + mAnimator = animator;
  151 + }
  152 +
  153 + @RequiresApi(api = Build.VERSION_CODES.KITKAT)
  154 + @Override
  155 + public void addListener(AnimatorListener listener) {
  156 + AnimatorListener wrapper = new AnimatorListenerWrapper(this, listener);
  157 + if (!mListeners.containsKey(listener)) {
  158 + mListeners.put(listener, wrapper);
  159 + mAnimator.addListener(wrapper);
  160 + }
  161 + }
  162 +
  163 + @Override
  164 + public void cancel() {
  165 + mAnimator.cancel();
  166 + }
  167 +
  168 + @Override
  169 + public void end() {
  170 + mAnimator.end();
  171 + }
  172 +
  173 + @Override
  174 + public long getDuration() {
  175 + return mAnimator.getDuration();
  176 + }
  177 +
  178 + @Override
  179 + public TimeInterpolator getInterpolator() {
  180 + return mAnimator.getInterpolator();
  181 + }
  182 +
  183 + @Override
  184 + public void setInterpolator(TimeInterpolator timeInterpolator) {
  185 + mAnimator.setInterpolator(timeInterpolator);
  186 + }
  187 +
  188 + @Override
  189 + public ArrayList<AnimatorListener> getListeners() {
  190 + return new ArrayList<AnimatorListener>(mListeners.keySet());
  191 + }
  192 +
  193 + @Override
  194 + public long getStartDelay() {
  195 + return mAnimator.getStartDelay();
  196 + }
  197 +
  198 + @Override
  199 + public void setStartDelay(long delayMS) {
  200 + mAnimator.setStartDelay(delayMS);
  201 + }
  202 +
  203 + @Override
  204 + public boolean isPaused() {
  205 + return mAnimator.isPaused();
  206 + }
  207 +
  208 + @Override
  209 + public boolean isRunning() {
  210 + return mAnimator.isRunning();
  211 + }
  212 +
  213 + @Override
  214 + public boolean isStarted() {
  215 + return mAnimator.isStarted();
  216 + }
  217 +
  218 + /* We don't want to override pause or resume methods because we don't want them
  219 + * to affect mAnimator.
  220 + public void pause();
  221 +
  222 + public void resume();
  223 +
  224 + public void addPauseListener(AnimatorPauseListener listener);
  225 +
  226 + public void removePauseListener(AnimatorPauseListener listener);
  227 + */
  228 +
  229 + @Override
  230 + public void removeAllListeners() {
  231 + mListeners.clear();
  232 + mAnimator.removeAllListeners();
  233 + }
  234 +
  235 + @Override
  236 + public void removeListener(AnimatorListener listener) {
  237 + AnimatorListener wrapper = mListeners.get(listener);
  238 + if (wrapper != null) {
  239 + mListeners.remove(listener);
  240 + mAnimator.removeListener(wrapper);
  241 + }
  242 + }
  243 +
  244 + @Override
  245 + public Animator setDuration(long durationMS) {
  246 + mAnimator.setDuration(durationMS);
  247 + return this;
  248 + }
  249 +
  250 + @Override
  251 + public void setTarget(Object target) {
  252 + mAnimator.setTarget(target);
  253 + }
  254 +
  255 + @Override
  256 + public void setupEndValues() {
  257 + mAnimator.setupEndValues();
  258 + }
  259 +
  260 + @Override
  261 + public void setupStartValues() {
  262 + mAnimator.setupStartValues();
  263 + }
  264 +
  265 + @Override
  266 + public void start() {
  267 + mAnimator.start();
  268 + }
  269 + }
  270 +
  271 + static class AnimatorListenerWrapper implements Animator.AnimatorListener {
  272 + private final Animator mAnimator;
  273 + private final Animator.AnimatorListener mListener;
  274 +
  275 + public AnimatorListenerWrapper(Animator animator, Animator.AnimatorListener listener) {
  276 + mAnimator = animator;
  277 + mListener = listener;
  278 + }
  279 +
  280 + @Override
  281 + public void onAnimationStart(Animator animator) {
  282 + mListener.onAnimationStart(mAnimator);
  283 + }
  284 +
  285 + @Override
  286 + public void onAnimationEnd(Animator animator) {
  287 + mListener.onAnimationEnd(mAnimator);
  288 + }
  289 +
  290 + @Override
  291 + public void onAnimationCancel(Animator animator) {
  292 + mListener.onAnimationCancel(mAnimator);
  293 + }
  294 +
  295 + @Override
  296 + public void onAnimationRepeat(Animator animator) {
  297 + mListener.onAnimationRepeat(mAnimator);
  298 + }
  299 + }
  300 +
  301 + @RequiresApi(api = Build.VERSION_CODES.KITKAT)
  302 + public static class TransitionListenerAdapter implements Transition.TransitionListener {
  303 +
  304 + @Override
  305 + public void onTransitionStart(Transition transition) {
  306 +
  307 + }
  308 +
  309 + @Override
  310 + public void onTransitionEnd(Transition transition) {
  311 +
  312 + }
  313 +
  314 + @Override
  315 + public void onTransitionCancel(Transition transition) {
  316 +
  317 + }
  318 +
  319 + @Override
  320 + public void onTransitionPause(Transition transition) {
  321 +
  322 + }
  323 +
  324 + @Override
  325 + public void onTransitionResume(Transition transition) {
  326 +
  327 + }
  328 + }
  329 +
  330 +}
mvpsdk/src/main/java/com/share/mvpsdk/anim/ToolbarAnimManager.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/anim/ToolbarAnimManager.java
@@ -0,0 +1,93 @@ @@ -0,0 +1,93 @@
  1 +package com.share.mvpsdk.anim;
  2 +
  3 +import android.content.Context;
  4 +import android.support.annotation.NonNull;
  5 +import android.support.v7.widget.ActionMenuView;
  6 +import android.support.v7.widget.Toolbar;
  7 +import android.view.View;
  8 +import android.widget.ImageButton;
  9 +import android.widget.TextView;
  10 +
  11 +/**
  12 + * Created by Horrarndoo on 2017/9/11.
  13 + * <p>
  14 + * Toolbar动画Manager
  15 + */
  16 +
  17 +public class ToolbarAnimManager {
  18 + /**
  19 + * Toolbar 进场动画
  20 + * <p>
  21 + * Textview&ActionMenuView渐变动画
  22 + *
  23 + * @param context context
  24 + * @param toolbar toolbar
  25 + */
  26 + public static void animIn(Context context, @NonNull Toolbar toolbar) {
  27 + ImageButton ibIcon = null;
  28 + TextView tvTitle = null;
  29 + ActionMenuView amvTheme = null;
  30 + int childCount = toolbar.getChildCount();
  31 + for (int i = 0; i < childCount; i++) {
  32 + View child = toolbar.getChildAt(i);
  33 + if(child instanceof ImageButton) {
  34 + ibIcon = (ImageButton) child;
  35 + continue;
  36 + }
  37 +
  38 + if (child instanceof ActionMenuView) {
  39 + amvTheme = (ActionMenuView) child;
  40 + continue;
  41 + }
  42 +
  43 + if (child instanceof TextView)
  44 + tvTitle = (TextView) child;
  45 + }
  46 +
  47 + if(ibIcon != null)
  48 + animNavigationIcon(context, ibIcon);
  49 +
  50 + if(tvTitle != null)
  51 + animTitle(context, tvTitle);
  52 +
  53 + if(amvTheme != null)
  54 + animMenu(context, amvTheme);
  55 + }
  56 +
  57 + /**
  58 + * Toolbar Title动画
  59 + * <p>
  60 + * NavigationIcon渐变动画
  61 + *
  62 + * @param context context
  63 + * @param imageButton 执行动画的view
  64 + */
  65 + public static void animNavigationIcon(Context context, @NonNull ImageButton imageButton) {
  66 + AnimManager.animAlphaAndScaleX(context, imageButton, 500, 900);
  67 + }
  68 +
  69 + /**
  70 + * Toolbar Title动画
  71 + * <p>
  72 + * ActionMenuView渐变动画
  73 + *
  74 + * @param context context
  75 + * @param textView 执行动画的view
  76 + */
  77 + public static void animTitle(Context context, @NonNull TextView textView) {
  78 + AnimManager.animAlphaAndScaleX(context, textView, 500, 900);
  79 + }
  80 +
  81 + /**
  82 + * Toolbar ActionMenuView动画
  83 + * <p>
  84 + * ActionMenuView渐变动画
  85 + *
  86 + * @param context context
  87 + * @param avm 执行动画的view
  88 + */
  89 + public static void animMenu(Context context, @NonNull ActionMenuView avm) {
  90 + AnimManager.animAlphaAndScale(context, avm, 500, 200); // filter
  91 + AnimManager.animAlphaAndScale(context, avm, 700, 200); // overflow
  92 + }
  93 +}
mvpsdk/src/main/java/com/share/mvpsdk/base/BaseModel.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/base/BaseModel.java
@@ -0,0 +1,11 @@ @@ -0,0 +1,11 @@
  1 +package com.share.mvpsdk.base;
  2 +
  3 +/**
  4 + * Created by Horrarndoo on 2017/4/25.
  5 + * base model类
  6 + */
  7 +
  8 +public abstract class BaseModel {
  9 + public BaseModel() {
  10 + }
  11 +}
mvpsdk/src/main/java/com/share/mvpsdk/base/BasePresenter.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/base/BasePresenter.java
@@ -0,0 +1,53 @@ @@ -0,0 +1,53 @@
  1 +package com.share.mvpsdk.base;
  2 +
  3 +import android.support.annotation.NonNull;
  4 +
  5 +import com.share.mvpsdk.RxManager;
  6 +
  7 +
  8 +/**
  9 + * Created by Horrarndoo on 2017/4/25.
  10 + * <p>
  11 + * base presenter
  12 + */
  13 +
  14 +public abstract class BasePresenter<M, V> {
  15 + public M mIModel;
  16 + public V mIView;
  17 + protected RxManager mRxManager = new RxManager();
  18 +
  19 + /**
  20 + * 返回presenter想持有的Model引用
  21 + *
  22 + * @return presenter持有的Model引用
  23 + */
  24 + public abstract M getModel();
  25 +
  26 + /**
  27 + * 绑定IModel和IView的引用
  28 + *
  29 + * @param m model
  30 + * @param v view
  31 + */
  32 + public void attachMV(@NonNull M m, @NonNull V v) {
  33 + this.mIModel = m;
  34 + this.mIView = v;
  35 + this.onStart();
  36 + }
  37 +
  38 + /**
  39 + * 解绑IModel和IView
  40 + */
  41 + public void detachMV() {
  42 + mRxManager.unSubscribe();
  43 + mIView = null;
  44 + mIModel = null;
  45 + }
  46 +
  47 + /**
  48 + * IView和IModel绑定完成立即执行
  49 + * <p>
  50 + * 实现类实现绑定完成后的逻辑,例如数据初始化等,界面初始化, 更新等
  51 + */
  52 + public abstract void onStart();
  53 +}
mvpsdk/src/main/java/com/share/mvpsdk/base/IBaseActivity.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/base/IBaseActivity.java
@@ -0,0 +1,35 @@ @@ -0,0 +1,35 @@
  1 +package com.share.mvpsdk.base;
  2 +
  3 +import android.os.Bundle;
  4 +import android.support.annotation.NonNull;
  5 +
  6 +/**
  7 + * Created by Horrarndoo on 2017/9/6.
  8 + * <p>
  9 + * BaseActivity接口
  10 + */
  11 +
  12 +public interface IBaseActivity extends IBaseView {
  13 + /**
  14 + * 跳往新的Activity
  15 + *
  16 + * @param clz 要跳往的Activity
  17 + */
  18 + void startNewActivity(@NonNull Class<?> clz);
  19 +
  20 + /**
  21 + * 跳往新的Activity
  22 + *
  23 + * @param clz 要跳往的Activity
  24 + * @param bundle 携带的bundle数据
  25 + */
  26 + void startNewActivity(@NonNull Class<?> clz, Bundle bundle);
  27 +
  28 + /**
  29 + * 跳往新的Activity
  30 + * @param clz 要跳转的Activity
  31 + * @param bundle bundel数据
  32 + * @param requestCode requestCode
  33 + */
  34 + void startNewActivityForResult(@NonNull Class<?> clz, Bundle bundle, int requestCode);
  35 +}
mvpsdk/src/main/java/com/share/mvpsdk/base/IBaseFragment.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/base/IBaseFragment.java
@@ -0,0 +1,92 @@ @@ -0,0 +1,92 @@
  1 +package com.share.mvpsdk.base;
  2 +
  3 +import android.app.Activity;
  4 +import android.os.Bundle;
  5 +import android.support.annotation.NonNull;
  6 +
  7 +import me.yokeyword.fragmentation.SupportFragment;
  8 +
  9 +/**
  10 + * Created by Horrarndoo on 2017/9/6.
  11 + * <p>
  12 + * BaseFragment接口
  13 + */
  14 +
  15 +public interface IBaseFragment extends IBaseView {
  16 + /**
  17 + * 出栈到目标fragment
  18 + *
  19 + * @param targetFragmentClass 目标fragment
  20 + * @param includeTargetFragment 是否包含该fragment
  21 + * true 目标fragment也出栈
  22 + * <p>
  23 + * false 出栈到目标fragment,目标fragment不出栈
  24 + */
  25 + void popToFragment(Class<?> targetFragmentClass, boolean includeTargetFragment);
  26 +
  27 + /**
  28 + * 跳往新的Fragment
  29 + *
  30 + * @param supportFragment 要跳往的Fragment(继承自supportFragment)
  31 + */
  32 + void startNewFragment(@NonNull SupportFragment supportFragment);
  33 +
  34 + /**
  35 + * 跳往新的Fragment,并出栈当前fragment
  36 + *
  37 + * @param supportFragment 要跳往的Fragment(继承自supportFragment)
  38 + */
  39 + void startNewFragmentWithPop(@NonNull SupportFragment supportFragment);
  40 +
  41 + /**
  42 + * 跳往新的Fragment
  43 + *
  44 + * @param supportFragment 要跳往的Fragment(继承自supportFragment)
  45 + * @param requestCode requestCode
  46 + */
  47 + void startNewFragmentForResult(@NonNull SupportFragment supportFragment, int requestCode);
  48 +
  49 + /**
  50 + * 设置Fragment返回Result
  51 + *
  52 + * @param resultCode resultCode
  53 + * @param data result data
  54 + */
  55 + void setOnFragmentResult(int resultCode, Bundle data);
  56 +
  57 + /**
  58 + * 跳往新的Activity
  59 + *
  60 + * @param clz 要跳往的Activity
  61 + */
  62 + void startNewActivity(@NonNull Class<?> clz);
  63 +
  64 + /**
  65 + * 跳往新的Activity
  66 + *
  67 + * @param clz 要跳往的Activity
  68 + * @param bundle 携带的bundle数据
  69 + */
  70 + void startNewActivity(@NonNull Class<?> clz, Bundle bundle);
  71 +
  72 + /**
  73 + * 跳往新的Activity
  74 + *
  75 + * @param clz 要跳转的Activity
  76 + * @param bundle bundel数据
  77 + * @param requestCode requestCode
  78 + */
  79 + void startNewActivityForResult(@NonNull Class<?> clz, Bundle bundle, int requestCode);
  80 +
  81 + /**
  82 + * 返回当前fragment是否可见
  83 + * @return 当前fragment是否可见
  84 + */
  85 + boolean isVisiable();
  86 +
  87 + /**
  88 + * 返回当前fragment绑定的activity
  89 + * @return activity
  90 + */
  91 + Activity getBindActivity();
  92 +}
mvpsdk/src/main/java/com/share/mvpsdk/base/IBaseModel.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/base/IBaseModel.java
@@ -0,0 +1,9 @@ @@ -0,0 +1,9 @@
  1 +package com.share.mvpsdk.base;
  2 +
  3 +/**
  4 + * Created by Horrarndoo on 2017/4/25.
  5 + * base model接口
  6 + */
  7 +
  8 +public interface IBaseModel {
  9 +}
mvpsdk/src/main/java/com/share/mvpsdk/base/IBaseView.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/base/IBaseView.java
@@ -0,0 +1,47 @@ @@ -0,0 +1,47 @@
  1 +package com.share.mvpsdk.base;
  2 +
  3 +import android.support.annotation.NonNull;
  4 +
  5 +/**
  6 + * Created by Horrarndoo on 2017/5/2.
  7 + * fragment base view接口
  8 + */
  9 +
  10 +public interface IBaseView {
  11 + /**
  12 + * 初始化presenter
  13 + * <p>
  14 + * 此方法返回的presenter对象不可为空
  15 + */
  16 + @NonNull
  17 + BasePresenter initPresenter();
  18 +
  19 + /**
  20 + * 显示toast消息
  21 + *
  22 + * @param msg 要显示的toast消息字符串
  23 + */
  24 + void showToast(String msg);
  25 +
  26 + /**
  27 + * 显示等待dialog
  28 + *
  29 + * @param waitMsg 等待消息字符串
  30 + */
  31 + void showWaitDialog(String waitMsg);
  32 +
  33 + /**
  34 + * 隐藏等待dialog
  35 + */
  36 + void hideWaitDialog();
  37 +
  38 + /**
  39 + * 隐藏键盘
  40 + */
  41 + void hideKeybord();
  42 +
  43 + /**
  44 + * 回退
  45 + */
  46 + void back();
  47 +}
mvpsdk/src/main/java/com/share/mvpsdk/base/activity/BaseCompatActivity.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/base/activity/BaseCompatActivity.java
@@ -0,0 +1,249 @@ @@ -0,0 +1,249 @@
  1 +package com.share.mvpsdk.base.activity;
  2 +
  3 +import android.content.Context;
  4 +import android.content.Intent;
  5 +import android.content.pm.ActivityInfo;
  6 +import android.os.Bundle;
  7 +import android.support.v7.app.AppCompatDelegate;
  8 +import android.support.v7.widget.Toolbar;
  9 +import android.view.View;
  10 +import android.view.inputmethod.InputMethodManager;
  11 +
  12 +
  13 +import com.share.mvpsdk.AppManager;
  14 +import com.share.mvpsdk.R;
  15 +import com.share.mvpsdk.global.GlobalApplication;
  16 +import com.share.mvpsdk.utils.AppUtils;
  17 +import com.share.mvpsdk.utils.SpUtils;
  18 +import com.share.mvpsdk.utils.StatusBarUtils;
  19 +import com.share.mvpsdk.utils.ThemeUtils;
  20 +import com.share.mvpsdk.widgets.WaitPorgressDialog;
  21 +
  22 +import butterknife.ButterKnife;
  23 +import me.yokeyword.fragmentation.SupportActivity;
  24 +import me.yokeyword.fragmentation.anim.DefaultVerticalAnimator;
  25 +import me.yokeyword.fragmentation.anim.FragmentAnimator;
  26 +
  27 +/**
  28 + * Created by Horrarndoo on 2017/9/7.
  29 + * <p>
  30 + * BaseActivity
  31 + */
  32 +
  33 +public abstract class BaseCompatActivity extends SupportActivity {
  34 + protected GlobalApplication mApplication;
  35 + protected WaitPorgressDialog mWaitPorgressDialog;
  36 + protected Context mContext;//全局上下文对象
  37 + protected boolean isTransAnim;
  38 +
  39 + static {
  40 + //5.0以下兼容vector
  41 + AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
  42 + }
  43 +
  44 + @Override
  45 + protected void onCreate(Bundle savedInstanceState) {
  46 + super.onCreate(savedInstanceState);
  47 + init(savedInstanceState);
  48 + }
  49 +
  50 + @Override
  51 + protected void onDestroy() {
  52 + super.onDestroy();
  53 + AppManager.getAppManager().finishActivity(this);
  54 + }
  55 +
  56 + @Override
  57 + public FragmentAnimator onCreateFragmentAnimator() {
  58 + //fragment切换使用默认Vertical动画
  59 + return new DefaultVerticalAnimator();
  60 + }
  61 +
  62 + private void init(Bundle savedInstanceState) {
  63 + setTheme(ThemeUtils.themeArr[SpUtils.getThemeIndex(this)][
  64 + SpUtils.getNightModel(this) ? 1 : 0]);
  65 + setContentView(getLayoutId());
  66 + ButterKnife.bind(this);
  67 + StatusBarUtils.setTransparent(this);
  68 + setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
  69 + initData();
  70 + initView(savedInstanceState);
  71 + AppManager.getAppManager().addActivity(this);
  72 + }
  73 +
  74 + public void reload() {
  75 + Intent intent = getIntent();
  76 + overridePendingTransition(0, 0);
  77 + intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
  78 + finish();
  79 + overridePendingTransition(0, 0);
  80 + startActivity(intent);
  81 + }
  82 +
  83 + /**
  84 + * 初始化数据
  85 + * <p>
  86 + * 子类可以复写此方法初始化子类数据
  87 + */
  88 + protected void initData() {
  89 + mContext = AppUtils.getContext();
  90 + mApplication = GlobalApplication.getInstance();
  91 + mWaitPorgressDialog = new WaitPorgressDialog(this);
  92 + isTransAnim = true;
  93 + }
  94 +
  95 + /**
  96 + * 初始化view
  97 + * <p>
  98 + * 子类实现 控件绑定、视图初始化等内容
  99 + *
  100 + * @param savedInstanceState savedInstanceState
  101 + */
  102 + protected abstract void initView(Bundle savedInstanceState);
  103 +
  104 + /**
  105 + * 获取当前layouty的布局ID,用于设置当前布局
  106 + * <p>
  107 + * 交由子类实现
  108 + *
  109 + * @return layout Id
  110 + */
  111 + protected abstract int getLayoutId();
  112 +
  113 + /**
  114 + * 显示提示框
  115 + *
  116 + * @param msg 提示框内容字符串
  117 + */
  118 + protected void showProgressDialog(String msg) {
  119 + mWaitPorgressDialog.setMessage(msg);
  120 + mWaitPorgressDialog.show();
  121 + }
  122 +
  123 + /**
  124 + * 隐藏提示框
  125 + */
  126 + protected void hideProgressDialog() {
  127 + if (mWaitPorgressDialog != null) {
  128 + mWaitPorgressDialog.dismiss();
  129 + }
  130 + }
  131 +
  132 + /**
  133 + * [页面跳转]
  134 + *
  135 + * @param clz 要跳转的Activity
  136 + */
  137 + public void startActivity(Class<?> clz) {
  138 + startActivity(new Intent(this, clz));
  139 + if (isTransAnim)
  140 + overridePendingTransition(R.anim.activity_start_zoom_in, R.anim
  141 + .activity_start_zoom_out);
  142 + }
  143 +
  144 + /**
  145 + * [页面跳转]
  146 + *
  147 + * @param clz 要跳转的Activity
  148 + * @param intent intent
  149 + */
  150 + public void startActivity(Class<?> clz, Intent intent) {
  151 + intent.setClass(this, clz);
  152 + startActivity(intent);
  153 + if (isTransAnim)
  154 + overridePendingTransition(R.anim.activity_start_zoom_in, R.anim
  155 + .activity_start_zoom_out);
  156 + }
  157 +
  158 + /**
  159 + * [携带数据的页面跳转]
  160 + *
  161 + * @param clz 要跳转的Activity
  162 + * @param bundle bundel数据
  163 + */
  164 + public void startActivity(Class<?> clz, Bundle bundle) {
  165 + Intent intent = new Intent();
  166 + intent.setClass(this, clz);
  167 + if (bundle != null) {
  168 + intent.putExtras(bundle);
  169 + }
  170 + startActivity(intent);
  171 + if (isTransAnim)
  172 + overridePendingTransition(R.anim.activity_start_zoom_in, R.anim
  173 + .activity_start_zoom_out);
  174 + }
  175 +
  176 + /**
  177 + * [含有Bundle通过Class打开编辑界面]
  178 + *
  179 + * @param clz 要跳转的Activity
  180 + * @param bundle bundel数据
  181 + * @param requestCode requestCode
  182 + */
  183 + public void startActivityForResult(Class<?> clz, Bundle bundle,
  184 + int requestCode) {
  185 + Intent intent = new Intent();
  186 + intent.setClass(this, clz);
  187 + if (bundle != null) {
  188 + intent.putExtras(bundle);
  189 + }
  190 + startActivityForResult(intent, requestCode);
  191 + if (isTransAnim)
  192 + overridePendingTransition(R.anim.activity_start_zoom_in, R.anim
  193 + .activity_start_zoom_out);
  194 + }
  195 +
  196 + @Override
  197 + public void finish() {
  198 + super.finish();
  199 + if (isTransAnim)
  200 + overridePendingTransition(R.anim.activity_finish_trans_in, R.anim
  201 + .activity_finish_trans_out);
  202 + }
  203 +
  204 + /**
  205 + * 隐藏键盘
  206 + *
  207 + * @return 隐藏键盘结果
  208 + * <p>
  209 + * true:隐藏成功
  210 + * <p>
  211 + * false:隐藏失败
  212 + */
  213 + protected boolean hiddenKeyboard() {
  214 + //点击空白位置 隐藏软键盘
  215 + InputMethodManager mInputMethodManager = (InputMethodManager) getSystemService
  216 + (INPUT_METHOD_SERVICE);
  217 + return mInputMethodManager.hideSoftInputFromWindow(this
  218 + .getCurrentFocus().getWindowToken(), 0);
  219 + }
  220 +
  221 + protected void initTitleBar(Toolbar toolbar, String title) {
  222 + toolbar.setTitle(title);
  223 + setSupportActionBar(toolbar);
  224 + getSupportActionBar().setDisplayHomeAsUpEnabled(true);
  225 + getSupportActionBar().setDisplayShowHomeEnabled(true);
  226 + toolbar.setNavigationIcon(R.mipmap.ic_arrow_back_white);
  227 + toolbar.setNavigationOnClickListener(new View.OnClickListener() {
  228 + @Override
  229 + public void onClick(View view) {
  230 + onBackPressedSupport();
  231 + }
  232 + });
  233 + }
  234 +
  235 + /**
  236 + * 是否使用overridePendingTransition过度动画
  237 + * @return 是否使用overridePendingTransition过度动画,默认使用
  238 + */
  239 + protected boolean isTransAnim() {
  240 + return isTransAnim;
  241 + }
  242 +
  243 + /**
  244 + * 设置是否使用overridePendingTransition过度动画
  245 + */
  246 + protected void setIsTransAnim(boolean b){
  247 + isTransAnim = b;
  248 + }
  249 +}
mvpsdk/src/main/java/com/share/mvpsdk/base/activity/BaseMVPCompatActivity.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/base/activity/BaseMVPCompatActivity.java
@@ -0,0 +1,94 @@ @@ -0,0 +1,94 @@
  1 +package com.share.mvpsdk.base.activity;
  2 +
  3 +import android.os.Bundle;
  4 +import android.support.annotation.NonNull;
  5 +
  6 +import com.share.mvpsdk.base.BasePresenter;
  7 +import com.share.mvpsdk.base.IBaseActivity;
  8 +import com.share.mvpsdk.base.IBaseModel;
  9 +import com.share.mvpsdk.utils.ToastUtils;
  10 +
  11 +
  12 +/**
  13 + * Created by Horrarndoo on 2017/4/6.
  14 + * <p>
  15 + * Mvp Activity基类
  16 + */
  17 +public abstract class BaseMVPCompatActivity<P extends BasePresenter, M extends IBaseModel> extends
  18 + BaseCompatActivity implements IBaseActivity {
  19 + /**
  20 + * presenter 具体的presenter由子类确定
  21 + */
  22 + protected P mPresenter;
  23 +
  24 + /**
  25 + * model 具体的model由子类确定
  26 + */
  27 + private M mIMode;
  28 +
  29 + /**
  30 + * 初始化数据
  31 + * <p>
  32 + * 子类可以复写此方法初始化子类数据
  33 + */
  34 + protected void initData() {
  35 + super.initData();
  36 + mPresenter = (P) initPresenter();
  37 + if (mPresenter != null) {
  38 + mIMode = (M) mPresenter.getModel();
  39 + if (mIMode != null) {
  40 + mPresenter.attachMV(mIMode, this);
  41 + }
  42 + //Logger.d("attach M V success.");
  43 + }
  44 + }
  45 +
  46 + @Override
  47 + protected void onDestroy() {
  48 + super.onDestroy();
  49 + if (mPresenter != null) {
  50 + mPresenter.detachMV();
  51 + //Logger.d("detach M V success.");
  52 + }
  53 + }
  54 +
  55 + @Override
  56 + public void showWaitDialog(String msg) {
  57 + showProgressDialog(msg);
  58 + }
  59 +
  60 + @Override
  61 + public void hideWaitDialog() {
  62 + hideProgressDialog();
  63 + }
  64 +
  65 + @Override
  66 + public void showToast(String msg) {
  67 + ToastUtils.showToast(msg);
  68 + }
  69 +
  70 + @Override
  71 + public void startNewActivity(@NonNull Class<?> clz) {
  72 + startActivity(clz);
  73 + }
  74 +
  75 + @Override
  76 + public void startNewActivity(@NonNull Class<?> clz, Bundle bundle) {
  77 + startActivity(clz, bundle);
  78 + }
  79 +
  80 + @Override
  81 + public void startNewActivityForResult(@NonNull Class<?> clz, Bundle bundle, int requestCode) {
  82 + startActivityForResult(clz, bundle, requestCode);
  83 + }
  84 +
  85 + @Override
  86 + public void hideKeybord() {
  87 + hiddenKeyboard();
  88 + }
  89 +
  90 + @Override
  91 + public void back() {
  92 + super.onBackPressedSupport();
  93 + }
  94 +}
mvpsdk/src/main/java/com/share/mvpsdk/base/adapter/BaseRecyclerViewAdapter.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/base/adapter/BaseRecyclerViewAdapter.java
@@ -0,0 +1,79 @@ @@ -0,0 +1,79 @@
  1 +package com.share.mvpsdk.base.adapter;
  2 +
  3 +import android.support.v7.widget.RecyclerView;
  4 +import android.view.ViewGroup;
  5 +
  6 +
  7 +import java.util.ArrayList;
  8 +import java.util.List;
  9 +
  10 +/**
  11 + * Created by ToaHanDong on 2017/3/23.
  12 + */
  13 +
  14 +public abstract class BaseRecyclerViewAdapter<T> extends RecyclerView.Adapter<BaseRecyclerViewHolder> {
  15 +
  16 + private List<T> data = new ArrayList<>();
  17 + public OnItemClickListener onItemClickListener;
  18 + public OnItemLongClickListener onItemLongClickListener;
  19 +
  20 + @Override
  21 + public BaseRecyclerViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
  22 + return null;
  23 + }
  24 +
  25 + @Override
  26 + public void onBindViewHolder(BaseRecyclerViewHolder holder, int position) {
  27 + holder.onBindViewHolder(data.get(getPosition(position)), getPosition(position));
  28 + }
  29 +
  30 +
  31 + @Override
  32 + public int getItemCount() {
  33 + return data.size();
  34 + }
  35 +
  36 + public void addAll(List<T> data) {
  37 + removeAll();
  38 + if (data!=null)
  39 + this.data.addAll(data);
  40 + notifyDataSetChanged();
  41 + }
  42 +
  43 + public void removeAll() {
  44 + data.clear();
  45 + }
  46 +
  47 + public void remove(int position) {
  48 + data.remove(position);
  49 + }
  50 +
  51 + public void notift() {
  52 + notifyDataSetChanged();
  53 + }
  54 +
  55 + public void remove(T object) {
  56 + data.remove(object);
  57 + }
  58 +
  59 + public List<T> getData() {
  60 + return data;
  61 + }
  62 +
  63 + public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
  64 + this.onItemClickListener = onItemClickListener;
  65 + }
  66 +
  67 + public void setOnItemLongClickListener(OnItemLongClickListener onItemLongClickListener) {
  68 + this.onItemLongClickListener = onItemLongClickListener;
  69 + }
  70 +
  71 + private int getPosition(int position) {
  72 + return position;
  73 +// if (data.size() <= 9) {
  74 +// return position;
  75 +// }
  76 +// return position % (data.size());
  77 + }
  78 +
  79 +}
mvpsdk/src/main/java/com/share/mvpsdk/base/adapter/BaseRecyclerViewHolder.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/base/adapter/BaseRecyclerViewHolder.java
@@ -0,0 +1,22 @@ @@ -0,0 +1,22 @@
  1 +package com.share.mvpsdk.base.adapter;
  2 +
  3 +import android.support.v7.widget.RecyclerView;
  4 +import android.view.View;
  5 +
  6 +/**
  7 + * Created by ToaHanDong on 2017/3/23.
  8 + */
  9 +
  10 +public abstract class BaseRecyclerViewHolder<T> extends RecyclerView.ViewHolder {
  11 +
  12 + public BaseRecyclerViewHolder(View itemView) {
  13 + super(itemView);
  14 + }
  15 +
  16 + public abstract void onBindViewHolder(T object, final int position);
  17 +
  18 + void OnBaseBindViewHolder(T Object,int position){
  19 + onBindViewHolder(Object,position);
  20 + }
  21 +
  22 +}
mvpsdk/src/main/java/com/share/mvpsdk/base/adapter/OnItemClickListener.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/base/adapter/OnItemClickListener.java
@@ -0,0 +1,10 @@ @@ -0,0 +1,10 @@
  1 +package com.share.mvpsdk.base.adapter;
  2 +
  3 +/**
  4 + * Created by ToaHanDong on 2017/3/23.
  5 + */
  6 +
  7 +public interface OnItemClickListener<T> {
  8 +
  9 + void onItemClickListener(T object, int position);
  10 +}
mvpsdk/src/main/java/com/share/mvpsdk/base/adapter/OnItemLongClickListener.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/base/adapter/OnItemLongClickListener.java
@@ -0,0 +1,10 @@ @@ -0,0 +1,10 @@
  1 +package com.share.mvpsdk.base.adapter;
  2 +
  3 +/**
  4 + * Created by ToaHanDong on 2017/3/23.
  5 + */
  6 +
  7 +public interface OnItemLongClickListener<T> {
  8 +
  9 + void onItemLongClickListener(T object, int position);
  10 +}
mvpsdk/src/main/java/com/share/mvpsdk/base/entity/BaseEntity.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/base/entity/BaseEntity.java
@@ -0,0 +1,47 @@ @@ -0,0 +1,47 @@
  1 +package com.share.mvpsdk.base.entity;
  2 +
  3 +import java.io.Serializable;
  4 +
  5 +/**
  6 + * Created by ToaHanDong on 2017/4/27.
  7 + */
  8 +
  9 +public class BaseEntity<T> implements Serializable {
  10 +
  11 + private int status;
  12 + private String message;
  13 + private T data;
  14 +
  15 + public int getStatus() {
  16 + return status;
  17 + }
  18 +
  19 + public void setStatus(int status) {
  20 + this.status = status;
  21 + }
  22 +
  23 + public String getMessage() {
  24 + return message;
  25 + }
  26 +
  27 + public void setMessage(String message) {
  28 + this.message = message;
  29 + }
  30 +
  31 + public T getData() {
  32 + return data;
  33 + }
  34 +
  35 + public void setData(T data) {
  36 + this.data = data;
  37 + }
  38 +
  39 + @Override
  40 + public String toString() {
  41 + return "BaseEntity{" +
  42 + "status=" + status +
  43 + ", message='" + message + '\'' +
  44 + ", data=" + data +
  45 + '}';
  46 + }
  47 +}
mvpsdk/src/main/java/com/share/mvpsdk/base/entity/BaseListEntity.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/base/entity/BaseListEntity.java
@@ -0,0 +1,48 @@ @@ -0,0 +1,48 @@
  1 +package com.share.mvpsdk.base.entity;
  2 +
  3 +import java.io.Serializable;
  4 +import java.util.List;
  5 +
  6 +/**
  7 + * Created by ToaHanDong on 2017/6/6.
  8 + */
  9 +
  10 +public class BaseListEntity<T> implements Serializable {
  11 +
  12 + private int status;
  13 + private String message;
  14 + private List<T> data;
  15 +
  16 + public int getStatus() {
  17 + return status;
  18 + }
  19 +
  20 + public void setStatus(int status) {
  21 + this.status = status;
  22 + }
  23 +
  24 + public String getMessage() {
  25 + return message;
  26 + }
  27 +
  28 + public void setMessage(String message) {
  29 + this.message = message;
  30 + }
  31 +
  32 + public List<T> getData() {
  33 + return data;
  34 + }
  35 +
  36 + public void setData(List<T> data) {
  37 + this.data = data;
  38 + }
  39 +
  40 + @Override
  41 + public String toString() {
  42 + return "BaseListEntity{" +
  43 + "status=" + status +
  44 + ", message='" + message + '\'' +
  45 + ", data=" + data +
  46 + '}';
  47 + }
  48 +}
mvpsdk/src/main/java/com/share/mvpsdk/base/fragment/BaseCompatFragment.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/base/fragment/BaseCompatFragment.java
@@ -0,0 +1,153 @@ @@ -0,0 +1,153 @@
  1 +package com.share.mvpsdk.base.fragment;
  2 +
  3 +import android.app.Activity;
  4 +import android.content.Context;
  5 +import android.content.pm.ActivityInfo;
  6 +import android.os.Bundle;
  7 +import android.support.annotation.LayoutRes;
  8 +import android.support.annotation.Nullable;
  9 +import android.util.Log;
  10 +import android.view.LayoutInflater;
  11 +import android.view.View;
  12 +import android.view.ViewGroup;
  13 +
  14 +
  15 +import com.share.mvpsdk.global.GlobalApplication;
  16 +import com.share.mvpsdk.utils.AppUtils;
  17 +import com.share.mvpsdk.widgets.WaitPorgressDialog;
  18 +
  19 +import butterknife.ButterKnife;
  20 +import butterknife.Unbinder;
  21 +import me.yokeyword.fragmentation.SupportFragment;
  22 +import timber.log.Timber;
  23 +
  24 +/**
  25 + * Created by Horrarndoo on 2017/9/26.
  26 + * <p>
  27 + */
  28 +
  29 +public abstract class BaseCompatFragment extends SupportFragment {
  30 +
  31 + protected String TAG;
  32 + protected Context mContext;
  33 + protected Activity mActivity;
  34 + protected GlobalApplication mApplication;
  35 + protected WaitPorgressDialog mWaitPorgressDialog;
  36 +// private Unbinder binder;
  37 +
  38 + @Override
  39 + public void onAttach(Context context) {
  40 + mActivity = (Activity) context;
  41 + mContext = context;
  42 + super.onAttach(context);
  43 + }
  44 +
  45 + @Override
  46 + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable
  47 + Bundle savedInstanceState) {
  48 + if (getLayoutView() != null) {
  49 + return getLayoutView();
  50 + } else {
  51 + // return inflater.inflate(getLayoutId(), null);
  52 + return inflater.inflate(getLayoutId(), container, false);
  53 + }
  54 + }
  55 +
  56 + @Override
  57 + public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
  58 + ButterKnife.bind(this, view);
  59 + super.onViewCreated(view, savedInstanceState);
  60 + mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
  61 + TAG = getClass().getSimpleName();
  62 + getBundle(getArguments());
  63 + initData();
  64 + initUI(view, savedInstanceState);
  65 + }
  66 +
  67 +
  68 + @Override
  69 + public void onDestroyView() {
  70 + super.onDestroyView();
  71 +// if (binder != null)
  72 +// binder.unbind();
  73 + }
  74 +
  75 + @Override
  76 + public void onDetach() {
  77 + super.onDetach();
  78 + }
  79 +
  80 + @Override
  81 + public void onDestroy() {
  82 + super.onDestroy();
  83 + }
  84 +
  85 + @LayoutRes
  86 + public abstract int getLayoutId();
  87 +
  88 + public View getLayoutView() {
  89 + return null;
  90 + }
  91 +
  92 + /**
  93 + * 得到Activity传进来的值
  94 + */
  95 + public void getBundle(Bundle bundle) {
  96 + }
  97 +
  98 + /**
  99 + * 初始化UI
  100 + */
  101 + public abstract void initUI(View view, @Nullable Bundle savedInstanceState);
  102 +
  103 + /**
  104 + * 在监听器之前把数据准备好
  105 + */
  106 + public void initData() {
  107 + mWaitPorgressDialog = new WaitPorgressDialog(mActivity);
  108 + mContext = AppUtils.getContext();
  109 + mApplication = GlobalApplication.getInstance();
  110 + }
  111 +
  112 + /**
  113 + * 处理回退事件
  114 + *
  115 + * @return true 事件已消费
  116 + * <p>
  117 + * false 事件向上传递
  118 + */
  119 + @Override
  120 + public boolean onBackPressedSupport() {
  121 + if (getFragmentManager().getBackStackEntryCount() > 1) {
  122 + //如果当前存在fragment>1,当前fragment出栈
  123 + pop();
  124 + } else {
  125 + //已经退栈到root fragment,交由Activity处理回退事件
  126 + return false;
  127 + }
  128 + return true;
  129 + }
  130 +
  131 + /**
  132 + * 显示提示框
  133 + *
  134 + * @param msg 提示框内容字符串
  135 + */
  136 + protected void showProgressDialog(String msg) {
  137 + if (mWaitPorgressDialog.isShowing()) {
  138 + mWaitPorgressDialog.dismiss();
  139 + }
  140 +
  141 + mWaitPorgressDialog.setMessage(msg);
  142 + mWaitPorgressDialog.show();
  143 + }
  144 +
  145 + /**
  146 + * 隐藏提示框
  147 + */
  148 + protected void hideProgressDialog() {
  149 + if (mWaitPorgressDialog != null) {
  150 + mWaitPorgressDialog.dismiss();
  151 + }
  152 + }
  153 +}
mvpsdk/src/main/java/com/share/mvpsdk/base/fragment/BaseMVPCompatFragment.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/base/fragment/BaseMVPCompatFragment.java
@@ -0,0 +1,128 @@ @@ -0,0 +1,128 @@
  1 +package com.share.mvpsdk.base.fragment;
  2 +
  3 +import android.app.Activity;
  4 +import android.os.Bundle;
  5 +import android.support.annotation.NonNull;
  6 +import android.widget.Toast;
  7 +
  8 +
  9 +import com.share.mvpsdk.base.BasePresenter;
  10 +import com.share.mvpsdk.base.IBaseFragment;
  11 +import com.share.mvpsdk.base.IBaseModel;
  12 +import com.share.mvpsdk.base.activity.BaseCompatActivity;
  13 +import com.share.mvpsdk.utils.ToastUtils;
  14 +
  15 +import me.yokeyword.fragmentation.SupportFragment;
  16 +
  17 +/**
  18 + * Created by Horrarndoo on 2017/9/6.
  19 + * <p>
  20 + * Mvp Fragment基类
  21 + * <p>
  22 + * 实现IBaseView方法、绑定butterknife
  23 + */
  24 +
  25 +public abstract class BaseMVPCompatFragment<P extends BasePresenter, M extends IBaseModel> extends
  26 + BaseCompatFragment implements IBaseFragment {
  27 + public P mPresenter;
  28 + public M mIMode;
  29 +
  30 + /**
  31 + * 在监听器之前把数据准备好
  32 + */
  33 + public void initData() {
  34 + super.initData();
  35 +
  36 + mPresenter = (P) initPresenter();
  37 + if (mPresenter != null) {
  38 + mIMode = (M) mPresenter.getModel();
  39 + if (mIMode != null) {
  40 + mPresenter.attachMV(mIMode, this);
  41 + }
  42 + }
  43 + }
  44 +
  45 + @Override
  46 + public void onDestroy() {
  47 + super.onDestroy();
  48 + if (mPresenter != null) {
  49 + mPresenter.detachMV();
  50 + }
  51 + }
  52 +
  53 + @Override
  54 + public void showWaitDialog(String msg) {
  55 + showProgressDialog(msg);
  56 + }
  57 +
  58 + @Override
  59 + public void hideWaitDialog() {
  60 + hideProgressDialog();
  61 + }
  62 +
  63 + @Override
  64 + public void showToast(String msg) {
  65 + ToastUtils.showToast(mContext, msg, Toast.LENGTH_SHORT);
  66 + }
  67 +
  68 + @Override
  69 + public void back() {
  70 + this.onBackPressedSupport();
  71 + }
  72 +
  73 + @Override
  74 + public void startNewFragment(@NonNull SupportFragment supportFragment) {
  75 + start(supportFragment);
  76 + }
  77 +
  78 + @Override
  79 + public void startNewFragmentWithPop(@NonNull SupportFragment supportFragment) {
  80 + startWithPop(supportFragment);
  81 + }
  82 +
  83 + @Override
  84 + public void startNewFragmentForResult(@NonNull SupportFragment supportFragment, int
  85 + requestCode) {
  86 + startForResult(supportFragment, requestCode);
  87 + }
  88 +
  89 + @Override
  90 + public void popToFragment(Class<?> targetFragmentClass, boolean includeTargetFragment) {
  91 + popTo(targetFragmentClass, includeTargetFragment);
  92 + }
  93 +
  94 + @Override
  95 + public void hideKeybord() {
  96 + hideSoftInput();
  97 + }
  98 +
  99 + @Override
  100 + public void setOnFragmentResult(int ResultCode, Bundle data) {
  101 + setFragmentResult(ResultCode, data);
  102 + }
  103 +
  104 + @Override
  105 + public void startNewActivity(@NonNull Class<?> clz) {
  106 + ((BaseCompatActivity) mActivity).startActivity(clz);
  107 + }
  108 +
  109 + @Override
  110 + public void startNewActivity(@NonNull Class<?> clz, Bundle bundle) {
  111 + ((BaseCompatActivity) mActivity).startActivity(clz, bundle);
  112 + }
  113 +
  114 + @Override
  115 + public void startNewActivityForResult(@NonNull Class<?> clz, Bundle bundle, int requestCode) {
  116 + ((BaseCompatActivity) mActivity).startActivityForResult(clz, bundle, requestCode);
  117 + }
  118 +
  119 + @Override
  120 + public boolean isVisiable() {
  121 + return isSupportVisible();
  122 + }
  123 +
  124 + @Override
  125 + public Activity getBindActivity() {
  126 + return mActivity;
  127 + }
  128 +}
0 \ No newline at end of file 129 \ No newline at end of file
mvpsdk/src/main/java/com/share/mvpsdk/base/fragment/BaseRecycleFragment.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/base/fragment/BaseRecycleFragment.java
@@ -0,0 +1,68 @@ @@ -0,0 +1,68 @@
  1 +package com.share.mvpsdk.base.fragment;
  2 +
  3 +import android.os.Bundle;
  4 +import android.support.annotation.Nullable;
  5 +import android.view.LayoutInflater;
  6 +import android.view.View;
  7 +import android.view.ViewGroup;
  8 +
  9 +import com.share.mvpsdk.R;
  10 +import com.share.mvpsdk.base.BasePresenter;
  11 +import com.share.mvpsdk.base.IBaseModel;
  12 +
  13 +
  14 +/**
  15 + * Created by Horrarndoo on 2017/10/17.
  16 + * <p>
  17 + * 带RecycleView加载状态view的fragment,主要用于显示加载中、空界面、加载失败等状态界面显示
  18 + */
  19 +
  20 +public abstract class BaseRecycleFragment<P extends BasePresenter, M extends IBaseModel> extends
  21 + BaseMVPCompatFragment<P, M> {
  22 + /**
  23 + * 网络异常View
  24 + */
  25 + protected View errorView;
  26 + /**
  27 + * loadingView
  28 + */
  29 + protected View loadingView;
  30 + /**
  31 + * 没有内容view
  32 + */
  33 + protected View emptyView;
  34 +
  35 + @Override
  36 + public void onLazyInitView(@Nullable Bundle savedInstanceState) {
  37 + super.onLazyInitView(savedInstanceState);
  38 + showLoading();
  39 + }
  40 +
  41 + @Override
  42 + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable
  43 + Bundle savedInstanceState) {
  44 + errorView = inflater.inflate(R.layout.view_network_error, container, false);
  45 + loadingView = inflater.inflate(R.layout.view_loading, container, false);
  46 + emptyView = inflater.inflate(R.layout.view_empty, container, false);
  47 + errorView.setOnClickListener(new View.OnClickListener() {
  48 + @Override
  49 + public void onClick(View v) {
  50 + showLoading();
  51 + onErrorViewClick(v);
  52 + }
  53 + });
  54 + return super.onCreateView(inflater, container, savedInstanceState);
  55 + }
  56 +
  57 + /**
  58 + * 网络异常view被点击时触发,由子类实现
  59 + *
  60 + * @param view view
  61 + */
  62 + protected abstract void onErrorViewClick(View view);
  63 +
  64 + /**
  65 + * 显示加载中view,由子类实现
  66 + */
  67 + protected abstract void showLoading();
  68 +}
mvpsdk/src/main/java/com/share/mvpsdk/config/DBConfig.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/config/DBConfig.java
@@ -0,0 +1,16 @@ @@ -0,0 +1,16 @@
  1 +package com.share.mvpsdk.config;
  2 +
  3 +/**
  4 + * Created by Horrarndoo on 2017/9/13.
  5 + * <p>
  6 + * 数据库全局常量
  7 + */
  8 +
  9 +public class DBConfig {
  10 + public static final String DB_NAME = "db_name_yizhi";
  11 + public static final String TABLE_ZHIHU = "table_zhihu";
  12 + public static final String TABLE_WANGYI = "table_top_news";
  13 + public static final String TABLE_WEIXIN = "table_weixin";
  14 + public static final String TABLE_GANKIO_DAY = "table_gank_io_day";
  15 + public static final String TABLE_GANKIO_CUSTOM = "table_gank_io_custom";
  16 +}
mvpsdk/src/main/java/com/share/mvpsdk/config/ItemState.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/config/ItemState.java
@@ -0,0 +1,19 @@ @@ -0,0 +1,19 @@
  1 +package com.share.mvpsdk.config;
  2 +
  3 +/**
  4 + * Created by Horrarndoo on 2017/9/13.
  5 + * <p>
  6 + * item状态全局常量
  7 + */
  8 +
  9 +public class ItemState {
  10 + /**
  11 + * 已读状态
  12 + */
  13 + public static final int STATE_IS_READ = 1;
  14 +
  15 + /**
  16 + * 非已读状态
  17 + */
  18 + public static final int STATE_IS_NO_READ = 0;
  19 +}
mvpsdk/src/main/java/com/share/mvpsdk/global/GlobalApplication.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/global/GlobalApplication.java
@@ -0,0 +1,67 @@ @@ -0,0 +1,67 @@
  1 +package com.share.mvpsdk.global;
  2 +
  3 +import android.app.Application;
  4 +import android.content.Context;
  5 +import android.os.Handler;
  6 +
  7 +import com.orhanobut.logger.LogLevel;
  8 +import com.orhanobut.logger.Logger;
  9 +
  10 +import timber.log.Timber;
  11 +
  12 +
  13 +/**
  14 + * Created by Horrarndoo on 2017/9/1.
  15 + * <p>
  16 + * 全局Application
  17 + */
  18 +
  19 +public class GlobalApplication extends Application {
  20 + private static final String LOG_TAG = "YZ_LOGGER";
  21 + protected static Context context;
  22 + protected static Handler handler;
  23 + protected static int mainThreadId;
  24 + private static GlobalApplication mApp;
  25 +
  26 + public static synchronized GlobalApplication getInstance() {
  27 + return mApp;
  28 + }
  29 +
  30 + @Override
  31 + public void onCreate() {
  32 + super.onCreate();
  33 + context = getApplicationContext();
  34 + handler = new Handler();
  35 + mainThreadId = android.os.Process.myTid();
  36 + mApp=this;
  37 + //LogLevel.FULL : LogLevel.NONE
  38 + Logger.init(LOG_TAG).logLevel(LogLevel.FULL);
  39 + }
  40 +
  41 + /**
  42 + * 获取上下文对象
  43 + *
  44 + * @return context
  45 + */
  46 + public static Context getContext() {
  47 + return context;
  48 + }
  49 +
  50 + /**
  51 + * 获取全局handler
  52 + *
  53 + * @return 全局handler
  54 + */
  55 + public static Handler getHandler() {
  56 + return handler;
  57 + }
  58 +
  59 + /**
  60 + * 获取主线程id
  61 + *
  62 + * @return 主线程id
  63 + */
  64 + public static int getMainThreadId() {
  65 + return mainThreadId;
  66 + }
  67 +}
mvpsdk/src/main/java/com/share/mvpsdk/helper/BottomNavigationViewHelper.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/helper/BottomNavigationViewHelper.java
@@ -0,0 +1,37 @@ @@ -0,0 +1,37 @@
  1 +package com.share.mvpsdk.helper;
  2 +
  3 +import android.support.design.internal.BottomNavigationItemView;
  4 +import android.support.design.internal.BottomNavigationMenuView;
  5 +import android.support.design.widget.BottomNavigationView;
  6 +import android.util.Log;
  7 +
  8 +import java.lang.reflect.Field;
  9 +
  10 +/**
  11 + * Created by Horrarndoo on 2017/9/22.
  12 + * <p>
  13 + * BottomNavigationView禁止3个item以上动画切换效果
  14 + */
  15 +public class BottomNavigationViewHelper {
  16 + public static void disableShiftMode(BottomNavigationView view) {
  17 + BottomNavigationMenuView menuView = (BottomNavigationMenuView) view.getChildAt(0);
  18 + try {
  19 + Field shiftingMode = menuView.getClass().getDeclaredField("mShiftingMode");
  20 + shiftingMode.setAccessible(true);
  21 + shiftingMode.setBoolean(menuView, false);
  22 + shiftingMode.setAccessible(false);
  23 + for (int i = 0; i < menuView.getChildCount(); i++) {
  24 + BottomNavigationItemView item = (BottomNavigationItemView) menuView.getChildAt(i);
  25 + //noinspection RestrictedApi
  26 + item.setShiftingMode(false);
  27 + // set once again checked value, so view will be updated
  28 + //noinspection RestrictedApi
  29 + item.setChecked(item.getItemData().isChecked());
  30 + }
  31 + } catch (NoSuchFieldException e) {
  32 + Log.e("BNVHelper", "Unable to get shift mode field", e);
  33 + } catch (IllegalAccessException e) {
  34 + Log.e("BNVHelper", "Unable to change value of shift mode", e);
  35 + }
  36 + }
  37 +}
mvpsdk/src/main/java/com/share/mvpsdk/helper/RetrofitCreateHelper.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/helper/RetrofitCreateHelper.java
@@ -0,0 +1,56 @@ @@ -0,0 +1,56 @@
  1 +package com.share.mvpsdk.helper;
  2 +
  3 +
  4 +
  5 +import com.share.mvpsdk.helper.okhttp.CacheInterceptor;
  6 +import com.share.mvpsdk.helper.okhttp.HttpCache;
  7 +import com.share.mvpsdk.helper.okhttp.TrustManager;
  8 +
  9 +import java.util.concurrent.TimeUnit;
  10 +
  11 +import okhttp3.OkHttpClient;
  12 +import okhttp3.logging.HttpLoggingInterceptor;
  13 +import retrofit2.Retrofit;
  14 +import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
  15 +import retrofit2.converter.gson.GsonConverterFactory;
  16 +
  17 +/**
  18 + * Created by Horrarndoo on 2017/9/7.
  19 + * <p>
  20 + */
  21 +
  22 +public class RetrofitCreateHelper {
  23 + private static final int TIMEOUT_READ = 20;
  24 + private static final int TIMEOUT_CONNECTION = 10;
  25 + private static final HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor()
  26 + .setLevel(HttpLoggingInterceptor.Level.BODY);
  27 + private static CacheInterceptor cacheInterceptor = new CacheInterceptor();
  28 + private static OkHttpClient okHttpClient = new OkHttpClient.Builder()
  29 + //SSL证书
  30 + .sslSocketFactory(TrustManager.getUnsafeOkHttpClient())
  31 + .hostnameVerifier(org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER)
  32 + //打印日志
  33 + .addInterceptor(interceptor)
  34 + //设置Cache拦截器
  35 + .addNetworkInterceptor(cacheInterceptor)
  36 + .addInterceptor(cacheInterceptor)
  37 + .cache(HttpCache.getCache())
  38 + //time out
  39 + .connectTimeout(TIMEOUT_CONNECTION, TimeUnit.SECONDS)
  40 + .readTimeout(TIMEOUT_READ, TimeUnit.SECONDS)
  41 + .writeTimeout(TIMEOUT_READ, TimeUnit.SECONDS)
  42 + //失败重连
  43 + .retryOnConnectionFailure(true)
  44 + .build();
  45 +
  46 + public static <T> T createApi(Class<T> clazz, String url) {
  47 + Retrofit retrofit = new Retrofit.Builder()
  48 + .baseUrl(url)
  49 + .client(okHttpClient)
  50 + .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
  51 + .addConverterFactory(GsonConverterFactory.create())
  52 + .build();
  53 + return retrofit.create(clazz);
  54 + }
  55 +}
  56 +
mvpsdk/src/main/java/com/share/mvpsdk/helper/RxHelper.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/helper/RxHelper.java
@@ -0,0 +1,76 @@ @@ -0,0 +1,76 @@
  1 +package com.share.mvpsdk.helper;
  2 +
  3 +
  4 +import io.reactivex.BackpressureStrategy;
  5 +import io.reactivex.Flowable;
  6 +import io.reactivex.FlowableEmitter;
  7 +import io.reactivex.FlowableOnSubscribe;
  8 +import io.reactivex.Observable;
  9 +import io.reactivex.ObservableEmitter;
  10 +import io.reactivex.ObservableOnSubscribe;
  11 +import io.reactivex.ObservableSource;
  12 +import io.reactivex.ObservableTransformer;
  13 +import io.reactivex.android.schedulers.AndroidSchedulers;
  14 +import io.reactivex.schedulers.Schedulers;
  15 +
  16 +/**
  17 + * Created by Horrarndoo on 2017/9/12.
  18 + * <p>
  19 + */
  20 +public class RxHelper {
  21 + /**
  22 + * 统一线程处理
  23 + * <p>
  24 + * 发布事件io线程,接收事件主线程
  25 + */
  26 + public static <T> ObservableTransformer<T, T> rxSchedulerHelper() {//compose处理线程
  27 + return new ObservableTransformer<T, T>() {
  28 +
  29 + @Override
  30 + public ObservableSource<T> apply(Observable<T> upstream) {
  31 + return upstream.subscribeOn(Schedulers.io())
  32 + .observeOn(AndroidSchedulers.mainThread());
  33 + }
  34 + };
  35 + }
  36 +
  37 + /**
  38 + * 生成Flowable
  39 + *
  40 + * @param t
  41 + * @return Flowable
  42 + */
  43 + public static <T> Flowable<T> createFlowable(final T t) {
  44 + return Flowable.create(new FlowableOnSubscribe<T>() {
  45 + @Override
  46 + public void subscribe(FlowableEmitter<T> emitter) throws Exception {
  47 + try {
  48 + emitter.onNext(t);
  49 + emitter.onComplete();
  50 + } catch (Exception e) {
  51 + emitter.onError(e);
  52 + }
  53 + }
  54 + }, BackpressureStrategy.BUFFER);
  55 + }
  56 +
  57 + /**
  58 + * 生成Observable
  59 + *
  60 + * @param t
  61 + * @return Flowable
  62 + */
  63 + public static <T> Observable<T> createObservable(final T t) {
  64 + return Observable.create(new ObservableOnSubscribe<T>() {
  65 + @Override
  66 + public void subscribe(ObservableEmitter<T> emitter) throws Exception {
  67 + try {
  68 + emitter.onNext(t);
  69 + emitter.onComplete();
  70 + } catch (Exception e) {
  71 + emitter.onError(e);
  72 + }
  73 + }
  74 + });
  75 + }
  76 +}
mvpsdk/src/main/java/com/share/mvpsdk/helper/okhttp/CacheInterceptor.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/helper/okhttp/CacheInterceptor.java
@@ -0,0 +1,84 @@ @@ -0,0 +1,84 @@
  1 +package com.share.mvpsdk.helper.okhttp;
  2 +
  3 +
  4 +
  5 +import com.share.mvpsdk.utils.AppUtils;
  6 +import com.share.mvpsdk.utils.NetworkConnectionUtils;
  7 +
  8 +import java.io.IOException;
  9 +
  10 +import okhttp3.CacheControl;
  11 +import okhttp3.Interceptor;
  12 +import okhttp3.Request;
  13 +import okhttp3.Response;
  14 +
  15 +import static com.share.mvpsdk.utils.HttpUtils.getUserAgent;
  16 +
  17 +
  18 +/**
  19 + * Created by Horrarndoo on 2017/9/12.
  20 + * <p>
  21 + * CacheInterceptor
  22 + */
  23 +public class CacheInterceptor implements Interceptor {
  24 +
  25 + @Override
  26 + public Response intercept(Chain chain) throws IOException {
  27 + Request request = chain.request();
  28 + if (NetworkConnectionUtils.isNetworkConnected(AppUtils.getContext())) {
  29 + // 有网络时, 缓存1小时
  30 + int maxAge = 60 * 60;
  31 + request = request.newBuilder()
  32 + .removeHeader("User-Agent")
  33 + .header("User-Agent", getUserAgent())
  34 + .build();
  35 +
  36 + Response response = chain.proceed(request);
  37 + return response.newBuilder()
  38 + .removeHeader("Pragma")
  39 + .removeHeader("Cache-Control")
  40 + .header("Cache-Control", "public, max-age=" + maxAge)
  41 + .build();
  42 + } else {
  43 + // 无网络时,缓存为4周
  44 + int maxStale = 60 * 60 * 24 * 28;
  45 + request = request.newBuilder()
  46 + .cacheControl(CacheControl.FORCE_CACHE)
  47 + .removeHeader("User-Agent")
  48 + .header("User-Agent", getUserAgent())
  49 + .build();
  50 +
  51 + Response response = chain.proceed(request);
  52 + return response.newBuilder()
  53 + .removeHeader("Pragma")
  54 + .removeHeader("Cache-Control")
  55 + .header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale)
  56 + .build();
  57 + }
  58 +
  59 + // Request request = chain.request();
  60 + // if (!NetworkConnectionUtils.isConnected(AppUtils.getContext())) {
  61 + // request = request.newBuilder()
  62 + // .cacheControl(CacheControl.FORCE_CACHE)
  63 + // .build();
  64 + // }
  65 + // Response response = chain.proceed(request);
  66 + // if (NetworkConnectionUtils.isConnected(AppUtils.getContext())) {
  67 + // int maxAge = 0;
  68 + // // 有网络时, 不缓存, 最大保存时长为0
  69 + // response.newBuilder()
  70 + // .header("Cache-Control", "public, max-age=" + maxAge)
  71 + // .removeHeader("Pragma")
  72 + // .build();
  73 + // } else {
  74 + // // 无网络时,设置超时为4周
  75 + // int maxStale = 60 * 60 * 24 * 28;
  76 + // response.newBuilder()
  77 + // .header("Cache-Control", "public, only-if-cached, max-stale=" +
  78 + // maxStale)
  79 + // .removeHeader("Pragma")
  80 + // .build();
  81 + // }
  82 + // return response;
  83 + }
  84 +}
mvpsdk/src/main/java/com/share/mvpsdk/helper/okhttp/HttpCache.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/helper/okhttp/HttpCache.java
@@ -0,0 +1,28 @@ @@ -0,0 +1,28 @@
  1 +package com.share.mvpsdk.helper.okhttp;
  2 +
  3 +
  4 +import android.os.Environment;
  5 +
  6 +import com.share.mvpsdk.utils.AppUtils;
  7 +
  8 +import java.io.File;
  9 +
  10 +import okhttp3.Cache;
  11 +
  12 +/**
  13 + * Created by Horrarndoo on 2017/9/12.
  14 + * <p>
  15 + */
  16 +public class HttpCache {
  17 +
  18 + private static final int HTTP_RESPONSE_DISK_CACHE_MAX_SIZE = 50 * 1024 * 1024;
  19 +
  20 + public static Cache getCache() {
  21 + File file=new File(Environment.getExternalStorageDirectory() + File
  22 + .separator + "data/NetCache");
  23 + if (!file.getParentFile().exists())file.getParentFile().mkdirs();
  24 + if (!file.exists())file.mkdirs();
  25 + return new Cache(file,
  26 + HTTP_RESPONSE_DISK_CACHE_MAX_SIZE);
  27 + }
  28 +}
mvpsdk/src/main/java/com/share/mvpsdk/helper/okhttp/NetInterceptor.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/helper/okhttp/NetInterceptor.java
@@ -0,0 +1,49 @@ @@ -0,0 +1,49 @@
  1 +package com.share.mvpsdk.helper.okhttp;
  2 +
  3 +
  4 +import com.share.mvpsdk.utils.AppUtils;
  5 +import com.share.mvpsdk.utils.NetworkConnectionUtils;
  6 +
  7 +import java.io.IOException;
  8 +
  9 +import okhttp3.Interceptor;
  10 +import okhttp3.Request;
  11 +import okhttp3.Response;
  12 +
  13 +import static com.share.mvpsdk.utils.HttpUtils.getUserAgent;
  14 +
  15 +
  16 +/**
  17 + * Created by Horrarndoo on 2017/9/18.
  18 + * <p>
  19 + * 有网络时的缓存拦截器
  20 + */
  21 +
  22 +public class NetInterceptor implements Interceptor{
  23 + @Override
  24 + public Response intercept(Chain chain) throws IOException {
  25 + // 有网络时, 缓存1分钟, 最大保存时长为60s
  26 + int maxAge = 60;
  27 + Request request = chain.request();
  28 +
  29 + if (NetworkConnectionUtils.isNetworkConnected(AppUtils.getContext())) {
  30 + request = request.newBuilder()
  31 + .removeHeader("User-Agent")
  32 + .header("User-Agent", getUserAgent())
  33 + // .header("User-Agent", "Mozilla/5.0 (Windows NT 6.1;
  34 + // WOW64) AppleWebKit/537.36" +
  35 + // " (KHTML, like Gecko) Chrome/50.0.2661.102
  36 + // Safari/537.36")
  37 + .build();
  38 +
  39 + Response response = chain.proceed(request);
  40 + return response.newBuilder()
  41 + .removeHeader("Pragma")
  42 + .removeHeader("Cache-Control")
  43 + .header("Cache-Control", "public, max-age=" + maxAge)
  44 + .build();
  45 + }
  46 +
  47 + return chain.proceed(request);
  48 + }
  49 +}
mvpsdk/src/main/java/com/share/mvpsdk/helper/okhttp/NoNetInterceptor.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/helper/okhttp/NoNetInterceptor.java
@@ -0,0 +1,50 @@ @@ -0,0 +1,50 @@
  1 +package com.share.mvpsdk.helper.okhttp;
  2 +
  3 +
  4 +import com.share.mvpsdk.utils.AppUtils;
  5 +import com.share.mvpsdk.utils.NetworkConnectionUtils;
  6 +
  7 +import java.io.IOException;
  8 +
  9 +import okhttp3.CacheControl;
  10 +import okhttp3.Interceptor;
  11 +import okhttp3.Request;
  12 +import okhttp3.Response;
  13 +
  14 +import static com.share.mvpsdk.utils.HttpUtils.getUserAgent;
  15 +
  16 +/**
  17 + * Created by Horrarndoo on 2017/9/18.
  18 + * <p>
  19 + * 无网络时的缓存拦截器
  20 + */
  21 +
  22 +public class NoNetInterceptor implements Interceptor {
  23 + @Override
  24 + public Response intercept(Chain chain) throws IOException {
  25 + // 无网络时,设置超时为4周
  26 + int maxStale = 60 * 60 * 24 * 28;
  27 + Request request = chain.request();
  28 +
  29 + if (!NetworkConnectionUtils.isNetworkConnected(AppUtils.getContext())) {
  30 + request = request.newBuilder()
  31 + .cacheControl(CacheControl.FORCE_CACHE)
  32 + .removeHeader("User-Agent")
  33 + .header("User-Agent", getUserAgent())
  34 + // .header("User-Agent", "Mozilla/5.0 (Windows NT 6.1;
  35 + // WOW64) AppleWebKit/537.36" +
  36 + // " (KHTML, like Gecko) Chrome/50.0.2661.102
  37 + // Safari/537.36")
  38 + .build();
  39 +
  40 + Response response = chain.proceed(request);
  41 + return response.newBuilder()
  42 + .removeHeader("Pragma")
  43 + .removeHeader("Cache-Control")
  44 + .header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale)
  45 + .build();
  46 + }
  47 +
  48 + return chain.proceed(request);
  49 + }
  50 +}
mvpsdk/src/main/java/com/share/mvpsdk/helper/okhttp/TrustManager.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/helper/okhttp/TrustManager.java
@@ -0,0 +1,54 @@ @@ -0,0 +1,54 @@
  1 +package com.share.mvpsdk.helper.okhttp;
  2 +
  3 +import java.security.cert.CertificateException;
  4 +import java.security.cert.X509Certificate;
  5 +
  6 +import javax.net.ssl.SSLContext;
  7 +import javax.net.ssl.SSLSocketFactory;
  8 +import javax.net.ssl.X509TrustManager;
  9 +
  10 +/**
  11 + * Created by Horrarndoo on 2017/9/12.
  12 + * <p>
  13 + */
  14 +public class TrustManager {
  15 +
  16 + public static SSLSocketFactory getUnsafeOkHttpClient() {
  17 + try {
  18 + // Create a trust manager that does not validate certificate chains
  19 + final X509TrustManager[] trustAllCerts = new X509TrustManager[]{new X509TrustManager() {
  20 + @Override
  21 + public void checkClientTrusted(
  22 + X509Certificate[] chain,
  23 + String authType) throws CertificateException {
  24 + }
  25 +
  26 + @Override
  27 + public void checkServerTrusted(
  28 + X509Certificate[] chain,
  29 + String authType) throws CertificateException {
  30 + }
  31 +
  32 + @Override
  33 + public X509Certificate[] getAcceptedIssuers() {
  34 + return new X509Certificate[0];
  35 + }
  36 + }};
  37 +
  38 + // Install the all-trusting trust manager
  39 + final SSLContext sslContext = SSLContext.getInstance("TLS");
  40 + sslContext.init(null, trustAllCerts,
  41 + new java.security.SecureRandom());
  42 + // Create an ssl socket factory with our all-trusting manager
  43 + final SSLSocketFactory sslSocketFactory = sslContext
  44 + .getSocketFactory();
  45 +
  46 +
  47 + return sslSocketFactory;
  48 + } catch (Exception e) {
  49 + throw new RuntimeException(e);
  50 + }
  51 +
  52 + }
  53 +}
  54 +
mvpsdk/src/main/java/com/share/mvpsdk/rxbus/BusData.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/rxbus/BusData.java
@@ -0,0 +1,34 @@ @@ -0,0 +1,34 @@
  1 +package com.share.mvpsdk.rxbus;
  2 +
  3 +/**
  4 + * RxBus data
  5 + * Created by gorden on 2016/7/8.
  6 + */
  7 +public class BusData {
  8 + String id;
  9 + String status;
  10 +
  11 + public BusData() {
  12 + }
  13 +
  14 + public BusData(String id, String status) {
  15 + this.id = id;
  16 + this.status = status;
  17 + }
  18 +
  19 + public String getId() {
  20 + return id;
  21 + }
  22 +
  23 + public void setId(String id) {
  24 + this.id = id;
  25 + }
  26 +
  27 + public String getStatus() {
  28 + return status;
  29 + }
  30 +
  31 + public void setStatus(String status) {
  32 + this.status = status;
  33 + }
  34 +}
0 \ No newline at end of file 35 \ No newline at end of file
mvpsdk/src/main/java/com/share/mvpsdk/rxbus/RxBus.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/rxbus/RxBus.java
@@ -0,0 +1,355 @@ @@ -0,0 +1,355 @@
  1 +package com.share.mvpsdk.rxbus;
  2 +
  3 +import java.lang.reflect.Method;
  4 +import java.util.ArrayList;
  5 +import java.util.HashMap;
  6 +import java.util.Iterator;
  7 +import java.util.List;
  8 +import java.util.Map;
  9 +
  10 +import io.reactivex.BackpressureStrategy;
  11 +import io.reactivex.Flowable;
  12 +import io.reactivex.Scheduler;
  13 +import io.reactivex.android.schedulers.AndroidSchedulers;
  14 +import io.reactivex.disposables.Disposable;
  15 +import io.reactivex.functions.Consumer;
  16 +import io.reactivex.functions.Function;
  17 +import io.reactivex.functions.Predicate;
  18 +import io.reactivex.schedulers.Schedulers;
  19 +import io.reactivex.subjects.PublishSubject;
  20 +import io.reactivex.subjects.Subject;
  21 +
  22 +/**
  23 + * RxBus
  24 + * Created by gorden on 2016/5/12.
  25 + * update 2017/3/1
  26 + */
  27 +@SuppressWarnings("unused")
  28 +public class RxBus {
  29 + public static final String LOG_BUS = "RXBUS_LOG";
  30 + private static volatile RxBus defaultInstance;
  31 +
  32 + private Map<Class, List<Disposable>> subscriptionsByEventType = new HashMap<>();
  33 +
  34 + private Map<Object, List<Class>> eventTypesBySubscriber = new HashMap<>();
  35 +
  36 + private Map<Class, List<SubscriberMethod>> subscriberMethodByEventType = new HashMap<>();
  37 +
  38 + private final Subject<Object> bus;
  39 +
  40 + private RxBus() {
  41 + this.bus = PublishSubject.create().toSerialized();
  42 + }
  43 +
  44 + public static RxBus get() {
  45 + RxBus rxBus = defaultInstance;
  46 + if (defaultInstance == null) {
  47 + synchronized (RxBus.class) {
  48 + rxBus = defaultInstance;
  49 + if (defaultInstance == null) {
  50 + rxBus = new RxBus();
  51 + defaultInstance = rxBus;
  52 + }
  53 + }
  54 + }
  55 + return rxBus;
  56 + }
  57 +
  58 + /**
  59 + * 根据传递的 eventType 类型返回特定类型(eventType)的 被观察者
  60 + *
  61 + * @param eventType 事件类型
  62 + * @return return
  63 + */
  64 + private <T> Flowable<T> toObservable(Class<T> eventType) {
  65 + return bus.toFlowable(BackpressureStrategy.BUFFER).ofType(eventType);
  66 + }
  67 +
  68 + /**
  69 + * 根据传递的code和 eventType 类型返回特定类型(eventType)的 被观察者
  70 + *
  71 + * @param code 事件code
  72 + * @param eventType 事件类型
  73 + */
  74 + private <T> Flowable<T> toObservable(final int code, final Class<T> eventType) {
  75 + return bus.toFlowable(BackpressureStrategy.BUFFER).ofType(Message.class)
  76 + .filter(new Predicate<Message>() {
  77 + @Override
  78 + public boolean test(Message o) throws Exception {
  79 + return o.getCode() == code && eventType.isInstance(o.getObject());
  80 + }
  81 + }).map(new Function<Message, Object>() {
  82 + @Override
  83 + public Object apply(Message o) throws Exception {
  84 + return o.getObject();
  85 + }
  86 + }).cast(eventType);
  87 + }
  88 +
  89 + /**
  90 + * 注册
  91 + *
  92 + * @param subscriber 订阅者
  93 + */
  94 + public void register(Object subscriber) {
  95 + Class<?> subClass = subscriber.getClass();
  96 + Method[] methods = subClass.getDeclaredMethods();
  97 + for (Method method : methods) {
  98 + if (method.isAnnotationPresent(Subscribe.class)) {
  99 + //获得参数类型
  100 + Class[] parameterType = method.getParameterTypes();
  101 + //参数不为空 且参数个数为1
  102 + if (parameterType != null && parameterType.length == 1) {
  103 +
  104 + Class eventType = parameterType[0];
  105 +
  106 + addEventTypeToMap(subscriber, eventType);
  107 + Subscribe sub = method.getAnnotation(Subscribe.class);
  108 + int code = sub.code();
  109 + ThreadMode threadMode = sub.threadMode();
  110 +
  111 + SubscriberMethod subscriberMethod = new SubscriberMethod(subscriber, method, eventType, code, threadMode);
  112 + addSubscriberToMap(eventType, subscriberMethod);
  113 +
  114 + addSubscriber(subscriberMethod);
  115 + } else if (parameterType == null || parameterType.length == 0) {
  116 +
  117 + Class eventType = BusData.class;
  118 +
  119 + addEventTypeToMap(subscriber, eventType);
  120 + Subscribe sub = method.getAnnotation(Subscribe.class);
  121 + int code = sub.code();
  122 + ThreadMode threadMode = sub.threadMode();
  123 +
  124 + SubscriberMethod subscriberMethod = new SubscriberMethod(subscriber, method, eventType, code, threadMode);
  125 + addSubscriberToMap(eventType, subscriberMethod);
  126 +
  127 + addSubscriber(subscriberMethod);
  128 +
  129 + }
  130 + }
  131 + }
  132 + }
  133 +
  134 +
  135 + /**
  136 + * 将event的类型以订阅中subscriber为key保存到map里
  137 + *
  138 + * @param subscriber 订阅者
  139 + * @param eventType event类型
  140 + */
  141 + private void addEventTypeToMap(Object subscriber, Class eventType) {
  142 + List<Class> eventTypes = eventTypesBySubscriber.get(subscriber);
  143 + if (eventTypes == null) {
  144 + eventTypes = new ArrayList<>();
  145 + eventTypesBySubscriber.put(subscriber, eventTypes);
  146 + }
  147 +
  148 + if (!eventTypes.contains(eventType)) {
  149 + eventTypes.add(eventType);
  150 + }
  151 + }
  152 +
  153 + /**
  154 + * 将注解方法信息以event类型为key保存到map中
  155 + *
  156 + * @param eventType event类型
  157 + * @param subscriberMethod 注解方法信息
  158 + */
  159 + private void addSubscriberToMap(Class eventType, SubscriberMethod subscriberMethod) {
  160 + List<SubscriberMethod> subscriberMethods = subscriberMethodByEventType.get(eventType);
  161 + if (subscriberMethods == null) {
  162 + subscriberMethods = new ArrayList<>();
  163 + subscriberMethodByEventType.put(eventType, subscriberMethods);
  164 + }
  165 +
  166 + if (!subscriberMethods.contains(subscriberMethod)) {
  167 + subscriberMethods.add(subscriberMethod);
  168 + }
  169 + }
  170 +
  171 + /**
  172 + * 将订阅事件以event类型为key保存到map,用于取消订阅时用
  173 + *
  174 + * @param eventType event类型
  175 + * @param disposable 订阅事件
  176 + */
  177 + private void addSubscriptionToMap(Class eventType, Disposable disposable) {
  178 + List<Disposable> disposables = subscriptionsByEventType.get(eventType);
  179 + if (disposables == null) {
  180 + disposables = new ArrayList<>();
  181 + subscriptionsByEventType.put(eventType, disposables);
  182 + }
  183 +
  184 + if (!disposables.contains(disposable)) {
  185 + disposables.add(disposable);
  186 + }
  187 + }
  188 +
  189 + /**
  190 + * 用RxJava添加订阅者
  191 + *
  192 + * @param subscriberMethod d
  193 + */
  194 + @SuppressWarnings("unchecked")
  195 + private void addSubscriber(final SubscriberMethod subscriberMethod) {
  196 + Flowable flowable;
  197 + if (subscriberMethod.code == -1) {
  198 + flowable = toObservable(subscriberMethod.eventType);
  199 + } else {
  200 + flowable = toObservable(subscriberMethod.code, subscriberMethod.eventType);
  201 + }
  202 + Disposable subscription = postToObservable(flowable, subscriberMethod)
  203 + .subscribe(new Consumer<Object>() {
  204 + @Override
  205 + public void accept(Object o) throws Exception {
  206 + callEvent(subscriberMethod, o);
  207 + }
  208 + });
  209 +
  210 + addSubscriptionToMap(subscriberMethod.subscriber.getClass(), subscription);
  211 + }
  212 +
  213 + /**
  214 + * 用于处理订阅事件在那个线程中执行
  215 + *
  216 + * @param observable d
  217 + * @param subscriberMethod d
  218 + * @return Observable
  219 + */
  220 + private Flowable postToObservable(Flowable observable, SubscriberMethod subscriberMethod) {
  221 + Scheduler scheduler;
  222 + switch (subscriberMethod.threadMode) {
  223 + case MAIN:
  224 + scheduler = AndroidSchedulers.mainThread();
  225 + break;
  226 +
  227 + case NEW_THREAD:
  228 + scheduler = Schedulers.newThread();
  229 + break;
  230 +
  231 + case CURRENT_THREAD:
  232 + scheduler = Schedulers.trampoline();
  233 + break;
  234 + default:
  235 + throw new IllegalStateException("Unknown thread mode: " + subscriberMethod.threadMode);
  236 + }
  237 + return observable.observeOn(scheduler);
  238 + }
  239 +
  240 + /**
  241 + * 回调到订阅者的方法中
  242 + *
  243 + * @param method code
  244 + * @param object obj
  245 + */
  246 + private void callEvent(SubscriberMethod method, Object object) {
  247 + Class eventClass = object.getClass();
  248 + List<SubscriberMethod> methods = subscriberMethodByEventType.get(eventClass);
  249 + if (methods != null && methods.size() > 0) {
  250 + for (SubscriberMethod subscriberMethod : methods) {
  251 + Subscribe sub = subscriberMethod.method.getAnnotation(Subscribe.class);
  252 + int c = sub.code();
  253 + if (c == method.code && method.subscriber.equals(subscriberMethod.subscriber) && method.method.equals(subscriberMethod.method)) {
  254 + subscriberMethod.invoke(object);
  255 + }
  256 +
  257 + }
  258 + }
  259 + }
  260 +
  261 + /**
  262 + * 取消注册
  263 + *
  264 + * @param subscriber object
  265 + */
  266 + public void unRegister(Object subscriber) {
  267 + List<Class> subscribedTypes = eventTypesBySubscriber.get(subscriber);
  268 + if (subscribedTypes != null) {
  269 + for (Class<?> eventType : subscribedTypes) {
  270 + unSubscribeByEventType(subscriber.getClass());
  271 + unSubscribeMethodByEventType(subscriber, eventType);
  272 + }
  273 + eventTypesBySubscriber.remove(subscriber);
  274 + }
  275 + }
  276 +
  277 + /**
  278 + * subscriptions unsubscribe
  279 + *
  280 + * @param eventType eventType
  281 + */
  282 + private void unSubscribeByEventType(Class eventType) {
  283 + List<Disposable> disposables = subscriptionsByEventType.get(eventType);
  284 + if (disposables != null) {
  285 + Iterator<Disposable> iterator = disposables.iterator();
  286 + while (iterator.hasNext()) {
  287 + Disposable disposable = iterator.next();
  288 + if (disposable != null && !disposable.isDisposed()) {
  289 + disposable.dispose();
  290 + iterator.remove();
  291 + }
  292 + }
  293 + }
  294 + }
  295 +
  296 + /**
  297 + * 移除subscriber对应的subscriberMethods
  298 + *
  299 + * @param subscriber subscriber
  300 + * @param eventType eventType
  301 + */
  302 + private void unSubscribeMethodByEventType(Object subscriber, Class eventType) {
  303 + List<SubscriberMethod> subscriberMethods = subscriberMethodByEventType.get(eventType);
  304 + if (subscriberMethods != null) {
  305 + Iterator<SubscriberMethod> iterator = subscriberMethods.iterator();
  306 + while (iterator.hasNext()) {
  307 + SubscriberMethod subscriberMethod = iterator.next();
  308 + if (subscriberMethod.subscriber.equals(subscriber)) {
  309 + iterator.remove();
  310 + }
  311 + }
  312 + }
  313 + }
  314 +
  315 + public void send(int code, Object o) {
  316 + bus.onNext(new Message(code, o));
  317 + }
  318 +
  319 + public void send(Object o) {
  320 + bus.onNext(o);
  321 + }
  322 +
  323 + public void send(int code) {
  324 + bus.onNext(new Message(code, new BusData()));
  325 + }
  326 +
  327 + private class Message {
  328 + private int code;
  329 + private Object object;
  330 +
  331 + public Message() {
  332 + }
  333 +
  334 + private Message(int code, Object o) {
  335 + this.code = code;
  336 + this.object = o;
  337 + }
  338 +
  339 + private int getCode() {
  340 + return code;
  341 + }
  342 +
  343 + public void setCode(int code) {
  344 + this.code = code;
  345 + }
  346 +
  347 + private Object getObject() {
  348 + return object;
  349 + }
  350 +
  351 + public void setObject(Object object) {
  352 + this.object = object;
  353 + }
  354 + }
  355 +}
0 \ No newline at end of file 356 \ No newline at end of file
mvpsdk/src/main/java/com/share/mvpsdk/rxbus/Subscribe.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/rxbus/Subscribe.java
@@ -0,0 +1,21 @@ @@ -0,0 +1,21 @@
  1 +package com.share.mvpsdk.rxbus;
  2 +
  3 +import java.lang.annotation.Documented;
  4 +import java.lang.annotation.ElementType;
  5 +import java.lang.annotation.Retention;
  6 +import java.lang.annotation.RetentionPolicy;
  7 +import java.lang.annotation.Target;
  8 +
  9 +
  10 +/**
  11 + * Rxbus
  12 + * Created by gorden on 2016/7/23.
  13 + */
  14 +@Documented
  15 +@Target(ElementType.METHOD)
  16 +@Retention(RetentionPolicy.RUNTIME)
  17 +public @interface Subscribe {
  18 + int code() default -1;
  19 +
  20 + ThreadMode threadMode() default ThreadMode.CURRENT_THREAD;
  21 +}
0 \ No newline at end of file 22 \ No newline at end of file
mvpsdk/src/main/java/com/share/mvpsdk/rxbus/SubscriberMethod.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/rxbus/SubscriberMethod.java
@@ -0,0 +1,44 @@ @@ -0,0 +1,44 @@
  1 +package com.share.mvpsdk.rxbus;
  2 +
  3 +import java.lang.reflect.InvocationTargetException;
  4 +import java.lang.reflect.Method;
  5 +
  6 +/**
  7 + *
  8 + * Created by gorden on 2016/7/23.
  9 + */
  10 +public class SubscriberMethod {
  11 + public Method method;
  12 + public ThreadMode threadMode;
  13 + public Class<?> eventType;
  14 + public Object subscriber;
  15 + public int code;
  16 +
  17 + public SubscriberMethod(Object subscriber, Method method, Class<?> eventType, int code,ThreadMode threadMode) {
  18 + this.method = method;
  19 + this.threadMode = threadMode;
  20 + this.eventType = eventType;
  21 + this.subscriber = subscriber;
  22 + this.code = code;
  23 + }
  24 +
  25 +
  26 + /**
  27 + * 调用方法
  28 + * @param o 参数
  29 + */
  30 + public void invoke(Object o){
  31 + try {
  32 + Class[] parameterType = method.getParameterTypes();
  33 + if(parameterType != null && parameterType.length == 1){
  34 + method.invoke(subscriber, o);
  35 + }else if(parameterType == null || parameterType.length == 0){
  36 + method.invoke(subscriber);
  37 + }
  38 + } catch (IllegalAccessException e) {
  39 + e.printStackTrace();
  40 + } catch (InvocationTargetException e) {
  41 + e.printStackTrace();
  42 + }
  43 + }
  44 +}
0 \ No newline at end of file 45 \ No newline at end of file
mvpsdk/src/main/java/com/share/mvpsdk/rxbus/ThreadMode.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/rxbus/ThreadMode.java
@@ -0,0 +1,23 @@ @@ -0,0 +1,23 @@
  1 +package com.share.mvpsdk.rxbus;
  2 +
  3 +/**
  4 + *
  5 + * Created by gorden on 2016/7/23.
  6 + */
  7 +public enum ThreadMode {
  8 + /**
  9 + * current thread
  10 + */
  11 + CURRENT_THREAD,
  12 +
  13 + /**
  14 + * android main thread
  15 + */
  16 + MAIN,
  17 +
  18 +
  19 + /**
  20 + * new thread
  21 + */
  22 + NEW_THREAD
  23 +}
mvpsdk/src/main/java/com/share/mvpsdk/utils/AppUtils.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/utils/AppUtils.java
@@ -0,0 +1,185 @@ @@ -0,0 +1,185 @@
  1 +package com.share.mvpsdk.utils;
  2 +
  3 +import android.annotation.SuppressLint;
  4 +import android.content.ClipData;
  5 +import android.content.ClipboardManager;
  6 +import android.content.Context;
  7 +import android.content.Intent;
  8 +import android.content.pm.PackageInfo;
  9 +import android.content.pm.PackageManager;
  10 +import android.net.Uri;
  11 +import android.os.Environment;
  12 +import android.os.Handler;
  13 +import android.telephony.TelephonyManager;
  14 +import android.util.Log;
  15 +import android.view.inputmethod.InputMethodManager;
  16 +import android.widget.EditText;
  17 +
  18 +
  19 +import com.share.mvpsdk.global.GlobalApplication;
  20 +
  21 +import java.io.File;
  22 +
  23 +import timber.log.Timber;
  24 +
  25 +/**
  26 + * Created by Horrarndoo on 2017/8/31.
  27 + * <p>
  28 + * App工具类
  29 + */
  30 +public class AppUtils {
  31 +
  32 + /**
  33 + * 获取上下文对象
  34 + *
  35 + * @return 上下文对象
  36 + */
  37 + public static Context getContext() {
  38 + return GlobalApplication.getContext();
  39 + }
  40 +
  41 + /**
  42 + * 获取全局handler
  43 + *
  44 + * @return 全局handler
  45 + */
  46 + public static Handler getHandler() {
  47 + return GlobalApplication.getHandler();
  48 + }
  49 +
  50 + /**
  51 + * 获取主线程id
  52 + *
  53 + * @return 主线程id
  54 + */
  55 + public static int getMainThreadId() {
  56 + return GlobalApplication.getMainThreadId();
  57 + }
  58 +
  59 + /**
  60 + * 获取版本名称
  61 + */
  62 + public static String getAppVersionName(Context context) {
  63 + String versionName = "";
  64 + try {
  65 + // ---get the package info---
  66 + PackageManager pm = context.getPackageManager();
  67 + PackageInfo pi = pm.getPackageInfo(context.getPackageName(), 0);
  68 + versionName = pi.versionName;
  69 + if (versionName == null || versionName.length() <= 0) {
  70 + return "";
  71 + }
  72 + } catch (Exception e) {
  73 + Log.e("VersionInfo", "Exception", e);
  74 + }
  75 + return versionName;
  76 + }
  77 +
  78 + /**
  79 + * 获取版本号
  80 + */
  81 + public static int getAppVersionCode(Context context) {
  82 + int versioncode = -1;
  83 + try {
  84 + // ---get the package info---
  85 + PackageManager pm = context.getPackageManager();
  86 + PackageInfo pi = pm.getPackageInfo(context.getPackageName(), 0);
  87 + versioncode = pi.versionCode;
  88 + } catch (Exception e) {
  89 + Log.e("VersionInfo", "Exception", e);
  90 + }
  91 + return versioncode;
  92 + }
  93 +
  94 + @SuppressLint("MissingPermission")
  95 + public static String getIMEI(Context context) {
  96 + TelephonyManager tm = (TelephonyManager) context.getSystemService(Context
  97 + .TELEPHONY_SERVICE);
  98 + return tm.getDeviceId();
  99 + }
  100 +
  101 + /**
  102 + * 显示软键盘
  103 + */
  104 + public static void openSoftInput(EditText et) {
  105 + InputMethodManager inputMethodManager = (InputMethodManager) et.getContext()
  106 + .getSystemService(Context.INPUT_METHOD_SERVICE);
  107 + inputMethodManager.showSoftInput(et, InputMethodManager.HIDE_NOT_ALWAYS);
  108 + }
  109 +
  110 + /**
  111 + * 隐藏软键盘
  112 + */
  113 + public static void hideSoftInput(EditText et) {
  114 + InputMethodManager inputMethodManager = (InputMethodManager) et.getContext()
  115 + .getSystemService(Context.INPUT_METHOD_SERVICE);
  116 + inputMethodManager.hideSoftInputFromWindow(et.getWindowToken(), InputMethodManager
  117 + .HIDE_NOT_ALWAYS);
  118 + }
  119 +
  120 + /**
  121 + * 获取SD卡路径
  122 + *
  123 + * @return 如果sd卡不存在则返回null
  124 + */
  125 + public static File getSDPath() {
  126 + File sdDir = null;
  127 + boolean sdCardExist = Environment.getExternalStorageState().equals(Environment
  128 + .MEDIA_MOUNTED); //判断sd卡是否存在
  129 + if (sdCardExist) {
  130 + sdDir = Environment.getExternalStorageDirectory();//获取跟目录
  131 + }
  132 + return sdDir;
  133 + }
  134 +
  135 + /**
  136 + * 安装文件
  137 + *
  138 + * @param data
  139 + */
  140 + public static void promptInstall(Context context, Uri data) {
  141 + Intent promptInstall = new Intent(Intent.ACTION_VIEW)
  142 + .setDataAndType(data, "application/vnd.android.package-archive");
  143 + // FLAG_ACTIVITY_NEW_TASK 可以保证安装成功时可以正常打开 app
  144 + promptInstall.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
  145 + context.startActivity(promptInstall);
  146 + }
  147 +
  148 + public static void copy2clipboard(Context context, String text) {
  149 + ClipboardManager cm = (ClipboardManager) context.getSystemService(Context
  150 + .CLIPBOARD_SERVICE);
  151 + ClipData clip = ClipData.newPlainText("clip", text);
  152 + cm.setPrimaryClip(clip);
  153 + }
  154 +
  155 + /**
  156 + * 判断是否运行在主线程
  157 + *
  158 + * @return true:当前线程运行在主线程
  159 + * fasle:当前线程没有运行在主线程
  160 + */
  161 + public static boolean isRunOnUIThread() {
  162 + // 获取当前线程id, 如果当前线程id和主线程id相同, 那么当前就是主线程
  163 + int myTid = android.os.Process.myTid();
  164 + if (myTid == getMainThreadId()) {
  165 + return true;
  166 + }
  167 + return false;
  168 + }
  169 +
  170 + /**
  171 + * 运行在主线程
  172 + *
  173 + * @param r 运行的Runnable对象
  174 + */
  175 + public static void runOnUIThread(Runnable r) {
  176 + if (isRunOnUIThread()) {
  177 + // 已经是主线程, 直接运行
  178 + r.run();
  179 + } else {
  180 + // 如果是子线程, 借助handler让其运行在主线程
  181 + Log.d("66666","getHander="+getHandler()+"r="+r);
  182 + getHandler().post(r);
  183 + }
  184 + }
  185 +}
mvpsdk/src/main/java/com/share/mvpsdk/utils/DBUtils.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/utils/DBUtils.java
@@ -0,0 +1,108 @@ @@ -0,0 +1,108 @@
  1 +package com.share.mvpsdk.utils;
  2 +
  3 +import android.content.ContentValues;
  4 +import android.content.Context;
  5 +import android.database.Cursor;
  6 +import android.database.sqlite.SQLiteDatabase;
  7 +import android.database.sqlite.SQLiteOpenHelper;
  8 +
  9 +import com.share.mvpsdk.config.DBConfig;
  10 +
  11 +
  12 +/**
  13 + * Created by Horrarndoo on 2017/8/31.
  14 + * <p>
  15 + * 数据库工具类
  16 + */
  17 +public class DBUtils {
  18 + public static final String CREATE_TABLE_IF_NOT_EXISTS = "create table if not exists %s " +
  19 + "(id integer primary key autoincrement,key text unique,is_read integer)";
  20 +
  21 + private static DBUtils sDBUtis;
  22 + private SQLiteDatabase mSQLiteDatabase;
  23 +
  24 + private DBUtils(Context context) {
  25 + mSQLiteDatabase = new DBHelper(context, DBConfig.DB_NAME + ".db")
  26 + .getWritableDatabase();
  27 + }
  28 +
  29 + public static synchronized DBUtils getDB(Context context) {
  30 + if (sDBUtis == null) {
  31 + synchronized (DBUtils.class) {
  32 + if (sDBUtis == null)
  33 + sDBUtis = new DBUtils(context);
  34 + }
  35 + }
  36 + return sDBUtis;
  37 + }
  38 +
  39 + /**
  40 + * 插入一个item已读状态到数据表
  41 + *
  42 + * @param table 数据表名
  43 + * @param key key值
  44 + * @param value 数据值
  45 + * @return 插入结果
  46 + */
  47 + public boolean insertRead(final String table, String key, int value) {
  48 + Cursor cursor = mSQLiteDatabase.query(table, null, null, null, null, null, "id asc");
  49 + //最多缓存200条
  50 + if (cursor.getCount() > 200 && cursor.moveToNext()) {
  51 + mSQLiteDatabase.delete(table, "id=?", new String[]{String.valueOf(cursor.getInt
  52 + (cursor.getColumnIndex("id")))});
  53 + }
  54 + cursor.close();
  55 + final ContentValues contentValues = new ContentValues();
  56 + contentValues.put("key", key);
  57 + contentValues.put("is_read", value);
  58 + return (mSQLiteDatabase.insertWithOnConflict(table, null, contentValues, SQLiteDatabase
  59 + .CONFLICT_REPLACE) > 0);
  60 + }
  61 +
  62 + /**
  63 + * 判断item是否已经阅读过
  64 + *
  65 + * @param table 数据表名
  66 + * @param key key值
  67 + * @param value
  68 + * @return
  69 + */
  70 + public boolean isRead(String table, String key, int value) {
  71 + boolean isRead = false;
  72 + Cursor cursor = mSQLiteDatabase.query(table, null, "key=?", new String[]{key}, null,
  73 + null, null);
  74 + if (cursor.moveToNext() && (cursor.getInt(cursor.getColumnIndex("is_read")) == value)) {
  75 + isRead = true;
  76 + }
  77 + cursor.close();
  78 + return isRead;
  79 + }
  80 +
  81 + public class DBHelper extends SQLiteOpenHelper {
  82 +
  83 + public DBHelper(Context context, String name) {
  84 + super(context, name, null, 1);
  85 + }
  86 +
  87 + @Override
  88 + public void onCreate(SQLiteDatabase db) {
  89 + //onCreate()方法只有数据库第一次被创建时才会调用,若数据库已存在,此方法不会被调用
  90 + }
  91 +
  92 + @Override
  93 + public void onOpen(SQLiteDatabase db) {
  94 + super.onOpen(db);
  95 + //数据库打开时就会被调用,将插入新表的操作方到onOpen中
  96 + db.execSQL(String.format(CREATE_TABLE_IF_NOT_EXISTS, DBConfig.TABLE_ZHIHU));
  97 + db.execSQL(String.format(CREATE_TABLE_IF_NOT_EXISTS, DBConfig.TABLE_WANGYI));
  98 + db.execSQL(String.format(CREATE_TABLE_IF_NOT_EXISTS, DBConfig.TABLE_WEIXIN));
  99 + db.execSQL(String.format(CREATE_TABLE_IF_NOT_EXISTS, DBConfig.TABLE_GANKIO_DAY));
  100 + db.execSQL(String.format(CREATE_TABLE_IF_NOT_EXISTS, DBConfig.TABLE_GANKIO_CUSTOM));
  101 + }
  102 +
  103 + @Override
  104 + public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
  105 + //只有数据库进行版本升级时被调用
  106 + }
  107 + }
  108 +}
mvpsdk/src/main/java/com/share/mvpsdk/utils/DateUtils.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/utils/DateUtils.java
@@ -0,0 +1,250 @@ @@ -0,0 +1,250 @@
  1 +package com.share.mvpsdk.utils;
  2 +
  3 +import android.text.TextUtils;
  4 +import android.text.format.DateFormat;
  5 +
  6 +import java.text.ParseException;
  7 +import java.text.SimpleDateFormat;
  8 +import java.util.Calendar;
  9 +import java.util.Date;
  10 +import java.util.Locale;
  11 +
  12 +/**
  13 + * Created by Horrarndoo on 2017/8/31.
  14 + * <p>
  15 + * 日期时间工具类
  16 + */
  17 +public class DateUtils {
  18 +
  19 + public static final long ONE_SECOND_MILLIONS = 1000;
  20 + public static final long ONE_MINUTE_MILLIONS = 60 * ONE_SECOND_MILLIONS;
  21 + public static final long ONE_HOUR_MILLIONS = 60 * ONE_MINUTE_MILLIONS;
  22 + public static final long ONE_DAY_MILLIONS = 24 * ONE_HOUR_MILLIONS;
  23 + public static final int DAY_OF_YEAR = 365;
  24 +
  25 + // 日期格式为 2016-02-03 17:04:58
  26 + public static final String PATTERN_DATE = "yyyy年MM月dd日";
  27 + public static final String PATTERN_TIME = "HH:mm:ss";
  28 + public static final String PATTERN_SPLIT = " ";
  29 + public static final String PATTERN = PATTERN_DATE + PATTERN_SPLIT + PATTERN_TIME;
  30 +
  31 + public static String getShortTime(String dateStr) {
  32 + String str;
  33 +
  34 + Date date = str2date(dateStr);
  35 + Date curDate = new Date();
  36 +
  37 + long durTime = curDate.getTime() - date.getTime();
  38 + int dayDiff = calculateDayDiff(date, curDate);
  39 +
  40 + if (durTime <= 10 * ONE_MINUTE_MILLIONS) {
  41 + str = "刚刚";
  42 + } else if (durTime < ONE_HOUR_MILLIONS) {
  43 + str = durTime / ONE_MINUTE_MILLIONS + "分钟前";
  44 + } else if (dayDiff == 0) {
  45 + str = durTime / ONE_HOUR_MILLIONS + "小时前";
  46 + } else if (dayDiff == -1) {
  47 + str = "昨天" + DateFormat.format("HH:mm", date);
  48 + } else if (isSameYear(date, curDate) && dayDiff < -1) {
  49 + str = DateFormat.format("MM-dd", date).toString();
  50 + } else {
  51 + str = DateFormat.format("yyyy-MM", date).toString();
  52 + }
  53 +
  54 + return str;
  55 + }
  56 +
  57 +
  58 +
  59 + /**
  60 + * 获取日期 PATTERN_DATE 部分
  61 + */
  62 + public static String getDate(String date) {
  63 + if (TextUtils.isEmpty(date) || !date.contains(PATTERN_SPLIT)) {
  64 + return "";
  65 + }
  66 + return date.split(PATTERN_SPLIT)[0];
  67 + }
  68 +
  69 + /**
  70 + * 原有日期上累加月
  71 + *
  72 + * @return 累加后的日期 PATTERN_DATE 部分
  73 + */
  74 + public static String addMonth(String date, int moonCount) {
  75 + //如果date为空 就用当前时间
  76 + if (TextUtils.isEmpty(date)) {
  77 + SimpleDateFormat df = new SimpleDateFormat(PATTERN_DATE + PATTERN_SPLIT + PATTERN_TIME);
  78 + date = df.format(new Date());
  79 + }
  80 + Calendar calendar = str2calendar(date);
  81 + calendar.add(Calendar.MONTH, moonCount);
  82 + return getDate(calendar2str(calendar));
  83 + }
  84 +
  85 + /**
  86 + * 计算天数差
  87 + */
  88 + public static int calculateDayDiff(Date targetTime, Date compareTime) {
  89 + boolean sameYear = isSameYear(targetTime, compareTime);
  90 + if (sameYear) {
  91 + return calculateDayDiffOfSameYear(targetTime, compareTime);
  92 + } else {
  93 + int dayDiff = 0;
  94 +
  95 + // 累计年数差的整年天数
  96 + int yearDiff = calculateYearDiff(targetTime, compareTime);
  97 + dayDiff += yearDiff * DAY_OF_YEAR;
  98 +
  99 + // 累计同一年内的天数
  100 + dayDiff += calculateDayDiffOfSameYear(targetTime, compareTime);
  101 +
  102 + return dayDiff;
  103 + }
  104 + }
  105 +
  106 + /**
  107 + * 计算同一年内的天数差
  108 + */
  109 + public static int calculateDayDiffOfSameYear(Date targetTime, Date compareTime) {
  110 + if (targetTime == null || compareTime == null) {
  111 + return 0;
  112 + }
  113 +
  114 + Calendar tarCalendar = Calendar.getInstance();
  115 + tarCalendar.setTime(targetTime);
  116 + int tarDayOfYear = tarCalendar.get(Calendar.DAY_OF_YEAR);
  117 +
  118 + Calendar compareCalendar = Calendar.getInstance();
  119 + compareCalendar.setTime(compareTime);
  120 + int comDayOfYear = compareCalendar.get(Calendar.DAY_OF_YEAR);
  121 +
  122 + return tarDayOfYear - comDayOfYear;
  123 + }
  124 +
  125 + /**
  126 + * 计算年数差
  127 + */
  128 + public static int calculateYearDiff(Date targetTime, Date compareTime) {
  129 + if (targetTime == null || compareTime == null) {
  130 + return 0;
  131 + }
  132 +
  133 + Calendar tarCalendar = Calendar.getInstance();
  134 + tarCalendar.setTime(targetTime);
  135 + int tarYear = tarCalendar.get(Calendar.YEAR);
  136 +
  137 + Calendar compareCalendar = Calendar.getInstance();
  138 + compareCalendar.setTime(compareTime);
  139 + int comYear = compareCalendar.get(Calendar.YEAR);
  140 +
  141 + return tarYear - comYear;
  142 + }
  143 +
  144 + /**
  145 + * 计算月数差
  146 + *
  147 + * @param targetTime
  148 + * @param compareTime
  149 + * @return
  150 + */
  151 + public static int calculateMonthDiff(String targetTime, String compareTime) {
  152 + return calculateMonthDiff(str2date(targetTime, PATTERN_DATE),
  153 + str2date(compareTime, PATTERN_DATE));
  154 + }
  155 +
  156 + /**
  157 + * 计算月数差
  158 + *
  159 + * @param targetTime
  160 + * @param compareTime
  161 + * @return
  162 + */
  163 + public static int calculateMonthDiff(Date targetTime, Date compareTime) {
  164 + Calendar tarCalendar = Calendar.getInstance();
  165 + tarCalendar.setTime(targetTime);
  166 + int tarYear = tarCalendar.get(Calendar.YEAR);
  167 + int tarMonth = tarCalendar.get(Calendar.MONTH);
  168 +
  169 + Calendar compareCalendar = Calendar.getInstance();
  170 + compareCalendar.setTime(compareTime);
  171 + int comYear = compareCalendar.get(Calendar.YEAR);
  172 + int comMonth = compareCalendar.get(Calendar.MONTH);
  173 + return ((tarYear - comYear) * 12 + tarMonth - comMonth);
  174 +
  175 + }
  176 +
  177 + /**
  178 + * 是否为同一年
  179 + */
  180 + public static boolean isSameYear(Date targetTime, Date compareTime) {
  181 + if (targetTime == null || compareTime == null) {
  182 + return false;
  183 + }
  184 +
  185 + Calendar tarCalendar = Calendar.getInstance();
  186 + tarCalendar.setTime(targetTime);
  187 + int tarYear = tarCalendar.get(Calendar.YEAR);
  188 +
  189 + Calendar compareCalendar = Calendar.getInstance();
  190 + compareCalendar.setTime(compareTime);
  191 + int comYear = compareCalendar.get(Calendar.YEAR);
  192 +
  193 + return tarYear == comYear;
  194 + }
  195 +
  196 + public static Date str2date(String str, String format) {
  197 + Date date = null;
  198 + try {
  199 + if (str != null) {
  200 + SimpleDateFormat sdf = new SimpleDateFormat(format);
  201 + date = sdf.parse(str);
  202 + }
  203 + } catch (ParseException e) {
  204 + e.printStackTrace();
  205 + }
  206 + return date;
  207 + }
  208 +
  209 + public static Date str2date(String str) {
  210 + return str2date(str, PATTERN);
  211 + }
  212 +
  213 + public static String date2str(Date date) {
  214 + return date2str(date, PATTERN);
  215 + }
  216 +
  217 + public static String date2str(Date date, String format) {
  218 + SimpleDateFormat sdf = new SimpleDateFormat(format, Locale.CHINA);
  219 + return sdf.format(date);
  220 + }
  221 +
  222 + public static Calendar str2calendar(String str) {
  223 + Calendar calendar = null;
  224 + Date date = str2date(str);
  225 + if (date != null) {
  226 + calendar = Calendar.getInstance();
  227 + calendar.setTime(date);
  228 + }
  229 + return calendar;
  230 + }
  231 +
  232 +
  233 + public static Calendar str2calendar(String str, String format) {
  234 + Calendar calendar = null;
  235 + Date date = str2date(str, format);
  236 + if (date != null) {
  237 + calendar = Calendar.getInstance();
  238 + calendar.setTime(date);
  239 + }
  240 + return calendar;
  241 + }
  242 +
  243 + public static String calendar2str(Calendar calendar) {
  244 + return date2str(calendar.getTime());
  245 + }
  246 +
  247 + public static String calendar2str(Calendar calendar, String format) {
  248 + return date2str(calendar.getTime(), format);
  249 + }
  250 +}
mvpsdk/src/main/java/com/share/mvpsdk/utils/DialogUtils.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/utils/DialogUtils.java
@@ -0,0 +1,60 @@ @@ -0,0 +1,60 @@
  1 +package com.share.mvpsdk.utils;
  2 +
  3 +import android.app.Dialog;
  4 +import android.app.ProgressDialog;
  5 +import android.content.Context;
  6 +import android.content.DialogInterface;
  7 +import android.support.v7.app.AlertDialog;
  8 +
  9 +import com.share.mvpsdk.R;
  10 +
  11 +
  12 +/**
  13 + * Created by Horrarndoo on 2017/8/31.
  14 + * <p>
  15 + * 对话框工具类, 提供常用对话框显示, 使用support.v7包内的AlertDialog样式
  16 + */
  17 +public class DialogUtils {
  18 +
  19 + public static Dialog createProgressDialog(Context context) {
  20 + return createProgressDialog(context, true);
  21 + }
  22 +
  23 + public static Dialog createProgressDialog(Context context, boolean needCancle) {
  24 + ProgressDialog dialog = new ProgressDialog(context);
  25 + dialog.setMessage("Loading ...");
  26 + dialog.setCancelable(needCancle);
  27 + dialog.setCanceledOnTouchOutside(false);
  28 + return dialog;
  29 + }
  30 +
  31 + public static Dialog showCommonDialog(Context context, String message,
  32 + DialogInterface.OnClickListener listener) {
  33 + return showCommonDialog(context, message, context.getString(R.string.dialog_positive),
  34 + context.getString(R.string.dialog_negative), listener);
  35 + }
  36 +
  37 + public static Dialog showCommonDialog(Context context, String message, String positiveText,
  38 + String negativeText, DialogInterface.OnClickListener
  39 + listener) {
  40 + return new AlertDialog.Builder(context)
  41 + .setMessage(message)
  42 + .setPositiveButton(positiveText, listener)
  43 + .setNegativeButton(negativeText, null)
  44 + .show();
  45 + }
  46 +
  47 + public static Dialog showConfirmDialog(Context context, String message,
  48 + DialogInterface.OnClickListener listener) {
  49 + return showConfirmDialog(context, message, context.getString(R.string.dialog_positive),
  50 + listener);
  51 + }
  52 +
  53 + public static Dialog showConfirmDialog(Context context, String message, String positiveText,
  54 + DialogInterface.OnClickListener listener) {
  55 + return new AlertDialog.Builder(context)
  56 + .setMessage(message)
  57 + .setPositiveButton(positiveText, listener)
  58 + .show();
  59 + }
  60 +}
mvpsdk/src/main/java/com/share/mvpsdk/utils/DisplayUtils.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/utils/DisplayUtils.java
@@ -0,0 +1,195 @@ @@ -0,0 +1,195 @@
  1 +package com.share.mvpsdk.utils;
  2 +
  3 +import android.app.Activity;
  4 +import android.content.Context;
  5 +import android.graphics.Bitmap;
  6 +import android.graphics.Canvas;
  7 +import android.os.Build;
  8 +import android.renderscript.Allocation;
  9 +import android.renderscript.Element;
  10 +import android.renderscript.RenderScript;
  11 +import android.renderscript.ScriptIntrinsicBlur;
  12 +import android.util.DisplayMetrics;
  13 +import android.view.View;
  14 +import android.widget.ImageView;
  15 +
  16 +import com.bumptech.glide.Glide;
  17 +import com.share.mvpsdk.R;
  18 +
  19 +import java.io.File;
  20 +
  21 +import jp.wasabeef.glide.transformations.BlurTransformation;
  22 +
  23 +/**
  24 + * Created by Horrarndoo on 2017/8/31.
  25 + * <p>
  26 + * 显示相关工具类
  27 + */
  28 +public class DisplayUtils {
  29 + /**
  30 + * 将px值转换为dp值
  31 + */
  32 + public static int px2dp(float pxValue) {
  33 + final float scale = AppUtils.getContext().getResources().getDisplayMetrics().density;
  34 + return (int) (pxValue / scale + 0.5f);
  35 + }
  36 +
  37 + /**
  38 + * 将dp值转换为px值
  39 + */
  40 + public static int dp2px(float dpValue) {
  41 + final float scale = AppUtils.getContext().getResources().getDisplayMetrics().density;
  42 + return (int) (dpValue * scale + 0.5f);
  43 + }
  44 +
  45 + /**
  46 + * 将px值转换为sp值
  47 + */
  48 + public static int px2sp(float pxValue) {
  49 + final float scale = AppUtils.getContext().getResources().getDisplayMetrics().scaledDensity;
  50 + return (int) (pxValue / scale + 0.5f);
  51 + }
  52 +
  53 + /**
  54 + * 将sp值转换为px值
  55 + */
  56 + public static int sp2px(float dpValue) {
  57 + final float scale = AppUtils.getContext().getResources().getDisplayMetrics().scaledDensity;
  58 + return (int) (dpValue * scale + 0.5f);
  59 + }
  60 +
  61 + /**
  62 + * 获取屏幕宽度
  63 + */
  64 + public static int getScreenWidthPixels(Activity context) {
  65 + DisplayMetrics metric = new DisplayMetrics();
  66 + context.getWindowManager().getDefaultDisplay().getMetrics(metric);
  67 + return metric.widthPixels;
  68 + }
  69 +
  70 + /**
  71 + * 获取屏幕高度
  72 + */
  73 + public static int getScreenHeightPixels(Activity context) {
  74 + DisplayMetrics metric = new DisplayMetrics();
  75 + context.getWindowManager().getDefaultDisplay().getMetrics(metric);
  76 + return metric.heightPixels;
  77 + }
  78 +
  79 + /**
  80 + * 将一个view转换成bitmap位图
  81 + *
  82 + * @param view 要转换的View
  83 + * @return view转换的bitmap
  84 + */
  85 + public static Bitmap viewToBitmap(View view) {
  86 + Bitmap bitmap = Bitmap.createBitmap(view.getMeasuredWidth(), view.getMeasuredHeight(),
  87 + Bitmap.Config.ARGB_8888);
  88 + view.draw(new Canvas(bitmap));
  89 + return bitmap;
  90 + }
  91 +
  92 + /**
  93 + * 获取模糊虚化的bitmap
  94 + *
  95 + * @param context
  96 + * @param bitmap 要模糊的图片
  97 + * @param radius 模糊等级 >=0 && <=25
  98 + * @return
  99 + */
  100 + public static Bitmap getBlurBitmap(Context context, Bitmap bitmap, int radius) {
  101 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
  102 + return blurBitmap(context, bitmap, radius);
  103 + }
  104 + return bitmap;
  105 + }
  106 +
  107 + /**
  108 + * android系统的模糊方法
  109 + *
  110 + * @param bitmap 要模糊的图片
  111 + * @param radius 模糊等级 >=0 && <=25
  112 + */
  113 + public static Bitmap blurBitmap(Context context, Bitmap bitmap, int radius) {
  114 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
  115 + //Let's create an empty bitmap with the same size of the bitmap we want to blur
  116 + Bitmap outBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap
  117 + .Config.ARGB_8888);
  118 + //Instantiate a new Renderscript
  119 + RenderScript rs = RenderScript.create(context);
  120 + //Create an Intrinsic Blur Script using the Renderscript
  121 + ScriptIntrinsicBlur blurScript = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));
  122 + //Create the Allocations (in/out) with the Renderscript and the in/out bitmaps
  123 + Allocation allIn = Allocation.createFromBitmap(rs, bitmap);
  124 + Allocation allOut = Allocation.createFromBitmap(rs, outBitmap);
  125 + //Set the radius of the blur
  126 + blurScript.setRadius(radius);
  127 + //Perform the Renderscript
  128 + blurScript.setInput(allIn);
  129 + blurScript.forEach(allOut);
  130 + //Copy the final bitmap created by the out Allocation to the outBitmap
  131 + allOut.copyTo(outBitmap);
  132 + //recycle the original bitmap
  133 + bitmap.recycle();
  134 + //After finishing everything, we destroy the Renderscript.
  135 + rs.destroy();
  136 + return outBitmap;
  137 + } else {
  138 + return bitmap;
  139 + }
  140 + }
  141 +
  142 + /**
  143 + * 显示网络虚化图片
  144 + *
  145 + * @param context context
  146 + * @param imgUrl 图片url
  147 + * @param imageView 要显示的imageview
  148 + */
  149 + public static void displayBlurImg(Context context, final String imgUrl, ImageView imageView) {
  150 + // "23":模糊度;"4":图片缩放4倍后再进行模糊
  151 + Glide.with(context)
  152 + .load(imgUrl)
  153 + .error(R.drawable.stackblur_default)
  154 + .placeholder(R.drawable.stackblur_default)
  155 + .crossFade(300)
  156 + .bitmapTransform(new BlurTransformation(context, 23, 4))
  157 + .into(imageView);
  158 + }
  159 +
  160 + /**
  161 + * 显示本地虚化图片
  162 + *
  163 + * @param context context
  164 + * @param file 本地图片file
  165 + * @param imageView 要显示的imageview
  166 + */
  167 + public static void displayBlurImg(Context context, File file, ImageView imageView) {
  168 + // "23":模糊度;"4":图片缩放4倍后再进行模糊
  169 + Glide.with(context)
  170 + .load(file)
  171 + .error(R.drawable.stackblur_default)
  172 + .placeholder(R.drawable.stackblur_default)
  173 + .crossFade(300)
  174 + .bitmapTransform(new BlurTransformation(context, 23, 4))
  175 + .into(imageView);
  176 + }
  177 +
  178 + /**
  179 + * 显示资源虚化图片
  180 + *
  181 + * @param context context
  182 + * @param resourceId 图片资源id
  183 + * @param imageView 要显示的imageview
  184 + */
  185 + public static void displayBlurImg(Context context, Integer resourceId, ImageView imageView) {
  186 + // "23":模糊度;"4":图片缩放4倍后再进行模糊
  187 + Glide.with(context)
  188 + .load(resourceId)
  189 + .error(R.drawable.stackblur_default)
  190 + .placeholder(R.drawable.stackblur_default)
  191 + .crossFade(300)
  192 + .bitmapTransform(new BlurTransformation(context, 23, 4))
  193 + .into(imageView);
  194 + }
  195 +}
mvpsdk/src/main/java/com/share/mvpsdk/utils/FileUtils.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/utils/FileUtils.java
@@ -0,0 +1,291 @@ @@ -0,0 +1,291 @@
  1 +package com.share.mvpsdk.utils;
  2 +
  3 +import android.content.ContentResolver;
  4 +import android.content.Context;
  5 +import android.content.Intent;
  6 +import android.database.Cursor;
  7 +import android.graphics.Bitmap;
  8 +import android.net.Uri;
  9 +import android.os.Environment;
  10 +import android.provider.MediaStore;
  11 +import android.text.TextUtils;
  12 +
  13 +import java.io.BufferedInputStream;
  14 +import java.io.BufferedOutputStream;
  15 +import java.io.File;
  16 +import java.io.FileInputStream;
  17 +import java.io.FileNotFoundException;
  18 +import java.io.FileOutputStream;
  19 +import java.io.IOException;
  20 +import java.io.InputStream;
  21 +
  22 +/**
  23 + * Created by Horrarndoo on 2017/8/31.
  24 + * <p>
  25 + * 读取文件工具类
  26 + */
  27 +public class FileUtils {
  28 + private static final String TAG = "FileUtils";
  29 +
  30 + /**
  31 + * Convert byte[] to hex string.将byte转换成int,
  32 + * 然后利用Integer.toHexString(int)来转换成16进制字符串。
  33 + *
  34 + * @param src byte[] data
  35 + * @return hex string
  36 + */
  37 + public static String bytesToHexString(byte[] src) {
  38 + StringBuilder stringBuilder = new StringBuilder("");
  39 + if (src == null || src.length <= 0) {
  40 + return null;
  41 + }
  42 + for (int i = 0; i < src.length; i++) {
  43 + int v = src[i] & 0xFF;
  44 + String hv = Integer.toHexString(v);
  45 + if (hv.length() < 2) {
  46 + stringBuilder.append(0);
  47 + }
  48 + stringBuilder.append(hv);
  49 + }
  50 + return stringBuilder.toString();
  51 + }
  52 +
  53 + /**
  54 + * 根据文件名称和路径,获取sd卡中的文件,以File形式返回byte
  55 + */
  56 + public static File getFile(String fileName, String folder)
  57 + throws IOException {
  58 + String state = Environment.getExternalStorageState();
  59 + if (state.equals(Environment.MEDIA_MOUNTED)) {
  60 + File pathFile = new File(Environment.getExternalStorageDirectory()
  61 + + folder);
  62 + // && !pathFile .isDirectory()
  63 + if (!pathFile.exists()) {
  64 + pathFile.mkdirs();
  65 + }
  66 + File file = new File(pathFile, fileName);
  67 + return file;
  68 + }
  69 + return null;
  70 + }
  71 +
  72 + /**
  73 + * 根据文件名称和路径,获取sd卡中的文件,判断文件是否存在,存在返回true
  74 + */
  75 + public static Boolean checkFile(String fileName, String folder)
  76 + throws IOException {
  77 +
  78 + File targetFile = getFile(fileName, folder);
  79 +
  80 + if (!targetFile.exists()) {
  81 + return false;
  82 + } else {
  83 + return true;
  84 + }
  85 + }
  86 +
  87 + /**
  88 + * 根据Uri返回文件绝对路径
  89 + * 兼容了file:///开头的 和 content://开头的情况
  90 + */
  91 + public static String getRealFilePathFromUri(final Context context, final Uri uri) {
  92 + if (null == uri)
  93 + return null;
  94 + final String scheme = uri.getScheme();
  95 + String data = null;
  96 + if (scheme == null) {
  97 + data = uri.getPath();
  98 + } else if (ContentResolver.SCHEME_FILE.equalsIgnoreCase(scheme)) {
  99 + data = uri.getPath();
  100 + } else if (ContentResolver.SCHEME_CONTENT.equalsIgnoreCase(scheme)) {
  101 + Cursor cursor = context.getContentResolver().query(uri, new String[]{MediaStore
  102 + .Images.ImageColumns.DATA}, null, null, null);
  103 + if (null != cursor) {
  104 + if (cursor.moveToFirst()) {
  105 + int index = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
  106 + if (index > -1) {
  107 + data = cursor.getString(index);
  108 + }
  109 + }
  110 + cursor.close();
  111 + }
  112 + }
  113 + return data;
  114 + }
  115 +
  116 + /**
  117 + * 检查文件是否存在
  118 + */
  119 + public static String checkDirPath(String dirPath) {
  120 + if (TextUtils.isEmpty(dirPath)) {
  121 + return "";
  122 + }
  123 + File dir = new File(dirPath);
  124 + if (!dir.exists()) {
  125 + dir.mkdirs();
  126 + }
  127 + return dirPath;
  128 + }
  129 +
  130 + public static void copyFile(File sourcefile, File targetFile) {
  131 + FileInputStream input = null;
  132 + BufferedInputStream inbuff = null;
  133 + FileOutputStream out = null;
  134 + BufferedOutputStream outbuff = null;
  135 +
  136 + try {
  137 +
  138 + input = new FileInputStream(sourcefile);
  139 + inbuff = new BufferedInputStream(input);
  140 +
  141 + out = new FileOutputStream(targetFile);
  142 + outbuff = new BufferedOutputStream(out);
  143 +
  144 + byte[] b = new byte[1024 * 5];
  145 + int len = 0;
  146 + while ((len = inbuff.read(b)) != -1) {
  147 + outbuff.write(b, 0, len);
  148 + }
  149 + outbuff.flush();
  150 + } catch (Exception ex) {
  151 + } finally {
  152 + try {
  153 + if (inbuff != null)
  154 + inbuff.close();
  155 + if (outbuff != null)
  156 + outbuff.close();
  157 + if (out != null)
  158 + out.close();
  159 + if (input != null)
  160 + input.close();
  161 + } catch (Exception ex) {
  162 +
  163 + }
  164 + }
  165 + }
  166 +
  167 + /**
  168 + * 保存图片到本机
  169 + *
  170 + * @param context context
  171 + * @param fileName 文件名
  172 + * @param file file
  173 + * @param saveResultCallback 保存结果callback
  174 + */
  175 + public static void saveImage(final Context context, final String fileName, final File file,
  176 + final SaveResultCallback saveResultCallback) {
  177 + new Thread(new Runnable() {
  178 + @Override
  179 + public void run() {
  180 + File appDir = new File(Environment.getExternalStorageDirectory(), "yizhi");
  181 + if (!appDir.exists()) {
  182 + appDir.mkdir();
  183 + }
  184 + String saveFileName = "yizhi_pic";
  185 + if (fileName.contains(".png") || fileName.contains(".gif")) {
  186 + String fileFormat = fileName.substring(fileName.lastIndexOf("."));
  187 + saveFileName = MD5Utils.getMD5("yizhi_pic" + fileName) + fileFormat;
  188 + } else {
  189 + saveFileName = MD5Utils.getMD5("yizhi_pic" + fileName) + ".png";
  190 + }
  191 + saveFileName = saveFileName.substring(20);//取前20位作为SaveName
  192 + File savefile = new File(appDir, saveFileName);
  193 + try {
  194 + InputStream is = new FileInputStream(file);
  195 + FileOutputStream fos = new FileOutputStream(savefile);
  196 + byte[] buffer = new byte[1024 * 1024];//1M缓冲区
  197 + int count = 0;
  198 + while ((count = is.read(buffer)) > 0) {
  199 + fos.write(buffer, 0, count);
  200 + }
  201 + fos.close();
  202 + is.close();
  203 + saveResultCallback.onSavedSuccess();
  204 + } catch (FileNotFoundException e) {
  205 + saveResultCallback.onSavedFailed();
  206 + e.printStackTrace();
  207 + } catch (IOException e) {
  208 + saveResultCallback.onSavedFailed();
  209 + e.printStackTrace();
  210 + }
  211 + //保存图片后发送广播通知更新数据库
  212 + Uri uri = Uri.fromFile(savefile);
  213 + context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, uri));
  214 + }
  215 + }).start();
  216 + }
  217 +
  218 + /**
  219 + * 保存Bitmap到本机
  220 + *
  221 + * @param context context
  222 + * @param fileName bitmap文件名
  223 + * @param bmp bitmap
  224 + * @param saveResultCallback 保存结果callback
  225 + */
  226 + public static void saveBitmap(final Context context, final String fileName, final Bitmap bmp,
  227 + final SaveResultCallback
  228 + saveResultCallback) {
  229 + new Thread(new Runnable() {
  230 + @Override
  231 + public void run() {
  232 + File appDir = new File(Environment.getExternalStorageDirectory(), "yizhi");
  233 + if (!appDir.exists()) {
  234 + appDir.mkdir();
  235 + }
  236 + // SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");
  237 + // 设置以当前时间格式为图片名称
  238 + String saveFileName = MD5Utils.getMD5("yizhi_pic" + fileName) + ".png";
  239 + saveFileName = saveFileName.substring(20);//取前20位作为SaveName
  240 + File file = new File(appDir, saveFileName);
  241 + try {
  242 + FileOutputStream fos = new FileOutputStream(file);
  243 + bmp.compress(Bitmap.CompressFormat.PNG, 100, fos);
  244 + fos.flush();
  245 + fos.close();
  246 + saveResultCallback.onSavedSuccess();
  247 + } catch (FileNotFoundException e) {
  248 + saveResultCallback.onSavedFailed();
  249 + e.printStackTrace();
  250 + } catch (IOException e) {
  251 + saveResultCallback.onSavedFailed();
  252 + e.printStackTrace();
  253 + }
  254 + //保存图片后发送广播通知更新数据库
  255 + Uri uri = Uri.fromFile(file);
  256 + context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, uri));
  257 + }
  258 + }).start();
  259 + }
  260 +
  261 + //保存webview缓存的
  262 + public static String getCache() {
  263 + String cacheFilePath=Environment.getExternalStorageDirectory()+File.separator+"Cache";
  264 + File cacheFile=new File(cacheFilePath);
  265 + if (!cacheFile.exists())cacheFile.mkdirs();
  266 + return cacheFile.toString();
  267 + }
  268 +
  269 + public static boolean webViewCacheIsExit(){
  270 + File file=new File(getCache());
  271 + FileInputStream fileInputStream=null;
  272 + try {
  273 + fileInputStream=new FileInputStream(file);
  274 + if (fileInputStream.available()>0)
  275 + return true;
  276 + } catch (FileNotFoundException e) {
  277 + e.printStackTrace();
  278 + } catch (IOException e) {
  279 + e.printStackTrace();
  280 + }
  281 + return false;
  282 + }
  283 +
  284 + public interface SaveResultCallback {
  285 + void onSavedSuccess();
  286 +
  287 + void onSavedFailed();
  288 + }
  289 +}
  290 +
  291 +
mvpsdk/src/main/java/com/share/mvpsdk/utils/HtmlUtils.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/utils/HtmlUtils.java
@@ -0,0 +1,93 @@ @@ -0,0 +1,93 @@
  1 +package com.share.mvpsdk.utils;
  2 +
  3 +import java.util.List;
  4 +
  5 +/**
  6 + * Created by Horrarndoo on 2017/8/31.
  7 + * <p>
  8 + * Html工具类
  9 + */
  10 +public class HtmlUtils {
  11 +
  12 + //css样式,隐藏header
  13 + private static final String HIDE_HEADER_STYLE = "<style>div.headline{display:none;}</style>";
  14 +
  15 + //css style tag,需要格式化
  16 + private static final String NEEDED_FORMAT_CSS_TAG = "<link rel=\"stylesheet\" " +
  17 + "type=\"text/css\" href=\"%s\"/>";
  18 +
  19 + // js script tag,需要格式化
  20 + private static final String NEEDED_FORMAT_JS_TAG = "<script src=\"%s\"></script>";
  21 +
  22 + public static final String MIME_TYPE = "text/html; charset=utf-8";
  23 +
  24 + public static final String ENCODING = "utf-8";
  25 +
  26 + private HtmlUtils() {
  27 +
  28 + }
  29 +
  30 + /**
  31 + * 根据css链接生成Link标签
  32 + *
  33 + * @param url String
  34 + * @return String
  35 + */
  36 + public static String createCssTag(String url) {
  37 +
  38 + return String.format(NEEDED_FORMAT_CSS_TAG, url);
  39 + }
  40 +
  41 + /**
  42 + * 根据多个css链接生成Link标签
  43 + *
  44 + * @param urls List<String>
  45 + * @return String
  46 + */
  47 + public static String createCssTag(List<String> urls) {
  48 +
  49 + final StringBuilder sb = new StringBuilder();
  50 + for (String url : urls) {
  51 + sb.append(createCssTag(url));
  52 + }
  53 + return sb.toString();
  54 + }
  55 +
  56 + /**
  57 + * 根据js链接生成Script标签
  58 + *
  59 + * @param url String
  60 + * @return String
  61 + */
  62 + public static String createJsTag(String url) {
  63 +
  64 + return String.format(NEEDED_FORMAT_JS_TAG, url);
  65 + }
  66 +
  67 + /**
  68 + * 根据多个js链接生成Script标签
  69 + *
  70 + * @param urls List<String>
  71 + * @return String
  72 + */
  73 + public static String createJsTag(List<String> urls) {
  74 +
  75 + final StringBuilder sb = new StringBuilder();
  76 + for (String url : urls) {
  77 + sb.append(createJsTag(url));
  78 + }
  79 + return sb.toString();
  80 + }
  81 +
  82 + /**
  83 + * 根据样式标签,html字符串,js标签
  84 + * 生成完整的HTML文档
  85 + */
  86 +
  87 + public static String createHtmlData(String html, List<String> cssList, List<String> jsList) {
  88 + final String css = HtmlUtils.createCssTag(cssList);
  89 + final String js = HtmlUtils.createJsTag(jsList);
  90 + return css.concat(HIDE_HEADER_STYLE).concat(html).concat(js);
  91 + }
  92 +}
  93 +
mvpsdk/src/main/java/com/share/mvpsdk/utils/HttpUtils.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/utils/HttpUtils.java
@@ -0,0 +1,76 @@ @@ -0,0 +1,76 @@
  1 +package com.share.mvpsdk.utils;
  2 +
  3 +import android.os.Build;
  4 +import android.support.annotation.NonNull;
  5 +import android.webkit.WebSettings;
  6 +
  7 +import com.orhanobut.logger.Logger;
  8 +
  9 +import java.util.ArrayList;
  10 +import java.util.List;
  11 +import java.util.regex.Matcher;
  12 +import java.util.regex.Pattern;
  13 +
  14 +/**
  15 + * Created by Horrarndoo on 2017/9/18.
  16 + * <p>
  17 + * HttpUtils 主要用于获取UserAgent
  18 + */
  19 +
  20 +public class HttpUtils {
  21 + /**
  22 + * 获取UserAgent
  23 + *
  24 + * @return UserAgent
  25 + */
  26 + @NonNull
  27 + public static String getUserAgent() {
  28 + String userAgent = "";
  29 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
  30 + try {
  31 + userAgent = WebSettings.getDefaultUserAgent(AppUtils.getContext());
  32 + } catch (Exception e) {
  33 + userAgent = System.getProperty("http.agent");
  34 + }
  35 + } else {
  36 + userAgent = System.getProperty("http.agent");
  37 + }
  38 + StringBuffer sb = new StringBuffer();
  39 + for (int i = 0, length = userAgent.length(); i < length; i++) {
  40 + char c = userAgent.charAt(i);
  41 + if (c <= '\u001f' || c >= '\u007f') {
  42 + sb.append(String.format("\\u%04x", (int) c));
  43 + } else {
  44 + sb.append(c);
  45 + }
  46 + }
  47 + return sb.toString();
  48 + }
  49 +
  50 + public static String makeUA() {
  51 + final String ua = Build.BRAND + "/" + Build.MODEL + "/" + Build.VERSION.RELEASE;
  52 + return ua;
  53 + }
  54 +
  55 + public static String[] returnImageUrlsFromHtml(String html) {
  56 + List<String> imageSrcList = new ArrayList<String>();
  57 + Pattern p = Pattern.compile("<img\\b[^>]*\\bsrc\\b\\s*=\\s*('|\")?([^'\"\n\r\f>]+(\\" +
  58 + ".jpg|\\.bmp|\\.eps|\\.gif|\\.mif|\\.miff|\\.png|\\.tif|\\.tiff|\\.svg|\\.wmf|\\" +
  59 + ".jpe|\\.jpeg|\\.dib|\\.ico|\\.tga|\\.cut|\\.pic|\\b)\\b)[^>]*>", Pattern
  60 + .CASE_INSENSITIVE);
  61 + Matcher m = p.matcher(html);
  62 + String quote = null;
  63 + String src = null;
  64 + while (m.find()) {
  65 + quote = m.group(1);
  66 + src = (quote == null || quote.trim().length() == 0) ? m.group(2).split("//s+")[0] : m
  67 + .group(2);
  68 + imageSrcList.add(src);
  69 + }
  70 + if (imageSrcList.size() == 0) {
  71 + Logger.e("资讯中未匹配到图片链接");
  72 + return null;
  73 + }
  74 + return imageSrcList.toArray(new String[imageSrcList.size()]);
  75 + }
  76 +}
mvpsdk/src/main/java/com/share/mvpsdk/utils/IOUtils.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/utils/IOUtils.java
@@ -0,0 +1,25 @@ @@ -0,0 +1,25 @@
  1 +package com.share.mvpsdk.utils;
  2 +
  3 +import java.io.Closeable;
  4 +import java.io.IOException;
  5 +
  6 +/**
  7 + * Created by Horrarndoo on 2017/8/31.
  8 + * <p>
  9 + * IO流工具类
  10 + */
  11 +public class IOUtils {
  12 + /**
  13 + * 关闭流
  14 + */
  15 + public static boolean close(Closeable io) {
  16 + if (io != null) {
  17 + try {
  18 + io.close();
  19 + } catch (IOException e) {
  20 + LogUtils.e(e);
  21 + }
  22 + }
  23 + return true;
  24 + }
  25 +}
mvpsdk/src/main/java/com/share/mvpsdk/utils/ImageUtils.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/utils/ImageUtils.java
@@ -0,0 +1,339 @@ @@ -0,0 +1,339 @@
  1 +package com.share.mvpsdk.utils;
  2 +
  3 +import android.annotation.TargetApi;
  4 +import android.app.Activity;
  5 +import android.content.ContentUris;
  6 +import android.content.ContentValues;
  7 +import android.content.Context;
  8 +import android.content.DialogInterface;
  9 +import android.content.Intent;
  10 +import android.database.Cursor;
  11 +import android.net.Uri;
  12 +import android.os.Build;
  13 +import android.os.Environment;
  14 +import android.provider.DocumentsContract;
  15 +import android.provider.MediaStore;
  16 +import android.support.v7.app.AlertDialog;
  17 +
  18 +import com.bumptech.glide.Glide;
  19 +import com.bumptech.glide.request.FutureTarget;
  20 +
  21 +import io.reactivex.Observable;
  22 +import io.reactivex.ObservableSource;
  23 +import io.reactivex.functions.Function;
  24 +
  25 +/**
  26 + * 图片工具类
  27 + */
  28 +public class ImageUtils {
  29 +
  30 + /**
  31 + * 拍照
  32 + */
  33 + public static final int REQUEST_CODE_FROM_CAMERA = 1 << 10;
  34 +
  35 + /**
  36 + * 相册
  37 + */
  38 + public static final int REQUEST_CODE_FROM_ALBUM = 1 << 12;
  39 +
  40 + /**
  41 + * 裁剪
  42 + */
  43 + public static final int REQUEST_CODE_CROP_IMAGE = 1 << 14;
  44 +
  45 + /**
  46 + * 存放拍照图片的uri地址
  47 + */
  48 + public static Uri imageUriFromCamera;
  49 +
  50 + /**
  51 + * 存放裁剪图片的uri地址
  52 + */
  53 + public static Uri cropImageUri;
  54 +
  55 + /**
  56 + * 显示获取照片不同方式对话框
  57 + */
  58 + public static void showImagePickDialog(final Activity activity) {
  59 + showImagePickDialog(activity, 0);
  60 + }
  61 +
  62 + /**
  63 + * 显示获取照片不同方式对话框
  64 + */
  65 + public static void showImagePickDialog(final Activity activity, final int addRequest) {
  66 + String title = "选择获取图片方式";
  67 + String[] items = new String[]{"拍照", "相册"};
  68 + new AlertDialog.Builder(activity)
  69 + .setTitle(title)
  70 + .setItems(items, new DialogInterface.OnClickListener() {
  71 + @Override
  72 + public void onClick(DialogInterface dialog, int which) {
  73 + dialog.dismiss();
  74 + switch (which) {
  75 + case 0:
  76 + pickImageFromCamera(activity, addRequest);
  77 + break;
  78 + case 1:
  79 + pickImageFromAlbum(activity, addRequest);
  80 + break;
  81 + default:
  82 + break;
  83 + }
  84 + }
  85 + })
  86 + .setNegativeButton("取消", null)
  87 + .show();
  88 + }
  89 +
  90 + /**
  91 + * 打开相机拍照获取图片
  92 + */
  93 + @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
  94 + public static void pickImageFromCamera(final Activity activity, int addRequest) {
  95 + // 先生成一个uri地址用于存放拍照获取的图片
  96 + imageUriFromCamera = createImageUri(activity);
  97 +
  98 + Intent intent = new Intent();
  99 + intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);
  100 + intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUriFromCamera);
  101 + activity.startActivityForResult(intent, REQUEST_CODE_FROM_CAMERA + addRequest);
  102 + }
  103 +
  104 + /**
  105 + * 打开相机拍照获取图片
  106 + */
  107 + public static void pickImageFromCamera(final Activity activity) {
  108 + pickImageFromCamera(activity, 0);
  109 + }
  110 +
  111 + /**
  112 + * 打开本地相册选取图片
  113 + */
  114 + @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
  115 + public static void pickImageFromAlbum(final Activity activity, int addRequest) {
  116 + Intent intent = new Intent();
  117 + intent.setAction(Intent.ACTION_GET_CONTENT);
  118 + intent.setType("image/*");
  119 + activity.startActivityForResult(intent, REQUEST_CODE_FROM_ALBUM + addRequest);
  120 + }
  121 +
  122 + /**
  123 + * 打开本地相册选取图片
  124 + */
  125 + public static void pickImageFromAlbum(final Activity activity) {
  126 + pickImageFromAlbum(activity, 0);
  127 + }
  128 +
  129 + /**
  130 + * 压缩图片
  131 + *
  132 + * @param context context
  133 + * @param uri 图片uri
  134 + * @param reqW 上传图片需要压缩的宽度
  135 + * @param reqH 上传图片需要压缩的高度
  136 + * @return 上传成功回调
  137 + */
  138 + public static Observable<byte[]> compressImage(final Context context,
  139 + Uri uri,
  140 + final int reqW,
  141 + final int reqH) {
  142 + // 先从本地获取图片,利用Glide压缩图片后获取byte[]
  143 + return Observable.just(uri)
  144 + .flatMap(new Function<Uri, ObservableSource<byte[]>>() {
  145 + @Override
  146 + public ObservableSource<byte[]> apply(Uri uri) throws Exception {
  147 + // 在work线程中,同步压缩图片,然后Observable返回
  148 + // 即将Glide的回调封装成RxJava的Observable
  149 + FutureTarget<byte[]> future = Glide.with(context)
  150 + .load(uri)
  151 + .asBitmap()
  152 + .toBytes()
  153 + .into(reqW, reqH);
  154 +
  155 + byte[] bytes;
  156 + try {
  157 + bytes = future.get();
  158 + } catch (Exception e) {
  159 + // 获取失败时,抛出runtime异常
  160 + // 该异常会被Subscriber捕捉,进onError
  161 + throw new RuntimeException(e);
  162 + }
  163 + return Observable.just(bytes);
  164 + }
  165 + });
  166 + }
  167 +
  168 + /**
  169 + * 图片裁剪
  170 + */
  171 + public static void cropImage(Activity activity, Uri srcUri) {
  172 + cropImageUri = createImageUri(activity);
  173 +
  174 + Intent intent = new Intent("com.android.camera.action.CROP");
  175 + intent.setDataAndType(srcUri, "image/*");
  176 + intent.putExtra("crop", "true");
  177 +
  178 + ////////////////////////////////////////////////////////////////
  179 + // 1.宽高和比例都不设置时,裁剪框可以自行调整(比例和大小都可以随意调整)
  180 + ////////////////////////////////////////////////////////////////
  181 + // 2.只设置裁剪框宽高比(aspect)后,裁剪框比例固定不可调整,只能调整大小
  182 + /////////////////////////////////
  183 + // 3.裁剪后生成图片宽高(output)的设置和裁剪框无关,只决定最终生成图片大小
  184 + ////////////////////////////////////////////////////////////////
  185 + // 4.裁剪框宽高比例(aspect)可以和裁剪后生成图片比例(output)不同,此时,
  186 + // 会以裁剪框的宽为准,按照裁剪宽高比例生成一个图片,该图和框选部分可能不同,
  187 + // 不同的情况可能是截取框选的一部分,也可能超出框选部分,向下延伸补足
  188 + ////////////////////////////////////////////////////////////////
  189 +
  190 + // aspectX aspectY 是裁剪框宽高的比例
  191 + intent.putExtra("aspectX", 1);
  192 + intent.putExtra("aspectY", 1);
  193 + // outputX outputY 是裁剪后生成图片的宽高
  194 + // intent.putExtra("outputX", 300);
  195 + // intent.putExtra("outputY", 100);
  196 +
  197 + // return-data为true时,会直接返回bitmap数据,但是大图裁剪时会出现OOM,推荐下面为false时的方式
  198 + // return-data为false时,不会返回bitmap,但需要指定一个MediaStore.EXTRA_OUTPUT保存图片uri
  199 + intent.putExtra("return-data", false);
  200 + intent.putExtra(MediaStore.EXTRA_OUTPUT, cropImageUri);
  201 +
  202 + activity.startActivityForResult(intent, REQUEST_CODE_CROP_IMAGE);
  203 + }
  204 +
  205 + /**
  206 + * 创建一条图片uri,用于保存拍照后的照片
  207 + */
  208 + private static Uri createImageUri(Context context) {
  209 + String name = "boreImg" + System.currentTimeMillis();
  210 + ContentValues values = new ContentValues();
  211 + values.put(MediaStore.Images.Media.TITLE, name);
  212 + values.put(MediaStore.Images.Media.DISPLAY_NAME, name + ".jpeg");
  213 + values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
  214 + Uri uri = context.getContentResolver().insert(MediaStore.Images.Media
  215 + .EXTERNAL_CONTENT_URI, values);
  216 + return uri;
  217 + }
  218 +
  219 + /**
  220 + * 删除一条图片
  221 + */
  222 + public static void deleteImageUri(Context context, Uri uri) {
  223 + context.getContentResolver().delete(uri, null, null);
  224 + }
  225 +
  226 + /**
  227 + * 用第三方应用app打开图片
  228 + */
  229 + public static void openImageByOtherApp(Context context, Uri imageUri) {
  230 + Intent intent = new Intent();
  231 + intent.setAction(Intent.ACTION_VIEW);
  232 + intent.setDataAndType(imageUri, "image/*");
  233 + context.startActivity(intent);
  234 + }
  235 +
  236 + /**
  237 + * 根据Uri获取图片绝对路径,解决Android4.4以上版本Uri转换
  238 + */
  239 + public static String getImageAbsolutePath19(Context context, Uri imageUri) {
  240 + if (context == null || imageUri == null)
  241 + return null;
  242 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT
  243 + && DocumentsContract.isDocumentUri(context, imageUri)) {
  244 + if (isExternalStorageDocument(imageUri)) {
  245 + String docId = DocumentsContract.getDocumentId(imageUri);
  246 + String[] split = docId.split(":");
  247 + String type = split[0];
  248 + if ("primary".equalsIgnoreCase(type)) {
  249 + return Environment.getExternalStorageDirectory() + "/" + split[1];
  250 + }
  251 + } else if (isDownloadsDocument(imageUri)) {
  252 + String id = DocumentsContract.getDocumentId(imageUri);
  253 + Uri contentUri = ContentUris.withAppendedId(Uri.parse
  254 + ("content://downloads/public_downloads"), Long.valueOf(id));
  255 + return getDataColumn(context, contentUri, null, null);
  256 + } else if (isMediaDocument(imageUri)) {
  257 + String docId = DocumentsContract.getDocumentId(imageUri);
  258 + String[] split = docId.split(":");
  259 + String type = split[0];
  260 + Uri contentUri = null;
  261 + if ("image".equals(type)) {
  262 + contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
  263 + } else if ("video".equals(type)) {
  264 + contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
  265 + } else if ("audio".equals(type)) {
  266 + contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
  267 + }
  268 + String selection = MediaStore.Images.Media._ID + "=?";
  269 + String[] selectionArgs = new String[]{split[1]};
  270 + return getDataColumn(context, contentUri, selection, selectionArgs);
  271 + }
  272 + }
  273 +
  274 + // MediaStore (and general)
  275 + if ("content".equalsIgnoreCase(imageUri.getScheme())) {
  276 + // Return the remote address
  277 + if (isGooglePhotosUri(imageUri))
  278 + return imageUri.getLastPathSegment();
  279 + return getDataColumn(context, imageUri, null, null);
  280 + }
  281 + // File
  282 + else if ("file".equalsIgnoreCase(imageUri.getScheme())) {
  283 + return imageUri.getPath();
  284 + }
  285 + return null;
  286 + }
  287 +
  288 + private static String getDataColumn(Context context, Uri uri, String selection, String[]
  289 + selectionArgs) {
  290 + Cursor cursor = null;
  291 + String column = MediaStore.Images.Media.DATA;
  292 + String[] projection = {column};
  293 + try {
  294 + cursor = context.getContentResolver().query(uri, projection, selection,
  295 + selectionArgs, null);
  296 + if (cursor != null && cursor.moveToFirst()) {
  297 + int index = cursor.getColumnIndexOrThrow(column);
  298 + return cursor.getString(index);
  299 + }
  300 + } finally {
  301 + if (cursor != null)
  302 + cursor.close();
  303 + }
  304 + return null;
  305 + }
  306 +
  307 + /**
  308 + * @param uri The Uri to check.
  309 + * @return Whether the Uri authority is ExternalStorageProvider.
  310 + */
  311 + private static boolean isExternalStorageDocument(Uri uri) {
  312 + return "com.android.externalstorage.documents".equals(uri.getAuthority());
  313 + }
  314 +
  315 + /**
  316 + * @param uri The Uri to check.
  317 + * @return Whether the Uri authority is DownloadsProvider.
  318 + */
  319 + private static boolean isDownloadsDocument(Uri uri) {
  320 + return "com.android.providers.downloads.documents".equals(uri.getAuthority());
  321 + }
  322 +
  323 + /**
  324 + * @param uri The Uri to check.
  325 + * @return Whether the Uri authority is MediaProvider.
  326 + */
  327 + private static boolean isMediaDocument(Uri uri) {
  328 + return "com.android.providers.media.documents".equals(uri.getAuthority());
  329 + }
  330 +
  331 + /**
  332 + * @param uri The Uri to check.
  333 + * @return Whether the Uri authority is Google Photos.
  334 + */
  335 + private static boolean isGooglePhotosUri(Uri uri) {
  336 + return "com.google.android.apps.photos.content".equals(uri.getAuthority());
  337 + }
  338 +
  339 +}
mvpsdk/src/main/java/com/share/mvpsdk/utils/JsonUtils.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/utils/JsonUtils.java
@@ -0,0 +1,65 @@ @@ -0,0 +1,65 @@
  1 +package com.share.mvpsdk.utils;
  2 +
  3 +import com.google.gson.Gson;
  4 +import com.google.gson.JsonObject;
  5 +import com.google.gson.JsonSyntaxException;
  6 +
  7 +import java.lang.reflect.Type;
  8 +
  9 +/**
  10 + * Created by Horrarndoo on 2017/9/20.
  11 + * <p>
  12 + * Json转换工具类
  13 + */
  14 +public class JsonUtils {
  15 +
  16 + private static Gson mGson = new Gson();
  17 +
  18 + /**
  19 + * 将对象准换为json字符串
  20 + *
  21 + * @param object
  22 + * @param <T>
  23 + * @return
  24 + */
  25 + public static <T> String serialize(T object) {
  26 + return mGson.toJson(object);
  27 + }
  28 +
  29 + /**
  30 + * 将json字符串转换为对象
  31 + *
  32 + * @param json
  33 + * @param clz
  34 + * @param <T>
  35 + * @return
  36 + */
  37 + public static <T> T deserialize(String json, Class<T> clz) throws JsonSyntaxException {
  38 + return mGson.fromJson(json, clz);
  39 + }
  40 +
  41 + /**
  42 + * 将json对象转换为实体对象
  43 + *
  44 + * @param json
  45 + * @param clz
  46 + * @param <T>
  47 + * @return
  48 + * @throws JsonSyntaxException
  49 + */
  50 + public static <T> T deserialize(JsonObject json, Class<T> clz) throws JsonSyntaxException {
  51 + return mGson.fromJson(json, clz);
  52 + }
  53 +
  54 + /**
  55 + * 将json字符串转换为对象
  56 + *
  57 + * @param json
  58 + * @param type
  59 + * @param <T>
  60 + * @return
  61 + */
  62 + public static <T> T deserialize(String json, Type type) throws JsonSyntaxException {
  63 + return mGson.fromJson(json, type);
  64 + }
  65 +}
mvpsdk/src/main/java/com/share/mvpsdk/utils/LogUtils.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/utils/LogUtils.java
@@ -0,0 +1,168 @@ @@ -0,0 +1,168 @@
  1 +package com.share.mvpsdk.utils;
  2 +
  3 +import android.util.Log;
  4 +
  5 +
  6 +/**
  7 + * Created by Horrarndoo on 2017/4/5.
  8 + * <p>
  9 + * Log工具类
  10 + */
  11 +public class LogUtils {
  12 + /**
  13 + * 日志输出级别NONE
  14 + */
  15 + public static final int LEVEL_NONE = 0;
  16 + /**
  17 + * 日志输出级别E
  18 + */
  19 + public static final int LEVEL_ERROR = 1;
  20 + /**
  21 + * 日志输出级别W
  22 + */
  23 + public static final int LEVEL_WARN = 2;
  24 + /**
  25 + * 日志输出级别I
  26 + */
  27 + public static final int LEVEL_INFO = 3;
  28 + /**
  29 + * 日志输出级别D
  30 + */
  31 + public static final int LEVEL_DEBUG = 4;
  32 + /**
  33 + * 日志输出级别V
  34 + */
  35 + public static final int LEVEL_VERBOSE = 5;
  36 +
  37 + /**
  38 + * 日志输出时的TAG
  39 + */
  40 + private static String mTag = "LogUtils";
  41 +
  42 + /**
  43 + * 是否允许输出log
  44 + */
  45 + private static int mDebuggable = LEVEL_VERBOSE;
  46 +
  47 + /**
  48 + * 设置调试Log开关
  49 + *
  50 + * @param isEnable 是否允许log
  51 + */
  52 + public static void setDebuggable(boolean isEnable) {
  53 + mDebuggable = isEnable ? LEVEL_VERBOSE : LEVEL_NONE;
  54 + }
  55 +
  56 + /**
  57 + * 以级别为 d 的形式输出LOG
  58 + */
  59 + public static void v(String msg) {
  60 + if (mDebuggable >= LEVEL_VERBOSE) {
  61 + Log.v(mTag, msg);
  62 + }
  63 + }
  64 +
  65 + /**
  66 + * 以级别为 d 的形式输出LOG
  67 + */
  68 + public static void d(String msg) {
  69 + if (mDebuggable >= LEVEL_DEBUG) {
  70 + Log.d(mTag, msg);
  71 + }
  72 + }
  73 +
  74 + /**
  75 + * 以级别为 i 的形式输出LOG
  76 + */
  77 + public static void i(String msg) {
  78 + if (mDebuggable >= LEVEL_INFO) {
  79 + Log.i(mTag, msg);
  80 + }
  81 + }
  82 +
  83 + /**
  84 + * 以级别为 w 的形式输出LOG
  85 + */
  86 + public static void w(String msg) {
  87 + if (mDebuggable >= LEVEL_WARN) {
  88 + Log.w(mTag, msg);
  89 + }
  90 + }
  91 +
  92 + /**
  93 + * 以级别为 e 的形式输出LOG
  94 + */
  95 + public static void e(String msg) {
  96 + if (mDebuggable >= LEVEL_ERROR) {
  97 + Log.e(mTag, msg);
  98 + }
  99 + }
  100 +
  101 + /**
  102 + * 以级别为 w 的形式输出Throwable
  103 + */
  104 + public static void w(Throwable tr) {
  105 + w("", tr);
  106 + }
  107 +
  108 + /**
  109 + * 以级别为 w 的形式输出LOG信息和Throwable
  110 + */
  111 + public static void w(String msg, Throwable tr) {
  112 + Log.w(mTag, msg, tr);
  113 + }
  114 +
  115 + /**
  116 + * 以级别为 e 的形式输出Throwable
  117 + */
  118 + public static void e(Throwable tr) {
  119 + e("", tr);
  120 + }
  121 +
  122 + /**
  123 + * 以级别为 e 的形式输出LOG信息和Throwable
  124 + */
  125 + public static void e(String msg, Throwable tr) {
  126 + if (mDebuggable >= LEVEL_ERROR && null != msg) {
  127 + Log.e(mTag, msg, tr);
  128 + }
  129 + }
  130 +
  131 + private static int originStackIndex = 2;
  132 +
  133 + /**
  134 + * 获取当前方法所在的文件名
  135 + *
  136 + * @return 当前方法所在的文件名
  137 + */
  138 + public static String getFileName() {
  139 + return Thread.currentThread().getStackTrace()[originStackIndex].getFileName();
  140 + }
  141 +
  142 + /**
  143 + * 获取当前方法所在的Class名
  144 + *
  145 + * @return 当前方法所在的Class名
  146 + */
  147 + public static String getClassName() {
  148 + return Thread.currentThread().getStackTrace()[originStackIndex].getClassName();
  149 + }
  150 +
  151 + /**
  152 + * 获取当前方法名
  153 + *
  154 + * @return 当前方法名
  155 + */
  156 + public static String getMethodName() {
  157 + return Thread.currentThread().getStackTrace()[originStackIndex].getMethodName();
  158 + }
  159 +
  160 + /**
  161 + * 获取当前代码执行处行数
  162 + *
  163 + * @return 当前代码执行处行数
  164 + */
  165 + public static int getLineNumber() {
  166 + return Thread.currentThread().getStackTrace()[originStackIndex].getLineNumber();
  167 + }
  168 +}
0 \ No newline at end of file 169 \ No newline at end of file
mvpsdk/src/main/java/com/share/mvpsdk/utils/MD5Utils.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/utils/MD5Utils.java
@@ -0,0 +1,38 @@ @@ -0,0 +1,38 @@
  1 +package com.share.mvpsdk.utils;
  2 +
  3 +import java.security.MessageDigest;
  4 +
  5 +/**
  6 + * Created by Horrarndoo on 2017/4/5.
  7 + * <p>
  8 + * MD5加密工具类
  9 + */
  10 +public class MD5Utils {
  11 + /*
  12 + * MD5加密,32位
  13 + */
  14 + public static String getMD5(String str) {
  15 + MessageDigest md5 = null;
  16 + try {
  17 + md5 = MessageDigest.getInstance("MD5");
  18 + } catch (Exception e) {
  19 + e.printStackTrace();
  20 + return "";
  21 + }
  22 + char[] charArray = str.toCharArray();
  23 + byte[] byteArray = new byte[charArray.length];
  24 + for (int i = 0; i < charArray.length; i++) {
  25 + byteArray[i] = (byte) charArray[i];
  26 + }
  27 + byte[] md5Bytes = md5.digest(byteArray);
  28 + StringBuffer hexValue = new StringBuffer();
  29 + for (int i = 0; i < md5Bytes.length; i++) {
  30 + int val = ((int) md5Bytes[i]) & 0xff;
  31 + if (val < 16) {
  32 + hexValue.append("0");
  33 + }
  34 + hexValue.append(Integer.toHexString(val));
  35 + }
  36 + return hexValue.toString();
  37 + }
  38 +}
0 \ No newline at end of file 39 \ No newline at end of file
mvpsdk/src/main/java/com/share/mvpsdk/utils/NavigationUtils.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/utils/NavigationUtils.java
@@ -0,0 +1,23 @@ @@ -0,0 +1,23 @@
  1 +package com.share.mvpsdk.utils;
  2 +
  3 +import android.support.design.internal.NavigationMenuView;
  4 +import android.support.design.widget.NavigationView;
  5 +
  6 +/**
  7 + * Created by Horrarndoo on 2017/12/12.
  8 + * <p>
  9 + * NavigationView utils
  10 + */
  11 +
  12 +public class NavigationUtils {
  13 +
  14 + public static void disableNavigationViewScrollbars(NavigationView navigationView) {
  15 + if (navigationView != null) {
  16 + NavigationMenuView navigationMenuView = (NavigationMenuView) navigationView
  17 + .getChildAt(0);
  18 + if (navigationMenuView != null) {
  19 + navigationMenuView.setVerticalScrollBarEnabled(false);
  20 + }
  21 + }
  22 + }
  23 +}
mvpsdk/src/main/java/com/share/mvpsdk/utils/NetworkConnectionUtils.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/utils/NetworkConnectionUtils.java
@@ -0,0 +1,236 @@ @@ -0,0 +1,236 @@
  1 +package com.share.mvpsdk.utils;
  2 +
  3 +import android.app.Activity;
  4 +import android.content.ComponentName;
  5 +import android.content.Context;
  6 +import android.content.Intent;
  7 +import android.net.ConnectivityManager;
  8 +import android.net.NetworkInfo;
  9 +import android.net.wifi.ScanResult;
  10 +import android.net.wifi.WifiConfiguration;
  11 +import android.net.wifi.WifiConfiguration.KeyMgmt;
  12 +import android.net.wifi.WifiManager;
  13 +import android.os.Build;
  14 +
  15 +import java.io.IOException;
  16 +import java.util.List;
  17 +
  18 +import static com.share.mvpsdk.utils.LogUtils.e;
  19 +
  20 +/**
  21 + * Created by Horrarndoo on 2017/8/31.
  22 + * <p>
  23 + * Wifi连接工具类
  24 + */
  25 +public class NetworkConnectionUtils {
  26 + private final static String TAG = "NetworkConnectionUtils";
  27 +
  28 + public NetworkConnectionUtils() {
  29 + }
  30 +
  31 + /**
  32 + * 连接指定
  33 + *
  34 + * @param manager
  35 + * @param wifiSSID
  36 + * @return
  37 + */
  38 + public static boolean connectToSocketWifi(WifiManager manager, String wifiSSID) {
  39 + LogUtils.i("要连接的socket wifi====>" + wifiSSID);
  40 + WifiConfiguration wifiConfiguration = new WifiConfiguration();
  41 + wifiConfiguration.SSID = "\"" + wifiSSID + "\"";
  42 + wifiConfiguration.allowedKeyManagement.set(KeyMgmt.NONE);
  43 + wifiConfiguration.wepKeys[0] = "\"" + "\""; //小米手机MIUI7/华为EMUI4.1 需要webKey
  44 +
  45 + int networkId = manager.addNetwork(wifiConfiguration);
  46 +
  47 + if (networkId != -1) {
  48 + manager.enableNetwork(networkId, true);
  49 + e("连接设备成功");
  50 + return true;
  51 + } else {
  52 + e("第一次连接失败,尝试第二次。");
  53 + WifiConfiguration wifiConfiguration2 = new WifiConfiguration();
  54 + wifiConfiguration2.SSID = "\"" + wifiSSID + "\"";
  55 + //wifiConfiguration.wepKeys[0] = "\"" + "\"";//去掉webKey //小米手机MIUI8不能有webKey
  56 + wifiConfiguration2.allowedKeyManagement.set(KeyMgmt.NONE);
  57 + networkId = manager.addNetwork(wifiConfiguration2);
  58 + if (networkId != -1) {
  59 + manager.enableNetwork(networkId, true);
  60 + e("连接设备成功");
  61 + return true;
  62 + }
  63 + e("连接设备失败");
  64 + }
  65 + return false;
  66 + }
  67 +
  68 + /**
  69 + * 获取要连接的wifi节点各个配置选项的加密类型
  70 + *
  71 + * @param ssid
  72 + * @return wifiConfiguration
  73 + */
  74 + public static WifiConfiguration getWifiConfiguration(WifiManager manager, String ssid, String
  75 + password) {
  76 + WifiConfiguration wifiConfiguration = new WifiConfiguration();
  77 + wifiConfiguration.SSID = "\"" + ssid + "\"";
  78 +
  79 + List<ScanResult> list = manager.getScanResults();
  80 + for (ScanResult scResult : list) {
  81 + if (ssid.equals(scResult.SSID)) {
  82 + String capabilities = scResult.capabilities;
  83 + LogUtils.i("capabilities=" + capabilities);
  84 + if (capabilities.contains("WEP") || capabilities.contains("wep")) {
  85 + wifiConfiguration.allowedKeyManagement.set(KeyMgmt.WPA_EAP);
  86 + wifiConfiguration.preSharedKey = "\"" + password + "\"";
  87 + LogUtils.i("wep");
  88 + } else if (capabilities.contains("WPA") || capabilities.contains("wpa")) {
  89 + wifiConfiguration.allowedKeyManagement.set(KeyMgmt.WPA_PSK);
  90 + wifiConfiguration.preSharedKey = "\"" + password + "\"";
  91 + LogUtils.i("wpa");
  92 + } else {
  93 + wifiConfiguration.allowedKeyManagement.set(KeyMgmt.NONE);
  94 + LogUtils.i("none");
  95 + }
  96 + }
  97 + }
  98 + return wifiConfiguration;
  99 + }
  100 +
  101 + /**
  102 + * 给温控器成功发送联网命令后,连接温控器连接的wifi节点
  103 + *
  104 + * @param context 上下文对象
  105 + * @param ssid ssid
  106 + * @param password 密码
  107 + */
  108 + public static void connectWifiSSID(Context context, WifiManager manager, String ssid, String
  109 + password) {
  110 + e("reSetNetwork----------连接设备连入的路由---" + ssid);
  111 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
  112 + e("当前手机系统>=Android6.0,采取兼容模式");
  113 + new WifiAutoConnectManager(manager).connect(ssid, password, WifiAutoConnectManager
  114 + .getCipherType(context, ssid));
  115 + } else {
  116 + int networkId = manager.addNetwork(getWifiConfiguration(manager, ssid, password));
  117 + if (networkId != -1) {
  118 + manager.enableNetwork(networkId, true);
  119 + }
  120 + }
  121 + }
  122 +
  123 + /**
  124 + * 格式化RouterSSID
  125 + *
  126 + * @param strRouterSSID 要格式化的当前连接的路由ssid
  127 + * @return 去除"\"后的RouterSSID字符串
  128 + */
  129 + public static String formatRouterSSID(String strRouterSSID) {
  130 + //e("formate routerSSID before---" + strRouterSSID);
  131 + if (strRouterSSID.contains("\"")) {
  132 + strRouterSSID = strRouterSSID.replaceAll("\"", "");
  133 + //e("formate routerSSID after---" + strRouterSSID);
  134 + }
  135 + return strRouterSSID;
  136 + }
  137 +
  138 + /**
  139 + * Ping
  140 + * 用于确定手机是否已经连接上指定设备ip地址
  141 + */
  142 + public static boolean pingTest(String IPOrDomainName) {
  143 +
  144 + boolean isSuccess = false;
  145 + int status;
  146 + String result = "failed";
  147 + Process p;
  148 + try {
  149 + p = Runtime.getRuntime().exec("ping -c 1 " + IPOrDomainName);//
  150 + // m_strForNetAddress是输入的网址或者Ip地址
  151 + status = p.waitFor();// status 只能获取是否成功,无法获取更多的信息
  152 +
  153 + if (status == 0) {
  154 + result = "success";
  155 + isSuccess = true;
  156 + }
  157 +
  158 + } catch (IOException | InterruptedException e) {
  159 + e(e);
  160 + }
  161 + LogUtils.d("Ping result = " + result);
  162 + return isSuccess;
  163 + }
  164 +
  165 + /**
  166 + * 判断网络是否连接
  167 + */
  168 + public static boolean isConnected(Context context) {
  169 + ConnectivityManager cm = (ConnectivityManager)
  170 + context.getSystemService(Context.CONNECTIVITY_SERVICE);
  171 +
  172 + if (null == cm) {
  173 + return false;
  174 + }
  175 +
  176 + NetworkInfo info = cm.getActiveNetworkInfo();
  177 + if (null != info && info.isConnected()) {
  178 + if (info.getState() == NetworkInfo.State.CONNECTED) {
  179 + return true;
  180 + }
  181 + }
  182 + return false;
  183 + }
  184 +
  185 + /**
  186 + * 判断是否有网络
  187 + *
  188 + * @return 返回值
  189 + */
  190 + public static boolean isNetworkConnected(Context context) {
  191 + if (context != null) {
  192 + ConnectivityManager mConnectivityManager = (ConnectivityManager) context
  193 + .getSystemService(Context.CONNECTIVITY_SERVICE);
  194 + NetworkInfo mNetworkInfo = mConnectivityManager.getActiveNetworkInfo();
  195 +
  196 + if (mNetworkInfo != null) {
  197 + return mNetworkInfo.isAvailable();
  198 + }
  199 + }
  200 + return false;
  201 + }
  202 +
  203 + /**
  204 + * 判断是否是wifi连接
  205 + */
  206 + public static boolean isWifi(Context context) {
  207 + ConnectivityManager cm = (ConnectivityManager)
  208 + context.getSystemService(Context.CONNECTIVITY_SERVICE);
  209 +
  210 + if (null == cm) {
  211 + return false;
  212 + }
  213 +
  214 + NetworkInfo info = cm.getActiveNetworkInfo();
  215 + if (null != info) {
  216 + if (info.getType() == ConnectivityManager.TYPE_WIFI) {
  217 + return true;
  218 + }
  219 + }
  220 + return false;
  221 +
  222 + }
  223 +
  224 +
  225 + /**
  226 + * 打开网络设置界面
  227 + */
  228 + public static void openSetting(Activity activity, int requestCode) {
  229 + Intent intent = new Intent("/");
  230 + ComponentName cm = new ComponentName("com.android.settings",
  231 + "com.android.settings.WirelessSettings");
  232 + intent.setComponent(cm);
  233 + intent.setAction(Intent.ACTION_VIEW);
  234 + activity.startActivityForResult(intent, requestCode);
  235 + }
  236 +}
mvpsdk/src/main/java/com/share/mvpsdk/utils/PermissionUtils.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/utils/PermissionUtils.java
@@ -0,0 +1,323 @@ @@ -0,0 +1,323 @@
  1 +package com.share.mvpsdk.utils;
  2 +
  3 +import android.Manifest;
  4 +import android.app.Activity;
  5 +import android.app.AlertDialog;
  6 +import android.content.DialogInterface;
  7 +import android.content.Intent;
  8 +import android.content.pm.PackageManager;
  9 +import android.net.Uri;
  10 +import android.provider.Settings;
  11 +import android.support.annotation.NonNull;
  12 +import android.support.v4.app.ActivityCompat;
  13 +import android.util.Log;
  14 +import android.widget.Toast;
  15 +
  16 +
  17 +import com.share.mvpsdk.R;
  18 +
  19 +import java.util.ArrayList;
  20 +import java.util.HashMap;
  21 +import java.util.List;
  22 +import java.util.Map;
  23 +
  24 +/**
  25 + * Created by ToaHanDong on 2017/11/3.
  26 + */
  27 +
  28 +public class PermissionUtils {
  29 + private static final String TAG = PermissionUtils.class.getSimpleName();
  30 + public static final int CODE_RECORD_AUDIO = 0;
  31 + public static final int CODE_GET_ACCOUNTS = 1;
  32 + public static final int CODE_READ_PHONE_STATE = 2;
  33 + public static final int CODE_CALL_PHONE = 3;
  34 + public static final int CODE_CAMERA = 4;
  35 + public static final int CODE_ACCESS_FINE_LOCATION = 5;
  36 + public static final int CODE_ACCESS_COARSE_LOCATION = 6;
  37 + public static final int CODE_READ_EXTERNAL_STORAGE = 7;
  38 + public static final int CODE_WRITE_EXTERNAL_STORAGE = 8;
  39 + public static final int CODE_MULTI_PERMISSION = 100;
  40 +
  41 + //com.huawei.permission.sec.PERMISSION_MDM_SDCARD
  42 +// public static final String PERMISSION_MDM_SDCARD = "PERMISSION_MDM_SDCARD";
  43 + public static final String PERMISSION_RECORD_AUDIO = Manifest.permission.RECORD_AUDIO;
  44 + public static final String PERMISSION_GET_ACCOUNTS = Manifest.permission.GET_ACCOUNTS;
  45 + public static final String PERMISSION_READ_PHONE_STATE = Manifest.permission.READ_PHONE_STATE;
  46 + public static final String PERMISSION_CALL_PHONE = Manifest.permission.CALL_PHONE;
  47 + public static final String PERMISSION_CAMERA = Manifest.permission.CAMERA;
  48 + public static final String PERMISSION_ACCESS_FINE_LOCATION = Manifest.permission.ACCESS_FINE_LOCATION;
  49 + public static final String PERMISSION_ACCESS_COARSE_LOCATION = Manifest.permission.ACCESS_COARSE_LOCATION;
  50 + public static final String PERMISSION_READ_EXTERNAL_STORAGE = Manifest.permission.READ_EXTERNAL_STORAGE;
  51 + public static final String PERMISSION_WRITE_EXTERNAL_STORAGE = Manifest.permission.WRITE_EXTERNAL_STORAGE;
  52 +
  53 + private static final String[] requestPermissions = {
  54 + PERMISSION_RECORD_AUDIO,
  55 + PERMISSION_GET_ACCOUNTS,
  56 + PERMISSION_READ_PHONE_STATE,
  57 + PERMISSION_CALL_PHONE,
  58 + PERMISSION_CAMERA,
  59 + PERMISSION_ACCESS_FINE_LOCATION,
  60 + PERMISSION_ACCESS_COARSE_LOCATION,
  61 + PERMISSION_READ_EXTERNAL_STORAGE,
  62 + PERMISSION_WRITE_EXTERNAL_STORAGE
  63 +// PERMISSION_MDM_SDCARD
  64 + };
  65 +
  66 + public interface PermissionGrant {
  67 + void onPermissionGranted(int requestCode);
  68 + }
  69 +
  70 + /**
  71 + * Requests permission.
  72 + *
  73 + * @param activity
  74 + * @param requestCode request code, e.g. if you need request CAMERA permission,parameters is PermissionUtils.CODE_CAMERA
  75 + */
  76 + public static void requestPermission(final Activity activity, final int requestCode, PermissionGrant permissionGrant) {
  77 + if (activity == null) {
  78 + return;
  79 + }
  80 +
  81 + Log.i(TAG, "requestPermission requestCode:" + requestCode);
  82 + if (requestCode < 0 || requestCode >= requestPermissions.length) {
  83 + Log.w(TAG, "requestPermission illegal requestCode:" + requestCode);
  84 + return;
  85 + }
  86 +
  87 + final String requestPermission = requestPermissions[requestCode];
  88 +
  89 + //如果是6.0以下的手机,ActivityCompat.checkSelfPermission()会始终等于PERMISSION_GRANTED,
  90 + // 但是,如果用户关闭了你申请的权限,ActivityCompat.checkSelfPermission(),会导致程序崩溃(java.lang.RuntimeException: Unknown exception code: 1 msg null),
  91 + // 你可以使用try{}catch(){},处理异常,也可以在这个地方,低于23就什么都不做,
  92 + // 个人建议try{}catch(){}单独处理,提示用户开启权限。
  93 +// if (Build.VERSION.SDK_INT < 23) {
  94 +// return;
  95 +// }
  96 +
  97 + int checkSelfPermission;
  98 + try {
  99 + checkSelfPermission = ActivityCompat.checkSelfPermission(activity, requestPermission);
  100 + } catch (RuntimeException e) {
  101 +// Toast.makeText(activity, "please open this permission", Toast.LENGTH_SHORT)
  102 +// .show();
  103 + Log.e(TAG, "RuntimeException:" + e.getMessage());
  104 + return;
  105 + }
  106 +
  107 + if (checkSelfPermission != PackageManager.PERMISSION_GRANTED) {
  108 + Log.i(TAG, "ActivityCompat.checkSelfPermission != PackageManager.PERMISSION_GRANTED");
  109 +
  110 +
  111 + if (ActivityCompat.shouldShowRequestPermissionRationale(activity, requestPermission)) {
  112 + Log.i(TAG, "requestPermission shouldShowRequestPermissionRationale");
  113 + shouldShowRationale(activity, requestCode, requestPermission);
  114 +
  115 + } else {
  116 + Log.d(TAG, "requestCameraPermission else");
  117 + ActivityCompat.requestPermissions(activity, new String[]{requestPermission}, requestCode);
  118 + }
  119 +
  120 + } else {
  121 + Log.d(TAG, "ActivityCompat.checkSelfPermission ==== PackageManager.PERMISSION_GRANTED");
  122 +// Toast.makeText(activity, "opened:" + requestPermissions[requestCode], Toast.LENGTH_SHORT).show();
  123 + permissionGrant.onPermissionGranted(requestCode);
  124 + }
  125 + }
  126 +
  127 + private static void requestMultiResult(Activity activity, String[] permissions, int[] grantResults, PermissionGrant permissionGrant) {
  128 +
  129 + if (activity == null) {
  130 + return;
  131 + }
  132 +
  133 + //TODO
  134 + Log.d(TAG, "onRequestPermissionsResult permissions length:" + permissions.length);
  135 + Map<String, Integer> perms = new HashMap<>();
  136 +
  137 + ArrayList<String> notGranted = new ArrayList<>();
  138 + for (int i = 0; i < permissions.length; i++) {
  139 + Log.d(TAG, "permissions: [i]:" + i + ", permissions[i]" + permissions[i] + ",grantResults[i]:" + grantResults[i]);
  140 + perms.put(permissions[i], grantResults[i]);
  141 + if (grantResults[i] != PackageManager.PERMISSION_GRANTED) {
  142 + notGranted.add(permissions[i]);
  143 + }
  144 + }
  145 +
  146 + if (notGranted.size() == 0) {
  147 +// Toast.makeText(activity, "all permission success" + notGranted, Toast.LENGTH_SHORT)
  148 +// .show();
  149 + permissionGrant.onPermissionGranted(CODE_MULTI_PERMISSION);
  150 + } else {
  151 + openSettingActivity(activity, "those permission need granted!");
  152 + }
  153 +
  154 + }
  155 +
  156 +
  157 + /**
  158 + * 一次申请多个权限
  159 + */
  160 + public static void requestMultiPermissions(final Activity activity, PermissionGrant grant) {
  161 +
  162 + final List<String> permissionsList = getNoGrantedPermission(activity, false);
  163 + final List<String> shouldRationalePermissionsList = getNoGrantedPermission(activity, true);
  164 +
  165 + //TODO checkSelfPermission
  166 + if (permissionsList == null || shouldRationalePermissionsList == null) {
  167 + return;
  168 + }
  169 + Log.d(TAG, "requestMultiPermissions permissionsList:" + permissionsList.size() + ",shouldRationalePermissionsList:" + shouldRationalePermissionsList.size());
  170 +
  171 + if (permissionsList.size() > 0) {
  172 + ActivityCompat.requestPermissions(activity, permissionsList.toArray(new String[permissionsList.size()]),
  173 + CODE_MULTI_PERMISSION);
  174 + Log.d(TAG, "showMessageOKCancel requestPermissions");
  175 +
  176 + } else if (shouldRationalePermissionsList.size() > 0) {
  177 + showMessageOKCancel(activity, "should open those permission",
  178 + new DialogInterface.OnClickListener() {
  179 + @Override
  180 + public void onClick(DialogInterface dialog, int which) {
  181 + ActivityCompat.requestPermissions(activity, shouldRationalePermissionsList.toArray(new String[shouldRationalePermissionsList.size()]),
  182 + CODE_MULTI_PERMISSION);
  183 + Log.d(TAG, "showMessageOKCancel requestPermissions");
  184 + }
  185 + });
  186 + } else {
  187 + grant.onPermissionGranted(CODE_MULTI_PERMISSION);
  188 + }
  189 +
  190 + }
  191 +
  192 +
  193 + private static void shouldShowRationale(final Activity activity, final int requestCode, final String requestPermission) {
  194 + //TODO
  195 + String[] permissionsHint = activity.getResources().getStringArray(R.array.permissions);
  196 + showMessageOKCancel(activity, "Rationale: " + permissionsHint[requestCode], new DialogInterface.OnClickListener() {
  197 + @Override
  198 + public void onClick(DialogInterface dialog, int which) {
  199 + ActivityCompat.requestPermissions(activity,
  200 + new String[]{requestPermission},
  201 + requestCode);
  202 + Log.d(TAG, "showMessageOKCancel requestPermissions:" + requestPermission);
  203 + }
  204 + });
  205 + }
  206 +
  207 + private static void showMessageOKCancel(final Activity context, String message, DialogInterface.OnClickListener okListener) {
  208 + new AlertDialog.Builder(context)
  209 + .setMessage(message)
  210 + .setPositiveButton("OK", okListener)
  211 + .setNegativeButton("Cancel", null)
  212 + .create()
  213 + .show();
  214 +
  215 + }
  216 +
  217 + /**
  218 + * @param activity
  219 + * @param requestCode Need consistent with requestPermission
  220 + * @param permissions
  221 + * @param grantResults
  222 + */
  223 + public static void requestPermissionsResult(final Activity activity, final int requestCode, @NonNull String[] permissions,
  224 + @NonNull int[] grantResults, PermissionGrant permissionGrant) {
  225 +
  226 + if (activity == null) {
  227 + return;
  228 + }
  229 + Log.d(TAG, "requestPermissionsResult requestCode:" + requestCode);
  230 +
  231 + if (requestCode == CODE_MULTI_PERMISSION) {
  232 + requestMultiResult(activity, permissions, grantResults, permissionGrant);
  233 + return;
  234 + }
  235 +
  236 + if (requestCode < 0 || requestCode >= requestPermissions.length) {
  237 + Log.w(TAG, "requestPermissionsResult illegal requestCode:" + requestCode);
  238 +// Toast.makeText(activity, "illegal requestCode:" + requestCode, Toast.LENGTH_SHORT).show();
  239 + return;
  240 + }
  241 +
  242 + Log.i(TAG, "onRequestPermissionsResult requestCode:" + requestCode + ",permissions:" + permissions.toString()
  243 + + ",grantResults:" + grantResults.toString() + ",length:" + grantResults.length);
  244 +
  245 + if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
  246 + Log.i(TAG, "onRequestPermissionsResult PERMISSION_GRANTED");
  247 + //TODO success, do something, can use callback
  248 + permissionGrant.onPermissionGranted(requestCode);
  249 +
  250 + } else {
  251 + //TODO hint user this permission function
  252 + Log.i(TAG, "onRequestPermissionsResult PERMISSION NOT GRANTED");
  253 + //TODO
  254 + String[] permissionsHint = activity.getResources().getStringArray(R.array.permissions);
  255 + openSettingActivity(activity, "Result" + permissionsHint[requestCode]);
  256 + }
  257 +
  258 + }
  259 +
  260 + private static void openSettingActivity(final Activity activity, String message) {
  261 +
  262 + showMessageOKCancel(activity, message, new DialogInterface.OnClickListener() {
  263 + @Override
  264 + public void onClick(DialogInterface dialog, int which) {
  265 + Intent intent = new Intent();
  266 + intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
  267 + Log.d(TAG, "getPackageName(): " + activity.getPackageName());
  268 + Uri uri = Uri.fromParts("package", activity.getPackageName(), null);
  269 + intent.setData(uri);
  270 + activity.startActivity(intent);
  271 + }
  272 + });
  273 + }
  274 +
  275 +
  276 + /**
  277 + * @param activity
  278 + * @param isShouldRationale true: return no granted and shouldShowRequestPermissionRationale permissions, false:return no granted and !shouldShowRequestPermissionRationale
  279 + * @return
  280 + */
  281 + public static ArrayList<String> getNoGrantedPermission(Activity activity, boolean isShouldRationale) {
  282 +
  283 + ArrayList<String> permissions = new ArrayList<>();
  284 +
  285 + for (int i = 0; i < requestPermissions.length; i++) {
  286 + String requestPermission = requestPermissions[i];
  287 +
  288 +
  289 + //TODO checkSelfPermission
  290 + int checkSelfPermission = -1;
  291 + try {
  292 + checkSelfPermission = ActivityCompat.checkSelfPermission(activity, requestPermission);
  293 + } catch (RuntimeException e) {
  294 + Toast.makeText(activity, "please open those permission", Toast.LENGTH_SHORT)
  295 + .show();
  296 + Log.e(TAG, "RuntimeException:" + e.getMessage());
  297 + return null;
  298 + }
  299 +
  300 + if (checkSelfPermission != PackageManager.PERMISSION_GRANTED) {
  301 + Log.i(TAG, "getNoGrantedPermission ActivityCompat.checkSelfPermission != PackageManager.PERMISSION_GRANTED:" + requestPermission);
  302 +
  303 + if (ActivityCompat.shouldShowRequestPermissionRationale(activity, requestPermission)) {
  304 + Log.d(TAG, "shouldShowRequestPermissionRationale if");
  305 + if (isShouldRationale) {
  306 + permissions.add(requestPermission);
  307 + }
  308 +
  309 + } else {
  310 +
  311 + if (!isShouldRationale) {
  312 + permissions.add(requestPermission);
  313 + }
  314 + Log.d(TAG, "shouldShowRequestPermissionRationale else");
  315 + }
  316 +
  317 + }
  318 + }
  319 +
  320 + return permissions;
  321 + }
  322 +
  323 +}
mvpsdk/src/main/java/com/share/mvpsdk/utils/ResourcesUtils.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/utils/ResourcesUtils.java
@@ -0,0 +1,83 @@ @@ -0,0 +1,83 @@
  1 +package com.share.mvpsdk.utils;
  2 +
  3 +import android.content.res.ColorStateList;
  4 +import android.graphics.drawable.Drawable;
  5 +import android.view.View;
  6 +
  7 +/**
  8 + * Created by Horrarndoo on 2017/9/1.
  9 + * <p>
  10 + * 资源工具类-加载资源文件
  11 + */
  12 +
  13 +public class ResourcesUtils {
  14 + /**
  15 + * 获取strings.xml资源文件字符串
  16 + *
  17 + * @param id 资源文件id
  18 + * @return 资源文件对应字符串
  19 + */
  20 + public static String getString(int id) {
  21 + return AppUtils.getContext().getResources().getString(id);
  22 + }
  23 +
  24 + /**
  25 + * 获取strings.xml资源文件字符串数组
  26 + *
  27 + * @param id 资源文件id
  28 + * @return 资源文件对应字符串数组
  29 + */
  30 + public static String[] getStringArray(int id) {
  31 + return AppUtils.getContext().getResources().getStringArray(id);
  32 + }
  33 +
  34 + /**
  35 + * 获取drawable资源文件图片
  36 + *
  37 + * @param id 资源文件id
  38 + * @return 资源文件对应图片
  39 + */
  40 + public static Drawable getDrawable(int id) {
  41 + return AppUtils.getContext().getResources().getDrawable(id);
  42 + }
  43 +
  44 + /**
  45 + * 获取colors.xml资源文件颜色
  46 + *
  47 + * @param id 资源文件id
  48 + * @return 资源文件对应颜色值
  49 + */
  50 + public static int getColor(int id) {
  51 + return AppUtils.getContext().getResources().getColor(id);
  52 + }
  53 +
  54 + /**
  55 + * 获取颜色的状态选择器
  56 + *
  57 + * @param id 资源文件id
  58 + * @return 资源文件对应颜色状态
  59 + */
  60 + public static ColorStateList getColorStateList(int id) {
  61 + return AppUtils.getContext().getResources().getColorStateList(id);
  62 + }
  63 +
  64 + /**
  65 + * 获取dimens资源文件中具体像素值
  66 + *
  67 + * @param id 资源文件id
  68 + * @return 资源文件对应像素值
  69 + */
  70 + public static int getDimen(int id) {
  71 + return AppUtils.getContext().getResources().getDimensionPixelSize(id);// 返回具体像素值
  72 + }
  73 +
  74 + /**
  75 + * 加载布局文件
  76 + *
  77 + * @param id 布局文件id
  78 + * @return 布局view
  79 + */
  80 + public static View inflate(int id) {
  81 + return View.inflate(AppUtils.getContext(), id, null);
  82 + }
  83 +}
mvpsdk/src/main/java/com/share/mvpsdk/utils/ScreenUtils.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/utils/ScreenUtils.java
@@ -0,0 +1,151 @@ @@ -0,0 +1,151 @@
  1 +package com.share.mvpsdk.utils;
  2 +
  3 +import android.app.Activity;
  4 +import android.app.ActivityGroup;
  5 +import android.content.Context;
  6 +import android.graphics.Bitmap;
  7 +import android.graphics.Rect;
  8 +import android.os.Build;
  9 +import android.support.v7.app.AppCompatActivity;
  10 +import android.util.Log;
  11 +import android.util.TypedValue;
  12 +import android.view.Display;
  13 +import android.view.View;
  14 +import android.view.ViewGroup;
  15 +import android.view.WindowManager;
  16 +
  17 +/**
  18 + * Created by Horrarndoo on 2017/9/7.
  19 + * <p>
  20 + * 屏幕相关工具类
  21 + */
  22 +
  23 +public class ScreenUtils {
  24 + private ScreenUtils() {
  25 + /* cannot be instantiated */
  26 + throw new UnsupportedOperationException("cannot be instantiated");
  27 + }
  28 +
  29 +
  30 + private static int mStatusHeight = -1;
  31 +
  32 + /**
  33 + * 获取屏幕的宽度
  34 + *
  35 + * @param context
  36 + * @return
  37 + */
  38 + public static int getScreenWidth(Context context) {
  39 + WindowManager manager = (WindowManager) context
  40 + .getSystemService(Context.WINDOW_SERVICE);
  41 + Display display = manager.getDefaultDisplay();
  42 + return display.getWidth();
  43 + }
  44 +
  45 + /**
  46 + * 获取屏幕的高度
  47 + *
  48 + * @param context
  49 + * @return
  50 + */
  51 + public static int getScreenHeight(Context context) {
  52 + WindowManager manager = (WindowManager) context
  53 + .getSystemService(Context.WINDOW_SERVICE);
  54 + Display display = manager.getDefaultDisplay();
  55 + return display.getHeight();
  56 + }
  57 +
  58 + /**
  59 + * 获取当前屏幕截图,不包含状态栏
  60 + *
  61 + * @param activity
  62 + * @return bp
  63 + */
  64 + public static Bitmap snapShotWithoutStatusBar(Activity activity) {
  65 + View view = activity.getWindow().getDecorView();
  66 + view.setDrawingCacheEnabled(true);
  67 + view.buildDrawingCache();
  68 + Bitmap bmp = view.getDrawingCache();
  69 + if (bmp == null) {
  70 + return null;
  71 + }
  72 + Rect frame = new Rect();
  73 + activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);
  74 + int statusBarHeight = frame.top;
  75 + Bitmap bp = Bitmap.createBitmap(bmp, 0, statusBarHeight, bmp.getWidth(), bmp.getHeight()
  76 + - statusBarHeight);
  77 + view.destroyDrawingCache();
  78 + view.setDrawingCacheEnabled(false);
  79 +
  80 + return bp;
  81 + }
  82 +
  83 + /**
  84 + * 获取actionbar的像素高度,默认使用android官方兼容包做actionbar兼容
  85 + *
  86 + * @return
  87 + */
  88 + public static int getActionBarHeight(Context context) {
  89 + int actionBarHeight = 0;
  90 + if (context instanceof AppCompatActivity && ((AppCompatActivity) context)
  91 + .getSupportActionBar() != null) {
  92 + Log.d("isAppCompatActivity", "==AppCompatActivity");
  93 + actionBarHeight = ((AppCompatActivity) context).getSupportActionBar().getHeight();
  94 + } else if (context instanceof Activity && ((Activity) context).getActionBar() != null) {
  95 + Log.d("isActivity", "==Activity");
  96 + actionBarHeight = ((Activity) context).getActionBar().getHeight();
  97 + } else if (context instanceof ActivityGroup) {
  98 + Log.d("ActivityGroup", "==ActivityGroup");
  99 + if (((ActivityGroup) context).getCurrentActivity() instanceof AppCompatActivity && (
  100 + (AppCompatActivity) ((ActivityGroup) context).getCurrentActivity())
  101 + .getSupportActionBar() != null) {
  102 + actionBarHeight = ((AppCompatActivity) ((ActivityGroup) context)
  103 + .getCurrentActivity()).getSupportActionBar().getHeight();
  104 + } else if (((ActivityGroup) context).getCurrentActivity() instanceof Activity && (
  105 + (Activity) ((ActivityGroup) context).getCurrentActivity()).getActionBar() !=
  106 + null) {
  107 + actionBarHeight = ((Activity) ((ActivityGroup) context).getCurrentActivity())
  108 + .getActionBar().getHeight();
  109 + }
  110 + }
  111 + if (actionBarHeight != 0)
  112 + return actionBarHeight;
  113 + final TypedValue tv = new TypedValue();
  114 + if (context.getTheme().resolveAttribute(android.support.v7.appcompat.R.attr
  115 + .actionBarSize, tv, true)) {
  116 + if (context.getTheme().resolveAttribute(android.support.v7.appcompat.R.attr
  117 + .actionBarSize, tv, true))
  118 + actionBarHeight = TypedValue.complexToDimensionPixelSize(tv.data, context
  119 + .getResources().getDisplayMetrics());
  120 + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
  121 + if (context.getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true))
  122 + actionBarHeight = TypedValue.complexToDimensionPixelSize(tv.data, context
  123 + .getResources().getDisplayMetrics());
  124 + } else {
  125 + if (context.getTheme().resolveAttribute(android.support.v7.appcompat.R.attr
  126 + .actionBarSize, tv, true))
  127 + actionBarHeight = TypedValue.complexToDimensionPixelSize(tv.data, context
  128 + .getResources().getDisplayMetrics());
  129 + }
  130 + Log.d("actionBarHeight", "====" + actionBarHeight);
  131 + return actionBarHeight;
  132 + }
  133 +
  134 +
  135 + /**
  136 + * 设置view margin
  137 + *
  138 + * @param v
  139 + * @param l
  140 + * @param t
  141 + * @param r
  142 + * @param b
  143 + */
  144 + public static void setMargins(View v, int l, int t, int r, int b) {
  145 + if (v.getLayoutParams() instanceof ViewGroup.MarginLayoutParams) {
  146 + ViewGroup.MarginLayoutParams p = (ViewGroup.MarginLayoutParams) v.getLayoutParams();
  147 + p.setMargins(l, t, r, b);
  148 + v.requestLayout();
  149 + }
  150 + }
  151 +}
mvpsdk/src/main/java/com/share/mvpsdk/utils/SnackbarUtils.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/utils/SnackbarUtils.java
@@ -0,0 +1,189 @@ @@ -0,0 +1,189 @@
  1 +package com.share.mvpsdk.utils;
  2 +
  3 +import android.graphics.Color;
  4 +import android.support.design.widget.Snackbar;
  5 +import android.view.Gravity;
  6 +import android.view.LayoutInflater;
  7 +import android.view.View;
  8 +import android.widget.LinearLayout;
  9 +import android.widget.TextView;
  10 +
  11 +import com.share.mvpsdk.R;
  12 +
  13 +
  14 +/**
  15 + * Created by Horrarndoo on 2017/8/31.
  16 + * <p>
  17 + * Snackbar工具类
  18 + */
  19 +public class SnackbarUtils {
  20 +
  21 + public static final int Info = 1;
  22 + public static final int Confirm = 2;
  23 + public static final int Warning = 3;
  24 + public static final int Alert = 4;
  25 +
  26 +
  27 + public static int red = 0xfff44336;
  28 + public static int green = 0xff4caf50;
  29 + public static int blue = 0xff2195f3;
  30 + public static int orange = 0xffffc107;
  31 +
  32 + /**
  33 + * 短显示Snackbar,自定义颜色
  34 + *
  35 + * @param view
  36 + * @param message
  37 + * @param messageColor
  38 + * @param backgroundColor
  39 + * @return
  40 + */
  41 + public static Snackbar getShort(View view, String message, int messageColor, int
  42 + backgroundColor) {
  43 + Snackbar snackbar = Snackbar.make(view, message, Snackbar.LENGTH_SHORT);
  44 + setSnackbarColor(snackbar, messageColor, backgroundColor);
  45 + return snackbar;
  46 + }
  47 +
  48 + /**
  49 + * 长显示Snackbar,自定义颜色
  50 + *
  51 + * @param view
  52 + * @param message
  53 + * @param messageColor
  54 + * @param backgroundColor
  55 + * @return
  56 + */
  57 + public static Snackbar getLong(View view, String message, int messageColor, int
  58 + backgroundColor) {
  59 + Snackbar snackbar = Snackbar.make(view, message, Snackbar.LENGTH_LONG);
  60 + setSnackbarColor(snackbar, messageColor, backgroundColor);
  61 + return snackbar;
  62 + }
  63 +
  64 + /**
  65 + * 自定义时常显示Snackbar,自定义颜色
  66 + *
  67 + * @param view
  68 + * @param message
  69 + * @param messageColor
  70 + * @param backgroundColor
  71 + * @return
  72 + */
  73 + public static Snackbar getIndefinite(View view, String message, int duration, int
  74 + messageColor, int backgroundColor) {
  75 + Snackbar snackbar = Snackbar.make(view, message, Snackbar.LENGTH_INDEFINITE).setDuration
  76 + (duration);
  77 + setSnackbarColor(snackbar, messageColor, backgroundColor);
  78 + return snackbar;
  79 + }
  80 +
  81 + /**
  82 + * 短显示Snackbar,可选预设类型
  83 + *
  84 + * @param view
  85 + * @param message
  86 + * @param type
  87 + * @return
  88 + */
  89 + public static Snackbar getShort(View view, String message, int type) {
  90 + Snackbar snackbar = Snackbar.make(view, message, Snackbar.LENGTH_SHORT);
  91 + switchType(snackbar, type);
  92 + return snackbar;
  93 + }
  94 +
  95 + /**
  96 + * 长显示Snackbar,可选预设类型
  97 + *
  98 + * @param view
  99 + * @param message
  100 + * @param type
  101 + * @return
  102 + */
  103 + public static Snackbar getLong(View view, String message, int type) {
  104 + Snackbar snackbar = Snackbar.make(view, message, Snackbar.LENGTH_LONG);
  105 + switchType(snackbar, type);
  106 + return snackbar;
  107 + }
  108 +
  109 + /**
  110 + * 自定义时常显示Snackbar,可选预设类型
  111 + *
  112 + * @param view
  113 + * @param message
  114 + * @param type
  115 + * @return
  116 + */
  117 + public static Snackbar getIndefinite(View view, String message, int duration, int type) {
  118 + Snackbar snackbar = Snackbar.make(view, message, Snackbar.LENGTH_INDEFINITE).setDuration
  119 + (duration);
  120 + switchType(snackbar, type);
  121 + return snackbar;
  122 + }
  123 +
  124 + //选择预设类型
  125 + private static void switchType(Snackbar snackbar, int type) {
  126 + switch (type) {
  127 + case Info:
  128 + setSnackbarColor(snackbar, blue);
  129 + break;
  130 + case Confirm:
  131 + setSnackbarColor(snackbar, green);
  132 + break;
  133 + case Warning:
  134 + setSnackbarColor(snackbar, orange);
  135 + break;
  136 + case Alert:
  137 + setSnackbarColor(snackbar, Color.YELLOW, red);
  138 + break;
  139 + }
  140 + }
  141 +
  142 + /**
  143 + * 设置Snackbar背景颜色
  144 + *
  145 + * @param snackbar
  146 + * @param backgroundColor
  147 + */
  148 + public static void setSnackbarColor(Snackbar snackbar, int backgroundColor) {
  149 + View view = snackbar.getView();
  150 + if (view != null) {
  151 + view.setBackgroundColor(backgroundColor);
  152 + }
  153 + }
  154 +
  155 + /**
  156 + * 设置Snackbar文字和背景颜色
  157 + *
  158 + * @param snackbar
  159 + * @param messageColor
  160 + * @param backgroundColor
  161 + */
  162 + public static void setSnackbarColor(Snackbar snackbar, int messageColor, int backgroundColor) {
  163 + View view = snackbar.getView();
  164 + if (view != null) {
  165 + view.setBackgroundColor(backgroundColor);
  166 + ((TextView) view.findViewById(R.id.snackbar_text)).setTextColor(messageColor);
  167 + }
  168 + }
  169 +
  170 + /**
  171 + * 向Snackbar中添加view
  172 + *
  173 + * @param snackbar
  174 + * @param layoutId
  175 + * @param index 新加布局在Snackbar中的位置
  176 + */
  177 + public static void addView(Snackbar snackbar, int layoutId, int index) {
  178 + View snackbarview = snackbar.getView();
  179 + Snackbar.SnackbarLayout snackbarLayout = (Snackbar.SnackbarLayout) snackbarview;
  180 +
  181 + View add_view = LayoutInflater.from(snackbarview.getContext()).inflate(layoutId, null);
  182 +
  183 + LinearLayout.LayoutParams p = new LinearLayout.LayoutParams(LinearLayout.LayoutParams
  184 + .WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
  185 + p.gravity = Gravity.CENTER_VERTICAL;
  186 +
  187 + snackbarLayout.addView(add_view, index, p);
  188 + }
  189 +}
0 \ No newline at end of file 190 \ No newline at end of file
mvpsdk/src/main/java/com/share/mvpsdk/utils/SpUtils.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/utils/SpUtils.java
@@ -0,0 +1,212 @@ @@ -0,0 +1,212 @@
  1 +package com.share.mvpsdk.utils;
  2 +
  3 +
  4 +import android.content.Context;
  5 +import android.content.SharedPreferences;
  6 +import android.preference.PreferenceManager;
  7 +
  8 +import com.google.gson.Gson;
  9 +import com.google.gson.JsonArray;
  10 +import com.google.gson.JsonElement;
  11 +import com.google.gson.JsonParser;
  12 +
  13 +import java.util.ArrayList;
  14 +import java.util.List;
  15 +
  16 +/**
  17 + * SharedPreferences工具类封装
  18 + */
  19 +public class SpUtils {
  20 + private static SharedPreferences sp;
  21 + private static String mPreferencesName = "share_preference_default";
  22 +
  23 + /**
  24 + * 设置preferencesName
  25 + *
  26 + * @param preferencesName preferencesName
  27 + */
  28 + private void setPreferencesName(String preferencesName) {
  29 + mPreferencesName = preferencesName;
  30 + }
  31 +
  32 + /**
  33 + * 写入boolean变量至sp中
  34 + *
  35 + * @param ctx 上下文环境
  36 + * @param key 存储节点名称
  37 + * @param value 存储节点的值
  38 + */
  39 + public static void putBoolean(Context ctx, String key, boolean value) {
  40 + //(存储节点文件名称,读写方式)
  41 + if (sp == null) {
  42 + sp = ctx.getSharedPreferences(mPreferencesName, Context
  43 + .MODE_PRIVATE);
  44 + }
  45 + sp.edit().putBoolean(key, value).apply();
  46 + }
  47 +
  48 + /**
  49 + * 读取boolean标示从sp中
  50 + *
  51 + * @param ctx 上下文环境
  52 + * @param key 存储节点名称
  53 + * @param defValue 没有此节点默认值
  54 + * @return 默认值或者此节点读取到的结果
  55 + */
  56 + public static boolean getBoolean(Context ctx, String key, boolean defValue) {
  57 + //(存储节点文件名称,读写方式)
  58 + if (sp == null) {
  59 + sp = ctx.getSharedPreferences(mPreferencesName, Context
  60 + .MODE_PRIVATE);
  61 + }
  62 + return sp.getBoolean(key, defValue);
  63 + }
  64 +
  65 + /**
  66 + * 写入String变量至sp中
  67 + *
  68 + * @param ctx 上下文环境
  69 + * @param key 存储节点名称
  70 + * @param value 存储节点的值
  71 + */
  72 + public static void putString(Context ctx, String key, String value) {
  73 + //(存储节点文件名称,读写方式)
  74 + if (sp == null) {
  75 + sp = ctx.getSharedPreferences(mPreferencesName, Context
  76 + .MODE_PRIVATE);
  77 + }
  78 + sp.edit().putString(key, value).apply();
  79 + }
  80 +
  81 + /**
  82 + * 读取String标示从sp中
  83 + *
  84 + * @param ctx 上下文环境
  85 + * @param key 存储节点名称
  86 + * @param defValue 没有此节点默认值
  87 + * @return 默认值或者此节点读取到的结果
  88 + */
  89 + public static String getString(Context ctx, String key, String defValue) {
  90 + //(存储节点文件名称,读写方式)
  91 + if (sp == null) {
  92 + sp = ctx.getSharedPreferences(mPreferencesName, Context
  93 + .MODE_PRIVATE);
  94 + }
  95 + return sp.getString(key, defValue);
  96 + }
  97 +
  98 +
  99 + /**
  100 + * 写入int变量至sp中
  101 + *
  102 + * @param ctx 上下文环境
  103 + * @param key 存储节点名称
  104 + * @param value 存储节点的值
  105 + */
  106 + public static void putInt(Context ctx, String key, int value) {
  107 + //(存储节点文件名称,读写方式)
  108 + if (sp == null) {
  109 + sp = ctx.getSharedPreferences(mPreferencesName, Context
  110 + .MODE_PRIVATE);
  111 + }
  112 + sp.edit().putInt(key, value).apply();
  113 + }
  114 +
  115 + /**
  116 + * 读取int标示从sp中
  117 + *
  118 + * @param ctx 上下文环境
  119 + * @param key 存储节点名称
  120 + * @param defValue 没有此节点默认值
  121 + * @return 默认值或者此节点读取到的结果
  122 + */
  123 + public static int getInt(Context ctx, String key, int defValue) {
  124 + //(存储节点文件名称,读写方式)
  125 + if (sp == null) {
  126 + sp = ctx.getSharedPreferences(mPreferencesName, Context
  127 + .MODE_PRIVATE);
  128 + }
  129 + return sp.getInt(key, defValue);
  130 + }
  131 +
  132 +
  133 + /**
  134 + * 从sp中移除指定节点
  135 + *
  136 + * @param ctx 上下文环境
  137 + * @param key 需要移除节点的名称
  138 + */
  139 + public static void remove(Context ctx, String key) {
  140 + if (sp == null) {
  141 + sp = ctx.getSharedPreferences(mPreferencesName, Context
  142 + .MODE_PRIVATE);
  143 + }
  144 + sp.edit().remove(key).apply();
  145 + }
  146 +
  147 + /**
  148 + * 保存List
  149 + *
  150 + * @param key sp key值
  151 + * @param datalist list
  152 + * @param <T> item 类型
  153 + */
  154 + public static <T> void setDataList(String key, List<T> datalist) {
  155 + if (null == datalist || datalist.size() <= 0)
  156 + return;
  157 +
  158 + Gson gson = new Gson();
  159 + //转换成json数据,再保存
  160 + String strJson = gson.toJson(datalist);
  161 + SpUtils.putString(AppUtils.getContext(), key, strJson);
  162 + }
  163 +
  164 + /**
  165 + * 获取List
  166 + *
  167 + * @param key sp key值
  168 + * @param <T> item 类型
  169 + * @return list
  170 + */
  171 + public static <T> List<T> getDataList(String key, Class<T> cls) {
  172 + List<T> datalist = new ArrayList<T>();
  173 + String strJson = SpUtils.getString(AppUtils.getContext(), key, null);
  174 +
  175 + if (null == strJson) {
  176 + return datalist;
  177 + }
  178 +
  179 + try {
  180 + Gson gson = new Gson();
  181 + // datalist = gson.fromJson(strJson, new TypeToken<List<T>>(){}.getType());
  182 + JsonArray array = new JsonParser().parse(strJson).getAsJsonArray();
  183 + for (final JsonElement elem : array) {
  184 + datalist.add(gson.fromJson(elem, cls));
  185 + }
  186 + }catch (Exception e){
  187 + e.printStackTrace();
  188 + }
  189 +
  190 + return datalist;
  191 + }
  192 +
  193 + public static int getThemeIndex(Context context) {
  194 + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
  195 + return prefs.getInt("ThemeIndex", 5);
  196 + }
  197 +
  198 + public static void setThemeIndex(Context context, int index) {
  199 + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
  200 + prefs.edit().putInt("ThemeIndex", index).apply();
  201 + }
  202 +
  203 + public static boolean getNightModel(Context context) {
  204 + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
  205 + return prefs.getBoolean("pNightMode", false);
  206 + }
  207 +
  208 + public static void setNightModel(Context context, boolean nightModel) {
  209 + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
  210 + prefs.edit().putBoolean("pNightMode", nightModel).apply();
  211 + }
  212 +}
mvpsdk/src/main/java/com/share/mvpsdk/utils/StatusBarUtils.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/utils/StatusBarUtils.java
@@ -0,0 +1,139 @@ @@ -0,0 +1,139 @@
  1 +package com.share.mvpsdk.utils;
  2 +
  3 +import android.app.Activity;
  4 +import android.content.Context;
  5 +import android.graphics.Color;
  6 +import android.os.Build;
  7 +import android.support.annotation.ColorInt;
  8 +import android.support.v7.widget.Toolbar;
  9 +import android.view.View;
  10 +import android.view.ViewGroup;
  11 +import android.view.Window;
  12 +import android.view.WindowManager;
  13 +
  14 +import java.lang.reflect.Field;
  15 +
  16 +
  17 +/**
  18 + * Created by Horrarndoo on 2017/8/31.
  19 + * <p>
  20 + * StatusBar工具类
  21 + */
  22 +public class StatusBarUtils {
  23 +
  24 + private static final int DEFAULT_STATUS_BAR_ALPHA = 0;
  25 +
  26 + /**
  27 + * 设置状态栏颜色
  28 + *
  29 + * @param activity 需要设置的 activity
  30 + * @param color 状态栏颜色值
  31 + */
  32 + public static void setColor(Activity activity, @ColorInt int color) {
  33 + setBarColor(activity, color);
  34 + }
  35 +
  36 + /**
  37 + * 设置状态栏背景色
  38 + * 4.4以下不处理
  39 + * 4.4使用默认沉浸式状态栏
  40 + *
  41 + * @param color 要为状态栏设置的颜色值
  42 + */
  43 + public static void setBarColor(Activity activity, int color) {
  44 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
  45 + Window win = activity.getWindow();
  46 + View decorView = win.getDecorView();
  47 + win.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);//沉浸式状态栏(4.4-5.0透明,5.0以上半透明)
  48 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {//android5.0以上设置透明效果
  49 + win.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);//清除flag,为了android5.0以上也全透明效果
  50 + //让应用的主体内容占用系统状态栏的空间
  51 + int option = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
  52 + | View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
  53 + decorView.setSystemUiVisibility(decorView.getSystemUiVisibility() | option);
  54 + win.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
  55 + win.setStatusBarColor(color);//设置状态栏背景色
  56 + }
  57 + }
  58 + }
  59 +
  60 + /**
  61 + * 设置状态栏全透明
  62 + *
  63 + * @param activity 需要设置的activity
  64 + */
  65 + public static void setTransparent(Activity activity) {
  66 + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
  67 + return;
  68 + }
  69 + setColor(activity, Color.TRANSPARENT);
  70 + }
  71 +
  72 + /**
  73 + * 修正 Toolbar 的位置
  74 + * 在 Android 4.4 版本下无法显示内容在 StatusBar 下,所以无需修正 Toolbar 的位置
  75 + *
  76 + * @param toolbar
  77 + */
  78 + public static void fixToolbar(Toolbar toolbar, Activity activity) {
  79 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
  80 + int statusHeight = getStatusBarHeight(activity);
  81 + ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) toolbar.getLayoutParams();
  82 + layoutParams.setMargins(0, statusHeight, 0, 0);
  83 + }
  84 + }
  85 +
  86 + /**
  87 + * 获取系统状态栏高度
  88 + *
  89 + * @param context
  90 + * @return
  91 + */
  92 + public static int getStatusBarHeight(Context context) {
  93 + Class<?> c = null;
  94 + Object obj = null;
  95 + Field field = null;
  96 + int x = 0, statusBarHeight = 0;
  97 + try {
  98 + c = Class.forName("com.android.internal.R$dimen");
  99 + obj = c.newInstance();
  100 + field = c.getField("status_bar_height");
  101 + x = Integer.parseInt(field.get(obj).toString());
  102 + statusBarHeight = context.getResources().getDimensionPixelSize(x);
  103 + } catch (Exception e1) {
  104 + e1.printStackTrace();
  105 + }
  106 + return statusBarHeight;
  107 + }
  108 +
  109 +// /**
  110 +// * 获取状态栏高度
  111 +// *
  112 +// * @param context context
  113 +// * @return 状态栏高度
  114 +// */
  115 +// private static int getStatusBarHeight(Context context) {
  116 +// // 获得状态栏高度
  117 +// int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen",
  118 +// "android");
  119 +// return context.getResources().getDimensionPixelSize(resourceId);
  120 +// }
  121 +
  122 + /**
  123 + * 计算状态栏颜色
  124 + *
  125 + * @param color color值
  126 + * @param alpha alpha值
  127 + * @return 最终的状态栏颜色
  128 + */
  129 + private static int calculateStatusColor(@ColorInt int color, int alpha) {
  130 + float a = 1 - alpha / 255f;
  131 + int red = color >> 16 & 0xff;
  132 + int green = color >> 8 & 0xff;
  133 + int blue = color & 0xff;
  134 + red = (int) (red * a + 0.5);
  135 + green = (int) (green * a + 0.5);
  136 + blue = (int) (blue * a + 0.5);
  137 + return 0xff << 24 | red << 16 | green << 8 | blue;
  138 + }
  139 +}
mvpsdk/src/main/java/com/share/mvpsdk/utils/StringUtils.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/utils/StringUtils.java
@@ -0,0 +1,125 @@ @@ -0,0 +1,125 @@
  1 +package com.share.mvpsdk.utils;
  2 +
  3 +import android.text.TextUtils;
  4 +
  5 +import java.util.regex.Matcher;
  6 +import java.util.regex.Pattern;
  7 +
  8 +/**
  9 + * Created by Horrarndoo on 2017/4/5.
  10 + * 字符串工具类
  11 + */
  12 +public class StringUtils {
  13 + /**
  14 + * 判断字符串是否有值,如果为null或者是空字符串或者只有空格或者为"null"字符串,则返回true,否则则返回false
  15 + */
  16 + public static boolean isEmpty(String value) {
  17 + return !(value != null && !"".equalsIgnoreCase(value.trim())
  18 + && !"null".equalsIgnoreCase(value.trim()));
  19 + }
  20 +
  21 + /**
  22 + * 判断字符串是否是邮箱
  23 + *
  24 + * @param email email
  25 + * @return 字符串是否是邮箱
  26 + */
  27 + public static boolean isEmail(String email) {
  28 + String str = "^([a-zA-Z0-9_\\-\\.]+)@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.)|(" +
  29 + "([a-zA-Z0-9\\-]+\\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\\]?)$";
  30 + Pattern p = Pattern.compile(str);
  31 + Matcher m = p.matcher(email);
  32 + return m.matches();
  33 + }
  34 +
  35 + /**
  36 + * 判断手机号字符串是否合法
  37 + *
  38 + * @param phoneNumber 手机号字符串
  39 + * @return 手机号字符串是否合法
  40 + */
  41 + public static boolean isPhoneNumberValid(String phoneNumber) {
  42 + boolean isValid = false;
  43 + String expression = "^1[3|4|5|7|8]\\d{9}$";
  44 + CharSequence inputStr = phoneNumber;
  45 + Pattern pattern = Pattern.compile(expression);
  46 + Matcher matcher = pattern.matcher(inputStr);
  47 + if (matcher.matches()) {
  48 + isValid = true;
  49 + }
  50 + return isValid;
  51 + }
  52 +
  53 + /**
  54 + * 判断手机号字符串是否合法
  55 + *
  56 + * @param areaCode 区号
  57 + * @param phoneNumber 手机号字符串
  58 + * @return 手机号字符串是否合法
  59 + */
  60 + public static boolean isPhoneNumberValid(String areaCode, String phoneNumber) {
  61 + if (TextUtils.isEmpty(phoneNumber)) {
  62 + return false;
  63 + }
  64 +
  65 + if (phoneNumber.length() < 5) {
  66 + return false;
  67 + }
  68 +
  69 + if (TextUtils.equals(areaCode, "+86") || TextUtils.equals(areaCode, "86")) {
  70 + return isPhoneNumberValid(phoneNumber);
  71 + }
  72 +
  73 + boolean isValid = false;
  74 + String expression = "^[0-9]*$";
  75 + CharSequence inputStr = phoneNumber;
  76 + Pattern pattern = Pattern.compile(expression);
  77 + Matcher matcher = pattern.matcher(inputStr);
  78 + if (matcher.matches()) {
  79 + isValid = true;
  80 + }
  81 + return isValid;
  82 + }
  83 +
  84 + /**
  85 + * 判断字符串是否是手机号格式
  86 + *
  87 + * @param areaCode 区号
  88 + * @param phoneNumber 手机号字符串
  89 + * @return 字符串是否是手机号格式
  90 + */
  91 + public static boolean isPhoneFormat(String areaCode, String phoneNumber) {
  92 + if (TextUtils.isEmpty(phoneNumber)) {
  93 + return false;
  94 + }
  95 +
  96 + if (phoneNumber.length() < 7) {
  97 + return false;
  98 + }
  99 +
  100 + boolean isValid = false;
  101 + String expression = "^[0-9]*$";
  102 + CharSequence inputStr = phoneNumber;
  103 + Pattern pattern = Pattern.compile(expression);
  104 + Matcher matcher = pattern.matcher(inputStr);
  105 + if (matcher.matches()) {
  106 + isValid = true;
  107 + }
  108 + return isValid;
  109 + }
  110 +
  111 + /**
  112 + * 判断字符串是否为纯数字
  113 + *
  114 + * @param str 字符串
  115 + * @return 是否纯数字
  116 + */
  117 + public static boolean isNumber(String str) {
  118 + for (int i = 0; i < str.length(); i++) {
  119 + if (!Character.isDigit(str.charAt(i))) {
  120 + return false;
  121 + }
  122 + }
  123 + return true;
  124 + }
  125 +}
mvpsdk/src/main/java/com/share/mvpsdk/utils/ThemeUtils.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/utils/ThemeUtils.java
@@ -0,0 +1,75 @@ @@ -0,0 +1,75 @@
  1 +package com.share.mvpsdk.utils;
  2 +
  3 +import android.content.Context;
  4 +import android.content.res.TypedArray;
  5 +import android.support.annotation.AttrRes;
  6 +import android.support.annotation.NonNull;
  7 +
  8 +import com.share.mvpsdk.R;
  9 +
  10 +
  11 +/**
  12 + * 作者:杭鹏伟
  13 + * 日期:16-7-8 15:15
  14 + * 邮箱:424346976@qq.com
  15 + */
  16 +public class ThemeUtils {
  17 + public static int[][] themeArr = {
  18 + {R.style.AppThemeLight_Red, R.style.AppThemeDark_Red},
  19 + {R.style.AppThemeLight_Pink, R.style.AppThemeDark_Pink},
  20 + {R.style.AppThemeLight_Purple, R.style.AppThemeDark_Purple},
  21 + {R.style.AppThemeLight_DeepPurple, R.style.AppThemeDark_DeepPurple},
  22 + {R.style.AppThemeLight_Indigo, R.style.AppThemeDark_Indigo},
  23 + {R.style.AppThemeLight_Blue, R.style.AppThemeDark_Blue},
  24 + {R.style.AppThemeLight_LightBlue, R.style.AppThemeDark_LightBlue},
  25 + {R.style.AppThemeLight_Cyan, R.style.AppThemeDark_Cyan},
  26 + {R.style.AppThemeLight_Teal, R.style.AppThemeDark_Teal},
  27 + {R.style.AppThemeLight_Green, R.style.AppThemeDark_Green},
  28 + {R.style.AppThemeLight_LightGreen, R.style.AppThemeDark_LightGreen},
  29 + {R.style.AppThemeLight_Lime, R.style.AppThemeDark_Lime},
  30 + {R.style.AppThemeLight_Yellow, R.style.AppThemeDark_Yellow},
  31 + {R.style.AppThemeLight_Amber, R.style.AppThemeDark_Amber},
  32 + {R.style.AppThemeLight_Orange, R.style.AppThemeDark_Orange},
  33 + {R.style.AppThemeLight_DeepOrange, R.style.AppThemeDark_DeepOrange},
  34 + {R.style.AppThemeLight_Brown, R.style.AppThemeDark_Brown},
  35 + {R.style.AppThemeLight_Grey, R.style.AppThemeDark_Grey},
  36 + {R.style.AppThemeLight_BlueGrey, R.style.AppThemeDark_BlueGrey}
  37 + };
  38 +
  39 + public static int[][] themeColorArr = {
  40 + {R.color.md_red_500, R.color.md_red_700}, {R.color.md_pink_500, R.color.md_pink_700},
  41 + {R.color.md_purple_500, R.color.md_purple_700},
  42 + {R.color.md_deep_purple_500, R.color.md_deep_purple_700},
  43 + {R.color.md_indigo_500, R.color.md_indigo_700},
  44 + {R.color.md_blue_500, R.color.md_blue_700},
  45 + {R.color.md_light_blue_500, R.color.md_light_blue_700},
  46 + {R.color.md_cyan_500, R.color.md_cyan_700}, {R.color.md_teal_500, R.color.md_teal_500},
  47 + {R.color.md_green_500, R.color.md_green_500},
  48 + {R.color.md_light_green_500, R.color.md_light_green_500},
  49 + {R.color.md_lime_500, R.color.md_lime_700},
  50 + {R.color.md_yellow_500, R.color.md_yellow_700},
  51 + {R.color.md_amber_500, R.color.md_amber_700},
  52 + {R.color.md_orange_500, R.color.md_orange_700},
  53 + {R.color.md_deep_orange_500, R.color.md_deep_orange_700},
  54 + {R.color.md_brown_500, R.color.md_brown_700}, {R.color.md_grey_500, R.color.md_grey_700},
  55 + {R.color.md_blue_grey_500, R.color.md_blue_grey_700}
  56 + };
  57 +
  58 + public static int getTheme(Context context) {
  59 + return context.getResources()
  60 + .getColor(themeColorArr[SpUtils.getThemeIndex(context)][0]);
  61 + }
  62 +
  63 + public static int getThemeColor(@NonNull Context context) {
  64 + return getThemeAttrColor(context, R.attr.colorPrimary);
  65 + }
  66 +
  67 + public static int getThemeAttrColor(@NonNull Context context, @AttrRes int attr) {
  68 + TypedArray a = context.obtainStyledAttributes(null, new int[]{attr});
  69 + try {
  70 + return a.getColor(0, 0);
  71 + } finally {
  72 + a.recycle();
  73 + }
  74 + }
  75 +}
mvpsdk/src/main/java/com/share/mvpsdk/utils/TimestampUtils.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/utils/TimestampUtils.java
@@ -0,0 +1,57 @@ @@ -0,0 +1,57 @@
  1 +package com.share.mvpsdk.utils;
  2 +
  3 +import java.text.SimpleDateFormat;
  4 +import java.util.Date;
  5 +import java.util.TimeZone;
  6 +
  7 +public class TimestampUtils {
  8 + /**
  9 + * 获取当前的时间戳,时区为北京
  10 + *
  11 + * @return
  12 + */
  13 + public static String getCurrentTimestamp() {
  14 + //时间戳的格式必须为 yyyy-MM-dd HH:mm:ss
  15 + String timestamp = null;
  16 + SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  17 + timestamp = format.format(new Date());
  18 + return timestamp;
  19 + }
  20 +
  21 + /**
  22 + * 获取当前的时间戳,时区为北京
  23 + *
  24 + * @return
  25 + */
  26 + public static String getCurrentTime(long times) {
  27 + //时间戳的格式必须为 yyyy-MM-dd HH:mm:ss
  28 + Date date = new Date(Long.valueOf(times));
  29 + SimpleDateFormat format = new SimpleDateFormat(
  30 + "yyyy-MM-dd HH:mm:ss");
  31 + String time = format.format(date);
  32 + LogUtils.e("timetimetimetimetimetimetime为:" + time);
  33 +
  34 + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
  35 + .format(new Date());
  36 +
  37 + return time;
  38 + }
  39 +
  40 + //法国时间:东一区
  41 + public static String getDateTimeByGMT(int timeZone) {
  42 + SimpleDateFormat dff = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  43 + switch (timeZone) {
  44 + case 1:
  45 + dff.setTimeZone(TimeZone.getTimeZone("GMT+1"));
  46 + break;
  47 + case 8:
  48 + dff.setTimeZone(TimeZone.getTimeZone("GMT+8"));
  49 + //LogUtils.i("采用东八区时区");
  50 + break;
  51 + }
  52 +
  53 + String time = dff.format(new Date());
  54 + //LogUtils.i("东八区时区时间为--》》" + time);
  55 + return time;
  56 + }
  57 +}
mvpsdk/src/main/java/com/share/mvpsdk/utils/ToastUtils.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/utils/ToastUtils.java
@@ -0,0 +1,66 @@ @@ -0,0 +1,66 @@
  1 +package com.share.mvpsdk.utils;
  2 +
  3 +import android.content.Context;
  4 +import android.widget.Toast;
  5 +
  6 +/**
  7 + * Created by Horrarndoo on 2017/4/5.
  8 + * <p>
  9 + * toast工具类封装
  10 + */
  11 +public class ToastUtils {
  12 + private static Toast mToast = null;
  13 +
  14 + /**
  15 + * 显示一个toast提示
  16 + *
  17 + * @param resouceId toast字符串资源id
  18 + */
  19 + public static void showToast(int resouceId) {
  20 + showToast(ResourcesUtils.getString(resouceId));
  21 + }
  22 +
  23 + /**
  24 + * 显示一个toast提示
  25 + *
  26 + * @param text toast字符串
  27 + */
  28 + public static void showToast(String text) {
  29 + showToast(text, Toast.LENGTH_SHORT);
  30 + }
  31 +
  32 + /**
  33 + * 显示一个toast提示
  34 + *
  35 + * @param text toast字符串
  36 + * @param duration toast显示时间
  37 + */
  38 + public static void showToast(String text, int duration) {
  39 + showToast(AppUtils.getContext(), text, duration);
  40 + }
  41 +
  42 + /**
  43 + * 显示一个toast提示
  44 + *
  45 + * @param context context 上下文对象
  46 + * @param text toast字符串
  47 + * @param duration toast显示时间
  48 + */
  49 + public static void showToast(final Context context, final String text, final int duration) {
  50 + /**
  51 + * 保证运行在主线程
  52 + */
  53 + AppUtils.runOnUIThread(new Runnable() {
  54 + @Override
  55 + public void run() {
  56 + if (mToast == null) {
  57 + mToast = Toast.makeText(context, text, duration);
  58 + } else {
  59 + mToast.setText(text);
  60 + mToast.setDuration(duration);
  61 + }
  62 + mToast.show();
  63 + }
  64 + });
  65 + }
  66 +}
mvpsdk/src/main/java/com/share/mvpsdk/utils/UnicodeUtils.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/utils/UnicodeUtils.java
@@ -0,0 +1,108 @@ @@ -0,0 +1,108 @@
  1 +package com.share.mvpsdk.utils;
  2 +
  3 +/**
  4 + * Created by Horrarndoo on 2017/10/11.
  5 + * <p>
  6 + */
  7 +public class UnicodeUtils {
  8 + /**
  9 + * utf-8 转换成 unicode
  10 + *
  11 + * @param inStr
  12 + * @return
  13 + */
  14 + public static String utf8ToUnicode(String inStr) {
  15 + char[] myBuffer = inStr.toCharArray();
  16 +
  17 + StringBuffer sb = new StringBuffer();
  18 + for (int i = 0; i < inStr.length(); i++) {
  19 + Character.UnicodeBlock ub = Character.UnicodeBlock.of(myBuffer[i]);
  20 + if (ub == Character.UnicodeBlock.BASIC_LATIN) {
  21 + //英文及数字等
  22 + sb.append(myBuffer[i]);
  23 + } else if (ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS) {
  24 + //全角半角字符
  25 + int j = (int) myBuffer[i] - 65248;
  26 + sb.append((char) j);
  27 + } else {
  28 + //汉字
  29 + short s = (short) myBuffer[i];
  30 + String hexS = Integer.toHexString(s);
  31 + String unicode = "\\u" + hexS;
  32 + sb.append(unicode.toLowerCase());
  33 + }
  34 + }
  35 + return sb.toString();
  36 + }
  37 +
  38 + /**
  39 + * unicode 转换成 utf-8
  40 + *
  41 + * @param theString
  42 + * @return
  43 + */
  44 + public static String unicodeToUtf8(String theString) {
  45 + char aChar;
  46 + int len = theString.length();
  47 + StringBuffer outBuffer = new StringBuffer(len);
  48 + for (int x = 0; x < len; ) {
  49 + aChar = theString.charAt(x++);
  50 + if (aChar == '\\') {
  51 + aChar = theString.charAt(x++);
  52 + if (aChar == 'u') {
  53 + // Read the xxxx
  54 + int value = 0;
  55 + for (int i = 0; i < 4; i++) {
  56 + aChar = theString.charAt(x++);
  57 + switch (aChar) {
  58 + case '0':
  59 + case '1':
  60 + case '2':
  61 + case '3':
  62 + case '4':
  63 + case '5':
  64 + case '6':
  65 + case '7':
  66 + case '8':
  67 + case '9':
  68 + value = (value << 4) + aChar - '0';
  69 + break;
  70 + case 'a':
  71 + case 'b':
  72 + case 'c':
  73 + case 'd':
  74 + case 'e':
  75 + case 'f':
  76 + value = (value << 4) + 10 + aChar - 'a';
  77 + break;
  78 + case 'A':
  79 + case 'B':
  80 + case 'C':
  81 + case 'D':
  82 + case 'E':
  83 + case 'F':
  84 + value = (value << 4) + 10 + aChar - 'A';
  85 + break;
  86 + default:
  87 + throw new IllegalArgumentException(
  88 + "Malformed \\uxxxx encoding.");
  89 + }
  90 + }
  91 + outBuffer.append((char) value);
  92 + } else {
  93 + if (aChar == 't')
  94 + aChar = '\t';
  95 + else if (aChar == 'r')
  96 + aChar = '\r';
  97 + else if (aChar == 'n')
  98 + aChar = '\n';
  99 + else if (aChar == 'f')
  100 + aChar = '\f';
  101 + outBuffer.append(aChar);
  102 + }
  103 + } else
  104 + outBuffer.append(aChar);
  105 + }
  106 + return outBuffer.toString();
  107 + }
  108 +}
0 \ No newline at end of file 109 \ No newline at end of file
mvpsdk/src/main/java/com/share/mvpsdk/utils/WifiAutoConnectManager.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/utils/WifiAutoConnectManager.java
@@ -0,0 +1,224 @@ @@ -0,0 +1,224 @@
  1 +package com.share.mvpsdk.utils;
  2 +
  3 +import android.content.Context;
  4 +import android.net.wifi.ScanResult;
  5 +import android.net.wifi.WifiConfiguration;
  6 +import android.net.wifi.WifiManager;
  7 +
  8 +import java.util.List;
  9 +
  10 +/**
  11 + * Created by Horrarndoo on 2017/8/10.
  12 + * <p>
  13 + * 兼容Android 6.0以上手机连接wifi
  14 + */
  15 +
  16 +public class WifiAutoConnectManager {
  17 +
  18 + private static final String TAG = WifiAutoConnectManager.class
  19 + .getSimpleName();
  20 +
  21 + WifiManager wifiManager;
  22 +
  23 + // 定义几种加密方式,一种是WEP,一种是WPA,还有没有密码的情况
  24 + public enum WifiCipherType {
  25 + WIFICIPHER_WEP, WIFICIPHER_WPA, WIFICIPHER_NOPASS, WIFICIPHER_INVALID
  26 + }
  27 +
  28 + // 构造函数
  29 + public WifiAutoConnectManager(WifiManager wifiManager) {
  30 + this.wifiManager = wifiManager;
  31 + }
  32 +
  33 + // 提供一个外部接口,传入要连接的无线网
  34 + public void connect(String ssid, String password, WifiCipherType type) {
  35 + Thread thread = new Thread(new ConnectRunnable(ssid, password, type));
  36 + thread.start();
  37 + }
  38 +
  39 + // 查看以前是否也配置过这个网络
  40 + private WifiConfiguration isExsits(String SSID) {
  41 + List<WifiConfiguration> existingConfigs = wifiManager
  42 + .getConfiguredNetworks();
  43 + for (WifiConfiguration existingConfig : existingConfigs) {
  44 + if (existingConfig.SSID.equals("\"" + SSID + "\"")) {
  45 + return existingConfig;
  46 + }
  47 + }
  48 + return null;
  49 + }
  50 +
  51 + private WifiConfiguration createWifiInfo(String SSID, String Password,
  52 + WifiCipherType Type) {
  53 + WifiConfiguration config = new WifiConfiguration();
  54 + config.allowedAuthAlgorithms.clear();
  55 + config.allowedGroupCiphers.clear();
  56 + config.allowedKeyManagement.clear();
  57 + config.allowedPairwiseCiphers.clear();
  58 + config.allowedProtocols.clear();
  59 + config.SSID = "\"" + SSID + "\"";
  60 + // config.SSID = SSID;
  61 + // nopass
  62 + if (Type == WifiCipherType.WIFICIPHER_NOPASS) {
  63 + // config.wepKeys[0] = "";
  64 + config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
  65 + // config.wepTxKeyIndex = 0;
  66 + }
  67 + // wep
  68 + if (Type == WifiCipherType.WIFICIPHER_WEP) {
  69 + if (!StringUtils.isEmpty(Password)) {
  70 + if (isHexWepKey(Password)) {
  71 + config.wepKeys[0] = Password;
  72 + } else {
  73 + config.wepKeys[0] = "\"" + Password + "\"";
  74 + }
  75 + }
  76 + config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
  77 + config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED);
  78 + config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
  79 + config.wepTxKeyIndex = 0;
  80 + }
  81 + // wpa
  82 + if (Type == WifiCipherType.WIFICIPHER_WPA) {
  83 + config.preSharedKey = "\"" + Password + "\"";
  84 + config.hiddenSSID = true;
  85 + config.allowedAuthAlgorithms
  86 + .set(WifiConfiguration.AuthAlgorithm.OPEN);
  87 + config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
  88 + config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
  89 + config.allowedPairwiseCiphers
  90 + .set(WifiConfiguration.PairwiseCipher.TKIP);
  91 + // 此处需要修改否则不能自动重联
  92 + // config.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
  93 + config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
  94 + config.allowedPairwiseCiphers
  95 + .set(WifiConfiguration.PairwiseCipher.CCMP);
  96 + config.status = WifiConfiguration.Status.ENABLED;
  97 +
  98 + }
  99 + return config;
  100 + }
  101 +
  102 + // 打开wifi功能
  103 + private boolean openWifi() {
  104 + boolean bRet = true;
  105 + if (!wifiManager.isWifiEnabled()) {
  106 + bRet = wifiManager.setWifiEnabled(true);
  107 + }
  108 + return bRet;
  109 + }
  110 +
  111 + // 关闭WIFI
  112 + private void closeWifi() {
  113 + if (wifiManager.isWifiEnabled()) {
  114 + wifiManager.setWifiEnabled(false);
  115 + }
  116 + }
  117 +
  118 + class ConnectRunnable implements Runnable {
  119 + private String ssid;
  120 +
  121 + private String password;
  122 +
  123 + private WifiCipherType type;
  124 +
  125 + public ConnectRunnable(String ssid, String password, WifiCipherType type) {
  126 + this.ssid = ssid;
  127 + this.password = password;
  128 + this.type = type;
  129 + }
  130 +
  131 + @Override
  132 + public void run() {
  133 + // 打开wifi
  134 + openWifi();
  135 + // 开启wifi功能需要一段时间(我在手机上测试一般需要1-3秒左右),所以要等到wifi
  136 + // 状态变成WIFI_STATE_ENABLED的时候才能执行下面的语句
  137 + while (wifiManager.getWifiState() == WifiManager.WIFI_STATE_ENABLING) {
  138 + try {
  139 + // 为了避免程序一直while循环,让它睡个100毫秒检测……
  140 + Thread.sleep(100);
  141 +
  142 + } catch (InterruptedException ie) {
  143 + LogUtils.e(ie.toString());
  144 + }
  145 + }
  146 +
  147 + WifiConfiguration tempConfig = isExsits(ssid);
  148 +
  149 + if (tempConfig != null) {
  150 + boolean b = wifiManager.enableNetwork(tempConfig.networkId,
  151 + true);
  152 + } else {
  153 + WifiConfiguration wifiConfig = createWifiInfo(ssid, password,
  154 + type);
  155 + if (wifiConfig == null) {
  156 + LogUtils.d("wifiConfig is null!");
  157 + return;
  158 + }
  159 +
  160 + int netID = wifiManager.addNetwork(wifiConfig);
  161 + boolean enabled = wifiManager.enableNetwork(netID, true);
  162 + LogUtils.d("enableNetwork status enable=" + enabled);
  163 + boolean connected = wifiManager.reconnect();
  164 + LogUtils.d("enableNetwork connected=" + connected);
  165 + }
  166 +
  167 + }
  168 + }
  169 +
  170 + private static boolean isHexWepKey(String wepKey) {
  171 + final int len = wepKey.length();
  172 +
  173 + // WEP-40, WEP-104, and some vendors using 256-bit WEP (WEP-232?)
  174 + if (len != 10 && len != 26 && len != 58) {
  175 + return false;
  176 + }
  177 +
  178 + return isHex(wepKey);
  179 + }
  180 +
  181 + private static boolean isHex(String key) {
  182 + for (int i = key.length() - 1; i >= 0; i--) {
  183 + final char c = key.charAt(i);
  184 + if (!(c >= '0' && c <= '9' || c >= 'A' && c <= 'F' || c >= 'a'
  185 + && c <= 'f')) {
  186 + return false;
  187 + }
  188 + }
  189 +
  190 + return true;
  191 + }
  192 +
  193 + // 获取ssid的加密方式
  194 + public static WifiCipherType getCipherType(Context context, String ssid) {
  195 + WifiManager wifiManager = (WifiManager) context
  196 + .getSystemService(Context.WIFI_SERVICE);
  197 +
  198 + List<ScanResult> list = wifiManager.getScanResults();
  199 +
  200 + for (ScanResult scResult : list) {
  201 +
  202 + if (!StringUtils.isEmpty(scResult.SSID) && scResult.SSID.equals(ssid)) {
  203 + String capabilities = scResult.capabilities;
  204 +
  205 + if (!StringUtils.isEmpty(capabilities)) {
  206 +
  207 + if (capabilities.contains("WPA")
  208 + || capabilities.contains("wpa")) {
  209 + LogUtils.i("wpa");
  210 + return WifiCipherType.WIFICIPHER_WPA;
  211 + } else if (capabilities.contains("WEP")
  212 + || capabilities.contains("wep")) {
  213 + LogUtils.i("wep");
  214 + return WifiCipherType.WIFICIPHER_WEP;
  215 + } else {
  216 + LogUtils.i("no");
  217 + return WifiCipherType.WIFICIPHER_NOPASS;
  218 + }
  219 + }
  220 + }
  221 + }
  222 + return WifiCipherType.WIFICIPHER_INVALID;
  223 + }
  224 +}
0 \ No newline at end of file 225 \ No newline at end of file
mvpsdk/src/main/java/com/share/mvpsdk/view/MyEyeView.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/view/MyEyeView.java
@@ -0,0 +1,71 @@ @@ -0,0 +1,71 @@
  1 +package com.share.mvpsdk.view;
  2 +
  3 +import android.content.Context;
  4 +import android.graphics.Canvas;
  5 +import android.graphics.Color;
  6 +import android.graphics.Paint;
  7 +import android.graphics.Shader;
  8 +import android.support.annotation.Nullable;
  9 +import android.util.AttributeSet;
  10 +import android.view.View;
  11 +
  12 +/**
  13 + * Created by ToaHanDong on 2018/2/7.
  14 + */
  15 +
  16 +public class MyEyeView extends View {
  17 +
  18 + Paint myPaint;
  19 +
  20 + int mypaintWidth=2;
  21 +
  22 + int centerLeft=0,centerTop=0,centerRight=0,centerBottom=0;
  23 + public MyEyeView(Context context) {
  24 + super(context);
  25 + init(context);
  26 + }
  27 +
  28 + public MyEyeView(Context context, @Nullable AttributeSet attrs) {
  29 + super(context, attrs);
  30 + init(context);
  31 + }
  32 +
  33 + public MyEyeView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
  34 + super(context, attrs, defStyleAttr);
  35 + init(context);
  36 + }
  37 +
  38 + @Override
  39 + protected void onDraw(Canvas canvas) {
  40 + super.onDraw(canvas);
  41 + while (centerLeft>0){
  42 + centerLeft-=10;
  43 + centerTop-=10;
  44 + centerRight+=10;
  45 + centerBottom+=10;
  46 + canvas.drawRect(centerLeft,centerTop,centerRight,centerBottom,myPaint);
  47 + }
  48 + }
  49 +
  50 + private void init(Context context) {
  51 + myPaint=new Paint();
  52 + myPaint.setColor(Color.WHITE);
  53 + myPaint.setAntiAlias(true);
  54 + myPaint.setStyle(Paint.Style.STROKE);
  55 + myPaint.setStrokeWidth(mypaintWidth);
  56 +// myPaint.setShader(new Shader());
  57 + }
  58 +
  59 + public void setMyPaintWidth(int paintWidth){
  60 + mypaintWidth=paintWidth;
  61 + }
  62 +
  63 + public void setIndexPoint(int centerLeft,int centerTop,int centerRight,int centerBottom){
  64 + this.centerLeft=centerLeft;
  65 + this.centerTop=centerTop;
  66 + this.centerRight=centerRight;
  67 + this.centerBottom=centerBottom;
  68 + invalidate();
  69 + }
  70 +
  71 +}
mvpsdk/src/main/java/com/share/mvpsdk/view/MyViewView.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/view/MyViewView.java
@@ -0,0 +1,368 @@ @@ -0,0 +1,368 @@
  1 +package com.share.mvpsdk.view;
  2 +
  3 +import android.content.Context;
  4 +import android.graphics.Bitmap;
  5 +import android.net.http.SslError;
  6 +import android.os.Build;
  7 +import android.util.AttributeSet;
  8 +import android.util.Log;
  9 +import android.view.View;
  10 +import android.webkit.JavascriptInterface;
  11 +import android.webkit.JsPromptResult;
  12 +import android.webkit.JsResult;
  13 +import android.webkit.SslErrorHandler;
  14 +import android.webkit.WebChromeClient;
  15 +import android.webkit.WebResourceError;
  16 +import android.webkit.WebResourceRequest;
  17 +import android.webkit.WebResourceResponse;
  18 +import android.webkit.WebSettings;
  19 +import android.webkit.WebView;
  20 +import android.webkit.WebViewClient;
  21 +import android.widget.FrameLayout;
  22 +
  23 +import com.share.mvpsdk.utils.FileUtils;
  24 +import com.share.mvpsdk.utils.NetworkConnectionUtils;
  25 +
  26 +/**
  27 + * Created by ToaHanDong on 2018/1/25.
  28 + */
  29 +
  30 +public class MyViewView extends WebView {
  31 +
  32 + public MyViewView(Context context) {
  33 + super(context);
  34 + init(context);
  35 + }
  36 +
  37 + public MyViewView(Context context, AttributeSet attrs) {
  38 + super(context, attrs);
  39 + init(context);
  40 + }
  41 +
  42 + public MyViewView(Context context, AttributeSet attrs, int defStyleAttr) {
  43 + super(context, attrs, defStyleAttr);
  44 + init(context);
  45 + }
  46 +
  47 + private String TAG="MyWebView";
  48 + //WebView的设置类
  49 + private WebSettings webSettings = null;
  50 +
  51 + private void init(Context context) {
  52 +
  53 + initWebSetting(context);
  54 +
  55 + }
  56 +
  57 + private void initWebSetting(Context context) {
  58 +
  59 + webSettings = getSettings();//初始化websettings
  60 +
  61 + //如果访问的页面中要与Javascript交互,则webview必须设置支持Javascript
  62 + webSettings.setJavaScriptEnabled(true);
  63 + //支持插件
  64 + webSettings.setPluginState(WebSettings.PluginState.ON);
  65 + //设置自适应屏幕,两者合用
  66 + webSettings.setUseWideViewPort(true);//将图片调整适合WebView的大小
  67 + webSettings.setLoadWithOverviewMode(true);//缩放至屏幕的大小
  68 + //缩放操作
  69 + webSettings.setSupportZoom(true); //支持缩放,默认为true。是下面那个的前提。
  70 + webSettings.setBuiltInZoomControls(true);//设置内置的缩放控件。若为false,则该WebView不可缩放
  71 + webSettings.setDisplayZoomControls(true);//隐藏原生的缩放控件
  72 + //其他细节操作
  73 + //LOAD_CACHE_ONLY: 不使用网络,只读取本地缓存数据
  74 + //LOAD_DEFAULT: (默认)根据cache-control决定是否从网络上取数据。
  75 + //LOAD_NO_CACHE: 不使用缓存,只从网络获取数据.
  76 + //LOAD_CACHE_ELSE_NETWORK,只要本地有,无论是否过期,或者no-cache,都使用缓存中的数据。
  77 +// webSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK); //关闭webview中缓存
  78 + webSettings.setAllowFileAccess(true);//设置可以访问文件
  79 + webSettings.setJavaScriptCanOpenWindowsAutomatically(true);//支持通过js打开新窗口
  80 + webSettings.setLoadsImagesAutomatically(true);//设置自动加载图片
  81 + webSettings.setDefaultTextEncodingName("utf-8");//设置编码格式为ytf-8
  82 + if (NetworkConnectionUtils.isConnected(context))
  83 + webSettings.setCacheMode(WebSettings.LOAD_DEFAULT);
  84 + else webSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
  85 + webSettings.setDomStorageEnabled(true); // 开启 DOM storage API 功能
  86 + webSettings.setDatabaseEnabled(true); //开启 database storage API 功能
  87 + webSettings.setAppCacheEnabled(true);//开启 Application Caches 功能
  88 + if (!FileUtils.webViewCacheIsExit()) {
  89 + webSettings.setAppCachePath(FileUtils.getCache()); //设置 Application Caches 缓存目录,只能设置一次
  90 + webSettings.setAppCacheMaxSize(8 * 1024 * 1024);
  91 + }
  92 + }
  93 +
  94 + FrameLayout frame;
  95 + public void setView(FrameLayout frame) {
  96 + this.frame=frame;
  97 + }
  98 +
  99 + /**
  100 + * js接口
  101 + */
  102 + public class SupportJavascriptInterface {
  103 + private Context context;
  104 +
  105 + public SupportJavascriptInterface(Context context) {
  106 + this.context = context;
  107 + }
  108 +
  109 + @JavascriptInterface
  110 + public void openImage(final String img) {
  111 + Log.d(TAG,"openImage="+img);
  112 +// goBackOrForward(-1);
  113 +// AppUtils.runOnUIThread(new Runnable() {
  114 +// @Override
  115 +// public void run() {
  116 +// gotoImageBrowse(img);
  117 +// }
  118 +// });
  119 + }
  120 + }
  121 +
  122 + // WebViewClient类(主要作用是:处理各种通知 & 请求事件)
  123 + public void setMyWebViewClient(String url) {
  124 + //步骤1: 选择加载方式
  125 +//方式a. 加载一个网页:
  126 + loadUrl(url);
  127 +//方式b:加载apk包中的html页面
  128 +// loadUrl("file:///android_asset/test.html");
  129 +//方式c:加载手机本地的html页面
  130 +// loadUrl("content://com.android.htmlfileprovider/sdcard/test.html");
  131 + addJavascriptInterface(new SupportJavascriptInterface(getContext()),"imagelistener");
  132 + setWebViewClient(new WebViewClient() {
  133 +
  134 + //设定加载开始的操作
  135 + @Override
  136 + public void onPageStarted(WebView view, String url, Bitmap favicon) {
  137 + super.onPageStarted(view, url, favicon);
  138 + Log.d(TAG,"onPageStarted="+url+"favicon="+favicon);
  139 + }
  140 +
  141 + //html加载完成
  142 + @Override
  143 + public void onPageFinished(WebView view, String url) {
  144 + super.onPageFinished(view, url);
  145 + Log.d(TAG,"onPageFinished="+url);
  146 + addWebImageClickListner(view);
  147 + }
  148 +
  149 + // 注入js函数监听
  150 + protected void addWebImageClickListner(WebView webView) {
  151 + // 这段js函数的功能就是,遍历所有的img节点,并添加onclick函数,
  152 + // 函数的功能是在图片点击的时候调用本地java接口并传递url过去
  153 + webView.loadUrl("javascript:(function(){" +
  154 + "var objs = document.getElementsByTagName(\"img\"); " +
  155 + "for(var i=0;i<objs.length;i++) " +
  156 + "{"
  157 + + " objs[i].onclick=function() " +
  158 + " { "
  159 + + " window.imagelistener.openImage(this.src); " +
  160 + " } " +
  161 + "}" +
  162 + "})()");
  163 + }
  164 +
  165 + /**
  166 + * 加载资源时会调用该方法
  167 + * @param view
  168 + * @param url
  169 + */
  170 + @Override
  171 + public void onLoadResource(WebView view, String url) {
  172 + super.onLoadResource(view, url);
  173 + Log.d(TAG,"onLoadResource="+url);
  174 + }
  175 +
  176 + @Override
  177 + public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
  178 + super.onReceivedError(view, errorCode, description, failingUrl);
  179 + switch (errorCode) {
  180 + case WebViewClient.ERROR_BAD_URL:
  181 + Log.d(TAG,"ERROR_BAD_URL");
  182 + break;
  183 + case WebViewClient.ERROR_UNKNOWN:
  184 + Log.d(TAG,"ERROR_UNKNOWN");
  185 + break;
  186 + }
  187 + }
  188 +
  189 +// @Override
  190 +// public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
  191 +// super.onReceivedError(view, request, error);
  192 +// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
  193 +// switch (error.getErrorCode())
  194 +// }
  195 +// }
  196 +
  197 + @Override
  198 + public boolean shouldOverrideUrlLoading(WebView view, String url) {
  199 + view.loadUrl(url);
  200 + return true;
  201 + }
  202 +
  203 + //webView默认是不处理https请求的,页面显示空白,需要进行如下设置:
  204 + @Override
  205 + public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
  206 + super.onReceivedSslError(view, handler, error);
  207 + Log.d(TAG,"onReceivedSslError");
  208 + handler.proceed();//表示等待证书响应
  209 + }
  210 + });
  211 +
  212 + }
  213 +
  214 + //辅助 WebView 处理 Javascript 的对话框,网站图标,网站标题等等。
  215 + public void setMyWebChromeClient(){
  216 + setWebChromeClient(new WebChromeClient(){
  217 +
  218 + @Override
  219 + public void onShowCustomView(View view, CustomViewCallback callback) {
  220 + super.onShowCustomView(view, callback);
  221 + Log.d(TAG,"onShowCustomView=");
  222 + }
  223 +
  224 + @Override
  225 + public void onProgressChanged(WebView view, int newProgress) {
  226 + super.onProgressChanged(view, newProgress);
  227 + Log.d(TAG,"newProgress="+newProgress);
  228 + }
  229 +
  230 + @Override
  231 + public void onReceivedTitle(WebView view, String title) {
  232 + super.onReceivedTitle(view, title);
  233 + Log.d(TAG,"onReceivedTitle="+title);
  234 + }
  235 +
  236 + /**
  237 + * js中的弹出框
  238 + * @param view
  239 + * @param url
  240 + * @param message
  241 + * @param result 可以对弹出框做取消和确认操作
  242 + * @return
  243 + */
  244 + @Override
  245 + public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
  246 + Log.d(TAG,"onJsAlert="+message+"url="+url);
  247 + return super.onJsAlert(view, url, message, result);
  248 + }
  249 +
  250 +// 支持javascript输入框,点击确认返回输入框中的值,点击取消返回 null。
  251 + @Override
  252 + public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
  253 + return super.onJsPrompt(view, url, message, defaultValue, result);
  254 + }
  255 + });
  256 + }
  257 +
  258 +
  259 + //WebView的状态
  260 +
  261 + /**
  262 + * 激活webView为活跃状态,能正常执行网页的响应
  263 + */
  264 + public void setonResume() {
  265 + onResume();
  266 + }
  267 +
  268 + /**
  269 + * 当页面被失去焦点被切换到后台不可见状态,需要执行onPause
  270 + * 通过onPause动作通知内核暂停所有的动作,比如DOM的解析、plugin的执行、JavaScript执行。
  271 + */
  272 + public void setOnPause() {
  273 + onPause();
  274 + }
  275 +
  276 + /**
  277 + * 当应用程序(存在webview)被切换到后台时,这个方法不仅仅针对当前的webview而是全局的全应用程序的webview
  278 + * 它会暂停所有webview的layout,parsing,javascripttimer。降低CPU功耗。
  279 + */
  280 + public void setPauseTimers() {
  281 + pauseTimers();
  282 + }
  283 +
  284 + /**
  285 + * 恢复pauseTimers状态
  286 + */
  287 + public void setResumeTimers() {
  288 + resumeTimers();
  289 + }
  290 +
  291 + public void destroyWebView() {
  292 + removeView(this);
  293 + destroy();
  294 + }
  295 +
  296 + //WebView的简单操作
  297 +
  298 + /**
  299 + * 判断网页是否可以回退
  300 + *
  301 + * @return
  302 + */
  303 + public boolean getCanGoBack() {
  304 + return canGoBack();
  305 + }
  306 +
  307 + /**
  308 + * 回退网页
  309 + */
  310 + public void setGoBack() {
  311 + goBack();
  312 + }
  313 +
  314 + /**
  315 + * 设置是否可以前进
  316 + *
  317 + * @return
  318 + */
  319 + public boolean setCanForward() {
  320 + return canGoForward();
  321 + }
  322 +
  323 + /**
  324 + * 前进网页
  325 + */
  326 + public void setGoForward() {
  327 + goForward();
  328 + }
  329 +
  330 + /**
  331 + * 以当前的index为起始点前进或者后退到历史记录中指定的steps
  332 + * 如果steps为负数则为后退,正数则为前进
  333 + *
  334 + * @param steps
  335 + */
  336 + public void setGoBackOrForward(int steps) {
  337 + goBackOrForward(steps);
  338 + }
  339 +
  340 + //清除缓存数据
  341 +
  342 + /**
  343 + * 清除网页访问留下的缓存
  344 + * 由于内核缓存是全局的因此这个方法不仅仅针对webview而是针对整个应用程序.
  345 + *
  346 + * @param isClear
  347 + */
  348 + public void clearMyCache(boolean isClear) {
  349 + clearCache(isClear);
  350 + }
  351 +
  352 + /**
  353 + * 清除当前webview访问的历史记录
  354 + * 只会webview访问历史记录里的所有记录除了当前访问记录
  355 + */
  356 + public void clearMyHistory() {
  357 +
  358 + }
  359 +
  360 + /**
  361 + * 这个api仅仅清除自动完成填充的表单数据,并不会清除WebView存储到本地的数据
  362 + */
  363 + public void clearMyFormData() {
  364 + clearFormData();
  365 + }
  366 +
  367 +
  368 +}
mvpsdk/src/main/java/com/share/mvpsdk/widgets/CompatNestedScrollView.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/widgets/CompatNestedScrollView.java
@@ -0,0 +1,86 @@ @@ -0,0 +1,86 @@
  1 +package com.share.mvpsdk.widgets;
  2 +
  3 +import android.content.Context;
  4 +import android.support.v4.widget.NestedScrollView;
  5 +import android.util.AttributeSet;
  6 +import android.view.View;
  7 +import android.view.ViewGroup;
  8 +
  9 +import com.share.mvpsdk.utils.AppUtils;
  10 +import com.share.mvpsdk.utils.DisplayUtils;
  11 +import com.share.mvpsdk.utils.StatusBarUtils;
  12 +
  13 +
  14 +/**
  15 + * Created by Horrarndoo on 2017/10/19.
  16 + * <p>
  17 + * 自定义NestedScrollView,主要实现根据滑动距离控制绑定View的alpha值
  18 + */
  19 +
  20 +public class CompatNestedScrollView extends NestedScrollView {
  21 + private ViewGroup childViewGroup;
  22 + private View headView;
  23 + private View bindView;
  24 +
  25 + public CompatNestedScrollView(Context context) {
  26 + super(context);
  27 + }
  28 +
  29 + public CompatNestedScrollView(Context context, AttributeSet attrs) {
  30 + super(context, attrs);
  31 + }
  32 +
  33 + public CompatNestedScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
  34 + super(context, attrs, defStyleAttr);
  35 + }
  36 +
  37 + @Override
  38 + protected void onFinishInflate() {
  39 + super.onFinishInflate();
  40 + if (getChildCount() > 1) {
  41 + throw new IllegalArgumentException("only can 1 child in this view");
  42 + } else {
  43 + if (getChildAt(0) instanceof ViewGroup) {
  44 + childViewGroup = (ViewGroup) getChildAt(0);
  45 + if (childViewGroup != null) {
  46 + headView = childViewGroup.getChildAt(0);
  47 + }
  48 + } else {
  49 + throw new IllegalArgumentException("child must be instanceof ViewGroup");
  50 + }
  51 + }
  52 + }
  53 +
  54 + @Override
  55 + protected void onScrollChanged(int l, int t, int oldl, int oldt) {
  56 + super.onScrollChanged(l, t, oldl, oldt);
  57 + float alpha = 1.f;
  58 + if (headView != null && bindView != null) {
  59 + //如果上滑超过toolbar高度,开启伴随动画
  60 + //Logger.e("t = " + t);
  61 + //Logger.e("headView.getHeight = " + headView.getHeight());
  62 + float slideValue = t - (DisplayUtils.dp2px(56) + StatusBarUtils.getStatusBarHeight
  63 + (AppUtils.getContext()));
  64 +
  65 + if (slideValue < 0)
  66 + slideValue = 0;
  67 +
  68 + float fraction = slideValue / (headView.getHeight() / 2.f);
  69 + if (fraction > 1) {
  70 + fraction = 1;
  71 + }
  72 +
  73 + alpha *= fraction;
  74 + bindView.setAlpha(alpha);
  75 + }
  76 + }
  77 +
  78 + /**
  79 + * 绑定要变化Alpha的view
  80 + *
  81 + * @param view 要变化Alpha的view
  82 + */
  83 + public void bindAlphaView(View view) {
  84 + bindView = view;
  85 + }
  86 +}
mvpsdk/src/main/java/com/share/mvpsdk/widgets/HistoryChartView.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/widgets/HistoryChartView.java
@@ -0,0 +1,719 @@ @@ -0,0 +1,719 @@
  1 +package com.share.mvpsdk.widgets;
  2 +
  3 +
  4 +import android.animation.ValueAnimator;
  5 +import android.content.Context;
  6 +import android.content.res.TypedArray;
  7 +import android.graphics.Bitmap;
  8 +import android.graphics.Canvas;
  9 +import android.graphics.Color;
  10 +import android.graphics.DashPathEffect;
  11 +import android.graphics.Paint;
  12 +import android.graphics.Path;
  13 +import android.graphics.PathEffect;
  14 +import android.graphics.PathMeasure;
  15 +import android.util.AttributeSet;
  16 +import android.view.View;
  17 +import android.view.animation.DecelerateInterpolator;
  18 +
  19 +import com.share.mvpsdk.R;
  20 +import com.share.mvpsdk.utils.DisplayUtils;
  21 +
  22 +
  23 +/**
  24 + * 历史记录查询图表 基于pathMeasure+DashPathEffect+属性动画实现
  25 + * 绘制时采取双缓冲绘制
  26 + *
  27 + * @author zyw
  28 + * @creation 2017-03-06
  29 + */
  30 +public class HistoryChartView extends View {
  31 +
  32 + private String TAG = "HistoryChartView";
  33 +
  34 + TypedArray ta;
  35 +
  36 + private float MarginTop = 100;
  37 +
  38 + private float MarginBottom = 100;
  39 +
  40 + private float MarginLeft = 100;
  41 +
  42 + private float MarginRight = 100;
  43 +
  44 + private float mYLabelSize = 50;
  45 +
  46 + private float mXlabelSize = 35;
  47 +
  48 + private float mXUnitTextSize;
  49 +
  50 + private float mYUnitTextSize;
  51 +
  52 + // 圆半径
  53 + private int circleRadius = 8;
  54 +
  55 + private int lineStrokeWidth = 3;
  56 +
  57 + private int dataStrokeWidth = 3;
  58 +
  59 + private static final long ANIM_DURATION = 1500;
  60 + private PathMeasure mRoomTempPathMeasure;
  61 + private PathMeasure mTargetTempPathMeasure;
  62 + private Path mRoomTempPath;
  63 + private Path mTargetTempPath;
  64 + private Paint mBmpPaint;
  65 + /**
  66 + * 柱形绘制进度
  67 + */
  68 + private float mRectFration;
  69 +
  70 + // X,Y轴的单位长度
  71 + private float Xscale = 20;
  72 + private float Yscale = 20;
  73 +
  74 + // 绘制X轴总长度
  75 + private float xLength;
  76 + // 绘制Y轴总长度
  77 + private float yLength;
  78 +
  79 + // X轴第1个节点的偏移位置
  80 + private float xFirstPointOffset;
  81 +
  82 + // y轴显示的节点间隔距离
  83 + private int yScaleForData = 1;
  84 +
  85 + // x轴显示的节点间隔距离
  86 + private int xScaleForData = 1;
  87 +
  88 + // 画线颜色
  89 + private int lineColor;
  90 +
  91 + private int roomTempLineColor;
  92 + private int targetTempLineColor;
  93 + private int powerTimeLineColor;
  94 + private int mUnitColor;
  95 +
  96 + private String mXUnitText;
  97 + private String mY1UnitText;
  98 + private String mY2UnitText;
  99 +
  100 + private int mMode = 1;// 从Activity传过来的模式值 1:天 2:周 3:月 4:年
  101 +
  102 + // 原点坐标
  103 + private float Xpoint;
  104 + private float Ypoint;
  105 +
  106 + // X,Y轴上面的显示文字
  107 + private String[] Xlabel = {"1", "2", "3", "4", "5", "6", "7"};
  108 + private String[] Ylabel = {"0", "9", "18", "27", "36"};
  109 + private String[] Ylabel2 = {"0", "25", "50", "75", "100"};
  110 +
  111 + private final static int X_SCALE_FOR_DATA_DAY = 2;
  112 + private final static int X_SCALE_FOR_DATA_WEEK = 1;
  113 + private final static int X_SCALE_FOR_DATA_YEAR = 1;
  114 + private final static int X_SCALE_FOR_DATA_MOUNTH = 5;
  115 +
  116 + private final static int DAY_MODE = 0;
  117 + private final static int WEEK_MODE = 1;
  118 + private final static int MONTH_MODE = 2;
  119 + private final static int YEAR_MODE = 3;
  120 +
  121 + // 曲线数据
  122 + private float[] roomTempDataArray = {15, 15, 15, 15, 15, 15, 15};
  123 + private float[] targetTempDataArray = {16, 16, 16, 16, 16, 16, 16};
  124 + private float[] powerOnTimeDataArray = {100, 100, 100, 100, 100, 100, 100};
  125 +
  126 + /**
  127 + * 各条柱形图当前top值数组
  128 + */
  129 + private Float[] rectCurrentTops;
  130 +
  131 + private ValueAnimator mValueAnimator;
  132 +
  133 + private Paint linePaint;
  134 + private Paint targetTempPaint;
  135 + private Paint roomTempPaint;
  136 + private PathEffect mRoomTempEffect;
  137 + private PathEffect mtargetTempEffect;
  138 + //定义一个内存中的图片,该图片将作为缓冲区
  139 + Bitmap mCacheBitmap = null;
  140 + //定义cacheBitmap上的Canvas对象
  141 + Canvas mCacheCanvas = null;
  142 +
  143 + public HistoryChartView(Context context, String[] xlabel, String[] ylabel,
  144 + float[] roomDataArray) {
  145 + super(context);
  146 + this.Xlabel = xlabel;
  147 + this.Ylabel = ylabel;
  148 + this.roomTempDataArray = roomDataArray;
  149 + }
  150 +
  151 + public HistoryChartView(Context context, AttributeSet attrs,
  152 + int defStyleAttr) {
  153 + super(context, attrs, defStyleAttr);
  154 + //Logger.e("HistoryChartView(Context context, AttributeSet attrs, int defStyleAttr)");
  155 +
  156 + ta = context.obtainStyledAttributes(attrs, R.styleable.HistoryChartView);
  157 +
  158 + setDefaultAttrrbutesValue();
  159 +
  160 + initPaint();
  161 +
  162 + initData();
  163 +
  164 + initParams();
  165 +
  166 + initPath();
  167 +
  168 + ta.recycle();
  169 + }
  170 +
  171 + public HistoryChartView(Context context, AttributeSet attrs) {
  172 + this(context, attrs, 0);
  173 + }
  174 +
  175 + public HistoryChartView(Context context) {
  176 + this(context, null);
  177 + }
  178 +
  179 + /**
  180 + * 设置显示数据
  181 + *
  182 + * @param strAlldata 历史数据全状态
  183 + * @param mode 历史数据模式
  184 + */
  185 + public void setData(String strAlldata, int mode) {
  186 + //Logger.e("history chart view strAlldata = " + strAlldata);
  187 + String[] allHistroyArray = strAlldata.split("-");
  188 +
  189 + String[] arrayRoomTempData = allHistroyArray[0].split(",");
  190 + String[] arraySetTempData = allHistroyArray[1].split(",");
  191 + String[] arrayPowerTimeData = allHistroyArray[2].split(",");
  192 +
  193 + mMode = mode;
  194 +
  195 + initXData(arrayRoomTempData);
  196 +
  197 + initRoomTempData(arrayRoomTempData);
  198 +
  199 + initTargetTempData(arraySetTempData);
  200 +
  201 + initPowerOnTimeData(arrayPowerTimeData);
  202 +
  203 + initData();
  204 +
  205 + initParams();
  206 +
  207 + initPath();
  208 +
  209 + startAnimation();
  210 + }
  211 +
  212 + private void initPaint() {
  213 + linePaint = new Paint();
  214 + linePaint.setStyle(Paint.Style.STROKE);
  215 + linePaint.setAntiAlias(true);
  216 + linePaint.setColor(lineColor);
  217 + linePaint.setDither(true);
  218 + linePaint.setStrokeWidth(lineStrokeWidth);
  219 +
  220 + roomTempPaint = new Paint();
  221 + roomTempPaint.setStyle(Paint.Style.STROKE);
  222 + roomTempPaint.setAntiAlias(true);
  223 + roomTempPaint.setColor(roomTempLineColor);
  224 + roomTempPaint.setDither(true);
  225 + roomTempPaint.setStrokeWidth(dataStrokeWidth);
  226 +
  227 + targetTempPaint = new Paint();
  228 + targetTempPaint.setStyle(Paint.Style.STROKE);
  229 + targetTempPaint.setAntiAlias(true);
  230 + targetTempPaint.setColor(targetTempLineColor);
  231 + targetTempPaint.setDither(true);
  232 + targetTempPaint.setStrokeWidth(dataStrokeWidth);
  233 +
  234 + mBmpPaint = new Paint();
  235 + }
  236 +
  237 + /**
  238 + * 初始化数据
  239 + */
  240 + private void initData() {
  241 +
  242 + mRoomTempPath = new Path();
  243 + mTargetTempPath = new Path();
  244 +
  245 + rectCurrentTops = new Float[roomTempDataArray.length];
  246 + }
  247 +
  248 + /**
  249 + * 初始化宽高比例等数据
  250 + */
  251 + public void initParams() {
  252 + // LogUtils.error(TAG, "initParams");
  253 + Xpoint = MarginLeft;
  254 +
  255 + xLength = this.getWidth() - MarginLeft - MarginRight
  256 + - (MarginRight + MarginLeft) / 16;
  257 + yLength = this.getHeight() - MarginTop - MarginBottom;
  258 +
  259 + Ypoint = this.getHeight() - MarginBottom + mYLabelSize / 3;
  260 + Xscale = (xLength - xFirstPointOffset * 2) / (this.Xlabel.length - 1);
  261 + Yscale = yLength / (this.Ylabel.length - 1);
  262 + }
  263 +
  264 + /**
  265 + * 初始化path
  266 + */
  267 + private void initPath() {
  268 + initRoomTempPath(roomTempDataArray);
  269 + initTargetTempPath(targetTempDataArray);
  270 + }
  271 +
  272 + /**
  273 + * 初始化设定温度数据
  274 + *
  275 + * @param arraySetTempData 设定温度数据
  276 + */
  277 + private void initTargetTempData(String[] arraySetTempData) {
  278 + targetTempDataArray = new float[arraySetTempData.length];
  279 + for (int i = 0; i < arraySetTempData.length; i++) {
  280 + if (arraySetTempData[i].length() > 0) {
  281 + targetTempDataArray[i] = Float.parseFloat(arraySetTempData[i]);
  282 + }
  283 + }
  284 + }
  285 +
  286 + /**
  287 + * 初始化房间温度数据
  288 + *
  289 + * @param arrayRoomTempData 房间温度数据
  290 + */
  291 + private void initRoomTempData(String[] arrayRoomTempData) {
  292 + roomTempDataArray = new float[arrayRoomTempData.length];
  293 + for (int i = 0; i < arrayRoomTempData.length; i++) {
  294 + if (arrayRoomTempData[i].length() > 0) {
  295 + roomTempDataArray[i] = Float.parseFloat(arrayRoomTempData[i]);
  296 + // LogUtils.error(TAG, "" + roomTempDataArray[i]);
  297 + }
  298 + }
  299 + }
  300 +
  301 + /**
  302 + * 初始化开机时间数据
  303 + *
  304 + * @param arrayPowerTimeData 开机时间数据
  305 + */
  306 + private void initPowerOnTimeData(String[] arrayPowerTimeData) {
  307 + powerOnTimeDataArray = new float[arrayPowerTimeData.length];
  308 + for (int i = 0; i < arrayPowerTimeData.length; i++) {
  309 + if (arrayPowerTimeData[i].length() > 0) {
  310 + powerOnTimeDataArray[i] = Float
  311 + .parseFloat(arrayPowerTimeData[i]);
  312 + }
  313 + }
  314 + }
  315 +
  316 + /**
  317 + * 初始化X轴数据
  318 + */
  319 + private void initXData(String[] tempData) {
  320 + switch (mMode) {
  321 + case DAY_MODE:
  322 + xScaleForData = X_SCALE_FOR_DATA_DAY;
  323 + setXUnitText(getResources().getString(R.string.history_x_unit_hour));
  324 + break;
  325 + case WEEK_MODE:
  326 + xScaleForData = X_SCALE_FOR_DATA_WEEK;
  327 + setXUnitText(getResources().getString(R.string.history_x_unit_day));
  328 + break;
  329 + case MONTH_MODE:
  330 + xScaleForData = X_SCALE_FOR_DATA_MOUNTH;
  331 + setXUnitText(getResources().getString(R.string.history_x_unit_day));
  332 + break;
  333 + case YEAR_MODE:
  334 + xScaleForData = X_SCALE_FOR_DATA_YEAR;
  335 + setXUnitText(getResources()
  336 + .getString(R.string.history_x_unit_month));
  337 + break;
  338 + default:
  339 + break;
  340 + }
  341 +
  342 + Xlabel = new String[tempData.length];
  343 + for (int i = 0; i < Xlabel.length; i++) {
  344 + Xlabel[i] = Integer.toString(i + 1);
  345 + }
  346 + }
  347 +
  348 + private void setDefaultAttrrbutesValue() {
  349 + float MarginTopPx = ta.getDimension(
  350 + R.styleable.HistoryChartView_margin_top, 50);
  351 + float MarginBottomPx = ta.getDimension(
  352 + R.styleable.HistoryChartView_margin_bottom, 50);
  353 + float MarginLeftPx = ta.getDimension(
  354 + R.styleable.HistoryChartView_margin_left, 50);
  355 + float MarginRightPx = ta.getDimension(
  356 + R.styleable.HistoryChartView_margin_right, 50);
  357 +
  358 + float yLabelSizePx = ta.getDimension(
  359 + R.styleable.HistoryChartView_ylabel_text_size, 30);
  360 + float xlabelSizePx = ta.getDimension(
  361 + R.styleable.HistoryChartView_xlabel_text_size, 20);
  362 + float xUnitSizePx = ta.getDimension(
  363 + R.styleable.HistoryChartView_x_unit_text_size, 30);
  364 + float yUnitSizePx = ta.getDimension(
  365 + R.styleable.HistoryChartView_y_unit_text_size, 30);
  366 +
  367 + float xFirstPointOffsetPx = ta.getDimension(
  368 + R.styleable.HistoryChartView_x_first_point_offset, 30);
  369 + float lineStrokeWidthPx = ta.getDimension(
  370 + R.styleable.HistoryChartView_line_stroke_width, 5);
  371 + float dataStrokeWidthPx = ta.getDimension(
  372 + R.styleable.HistoryChartView_data_stroke_width, 5);
  373 + float circleRadiusPx = ta.getDimension(
  374 + R.styleable.HistoryChartView_circle_radius, 6);
  375 +
  376 + xFirstPointOffset = DisplayUtils.px2sp(xFirstPointOffsetPx);
  377 +
  378 + MarginTop = DisplayUtils.px2dp(MarginTopPx);
  379 + MarginBottom = DisplayUtils.px2dp(MarginBottomPx);
  380 + MarginLeft = DisplayUtils.px2dp(MarginLeftPx);
  381 + MarginRight = DisplayUtils.px2dp(MarginRightPx);
  382 +
  383 + mYLabelSize = DisplayUtils.px2sp(yLabelSizePx);
  384 + mXlabelSize = DisplayUtils.px2sp(xlabelSizePx);
  385 +
  386 + mXUnitTextSize = DisplayUtils.px2sp(xUnitSizePx);
  387 + mYUnitTextSize = DisplayUtils.px2sp(yUnitSizePx);
  388 +
  389 + lineStrokeWidth = DisplayUtils.px2sp(lineStrokeWidthPx);
  390 + dataStrokeWidth = DisplayUtils.px2sp(dataStrokeWidthPx);
  391 + circleRadius = DisplayUtils.px2sp(circleRadiusPx);
  392 +
  393 + lineColor = ta.getColor(R.styleable.HistoryChartView_line_color,
  394 + getResources().getColor(R.color.light_yellow));
  395 + roomTempLineColor = ta.getColor(
  396 + R.styleable.HistoryChartView_first_data_line_color,
  397 + getResources().getColor(R.color.indoor_temp));
  398 + targetTempLineColor = ta.getColor(
  399 + R.styleable.HistoryChartView_second_data_line_color,
  400 + getResources().getColor(R.color.setpoint_temp));
  401 +
  402 + powerTimeLineColor = ta.getColor(
  403 + R.styleable.HistoryChartView_rect_background_color,
  404 + getResources().getColor(R.color.power_time));
  405 +
  406 + mUnitColor = ta.getColor(R.styleable.HistoryChartView_unit_color,
  407 + getResources().getColor(R.color.light_grey));
  408 +
  409 + mXUnitText = ta.getString(R.styleable.HistoryChartView_x_unit_text);
  410 + mY1UnitText = ta.getString(R.styleable.HistoryChartView_y1_unit_text);
  411 + mY2UnitText = ta.getString(R.styleable.HistoryChartView_y2_unit_text);
  412 + }
  413 +
  414 + /**
  415 + * 设置X轴单位符号
  416 + *
  417 + * @param xUnit x轴单位符号
  418 + */
  419 + public void setXUnitText(String xUnit) {
  420 + mXUnitText = xUnit;
  421 + }
  422 +
  423 + /**
  424 + * 绘制单位符号
  425 + *
  426 + * @param canvas canvas
  427 + */
  428 + private void drawUnit(Canvas canvas) {
  429 + Paint p = new Paint();
  430 + p.setAntiAlias(true);
  431 + p.setStrokeWidth(dataStrokeWidth);
  432 + p.setColor(mUnitColor);
  433 +
  434 + drawXUnit(canvas, p);
  435 + drawY1Unit(canvas, p);
  436 + drawY2Unit(canvas, p);
  437 + }
  438 +
  439 + // 画横轴
  440 + private void drawXLine(Canvas canvas, Paint p) {
  441 + p.setColor(getResources().getColor(R.color.light_yellow));
  442 + canvas.drawLine(Xpoint, Ypoint, xLength + MarginLeft, Ypoint, p);
  443 + }
  444 +
  445 + // 画灰色横轴
  446 + private void drawGreyXLine(Canvas canvas, Paint p) {
  447 + p.setColor(getResources().getColor(R.color.grey_line));
  448 + float startX = Xpoint + MarginLeft / 4;
  449 + // 纵向
  450 + for (int i = yScaleForData; (yLength - i * Yscale) >= 0; i += yScaleForData) {
  451 + float startY = Ypoint - i * Yscale;
  452 + canvas.drawLine(startX - MarginLeft / 4, startY, xLength
  453 + + MarginLeft, startY, p);
  454 + }
  455 + }
  456 +
  457 + // 画数据
  458 + private void drawData(Canvas canvas, float[] data, int dataColor) {
  459 + Paint p = new Paint();
  460 + p.setAntiAlias(true);
  461 + p.setStrokeWidth(dataStrokeWidth);
  462 + p.setTextSize(mXlabelSize);
  463 + // 横向
  464 + for (int i = 0; i < Xlabel.length; i++) {
  465 + int xLableInt = Integer.parseInt(Xlabel[i]);
  466 + float startX = Xpoint + i * Xscale + xFirstPointOffset;
  467 + if (xLableInt % xScaleForData == 0) {
  468 + p.setColor(lineColor);
  469 + canvas.drawText(this.Xlabel[i], startX - mXlabelSize / 3,
  470 + Ypoint + mXlabelSize * 3 / 2, p);
  471 + }
  472 + p.setColor(dataColor);
  473 + canvas.drawCircle(startX, getDataY(data[i], Ylabel), circleRadius,
  474 + p);
  475 + }
  476 +
  477 + p.setTextSize(mYLabelSize);
  478 + // 纵向
  479 + for (int i = 0; (yLength - i * Yscale) >= 0; i += yScaleForData) {
  480 + p.setColor(lineColor);
  481 + canvas.drawText(this.Ylabel[i], MarginLeft / 4,
  482 + getDataY(Float.valueOf(Ylabel[i]), Ylabel) + mYLabelSize
  483 + / 3, p);
  484 + canvas.drawText(this.Ylabel2[i], this.getWidth() - MarginLeft,
  485 + getDataY(Float.valueOf(Ylabel2[i]), Ylabel2) + mYLabelSize
  486 + / 3, p);
  487 + }
  488 + }
  489 +
  490 + // 获取room temp绘线Path数据
  491 + private void initRoomTempPath(float[] data) {
  492 + mRoomTempPath.reset();
  493 + // Path path = new Path();
  494 + float pointX;
  495 + float pointY;
  496 + // 横向
  497 + mRoomTempPath.moveTo(Xpoint + xFirstPointOffset,
  498 + getDataY(data[0], Ylabel));
  499 + mRoomTempPath.moveTo(Xpoint + xFirstPointOffset,
  500 + getDataY(data[0], Ylabel));
  501 + for (int i = 0; i < Xlabel.length; i++) {
  502 + float startX = Xpoint + i * Xscale + xFirstPointOffset;
  503 + // 绘制数据连线
  504 + if (i != 0) {
  505 + pointX = Xpoint + (i - 1) * Xscale + xFirstPointOffset;
  506 + pointY = getDataY(data[i - 1], Ylabel);
  507 + mRoomTempPath.lineTo(pointX, pointY);
  508 + }
  509 + if (i == Xlabel.length - 1) {
  510 + pointX = startX;
  511 + pointY = getDataY(data[i], Ylabel);
  512 + mRoomTempPath.lineTo(pointX, pointY);
  513 + }
  514 + }
  515 + mRoomTempPathMeasure = new PathMeasure(mRoomTempPath, false);
  516 + }
  517 +
  518 + /**
  519 + * 获取target temp绘线Path数据
  520 + *
  521 + * @param data target temp绘线Path数据
  522 + */
  523 + private void initTargetTempPath(float[] data) {
  524 + mTargetTempPath.reset();
  525 + float pointX;
  526 + float pointY;
  527 + // 横向
  528 + mTargetTempPath.moveTo(Xpoint + xFirstPointOffset,
  529 + getDataY(data[0], Ylabel));
  530 + for (int i = 0; i < Xlabel.length; i++) {
  531 + float startX = Xpoint + i * Xscale + xFirstPointOffset;
  532 + // 绘制数据连线
  533 + if (i != 0) {
  534 + pointX = Xpoint + (i - 1) * Xscale + xFirstPointOffset;
  535 + pointY = getDataY(data[i - 1], Ylabel);
  536 + mTargetTempPath.lineTo(pointX, pointY);
  537 + }
  538 + if (i == Xlabel.length - 1) {
  539 + pointX = startX;
  540 + pointY = getDataY(data[i], Ylabel);
  541 + mTargetTempPath.lineTo(pointX, pointY);
  542 + }
  543 + }
  544 + mTargetTempPathMeasure = new PathMeasure(mTargetTempPath, false);
  545 + }
  546 +
  547 + // 绘制矩形图
  548 + private void drawRect(Canvas canvas, float[] data, int dataColor) {
  549 + Paint p = new Paint();
  550 + float left;
  551 + float top;
  552 + float right;
  553 + float bottom;
  554 + float stopY = getDataY(Float.parseFloat(Ylabel[Ylabel.length - 1]),
  555 + Ylabel);// 灰色线Y轴位置
  556 + float rectYScale = (Ypoint - stopY) / 100;
  557 +
  558 + p.setAntiAlias(true);
  559 + p.setStrokeWidth(dataStrokeWidth);
  560 + p.setColor(dataColor);
  561 +
  562 + // 横向
  563 + for (int i = 0; i < Xlabel.length; i++) {
  564 + // 绘制柱形图
  565 + if (i != 0) {
  566 + left = Xpoint + (i - 1) * Xscale + xFirstPointOffset + Xscale
  567 + / 6;
  568 + top = Ypoint - data[i - 1] * rectYScale + lineStrokeWidth;// 要绘制的rect最终top值
  569 + // 起点top + (起点top - 终点top) * mRectFration
  570 + rectCurrentTops[i] = Ypoint - (Ypoint - top) * mRectFration;// 根据fraction动态更新top值
  571 + right = left + Xscale * 4 / 6;
  572 + bottom = Ypoint;
  573 + canvas.drawRect(left, rectCurrentTops[i], right, bottom, p);//
  574 + // 每次valueAnimator更新时重绘最新top值
  575 + }
  576 + }
  577 + }
  578 +
  579 + private void drawY1Unit(Canvas canvas, Paint p) {
  580 + int maxYLabelValue = Integer.valueOf(Ylabel[Ylabel.length - 1]);
  581 + p.setTextSize(mYUnitTextSize);
  582 + float textWidth = p.measureText(mY1UnitText);
  583 + canvas.drawText(mY1UnitText, MarginLeft / 2 - textWidth / 2,
  584 + getDataY(maxYLabelValue, Ylabel) - mYLabelSize - mYLabelSize
  585 + / 5, p);
  586 + }
  587 +
  588 + private void drawY2Unit(Canvas canvas, Paint p) {
  589 + int maxYLabel2Value = Integer.valueOf(Ylabel2[Ylabel2.length - 1]);
  590 + p.setTextSize(mYUnitTextSize);
  591 + float textWidth = p.measureText(mY2UnitText);
  592 + canvas.drawText(mY2UnitText, this.getWidth() - MarginRight / 2
  593 + - textWidth * 3 / 4, getDataY(maxYLabel2Value, Ylabel2)
  594 + - mYLabelSize - mYLabelSize / 5, p);
  595 + }
  596 +
  597 + private void drawXUnit(Canvas canvas, Paint p) {
  598 + p.setTextSize(mXUnitTextSize);
  599 + float textWidth = p.measureText(mXUnitText);
  600 + canvas.drawText(mXUnitText, this.getWidth() / 2 - textWidth / 2, Ypoint
  601 + + mXlabelSize * 3 + mXlabelSize / 5, p);
  602 + }
  603 +
  604 + /**
  605 + * 获取data对应绘制Y点值
  606 + */
  607 + private float getDataY(float dataY, String[] Ylabel) {
  608 + float y0 = 0;
  609 + float y1 = 0;
  610 + try {
  611 + y0 = Float.parseFloat(Ylabel[0]);
  612 + y1 = Float.parseFloat(Ylabel[1]);
  613 + } catch (Exception e) {
  614 + return 0;
  615 + }
  616 + try {
  617 + return Ypoint - ((dataY - y0) * Yscale / (y1 - y0));
  618 + } catch (Exception e) {
  619 + return 0;
  620 + }
  621 + }
  622 +
  623 + @Override
  624 + protected void onLayout(boolean changed, int left, int top, int right,
  625 + int bottom) {
  626 + super.onLayout(changed, left, top, right, bottom);
  627 + // LogUtils.error(TAG, "onLayout");
  628 + initParams();
  629 +
  630 + if (onViewLayoutListener != null) {
  631 + onViewLayoutListener.onLayoutSuccess();
  632 + }
  633 +
  634 + //创建一个与该View相同大小的缓冲区
  635 + mCacheBitmap = Bitmap.createBitmap(this.getWidth(), this.getHeight(), Bitmap.Config
  636 + .ARGB_8888);
  637 + mCacheCanvas = new Canvas();
  638 + //设置cacheCanvas将会绘制到内存中cacheBitmap上
  639 + mCacheCanvas.setBitmap(mCacheBitmap);
  640 + }
  641 +
  642 + @Override
  643 + protected void onDraw(Canvas canvas) {
  644 + super.onDraw(canvas);
  645 + mCacheCanvas.drawColor(Color.BLACK);
  646 +
  647 + drawGreyXLine(mCacheCanvas, linePaint);
  648 +
  649 + drawUnit(mCacheCanvas);
  650 +
  651 + if (powerOnTimeDataArray.length > 1) {
  652 + drawRect(mCacheCanvas, powerOnTimeDataArray, powerTimeLineColor);
  653 + }
  654 +
  655 + mCacheCanvas.drawPath(mRoomTempPath, roomTempPaint);
  656 +
  657 + if (roomTempDataArray.length > 1) {
  658 + drawData(mCacheCanvas, roomTempDataArray, roomTempLineColor);
  659 + }
  660 +
  661 + mCacheCanvas.drawPath(mTargetTempPath, targetTempPaint);
  662 +
  663 + if (targetTempDataArray.length > 1) {
  664 + drawData(mCacheCanvas, targetTempDataArray, targetTempLineColor);
  665 + }
  666 +
  667 + drawXLine(mCacheCanvas, linePaint);
  668 +
  669 + //将cacheBitmap绘制到该View组件
  670 + canvas.drawBitmap(mCacheBitmap, 0, 0, mBmpPaint);
  671 + }
  672 +
  673 + /**
  674 + * 开启动画
  675 + */
  676 + private void startAnimation() {
  677 + if (mValueAnimator != null) {
  678 + mValueAnimator.cancel();
  679 + }
  680 + final float targetTempLength = mTargetTempPathMeasure.getLength();
  681 + final float roomTempLength = mRoomTempPathMeasure.getLength();
  682 + mValueAnimator = ValueAnimator.ofFloat(1, 0);
  683 + mValueAnimator.setDuration(ANIM_DURATION);
  684 + // 减速插值器
  685 + mValueAnimator.setInterpolator(new DecelerateInterpolator());
  686 + mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
  687 + @Override
  688 + public void onAnimationUpdate(ValueAnimator animation) {
  689 + float fraction = (Float) animation.getAnimatedValue();
  690 + // 更新mtargetTempEffect
  691 + mtargetTempEffect = new DashPathEffect(new float[]{
  692 + targetTempLength, targetTempLength}, fraction
  693 + * targetTempLength);
  694 + targetTempPaint.setPathEffect(mtargetTempEffect);
  695 + // 更新mRoomTempEffect
  696 + mRoomTempEffect = new DashPathEffect(new float[]{
  697 + roomTempLength, roomTempLength}, fraction
  698 + * roomTempLength);
  699 + roomTempPaint.setPathEffect(mRoomTempEffect);
  700 + // 更新rect绘制fraction进度
  701 + mRectFration = 1 - fraction;// fraction是1->0 我们需要的柱形图绘制比例是0->1
  702 + postInvalidate();
  703 + }
  704 + });
  705 + mValueAnimator.start();
  706 + }
  707 +
  708 + public interface OnViewLayoutListener {
  709 + void onLayoutSuccess();
  710 + }
  711 +
  712 + public void setOnViewLayoutListener(
  713 + OnViewLayoutListener onViewLayoutListener) {
  714 + this.onViewLayoutListener = onViewLayoutListener;
  715 + }
  716 +
  717 + private OnViewLayoutListener onViewLayoutListener;
  718 +}
  719 +
mvpsdk/src/main/java/com/share/mvpsdk/widgets/HistoryModeView.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/widgets/HistoryModeView.java
@@ -0,0 +1,107 @@ @@ -0,0 +1,107 @@
  1 +package com.share.mvpsdk.widgets;
  2 +
  3 +import android.content.Context;
  4 +import android.content.res.TypedArray;
  5 +import android.util.AttributeSet;
  6 +import android.view.View;
  7 +import android.widget.LinearLayout;
  8 +import android.widget.TextView;
  9 +
  10 +import com.share.mvpsdk.R;
  11 +import com.share.mvpsdk.utils.ResourcesUtils;
  12 +
  13 +
  14 +/**
  15 + * 历史数据查询界面模式自定义View
  16 + * @author zyw
  17 + * @creation 2016-12-26
  18 + */
  19 +public class HistoryModeView extends LinearLayout {
  20 + private LinearLayout ll_click_view;
  21 + private TextView tv_mode;
  22 + private float mSelectTextSize;
  23 + private float mUnSelectTextSize;
  24 +
  25 + public HistoryModeView(Context context, AttributeSet attrs, int defStyleAttr) {
  26 + super(context, attrs, defStyleAttr);
  27 +
  28 + ll_click_view = (LinearLayout) View.inflate(context, R.layout.sub_history_click_view, this);
  29 + tv_mode = (TextView) findViewById(R.id.tv_click_view);
  30 +
  31 + TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.HistoryModeView);
  32 +
  33 + setText(ta.getString(R.styleable.HistoryModeView_android_text));
  34 + setSelectTextSize(ta.getDimension(R.styleable.HistoryModeView_select_text_size, 16));
  35 + setUnSelectTextSize(ta.getDimension(R.styleable.HistoryModeView_un_select_text_size, 12));
  36 + setViewTextSize();
  37 +
  38 + ta.recycle();
  39 + }
  40 +
  41 + public HistoryModeView(Context context, AttributeSet attrs) {
  42 + this(context, attrs, 0);
  43 + //init(context);
  44 + }
  45 +
  46 + public HistoryModeView(Context context) {
  47 + this(context, null);
  48 + //init(context);
  49 + }
  50 +
  51 + /**
  52 + * 设置控件选中状态
  53 + * @param isSelected 控件是否选中
  54 + */
  55 + public void setHistoryViewSelected(boolean isSelected){
  56 + ll_click_view.setSelected(isSelected);
  57 + setViewTextSize();
  58 + if(isSelected){
  59 + setTextColor(ResourcesUtils.getColor(R.color.light_yellow));
  60 + }else {
  61 + setTextColor(ResourcesUtils.getColor(R.color.light_grey));
  62 + }
  63 + }
  64 +
  65 + /**
  66 + * 设置控件文字
  67 + * @param str 控件文字
  68 + */
  69 + public void setText(String str){
  70 + tv_mode.setText(str);
  71 + }
  72 +
  73 + /**
  74 + * 设置控件文字颜色
  75 + * @param color 控件文字颜色
  76 + */
  77 + public void setTextColor(int color){
  78 + tv_mode.setTextColor(color);
  79 + }
  80 +
  81 + /**
  82 + * 设置根据view的选中状态更新text字号
  83 + */
  84 + public void setViewTextSize() {
  85 + if(ll_click_view.isSelected()){
  86 + tv_mode.getPaint().setTextSize(mSelectTextSize);
  87 + }else{
  88 + tv_mode.getPaint().setTextSize(mUnSelectTextSize);
  89 + }
  90 + }
  91 +
  92 + /**
  93 + * 设置view选中的字体大小
  94 + * @param selectSize 选中字体大小
  95 + */
  96 + public void setSelectTextSize(float selectSize){
  97 + mSelectTextSize = selectSize;
  98 + }
  99 +
  100 + /**
  101 + * 设置view没有选中的字体大小
  102 + * @param unSelectSize 非选中字体大小
  103 + */
  104 + public void setUnSelectTextSize(float unSelectSize){
  105 + mUnSelectTextSize = unSelectSize;
  106 + }
  107 +}
0 \ No newline at end of file 108 \ No newline at end of file
mvpsdk/src/main/java/com/share/mvpsdk/widgets/HistoryTipView.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/widgets/HistoryTipView.java
@@ -0,0 +1,95 @@ @@ -0,0 +1,95 @@
  1 +package com.share.mvpsdk.widgets;
  2 +
  3 +import android.content.Context;
  4 +import android.content.res.TypedArray;
  5 +import android.graphics.Color;
  6 +import android.util.AttributeSet;
  7 +import android.view.View;
  8 +import android.widget.ImageView;
  9 +import android.widget.LinearLayout;
  10 +import android.widget.TextView;
  11 +
  12 +import com.share.mvpsdk.R;
  13 +
  14 +
  15 +/**
  16 + * 历史数据查询界面Tips自定义View
  17 + * @author zyw
  18 + * @creation 2016-12-27
  19 + */
  20 +public class HistoryTipView extends LinearLayout {
  21 + private TextView tv_tips1;
  22 + private TextView tv_tips2;
  23 + private ImageView iv_tips;
  24 + private TypedArray ta;
  25 +
  26 + public HistoryTipView(Context context, AttributeSet attrs, int defStyleAttr) {
  27 + super(context, attrs, defStyleAttr);
  28 +
  29 + ta = context.obtainStyledAttributes(attrs, R.styleable.HistoryTipsView);
  30 + init(context);
  31 + ta.recycle();
  32 + }
  33 +
  34 + public HistoryTipView(Context context, AttributeSet attrs) {
  35 + this(context, attrs, 0);
  36 + //init(context);
  37 + }
  38 +
  39 + public HistoryTipView(Context context) {
  40 + this(context, null);
  41 + //init(context);
  42 + }
  43 +
  44 + public void init(Context context){
  45 + View.inflate(context, R.layout.sub_history_tips, this);
  46 +
  47 + tv_tips1 = (TextView) findViewById(R.id.tv_tip1);
  48 + tv_tips2 = (TextView) findViewById(R.id.tv_tip2);
  49 + iv_tips = (ImageView) findViewById(R.id.iv_tip);
  50 +
  51 + setTipOneText(ta.getString(R.styleable.HistoryTipsView_tip_one_text));
  52 + setTipTwoText(ta.getString(R.styleable.HistoryTipsView_tip_two_text));
  53 + setTextColor(ta.getColor(R.styleable.HistoryTipsView_android_textColor, Color.WHITE));
  54 + setTextSize(ta.getDimension(R.styleable.HistoryTipsView_android_textSize, 12));
  55 + setBackground(ta.getResourceId(R.styleable.HistoryTipsView_android_src, 0));
  56 + }
  57 +
  58 + /**
  59 + * 设置控件Tip1文字
  60 + * @param str
  61 + */
  62 + public void setTipOneText(String str){
  63 + tv_tips1.setText(str);
  64 + }
  65 +
  66 + /**
  67 + * 设置控件Tip2s文字
  68 + * @param str
  69 + */
  70 + public void setTipTwoText(String str){
  71 + tv_tips2.setText(str);
  72 + }
  73 +
  74 + /**
  75 + * 设置控件Tip1 2文字颜色
  76 + * @param color
  77 + */
  78 + public void setTextColor(int color){
  79 + tv_tips1.setTextColor(color);
  80 + tv_tips2.setTextColor(color);
  81 + }
  82 +
  83 + /**
  84 + * 设置根据view的选中状态更新text字号
  85 + */
  86 + public void setTextSize(float textSize) {
  87 + tv_tips1.getPaint().setTextSize(textSize);
  88 + tv_tips2.getPaint().setTextSize(textSize);
  89 + }
  90 +
  91 + public void setBackground(int resId){
  92 + iv_tips.setImageResource(resId);
  93 + }
  94 +}
  95 +
mvpsdk/src/main/java/com/share/mvpsdk/widgets/MovingImageView.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/widgets/MovingImageView.java
@@ -0,0 +1,332 @@ @@ -0,0 +1,332 @@
  1 +/*
  2 + * Copyright (C) 2014 Albert Grobas
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +
  17 +package com.share.mvpsdk.widgets;
  18 +
  19 +import android.content.Context;
  20 +import android.content.res.TypedArray;
  21 +import android.graphics.Bitmap;
  22 +import android.graphics.Matrix;
  23 +import android.graphics.drawable.Drawable;
  24 +import android.net.Uri;
  25 +import android.util.AttributeSet;
  26 +import android.widget.ImageView;
  27 +
  28 +import com.share.mvpsdk.R;
  29 +
  30 +
  31 +/**
  32 + * Created by Horrarndoo on 2017/9/7.
  33 + * <p>
  34 + * 自定义可以背景滚动的ImageView
  35 + */
  36 +public class MovingImageView extends ImageView {
  37 +
  38 + private float canvasWidth, canvasHeight;
  39 + private float imageWidth, imageHeight;
  40 + private float offsetWidth, offsetHeight;
  41 + /**
  42 + * 移动类型
  43 + */
  44 + private int movementType;
  45 +
  46 + /**
  47 + * 限定最大比值
  48 + * canvasHeight/drawableHeight 或者 canvasWidth/drawableWidth
  49 + */
  50 + private float maxRelativeSize;
  51 + /**
  52 + * 最小相对偏移值,图片最起码可以位移图*0.2的距离
  53 + */
  54 + private float minRelativeOffset;
  55 + private int mSpeed;
  56 + private long startDelay;
  57 + private int mRepetitions;
  58 + private boolean loadOnCreate;//load完毕后是否移动
  59 +
  60 + private MovingViewAnimator mAnimator;
  61 +
  62 + public MovingImageView(Context context) {
  63 + this(context, null);
  64 + }
  65 +
  66 + public MovingImageView(Context context, AttributeSet attrs) {
  67 + this(context, attrs, 0);
  68 + }
  69 +
  70 + public MovingImageView(Context context, AttributeSet attrs, int defStyle) {
  71 + super(context, attrs, defStyle);
  72 +
  73 + TypedArray ta = context.getTheme().obtainStyledAttributes(attrs,
  74 + R.styleable.MovingImageView, defStyle, 0);
  75 +
  76 + try {
  77 + maxRelativeSize = ta.getFloat(R.styleable.MovingImageView_miv_max_relative_size, 3.0f);
  78 + minRelativeOffset = ta.getFloat(R.styleable.MovingImageView_miv_min_relative_offset,
  79 + 0.2f);
  80 + mSpeed = ta.getInt(R.styleable.MovingImageView_miv_speed, 50);
  81 + mRepetitions = ta.getInt(R.styleable.MovingImageView_miv_repetitions, -1);
  82 + startDelay = ta.getInt(R.styleable.MovingImageView_miv_start_delay, 0);
  83 + loadOnCreate = ta.getBoolean(R.styleable.MovingImageView_miv_load_on_create, true);
  84 + } finally {
  85 + ta.recycle();
  86 + }
  87 +
  88 + init();
  89 + }
  90 +
  91 + private void init() {
  92 + super.setScaleType(ScaleType.MATRIX);
  93 + mAnimator = new MovingViewAnimator(this);
  94 + }
  95 +
  96 + /**
  97 + * 更新canvas size
  98 + *
  99 + * @param w new width.
  100 + * @param h new height.
  101 + * @param oldW old width.
  102 + * @param oldH old height.
  103 + */
  104 + @Override
  105 + protected void onSizeChanged(int w, int h, int oldW, int oldH) {
  106 + super.onSizeChanged(w, h, oldW, oldH);
  107 + canvasWidth = (float) w - (float) (getPaddingLeft() + getPaddingRight());
  108 + canvasHeight = (float) h - (float) (getPaddingTop() + getPaddingBottom());
  109 + updateAll();
  110 + }
  111 +
  112 + private void updateAll() {
  113 + if (getDrawable() != null) {
  114 + updateImageSize();
  115 + updateOffsets();
  116 + updateAnimatorValues();
  117 + }
  118 + }
  119 +
  120 + /**
  121 + * 更新图片Size
  122 + */
  123 + private void updateImageSize() {
  124 + imageWidth = getDrawable().getIntrinsicWidth();//获取图片高度
  125 + imageHeight = getDrawable().getIntrinsicHeight();//获取图片宽度
  126 + }
  127 +
  128 + /**
  129 + * 更新偏移量,确定动画范围
  130 + */
  131 + private void updateOffsets() {
  132 + float minSizeX = imageWidth * minRelativeOffset;
  133 + float minSizeY = imageHeight * minRelativeOffset;
  134 + offsetWidth = (imageWidth - canvasWidth - minSizeX) > 0 ? imageWidth - canvasWidth : 0;
  135 + offsetHeight = (imageHeight - canvasHeight - minSizeY) > 0 ? imageHeight - canvasHeight : 0;
  136 + }
  137 +
  138 + /**
  139 + * 更新动画基本数据
  140 + */
  141 + private void updateAnimatorValues() {
  142 + if (canvasHeight == 0 && canvasWidth == 0)
  143 + return;
  144 +
  145 + float scale = calculateTypeAndScale();
  146 + if (scale == 0)
  147 + return;
  148 +
  149 + float w = (imageWidth * scale) - canvasWidth;
  150 + float h = (imageHeight * scale) - canvasHeight;
  151 +
  152 + mAnimator.updateValues(movementType, w, h);
  153 + mAnimator.setStartDelay(startDelay);
  154 + mAnimator.setSpeed(mSpeed);
  155 + mAnimator.setRepetition(mRepetitions);
  156 +
  157 + if (loadOnCreate) {
  158 + startMoving();
  159 + }
  160 + }
  161 +
  162 + /**
  163 + * 设置最佳的运动类型
  164 + * 计算缩放比例
  165 + *
  166 + * @return image scale.
  167 + */
  168 + private float calculateTypeAndScale() {
  169 + movementType = MovingViewAnimator.AUTO_MOVE;
  170 + float scale = 1f;
  171 + float scaleByImage = Math.max(imageWidth / canvasWidth, imageHeight / canvasHeight);
  172 + Matrix matrix = new Matrix();
  173 +
  174 + if (offsetWidth == 0 && offsetHeight == 0) {//图片太小,无法动画,需要放大
  175 + //画布宽度/图片宽度
  176 + float sW = canvasWidth / imageWidth;
  177 + //画布高度/图片高度
  178 + float sH = canvasHeight / imageHeight;
  179 +
  180 + if (sW > sH) {
  181 + scale = Math.min(sW, maxRelativeSize);//限定最大缩放值
  182 + matrix.setTranslate((canvasWidth - imageWidth * scale) / 2f, 0);
  183 + movementType = MovingViewAnimator.VERTICAL_MOVE;//垂直移动
  184 +
  185 + } else if (sW < sH) {
  186 + scale = Math.min(sH, maxRelativeSize);//限定最大缩放值
  187 + matrix.setTranslate(0, (canvasHeight - imageHeight * scale) / 2f);
  188 + movementType = MovingViewAnimator.HORIZONTAL_MOVE;//水平移动
  189 +
  190 + } else {
  191 + scale = Math.max(sW, maxRelativeSize);//限定最大缩放值
  192 + movementType = (scale == sW) ? MovingViewAnimator.NONE_MOVE :
  193 + MovingViewAnimator.DIAGONAL_MOVE;//对角线移动
  194 + }
  195 + } else if (offsetWidth == 0) {//宽度太小,无法执行水平动画,放大宽度
  196 + scale = canvasWidth / imageWidth;
  197 + movementType = MovingViewAnimator.VERTICAL_MOVE;
  198 +
  199 + } else if (offsetHeight == 0) {//高度太小,无法执行垂直动画,放大高度
  200 + scale = canvasHeight / imageHeight;//求出画布高度和图片高度的比值用于确定画布起始坐标
  201 + movementType = MovingViewAnimator.HORIZONTAL_MOVE;
  202 +
  203 + } else if (scaleByImage > maxRelativeSize) {//图片太大,根据最大比值设定图片缩放值
  204 + scale = maxRelativeSize / scaleByImage;
  205 + if (imageWidth * scale < canvasWidth || imageHeight * scale < canvasHeight) {
  206 + scale = Math.max(canvasWidth / imageWidth, canvasHeight / imageHeight);
  207 + }
  208 + }
  209 +
  210 + matrix.preScale(scale, scale);
  211 + setImageMatrix(matrix);
  212 + return scale;
  213 + }
  214 +
  215 + /**
  216 + * 禁止设置ScaleType
  217 + *
  218 + * @param scaleType
  219 + */
  220 + @Override
  221 + @Deprecated
  222 + public void setScaleType(ScaleType scaleType) {
  223 + //super.setScaleType(scaleType);
  224 + }
  225 +
  226 + @Override
  227 + public void setImageResource(int resId) {
  228 + super.setImageResource(resId);
  229 + updateAll();
  230 + }
  231 +
  232 + @Override
  233 + public void setImageURI(Uri uri) {
  234 + super.setImageURI(uri);
  235 + updateAll();
  236 + }
  237 +
  238 + @Override
  239 + public void setImageDrawable(Drawable drawable) {
  240 + super.setImageDrawable(drawable);
  241 + updateAll();
  242 + }
  243 +
  244 + @Override
  245 + public void setImageBitmap(Bitmap bm) {
  246 + super.setImageBitmap(bm);
  247 + updateAll();
  248 + }
  249 +
  250 + /**
  251 + * 获取animator
  252 + *
  253 + * @return
  254 + */
  255 + public MovingViewAnimator getMovingAnimator() {
  256 + return mAnimator;
  257 + }
  258 +
  259 + public float getMaxRelativeSize() {
  260 + return maxRelativeSize;
  261 + }
  262 +
  263 + public void setMaxRelativeSize(float max) {
  264 + maxRelativeSize = max;
  265 + updateAnimatorValues();
  266 + }
  267 +
  268 + public float getMinRelativeOffset() {
  269 + return minRelativeOffset;
  270 + }
  271 +
  272 + public void setMinRelativeOffset(float min) {
  273 + minRelativeOffset = min;
  274 + updateAnimatorValues();
  275 + }
  276 +
  277 + public boolean isLoadOnCreate() {
  278 + return loadOnCreate;
  279 + }
  280 +
  281 + public void setLoadOnCreate(boolean loadOnCreate) {
  282 + this.loadOnCreate = loadOnCreate;
  283 + }
  284 +
  285 + /**
  286 + * 开始移动
  287 + * 默认不停的移动
  288 + */
  289 + public void startMoving() {
  290 + startMoving(-1);
  291 + }
  292 +
  293 + /**
  294 + * 开始移动
  295 + *
  296 + * @param repetition 循环模式
  297 + */
  298 + public void startMoving(int repetition) {
  299 + mAnimator.setRepetition(repetition);
  300 + mAnimator.start();
  301 + }
  302 +
  303 + /**
  304 + * 恢复移动
  305 + */
  306 + public void resumeMoving() {
  307 + mAnimator.resume();
  308 + }
  309 +
  310 + /**
  311 + * 暂停移动
  312 + */
  313 + public void pauseMoving() {
  314 + mAnimator.pause();
  315 + }
  316 +
  317 + /**
  318 + * 停止移动
  319 + */
  320 + public void stopMoving() {
  321 + mAnimator.stop();
  322 + }
  323 +
  324 + /**
  325 + * 获取当前状态
  326 + *
  327 + * @return
  328 + */
  329 + public MovingViewAnimator.MovingState getMovingState() {
  330 + return mAnimator.getMovingState();
  331 + }
  332 +}
mvpsdk/src/main/java/com/share/mvpsdk/widgets/MovingViewAnimator.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/widgets/MovingViewAnimator.java
@@ -0,0 +1,448 @@ @@ -0,0 +1,448 @@
  1 +/*
  2 + * Copyright (C) 2014 Albert Grobas
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +
  17 +package com.share.mvpsdk.widgets;
  18 +
  19 +import android.animation.Animator;
  20 +import android.animation.AnimatorListenerAdapter;
  21 +import android.animation.AnimatorSet;
  22 +import android.animation.ObjectAnimator;
  23 +import android.animation.PropertyValuesHolder;
  24 +import android.annotation.TargetApi;
  25 +import android.os.Build;
  26 +import android.view.View;
  27 +import android.view.animation.AccelerateDecelerateInterpolator;
  28 +import android.view.animation.Interpolator;
  29 +
  30 +import java.util.ArrayList;
  31 +import java.util.List;
  32 +
  33 +/**
  34 + * Created by Horrarndoo on 2017/9/7.
  35 + * <p>
  36 + * 滚动view动画
  37 + */
  38 +public class MovingViewAnimator {
  39 + /**
  40 + * 水平移动
  41 + */
  42 + public static final int HORIZONTAL_MOVE = 1;
  43 + /**
  44 + * 垂直移动
  45 + */
  46 + public static final int VERTICAL_MOVE = 2;
  47 + /**
  48 + * 对角线移动
  49 + */
  50 + public static final int DIAGONAL_MOVE = 3;
  51 + /**
  52 + * 自动移动
  53 + */
  54 + public static final int AUTO_MOVE = 0;
  55 + /**
  56 + * 不移动
  57 + */
  58 + public static final int NONE_MOVE = -1;
  59 +
  60 + private AnimatorSet mAnimatorSet;
  61 + private View mView;
  62 +
  63 + private boolean isRunning;
  64 + private int currentLoop;
  65 + private boolean infiniteRepetition = true;
  66 + private ArrayList<Float> pathDistances;
  67 +
  68 + private int loopCount = -1;
  69 + private int movementType;
  70 + private float offsetWidth, offsetHeight;
  71 + private int mSpeed = 50;
  72 + private long mDelay = 0;
  73 + private Interpolator mInterpolator;
  74 +
  75 + private MovingState currentState = MovingState.stop;
  76 +
  77 + public enum MovingState {
  78 + stop,
  79 + moving,
  80 + pause
  81 + }
  82 +
  83 + private Animator.AnimatorListener animatorListener = new AnimatorListenerAdapter() {
  84 + @Override
  85 + public void onAnimationEnd(final Animator animation) {
  86 + //super.onAnimationEnd(animation);
  87 + //运行在主线程
  88 + mView.post((new Runnable() {
  89 + public void run() {
  90 + if (isRunning) {
  91 + if (infiniteRepetition) {
  92 + mAnimatorSet.start();
  93 + } else {
  94 + currentLoop--;
  95 + if (currentLoop > 0) {
  96 + mAnimatorSet.start();
  97 + }
  98 + }
  99 + }
  100 + }
  101 + }));
  102 + }
  103 + };
  104 +
  105 + public MovingViewAnimator(View imgView) {
  106 + mView = imgView;
  107 + isRunning = false;
  108 + mAnimatorSet = new AnimatorSet();
  109 + pathDistances = new ArrayList<>();
  110 + mInterpolator = new AccelerateDecelerateInterpolator();
  111 + }
  112 +
  113 + public MovingViewAnimator(View imgView, int type, float width, float height) {
  114 + this(imgView);
  115 + updateValues(type, width, height);
  116 + }
  117 +
  118 + private void init() {
  119 + setUpAnimator();
  120 + setUpValues();
  121 + }
  122 +
  123 + /**
  124 + * 根据移动类型设置不同的动画
  125 + */
  126 + private void setUpAnimator() {
  127 + AnimatorSet animatorSet = new AnimatorSet();
  128 + pathDistances.clear();
  129 +
  130 + switch (movementType) {
  131 + case HORIZONTAL_MOVE:
  132 + animatorSet.playSequentially(createHorizontalAnimator(0, offsetWidth),
  133 + createHorizontalAnimator(offsetWidth, 0));
  134 + break;
  135 + case VERTICAL_MOVE:
  136 + animatorSet.playSequentially(createVerticalAnimator(0, offsetHeight),
  137 + createVerticalAnimator(offsetHeight, 0));
  138 + break;
  139 + case DIAGONAL_MOVE:
  140 + animatorSet.playSequentially(createDiagonalAnimator(0, offsetWidth, 0,
  141 + offsetHeight),
  142 + createDiagonalAnimator(offsetWidth, 0, offsetHeight, 0));
  143 + break;
  144 + case AUTO_MOVE:
  145 + animatorSet.playSequentially(
  146 + createVerticalAnimator(0, offsetHeight),
  147 + createDiagonalAnimator(0, offsetWidth, offsetHeight, 0),
  148 + createHorizontalAnimator(offsetWidth, 0),
  149 + createDiagonalAnimator(0, offsetWidth, 0, offsetHeight),
  150 + createHorizontalAnimator(offsetWidth, 0),
  151 + createVerticalAnimator(offsetHeight, 0));
  152 + }
  153 +
  154 + if (mAnimatorSet != null) {
  155 + mAnimatorSet.removeAllListeners();
  156 + stop();
  157 + }
  158 + mAnimatorSet = animatorSet;
  159 + }
  160 +
  161 + /**
  162 + * 设置参数数据
  163 + */
  164 + private void setUpValues() {
  165 + setSpeed(mSpeed);
  166 + setStartDelay(mDelay);
  167 + setRepetition(loopCount);
  168 + setInterpolator(mInterpolator);
  169 + }
  170 +
  171 + private void setListener() {
  172 + mAnimatorSet.addListener(animatorListener);
  173 + }
  174 +
  175 + /**
  176 + * 更新动画值.
  177 + *
  178 + * @param type
  179 + * @param w
  180 + * @param h
  181 + */
  182 + public void updateValues(int type, float w, float h) {
  183 + this.movementType = type;
  184 + this.offsetWidth = w;
  185 + this.offsetHeight = h;
  186 + init();
  187 + }
  188 +
  189 + public void setMovementType(int type) {
  190 + updateValues(type, offsetWidth, offsetHeight);
  191 + }
  192 +
  193 + public void setOffsets(float w, float h) {
  194 + updateValues(movementType, w, h);
  195 + }
  196 +
  197 + public void start() {
  198 + //Log.e("tag", "start.");
  199 + if (movementType != NONE_MOVE) {
  200 + isRunning = true;
  201 + if (!infiniteRepetition)
  202 + currentLoop = loopCount;
  203 + setListener();
  204 + mAnimatorSet.start();
  205 + currentState = MovingState.moving;
  206 + }
  207 + }
  208 +
  209 + public void cancel() {
  210 + if (isRunning) {
  211 + mAnimatorSet.removeListener(animatorListener);
  212 + mAnimatorSet.cancel();
  213 + currentState = MovingState.stop;
  214 + }
  215 + }
  216 +
  217 + @TargetApi(19)
  218 + public void pause() {
  219 + //Log.e("tag", "pause.");
  220 + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT)
  221 + return;
  222 +
  223 + if (mAnimatorSet.isStarted()) {
  224 + mAnimatorSet.pause();
  225 + currentState = MovingState.pause;
  226 + }
  227 + }
  228 +
  229 + @TargetApi(19)
  230 + public void resume() {
  231 + //Log.e("tag", "resume.");
  232 + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT)
  233 + return;
  234 +
  235 + if (mAnimatorSet.isPaused()) {
  236 + mAnimatorSet.resume();
  237 + currentState = MovingState.moving;
  238 + }
  239 + }
  240 +
  241 + public void stop() {
  242 + //Log.e("tag", "stop.");
  243 + isRunning = false;
  244 + mAnimatorSet.removeListener(animatorListener);
  245 + mAnimatorSet.end();
  246 + mView.clearAnimation();
  247 + currentState = MovingState.stop;
  248 + }
  249 +
  250 + /**
  251 + * 设置重复模式
  252 + *
  253 + * @param repetition repetition < 0 循环播放
  254 + * repetition > 0 循环repetition次
  255 + */
  256 + public void setRepetition(int repetition) {
  257 + if (repetition < 0)
  258 + infiniteRepetition = true;
  259 + else {
  260 + loopCount = repetition;
  261 + currentLoop = loopCount;
  262 + infiniteRepetition = false;
  263 + }
  264 + }
  265 +
  266 + public Builder addCustomMovement() {
  267 + return new Builder();
  268 + }
  269 +
  270 + public void clearCustomMovement() {
  271 + init();
  272 + start();
  273 + }
  274 +
  275 + public int getMovementType() {
  276 + return movementType;
  277 + }
  278 +
  279 + public int getRemainingRepetitions() {
  280 + return (infiniteRepetition) ? -1 : currentLoop;
  281 + }
  282 +
  283 + public void setInterpolator(Interpolator interpolator) {
  284 + mInterpolator = interpolator;
  285 + mAnimatorSet.setInterpolator(interpolator);
  286 + }
  287 +
  288 + /**
  289 + * 设置动画播放之前的延时时间
  290 + *
  291 + * @param time
  292 + */
  293 + public void setStartDelay(long time) {
  294 + mDelay = time;
  295 + mAnimatorSet.setStartDelay(time);
  296 + }
  297 +
  298 + /**
  299 + * 设置每个动画对应的持续时间
  300 + *
  301 + * @param speed
  302 + */
  303 + public void setSpeed(int speed) {
  304 + mSpeed = speed;
  305 + List<Animator> listAnimator = mAnimatorSet.getChildAnimations();
  306 + for (int i = 0; i < listAnimator.size(); i++) {
  307 + Animator a = listAnimator.get(i);
  308 + a.setDuration(parseSpeed(pathDistances.get(i)));
  309 + }
  310 + }
  311 +
  312 + /**
  313 + * 将速度设置值转换成秒
  314 + *
  315 + * @param distance
  316 + * @return
  317 + */
  318 + private long parseSpeed(float distance) {
  319 + return (long) ((distance / (float) mSpeed) * 1000f);
  320 + }
  321 +
  322 + /**
  323 + * 创建水平移动动画
  324 + *
  325 + * @param startValue
  326 + * @param endValue
  327 + * @return
  328 + */
  329 + private ObjectAnimator createHorizontalAnimator(float startValue, float endValue) {
  330 + pathDistances.add(Math.abs(startValue - endValue));
  331 + return createObjectAnimation("scrollX", startValue, endValue);
  332 + }
  333 +
  334 + /**
  335 + * 创建垂直移动动画
  336 + *
  337 + * @param startValue
  338 + * @param endValue
  339 + * @return
  340 + */
  341 + private ObjectAnimator createVerticalAnimator(float startValue, float endValue) {
  342 + pathDistances.add(Math.abs(startValue - endValue));
  343 + return createObjectAnimation("scrollY", startValue, endValue);
  344 + }
  345 +
  346 + /**
  347 + * 创建对角线移动动画
  348 + *
  349 + * @param startW
  350 + * @param endW
  351 + * @param startH
  352 + * @param endH
  353 + * @return
  354 + */
  355 + private ObjectAnimator createDiagonalAnimator(float startW, float endW, float startH, float
  356 + endH) {
  357 + float diagonal = Pythagoras(Math.abs(startW - endW), Math.abs(startH - endH));
  358 + pathDistances.add(diagonal);
  359 + PropertyValuesHolder pvhX = createPropertyValuesHolder("scrollX", startW, endW);
  360 + PropertyValuesHolder pvhY = createPropertyValuesHolder("scrollY", startH, endH);
  361 + return ObjectAnimator.ofPropertyValuesHolder(mView, pvhX, pvhY);
  362 + }
  363 +
  364 + private ObjectAnimator createObjectAnimation(String prop, float startValue, float endValue) {
  365 + return ObjectAnimator.ofInt(mView, prop, (int) startValue, (int) endValue);
  366 + }
  367 +
  368 + private PropertyValuesHolder createPropertyValuesHolder(String prop, float startValue, float
  369 + endValue) {
  370 + return PropertyValuesHolder.ofInt(prop, (int) startValue, (int) endValue);
  371 + }
  372 +
  373 + private static float Pythagoras(float a, float b) {
  374 + return (float) Math.sqrt((a * a) + (b * b));
  375 + }
  376 +
  377 + /**
  378 + * 自定义自动移动方式
  379 + */
  380 + public class Builder {
  381 +
  382 + private ArrayList<Animator> mList;
  383 +
  384 + private Builder() {
  385 + mList = new ArrayList<>();
  386 + pathDistances.clear();
  387 + }
  388 +
  389 + public Builder addHorizontalMoveToRight() {
  390 + mList.add(createHorizontalAnimator(0, offsetWidth));
  391 + return this;
  392 + }
  393 +
  394 + public Builder addHorizontalMoveToLeft() {
  395 + mList.add(createHorizontalAnimator(offsetWidth, 0));
  396 + return this;
  397 + }
  398 +
  399 + public Builder addVerticalMoveToDown() {
  400 + mList.add(createVerticalAnimator(0, offsetHeight));
  401 + return this;
  402 + }
  403 +
  404 + public Builder addVerticalMoveToUp() {
  405 + mList.add(createVerticalAnimator(offsetHeight, 0));
  406 + return this;
  407 + }
  408 +
  409 + public Builder addDiagonalMoveToDownRight() {
  410 + mList.add(createDiagonalAnimator(0, offsetWidth, 0, offsetHeight));
  411 + return this;
  412 + }
  413 +
  414 + public Builder addDiagonalMoveToDownLeft() {
  415 + mList.add(createDiagonalAnimator(offsetWidth, 0, 0, offsetHeight));
  416 + return this;
  417 + }
  418 +
  419 + public Builder addDiagonalMoveToUpRight() {
  420 + mList.add(createDiagonalAnimator(0, offsetWidth, offsetHeight, 0));
  421 + return this;
  422 + }
  423 +
  424 + public Builder addDiagonalMoveToUpLeft() {
  425 + mList.add(createDiagonalAnimator(offsetWidth, 0, offsetHeight, 0));
  426 + return this;
  427 + }
  428 +
  429 + public void start() {
  430 + mAnimatorSet.removeAllListeners();
  431 + stop();
  432 + mAnimatorSet = new AnimatorSet();
  433 + mAnimatorSet.playSequentially(mList);
  434 + setListener();
  435 + setUpValues();
  436 + MovingViewAnimator.this.start();
  437 + }
  438 + }
  439 +
  440 + /**
  441 + * 获取当前状态
  442 + *
  443 + * @return
  444 + */
  445 + public MovingState getMovingState() {
  446 + return currentState;
  447 + }
  448 +}
0 \ No newline at end of file 449 \ No newline at end of file
mvpsdk/src/main/java/com/share/mvpsdk/widgets/NestedScrollWebView.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/widgets/NestedScrollWebView.java
@@ -0,0 +1,168 @@ @@ -0,0 +1,168 @@
  1 +package com.share.mvpsdk.widgets;
  2 +
  3 +import android.content.Context;
  4 +import android.support.v4.view.MotionEventCompat;
  5 +import android.support.v4.view.NestedScrollingChild;
  6 +import android.support.v4.view.NestedScrollingChildHelper;
  7 +import android.support.v4.view.ViewCompat;
  8 +import android.util.AttributeSet;
  9 +import android.view.MotionEvent;
  10 +import android.webkit.WebView;
  11 +
  12 +/**
  13 + * Created by Horrarndoo on 2017/9/27.
  14 + * <p>
  15 + * 继承原生WebView,目的是为了和AppBarLayout、CollapsingToolbarLayout等Android Design Support Library控件配合使用。
  16 + * <p>
  17 + * 避免AppBarLayout+NestSrollView+WebView嵌套导致的WebView高度判断异常导致WebView跳转后高度异常的问题;
  18 + */
  19 +public class NestedScrollWebView extends WebView implements NestedScrollingChild {
  20 +
  21 + public static final String TAG = NestedScrollWebView.class.getSimpleName();
  22 +
  23 + private int mLastMotionY;
  24 +
  25 + private final int[] mScrollOffset = new int[2];
  26 + private final int[] mScrollConsumed = new int[2];
  27 +
  28 + private int mNestedYOffset;
  29 + private boolean mChange;
  30 +
  31 + private NestedScrollingChildHelper mChildHelper;
  32 +
  33 + public NestedScrollWebView(Context context) {
  34 + super(context);
  35 + init();
  36 + }
  37 +
  38 + public NestedScrollWebView(Context context, AttributeSet attrs) {
  39 + super(context, attrs);
  40 + init();
  41 + }
  42 +
  43 + public NestedScrollWebView(Context context, AttributeSet attrs, int defStyleAttr) {
  44 + super(context, attrs, defStyleAttr);
  45 + init();
  46 + }
  47 +
  48 + private void init() {
  49 + mChildHelper = new NestedScrollingChildHelper(this);
  50 + setNestedScrollingEnabled(true);
  51 + }
  52 +
  53 + @Override
  54 + public boolean onTouchEvent(MotionEvent event) {
  55 + boolean result = false;
  56 +
  57 + MotionEvent trackedEvent = MotionEvent.obtain(event);
  58 +
  59 + final int action = MotionEventCompat.getActionMasked(event);
  60 +
  61 + if (action == MotionEvent.ACTION_DOWN) {
  62 + mNestedYOffset = 0;
  63 + }
  64 +
  65 + int y = (int) event.getY();
  66 +
  67 + event.offsetLocation(0, mNestedYOffset);
  68 +
  69 + switch (action) {
  70 + case MotionEvent.ACTION_DOWN:
  71 + mLastMotionY = y;
  72 + startNestedScroll(ViewCompat.SCROLL_AXIS_VERTICAL);
  73 + result = super.onTouchEvent(event);
  74 + mChange = false;
  75 + break;
  76 + case MotionEvent.ACTION_MOVE:
  77 + int deltaY = mLastMotionY - y;
  78 +
  79 + if (dispatchNestedPreScroll(0, deltaY, mScrollConsumed, mScrollOffset)) {
  80 + deltaY -= mScrollConsumed[1];
  81 + trackedEvent.offsetLocation(0, mScrollOffset[1]);
  82 + mNestedYOffset += mScrollOffset[1];
  83 + }
  84 +
  85 + int oldY = getScrollY();
  86 + mLastMotionY = y - mScrollOffset[1];
  87 + int newScrollY = Math.max(0, oldY + deltaY);
  88 + deltaY -= newScrollY - oldY;
  89 + if (dispatchNestedScroll(0, newScrollY - deltaY, 0, deltaY, mScrollOffset)) {
  90 + mLastMotionY -= mScrollOffset[1];
  91 + trackedEvent.offsetLocation(0, mScrollOffset[1]);
  92 + mNestedYOffset += mScrollOffset[1];
  93 + }
  94 + if (mScrollConsumed[1] == 0 && mScrollOffset[1] == 0) {
  95 + if (mChange) {
  96 + mChange = false;
  97 + trackedEvent.setAction(MotionEvent.ACTION_DOWN);
  98 + super.onTouchEvent(trackedEvent);
  99 + } else {
  100 + result = super.onTouchEvent(trackedEvent);
  101 + }
  102 + trackedEvent.recycle();
  103 + } else {
  104 + if (!mChange) {
  105 + mChange = true;
  106 + super.onTouchEvent(MotionEvent.obtain(0, 0, MotionEvent.ACTION_CANCEL, 0,
  107 + 0, 0));
  108 + }
  109 + }
  110 + break;
  111 + case MotionEvent.ACTION_POINTER_DOWN:
  112 + case MotionEvent.ACTION_UP:
  113 + case MotionEvent.ACTION_CANCEL:
  114 + stopNestedScroll();
  115 + result = super.onTouchEvent(event);
  116 + break;
  117 + }
  118 + return result;
  119 + }
  120 +
  121 + // NestedScrollingChild
  122 + @Override
  123 + public void setNestedScrollingEnabled(boolean enabled) {
  124 + mChildHelper.setNestedScrollingEnabled(enabled);
  125 + }
  126 +
  127 + @Override
  128 + public boolean isNestedScrollingEnabled() {
  129 + return mChildHelper.isNestedScrollingEnabled();
  130 + }
  131 +
  132 + @Override
  133 + public boolean startNestedScroll(int axes) {
  134 + return mChildHelper.startNestedScroll(axes);
  135 + }
  136 +
  137 + @Override
  138 + public void stopNestedScroll() {
  139 + mChildHelper.stopNestedScroll();
  140 + }
  141 +
  142 + @Override
  143 + public boolean hasNestedScrollingParent() {
  144 + return mChildHelper.hasNestedScrollingParent();
  145 + }
  146 +
  147 + @Override
  148 + public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed, int
  149 + dyUnconsumed, int[] offsetInWindow) {
  150 + return mChildHelper.dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed,
  151 + dyUnconsumed, offsetInWindow);
  152 + }
  153 +
  154 + @Override
  155 + public boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] offsetInWindow) {
  156 + return mChildHelper.dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow);
  157 + }
  158 +
  159 + @Override
  160 + public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
  161 + return mChildHelper.dispatchNestedFling(velocityX, velocityY, consumed);
  162 + }
  163 +
  164 + @Override
  165 + public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
  166 + return mChildHelper.dispatchNestedPreFling(velocityX, velocityY);
  167 + }
  168 +}
0 \ No newline at end of file 169 \ No newline at end of file
mvpsdk/src/main/java/com/share/mvpsdk/widgets/PickerView.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/widgets/PickerView.java
@@ -0,0 +1,314 @@ @@ -0,0 +1,314 @@
  1 +package com.share.mvpsdk.widgets;
  2 +
  3 +import android.content.Context;
  4 +import android.graphics.Canvas;
  5 +import android.graphics.Paint;
  6 +import android.graphics.Paint.Align;
  7 +import android.graphics.Paint.FontMetricsInt;
  8 +import android.graphics.Paint.Style;
  9 +import android.os.Handler;
  10 +import android.os.Message;
  11 +import android.util.AttributeSet;
  12 +import android.view.MotionEvent;
  13 +import android.view.View;
  14 +
  15 +import java.util.ArrayList;
  16 +import java.util.List;
  17 +import java.util.Timer;
  18 +import java.util.TimerTask;
  19 +
  20 +/**
  21 + * Created by Horrarndoo on 2017/4/5.
  22 + * <p>
  23 + * 滚动选择器
  24 + */
  25 +public class PickerView extends View {
  26 +
  27 + public static final String TAG = "PickerView";
  28 + /**
  29 + * text之间间距和minTextSize之比
  30 + */
  31 + public static final float MARGIN_ALPHA = 2.8f;
  32 + /**
  33 + * 自动回滚到中间的速度
  34 + */
  35 + public static final float SPEED = 2;
  36 +
  37 + private List<String> mDataList;
  38 + /**
  39 + * 选中的位置,这个位置是mDataList的中心位置,一直不变
  40 + */
  41 + private int mCurrentSelected;
  42 + private Paint mPaint;
  43 +
  44 + private float mMaxTextSize = 80;
  45 + private float mMinTextSize = 50;
  46 + // private float mMinTextSize = 40;
  47 +
  48 + private float mMaxTextAlpha = 255;
  49 + private float mMinTextAlpha = 120;
  50 +
  51 + private int mColorText = 0xFF9500;// 森威尔的黄色
  52 +
  53 + private int mViewHeight;
  54 + private int mViewWidth;
  55 +
  56 + private float mLastDownY;
  57 + /**
  58 + * 滑动的距离
  59 + */
  60 + private float mMoveLen = 0;
  61 + private boolean isInit = false;
  62 + private onSelectListener mSelectListener;
  63 + private Timer timer;
  64 + private MyTimerTask mTask;
  65 +
  66 + Handler updateHandler = new Handler() {
  67 + @Override
  68 + public void handleMessage(Message msg) {
  69 + if (Math.abs(mMoveLen) < SPEED) {
  70 + mMoveLen = 0;
  71 + if (mTask != null) {
  72 + mTask.cancel();
  73 + mTask = null;
  74 + performSelect();
  75 + }
  76 + } else
  77 + // 这里mMoveLen / Math.abs(mMoveLen)是为了保有mMoveLen的正负号,以实现上滚或下滚
  78 + mMoveLen = mMoveLen - mMoveLen / Math.abs(mMoveLen) * SPEED;
  79 + invalidate();
  80 + }
  81 +
  82 + };
  83 +
  84 + public PickerView(Context context) {
  85 + super(context);
  86 + init();
  87 + }
  88 +
  89 + public PickerView(Context context, AttributeSet attrs) {
  90 + super(context, attrs);
  91 + init();
  92 + }
  93 +
  94 + public void setOnSelectListener(onSelectListener listener) {
  95 + mSelectListener = listener;
  96 + }
  97 +
  98 + private void performSelect() {
  99 + if (mSelectListener != null)
  100 + mSelectListener.onSelect(mDataList.get(mCurrentSelected));
  101 + }
  102 +
  103 + public void setData(List<String> datas) {
  104 + mDataList = datas;
  105 + mCurrentSelected = datas.size() / 2;
  106 + invalidate();
  107 + }
  108 +
  109 + /**
  110 + * 选择选中的item的index
  111 + *
  112 + * @param selected
  113 + */
  114 + public void setSelected(int selected) {
  115 + mCurrentSelected = selected;
  116 + int distance = mDataList.size() / 2 - mCurrentSelected;
  117 + if (distance < 0)
  118 + for (int i = 0; i < -distance; i++) {
  119 + moveHeadToTail();
  120 + mCurrentSelected--;
  121 + }
  122 + else if (distance > 0)
  123 + for (int i = 0; i < distance; i++) {
  124 + moveTailToHead();
  125 + mCurrentSelected++;
  126 + }
  127 + invalidate();
  128 + }
  129 +
  130 + /**
  131 + * 选择选中的内容
  132 + *
  133 + * @param mSelectItem
  134 + */
  135 + public void setSelected(String mSelectItem) {
  136 + for (int i = 0; i < mDataList.size(); i++)
  137 + if (mDataList.get(i).equals(mSelectItem)) {
  138 + setSelected(i);
  139 + break;
  140 + }
  141 + }
  142 +
  143 + private void moveHeadToTail() {
  144 + String head = mDataList.get(0);
  145 + mDataList.remove(0);
  146 + mDataList.add(head);
  147 + }
  148 +
  149 + private void moveTailToHead() {
  150 + String tail = mDataList.get(mDataList.size() - 1);
  151 + mDataList.remove(mDataList.size() - 1);
  152 + mDataList.add(0, tail);
  153 + }
  154 +
  155 + @Override
  156 + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  157 + super.onMeasure(widthMeasureSpec, heightMeasureSpec);
  158 + mViewHeight = getMeasuredHeight();
  159 + mViewWidth = getMeasuredWidth();
  160 + // 按照View的高度计算字体大小
  161 + mMaxTextSize = mViewHeight / 4.0f;
  162 + mMinTextSize = mMaxTextSize / 2f;
  163 + isInit = true;
  164 + invalidate();
  165 + }
  166 +
  167 + private void init() {
  168 + timer = new Timer();
  169 + mDataList = new ArrayList<String>();
  170 + mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
  171 + mPaint.setStyle(Style.FILL);
  172 + mPaint.setTextAlign(Align.CENTER);
  173 + mPaint.setColor(mColorText);
  174 + }
  175 +
  176 + @Override
  177 + protected void onDraw(Canvas canvas) {
  178 + super.onDraw(canvas);
  179 + // 根据index绘制view
  180 + if (isInit)
  181 + drawData(canvas);
  182 + }
  183 +
  184 + private void drawData(Canvas canvas) {
  185 + // 先绘制选中的text再往上往下绘制其余的text
  186 + float scale = parabola(mViewHeight / 4.0f, mMoveLen);
  187 + float size = (mMaxTextSize - mMinTextSize) * scale + mMinTextSize;
  188 + mPaint.setTextSize(size);
  189 + mPaint.setAlpha((int) ((mMaxTextAlpha - mMinTextAlpha) * scale + mMinTextAlpha));
  190 + // text居中绘制,注意baseline的计算才能达到居中,y值是text中心坐标
  191 + float x = (float) (mViewWidth / 2.0);
  192 + float y = (float) (mViewHeight / 2.0 + mMoveLen);
  193 + FontMetricsInt fmi = mPaint.getFontMetricsInt();
  194 + float baseline = (float) (y - (fmi.bottom / 2.0 + fmi.top / 2.0));
  195 + if (mDataList.size() > 0) {
  196 + canvas.drawText(mDataList.get(mCurrentSelected), x, baseline,
  197 + mPaint);
  198 + }
  199 + // 绘制上方data
  200 + for (int i = 1; (mCurrentSelected - i) >= 0; i++) {
  201 + drawOtherText(canvas, i, -1);
  202 + }
  203 + // 绘制下方data
  204 + for (int i = 1; (mCurrentSelected + i) < mDataList.size(); i++) {
  205 + drawOtherText(canvas, i, 1);
  206 + }
  207 + }
  208 +
  209 + /**
  210 + * @param canvas
  211 + * @param position 距离mCurrentSelected的差值
  212 + * @param type 1表示向下绘制,-1表示向上绘制
  213 + */
  214 + private void drawOtherText(Canvas canvas, int position, int type) {
  215 + float d = (float) (MARGIN_ALPHA * mMinTextSize * position + type
  216 + * mMoveLen);
  217 + float scale = parabola(mViewHeight / 4.0f, d);
  218 + float size = (mMaxTextSize - mMinTextSize) * scale + mMinTextSize;
  219 + mPaint.setTextSize(size);
  220 + mPaint.setAlpha((int) ((mMaxTextAlpha - mMinTextAlpha) * scale + mMinTextAlpha));
  221 + float y = (float) (mViewHeight / 2.0 + type * d);
  222 + FontMetricsInt fmi = mPaint.getFontMetricsInt();
  223 + float baseline = (float) (y - (fmi.bottom / 2.0 + fmi.top / 2.0));
  224 + canvas.drawText(mDataList.get(mCurrentSelected + type * position),
  225 + (float) (mViewWidth / 2.0), baseline, mPaint);
  226 + }
  227 +
  228 + /**
  229 + * 抛物线
  230 + *
  231 + * @param zero 零点坐标
  232 + * @param x 偏移量
  233 + * @return scale
  234 + */
  235 + private float parabola(float zero, float x) {
  236 + float f = (float) (1 - Math.pow(x / zero, 2));
  237 + return f < 0 ? 0 : f;
  238 + }
  239 +
  240 + @Override
  241 + public boolean onTouchEvent(MotionEvent event) {
  242 + switch (event.getActionMasked()) {
  243 + case MotionEvent.ACTION_DOWN:
  244 + doDown(event);
  245 + break;
  246 + case MotionEvent.ACTION_MOVE:
  247 + doMove(event);
  248 + break;
  249 + case MotionEvent.ACTION_UP:
  250 + doUp(event);
  251 + break;
  252 + }
  253 + return true;
  254 + }
  255 +
  256 + private void doDown(MotionEvent event) {
  257 + if (mTask != null) {
  258 + mTask.cancel();
  259 + mTask = null;
  260 + }
  261 + mLastDownY = event.getY();
  262 + }
  263 +
  264 + private void doMove(MotionEvent event) {
  265 +
  266 + mMoveLen += (event.getY() - mLastDownY);
  267 +
  268 + if (mMoveLen > MARGIN_ALPHA * mMinTextSize / 2) {
  269 + // 往下滑超过离开距离
  270 + moveTailToHead();
  271 + mMoveLen = mMoveLen - MARGIN_ALPHA * mMinTextSize;
  272 + } else if (mMoveLen < -MARGIN_ALPHA * mMinTextSize / 2) {
  273 + // 往上滑超过离开距离
  274 + moveHeadToTail();
  275 + mMoveLen = mMoveLen + MARGIN_ALPHA * mMinTextSize;
  276 + }
  277 +
  278 + mLastDownY = event.getY();
  279 + invalidate();
  280 + }
  281 +
  282 + private void doUp(MotionEvent event) {
  283 + // 抬起手后mCurrentSelected的位置由当前位置move到中间选中位置
  284 + if (Math.abs(mMoveLen) < 0.0001) {
  285 + mMoveLen = 0;
  286 + return;
  287 + }
  288 + if (mTask != null) {
  289 + mTask.cancel();
  290 + mTask = null;
  291 + }
  292 + mTask = new MyTimerTask(updateHandler);
  293 + timer.schedule(mTask, 0, 10);
  294 + }
  295 +
  296 + class MyTimerTask extends TimerTask {
  297 + Handler handler;
  298 +
  299 + public MyTimerTask(Handler handler) {
  300 + this.handler = handler;
  301 + }
  302 +
  303 + @Override
  304 + public void run() {
  305 + handler.sendMessage(handler.obtainMessage());
  306 + }
  307 +
  308 + }
  309 +
  310 + public interface onSelectListener {
  311 + void onSelect(String text);
  312 + }
  313 +}
  314 +
mvpsdk/src/main/java/com/share/mvpsdk/widgets/ProgressButton.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/widgets/ProgressButton.java
@@ -0,0 +1,79 @@ @@ -0,0 +1,79 @@
  1 +package com.share.mvpsdk.widgets;
  2 +
  3 +
  4 +import android.content.Context;
  5 +import android.graphics.Canvas;
  6 +import android.graphics.Color;
  7 +import android.graphics.Paint;
  8 +import android.graphics.Paint.Style;
  9 +import android.graphics.RectF;
  10 +import android.util.AttributeSet;
  11 +import android.widget.Button;
  12 +
  13 +import com.share.mvpsdk.R;
  14 +
  15 +
  16 +/**
  17 + * Created by Horrarndoo on 2017/4/5.
  18 + * <p>
  19 + * 带有进度变化的button
  20 + */
  21 +public class ProgressButton extends Button {
  22 + public static final int MAX_PROGRESS = 1000;
  23 + private boolean isAdding = false;
  24 + private int progress = 0;
  25 + private int progressStrokeWidth = 6;
  26 +
  27 + private Paint mPaint;
  28 + private RectF dst;
  29 +
  30 + private Context context;
  31 +
  32 + public ProgressButton(Context context, AttributeSet attrs) {
  33 + super(context, attrs);
  34 + dst = new RectF();
  35 + mPaint = new Paint();
  36 + mPaint.setAntiAlias(true);
  37 + mPaint.setStyle(Style.STROKE);
  38 + mPaint.setStrokeWidth(progressStrokeWidth);
  39 + this.context = context;
  40 + }
  41 +
  42 + @Override
  43 + protected void onDraw(Canvas canvas) {
  44 + super.onDraw(canvas);
  45 +
  46 + int width = this.getWidth();
  47 + int height = this.getHeight();
  48 +
  49 + if (width != height) {
  50 + int min = Math.min(width, height);
  51 + width = min;
  52 + height = min;
  53 + }
  54 +
  55 + mPaint.setColor(context.getResources().getColor(R.color.dark_grey));
  56 + canvas.drawColor(Color.TRANSPARENT);
  57 +
  58 + dst.left = progressStrokeWidth / 2; // 左上角x
  59 + dst.top = progressStrokeWidth / 2; // 左上角y
  60 + dst.right = width - progressStrokeWidth / 2; // 左下角x
  61 + dst.bottom = height - progressStrokeWidth / 2; // 右下角y
  62 +
  63 + canvas.drawArc(dst, -90, 360, false, mPaint);
  64 +
  65 + if (isAdding) {
  66 + mPaint.setColor(context.getResources().getColor(R.color.light_yellow));
  67 + canvas.drawArc(dst, -90, ((float) progress / MAX_PROGRESS) * 360, false, mPaint);
  68 + }
  69 + }
  70 +
  71 + /**
  72 + * 非UI线程调用
  73 + */
  74 + public void setProgressNotInUiThread(int progress, boolean isAdding) {
  75 + this.isAdding = isAdding;
  76 + this.progress = progress;
  77 + this.postInvalidate();
  78 + }
  79 +}
0 \ No newline at end of file 80 \ No newline at end of file
mvpsdk/src/main/java/com/share/mvpsdk/widgets/SlideSwitchView.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/widgets/SlideSwitchView.java
@@ -0,0 +1,259 @@ @@ -0,0 +1,259 @@
  1 +package com.share.mvpsdk.widgets;
  2 +
  3 +import android.content.Context;
  4 +import android.content.res.TypedArray;
  5 +import android.graphics.Bitmap;
  6 +import android.graphics.BitmapFactory;
  7 +import android.graphics.Canvas;
  8 +import android.graphics.Color;
  9 +import android.graphics.Matrix;
  10 +import android.graphics.Paint;
  11 +import android.util.AttributeSet;
  12 +import android.view.MotionEvent;
  13 +import android.view.View;
  14 +
  15 +import com.share.mvpsdk.R;
  16 +
  17 +
  18 +/**
  19 + * Created by Horrarndoo on 2017/6/1.
  20 + * <p>
  21 + * 自定义滑动开关
  22 + * <p>
  23 + * Android 的界面绘制流程
  24 + * 测量 摆放 绘制
  25 + * measure -> layout -> draw
  26 + * | | |
  27 + * onMeasure -> onLayout -> onDraw 重写这些方法, 实现自定义控件
  28 + * <p>
  29 + * onResume()之后执行
  30 + * <p>
  31 + * View
  32 + * onMeasure() (在这个方法里指定自己的宽高) -> onDraw() (绘制自己的内容)
  33 + * <p>
  34 + * ViewGroup
  35 + * onMeasure() (指定自己的宽高, 所有子View的宽高)-> onLayout() (摆放所有子View) -> onDraw() (绘制内容)
  36 + */
  37 +public class SlideSwitchView extends View {
  38 + private Bitmap slideButtonBitmap; // 滑块图片
  39 + private Paint mPaint; // 画笔
  40 + private float currentX; //当前滑动的x坐标
  41 + private int mBaseLineY; // text基准线
  42 + private String mTextContent; //text内容
  43 +
  44 + public SlideSwitchView(Context context) {
  45 + this(context, null);
  46 + }
  47 +
  48 + public SlideSwitchView(Context context, AttributeSet attrs) {
  49 + this(context, attrs, 0);
  50 + }
  51 +
  52 + public SlideSwitchView(Context context, AttributeSet attrs, int defStyle) {
  53 + super(context, attrs, defStyle);
  54 + initPaint();
  55 + TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.SlideSwitchView);
  56 + setSlideButtonResource(ta.getResourceId(R.styleable.SlideSwitchView_slide_button, -1));
  57 + setText(ta.getString(R.styleable.SlideSwitchView_android_text));
  58 + setTextSize(ta.getDimension(R.styleable.SlideSwitchView_android_textSize, 30));
  59 + setTextColor(ta.getColor(R.styleable.SlideSwitchView_android_textColor, Color.BLACK));
  60 + ta.recycle();
  61 + }
  62 +
  63 + /**
  64 + * 初始化画笔
  65 + */
  66 + private void initPaint() {
  67 + mPaint = new Paint();
  68 + mPaint.setStyle(Paint.Style.FILL);
  69 + mPaint.setTextAlign(Paint.Align.LEFT);
  70 + mPaint.setAntiAlias(true);
  71 + }
  72 +
  73 + /**
  74 + * 初始化text居中基准线
  75 + */
  76 + private void initTextBaseLine() {
  77 + Paint.FontMetrics fontMetrics = mPaint.getFontMetrics();
  78 + float top = fontMetrics.top;//为基线到字体上边框的距离,即上图中的top
  79 + float bottom = fontMetrics.bottom;//为基线到字体下边框的距离,即上图中的bottom
  80 + mBaseLineY = (int) (getMeasuredHeight() / 2 - top / 2 - bottom / 2);//基线中间点的y轴计算公式
  81 + }
  82 +
  83 + @Override
  84 + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  85 + int widthMode = MeasureSpec.getMode(widthMeasureSpec);
  86 + int heightMode = MeasureSpec.getMode(heightMeasureSpec);
  87 + int width = MeasureSpec.getSize(widthMeasureSpec);
  88 + int height = MeasureSpec.getSize(heightMeasureSpec);
  89 +
  90 + if (widthMode == MeasureSpec.AT_MOST) {
  91 + int newWidth = (int) (slideButtonBitmap.getWidth() * 2 + getTextWidth());
  92 + if (width >= newWidth)
  93 + width = newWidth;
  94 + }
  95 +
  96 + if (heightMode == MeasureSpec.EXACTLY) {
  97 + if (height < slideButtonBitmap.getHeight()) {
  98 + // 获得图片的宽高
  99 + int widthSlide = slideButtonBitmap.getWidth();
  100 + int heightSlide = slideButtonBitmap.getHeight();
  101 + float scaleHeight = height * 1.0f / slideButtonBitmap.getHeight();
  102 + Matrix matrix = new Matrix();
  103 + matrix.postScale(scaleHeight, scaleHeight);
  104 + slideButtonBitmap = Bitmap.createBitmap(slideButtonBitmap, 0, 0, widthSlide,
  105 + heightSlide, matrix, true);
  106 + invalidate();
  107 + }
  108 + }
  109 +
  110 + if (slideButtonBitmap.getWidth() > (width - getTextWidth()) / 2) {
  111 + // 获得图片的宽高
  112 + int widthSlide = slideButtonBitmap.getWidth();
  113 + int heightSlide = slideButtonBitmap.getHeight();
  114 + float scaleWidth = (width - getTextWidth()) / 2 / slideButtonBitmap.getWidth();
  115 + Matrix matrix = new Matrix();
  116 + matrix.postScale(scaleWidth, scaleWidth);
  117 + slideButtonBitmap = Bitmap.createBitmap(slideButtonBitmap, 0, 0, widthSlide,
  118 + heightSlide, matrix, true);
  119 + invalidate();
  120 + }
  121 +
  122 + setMeasuredDimension(width, slideButtonBitmap.getHeight());
  123 + initTextBaseLine();
  124 + }
  125 +
  126 + // Canvas 画布, 画板. 在上边绘制的内容都会显示到界面上.
  127 + @Override
  128 + protected void onDraw(Canvas canvas) {
  129 + // 1. 绘制text
  130 + canvas.drawText(mTextContent, slideButtonBitmap.getWidth(), mBaseLineY, mPaint);
  131 +
  132 + // 2. 绘制滑块
  133 + if (isTouchMode) {
  134 + // 根据当前用户触摸到的位置画滑块
  135 + // 让滑块向左移动自身一半大小的位置
  136 + float newLeft = currentX - slideButtonBitmap.getWidth() / 2.0f;
  137 +
  138 + int maxLeft = getMeasuredWidth() - slideButtonBitmap.getWidth();
  139 +
  140 + // 限定滑块范围
  141 + if (newLeft < 0) {
  142 + newLeft = 0; // 左边范围
  143 + } else if (newLeft > maxLeft) {
  144 + newLeft = maxLeft; // 右边范围
  145 + }
  146 +
  147 + canvas.drawBitmap(slideButtonBitmap, newLeft, 0, mPaint);
  148 + } else {
  149 + //还原button位置
  150 + canvas.drawBitmap(slideButtonBitmap, 0, 0, mPaint);
  151 + }
  152 +
  153 + }
  154 +
  155 + boolean isTouchMode = false;
  156 + private OnSwitchStateUpdateListener onSwitchStateUpdateListener;
  157 +
  158 + // 重写触摸事件, 响应用户的触摸.
  159 + @Override
  160 + public boolean onTouchEvent(MotionEvent event) {
  161 +
  162 + switch (event.getAction()) {
  163 + case MotionEvent.ACTION_DOWN:
  164 + isTouchMode = true;
  165 + currentX = event.getX();
  166 + break;
  167 + case MotionEvent.ACTION_MOVE:
  168 + currentX = event.getX();
  169 + break;
  170 + case MotionEvent.ACTION_UP:
  171 + isTouchMode = false;
  172 + currentX = event.getX();
  173 +
  174 + float center = getMeasuredWidth() / 2.0f;
  175 +
  176 + // 根据当前按下的位置, 和控件中心的位置进行比较.
  177 + boolean isStateChanged = currentX > center;
  178 +
  179 + // 如果开关状态变化了, 通知界面
  180 + if (isStateChanged && onSwitchStateUpdateListener != null) {
  181 + onSwitchStateUpdateListener.onStateUpdate();
  182 + }
  183 + break;
  184 +
  185 + default:
  186 + break;
  187 + }
  188 +
  189 + // 重绘界面
  190 + invalidate(); // 会引发onDraw()被调用, 里边的变量会重新生效.界面会更新
  191 +
  192 + return true; // 消费了用户的触摸事件, 才可以收到其他的事件.
  193 + }
  194 +
  195 + /**
  196 + * 设置滑块图片资源
  197 + *
  198 + * @param slideButton 滑块图片资源
  199 + */
  200 + public void setSlideButtonResource(int slideButton) {
  201 + slideButtonBitmap = BitmapFactory.decodeResource(getResources(), slideButton);
  202 + }
  203 +
  204 + /**
  205 + * 设置text字号大小
  206 + *
  207 + * @param textSize text字号大小
  208 + */
  209 + public void setTextSize(float textSize) {
  210 + mPaint.setTextSize(textSize);
  211 + mPaint.setStrokeWidth(textSize / 15.f);
  212 + }
  213 +
  214 + /**
  215 + * 设置text内容
  216 + *
  217 + * @param text text内容
  218 + */
  219 + public void setText(String text) {
  220 + mTextContent = text;
  221 + }
  222 +
  223 + /**
  224 + * 设置text颜色
  225 + *
  226 + * @param color text颜色资源
  227 + */
  228 + public void setTextColor(int color) {
  229 + mPaint.setColor(color);
  230 + }
  231 +
  232 + /**
  233 + * 获取text文字宽度
  234 + *
  235 + * @return text文字宽度
  236 + */
  237 + private float getTextWidth() {
  238 + return mPaint.measureText(mTextContent);
  239 + }
  240 +
  241 + /**
  242 + * 获取text文字高度
  243 + *
  244 + * @return text文字高度
  245 + */
  246 + private float getTextHeight() {
  247 + return mPaint.getFontMetrics().bottom - mPaint.getFontMetrics().top;
  248 + }
  249 +
  250 + public interface OnSwitchStateUpdateListener {
  251 + // 状态回调
  252 + void onStateUpdate();
  253 + }
  254 +
  255 + public void setOnSwitchStateUpdateListener(
  256 + OnSwitchStateUpdateListener onSwitchStateUpdateListener) {
  257 + this.onSwitchStateUpdateListener = onSwitchStateUpdateListener;
  258 + }
  259 +}
0 \ No newline at end of file 260 \ No newline at end of file
mvpsdk/src/main/java/com/share/mvpsdk/widgets/WaitPorgressDialog.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/widgets/WaitPorgressDialog.java
@@ -0,0 +1,22 @@ @@ -0,0 +1,22 @@
  1 +package com.share.mvpsdk.widgets;
  2 +
  3 +import android.app.ProgressDialog;
  4 +import android.content.Context;
  5 +
  6 +/**
  7 + * Created by Horrarndoo on 2017/4/17.
  8 + * <p>
  9 + * 等待提示dialog
  10 + */
  11 +
  12 +public class WaitPorgressDialog extends ProgressDialog {
  13 +
  14 + public WaitPorgressDialog(Context context) {
  15 + this(context, 0);
  16 + }
  17 +
  18 + public WaitPorgressDialog(Context context, int theme) {
  19 + super(context, theme);
  20 + setCanceledOnTouchOutside(false);
  21 + }
  22 +}
mvpsdk/src/main/java/com/share/mvpsdk/widgets/headclip/ClipView.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/widgets/headclip/ClipView.java
@@ -0,0 +1,157 @@ @@ -0,0 +1,157 @@
  1 +package com.share.mvpsdk.widgets.headclip;
  2 +
  3 +/**
  4 + * Created by Horrarndoo on 2017/9/25.
  5 + * <p>
  6 + */
  7 +
  8 +import android.content.Context;
  9 +import android.graphics.Canvas;
  10 +import android.graphics.Color;
  11 +import android.graphics.Paint;
  12 +import android.graphics.PorterDuff;
  13 +import android.graphics.PorterDuffXfermode;
  14 +import android.graphics.Rect;
  15 +import android.graphics.Xfermode;
  16 +import android.util.AttributeSet;
  17 +import android.util.DisplayMetrics;
  18 +import android.view.View;
  19 +import android.view.WindowManager;
  20 +
  21 +/**
  22 + * 头像上传裁剪框
  23 + */
  24 +public class ClipView extends View {
  25 + private Paint paint = new Paint();
  26 + //画裁剪区域边框的画笔
  27 + private Paint borderPaint = new Paint();
  28 + //裁剪框水平方向间距
  29 + private float mHorizontalPadding;
  30 + //裁剪框边框宽度
  31 + private int clipBorderWidth;
  32 + //裁剪圆框的半径
  33 + private int clipRadiusWidth;
  34 + //裁剪框矩形宽度
  35 + private int clipWidth;
  36 + //裁剪框类别,(圆形、矩形),默认为圆形
  37 + private ClipType clipType = ClipType.CIRCLE;
  38 + private Xfermode xfermode;
  39 +
  40 + public ClipView(Context context) {
  41 + this(context, null);
  42 + }
  43 +
  44 + public ClipView(Context context, AttributeSet attrs) {
  45 + this(context, attrs, 0);
  46 + }
  47 +
  48 + public ClipView(Context context, AttributeSet attrs, int defStyle) {
  49 + super(context, attrs, defStyle);
  50 + //去锯齿
  51 + paint.setAntiAlias(true);
  52 + borderPaint.setStyle(Paint.Style.STROKE);
  53 + borderPaint.setColor(Color.WHITE);
  54 + borderPaint.setStrokeWidth(clipBorderWidth);
  55 + borderPaint.setAntiAlias(true);
  56 + xfermode = new PorterDuffXfermode(PorterDuff.Mode.DST_OUT);
  57 + }
  58 +
  59 + @Override
  60 + protected void onDraw(Canvas canvas) {
  61 + super.onDraw(canvas);
  62 + int LAYER_FLAGS = Canvas.MATRIX_SAVE_FLAG | Canvas.CLIP_SAVE_FLAG
  63 + | Canvas.HAS_ALPHA_LAYER_SAVE_FLAG | Canvas.FULL_COLOR_LAYER_SAVE_FLAG
  64 + | Canvas.CLIP_TO_LAYER_SAVE_FLAG;
  65 + //通过Xfermode的DST_OUT来产生中间的透明裁剪区域,一定要另起一个Layer(层)
  66 + canvas.saveLayer(0, 0, this.getWidth(), this.getHeight(), null, LAYER_FLAGS);
  67 + //设置背景
  68 + canvas.drawColor(Color.parseColor("#a8000000"));
  69 + paint.setXfermode(xfermode);
  70 + //绘制圆形裁剪框
  71 + if (clipType == ClipType.CIRCLE) {
  72 + //中间的透明的圆
  73 + canvas.drawCircle(this.getWidth() / 2, this.getHeight() / 2, clipRadiusWidth, paint);
  74 + //白色的圆边框
  75 + canvas.drawCircle(this.getWidth() / 2, this.getHeight() / 2, clipRadiusWidth, borderPaint);
  76 + } else if (clipType == ClipType.RECTANGLE) { //绘制矩形裁剪框
  77 + //绘制中间的矩形
  78 + canvas.drawRect(mHorizontalPadding, this.getHeight() / 2 - clipWidth / 2,
  79 + this.getWidth() - mHorizontalPadding, this.getHeight() / 2 + clipWidth / 2, paint);
  80 + //绘制白色的矩形边框
  81 + canvas.drawRect(mHorizontalPadding, this.getHeight() / 2 - clipWidth / 2,
  82 + this.getWidth() - mHorizontalPadding, this.getHeight() / 2 + clipWidth / 2, borderPaint);
  83 + }
  84 + //出栈,恢复到之前的图层,意味着新建的图层会被删除,新建图层上的内容会被绘制到canvas (or the previous layer)
  85 + canvas.restore();
  86 + }
  87 +
  88 + /**
  89 + * 获取裁剪区域的Rect
  90 + *
  91 + * @return
  92 + */
  93 + public Rect getClipRect() {
  94 + Rect rect = new Rect();
  95 + //宽度的一半 - 圆的半径
  96 + rect.left = (this.getWidth() / 2 - clipRadiusWidth);
  97 + //宽度的一半 + 圆的半径
  98 + rect.right = (this.getWidth() / 2 + clipRadiusWidth);
  99 + //高度的一半 - 圆的半径
  100 + rect.top = (this.getHeight() / 2 - clipRadiusWidth);
  101 + //高度的一半 + 圆的半径
  102 + rect.bottom = (this.getHeight() / 2 + clipRadiusWidth);
  103 + return rect;
  104 + }
  105 +
  106 + /**
  107 + * 设置裁剪框边框宽度
  108 + *
  109 + * @param clipBorderWidth
  110 + */
  111 + public void setClipBorderWidth(int clipBorderWidth) {
  112 + this.clipBorderWidth = clipBorderWidth;
  113 + borderPaint.setStrokeWidth(clipBorderWidth);
  114 + invalidate();
  115 + }
  116 +
  117 + /**
  118 + * 设置裁剪框水平间距
  119 + *
  120 + * @param mHorizontalPadding
  121 + */
  122 + public void setmHorizontalPadding(float mHorizontalPadding) {
  123 + this.mHorizontalPadding = mHorizontalPadding;
  124 + this.clipRadiusWidth = (int) (getScreenWidth(getContext()) - 2 * mHorizontalPadding) / 2;
  125 + this.clipWidth = clipRadiusWidth * 2;
  126 + }
  127 +
  128 + /**
  129 + * 获得屏幕高度
  130 + *
  131 + * @param context
  132 + * @return
  133 + */
  134 + public static int getScreenWidth(Context context) {
  135 + WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
  136 + DisplayMetrics outMetrics = new DisplayMetrics();
  137 + wm.getDefaultDisplay().getMetrics(outMetrics);
  138 + return outMetrics.widthPixels;
  139 + }
  140 +
  141 +
  142 + /**
  143 + * 设置裁剪框类别
  144 + *
  145 + * @param clipType
  146 + */
  147 + public void setClipType(ClipType clipType) {
  148 + this.clipType = clipType;
  149 + }
  150 +
  151 + /**
  152 + * 裁剪框类别,圆形、矩形
  153 + */
  154 + public enum ClipType {
  155 + CIRCLE, RECTANGLE
  156 + }
  157 +}
0 \ No newline at end of file 158 \ No newline at end of file
mvpsdk/src/main/java/com/share/mvpsdk/widgets/headclip/ClipViewLayout.java 0 → 100644
  1 +++ a/mvpsdk/src/main/java/com/share/mvpsdk/widgets/headclip/ClipViewLayout.java
@@ -0,0 +1,485 @@ @@ -0,0 +1,485 @@
  1 +package com.share.mvpsdk.widgets.headclip;
  2 +
  3 +/**
  4 + * Created by Horrarndoo on 2017/9/25.
  5 + * <p>
  6 + */
  7 +
  8 +import android.content.Context;
  9 +import android.content.res.TypedArray;
  10 +import android.graphics.Bitmap;
  11 +import android.graphics.BitmapFactory;
  12 +import android.graphics.Matrix;
  13 +import android.graphics.PointF;
  14 +import android.graphics.Rect;
  15 +import android.graphics.RectF;
  16 +import android.graphics.drawable.Drawable;
  17 +import android.media.ExifInterface;
  18 +import android.net.Uri;
  19 +import android.text.TextUtils;
  20 +import android.util.AttributeSet;
  21 +import android.util.TypedValue;
  22 +import android.view.MotionEvent;
  23 +import android.view.ViewTreeObserver;
  24 +import android.widget.ImageView;
  25 +import android.widget.RelativeLayout;
  26 +
  27 +
  28 +import com.share.mvpsdk.R;
  29 +import com.share.mvpsdk.utils.LogUtils;
  30 +
  31 +import java.io.IOException;
  32 +
  33 +import static com.share.mvpsdk.utils.FileUtils.getRealFilePathFromUri;
  34 +
  35 +
  36 +/**
  37 + * 头像上传原图裁剪容器
  38 + */
  39 +public class ClipViewLayout extends RelativeLayout {
  40 + //裁剪原图
  41 + private ImageView imageView;
  42 + //裁剪框
  43 + private ClipView clipView;
  44 + //裁剪框水平方向间距,xml布局文件中指定
  45 + private float mHorizontalPadding;
  46 + //裁剪框垂直方向间距,计算得出
  47 + private float mVerticalPadding;
  48 + //图片缩放、移动操作矩阵
  49 + private Matrix matrix = new Matrix();
  50 + //图片原来已经缩放、移动过的操作矩阵
  51 + private Matrix savedMatrix = new Matrix();
  52 + //动作标志:无
  53 + private static final int NONE = 0;
  54 + //动作标志:拖动
  55 + private static final int DRAG = 1;
  56 + //动作标志:缩放
  57 + private static final int ZOOM = 2;
  58 + //初始化动作标志
  59 + private int mode = NONE;
  60 + //记录起始坐标
  61 + private PointF start = new PointF();
  62 + //记录缩放时两指中间点坐标
  63 + private PointF mid = new PointF();
  64 + private float oldDist = 1f;
  65 + //用于存放矩阵的9个值
  66 + private final float[] matrixValues = new float[9];
  67 + //最小缩放比例
  68 + private float minScale;
  69 + //最大缩放比例
  70 + private float maxScale = 4;
  71 +
  72 +
  73 + public ClipViewLayout(Context context) {
  74 + this(context, null);
  75 + }
  76 +
  77 + public ClipViewLayout(Context context, AttributeSet attrs) {
  78 + this(context, attrs, 0);
  79 + }
  80 +
  81 + public ClipViewLayout(Context context, AttributeSet attrs, int defStyleAttr) {
  82 + super(context, attrs, defStyleAttr);
  83 + init(context, attrs);
  84 + }
  85 +
  86 + //初始化控件自定义的属性
  87 + public void init(Context context, AttributeSet attrs) {
  88 + TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.ClipViewLayout);
  89 +
  90 + //获取剪切框距离左右的边距, 默认为50dp
  91 + mHorizontalPadding = array.getDimensionPixelSize(R.styleable.ClipViewLayout_mHorizontalPadding,
  92 + (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 50, getResources().getDisplayMetrics()));
  93 + //获取裁剪框边框宽度,默认1dp
  94 + int clipBorderWidth = array.getDimensionPixelSize(R.styleable.ClipViewLayout_clipBorderWidth,
  95 + (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1, getResources().getDisplayMetrics()));
  96 + //裁剪框类型(圆或者矩形)
  97 + int clipType = array.getInt(R.styleable.ClipViewLayout_clipType, 1);
  98 +
  99 + //回收
  100 + array.recycle();
  101 + clipView = new ClipView(context);
  102 + //设置裁剪框类型
  103 + clipView.setClipType(clipType == 1 ? ClipView.ClipType.CIRCLE : ClipView.ClipType.RECTANGLE);
  104 + //设置剪切框边框
  105 + clipView.setClipBorderWidth(clipBorderWidth);
  106 + //设置剪切框水平间距
  107 + clipView.setmHorizontalPadding(mHorizontalPadding);
  108 + imageView = new ImageView(context);
  109 + //相对布局布局参数
  110 + android.view.ViewGroup.LayoutParams lp = new LayoutParams(
  111 + android.view.ViewGroup.LayoutParams.MATCH_PARENT,
  112 + android.view.ViewGroup.LayoutParams.MATCH_PARENT);
  113 + this.addView(imageView, lp);
  114 + this.addView(clipView, lp);
  115 + }
  116 +
  117 +
  118 + /**
  119 + * 初始化图片
  120 + */
  121 + public void setImageSrc(final Uri uri) {
  122 + //需要等到imageView绘制完毕再初始化原图
  123 + ViewTreeObserver observer = imageView.getViewTreeObserver();
  124 + observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
  125 + public void onGlobalLayout() {
  126 + initSrcPic(uri);
  127 + imageView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
  128 + }
  129 + });
  130 + }
  131 +
  132 + /**
  133 + * 初始化图片
  134 + * step 1: decode 出 720*1280 左右的照片 因为原图可能比较大 直接加载出来会OOM
  135 + * step 2: 将图片缩放 移动到imageView 中间
  136 + */
  137 + public void initSrcPic(Uri uri) {
  138 + if (uri == null) {
  139 + return;
  140 + }
  141 + LogUtils.d("**********clip_view uri******* " + uri);
  142 + String path = getRealFilePathFromUri(getContext(), uri);
  143 + LogUtils.d("**********clip_view path******* " + path);
  144 + if (TextUtils.isEmpty(path)) {
  145 + return;
  146 + }
  147 +
  148 + //这里decode出720*1280 左右的照片,防止OOM
  149 + Bitmap bitmap = decodeSampledBitmap(path, 720, 1280);
  150 + if (bitmap == null) {
  151 + return;
  152 + }
  153 +
  154 + //竖屏拍照的照片,直接使用的话,会旋转90度,下面代码把角度旋转过来
  155 + int rotation = getExifOrientation(path); //查询旋转角度
  156 + Matrix m = new Matrix();
  157 + m.setRotate(rotation);
  158 + bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), m, true);
  159 +
  160 + //图片的缩放比
  161 + float scale;
  162 + if (bitmap.getWidth() >= bitmap.getHeight()) {//宽图
  163 + scale = (float) imageView.getWidth() / bitmap.getWidth();
  164 + //如果高缩放后小于裁剪区域 则将裁剪区域与高的缩放比作为最终的缩放比
  165 + Rect rect = clipView.getClipRect();
  166 + //高的最小缩放比
  167 + minScale = rect.height() / (float) bitmap.getHeight();
  168 + if (scale < minScale) {
  169 + scale = minScale;
  170 + }
  171 + } else {//高图
  172 + //高的缩放比
  173 + scale = (float) imageView.getHeight() / bitmap.getHeight();
  174 + //如果宽缩放后小于裁剪区域 则将裁剪区域与宽的缩放比作为最终的缩放比
  175 + Rect rect = clipView.getClipRect();
  176 + //宽的最小缩放比
  177 + minScale = rect.width() / (float) bitmap.getWidth();
  178 + if (scale < minScale) {
  179 + scale = minScale;
  180 + }
  181 + }
  182 + // 缩放
  183 + matrix.postScale(scale, scale);
  184 + // 平移,将缩放后的图片平移到imageview的中心
  185 + //imageView的中心x
  186 + int midX = imageView.getWidth() / 2;
  187 + //imageView的中心y
  188 + int midY = imageView.getHeight() / 2;
  189 + //bitmap的中心x
  190 + int imageMidX = (int) (bitmap.getWidth() * scale / 2);
  191 + //bitmap的中心y
  192 + int imageMidY = (int) (bitmap.getHeight() * scale / 2);
  193 + matrix.postTranslate(midX - imageMidX, midY - imageMidY);
  194 + imageView.setScaleType(ImageView.ScaleType.MATRIX);
  195 + imageView.setImageMatrix(matrix);
  196 + imageView.setImageBitmap(bitmap);
  197 + }
  198 +
  199 + /**
  200 + * 查询图片旋转角度
  201 + */
  202 + public static int getExifOrientation(String filepath) {// YOUR MEDIA PATH AS STRING
  203 + int degree = 0;
  204 + ExifInterface exif = null;
  205 + try {
  206 + exif = new ExifInterface(filepath);
  207 + } catch (IOException ex) {
  208 + ex.printStackTrace();
  209 + }
  210 + if (exif != null) {
  211 + int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, -1);
  212 + if (orientation != -1) {
  213 + switch (orientation) {
  214 + case ExifInterface.ORIENTATION_ROTATE_90:
  215 + degree = 90;
  216 + break;
  217 + case ExifInterface.ORIENTATION_ROTATE_180:
  218 + degree = 180;
  219 + break;
  220 + case ExifInterface.ORIENTATION_ROTATE_270:
  221 + degree = 270;
  222 + break;
  223 + }
  224 +
  225 + }
  226 + }
  227 + return degree;
  228 + }
  229 +
  230 +
  231 + @Override
  232 + public boolean onTouchEvent(MotionEvent event) {
  233 + switch (event.getAction() & MotionEvent.ACTION_MASK) {
  234 + case MotionEvent.ACTION_DOWN:
  235 + savedMatrix.set(matrix);
  236 + //设置开始点位置
  237 + start.set(event.getX(), event.getY());
  238 + mode = DRAG;
  239 + break;
  240 + case MotionEvent.ACTION_POINTER_DOWN:
  241 + //开始放下时候两手指间的距离
  242 + oldDist = spacing(event);
  243 + if (oldDist > 10f) {
  244 + savedMatrix.set(matrix);
  245 + midPoint(mid, event);
  246 + mode = ZOOM;
  247 + }
  248 + break;
  249 + case MotionEvent.ACTION_UP:
  250 + break;
  251 + case MotionEvent.ACTION_POINTER_UP:
  252 + mode = NONE;
  253 + break;
  254 + case MotionEvent.ACTION_MOVE:
  255 + if (mode == DRAG) { //拖动
  256 + matrix.set(savedMatrix);
  257 + float dx = event.getX() - start.x;
  258 + float dy = event.getY() - start.y;
  259 + mVerticalPadding = clipView.getClipRect().top;
  260 + matrix.postTranslate(dx, dy);
  261 + //检查边界
  262 + checkBorder();
  263 + } else if (mode == ZOOM) { //缩放
  264 + //缩放后两手指间的距离
  265 + float newDist = spacing(event);
  266 + if (newDist > 10f) {
  267 + //手势缩放比例
  268 + float scale = newDist / oldDist;
  269 + if (scale < 1) { //缩小
  270 + if (getScale() > minScale) {
  271 + matrix.set(savedMatrix);
  272 + mVerticalPadding = clipView.getClipRect().top;
  273 + matrix.postScale(scale, scale, mid.x, mid.y);
  274 + //缩放到最小范围下面去了,则返回到最小范围大小
  275 + while (getScale() < minScale) {
  276 + //返回到最小范围的放大比例
  277 + scale = 1 + 0.01F;
  278 + matrix.postScale(scale, scale, mid.x, mid.y);
  279 + }
  280 + }
  281 + //边界检查
  282 + checkBorder();
  283 + } else { //放大
  284 + if (getScale() <= maxScale) {
  285 + matrix.set(savedMatrix);
  286 + mVerticalPadding = clipView.getClipRect().top;
  287 + matrix.postScale(scale, scale, mid.x, mid.y);
  288 + }
  289 + }
  290 + }
  291 + }
  292 + imageView.setImageMatrix(matrix);
  293 + break;
  294 + }
  295 + return true;
  296 + }
  297 +
  298 + /**
  299 + * 根据当前图片的Matrix获得图片的范围
  300 + */
  301 + private RectF getMatrixRectF(Matrix matrix) {
  302 + RectF rect = new RectF();
  303 + Drawable d = imageView.getDrawable();
  304 + if (null != d) {
  305 + rect.set(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());
  306 + matrix.mapRect(rect);
  307 + }
  308 + return rect;
  309 + }
  310 +
  311 + /**
  312 + * 边界检测
  313 + */
  314 + private void checkBorder() {
  315 + RectF rect = getMatrixRectF(matrix);
  316 + float deltaX = 0;
  317 + float deltaY = 0;
  318 + int width = imageView.getWidth();
  319 + int height = imageView.getHeight();
  320 + // 如果宽或高大于屏幕,则控制范围 ; 这里的0.001是因为精度丢失会产生问题,但是误差一般很小,所以我们直接加了一个0.01
  321 + if (rect.width() >= width - 2 * mHorizontalPadding) {
  322 + if (rect.left > mHorizontalPadding) {
  323 + deltaX = -rect.left + mHorizontalPadding;
  324 + }
  325 + if (rect.right < width - mHorizontalPadding) {
  326 + deltaX = width - mHorizontalPadding - rect.right;
  327 + }
  328 + }
  329 + if (rect.height() >= height - 2 * mVerticalPadding) {
  330 + if (rect.top > mVerticalPadding) {
  331 + deltaY = -rect.top + mVerticalPadding;
  332 + }
  333 + if (rect.bottom < height - mVerticalPadding) {
  334 + deltaY = height - mVerticalPadding - rect.bottom;
  335 + }
  336 + }
  337 + matrix.postTranslate(deltaX, deltaY);
  338 + }
  339 +
  340 + /**
  341 + * 获得当前的缩放比例
  342 + */
  343 + public final float getScale() {
  344 + matrix.getValues(matrixValues);
  345 + return matrixValues[Matrix.MSCALE_X];
  346 + }
  347 +
  348 +
  349 + /**
  350 + * 多点触控时,计算最先放下的两指距离
  351 + */
  352 + private float spacing(MotionEvent event) {
  353 + float x = event.getX(0) - event.getX(1);
  354 + float y = event.getY(0) - event.getY(1);
  355 + return (float) Math.sqrt(x * x + y * y);
  356 + }
  357 +
  358 + /**
  359 + * 多点触控时,计算最先放下的两指中心坐标
  360 + */
  361 + private void midPoint(PointF point, MotionEvent event) {
  362 + float x = event.getX(0) + event.getX(1);
  363 + float y = event.getY(0) + event.getY(1);
  364 + point.set(x / 2, y / 2);
  365 + }
  366 +
  367 +
  368 + /**
  369 + * 获取剪切图
  370 + */
  371 + public Bitmap clip() {
  372 + imageView.setDrawingCacheEnabled(true);
  373 + imageView.buildDrawingCache();
  374 + Rect rect = clipView.getClipRect();
  375 + Bitmap cropBitmap = null;
  376 + Bitmap zoomedCropBitmap = null;
  377 + try {
  378 + cropBitmap = Bitmap.createBitmap(imageView.getDrawingCache(), rect.left, rect.top, rect.width(), rect.height());
  379 + zoomedCropBitmap = zoomBitmap(cropBitmap, 200, 200);
  380 + } catch (Exception e) {
  381 + e.printStackTrace();
  382 + }
  383 + if (cropBitmap != null) {
  384 + cropBitmap.recycle();
  385 + }
  386 + // 释放资源
  387 + imageView.destroyDrawingCache();
  388 + return zoomedCropBitmap;
  389 + }
  390 +
  391 +
  392 + /**
  393 + * 图片等比例压缩
  394 + *
  395 + * @param filePath
  396 + * @param reqWidth 期望的宽
  397 + * @param reqHeight 期望的高
  398 + * @return
  399 + */
  400 + public static Bitmap decodeSampledBitmap(String filePath, int reqWidth,
  401 + int reqHeight) {
  402 +
  403 + // First decode with inJustDecodeBounds=true to check dimensions
  404 + final BitmapFactory.Options options = new BitmapFactory.Options();
  405 + options.inJustDecodeBounds = true;
  406 + options.inPreferredConfig = Bitmap.Config.RGB_565;
  407 + //bitmap is null
  408 + Bitmap bitmap = BitmapFactory.decodeFile(filePath, options);
  409 +
  410 + // Calculate inSampleSize
  411 + options.inSampleSize = calculateInSampleSize(options, reqWidth,
  412 + reqHeight);
  413 +
  414 + // Decode bitmap with inSampleSize set
  415 + options.inJustDecodeBounds = false;
  416 + return BitmapFactory.decodeFile(filePath, options);
  417 + }
  418 +
  419 + /**
  420 + * 计算InSampleSize
  421 + * 宽的压缩比和高的压缩比的较小值 取接近的2的次幂的值
  422 + * 比如宽的压缩比是3 高的压缩比是5 取较小值3 而InSampleSize必须是2的次幂,取接近的2的次幂4
  423 + *
  424 + * @param options
  425 + * @param reqWidth
  426 + * @param reqHeight
  427 + * @return
  428 + */
  429 + public static int calculateInSampleSize(BitmapFactory.Options options,
  430 + int reqWidth, int reqHeight) {
  431 + // Raw height and width of image
  432 + final int height = options.outHeight;
  433 + final int width = options.outWidth;
  434 + int inSampleSize = 1;
  435 +
  436 + if (height > reqHeight || width > reqWidth) {
  437 +
  438 + // Calculate ratios of height and width to requested height and
  439 + // width
  440 + final int heightRatio = Math.round((float) height
  441 + / (float) reqHeight);
  442 + final int widthRatio = Math.round((float) width / (float) reqWidth);
  443 +
  444 + // Choose the smallest ratio as inSampleSize value, this will
  445 + // guarantee
  446 + // a final image with both dimensions larger than or equal to the
  447 + // requested height and width.
  448 + int ratio = heightRatio < widthRatio ? heightRatio : widthRatio;
  449 + // inSampleSize只能是2的次幂 将ratio就近取2的次幂的值
  450 + if (ratio < 3)
  451 + inSampleSize = ratio;
  452 + else if (ratio < 6.5)
  453 + inSampleSize = 4;
  454 + else if (ratio < 8)
  455 + inSampleSize = 8;
  456 + else
  457 + inSampleSize = ratio;
  458 + }
  459 +
  460 + return inSampleSize;
  461 + }
  462 +
  463 + /**
  464 + * 图片缩放到指定宽高
  465 + * <p/>
  466 + * 非等比例压缩,图片会被拉伸
  467 + *
  468 + * @param bitmap 源位图对象
  469 + * @param w 要缩放的宽度
  470 + * @param h 要缩放的高度
  471 + * @return 新Bitmap对象
  472 + */
  473 + public static Bitmap zoomBitmap(Bitmap bitmap, int w, int h) {
  474 + int width = bitmap.getWidth();
  475 + int height = bitmap.getHeight();
  476 + Matrix matrix = new Matrix();
  477 + float scaleWidth = ((float) w / width);
  478 + float scaleHeight = ((float) h / height);
  479 + matrix.postScale(scaleWidth, scaleHeight);
  480 + Bitmap newBmp = Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, false);
  481 + return newBmp;
  482 + }
  483 +
  484 +
  485 +}
0 \ No newline at end of file 486 \ No newline at end of file
mvpsdk/src/main/res/anim/activity_finish_trans_in.xml 0 → 100644
  1 +++ a/mvpsdk/src/main/res/anim/activity_finish_trans_in.xml
@@ -0,0 +1,11 @@ @@ -0,0 +1,11 @@
  1 +<set xmlns:android="http://schemas.android.com/apk/res/android"
  2 + android:zAdjustment="normal">
  3 + <alpha
  4 + android:duration="250"
  5 + android:fillAfter="true"
  6 + android:fillBefore="true"
  7 + android:fillEnabled="true"
  8 + android:fromAlpha="0.7"
  9 + android:interpolator="@android:anim/accelerate_interpolator"
  10 + android:toAlpha="1.0"/>
  11 +</set>
0 \ No newline at end of file 12 \ No newline at end of file
mvpsdk/src/main/res/anim/activity_finish_trans_out.xml 0 → 100644
  1 +++ a/mvpsdk/src/main/res/anim/activity_finish_trans_out.xml
@@ -0,0 +1,21 @@ @@ -0,0 +1,21 @@
  1 +<set xmlns:android="http://schemas.android.com/apk/res/android"
  2 + android:shareInterpolator="false"
  3 + android:zAdjustment="top">
  4 + <alpha
  5 + android:duration="150"
  6 + android:fillAfter="true"
  7 + android:fillBefore="false"
  8 + android:fillEnabled="true"
  9 + android:fromAlpha="1.0"
  10 + android:interpolator="@android:anim/linear_interpolator"
  11 + android:startOffset="100"
  12 + android:toAlpha="0.0"/>
  13 + <translate
  14 + android:duration="250"
  15 + android:fillAfter="true"
  16 + android:fillBefore="true"
  17 + android:fillEnabled="true"
  18 + android:fromYDelta="0%"
  19 + android:interpolator="@android:anim/accelerate_interpolator"
  20 + android:toYDelta="12%"/>
  21 +</set>
0 \ No newline at end of file 22 \ No newline at end of file
mvpsdk/src/main/res/anim/activity_finish_zoom_in.xml 0 → 100644
  1 +++ a/mvpsdk/src/main/res/anim/activity_finish_zoom_in.xml
@@ -0,0 +1,12 @@ @@ -0,0 +1,12 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<set xmlns:Android="http://schemas.android.com/apk/res/android"
  3 + Android:interpolator="@android:anim/decelerate_interpolator">
  4 + <scale
  5 + Android:duration="300"
  6 + Android:fromXScale="2.0"
  7 + Android:fromYScale="2.0"
  8 + Android:pivotX="50%p"
  9 + Android:pivotY="50%p"
  10 + Android:toXScale="1.0"
  11 + Android:toYScale="1.0" />
  12 +</set>
0 \ No newline at end of file 13 \ No newline at end of file
mvpsdk/src/main/res/anim/activity_finish_zoom_out.xml 0 → 100644
  1 +++ a/mvpsdk/src/main/res/anim/activity_finish_zoom_out.xml
@@ -0,0 +1,18 @@ @@ -0,0 +1,18 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<set xmlns:Android="http://schemas.android.com/apk/res/android"
  3 + Android:interpolator="@android:anim/decelerate_interpolator"
  4 + Android:zAdjustment="top">
  5 + <scale
  6 + Android:duration="300"
  7 + Android:fromXScale="1.0"
  8 + Android:fromYScale="1.0"
  9 + Android:pivotX="50%p"
  10 + Android:pivotY="50%p"
  11 + Android:toXScale="0.5"
  12 + Android:toYScale="0.5"/>
  13 +
  14 + <alpha
  15 + Android:duration="300"
  16 + Android:fromAlpha="1.0"
  17 + Android:toAlpha="0"/>
  18 +</set>
0 \ No newline at end of file 19 \ No newline at end of file
mvpsdk/src/main/res/anim/activity_start_trans_in.xml 0 → 100644
  1 +++ a/mvpsdk/src/main/res/anim/activity_start_trans_in.xml
@@ -0,0 +1,21 @@ @@ -0,0 +1,21 @@
  1 +<set xmlns:android="http://schemas.android.com/apk/res/android"
  2 + android:shareInterpolator="false"
  3 + android:zAdjustment="top">
  4 + <alpha
  5 + android:duration="200"
  6 + android:fillAfter="true"
  7 + android:fillBefore="false"
  8 + android:fillEnabled="true"
  9 + android:fromAlpha="0.0"
  10 + android:interpolator="@android:anim/decelerate_interpolator"
  11 + android:toAlpha="1.0"/>
  12 +
  13 + <translate
  14 + android:duration="300"
  15 + android:fillAfter="true"
  16 + android:fillBefore="true"
  17 + android:fillEnabled="true"
  18 + android:fromYDelta="12%"
  19 + android:interpolator="@android:anim/decelerate_interpolator"
  20 + android:toYDelta="0"/>
  21 +</set>
0 \ No newline at end of file 22 \ No newline at end of file
mvpsdk/src/main/res/anim/activity_start_trans_out.xml 0 → 100644
  1 +++ a/mvpsdk/src/main/res/anim/activity_start_trans_out.xml
@@ -0,0 +1,11 @@ @@ -0,0 +1,11 @@
  1 +<set xmlns:android="http://schemas.android.com/apk/res/android"
  2 + android:zAdjustment="normal">
  3 + <alpha
  4 + android:duration="300"
  5 + android:fillAfter="true"
  6 + android:fillBefore="false"
  7 + android:fillEnabled="true"
  8 + android:fromAlpha="1.0"
  9 + android:interpolator="@android:anim/decelerate_interpolator"
  10 + android:toAlpha="0.9"/>
  11 +</set>
0 \ No newline at end of file 12 \ No newline at end of file
mvpsdk/src/main/res/anim/activity_start_zoom_in.xml 0 → 100644
  1 +++ a/mvpsdk/src/main/res/anim/activity_start_zoom_in.xml
@@ -0,0 +1,12 @@ @@ -0,0 +1,12 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<set xmlns:Android="http://schemas.android.com/apk/res/android"
  3 + Android:interpolator="@android:anim/decelerate_interpolator">
  4 + <scale
  5 + Android:duration="300"
  6 + Android:fromXScale="0.8"
  7 + Android:fromYScale="0.8"
  8 + Android:pivotX="50%p"
  9 + Android:pivotY="50%p"
  10 + Android:toXScale="1.0"
  11 + Android:toYScale="1.0"/>
  12 +</set>
0 \ No newline at end of file 13 \ No newline at end of file
mvpsdk/src/main/res/anim/activity_start_zoom_out.xml 0 → 100644
  1 +++ a/mvpsdk/src/main/res/anim/activity_start_zoom_out.xml
@@ -0,0 +1,17 @@ @@ -0,0 +1,17 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<set xmlns:Android="http://schemas.android.com/apk/res/android"
  3 + Android:interpolator="@android:anim/decelerate_interpolator"
  4 + Android:zAdjustment="top">
  5 + <!--<scale-->
  6 + <!--Android:duration="300"-->
  7 + <!--Android:fromXScale="1.0"-->
  8 + <!--Android:fromYScale="1.0"-->
  9 + <!--Android:pivotX="50%p"-->
  10 + <!--Android:pivotY="50%p"-->
  11 + <!--Android:toXScale="2.0"-->
  12 + <!--Android:toYScale="2.0"/>-->
  13 + <alpha
  14 + Android:duration="300"
  15 + Android:fromAlpha="1.0"
  16 + Android:toAlpha="0"/>
  17 +</set>
0 \ No newline at end of file 18 \ No newline at end of file
mvpsdk/src/main/res/drawable/ic_vector_empty.xml 0 → 100644
  1 +++ a/mvpsdk/src/main/res/drawable/ic_vector_empty.xml
@@ -0,0 +1,30 @@ @@ -0,0 +1,30 @@
  1 +<vector xmlns:android="http://schemas.android.com/apk/res/android"
  2 + android:width="344dp"
  3 + android:height="200dp"
  4 + android:viewportWidth="1762.0"
  5 + android:viewportHeight="1024.0">
  6 + <path
  7 + android:pathData="M1592.9,920.6c0,57.5 -46.7,103.4 -104.3,103.4H306.2c-57.6,0 -106.2,-45.9 -106.2,-103.4V244c0,-57.5 48.5,-104 106.2,-104H1488.6c57.6,0 104.3,46.6 104.3,104v676.7z"
  8 + android:fillColor="#F4F4F4"/>
  9 + <path
  10 + android:pathData="M1472.1,585.1v-470.2c0,-57.5 -48.7,-102.2 -106.3,-102.2H183.4c-57.6,0 -104.2,44.7 -104.2,102.2V345.7c50.9,6.4 95.6,52.1 95.6,107.6s-44.8,101.1 -95.6,107.6v230.7c0,57.5 46.6,105.2 69.4,105.2h999.1z"
  11 + android:fillColor="#FFFFFF"/>
  12 + <path
  13 + android:pathData="M1147.3,903.2H148.6c-30.5,0 -88.5,-50 -88.5,-111.6V560.8c0,-5.8 8.1,-10.7 13.8,-11.4 48.8,-5.8 87.4,-47.2 87.4,-96.2 0,-49 -39.6,-90.4 -88.3,-96.2 -5.8,-0.7 -12.9,-5.6 -12.9,-11.4V114.9C60.1,51.2 119.5,0 183.4,0h1182.4c63.8,0 119,51.2 119,114.9V585.7c0,6.3 -6.4,11.4 -12.7,11.4s-12.7,-5.1 -12.7,-11.4V114.9c0,-51.1 -42.4,-89.5 -93.6,-89.5H183.4c-51.2,0 -97.8,38.4 -97.8,89.5v221c57.2,11.4 95.6,60.1 95.6,117.3 0,57.2 -38.4,105.9 -95.6,117.3v221c0,54.2 49,92.5 63,92.5h998.7c6.3,0 11.5,3.2 11.5,9.5 0,6.3 -5.1,9.5 -11.5,9.5z"
  14 + android:fillColor="#BABABA"/>
  15 + <path
  16 + android:pathData="M1162.6,764.1c0,95.8 77.8,173.5 173.9,173.5s173.9,-77.7 173.9,-173.5 -77.8,-173.5 -173.9,-173.5 -173.9,77.7 -173.9,173.5z"
  17 + android:fillColor="#FFFFFF"/>
  18 + <path
  19 + android:pathData="M1336.4,949c-102.2,0 -185.3,-83 -185.3,-184.9 0,-102 83.1,-184.9 185.3,-184.9s185.3,83 185.3,184.9c-0,102 -83.2,184.9 -185.3,184.9zM1336.4,602c-89.6,0 -162.4,72.7 -162.4,162.1 0,89.4 72.9,162.1 162.4,162.1s162.4,-72.7 162.4,-162.1c0,-89.4 -72.9,-162.1 -162.4,-162.1z"
  20 + android:fillColor="#BABABA"/>
  21 + <path
  22 + android:pathData="M1188.7,764.1c0,81.4 66.2,147.5 147.8,147.5s147.8,-66 147.8,-147.5 -66.2,-147.5 -147.8,-147.5 -147.8,66 -147.8,147.5z"
  23 + android:fillColor="#F4F4F4"/>
  24 + <path
  25 + android:pathData="M1163.6,273.5c0,7.2 -4.6,12.7 -10.2,12.7L919.7,286.2c-5.6,0 -10.2,-5.5 -10.2,-12.7 0,-7.2 4.5,-12.7 10.2,-12.7h233.8c5.6,0 10.2,5.5 10.2,12.7zM642.8,636c0,7.2 -4.6,12.7 -10.2,12.7L398.9,648.7c-5.6,0 -10.2,-5.5 -10.2,-12.7 0,-7.2 4.6,-12.7 10.2,-12.7h233.7c5.6,0 10.2,5.5 10.2,12.7zM1147.8,391.2c0,4.8 -2.8,9.5 -6.4,9.5L391.9,400.7c-3.5,0 -6.4,-4.8 -6.4,-9.5s2.8,-9.5 6.4,-9.5h749.5c3.5,0 6.4,4.8 6.4,9.5zM1147.8,515.2c0,4.8 -2.8,12.7 -6.4,12.7L391.9,527.9c-3.5,0 -6.4,-7.9 -6.4,-12.7s2.8,-12.7 6.4,-12.7h749.5c3.5,0 6.4,7.9 6.4,12.7z"
  26 + android:fillColor="#E8E8E8"/>
  27 + <path
  28 + android:pathData="M1360.8,773.1c12.5,0 23.7,-0.4 33.4,-1.4v14.6c-9.3,-0.9 -20.4,-1.4 -33.4,-1.4h-15.3v41.6h42.4c13.4,0 24.3,-0.5 32.7,-1.4v14.6c-7.9,-0.9 -18.3,-1.4 -31.3,-1.4h-91.8c-18.1,0 -31.1,0.5 -38.9,1.4v-14.6c8.8,0.9 22.3,1.4 40.3,1.4h31.3v-41.6h-17.4c-12.5,0 -23.4,0.5 -32.7,1.4v-14.6c8.8,0.9 20.4,1.4 34.8,1.4h45.9zM1302.8,750.5c-9,6.7 -19.4,13.5 -30.9,20.5 -3.2,-4.7 -6.6,-8.8 -10.4,-12.5 9.8,-4.2 18.3,-9 26.2,-14.5a115.7,115.7 0,0 0,21 -18.7c4.7,4 9.8,8 15.4,11.7 -5.1,2.3 -12.2,6.8 -21.2,13.5zM1394.9,736.3v-18.7h-114v20.8h-15.3c0.5,-4.6 0.7,-9.9 0.7,-16 0,-6.5 -0.2,-12.3 -0.7,-17.4h69.5c-3.4,-7.8 -6.6,-14.2 -10.2,-20.3 5.1,-1.4 10.2,-3.5 15.8,-5.3 8.3,19.5 11.5,26.5 14.8,33.6 -9.7,-10.7 -14.1,-9.3 -18.3,-7.9h73.7c-0.5,4.2 -0.7,9.7 -0.7,16.7 0,6.5 0.2,11.3 0.7,14.6h-16zM1381.3,738.4c9,4.2 19.8,9.9 32.3,17.3 -4.6,5.1 -7.9,9.5 -9.7,13.2 -6.1,-4 -14.5,-9.1 -23.1,-13.9a492,492 0,0 0,-26.8 -14c-0.6,-4.1 2.1,-7.8 5.4,-12.4 5.6,2.3 12.9,5.5 21.9,9.7z"
  29 + android:fillColor="#BABABA"/>
  30 +</vector>
mvpsdk/src/main/res/drawable/ic_vector_loading.xml 0 → 100644
  1 +++ a/mvpsdk/src/main/res/drawable/ic_vector_loading.xml
@@ -0,0 +1,8 @@ @@ -0,0 +1,8 @@
  1 +<vector android:height="24dp" android:viewportHeight="1024.0"
  2 + android:viewportWidth="1024.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
  3 + <path android:fillColor="#707070" android:pathData="M390.2,438.8c-17.3,0 -31.3,14 -31.3,31.3l0,30.6c0,17.3 14,31.3 31.3,31.3 17.3,0 31.3,-14 31.3,-31.3l0,-30.6C421.5,452.8 407.5,438.8 390.2,438.8z"/>
  4 + <path android:fillColor="#707070" android:pathData="M634.8,438.8c-17.3,0 -31.3,14 -31.3,31.3l0,30.6c0,17.3 14,31.3 31.3,31.3 17.3,0 31.3,-14 31.3,-31.3l0,-30.6C666.1,452.8 652.1,438.8 634.8,438.8z"/>
  5 + <path android:fillColor="#707070" android:pathData="M589.8,580.7c-14.3,-9.4 -33.7,-5.4 -43.3,8.8 -0.1,0.2 -13.7,19.8 -34.3,19.8 -20.1,0 -32.5,-18.2 -33.4,-19.4 -9.2,-14.5 -28.4,-18.9 -43,-9.8 -14.7,9.1 -19.2,28.4 -10.1,43.1 11.2,18.1 42.1,48.7 86.4,48.7 44.1,0 75.4,-30.4 86.9,-48.4C608.3,609.1 604.1,590.1 589.8,580.7z"/>
  6 + <path android:fillColor="#707070" android:pathData="M94.4,554c4.4,2.1 9,3.1 13.6,3.1 11.7,0 22.9,-6.5 28.3,-17.7 25.1,-52.1 61.9,-89.8 96.2,-98.6 11.2,-2.9 19.9,-11.7 22.7,-22.9 28.3,-115.7 116.8,-184.8 236.8,-184.8 85.3,0 168,51.1 184.3,113.8 3.7,14.2 16.8,24.3 31.3,23.4 1.8,-0.1 3.5,-0.1 5.2,-0.1 94.3,0 158.5,80.3 173.4,161.1 3.1,17 19.5,28.3 36.5,25.1 17,-3.1 28.3,-19.5 25.1,-36.5 -21.8,-118.1 -111.8,-203.8 -218.8,-211.8 -34,-80 -131.2,-137.8 -237.1,-137.8 -142.7,0 -253.5,82.2 -293.2,215.7 -46,19 -89.5,64.8 -119,126.1C72.2,527.7 78.8,546.5 94.4,554z"/>
  7 + <path android:fillColor="#707070" android:pathData="M934.4,598.6c-17,-3.7 -33.6,6 -37.3,22.9 -22,100.7 -104.7,171.8 -196.7,171.8L280,793.3c-82.1,0 -151.4,-76.5 -151.4,-168.8 0,-17.3 -14,-29.8 -31.3,-29.8s-31.3,13 -31.3,30.3c0,126.3 98,231 214,231L700.4,856c121.2,0 229.7,-92.3 257.9,-221.6C962,617.5 951.3,602.3 934.4,598.6z"/>
  8 +</vector>
mvpsdk/src/main/res/drawable/ic_vector_net_error.xml 0 → 100644
  1 +++ a/mvpsdk/src/main/res/drawable/ic_vector_net_error.xml
@@ -0,0 +1,15 @@ @@ -0,0 +1,15 @@
  1 +<vector xmlns:android="http://schemas.android.com/apk/res/android"
  2 + android:width="308dp"
  3 + android:height="200dp"
  4 + android:viewportWidth="1581.0"
  5 + android:viewportHeight="1024.0">
  6 + <path
  7 + android:pathData="M1074.7,709.8c20,3.1 38.7,-10.6 41.8,-30.5 3.1,-20 -10.6,-38.7 -30.5,-41.8l-260.6,-40.5 -14.2,71.9 263.6,41z"
  8 + android:fillColor="#8a8a8a"/>
  9 + <path
  10 + android:pathData="M1522.5,927.7l56.2,-361.8c9.3,-60 -31.7,-116.1 -91.7,-125.4l-434.1,-67.5c-60,-9.3 -116.1,31.7 -125.4,91.6l-11.2,72.4 72.3,11.2 11.2,-72.3c3.1,-20 21.8,-33.7 41.8,-30.6l434.1,67.5c20,3.1 33.7,21.9 30.6,41.8l-56.2,361.8c-3.1,19.9 -21.8,33.6 -41.8,30.5l-434.2,-67.5c-19.9,-3.2 -33.6,-21.9 -30.6,-41.8l11.2,-72.3 -72.4,-11.3 -11.2,72.4c-9.3,60 31.7,116.1 91.7,125.4l434.2,67.5c60,9.3 116.1,-31.7 125.4,-91.6zM494.8,638.4c-19.9,3.2 -33.5,22.1 -30.2,42 3.3,20 22.1,33.5 42,30.2l260.3,-42.5 -8.9,-72.8 -263.2,43z"
  11 + android:fillColor="#8a8a8a"/>
  12 + <path
  13 + android:pathData="M710.9,825.6l-11.8,-72.3 -72.3,11.8 11.8,72.2c3.2,19.9 -10.3,38.8 -30.2,42l-433.6,70.8c-19.9,3.3 -38.8,-10.3 -42,-30.2L73.7,558.7c-3.2,-19.9 10.3,-38.8 30.2,-42.1l433.6,-70.8c19.9,-3.2 38.8,10.3 42,30.2l11.8,72.2 72.3,-11.8 -11.8,-72.3c-9.8,-59.9 -66.2,-100.5 -126.1,-90.7L92.1,444.4c-59.9,9.8 -100.5,66.2 -90.7,126.1L60.5,931.9c9.8,59.9 66.2,100.4 126.1,90.7l433.6,-70.8c59.9,-9.8 100.5,-66.2 90.7,-126.1zM518,215.3s0,0 0,0l-95.3,-90.4c-10.2,-9.7 -10.6,-25.8 -0.9,-36.1 9.7,-10.2 25.8,-10.6 36.1,-0.9 0,0 0,0 0,0l95.3,90.4c10.2,9.7 10.6,25.8 0.9,36.1 -9.7,10.2 -25.8,10.6 -36.1,0.9zM780.6,175.4a25.4,25.4 0,0 1,-7.9 -17.8l-3.4,-131.3C768.8,12.1 779.9,0.4 794,0c14.1,-0.4 25.8,10.8 26.2,24.8l3.4,131.3c0.4,14.1 -10.8,25.8 -24.8,26.2a25.4,25.4 0,0 1,-18.2 -7zM1027.6,210.6c-10.2,-9.7 -10.6,-25.8 -0.9,-36.1l90.4,-95.3c9.7,-10.2 25.8,-10.6 36.1,-0.9 10.2,9.7 10.6,25.8 0.9,36.1l-90.4,95.3c-9.7,10.2 -25.8,10.6 -36.1,0.9z"
  14 + android:fillColor="#8a8a8a"/>
  15 +</vector>
mvpsdk/src/main/res/drawable/indoor_temp.png 0 → 100644

617 Bytes

mvpsdk/src/main/res/drawable/item_touch_bg.xml 0 → 100644
  1 +++ a/mvpsdk/src/main/res/drawable/item_touch_bg.xml
@@ -0,0 +1,5 @@ @@ -0,0 +1,5 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<selector xmlns:android="http://schemas.android.com/apk/res/android">
  3 + <item android:drawable="@color/md_grey_500" android:state_pressed="true"/>
  4 + <item android:drawable="@color/md_grey_500" android:state_focused="true"/>
  5 +</selector>
mvpsdk/src/main/res/drawable/stackblur_default.png 0 → 100644

32.1 KB

mvpsdk/src/main/res/drawable/week_normal.png 0 → 100644

904 Bytes

mvpsdk/src/main/res/drawable/week_selector.png 0 → 100644

3.03 KB

mvpsdk/src/main/res/drawable/week_status.xml 0 → 100644
  1 +++ a/mvpsdk/src/main/res/drawable/week_status.xml
@@ -0,0 +1,9 @@ @@ -0,0 +1,9 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<selector xmlns:android="http://schemas.android.com/apk/res/android">
  3 +
  4 + <item android:drawable="@drawable/week_selector" android:state_checked="true"/>
  5 + <item android:drawable="@drawable/week_selector" android:state_pressed="true"/>
  6 + <item android:drawable="@drawable/week_selector" android:state_selected="true"/>
  7 + <item android:drawable="@drawable/week_normal"/>
  8 +
  9 +</selector>
0 \ No newline at end of file 10 \ No newline at end of file
mvpsdk/src/main/res/drawable/week_tv_status.xml 0 → 100644
  1 +++ a/mvpsdk/src/main/res/drawable/week_tv_status.xml
@@ -0,0 +1,7 @@ @@ -0,0 +1,7 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<selector xmlns:android="http://schemas.android.com/apk/res/android">
  3 +
  4 + <item android:drawable="@color/light_yellow" android:state_selected="true"/>
  5 + <item android:drawable="@color/white"/>
  6 +
  7 +</selector>
0 \ No newline at end of file 8 \ No newline at end of file
mvpsdk/src/main/res/layout/sub_history_click_view.xml 0 → 100644
  1 +++ a/mvpsdk/src/main/res/layout/sub_history_click_view.xml
@@ -0,0 +1,25 @@ @@ -0,0 +1,25 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3 + android:layout_width="match_parent"
  4 + android:layout_height="match_parent"
  5 + android:gravity="center_horizontal"
  6 + android:orientation="vertical" >
  7 +
  8 + <ImageView
  9 + android:id="@+id/iv_click_view"
  10 + android:layout_width="wrap_content"
  11 + android:layout_height="0dp"
  12 + android:src="@drawable/week_status"
  13 + android:layout_weight="1" />
  14 +
  15 + <TextView
  16 + android:id="@+id/tv_click_view"
  17 + android:layout_width="match_parent"
  18 + android:layout_height="wrap_content"
  19 + android:text="@string/history_day"
  20 + android:gravity="center_horizontal"
  21 + android:textColor="@color/light_grey"
  22 + android:paddingTop="5dp"
  23 + android:paddingBottom="8dp"/>
  24 +
  25 +</LinearLayout>
0 \ No newline at end of file 26 \ No newline at end of file
mvpsdk/src/main/res/layout/sub_history_tips.xml 0 → 100644
  1 +++ a/mvpsdk/src/main/res/layout/sub_history_tips.xml
@@ -0,0 +1,35 @@ @@ -0,0 +1,35 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3 + android:layout_width="wrap_content"
  4 + android:layout_height="match_parent"
  5 + android:orientation="horizontal" >
  6 +
  7 + <ImageView
  8 + android:id="@+id/iv_tip"
  9 + android:layout_width="30dp"
  10 + android:layout_height="match_parent"
  11 + android:paddingRight="5dp"
  12 + android:src="@drawable/indoor_temp" />
  13 +
  14 + <LinearLayout
  15 + android:layout_width="match_parent"
  16 + android:layout_height="match_parent"
  17 + android:gravity="center_vertical"
  18 + android:orientation="vertical" >
  19 +
  20 + <TextView
  21 + android:id="@+id/tv_tip1"
  22 + android:layout_width="match_parent"
  23 + android:layout_height="wrap_content"
  24 + android:text="tip1"
  25 + android:textColor="@color/light_grey2" />
  26 +
  27 + <TextView
  28 + android:id="@+id/tv_tip2"
  29 + android:layout_width="match_parent"
  30 + android:layout_height="wrap_content"
  31 + android:text="tip2"
  32 + android:textColor="@color/light_grey2" />
  33 + </LinearLayout>
  34 +
  35 +</LinearLayout>
0 \ No newline at end of file 36 \ No newline at end of file
mvpsdk/src/main/res/layout/view_empty.xml 0 → 100644
  1 +++ a/mvpsdk/src/main/res/layout/view_empty.xml
@@ -0,0 +1,19 @@ @@ -0,0 +1,19 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3 + xmlns:app="http://schemas.android.com/apk/res-auto"
  4 + style="@style/bg"
  5 + android:gravity="center"
  6 + android:orientation="vertical">
  7 +
  8 + <android.support.v7.widget.AppCompatImageView
  9 + style="@style/empty_img"
  10 + app:srcCompat = "@drawable/ic_vector_empty"/>
  11 +
  12 + <TextView
  13 + android:layout_width="wrap_content"
  14 + android:layout_height="wrap_content"
  15 + android:layout_marginBottom="30dp"
  16 + android:layout_marginTop="5dp"
  17 + android:text="@string/empty_no_data"
  18 + android:textColor="@color/txt_color"/>
  19 +</LinearLayout>
0 \ No newline at end of file 20 \ No newline at end of file
mvpsdk/src/main/res/layout/view_loading.xml 0 → 100644
  1 +++ a/mvpsdk/src/main/res/layout/view_loading.xml
@@ -0,0 +1,32 @@ @@ -0,0 +1,32 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3 + xmlns:app="http://schemas.android.com/apk/res-auto"
  4 + style="@style/bg"
  5 + android:gravity="center"
  6 + android:orientation="vertical">
  7 +
  8 + <android.support.v7.widget.AppCompatImageView
  9 + style="@style/loading_img"
  10 + app:srcCompat="@drawable/ic_vector_loading"/>
  11 +
  12 + <LinearLayout
  13 + android:layout_width="wrap_content"
  14 + android:layout_height="60dp"
  15 + android:gravity="center_vertical"
  16 + android:orientation="horizontal">
  17 +
  18 + <ProgressBar
  19 + android:id="@+id/progressBar"
  20 + style="?android:attr/progressBarStyle"
  21 + android:layout_width="35dp"
  22 + android:layout_height="35dp"/>
  23 +
  24 + <TextView
  25 + android:layout_width="wrap_content"
  26 + android:layout_height="wrap_content"
  27 + android:layout_marginLeft="8dp"
  28 + android:text="@string/loading"
  29 + android:textColor="@color/txt_color"
  30 + android:textSize="16sp"/>
  31 + </LinearLayout>
  32 +</LinearLayout>
0 \ No newline at end of file 33 \ No newline at end of file
mvpsdk/src/main/res/layout/view_network_error.xml 0 → 100644
  1 +++ a/mvpsdk/src/main/res/layout/view_network_error.xml
@@ -0,0 +1,19 @@ @@ -0,0 +1,19 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3 + xmlns:app="http://schemas.android.com/apk/res-auto"
  4 + style="@style/bg"
  5 + android:gravity="center"
  6 + android:orientation="vertical">
  7 +
  8 + <android.support.v7.widget.AppCompatImageView
  9 + style="@style/net_error_img"
  10 + app:srcCompat="@drawable/ic_vector_net_error"/>
  11 +
  12 + <TextView
  13 + android:layout_width="wrap_content"
  14 + android:layout_height="wrap_content"
  15 + android:layout_marginBottom="30dp"
  16 + android:layout_marginTop="5dp"
  17 + android:text="@string/empty_network_error"
  18 + android:textColor="@color/txt_color"/>
  19 +</LinearLayout>
0 \ No newline at end of file 20 \ No newline at end of file
mvpsdk/src/main/res/mipmap-xhdpi/ic_arrow_back_white.png 0 → 100644

233 Bytes

mvpsdk/src/main/res/mipmap-xxhdpi/ic_arrow_back_white.png 0 → 100644

374 Bytes

mvpsdk/src/main/res/values-v21/styles.xml 0 → 100644
  1 +++ a/mvpsdk/src/main/res/values-v21/styles.xml
@@ -0,0 +1,13 @@ @@ -0,0 +1,13 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<resources>
  3 +
  4 + <style name="CompatAppTheme" parent="AppBaseTheme">
  5 + <item name="android:windowNoTitle">true</item>
  6 + <item name="android:windowFullscreen">false</item>
  7 + <item name="android:windowActionBar">false</item>
  8 + <item name="windowActionModeOverlay">true</item>
  9 + <item name="android:windowDrawsSystemBarBackgrounds">true</item>
  10 + <item name="android:statusBarColor">@android:color/transparent</item>
  11 + </style>
  12 +
  13 +</resources>
mvpsdk/src/main/res/values-zh-rCN/strings.xml 0 → 100644
  1 +++ a/mvpsdk/src/main/res/values-zh-rCN/strings.xml
@@ -0,0 +1,38 @@ @@ -0,0 +1,38 @@
  1 +<resources>
  2 + <string name="dialog_positive">确定</string>
  3 + <string name="dialog_negative">取消</string>
  4 + <string name="loading">正在加载中……</string>
  5 + <string name="load_failed">加载失败,请点我重试</string>
  6 + <string name="press_again">再按一次退出</string>
  7 +
  8 + <!--历史数据界面-->
  9 + <string name="history_day">天</string>
  10 + <string name="history_week">周</string>
  11 + <string name="history_month">月</string>
  12 + <string name="history_year">年</string>
  13 + <string name="history_Indoor">室内</string>
  14 + <string name="history_Temp">温度</string>
  15 + <string name="history_Setpoint">目标</string>
  16 + <string name="history_On">加热</string>
  17 + <string name="history_Time">时间</string>
  18 + <string name="history_x_unit_day">(天)</string>
  19 + <string name="history_x_unit_hour">(小时)</string>
  20 + <string name="history_x_unit_month">(月)</string>
  21 + <string name="history_y1_unit">(℃)</string>
  22 + <string name="history_y2_unit">(%)</string>
  23 +
  24 + <!--能耗单位-->
  25 + <string name="y_unit_day">(分)</string>
  26 + <string name="y_unit_week">(小时)</string>
  27 + <string name="y_unit_month">(小时)</string>
  28 + <string name="x_unit_day">(小时)</string>
  29 + <string name="x_unit_week">(天)</string>
  30 + <string name="x_unit_month">(天)</string>
  31 + <string name="y_unit_degree">(千瓦/时)</string>
  32 + <string name="energy_consumption_day">天</string>
  33 + <string name="energy_consumption_week">周</string>
  34 + <string name="energy_consumption_month">月</string>
  35 +
  36 + <string name="empty_network_error">网络异常,点击重试</string>
  37 + <string name="empty_no_data">没有数据,点击重试</string>
  38 +</resources>
mvpsdk/src/main/res/values/arrays.xml 0 → 100644
  1 +++ a/mvpsdk/src/main/res/values/arrays.xml
@@ -0,0 +1,24 @@ @@ -0,0 +1,24 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<resources>
  3 + <string-array name="permissions">
  4 + <item>@string/permission_recode_audio_hint</item>
  5 + <item>@string/permission_get_accounts_hint</item>
  6 + <item>@string/permission_read_phone_hint</item>
  7 + <item>@string/permission_call_phone_hint</item>
  8 + <item>@string/permission_camera_hint</item>
  9 + <item>@string/permission_access_fine_location_hint</item>
  10 + <item>@string/permission_access_coarse_location_hint</item>
  11 + <item>@string/permission_read_external_hint</item>
  12 + <item>@string/permission_white_external_hint</item>
  13 + </string-array>
  14 + <string name="permission_get_accounts_hint">没有此权限,无法开启这个功能,请开启权限。PERMISSION_GET_ACCOUNTS</string>
  15 + <string name="permission_read_phone_hint">没有此权限,无法开启这个功能,请开启权限。PERMISSION_READ_PHONE_STATE</string>
  16 + <string name="permission_call_phone_hint">没有此权限,无法开启这个功能,请开启权限。PERMISSION_CALL_PHONE</string>
  17 + <string name="permission_camera_hint">没有此权限,无法开启这个功能,请开启权限。PERMISSION_CAMERA</string>
  18 + <string name="permission_access_fine_location_hint">没有此权限,无法开启这个功能,请开启权限。PERMISSION_ACCESS_FINE_LOCATION</string>
  19 + <string name="permission_access_coarse_location_hint">没有此权限,无法开启这个功能,请开启权限。PERMISSION_ACCESS_COARSE_LOCATION</string>
  20 + <string name="permission_read_external_hint">没有此权限,无法开启这个功能,请开启权限。PERMISSION_READ_EXTERNAL_STORAGE</string>
  21 + <string name="permission_white_external_hint">没有此权限,无法开启这个功能,请开启权限。PERMISSION_WRITE_EXTERNAL_STORAGE</string>
  22 + <string name="permission_recode_audio_hint">没有此权限,无法开启这个功能,请开启权限。PERMISSION_RECORD_AUDIO</string>
  23 +
  24 +</resources>
0 \ No newline at end of file 25 \ No newline at end of file
mvpsdk/src/main/res/values/attrs.xml 0 → 100644
  1 +++ a/mvpsdk/src/main/res/values/attrs.xml
@@ -0,0 +1,81 @@ @@ -0,0 +1,81 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<resources>
  3 + <attr name="themeColor" format="color|reference"/>
  4 + <attr name="widgetBackground" format="color|reference"/>
  5 + <attr name="widgetBackgroundDark" format="color|reference"/>
  6 + <attr name="widgetBackgroundTitle" format="color|reference"/>
  7 +
  8 + <declare-styleable name="RecyclerViewPager">
  9 + <attr name="rvp_triggerOffset" format="float"/>
  10 + <attr name="rvp_flingFactor" format="float"/>
  11 + <attr name="rvp_singlePageFling" format="boolean"/>
  12 + </declare-styleable>
  13 +
  14 + <declare-styleable name="SlideSwitchView">
  15 + <attr name="slide_button" format="reference"/>
  16 + <attr name="android:text"/>
  17 + <attr name="android:textSize"/>
  18 + <attr name="android:textColor"/>
  19 + </declare-styleable>
  20 +
  21 + <declare-styleable name="HistoryModeView">
  22 + <attr name="android:textColor"/>
  23 + <attr name="android:text"/>
  24 + <attr name="select_text_size" format="dimension"/>
  25 + <attr name="un_select_text_size" format="dimension"/>
  26 + </declare-styleable>
  27 +
  28 + <declare-styleable name="HistoryTipsView">
  29 + <attr name="android:textColor"/>
  30 + <attr name="android:textSize"/>
  31 + <attr name="android:src"/>
  32 + <attr name="tip_one_text" format="string"/>
  33 + <attr name="tip_two_text" format="string"/>
  34 + </declare-styleable>
  35 +
  36 + <declare-styleable name="HistoryChartView">
  37 + <attr name="ylabel_text_size" format="dimension"/>
  38 + <attr name="xlabel_text_size" format="dimension"/>
  39 + <attr name="margin_top" format="dimension"/>
  40 + <attr name="margin_bottom" format="dimension"/>
  41 + <attr name="margin_left" format="dimension"/>
  42 + <attr name="margin_right" format="dimension"/>
  43 + <attr name="line_stroke_width" format="dimension"/>
  44 + <attr name="data_stroke_width" format="dimension"/>
  45 + <attr name="circle_radius" format="dimension"/>
  46 + <attr name="line_color" format="color"/>
  47 + <attr name="unit_color" format="color"/>
  48 + <attr name="x_unit_text" format="string"/>
  49 + <attr name="y1_unit_text" format="string"/>
  50 + <attr name="y2_unit_text" format="string"/>
  51 + <attr name="y_unit_text_size" format="dimension"/>
  52 + <attr name="x_unit_text_size" format="dimension"/>
  53 + <attr name="first_data_line_color" format="color"/>
  54 + <attr name="second_data_line_color" format="color"/>
  55 + <attr name="rect_background_color" format="color"/>
  56 + <attr name="x_first_point_offset" format="dimension"/>
  57 + </declare-styleable>
  58 +
  59 + <declare-styleable name="MovingImageView">
  60 + <attr name="miv_speed" format="integer"/>
  61 + <attr name="miv_repetitions" format="integer"/>
  62 + <attr name="miv_max_relative_size" format="float"/>
  63 + <attr name="miv_min_relative_offset" format="float"/>
  64 + <attr name="miv_start_delay" format="integer"/>
  65 + <attr name="miv_load_on_create" format="boolean"/>
  66 + </declare-styleable>
  67 +
  68 + <declare-styleable name="MovingImageViewTheme">
  69 + <attr name="movingImageViewStyle" format="reference"/>
  70 + </declare-styleable>
  71 +
  72 +
  73 + <declare-styleable name="ClipViewLayout">
  74 + <attr name="clipType" format="enum">
  75 + <enum name="circle" value="1" />
  76 + <enum name="rectangle" value="2" />
  77 + </attr>
  78 + <attr name="mHorizontalPadding" format="dimension" />
  79 + <attr name="clipBorderWidth" format="dimension" />
  80 + </declare-styleable>
  81 +</resources>
0 \ No newline at end of file 82 \ No newline at end of file
mvpsdk/src/main/res/values/colors.xml 0 → 100644
  1 +++ a/mvpsdk/src/main/res/values/colors.xml
@@ -0,0 +1,76 @@ @@ -0,0 +1,76 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<resources>
  3 + <!-- basic -->
  4 + <!-- 主色调 -->
  5 + <color name="colorPrimary">#ffeeeeee</color>
  6 + <!-- 主题相关颜色 -->
  7 + <color name="window_background_light">#ffeeeeee</color>
  8 + <color name="window_background_dark">#ff303030</color>
  9 + <color name="text_color_light">#b3ffffff</color>
  10 + <color name="text_color_dark">#de000000</color>
  11 + <color name="list_divider_light">#ffe0e0e0</color>
  12 + <color name="list_divider_dark">#ff666666</color>
  13 + <color name="selectable_item_background_general_light_normal">@android:color/white</color>
  14 + <color name="selectable_item_background_general_light_pressed">#ffeeeeee</color>
  15 + <color name="selectable_item_background_general_light_accent">#ffcccccc</color>
  16 + <color name="selectable_item_background_general_dark_normal">#ff3c3c3c</color>
  17 + <color name="selectable_item_background_general_dark_pressed">#ff444444</color>
  18 + <color name="selectable_item_background_general_dark_accent">#ff666666</color>
  19 + <!-- 主体文字,标题/标签 -->
  20 + <color name="txt_black">#212121</color>
  21 + <!-- 内容文字,正文 -->
  22 + <color name="txt_gray">#808080</color>
  23 + <!-- 辅助文字,提示 -->
  24 + <color name="txt_light_gray">#CCCCCC</color>
  25 + <!-- 背景色 -->
  26 + <color name="bg_gray">#f1f1f1</color>
  27 + <!-- 按下灰色 -->
  28 + <color name="bg_gray_pressed">#e8e8e8</color>
  29 + <!-- 高亮,红棕色 -->
  30 + <color name="brown">#d54c1c</color>
  31 + <!-- 分割线 -->
  32 + <color name="divider_gray">#cbcbcb</color>
  33 + <!-- other -->
  34 + <color name="txt_link_blue">#1ea5ff</color>
  35 +
  36 + <!-- wheel -->
  37 + <color name="province_line_border">#C7C7C7</color>
  38 +
  39 + <!-- drop down menu -->
  40 + <color name="white">#ffffff</color>
  41 + <color name="gray">#cccccc</color>
  42 +
  43 + <color name="drop_down_selected">#8BC34A</color>
  44 + <color name="drop_down_unselected">#808080</color>
  45 +
  46 + <color name="mask_color">#88888888</color>
  47 + <color name="check_bg">#f1f1f1</color>
  48 + <color name="un_press_color">#8BC34A</color>
  49 +
  50 + <!-- position bar -->
  51 + <color name="bg_position_bar_up">#0D8BC34A</color>
  52 + <color name="bg_position_bar_down">#1A8BC34A</color>
  53 + <color name="theme_black_7f">#8f000000</color>
  54 +
  55 + <color name="light_yellow">#FF9500</color>
  56 + <color name="light_grey">#808080</color>
  57 + <color name="dark_grey">#333333</color>
  58 +
  59 + <color name="yellow_translucent">#80FF9500</color>
  60 +
  61 + <color name="grey_line">#808080</color>
  62 + <color name="setpoint_temp">#FF9500</color>
  63 + <color name="indoor_temp">#ffffff</color>
  64 + <color name="power_time">#4a2317</color>
  65 + <color name="light_grey2">#AAAAAA</color>
  66 +
  67 + <color name="shape_count_down_bg">#88000000</color>
  68 + <color name="text_translucent">#88000000</color>
  69 + <color name="gankio_text_type_grey">#707070</color>
  70 +
  71 + <color name="bg">#F0F0F0</color>
  72 + <color name="txt_color">#48495F</color>
  73 +
  74 + <!--电影评分-->
  75 + <color name="colorRateRed">#FB5B81</color>
  76 +</resources>
mvpsdk/src/main/res/values/dimens.xml 0 → 100644
  1 +++ a/mvpsdk/src/main/res/values/dimens.xml
@@ -0,0 +1,45 @@ @@ -0,0 +1,45 @@
  1 +<resources>
  2 +
  3 + <!-- Default screen margins, per the Android Design guidelines. -->
  4 + <dimen name="activity_horizontal_margin">16dp</dimen>
  5 + <dimen name="activity_vertical_margin">16dp</dimen>
  6 +
  7 + <!-- margin -->
  8 + <dimen name="margin_tiny">4dp</dimen>
  9 + <dimen name="margin_small">8dp</dimen>
  10 + <dimen name="margin_medium">16dp</dimen>
  11 + <dimen name="margin_large">32dp</dimen>
  12 + <dimen name="margin_huge">64dp</dimen>
  13 + <dimen name="margin_only_txt">48dp</dimen>
  14 +
  15 + <!-- txtsize -->
  16 + <dimen name="txtsize_display1">34sp</dimen>
  17 + <dimen name="txtsize_headline">24sp</dimen>
  18 + <dimen name="txtsize_title">20sp</dimen>
  19 + <dimen name="txtsize_subhead">16sp</dimen>
  20 + <dimen name="txtsize_body">14sp</dimen>
  21 + <dimen name="txtsize_caption">12sp</dimen>
  22 +
  23 + <!-- other size -->
  24 + <dimen name="corner_radius">2dp</dimen>
  25 + <dimen name="banner_height">136dp</dimen>
  26 +
  27 + <dimen name="def_height">50dp</dimen>
  28 + <dimen name="avatarSize">50dp</dimen>
  29 + <dimen name="smallSpace">6dp</dimen>
  30 +
  31 + <dimen name="dp_066">0.66dp</dimen>
  32 + <dimen name="dp_4">4dp</dimen>
  33 + <dimen name="dp_10">10dp</dimen>
  34 + <dimen name="dp_14">14dp</dimen>
  35 + <dimen name="dp_22">22dp</dimen>
  36 + <dimen name="dp_36">36dp</dimen>
  37 + <dimen name="dp_40">40dp</dimen>
  38 + <dimen name="dp_60">60dp</dimen>
  39 + <dimen name="dp_72">72dp</dimen>
  40 +
  41 + <dimen name="sp_12">12sp</dimen>
  42 + <dimen name="sp_14">14sp</dimen>
  43 + <dimen name="sp_16">16sp</dimen>
  44 + <dimen name="sp_18">18sp</dimen>
  45 +</resources>
0 \ No newline at end of file 46 \ No newline at end of file
mvpsdk/src/main/res/values/strings.xml 0 → 100644
  1 +++ a/mvpsdk/src/main/res/values/strings.xml
@@ -0,0 +1,38 @@ @@ -0,0 +1,38 @@
  1 +<resources>
  2 + <string name="dialog_positive">Confirm</string>
  3 + <string name="dialog_negative">Cancel</string>
  4 + <string name="loading">Loading……</string>
  5 + <string name="load_failed">Load failed. Please click me again</string>
  6 + <string name="press_again">Press again to exit</string>
  7 +
  8 + <!--历史数据界面-->
  9 + <string name="history_day">Day</string>
  10 + <string name="history_week">Week</string>
  11 + <string name="history_month">Month</string>
  12 + <string name="history_year">Year</string>
  13 + <string name="history_Indoor">Indoor</string>
  14 + <string name="history_Temp">Temp</string>
  15 + <string name="history_Setpoint">Setpoint</string>
  16 + <string name="history_On">Cumulative</string>
  17 + <string name="history_Time">Time</string>
  18 + <string name="history_x_unit_day">(DAY)</string>
  19 + <string name="history_x_unit_hour">(HOUR)</string>
  20 + <string name="history_x_unit_month">(MONTH)</string>
  21 + <string name="history_y1_unit">(℃)</string>
  22 + <string name="history_y2_unit">(%)</string>
  23 +
  24 + <!--能耗单位-->
  25 + <string name="y_unit_day">(min)</string>
  26 + <string name="y_unit_week">(hour)</string>
  27 + <string name="y_unit_month">(hour)</string>
  28 + <string name="x_unit_day">(hour)</string>
  29 + <string name="x_unit_week">(day)</string>
  30 + <string name="x_unit_month">(day)</string>
  31 + <string name="y_unit_degree">(KW/H)</string>
  32 + <string name="energy_consumption_day">DAY</string>
  33 + <string name="energy_consumption_week">WEEK</string>
  34 + <string name="energy_consumption_month">MONTH</string>
  35 +
  36 + <string name="empty_network_error">Network error, Click Retry</string>
  37 + <string name="empty_no_data">There is no data, Click Retry</string>
  38 +</resources>
mvpsdk/src/main/res/values/styles.xml 0 → 100644
  1 +++ a/mvpsdk/src/main/res/values/styles.xml
@@ -0,0 +1,51 @@ @@ -0,0 +1,51 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<resources>
  3 + <style name="AppBaseTheme" parent="AppThemeLight">
  4 +
  5 + </style>
  6 +
  7 + <style name="CompatAppTheme" parent="AppBaseTheme">
  8 + <item name="android:windowNoTitle">true</item>
  9 + <item name="android:windowFullscreen">false</item>
  10 + <item name="android:windowActionBar">false</item>
  11 + <item name="windowActionModeOverlay">true</item>
  12 + </style>
  13 +
  14 + <style name="TextViewTitle" parent="TextAppearance.AppCompat.Title">
  15 + <item name="android:layout_width">wrap_content</item>
  16 + <item name="android:layout_height">wrap_content</item>
  17 + <item name="android:singleLine">true</item>
  18 + <item name="android:textColor">@color/txt_black</item>
  19 + </style>
  20 +
  21 + <style name="TextViewSubhead" parent="TextAppearance.AppCompat.Subhead">
  22 + <item name="android:layout_width">wrap_content</item>
  23 + <item name="android:layout_height">wrap_content</item>
  24 + <item name="android:textColor">@color/txt_black</item>
  25 + </style>
  26 +
  27 + <style name="bg">
  28 + <item name="android:layout_width">match_parent</item>
  29 + <item name="android:layout_height">match_parent</item>
  30 + <item name="android:background">@color/bg</item>
  31 + <item name="android:orientation">vertical</item>
  32 + </style>
  33 +
  34 + <style name="net_error_img">
  35 + <item name="android:layout_width">80dp</item>
  36 + <item name="android:layout_height">80dp</item>
  37 + <item name="android:layout_marginBottom">10dp</item>
  38 + </style>
  39 +
  40 + <style name="loading_img">
  41 + <item name="android:layout_width">80dp</item>
  42 + <item name="android:layout_height">80dp</item>
  43 + </style>
  44 +
  45 + <style name="empty_img">
  46 + <item name="android:layout_width">80dp</item>
  47 + <item name="android:layout_height">80dp</item>
  48 + <item name="android:layout_marginBottom">10dp</item>
  49 + </style>
  50 +
  51 +</resources>
0 \ No newline at end of file 52 \ No newline at end of file
mvpsdk/src/main/res/values/themes.xml 0 → 100644
  1 +++ a/mvpsdk/src/main/res/values/themes.xml
@@ -0,0 +1,265 @@ @@ -0,0 +1,265 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<resources>
  3 + <!-- App Theme Light -->
  4 + <style name="BaseAppThemeLight" parent="Theme.AppCompat.Light.NoActionBar">
  5 + <item name="android:windowNoTitle">true</item>
  6 + <item name="android:windowFullscreen">false</item>
  7 + <item name="android:windowActionBar">false</item>
  8 + <item name="colorPrimary">?attr/themeColor</item>
  9 + <item name="colorPrimaryDark">?attr/themeColor</item>
  10 + <item name="colorAccent">?attr/themeColor</item>
  11 + <item name="windowActionModeOverlay">true</item>
  12 + <item name="android:windowBackground">@color/window_background_light</item>
  13 + <item name="android:listDivider">@color/list_divider_light</item>
  14 + <item name="widgetBackground">@color/selectable_item_background_general_light_normal</item>
  15 + <item name="widgetBackgroundDark">@color/selectable_item_background_general_light_pressed
  16 + </item>
  17 + <item name="widgetBackgroundTitle">@android:color/white</item>
  18 + </style>
  19 +
  20 + <style name="AppThemeLight" parent="BaseAppThemeLight">
  21 + <item name="themeColor">@color/md_light_blue_500</item>
  22 + </style>
  23 +
  24 + <style name="AppThemeLight.NoTranslucent" parent="BaseAppThemeLight">
  25 + <item name="android:windowIsTranslucent">false</item>
  26 + </style>
  27 +
  28 + <style name="AppThemeLight.FitsStatusBar" />
  29 +
  30 + <!-- App Theme Dark -->
  31 + <style name="BaseAppThemeDark" parent="Theme.AppCompat.NoActionBar">
  32 + <item name="android:windowNoTitle">true</item>
  33 + <item name="android:windowFullscreen">false</item>
  34 + <item name="android:windowActionBar">false</item>
  35 + <item name="colorPrimary">?attr/themeColor</item>
  36 + <item name="colorPrimaryDark">?attr/themeColor</item>
  37 + <item name="colorAccent">?attr/themeColor</item>
  38 + <item name="windowActionModeOverlay">true</item>
  39 + <item name="android:windowBackground">@color/window_background_dark</item>
  40 + <item name="android:listDivider">@color/list_divider_dark</item>
  41 + <item name="widgetBackground">@color/selectable_item_background_general_dark_normal</item>
  42 + <item name="widgetBackgroundDark">@color/selectable_item_background_general_dark_pressed
  43 + </item>
  44 + <item name="widgetBackgroundTitle">?attr/colorPrimary</item>
  45 + <item name="android:windowIsTranslucent">true</item>
  46 + </style>
  47 +
  48 + <style name="AppThemeDark" parent="BaseAppThemeDark">
  49 + <item name="themeColor">@color/theme_night_blue</item>
  50 + </style>
  51 +
  52 + <style name="AppThemeDark.NoTranslucent" parent="BaseAppThemeDark">
  53 + <item name="android:windowIsTranslucent">false</item>
  54 + </style>
  55 +
  56 + <style name="AppThemeDark.FitsStatusBar" />
  57 +
  58 + <!-- App Theme Launch -->
  59 + <style name="AppThemeLaunch" parent="BaseAppThemeLight">
  60 + <item name="android:windowBackground">?attr/colorPrimary</item>
  61 + </style>
  62 +
  63 + <style name="AppWidget" parent="Theme.AppCompat.Light" />
  64 +
  65 + <style name="AppWidget.DeepLine">
  66 + <item name="android:layout_width">match_parent</item>
  67 + <item name="android:layout_height">1dp</item>
  68 + <item name="android:background">?android:attr/listDivider</item>
  69 + </style>
  70 +
  71 + <style name="AppWidget.DeepLine.Vertical">
  72 + <item name="android:layout_width">1dp</item>
  73 + <item name="android:layout_height">match_parent</item>
  74 + </style>
  75 +
  76 +
  77 + <!-- red -->
  78 + <style name="AppThemeLight.Red">
  79 + <item name="themeColor">@color/md_red_500</item>
  80 + </style>
  81 +
  82 + <style name="AppThemeDark.Red">
  83 + <item name="themeColor">@color/md_red_700</item>
  84 + </style>
  85 +
  86 +
  87 + <!-- pink -->
  88 + <style name="AppThemeLight.Pink">
  89 + <item name="themeColor">@color/md_pink_500</item>
  90 + </style>
  91 +
  92 + <style name="AppThemeDark.Pink">
  93 + <item name="themeColor">@color/md_pink_700</item>
  94 + </style>
  95 +
  96 +
  97 + <!-- purple -->
  98 + <style name="AppThemeLight.Purple">
  99 + <item name="themeColor">@color/md_purple_500</item>
  100 + </style>
  101 +
  102 + <style name="AppThemeDark.Purple">
  103 + <item name="themeColor">@color/md_purple_700</item>
  104 + </style>
  105 +
  106 +
  107 + <!-- deep_purple -->
  108 + <style name="AppThemeLight.DeepPurple">
  109 + <item name="themeColor">@color/md_deep_purple_500</item>
  110 + </style>
  111 +
  112 + <style name="AppThemeDark.DeepPurple">
  113 + <item name="themeColor">@color/md_deep_purple_700</item>
  114 + </style>
  115 +
  116 +
  117 + <!-- indigo -->
  118 + <style name="AppThemeLight.Indigo">
  119 + <item name="themeColor">@color/md_indigo_500</item>
  120 + </style>
  121 +
  122 + <style name="AppThemeDark.Indigo">
  123 + <item name="themeColor">@color/md_indigo_700</item>
  124 + </style>
  125 +
  126 +
  127 + <!-- blue -->
  128 + <style name="AppThemeLight.Blue">
  129 + <item name="themeColor">@color/theme_day_blue</item>
  130 + </style>
  131 +
  132 + <style name="AppThemeDark.Blue">
  133 + <item name="themeColor">@color/theme_night_blue</item>
  134 + </style>
  135 +
  136 +
  137 + <!-- light_blue -->
  138 + <style name="AppThemeLight.LightBlue">
  139 + <item name="themeColor">@color/md_light_blue_500</item>
  140 + </style>
  141 +
  142 + <style name="AppThemeDark.LightBlue">
  143 + <item name="themeColor">@color/md_light_blue_700</item>
  144 + </style>
  145 +
  146 +
  147 + <!-- cyan -->
  148 + <style name="AppThemeLight.Cyan">
  149 + <item name="themeColor">@color/md_cyan_500</item>
  150 + </style>
  151 +
  152 + <style name="AppThemeDark.Cyan">
  153 + <item name="themeColor">@color/md_cyan_700</item>
  154 + </style>
  155 +
  156 +
  157 + <!-- teal -->
  158 + <style name="AppThemeLight.Teal">
  159 + <item name="themeColor">@color/md_teal_500</item>
  160 + </style>
  161 +
  162 + <style name="AppThemeDark.Teal">
  163 + <item name="themeColor">@color/md_teal_700</item>
  164 + </style>
  165 +
  166 +
  167 + <!-- green -->
  168 + <style name="AppThemeLight.Green">
  169 + <item name="themeColor">@color/md_green_500</item>
  170 + </style>
  171 +
  172 + <style name="AppThemeDark.Green">
  173 + <item name="themeColor">@color/md_green_700</item>
  174 + </style>
  175 +
  176 +
  177 + <!-- light_green -->
  178 + <style name="AppThemeLight.LightGreen">
  179 + <item name="themeColor">@color/md_light_green_500</item>
  180 + </style>
  181 +
  182 + <style name="AppThemeDark.LightGreen">
  183 + <item name="themeColor">@color/md_light_green_700</item>
  184 + </style>
  185 +
  186 +
  187 + <!-- lime -->
  188 + <style name="AppThemeLight.Lime">
  189 + <item name="themeColor">@color/md_lime_500</item>
  190 + </style>
  191 +
  192 + <style name="AppThemeDark.Lime">
  193 + <item name="themeColor">@color/md_lime_700</item>
  194 + </style>
  195 +
  196 +
  197 + <!-- yellow -->
  198 + <style name="AppThemeLight.Yellow">
  199 + <item name="themeColor">@color/md_yellow_500</item>
  200 + </style>
  201 +
  202 + <style name="AppThemeDark.Yellow">
  203 + <item name="themeColor">@color/md_yellow_700</item>
  204 + </style>
  205 +
  206 +
  207 + <!-- amber -->
  208 + <style name="AppThemeLight.Amber">
  209 + <item name="themeColor">@color/md_amber_500</item>
  210 + </style>
  211 +
  212 + <style name="AppThemeDark.Amber">
  213 + <item name="themeColor">@color/md_amber_700</item>
  214 + </style>
  215 +
  216 +
  217 + <!-- orange -->
  218 + <style name="AppThemeLight.Orange">
  219 + <item name="themeColor">@color/md_orange_500</item>
  220 + </style>
  221 +
  222 + <style name="AppThemeDark.Orange">
  223 + <item name="themeColor">@color/md_orange_700</item>
  224 + </style>
  225 +
  226 +
  227 + <!-- deep_orange -->
  228 + <style name="AppThemeLight.DeepOrange">
  229 + <item name="themeColor">@color/md_deep_orange_500</item>
  230 + </style>
  231 +
  232 + <style name="AppThemeDark.DeepOrange">
  233 + <item name="themeColor">@color/md_deep_orange_700</item>
  234 + </style>
  235 +
  236 +
  237 + <!-- brown -->
  238 + <style name="AppThemeLight.Brown">
  239 + <item name="themeColor">@color/md_brown_500</item>
  240 + </style>
  241 +
  242 + <style name="AppThemeDark.Brown">
  243 + <item name="themeColor">@color/md_brown_700</item>
  244 + </style>
  245 +
  246 +
  247 + <!-- grey -->
  248 + <style name="AppThemeLight.Grey">
  249 + <item name="themeColor">@color/md_grey_500</item>
  250 + </style>
  251 +
  252 + <style name="AppThemeDark.Grey">
  253 + <item name="themeColor">@color/md_grey_700</item>
  254 + </style>
  255 +
  256 +
  257 + <!-- blue_grey -->
  258 + <style name="AppThemeLight.BlueGrey">
  259 + <item name="themeColor">@color/md_blue_grey_500</item>
  260 + </style>
  261 +
  262 + <style name="AppThemeDark.BlueGrey">
  263 + <item name="themeColor">@color/md_blue_grey_700</item>
  264 + </style>
  265 +</resources>
0 \ No newline at end of file 266 \ No newline at end of file
mvpsdk/src/main/res/values/themes_colors.xml 0 → 100644
  1 +++ a/mvpsdk/src/main/res/values/themes_colors.xml
@@ -0,0 +1,85 @@ @@ -0,0 +1,85 @@
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<resources>
  3 + <!-- red -->
  4 + <color name="md_red_500">#e51c23</color>
  5 + <color name="md_red_700">#d01716</color>
  6 +
  7 + <!-- pink -->
  8 + <color name="md_pink_500">#e91e63</color>
  9 + <color name="md_pink_700">#c2185b</color>
  10 +
  11 + <!-- purple -->
  12 + <color name="md_purple_500">#9c27b0</color>
  13 + <color name="md_purple_700">#7b1fa2</color>
  14 +
  15 + <!-- deep_purple -->
  16 + <color name="md_deep_purple_500">#673ab7</color>
  17 + <color name="md_deep_purple_700">#512da8</color>
  18 +
  19 + <!-- indigo -->
  20 + <color name="md_indigo_500">#3f51b5</color>
  21 + <color name="md_indigo_700">#303f9f</color>
  22 +
  23 + <!-- blue -->
  24 + <color name="md_blue_500">#5677fc</color>
  25 + <color name="md_blue_700">#455ede</color>
  26 +
  27 + <!-- light_blue -->
  28 + <color name="md_light_blue_500">#03a9f4</color>
  29 + <color name="md_light_blue_700">#0288d1</color>
  30 +
  31 + <!-- cyan -->
  32 + <color name="md_cyan_500">#00bcd4</color>
  33 + <color name="md_cyan_700">#0097a7</color>
  34 +
  35 + <!-- teal -->
  36 + <color name="md_teal_500">#009688</color>
  37 + <color name="md_teal_700">#00796b</color>
  38 +
  39 + <!-- green -->
  40 + <color name="md_green_500">#259b24</color>
  41 + <color name="md_green_700">#0a7e07</color>
  42 + <!--<color name="md_green_700">#ff3c3c3c</color>-->
  43 +
  44 + <!-- light_green -->
  45 + <color name="md_light_green_500">#8bc34a</color>
  46 + <color name="md_light_green_700">#689f38</color>
  47 +
  48 + <!-- lime -->
  49 + <color name="md_lime_500">#cddc39</color>
  50 + <color name="md_lime_700">#afb42b</color>
  51 +
  52 + <!-- yellow -->
  53 + <color name="md_yellow_500">#ffeb3b</color>
  54 + <color name="md_yellow_700">#fbc02d</color>
  55 +
  56 + <!-- amber -->
  57 + <color name="md_amber_500">#ffc107</color>
  58 + <color name="md_amber_700">#ffa000</color>
  59 +
  60 + <!-- orange -->
  61 + <color name="md_orange_500">#ff9800</color>
  62 + <color name="md_orange_700">#f57c00</color>
  63 +
  64 + <!-- deep_orange -->
  65 + <color name="md_deep_orange_500">#ff5722</color>
  66 + <color name="md_deep_orange_700">#e64a19</color>
  67 +
  68 + <!-- brown -->
  69 + <color name="md_brown_500">#795548</color>
  70 + <color name="md_brown_700">#5d4037</color>
  71 +
  72 + <!-- grey -->
  73 + <color name="md_grey_500">#9e9e9e</color>
  74 + <color name="md_grey_700">#616161</color>
  75 + <!-- <color name="md_grey_1000">#000000</color> -->
  76 + <!-- <color name="md_grey_1000">#ffffff</color> -->
  77 + <color name="md_white">#ffffff</color>
  78 +
  79 + <!-- blue_grey -->
  80 + <color name="md_blue_grey_500">#607d8b</color>
  81 + <color name="md_blue_grey_700">#455a64</color>
  82 +
  83 + <color name="theme_day_blue">#03a9f4</color>
  84 + <color name="theme_night_blue">#ff3c3c3c</color>
  85 +</resources>
0 \ No newline at end of file 86 \ No newline at end of file
mvpsdk/src/test/java/com/share/mvpsdk/ExampleUnitTest.java 0 → 100644
  1 +++ a/mvpsdk/src/test/java/com/share/mvpsdk/ExampleUnitTest.java
@@ -0,0 +1,17 @@ @@ -0,0 +1,17 @@
  1 +package com.share.mvpsdk;
  2 +
  3 +import org.junit.Test;
  4 +
  5 +import static org.junit.Assert.*;
  6 +
  7 +/**
  8 + * Example local unit test, which will execute on the development machine (host).
  9 + *
  10 + * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
  11 + */
  12 +public class ExampleUnitTest {
  13 + @Test
  14 + public void addition_isCorrect() throws Exception {
  15 + assertEquals(4, 2 + 2);
  16 + }
  17 +}
0 \ No newline at end of file 18 \ No newline at end of file
settings.gradle 0 → 100644
  1 +++ a/settings.gradle
@@ -0,0 +1 @@ @@ -0,0 +1 @@
  1 +include ':app', ':mvpsdk'