Commit 54127ffd102ed962a04324441ea77977dbc12a37
0 parents
Exists in
master
and in
3 other branches
no message
Showing
175 changed files
with
13161 additions
and
0 deletions
Show diff stats
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 |
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 |
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 |
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 |
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 |
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 | +} |
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 | +} |
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 |
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> |
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> |
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> |
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> |
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> |
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> |
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> |
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> |
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> |
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> |
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 |
2.98 KB
4.91 KB
2.05 KB
2.79 KB
4.46 KB
6.93 KB
6.31 KB
10.4 KB
9.03 KB
15.2 KB
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 |
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 | + |
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 |
No preview for this file type
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 |
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 "$@" |
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 |
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 | +} |
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 | +} |
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 | +} |
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
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
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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> |
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> |
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> |
617 Bytes
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> |
32.1 KB
904 Bytes
3.03 KB
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 |
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 |
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 |
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 |
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 |
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 |
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 |
233 Bytes
374 Bytes
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> |
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> |
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 |
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 |
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> |
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 |
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> |
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 |
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 |
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 |