Commit 852255b217512aea588ab1a7b5314ef4a426685a

Authored by 韩亚云
1 parent 31cde7c5

图片基类编写

Showing 30 changed files with 2711 additions and 4 deletions
app/strike/build.gradle
... ... @@ -157,7 +157,7 @@ dependencies {
157 157 // implementation project(path: ':core:database')
158 158 implementation project(path: ':core:network')
159 159 implementation project(path: ':core:base')
160   -
  160 + implementation project(path: ':core:imageload')
161 161 // implementation project(path: ':core:util')
162 162 // implementation project(path: ':core:encipher')
163 163 // implementation project(path: ':cloud:user')
... ...
app/strike/src/main/AndroidManifest.xml
... ... @@ -13,7 +13,8 @@
13 13 android:roundIcon="@mipmap/ic_launcher_round"
14 14 android:supportsRtl="true"
15 15 android:theme="@style/AppTheme">
16   - <activity android:name=".MyActivity"></activity>
  16 + <activity android:name=".imgutil.ImgActivity"></activity>
  17 + <activity android:name=".MyActivity" />
17 18 <activity android:name=".MainActivity">
18 19 <intent-filter>
19 20 <action android:name="android.intent.action.MAIN" />
... ...
app/strike/src/main/java/com/cnlive/strike/MainActivity.java
... ... @@ -7,6 +7,8 @@ import android.os.Bundle;
7 7 import android.util.AttributeSet;
8 8 import android.view.View;
9 9  
  10 +import com.cnlive.strike.imgutil.ImgActivity;
  11 +
10 12 import androidx.annotation.NonNull;
11 13 import androidx.annotation.Nullable;
12 14 import androidx.appcompat.app.AppCompatActivity;
... ... @@ -19,7 +21,7 @@ public class MainActivity extends AppCompatActivity {
19 21 super.onCreate(savedInstanceState);
20 22 setContentView(R.layout.activity_main);
21 23 findViewById(R.id.go_to).setOnClickListener(view -> startActivity(new Intent(this,MyActivity.class)) );
22   -
  24 + findViewById(R.id.to_img).setOnClickListener(view -> startActivity(new Intent(this, ImgActivity.class)) );
23 25 }
24 26  
25 27 @Nullable
... ...
app/strike/src/main/java/com/cnlive/strike/imgutil/ImgActivity.java 0 → 100644
  1 +package com.cnlive.strike.imgutil;
  2 +
  3 +import androidx.appcompat.app.AppCompatActivity;
  4 +
  5 +import android.animation.ObjectAnimator;
  6 +import android.os.Bundle;
  7 +import android.view.View;
  8 +import android.view.ViewPropertyAnimator;
  9 +import android.widget.ImageView;
  10 +
  11 +import com.bumptech.glide.request.transition.ViewPropertyTransition;
  12 +import com.cnlive.core.imageload.loader.ImageLoader;
  13 +import com.cnlive.strike.R;
  14 +
  15 +public class ImgActivity extends AppCompatActivity {
  16 +
  17 + private ImageView iv_test1;
  18 + private ImageView iv_test2;
  19 + private ImageView iv_test02;
  20 + private ImageView iv_test3;
  21 + private ImageView iv_test4;
  22 + private ImageView iv_test5;
  23 + private ImageView iv_test6;
  24 + private ImageView iv_test7;
  25 + private ImageView iv_test8;
  26 + private ImageView iv_test9;
  27 + private ImageView iv_test10;
  28 + private ImageView iv_test11;
  29 + private ImageView iv_test12;
  30 + private ImageView iv_test13;
  31 + private ImageView iv_test14;
  32 + private ImageView iv_test15;
  33 +
  34 + String URL1 = "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1574403931080&di=ea10bd1adb20025f02e296d8694f7bb4&imgtype=0&src=http%3A%2F%2Fimg3.duitang.com%2Fuploads%2Fitem%2F201506%2F23%2F20150623164841_jtvR3.thumb.700_0.jpeg";
  35 +
  36 + @Override
  37 + protected void onCreate(Bundle savedInstanceState) {
  38 + super.onCreate(savedInstanceState);
  39 + setContentView(R.layout.activity_img);
  40 + ImageLoader.init(this);
  41 + findview();
  42 + load();
  43 + }
  44 +
  45 + private void findview() {
  46 + iv_test1 = findViewById(R.id.iv_test1);
  47 + iv_test2 = findViewById(R.id.iv_test2);
  48 + iv_test02 = findViewById(R.id.iv_test02);
  49 + iv_test3 = findViewById(R.id.iv_test3);
  50 + iv_test4 = findViewById(R.id.iv_test4);
  51 + iv_test5 = findViewById(R.id.iv_test5);
  52 + iv_test6 =findViewById(R.id.iv_test6);
  53 + iv_test7 = findViewById(R.id.iv_test7);
  54 + iv_test8 = findViewById(R.id.iv_test8);
  55 + iv_test9 = findViewById(R.id.iv_test9);
  56 + iv_test10 = findViewById(R.id.iv_test10);
  57 + iv_test11 = findViewById(R.id.iv_test11);
  58 + iv_test12 = findViewById(R.id.iv_test12);
  59 + iv_test13 = findViewById(R.id.iv_test13);
  60 + iv_test14 = findViewById(R.id.iv_test14);
  61 + iv_test15 = findViewById(R.id.iv_test15);
  62 + }
  63 +
  64 +
  65 + private void load(){
  66 + ViewPropertyTransition.Animator animation = new ViewPropertyTransition.Animator(){
  67 +
  68 + @Override
  69 + public void animate(View view) {
  70 + view.setAlpha( 0f );
  71 + ObjectAnimator fadeAnim = ObjectAnimator.ofFloat( view, "alpha", 0f, 1f );
  72 + fadeAnim.setDuration( 2500 );
  73 + fadeAnim.start();
  74 + }
  75 + };
  76 +
  77 + ImageLoader.with(this)
  78 + .url(URL1)
  79 + .animate(animation)
  80 + .into(iv_test1);
  81 +
  82 + ImageLoader.with(this)
  83 + .url(URL1)
  84 + .scale(1)//缩放几倍
  85 + .into(iv_test02);
  86 +
  87 + ImageLoader.with(this)
  88 + .url(URL1)
  89 + .scale(3)
  90 + .into(iv_test2);
  91 +
  92 +
  93 + }
  94 +}
... ...
app/strike/src/main/res/layout/activity_img.xml 0 → 100644
  1 +<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
  2 + android:layout_width="match_parent"
  3 + android:layout_height="match_parent"
  4 + xmlns:lb="http://schemas.android.com/apk/res-auto">
  5 +
  6 + <LinearLayout
  7 + android:layout_width="match_parent"
  8 + android:layout_height="match_parent"
  9 + android:orientation="vertical">
  10 +
  11 + <TextView
  12 + android:layout_width="wrap_content"
  13 + android:layout_height="wrap_content"
  14 + android:text="加载动效自定义:"
  15 + />
  16 + <ImageView
  17 + android:id="@+id/iv_test1"
  18 + android:layout_width="300dp"
  19 + android:layout_height="300dp"
  20 + android:padding="10dp" />
  21 + <TextView
  22 + android:layout_width="wrap_content"
  23 + android:layout_height="wrap_content"
  24 + android:text="放大缩小:"
  25 + />
  26 + <LinearLayout
  27 + android:layout_width="wrap_content"
  28 + android:layout_height="wrap_content"
  29 + android:orientation="vertical">
  30 + <ImageView
  31 + android:id="@+id/iv_test02"
  32 + android:layout_width="300dp"
  33 + android:layout_height="300dp"
  34 + android:padding="10dp" />
  35 + <ImageView
  36 + android:id="@+id/iv_test2"
  37 + android:layout_width="300dp"
  38 + android:layout_height="300dp"
  39 + android:padding="10dp" />
  40 + </LinearLayout>
  41 +
  42 + <ImageView
  43 + android:id="@+id/iv_test3"
  44 + android:layout_width="300dp"
  45 + android:layout_height="300dp"
  46 + android:padding="30dp" />
  47 +
  48 + <ImageView
  49 + android:id="@+id/iv_test4"
  50 + android:layout_width="300dp"
  51 + android:layout_height="300dp"
  52 + android:padding="30dp" />
  53 +
  54 + <ImageView
  55 + android:id="@+id/iv_test5"
  56 + android:layout_width="300dp"
  57 + android:layout_height="300dp"
  58 + android:padding="30dp" />
  59 +
  60 + <ImageView
  61 + android:id="@+id/iv_test6"
  62 + android:layout_width="300dp"
  63 + android:layout_height="300dp"
  64 + android:padding="30dp" />
  65 +
  66 + <ImageView
  67 + android:id="@+id/iv_test7"
  68 + android:layout_width="300dp"
  69 + android:layout_height="300dp"
  70 + android:padding="30dp" />
  71 +
  72 + <ImageView
  73 + android:id="@+id/iv_test8"
  74 + android:layout_width="300dp"
  75 + android:layout_height="300dp"
  76 + android:padding="30dp" />
  77 +
  78 + <ImageView
  79 + android:id="@+id/iv_test9"
  80 + android:layout_width="300dp"
  81 + android:layout_height="300dp"
  82 + android:padding="30dp" />
  83 +
  84 + <ImageView
  85 + android:id="@+id/iv_test10"
  86 + android:layout_width="300dp"
  87 + android:layout_height="300dp"
  88 + android:padding="30dp" />
  89 +
  90 + <ImageView
  91 + android:id="@+id/iv_test11"
  92 + android:layout_width="300dp"
  93 + android:layout_height="300dp"
  94 + android:padding="30dp" />
  95 +
  96 + <ImageView
  97 + android:id="@+id/iv_test12"
  98 + android:layout_width="300dp"
  99 + android:layout_height="300dp"
  100 + android:padding="30dp" />
  101 +
  102 + <ImageView
  103 + android:id="@+id/iv_test13"
  104 + android:layout_width="300dp"
  105 + android:layout_height="300dp"
  106 + android:padding="30dp" />
  107 +
  108 + <ImageView
  109 + android:id="@+id/iv_test14"
  110 + android:layout_width="300dp"
  111 + android:layout_height="300dp"
  112 + android:padding="30dp" />
  113 +
  114 + <ImageView
  115 + android:id="@+id/iv_test15"
  116 + android:layout_width="300dp"
  117 + android:layout_height="300dp"
  118 + android:padding="30dp" />
  119 +
  120 +
  121 + <com.cnlive.core.imageload.util.MultiView
  122 + android:layout_width="300dp"
  123 + android:layout_height="300dp"
  124 + android:layout_margin="30dp"
  125 + lb:angleCount="5"
  126 + lb:type="multi"
  127 + />
  128 +
  129 + <com.cnlive.core.imageload.util.MultiView
  130 + android:layout_width="200dp"
  131 + android:layout_height="200dp"
  132 + android:layout_margin="30dp"
  133 + android:layout_gravity="center"
  134 + lb:borderRadius="10dp"
  135 + lb:type="round"
  136 + />
  137 +
  138 + <com.cnlive.core.imageload.util.MultiView
  139 + android:layout_margin="30dp"
  140 + android:layout_width="200dp"
  141 + android:layout_height="200dp"
  142 + android:layout_gravity="center"
  143 + lb:type="circle"
  144 + />
  145 +
  146 + </LinearLayout>
  147 +</ScrollView>
... ...
app/strike/src/main/res/layout/activity_main.xml
... ... @@ -14,5 +14,11 @@
14 14 android:layout_height="wrap_content"
15 15 android:text="跳转"/>
16 16  
  17 + <Button
  18 + android:id="@+id/to_img"
  19 + android:layout_width="wrap_content"
  20 + android:layout_height="wrap_content"
  21 + android:text="图片加载测试"/>
  22 +
17 23 </RelativeLayout>
18 24 </layout>
19 25 \ No newline at end of file
... ...
core/imageload/.gitignore 0 → 100644
  1 +/build
... ...
core/imageload/build.gradle 0 → 100644
  1 +apply plugin: 'com.android.library'
  2 +
  3 +android {
  4 + compileSdkVersion 29
  5 + buildToolsVersion "29.0.2"
  6 +
  7 +
  8 + defaultConfig {
  9 + minSdkVersion 16
  10 + targetSdkVersion 29
  11 + versionCode 1
  12 + versionName "1.0"
  13 +
  14 + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
  15 + consumerProguardFiles 'consumer-rules.pro'
  16 + }
  17 +
  18 + buildTypes {
  19 + release {
  20 + minifyEnabled false
  21 + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
  22 + }
  23 + }
  24 +
  25 +}
  26 +
  27 +dependencies {
  28 + implementation fileTree(dir: 'libs', include: ['*.jar'])
  29 +
  30 + implementation 'androidx.appcompat:appcompat:1.1.0'
  31 + testImplementation 'junit:junit:4.12'
  32 + androidTestImplementation 'androidx.test:runner:1.1.1'
  33 + androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
  34 +
  35 + implementation 'com.github.bumptech.glide:glide:4.10.0'
  36 + implementation 'com.squareup.okhttp3:okhttp:3.14.2'
  37 + implementation 'jp.wasabeef:glide-transformations:3.0.1'
  38 + //滤镜
  39 + implementation 'jp.co.cyberagent.android.gpuimage:gpuimage-library:1.4.1'
  40 +}
... ...
core/imageload/consumer-rules.pro 0 → 100644
core/imageload/proguard-rules.pro 0 → 100644
  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
... ...
core/imageload/src/androidTest/java/com/mm999/imageload/ExampleInstrumentedTest.java 0 → 100644
  1 +package com.mm999.imageload;
  2 +
  3 +import android.content.Context;
  4 +
  5 +import androidx.test.platform.app.InstrumentationRegistry;
  6 +import androidx.test.ext.junit.runners.AndroidJUnit4;
  7 +
  8 +import org.junit.Test;
  9 +import org.junit.runner.RunWith;
  10 +
  11 +import static org.junit.Assert.*;
  12 +
  13 +/**
  14 + * Instrumented test, which will execute on an Android device.
  15 + *
  16 + * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
  17 + */
  18 +@RunWith(AndroidJUnit4.class)
  19 +public class ExampleInstrumentedTest {
  20 + @Test
  21 + public void useAppContext() {
  22 + // Context of the app under test.
  23 + Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
  24 +
  25 + assertEquals("com.mm999.imageload.test", appContext.getPackageName());
  26 + }
  27 +}
... ...
core/imageload/src/main/AndroidManifest.xml 0 → 100644
  1 +<manifest xmlns:android="http://schemas.android.com/apk/res/android"
  2 + package="com.cnlive.core.imageload" />
... ...
core/imageload/src/main/java/com/cnlive/core/imageload/callback/ImageDownLoadCallBack.java 0 → 100644
  1 +package com.cnlive.core.imageload.callback;
  2 +
  3 +import android.graphics.Bitmap;
  4 +
  5 +/**
  6 + * created by hanyayun
  7 + * on 2019/11/19
  8 + */
  9 +public interface ImageDownLoadCallBack {
  10 +
  11 + void onDownLoadSuccess(Bitmap bitmap);
  12 +
  13 + void onDownLoadFailed();
  14 +}
... ...
core/imageload/src/main/java/com/cnlive/core/imageload/config/AnimationMode.java 0 → 100644
  1 +package com.cnlive.core.imageload.config;
  2 +
  3 +/**
  4 + * created by hanyayun
  5 + * on 2019/11/19
  6 + */
  7 +public interface AnimationMode {
  8 +
  9 + int ANIMATIONID = 1;
  10 +
  11 + int ANIMATION = 2;
  12 +
  13 + int ANIMATOR = 3;
  14 +}
... ...
core/imageload/src/main/java/com/cnlive/core/imageload/config/Contants.java 0 → 100644
  1 +package com.cnlive.core.imageload.config;
  2 +
  3 +/**
  4 + * created by hanyayun
  5 + * on 2019/11/19
  6 + */
  7 +public interface Contants {
  8 + String FOREWARD_SLASH = "/";
  9 + String ASSERTS_PATH ="file:///android_asset/" ;
  10 + String ANDROID_RESOURCE ="android.resource://" ;
  11 + String RAW ="/raw/" ;
  12 +}
... ...
core/imageload/src/main/java/com/cnlive/core/imageload/config/GlobalConfig.java 0 → 100644
  1 +package com.cnlive.core.imageload.config;
  2 +
  3 +import android.content.Context;
  4 +import android.content.res.Configuration;
  5 +import android.os.Handler;
  6 +import android.os.Looper;
  7 +import android.view.WindowManager;
  8 +
  9 +import com.bumptech.glide.MemoryCategory;
  10 +import com.cnlive.core.imageload.loader.GlideLoader;
  11 +import com.cnlive.core.imageload.loader.ILoader;
  12 +
  13 +/**
  14 + * created by hanyayun
  15 + * on 2019/11/19
  16 + */
  17 +public class GlobalConfig {
  18 +
  19 + public static String baseUrl;
  20 + public static Context context;
  21 +
  22 + /**
  23 + * 屏幕高度
  24 + */
  25 + private static int winHeight;
  26 +
  27 + /**
  28 + * 屏幕宽度
  29 + */
  30 + private static int winWidth;
  31 +
  32 + /**
  33 + * lrucache 最大值
  34 + */
  35 + public static int cacheMaxSize;
  36 +
  37 + /**
  38 + * https是否忽略校验,默认不忽略
  39 + */
  40 + public static boolean ignoreCertificateVerify = false;
  41 +
  42 + private static Handler mainHandler;
  43 + public static Handler getMainHandler() {
  44 + if (mainHandler == null) {
  45 + mainHandler = new Handler(Looper.getMainLooper());
  46 + }
  47 + return mainHandler;
  48 + }
  49 +
  50 + public static void init(Context context, int cacheSizeInM, MemoryCategory memoryCategory, boolean isInternalCD) {
  51 +
  52 + GlobalConfig.context = context;
  53 + GlobalConfig.cacheMaxSize = cacheSizeInM;
  54 + WindowManager wm = (WindowManager) context
  55 + .getSystemService(Context.WINDOW_SERVICE);
  56 +
  57 + GlobalConfig.winWidth = wm.getDefaultDisplay().getWidth();
  58 + GlobalConfig.winHeight = wm.getDefaultDisplay().getHeight();
  59 + getLoader().init(context, cacheSizeInM, memoryCategory, isInternalCD);
  60 +
  61 + }
  62 +
  63 + private static ILoader loader;
  64 +
  65 + public static ILoader getLoader() {
  66 +
  67 + if (loader == null) {
  68 + loader = new GlideLoader();
  69 + }
  70 +
  71 + return loader;
  72 + }
  73 +
  74 + public static int getWinHeight() {
  75 + if (context.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
  76 + return winHeight < winWidth ? winHeight : winWidth;
  77 + } else if (context.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
  78 + return winHeight > winWidth ? winHeight : winWidth;
  79 + }
  80 + return winHeight;
  81 + }
  82 +
  83 + public static int getWinWidth() {
  84 + if (context.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
  85 + return winHeight > winWidth ? winHeight : winWidth;
  86 + } else if (context.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
  87 + return winHeight < winWidth ? winHeight : winWidth;
  88 + }
  89 + return winWidth;
  90 + }
  91 +}
... ...
core/imageload/src/main/java/com/cnlive/core/imageload/config/PriorityMode.java 0 → 100644
  1 +package com.cnlive.core.imageload.config;
  2 +
  3 +/**
  4 + * created by hanyayun
  5 + * on 2019/11/19
  6 + */
  7 +public interface PriorityMode {
  8 + int PRIORITY_LOW = 1 ;
  9 +
  10 + int PRIORITY_NORMAL = 2 ;
  11 +
  12 + int PRIORITY_HIGH = 3 ;
  13 +
  14 + int PRIORITY_IMMEDIATE = 4 ;
  15 +}
... ...
core/imageload/src/main/java/com/cnlive/core/imageload/config/ScaleMode.java 0 → 100644
  1 +package com.cnlive.core.imageload.config;
  2 +
  3 +/**
  4 + * created by hanyayun
  5 + * on 2019/11/20
  6 + */
  7 +public interface ScaleMode {
  8 + /**
  9 + * 等比例缩放图片,直到图片的狂高都大于等于ImageView的宽度,然后截取中间的显示
  10 + */
  11 + int CENTER_CROP = 1;
  12 + /**
  13 + * 等比例缩放图片,宽或者是高等于ImageView的宽或者是高
  14 + */
  15 + int FIT_CENTER = 2;
  16 +}
... ...
core/imageload/src/main/java/com/cnlive/core/imageload/config/ShapeMode.java 0 → 100644
  1 +package com.cnlive.core.imageload.config;
  2 +
  3 +/**
  4 + * created by hanyayun
  5 + * on 2019/11/19
  6 + */
  7 +public interface ShapeMode {
  8 +
  9 + /**
  10 + * 直角矩形
  11 + */
  12 + int RECT = 0;
  13 +
  14 + /**
  15 + * 圆角矩形
  16 + */
  17 + int RECT_ROUND = 1;
  18 +
  19 + /**
  20 + * 椭圆/圆
  21 + */
  22 + int OVAL = 2;
  23 +
  24 + /**
  25 + *正方形
  26 + */
  27 + int SQUARE = 3;
  28 +}
... ...
core/imageload/src/main/java/com/cnlive/core/imageload/config/SingleConfig.java 0 → 100644
  1 +package com.cnlive.core.imageload.config;
  2 +
  3 +import android.content.Context;
  4 +import android.graphics.Bitmap;
  5 +import android.util.Log;
  6 +import android.view.View;
  7 +import android.view.animation.Animation;
  8 +
  9 +import com.bumptech.glide.load.engine.DiskCacheStrategy;
  10 +import com.bumptech.glide.request.transition.ViewPropertyAnimationFactory;
  11 +import com.bumptech.glide.request.transition.ViewPropertyTransition;
  12 +import com.cnlive.core.imageload.util.ImageUtil;
  13 +
  14 +import java.io.File;
  15 +
  16 +/**
  17 + * created by hanyayun
  18 + * on 2019/11/19
  19 + */
  20 +public class SingleConfig {
  21 + private Context context;
  22 + private boolean ignoreCertificateVerify; //https是否忽略校验
  23 + private String url;
  24 +
  25 + private float thumbnail; //缩略图缩放倍数
  26 + private String filePath; //文件路径
  27 +
  28 + private File file; //文件路径
  29 + private int resId; //资源id
  30 + private String rawPath; //raw路径
  31 + private String assertspath; //asserts路径
  32 + private String contentProvider; //内容提供者
  33 + private boolean isGif; //是否是GIF图
  34 + private View target;
  35 + private int width;
  36 + private int height;
  37 + private int oWidth;
  38 + private int oHeight;
  39 +
  40 + //滤镜
  41 + private boolean isNeedVignette; //是否需要晕映
  42 + private boolean isNeedSketch; //是否需要素描
  43 + private float pixelationLevel; //是否需要马赛克
  44 + private boolean isNeedPixelation; //是否需要马赛克
  45 + private boolean isNeedInvert; //是否需要胶片
  46 + public float contrastLevel; //锐化等级
  47 + private boolean isNeedContrast; //是否需要锐化
  48 + private boolean isNeedSepia; //是否需要墨画
  49 + private boolean isNeedToon; //是否需要油画
  50 + private boolean isNeedSwirl; // 是否需要漩涡
  51 + private boolean isNeedGrayscale; //是否需要黑色
  52 + private boolean isNeedBrightness; //是否需要亮度
  53 + private float brightnessLeve; //是否需要亮度
  54 + private boolean needBlur;//是否需要模糊
  55 + private boolean needFilteColor;//是否需要模糊
  56 +
  57 + private int filteColor;//滤镜颜色
  58 + private int priority;//请求优先级
  59 +
  60 + private int animationType;//动画资源Type
  61 + private int animationId;//动画资源id
  62 + private ViewPropertyTransition.Animator animation;//动画资源
  63 +
  64 + private ViewPropertyAnimationFactory animator;//动画资源id
  65 +
  66 + private int blurRadius;//是否需要高斯模糊
  67 + private int placeHolderResId; //占位图
  68 + private int errorResId; //error图
  69 +
  70 + private int shapeMode;//默认矩形,可选直角矩形,圆形/椭圆
  71 + private int rectRoundRadius;//圆角矩形时圆角的半径
  72 + private DiskCacheStrategy diskCacheStrategy;//是否跳过磁盘存储
  73 + private int scaleMode;//填充模式,默认centercrop,可选fitXY,centerInside...
  74 +
  75 + private BitmapListener bitmapListener;
  76 + private boolean asBitmap;//只获取bitmap
  77 +
  78 + public SingleConfig(ConfigBuilder builder) {
  79 + this.url = builder.url;
  80 + this.thumbnail = builder.thumbnail;
  81 + this.filePath = builder.filePath;
  82 + this.file = builder.file;
  83 + this.resId = builder.resId;
  84 + this.rawPath = builder.rawPath;
  85 + this.assertspath = builder.assertspath;
  86 + this.contentProvider = builder.contentProvider;
  87 +
  88 + this.ignoreCertificateVerify = builder.ignoreCertificateVerify;
  89 +
  90 + this.target = builder.target;
  91 +
  92 + this.width = builder.width;
  93 + this.height = builder.height;
  94 +
  95 + this.oWidth = builder.oWidth;
  96 + this.oHeight = builder.oHeight;
  97 +
  98 + this.shapeMode = builder.shapeMode;
  99 + if (shapeMode == ShapeMode.RECT_ROUND) {
  100 + this.rectRoundRadius = builder.rectRoundRadius;
  101 + }
  102 + this.scaleMode = builder.scaleMode;
  103 +
  104 + this.diskCacheStrategy = builder.diskCacheStrategy;
  105 +
  106 + this.animationId = builder.animationId;
  107 + this.animationType = builder.animationType;
  108 + this.animator = builder.animator;
  109 + this.animation = builder.animation;
  110 +
  111 + this.priority = builder.priority;
  112 + //滤镜
  113 + this.isNeedVignette = builder.isNeedVignette; //是否需要晕映
  114 + this.isNeedSketch = builder.isNeedSketch; //是否需要素描
  115 + this.pixelationLevel = builder.pixelationLevel; //是否需要马赛克
  116 + this.isNeedPixelation = builder.isNeedPixelation; //是否需要马赛克
  117 + this.isNeedInvert = builder.isNeedInvert; //是否需要胶片
  118 + this.contrastLevel = builder.contrastLevel; //锐化等级
  119 + this.isNeedContrast = builder.isNeedContrast; //是否需要锐化
  120 + this.isNeedSepia = builder.isNeedSepia; //是否需要亮度
  121 + this.isNeedToon = builder.isNeedToon; //是否需要亮度
  122 + this.isNeedSwirl = builder.isNeedSwirl; //是否需要亮度
  123 + this.isNeedGrayscale = builder.isNeedGrayscale; //是否需要黑色
  124 + this.isNeedBrightness = builder.isNeedBrightness; //是否需要亮度
  125 + this.brightnessLeve = builder.brightnessLeve; //是否需要亮度
  126 + this.filteColor = builder.filteColor;
  127 + this.needBlur = builder.needBlur;
  128 + this.needFilteColor = builder.needFilteColor;
  129 + this.placeHolderResId = builder.placeHolderResId;
  130 +
  131 + this.asBitmap = builder.asBitmap;
  132 + this.bitmapListener = builder.bitmapListener;
  133 + this.isGif = builder.isGif;
  134 + this.blurRadius = builder.blurRadius;
  135 + this.errorResId = builder.errorResId;
  136 + }
  137 +
  138 +
  139 + public Context getContext() {
  140 + if (context == null) {
  141 + context = GlobalConfig.context;
  142 + }
  143 + return context;
  144 + }
  145 +
  146 + public DiskCacheStrategy getDiskCacheStrategy() {
  147 + return diskCacheStrategy;
  148 + }
  149 +
  150 + public String getContentProvider() {
  151 + return contentProvider;
  152 + }
  153 +
  154 + public int getErrorResId() {
  155 + return errorResId;
  156 + }
  157 +
  158 + public String getFilePath() {
  159 + return filePath;
  160 + }
  161 +
  162 + public File getFile() {
  163 + return file;
  164 + }
  165 +
  166 + public boolean isIgnoreCertificateVerify() {
  167 + return ignoreCertificateVerify;
  168 + }
  169 +
  170 + public String getUrl() {
  171 + return url;
  172 + }
  173 +
  174 + public float getThumbnail() {
  175 + return thumbnail;
  176 + }
  177 +
  178 + public int getResId() {
  179 + return resId;
  180 + }
  181 +
  182 + public String getRawPath() {
  183 + return rawPath;
  184 + }
  185 +
  186 + public String getAssertspath() {
  187 + return assertspath;
  188 + }
  189 +
  190 + public boolean isGif() {
  191 + return isGif;
  192 + }
  193 +
  194 + public View getTarget() {
  195 + return target;
  196 + }
  197 +
  198 + public int getWidth() {
  199 + if (width <= 0) {
  200 + //先去imageview里取,如果为0,则赋值成matchparent
  201 + if (target != null) {
  202 + width = target.getMeasuredWidth();
  203 + }
  204 + if (width <= 0) {
  205 + width = GlobalConfig.getWinWidth();
  206 + }
  207 + }
  208 + return width;
  209 + }
  210 +
  211 + public int getHeight() {
  212 + if (height <= 0) {
  213 + //先去imageview里取,如果为0,则赋值成matchparent
  214 + if (target != null) {
  215 + height = target.getMeasuredWidth();
  216 + }
  217 + if (height <= 0) {
  218 + height = GlobalConfig.getWinHeight();
  219 + }
  220 + }
  221 + return height;
  222 + }
  223 +
  224 + public int getoWidth() {
  225 + return oWidth;
  226 + }
  227 +
  228 + public int getoHeight() {
  229 + return oHeight;
  230 + }
  231 +
  232 + public boolean isNeedVignette() {
  233 + return isNeedVignette;
  234 + }
  235 +
  236 + public boolean isNeedSketch() {
  237 + return isNeedSketch;
  238 + }
  239 +
  240 + public float getPixelationLevel() {
  241 + return pixelationLevel;
  242 + }
  243 +
  244 + public boolean isNeedPixelation() {
  245 + return isNeedPixelation;
  246 + }
  247 +
  248 + public boolean isNeedInvert() {
  249 + return isNeedInvert;
  250 + }
  251 +
  252 + public float getContrastLevel() {
  253 + return contrastLevel;
  254 + }
  255 +
  256 + public boolean isNeedContrast() {
  257 + return isNeedContrast;
  258 + }
  259 +
  260 + public boolean isNeedSepia() {
  261 + return isNeedSepia;
  262 + }
  263 +
  264 + public boolean isNeedToon() {
  265 + return isNeedToon;
  266 + }
  267 +
  268 + public boolean isNeedSwirl() {
  269 + return isNeedSwirl;
  270 + }
  271 +
  272 + public boolean isNeedGrayscale() {
  273 + return isNeedGrayscale;
  274 + }
  275 +
  276 + public boolean isNeedBrightness() {
  277 + return isNeedBrightness;
  278 + }
  279 +
  280 + public float getBrightnessLeve() {
  281 + return brightnessLeve;
  282 + }
  283 +
  284 + public boolean isNeedBlur() {
  285 + return needBlur;
  286 + }
  287 +
  288 + public boolean isNeedFilteColor() {
  289 + return needFilteColor;
  290 + }
  291 +
  292 + public int getFilteColor() {
  293 + return filteColor;
  294 + }
  295 +
  296 + public int getPriority() {
  297 + return priority;
  298 + }
  299 +
  300 + public int getAnimationType() {
  301 + return animationType;
  302 + }
  303 +
  304 + public int getAnimationId() {
  305 + return animationId;
  306 + }
  307 +
  308 + public ViewPropertyTransition.Animator getAnimation() {
  309 + return animation;
  310 + }
  311 +
  312 + public ViewPropertyAnimationFactory getAnimator() {
  313 + return animator;
  314 + }
  315 +
  316 + public int getBlurRadius() {
  317 + return blurRadius;
  318 + }
  319 +
  320 + public int getPlaceHolderResId() {
  321 + return placeHolderResId;
  322 + }
  323 +
  324 + public int getShapeMode() {
  325 + return shapeMode;
  326 + }
  327 +
  328 + public int getRectRoundRadius() {
  329 + return rectRoundRadius;
  330 + }
  331 +
  332 + public int getScaleMode() {
  333 + return scaleMode;
  334 + }
  335 +
  336 + public BitmapListener getBitmapListener() {
  337 + return bitmapListener;
  338 + }
  339 +
  340 + public boolean isAsBitmap() {
  341 + return asBitmap;
  342 + }
  343 +
  344 + public interface BitmapListener {
  345 + void onSuccess(Bitmap bitmap);
  346 +
  347 + void onFail();
  348 + }
  349 +
  350 + public void setBitmapListener(BitmapListener bitmapListener) {
  351 + this.bitmapListener = ImageUtil.getBitmapListenerProxy(bitmapListener);
  352 + }
  353 +
  354 + private void show() {
  355 + GlobalConfig.getLoader().request(this);
  356 + }
  357 +
  358 + public static class ConfigBuilder {
  359 + private Context context;
  360 +
  361 + private boolean ignoreCertificateVerify = GlobalConfig.ignoreCertificateVerify;
  362 +
  363 + /**
  364 + * 图片源
  365 + * 类型 SCHEME 示例
  366 + * 远程图片 http://, https:// HttpURLConnection 或者参考 使用其他网络加载方案
  367 + * 本地文件 file:// FileInputStream
  368 + * Content provider content:// ContentResolver
  369 + * asset目录下的资源 asset:// AssetManager
  370 + * res目录下的资源 res:// Resources.openRawResource
  371 + * Uri中指定图片数据 data:mime/type;base64, 数据类型必须符合 rfc2397规定 (仅支持 UTF-8)
  372 + *
  373 + * @param config
  374 + * @return
  375 + */
  376 + private String url;
  377 + private float thumbnail;
  378 + private String filePath;
  379 + private File file;
  380 + private int resId;
  381 + private String rawPath;
  382 + private String assertspath;
  383 + private String contentProvider;
  384 + private boolean isGif = false;
  385 +
  386 + private View target;
  387 + private boolean asBitmap;//只获取bitmap
  388 + private BitmapListener bitmapListener;
  389 +
  390 + // TODO: 2017/4/24 宽高的获取
  391 + private int width;
  392 + private int height;
  393 +
  394 + private int oWidth; //选择加载分辨率的宽
  395 + private int oHeight; //选择加载分辨率的高
  396 +
  397 + //滤镜
  398 + private boolean isNeedVignette; //是否需要晕映
  399 + private boolean isNeedSketch; //是否需要素描
  400 + private float pixelationLevel; //是否需要马赛克
  401 + private boolean isNeedPixelation; //是否需要马赛克
  402 + private boolean isNeedInvert; //是否需要胶片
  403 + private float contrastLevel; //是否需要墨画
  404 + private boolean isNeedContrast = false; //是否需要墨画
  405 + private boolean isNeedSepia = false; //是否需要墨画
  406 + private boolean isNeedToon = false; //是否需要油画
  407 + private boolean isNeedSwirl = false; //是否需要漩涡
  408 + private boolean isNeedGrayscale = false; //是否需要亮度
  409 + private boolean isNeedBrightness = false; //是否需要亮度
  410 + private float brightnessLeve; //亮度等级
  411 + private boolean needBlur = false;//是否需要模糊
  412 + private boolean needFilteColor = false;//是否需要滤镜颜色
  413 + private int blurRadius;
  414 +
  415 + //UI:
  416 + private int placeHolderResId;
  417 +
  418 + private int errorResId;
  419 +
  420 + private int shapeMode;//默认矩形,可选直角矩形,圆形/椭圆
  421 + private int rectRoundRadius;//圆角矩形时圆角的半径
  422 +
  423 + private DiskCacheStrategy diskCacheStrategy;
  424 +
  425 + private int scaleMode;//填充模式,默认centercrop,可选fitXY,centerInside...
  426 +
  427 + private int priority; //请求优先级
  428 +
  429 + private int filteColor; //滤镜颜色
  430 +
  431 + public int animationId; //动画资源id
  432 + public int animationType; //动画资源Type
  433 + public ViewPropertyTransition.Animator animation; //动画资源
  434 + public ViewPropertyAnimationFactory animator; //动画资源id
  435 +
  436 + public ConfigBuilder(Context context) {
  437 + this.context = context;
  438 + }
  439 +
  440 + public ConfigBuilder ignoreCertificateVerify(boolean ignoreCertificateVerify) {
  441 + this.ignoreCertificateVerify = ignoreCertificateVerify;
  442 + return this;
  443 + }
  444 +
  445 + /**
  446 + * 缩略图
  447 + *
  448 + * @param thumbnail
  449 + * @return
  450 + */
  451 + public ConfigBuilder thumbnail(float thumbnail) {
  452 + this.thumbnail = thumbnail;
  453 + return this;
  454 + }
  455 +
  456 + /**
  457 + * error图
  458 + *
  459 + * @param errorResId
  460 + * @return
  461 + */
  462 + public ConfigBuilder error(int errorResId) {
  463 + this.errorResId = errorResId;
  464 + return this;
  465 + }
  466 +
  467 + /**
  468 + * 设置网络路径
  469 + *
  470 + * @param url
  471 + * @return
  472 + */
  473 + public ConfigBuilder url(String url) {
  474 + this.url = url;
  475 + if (url.contains("gif")) {
  476 + isGif = true;
  477 + }
  478 + return this;
  479 + }
  480 +
  481 + /**
  482 + * 加载SD卡资源
  483 + *
  484 + * @param filePath
  485 + * @return
  486 + */
  487 + public ConfigBuilder file(String filePath) {
  488 + if (filePath.startsWith("file:")) {
  489 + this.filePath = filePath;
  490 + return this;
  491 + }
  492 +
  493 + if (!new File(filePath).exists()) {
  494 + //throw new RuntimeException("文件不存在");
  495 + Log.e("imageloader", "文件不存在");
  496 + return this;
  497 + }
  498 +
  499 + this.filePath = filePath;
  500 + if (filePath.contains("gif")) {
  501 + isGif = true;
  502 + }
  503 + return this;
  504 + }
  505 +
  506 + /**
  507 + * 加载SD卡资源
  508 + *
  509 + * @param file
  510 + * @return
  511 + */
  512 + public ConfigBuilder file(File file) {
  513 + this.file = file;
  514 +
  515 + return this;
  516 + }
  517 +
  518 + /**
  519 + * 加载drawable资源
  520 + *
  521 + * @param resId
  522 + * @return
  523 + */
  524 + public ConfigBuilder res(int resId) {
  525 + this.resId = resId;
  526 + return this;
  527 + }
  528 +
  529 + /**
  530 + * 加载ContentProvider资源
  531 + *
  532 + * @param contentProvider
  533 + * @return
  534 + */
  535 + public ConfigBuilder content(String contentProvider) {
  536 + if (contentProvider.startsWith("content:")) {
  537 + this.contentProvider = contentProvider;
  538 + return this;
  539 + }
  540 +
  541 + if (contentProvider.contains("gif")) {
  542 + isGif = true;
  543 + }
  544 +
  545 + return this;
  546 + }
  547 +
  548 + /**
  549 + * 加载raw资源
  550 + *
  551 + * @param rawPath
  552 + * @return
  553 + */
  554 + public ConfigBuilder raw(String rawPath) {
  555 +
  556 + this.rawPath = rawPath;
  557 +
  558 + if (rawPath.contains("gif")) {
  559 + isGif = true;
  560 + }
  561 +
  562 + return this;
  563 + }
  564 +
  565 + /**
  566 + * 加载asserts资源
  567 + *
  568 + * @param assertspath
  569 + * @return
  570 + */
  571 + public ConfigBuilder asserts(String assertspath) {
  572 + this.assertspath = assertspath;
  573 +
  574 + if (assertspath.contains("gif")) {
  575 + isGif = true;
  576 + }
  577 +
  578 + return this;
  579 + }
  580 +
  581 + public void into(View targetView) {
  582 + this.target = targetView;
  583 + new SingleConfig(this).show();
  584 + }
  585 +
  586 + public void asBitmap(BitmapListener bitmapListener) {
  587 + this.bitmapListener = ImageUtil.getBitmapListenerProxy(bitmapListener);
  588 + this.asBitmap = true;
  589 + new SingleConfig(this).show();
  590 + }
  591 +
  592 + /**
  593 + * 加载图片的分辨率
  594 + *
  595 + * @param oWidth
  596 + * @param oHeight
  597 + * @return
  598 + */
  599 + public ConfigBuilder override(int oWidth, int oHeight) {
  600 + this.oWidth = ImageUtil.dip2px(oWidth);
  601 + this.oHeight = ImageUtil.dip2px(oHeight);
  602 + return this;
  603 + }
  604 +
  605 + /**
  606 + * 占位图
  607 + *
  608 + * @param placeHolderResId
  609 + * @return
  610 + */
  611 + public ConfigBuilder placeHolder(int placeHolderResId) {
  612 + this.placeHolderResId = placeHolderResId;
  613 + return this;
  614 + }
  615 +
  616 +
  617 + /**
  618 + * 是否需要高斯模糊
  619 + *
  620 + * @return
  621 + */
  622 + public ConfigBuilder blur(int blurRadius) {
  623 + this.needBlur = true;
  624 + this.blurRadius = blurRadius;
  625 + return this;
  626 + }
  627 +
  628 + /**
  629 + * 圆角
  630 +
  631 + * @return
  632 + */
  633 + public ConfigBuilder asCircle() {
  634 + this.shapeMode = ShapeMode.OVAL;
  635 + return this;
  636 + }
  637 +
  638 + /**
  639 + * 形状为圆角矩形时的圆角半径
  640 + *
  641 + * @param rectRoundRadius
  642 + * @return
  643 + */
  644 + public ConfigBuilder rectRoundCorner(int rectRoundRadius) {
  645 + this.rectRoundRadius = ImageUtil.dip2px(rectRoundRadius);
  646 + this.shapeMode = ShapeMode.RECT_ROUND;
  647 + return this;
  648 + }
  649 +
  650 +
  651 + /**
  652 + * 正方形
  653 + *
  654 + * @return
  655 + */
  656 + public ConfigBuilder asSquare() {
  657 + this.shapeMode = ShapeMode.SQUARE;
  658 + return this;
  659 + }
  660 +
  661 +
  662 + /**
  663 + * 磁盘缓存
  664 + */
  665 + public ConfigBuilder diskCacheStrategy(DiskCacheStrategy diskCacheStrategy) {
  666 + this.diskCacheStrategy = diskCacheStrategy;
  667 + return this;
  668 + }
  669 +
  670 + /**
  671 + * 拉伸/裁剪模式
  672 + *
  673 + * @param scaleMode 取值ScaleMode
  674 + * @return
  675 + */
  676 + public ConfigBuilder scale(int scaleMode) {
  677 + this.scaleMode = scaleMode;
  678 + return this;
  679 + }
  680 +
  681 +
  682 + public ConfigBuilder animate(int animationId) {
  683 + this.animationType = AnimationMode.ANIMATIONID;
  684 + this.animationId = animationId;
  685 + return this;
  686 + }
  687 +
  688 + public ConfigBuilder animate(ViewPropertyAnimationFactory animator) {
  689 + this.animationType = AnimationMode.ANIMATOR;
  690 + this.animator = animator;
  691 + return this;
  692 + }
  693 +
  694 + public ConfigBuilder animate(ViewPropertyTransition.Animator animation) {
  695 + this.animationType = AnimationMode.ANIMATION;
  696 + this.animation = animation;
  697 + return this;
  698 + }
  699 +
  700 + public ConfigBuilder priority(int priority) {
  701 + this.priority = priority;
  702 +
  703 + return this;
  704 + }
  705 +
  706 + public ConfigBuilder colorFilter(int filteColor) {
  707 + this.filteColor = filteColor;
  708 + this.needFilteColor = true;
  709 + return this;
  710 + }
  711 +
  712 + public ConfigBuilder brightnessFilter(float level) {
  713 + this.isNeedBrightness = true;
  714 + this.brightnessLeve = level;
  715 + return this;
  716 + }
  717 +
  718 + public ConfigBuilder grayscaleFilter() {
  719 + this.isNeedGrayscale = true;
  720 + return this;
  721 + }
  722 +
  723 + public ConfigBuilder swirlFilter() {
  724 + this.isNeedSwirl = true;
  725 + return this;
  726 + }
  727 +
  728 + public ConfigBuilder toonFilter() {
  729 + this.isNeedToon = true;
  730 + return this;
  731 + }
  732 +
  733 + public ConfigBuilder sepiaFilter() {
  734 + this.isNeedSepia = true;
  735 + return this;
  736 + }
  737 +
  738 + public ConfigBuilder contrastFilter(float constrasrLevel) {
  739 + this.contrastLevel = constrasrLevel;
  740 + this.isNeedContrast = true;
  741 + return this;
  742 + }
  743 +
  744 + public ConfigBuilder invertFilter() {
  745 + this.isNeedInvert = true;
  746 + return this;
  747 + }
  748 +
  749 + public ConfigBuilder pixelationFilter(float pixelationLevel) {
  750 + this.pixelationLevel = pixelationLevel;
  751 + this.isNeedPixelation = true;
  752 + return this;
  753 + }
  754 +
  755 + public ConfigBuilder sketchFilter() {
  756 + this.isNeedSketch = true;
  757 + return this;
  758 + }
  759 +
  760 + public ConfigBuilder vignetteFilter() {
  761 + this.isNeedVignette = true;
  762 + return this;
  763 + }
  764 +
  765 +
  766 + }
  767 +
  768 +
  769 +}
... ...
core/imageload/src/main/java/com/cnlive/core/imageload/loader/GlideLoader.java 0 → 100644
  1 +package com.cnlive.core.imageload.loader;
  2 +
  3 +import android.content.Context;
  4 +import android.graphics.Bitmap;
  5 +import android.graphics.PointF;
  6 +import android.graphics.drawable.Drawable;
  7 +import android.net.Uri;
  8 +import android.text.TextUtils;
  9 +import android.util.Log;
  10 +import android.view.View;
  11 +import android.widget.ImageView;
  12 +
  13 +import com.bumptech.glide.GenericTransitionOptions;
  14 +import com.bumptech.glide.Glide;
  15 +import com.bumptech.glide.GlideBuilder;
  16 +import com.bumptech.glide.MemoryCategory;
  17 +import com.bumptech.glide.Priority;
  18 +import com.bumptech.glide.RequestBuilder;
  19 +import com.bumptech.glide.RequestManager;
  20 +import com.bumptech.glide.load.Transformation;
  21 +import com.bumptech.glide.load.engine.cache.ExternalCacheDiskCacheFactory;
  22 +import com.bumptech.glide.load.engine.cache.InternalCacheDiskCacheFactory;
  23 +import com.bumptech.glide.request.RequestOptions;
  24 +import com.bumptech.glide.request.target.SimpleTarget;
  25 +import com.bumptech.glide.request.transition.Transition;
  26 +import com.bumptech.glide.request.transition.ViewPropertyTransition;
  27 +import com.cnlive.core.imageload.R;
  28 +import com.cnlive.core.imageload.config.AnimationMode;
  29 +import com.cnlive.core.imageload.config.GlobalConfig;
  30 +import com.cnlive.core.imageload.config.PriorityMode;
  31 +import com.cnlive.core.imageload.config.ScaleMode;
  32 +import com.cnlive.core.imageload.config.ShapeMode;
  33 +import com.cnlive.core.imageload.config.SingleConfig;
  34 +import com.cnlive.core.imageload.util.DownLoadImageService;
  35 +import com.cnlive.core.imageload.util.ImageUtil;
  36 +import com.cnlive.libs.base.application.GlideApp;
  37 +
  38 +import androidx.annotation.Nullable;
  39 +import jp.wasabeef.glide.transformations.BlurTransformation;
  40 +import jp.wasabeef.glide.transformations.ColorFilterTransformation;
  41 +import jp.wasabeef.glide.transformations.CropCircleTransformation;
  42 +import jp.wasabeef.glide.transformations.CropSquareTransformation;
  43 +import jp.wasabeef.glide.transformations.GrayscaleTransformation;
  44 +import jp.wasabeef.glide.transformations.RoundedCornersTransformation;
  45 +import jp.wasabeef.glide.transformations.gpu.BrightnessFilterTransformation;
  46 +import jp.wasabeef.glide.transformations.gpu.ContrastFilterTransformation;
  47 +import jp.wasabeef.glide.transformations.gpu.InvertFilterTransformation;
  48 +import jp.wasabeef.glide.transformations.gpu.PixelationFilterTransformation;
  49 +import jp.wasabeef.glide.transformations.gpu.SepiaFilterTransformation;
  50 +import jp.wasabeef.glide.transformations.gpu.SketchFilterTransformation;
  51 +import jp.wasabeef.glide.transformations.gpu.SwirlFilterTransformation;
  52 +import jp.wasabeef.glide.transformations.gpu.ToonFilterTransformation;
  53 +import jp.wasabeef.glide.transformations.gpu.VignetteFilterTransformation;
  54 +
  55 +/**
  56 + * created by hanyayun
  57 + * on 2019/11/19
  58 + */
  59 +public class GlideLoader implements ILoader{
  60 +
  61 + /**
  62 + * @param context 上下文
  63 + * @param cacheSizeInM Glide默认磁盘缓存最大容量250MB
  64 + * @param memoryCategory 调整内存缓存的大小 LOW(0.5f) / NORMAL(1f) / HIGH(1.5f);
  65 + * @param isInternalCD true 磁盘缓存到应用的内部目录 / false 磁盘缓存到外部存
  66 + */
  67 + @Override
  68 + public void init(Context context, int cacheSizeInM, MemoryCategory memoryCategory, boolean isInternalCD) {
  69 + Glide.get(context).setMemoryCategory(memoryCategory); //如果在应用当中想要调整内存缓存的大小,开发者可以通过如下方式:
  70 + GlideBuilder builder = new GlideBuilder();
  71 + if (isInternalCD) {
  72 + builder.setDiskCache(new InternalCacheDiskCacheFactory(context, cacheSizeInM * 1024 * 1024));
  73 + } else {
  74 + builder.setDiskCache(new ExternalCacheDiskCacheFactory(context, cacheSizeInM * 1024 * 1024));
  75 + }
  76 + }
  77 +
  78 + @Override
  79 + public void request(SingleConfig config) {
  80 + RequestManager requestManager = Glide.with(config.getContext());
  81 + RequestBuilder<Drawable> request = getDrawableTypeRequest(config, requestManager);
  82 +
  83 + if (config.isAsBitmap()) {
  84 + SimpleTarget target = new SimpleTarget<Bitmap>(config.getWidth(), config.getHeight()) {
  85 + @Override
  86 + public void onResourceReady(Bitmap bitmap, Transition glideAnimation) {
  87 + config.getBitmapListener().onSuccess(bitmap);
  88 + }
  89 + };
  90 +
  91 + setShapeModeAndBlur(config, request);
  92 +
  93 + if (config.getDiskCacheStrategy() != null) {
  94 + request.diskCacheStrategy(config.getDiskCacheStrategy());
  95 + }
  96 +
  97 + request.into(target);
  98 +
  99 + } else {
  100 +
  101 + if (request == null) {
  102 + return;
  103 + }
  104 +
  105 + if (ImageUtil.shouldSetPlaceHolder(config)) {
  106 + request.placeholder(config.getPlaceHolderResId());
  107 + }
  108 +
  109 + int scaleMode = config.getScaleMode();
  110 +
  111 + switch (scaleMode) {
  112 + case ScaleMode.CENTER_CROP:
  113 + request.centerCrop();
  114 + break;
  115 + case ScaleMode.FIT_CENTER:
  116 + request.fitCenter();
  117 + break;
  118 + default:
  119 + request.fitCenter();
  120 + break;
  121 + }
  122 +
  123 + setShapeModeAndBlur(config, request);
  124 +
  125 + //设置缩略图
  126 + if (config.getThumbnail() != 0) {
  127 + request.thumbnail(config.getThumbnail());
  128 + }
  129 +
  130 + //设置图片加载的分辨 sp
  131 + if (config.getoWidth() != 0 && config.getoHeight() != 0) {
  132 + request.override(config.getoWidth(), config.getoHeight());
  133 + }
  134 +
  135 + //是否跳过磁盘存储
  136 + if (config.getDiskCacheStrategy() != null) {
  137 + request.diskCacheStrategy(config.getDiskCacheStrategy());
  138 + }
  139 +
  140 + //设置图片加载动画
  141 + setAnimator(config, request);
  142 +
  143 + //设置图片加载优先级
  144 + setPriority(config, request);
  145 +
  146 + if (config.getErrorResId() > 0) {
  147 + request.error(config.getErrorResId());
  148 + }
  149 +
  150 +// if(config.isGif()){
  151 +// request.asGif();
  152 +// }
  153 +
  154 + if (config.getTarget() instanceof ImageView) {
  155 + request.into((ImageView) config.getTarget());
  156 +
  157 + }
  158 + }
  159 + }
  160 +
  161 + /**
  162 + * 设置加载优先级
  163 + *
  164 + * @param config
  165 + * @param request
  166 + */
  167 + private void setPriority(SingleConfig config, RequestBuilder<Drawable> request) {
  168 + switch (config.getPriority()) {
  169 + case PriorityMode.PRIORITY_LOW:
  170 + request.priority(Priority.LOW);
  171 + break;
  172 + case PriorityMode.PRIORITY_NORMAL:
  173 + request.priority(Priority.NORMAL);
  174 + break;
  175 + case PriorityMode.PRIORITY_HIGH:
  176 + request.priority(Priority.HIGH);
  177 + break;
  178 + case PriorityMode.PRIORITY_IMMEDIATE:
  179 + request.priority(Priority.IMMEDIATE);
  180 + break;
  181 + default:
  182 + request.priority(Priority.IMMEDIATE);
  183 + break;
  184 + }
  185 + }
  186 +
  187 + /**
  188 + * 设置加载进入动画
  189 + *
  190 + * @param config
  191 + * @param request
  192 + */
  193 + private void setAnimator(SingleConfig config, RequestBuilder<Drawable> request) {
  194 + if (config.getAnimationType() == AnimationMode.ANIMATIONID) {
  195 + request.transition(GenericTransitionOptions.with(config.getAnimationId()));
  196 +// request.anaimate(config.getAnimationId());
  197 + } else if (config.getAnimationType() == AnimationMode.ANIMATOR) {
  198 + request.transition(GenericTransitionOptions.with(config.getAnimator()));
  199 +// request.animate(config.getAnimator());
  200 + } else if (config.getAnimationType() == AnimationMode.ANIMATION) {
  201 + request.transition(GenericTransitionOptions.with(config.getAnimation()));
  202 +// request.animate(config.getAnimation());
  203 + }
  204 + }
  205 +
  206 + @Nullable
  207 + private RequestBuilder<Drawable> getDrawableTypeRequest(SingleConfig config, RequestManager requestManager) {
  208 + RequestBuilder<Drawable> request = null;
  209 + if (!TextUtils.isEmpty(config.getUrl())) {
  210 + request = requestManager.load(ImageUtil.appendUrl(config.getUrl()));
  211 + Log.e("TAG","getUrl : "+config.getUrl());
  212 + } else if (!TextUtils.isEmpty(config.getFilePath())) {
  213 + request = requestManager.load(ImageUtil.appendUrl(config.getFilePath()));
  214 + Log.e("TAG","getFilePath : "+config.getFilePath());
  215 + } else if (!TextUtils.isEmpty(config.getContentProvider())) {
  216 + request = requestManager.load(Uri.parse(config.getContentProvider()));
  217 + Log.e("TAG","getContentProvider : "+config.getContentProvider());
  218 + } else if (config.getResId() > 0) {
  219 + request = requestManager.load(config.getResId());
  220 + Log.e("TAG","getResId : "+config.getResId());
  221 + } else if(config.getFile() != null){
  222 + request = requestManager.load(config.getFile());
  223 + Log.e("TAG","getFile : "+config.getFile());
  224 + } else if(!TextUtils.isEmpty(config.getAssertspath())){
  225 + request = requestManager.load(config.getAssertspath());
  226 + Log.e("TAG","getAssertspath : "+config.getAssertspath());
  227 + } else if(!TextUtils.isEmpty(config.getRawPath())){
  228 + request = requestManager.load(config.getRawPath());
  229 + Log.e("TAG","getRawPath : "+config.getRawPath());
  230 + }
  231 + return request;
  232 + }
  233 +
  234 + /**
  235 + * 设置图片滤镜和形状
  236 + *
  237 + * @param config
  238 + * @param request
  239 + */
  240 + private void setShapeModeAndBlur(SingleConfig config, RequestBuilder<Drawable> request) {
  241 +
  242 + int count = 0;
  243 +
  244 + Transformation[] transformation = new Transformation[statisticsCount(config)];
  245 +
  246 + if (config.isNeedBlur()) {
  247 + transformation[count] = new BlurTransformation(config.getBlurRadius());
  248 + count++;
  249 + }
  250 +
  251 + if (config.isNeedBrightness()) {
  252 + transformation[count] = new BrightnessFilterTransformation(config.getBrightnessLeve()); //亮度
  253 + count++;
  254 + }
  255 +
  256 + if (config.isNeedGrayscale()) {
  257 + transformation[count] = new GrayscaleTransformation(); //黑白效果
  258 + count++;
  259 + }
  260 +
  261 + if (config.isNeedFilteColor()) {
  262 + transformation[count] = new ColorFilterTransformation(config.getFilteColor());
  263 + count++;
  264 + }
  265 +
  266 + if (config.isNeedSwirl()) {
  267 + transformation[count] = new SwirlFilterTransformation( 0.5f, 1.0f, new PointF(0.5f, 0.5f)); //漩涡
  268 + count++;
  269 + }
  270 +
  271 + if (config.isNeedToon()) {
  272 + transformation[count] = new ToonFilterTransformation(); //油画
  273 + count++;
  274 + }
  275 +
  276 + if (config.isNeedSepia()) {
  277 + transformation[count] = new SepiaFilterTransformation(); //墨画
  278 + count++;
  279 + }
  280 +
  281 + if (config.isNeedContrast()) {
  282 + transformation[count] = new ContrastFilterTransformation( config.getContrastLevel()); //锐化
  283 + count++;
  284 + }
  285 +
  286 + if (config.isNeedInvert()) {
  287 + transformation[count] = new InvertFilterTransformation(); //胶片
  288 + count++;
  289 + }
  290 +
  291 + if (config.isNeedPixelation()) {
  292 + transformation[count] =new PixelationFilterTransformation(config.getPixelationLevel()); //马赛克
  293 + count++;
  294 + }
  295 +
  296 + if (config.isNeedSketch()) {
  297 + transformation[count] =new SketchFilterTransformation(); //素描
  298 + count++;
  299 + }
  300 +
  301 + if (config.isNeedVignette()) {
  302 + transformation[count] =new VignetteFilterTransformation(new PointF(0.5f, 0.5f),
  303 + new float[] { 0.0f, 0.0f, 0.0f }, 0f, 0.75f);//晕映
  304 + count++;
  305 + }
  306 +
  307 + switch (config.getShapeMode()) {
  308 + case ShapeMode.RECT:
  309 +
  310 + break;
  311 + case ShapeMode.RECT_ROUND:
  312 + transformation[count] = new RoundedCornersTransformation
  313 + (config.getRectRoundRadius(), 0, RoundedCornersTransformation.CornerType.ALL);
  314 + count++;
  315 + break;
  316 + case ShapeMode.OVAL:
  317 + transformation[count] = new CropCircleTransformation();
  318 + count++;
  319 + break;
  320 +
  321 + case ShapeMode.SQUARE:
  322 + transformation[count] = new CropSquareTransformation();
  323 + count++;
  324 + break;
  325 + }
  326 +
  327 + if (transformation.length != 0) {
  328 + request.transform(transformation);
  329 +
  330 + }
  331 +
  332 + }
  333 +
  334 +
  335 + private int statisticsCount(SingleConfig config) {
  336 + int count = 0;
  337 +
  338 + if (config.getShapeMode() == ShapeMode.OVAL || config.getShapeMode() == ShapeMode.RECT_ROUND || config.getShapeMode() == ShapeMode.SQUARE) {
  339 + count++;
  340 + }
  341 +
  342 + if (config.isNeedBlur()) {
  343 + count++;
  344 + }
  345 +
  346 + if (config.isNeedFilteColor()) {
  347 + count++;
  348 + }
  349 +
  350 + if (config.isNeedBrightness()) {
  351 + count++;
  352 + }
  353 +
  354 + if (config.isNeedGrayscale()) {
  355 + count++;
  356 + }
  357 +
  358 + if (config.isNeedSwirl()) {
  359 + count++;
  360 + }
  361 +
  362 + if (config.isNeedToon()) {
  363 + count++;
  364 + }
  365 +
  366 + if (config.isNeedSepia()) {
  367 + count++;
  368 + }
  369 +
  370 + if (config.isNeedContrast()) {
  371 + count++;
  372 + }
  373 +
  374 + if (config.isNeedInvert()) {
  375 + count++;
  376 + }
  377 +
  378 + if (config.isNeedPixelation()) {
  379 + count++;
  380 + }
  381 +
  382 + if (config.isNeedSketch()) {
  383 + count++;
  384 + }
  385 +
  386 + if (config.isNeedVignette()) {
  387 + count++;
  388 + }
  389 +
  390 + return count;
  391 + }
  392 +
  393 + @Override
  394 + public void pause() {
  395 + Glide.with(GlobalConfig.context).pauseRequestsRecursive();
  396 + }
  397 +
  398 + @Override
  399 + public void resume() {
  400 + Glide.with(GlobalConfig.context).resumeRequestsRecursive();
  401 + }
  402 +
  403 + @Override
  404 + public void clearDiskCache() {
  405 + Glide.get(GlobalConfig.context).clearDiskCache();
  406 + }
  407 +
  408 + @Override
  409 + public void clearMomoryCache(Context context,View view) {
  410 + Glide.with(context).clear(view);
  411 + }
  412 +
  413 + @Override
  414 + public void clearMomory() {
  415 + Glide.get(GlobalConfig.context).clearMemory();
  416 + }
  417 +
  418 + @Override
  419 + public boolean isCached(String url) {
  420 + return false;
  421 + }
  422 +
  423 + @Override
  424 + public void trimMemory(int level) {
  425 + Glide.with(GlobalConfig.context).onTrimMemory(level);
  426 + }
  427 +
  428 + @Override
  429 + public void clearAllMemoryCaches() {
  430 + Glide.with(GlobalConfig.context).onLowMemory();
  431 + }
  432 +
  433 + @Override
  434 + public void saveImageIntoGallery(DownLoadImageService downLoadImageService) {
  435 + new Thread(downLoadImageService).start();
  436 + }
  437 +}
... ...
core/imageload/src/main/java/com/cnlive/core/imageload/loader/ILoader.java 0 → 100644
  1 +package com.cnlive.core.imageload.loader;
  2 +
  3 +import android.content.Context;
  4 +import android.view.View;
  5 +
  6 +import com.bumptech.glide.MemoryCategory;
  7 +import com.cnlive.core.imageload.config.SingleConfig;
  8 +import com.cnlive.core.imageload.util.DownLoadImageService;
  9 +
  10 +/**
  11 + * created by hanyayun
  12 + * on 2019/11/19
  13 + */
  14 +public interface ILoader {
  15 +
  16 + void init(Context context, int cacheSizeInM, MemoryCategory memoryCategory, boolean isInternalCD);
  17 +
  18 + void request(SingleConfig config);
  19 +
  20 + void pause();
  21 +
  22 + void resume();
  23 +
  24 + void clearDiskCache();
  25 +
  26 + void clearMomoryCache(Context context,View view);
  27 +
  28 + void clearMomory();
  29 +
  30 + boolean isCached(String url);
  31 +
  32 + void trimMemory(int level);
  33 +
  34 + void clearAllMemoryCaches();
  35 +
  36 + void saveImageIntoGallery(DownLoadImageService downLoadImageService);
  37 +}
... ...
core/imageload/src/main/java/com/cnlive/core/imageload/loader/ImageLoader.java 0 → 100644
  1 +package com.cnlive.core.imageload.loader;
  2 +
  3 +import android.content.Context;
  4 +import android.view.View;
  5 +
  6 +import com.bumptech.glide.MemoryCategory;
  7 +import com.cnlive.core.imageload.config.GlobalConfig;
  8 +import com.cnlive.core.imageload.config.SingleConfig;
  9 +import com.cnlive.core.imageload.util.DownLoadImageService;
  10 +
  11 +
  12 +/**
  13 + * created by hanyayun
  14 + * on 2019/11/22
  15 + */
  16 +public class ImageLoader {
  17 +
  18 + public static Context context;
  19 + /**
  20 + * 默认最大缓存
  21 + */
  22 + public static int CACHE_IMAGE_SIZE = 250;
  23 +
  24 + public static void init(final Context context) {
  25 + init(context, CACHE_IMAGE_SIZE);
  26 + }
  27 +
  28 + public static void init(final Context context, int cacheSizeInM) {
  29 + init(context, cacheSizeInM, MemoryCategory.NORMAL);
  30 + }
  31 +
  32 + public static void init(final Context context, int cacheSizeInM, MemoryCategory memoryCategory) {
  33 + init(context, cacheSizeInM, memoryCategory, true);
  34 + }
  35 +
  36 + /**
  37 + * @param context 上下文
  38 + * @param cacheSizeInM Glide默认磁盘缓存最大容量250MB
  39 + * @param memoryCategory 调整内存缓存的大小 LOW(0.5f) / NORMAL(1f) / HIGH(1.5f);
  40 + * @param isInternalCD true 磁盘缓存到应用的内部目录 / false 磁盘缓存到外部存
  41 + */
  42 + public static void init(final Context context, int cacheSizeInM, MemoryCategory memoryCategory, boolean isInternalCD) {
  43 + ImageLoader.context = context;
  44 + GlobalConfig.init(context, cacheSizeInM, memoryCategory, isInternalCD);
  45 + }
  46 +
  47 + /**
  48 + * 获取当前的Loader
  49 + * @return
  50 + */
  51 + public static ILoader getActualLoader() {
  52 + return GlobalConfig.getLoader();
  53 + }
  54 +
  55 + /**
  56 + * 加载普通图片
  57 + *
  58 + * @param context
  59 + * @return
  60 + */
  61 + public static SingleConfig.ConfigBuilder with(Context context) {
  62 + return new SingleConfig.ConfigBuilder(context);
  63 + }
  64 +
  65 + public static void trimMemory(int level) {
  66 + getActualLoader().trimMemory(level);
  67 + }
  68 +
  69 + public static void clearAllMemoryCaches() {
  70 + getActualLoader().clearAllMemoryCaches();
  71 + }
  72 +
  73 + public static void pauseRequests() {
  74 + getActualLoader().pause();
  75 +
  76 + }
  77 +
  78 + public static void resumeRequests() {
  79 + getActualLoader().resume();
  80 + }
  81 +
  82 + /**
  83 + *Cancel any pending loads Glide may have for the view and free any resources that may have been loaded for the view.
  84 + * @param view
  85 + */
  86 + public static void clearMomoryCache(Context context,View view) {
  87 + getActualLoader().clearMomoryCache(context,view);
  88 + }
  89 +
  90 +
  91 + /**
  92 + * Clears disk cache.
  93 + *
  94 + * <p>
  95 + * This method should always be called on a background thread, since it is a blocking call.
  96 + * </p>
  97 + */
  98 + public static void clearDiskCache() {
  99 + getActualLoader().clearDiskCache();
  100 + }
  101 +
  102 + /**
  103 + * Clears as much memory as possible.
  104 + */
  105 + public static void clearMomory() {
  106 + getActualLoader().clearMomory();
  107 + }
  108 +
  109 + /**
  110 + * 图片保存到相册
  111 + *
  112 + * @param downLoadImageService
  113 + */
  114 + public static void saveImageIntoGallery(DownLoadImageService downLoadImageService) {
  115 + getActualLoader().saveImageIntoGallery(downLoadImageService);
  116 + }
  117 +
  118 +}
... ...
core/imageload/src/main/java/com/cnlive/core/imageload/util/DownLoadImageService.java 0 → 100644
  1 +package com.cnlive.core.imageload.util;
  2 +
  3 +import android.content.Context;
  4 +import android.content.Intent;
  5 +import android.graphics.Bitmap;
  6 +import android.net.Uri;
  7 +import android.os.Build;
  8 +import android.os.Environment;
  9 +import android.provider.MediaStore;
  10 +
  11 +import com.bumptech.glide.Glide;
  12 +import com.bumptech.glide.request.target.Target;
  13 +import com.cnlive.core.imageload.callback.ImageDownLoadCallBack;
  14 +
  15 +import java.io.File;
  16 +import java.io.FileNotFoundException;
  17 +import java.io.FileOutputStream;
  18 +import java.io.IOException;
  19 +
  20 +/**
  21 + * 图片下载
  22 + * created by hanyayun
  23 + * on 2019/11/19
  24 + */
  25 +public class DownLoadImageService implements Runnable{
  26 +
  27 + private String url;
  28 + private Context context;
  29 + private ImageDownLoadCallBack callBack;
  30 + private File currentFile;
  31 + private String fileName;
  32 +
  33 + private boolean isSetMediaStore;
  34 +
  35 + public DownLoadImageService(Context context, String url,boolean isSetMediaStore , String fileName, ImageDownLoadCallBack callBack) {
  36 + this.url = url;
  37 + this.callBack = callBack;
  38 + this.context = context;
  39 + this.isSetMediaStore = isSetMediaStore;
  40 + this.fileName = fileName;
  41 + }
  42 +
  43 + @Override
  44 + public void run() {
  45 +
  46 + Bitmap bitmap = null;
  47 + try {
  48 + bitmap = Glide.with(context)
  49 + .asBitmap()
  50 + .load(url)
  51 + .into(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL)
  52 + .get();
  53 + if (bitmap != null){
  54 + // 在这里执行图片保存方法
  55 + saveImageToGallery(context,bitmap);
  56 + }
  57 + } catch (Exception e) {
  58 + e.printStackTrace();
  59 + } finally {
  60 + if (bitmap != null && currentFile.exists()) {
  61 + callBack.onDownLoadSuccess(bitmap);
  62 + } else {
  63 + callBack.onDownLoadFailed();
  64 + }
  65 + }
  66 + }
  67 +
  68 + public void saveImageToGallery(Context context, Bitmap bmp) {
  69 + // 首先保存图片
  70 +
  71 + File file = Build.VERSION.SDK_INT > 28?context.getExternalFilesDir(Environment.DIRECTORY_PICTURES).getAbsoluteFile():Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getAbsoluteFile();//注意小米手机必须这样获得public绝对路径
  72 +
  73 + File appDir = new File(file ,fileName);
  74 + if (!appDir.exists()) {
  75 + appDir.mkdirs();
  76 + }
  77 + fileName = System.currentTimeMillis() + ".jpg";
  78 + currentFile = new File(appDir, fileName);
  79 +
  80 + FileOutputStream fos = null;
  81 + try {
  82 + fos = new FileOutputStream(currentFile);
  83 + bmp.compress(Bitmap.CompressFormat.JPEG, 100, fos);
  84 + fos.flush();
  85 + } catch (FileNotFoundException e) {
  86 + e.printStackTrace();
  87 + } catch (IOException e) {
  88 + e.printStackTrace();
  89 + } finally {
  90 + try {
  91 + if (fos != null) {
  92 + fos.close();
  93 + }
  94 + } catch (IOException e) {
  95 + e.printStackTrace();
  96 + }
  97 + }
  98 +
  99 + if(isSetMediaStore){
  100 + setMediaDtore(fileName);
  101 + }
  102 +
  103 + // 最后通知图库更新
  104 + context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,
  105 + Uri.fromFile(new File(currentFile.getPath()))));
  106 + }
  107 +
  108 + /**
  109 + * 加入到系统图库
  110 + * @param fileName
  111 + */
  112 + public void setMediaDtore(String fileName){
  113 + try {
  114 + MediaStore.Images.Media.insertImage(context.getContentResolver(),
  115 + currentFile.getAbsolutePath(), fileName, null);
  116 + } catch (FileNotFoundException e) {
  117 + e.printStackTrace();
  118 + }
  119 + }
  120 +}
... ...
core/imageload/src/main/java/com/cnlive/core/imageload/util/ImageUtil.java 0 → 100644
  1 +package com.cnlive.core.imageload.util;
  2 +
  3 +import android.content.Context;
  4 +import android.graphics.Bitmap;
  5 +import android.graphics.Matrix;
  6 +import android.net.Uri;
  7 +import android.text.TextUtils;
  8 +import android.util.Log;
  9 +
  10 +import com.cnlive.core.imageload.config.GlobalConfig;
  11 +import com.cnlive.core.imageload.config.SingleConfig;
  12 +
  13 +import java.io.File;
  14 +import java.io.FileInputStream;
  15 +import java.io.IOException;
  16 +import java.lang.reflect.InvocationHandler;
  17 +import java.lang.reflect.InvocationTargetException;
  18 +import java.lang.reflect.Method;
  19 +import java.lang.reflect.Proxy;
  20 +import java.security.KeyManagementException;
  21 +import java.security.NoSuchAlgorithmException;
  22 +import java.security.SecureRandom;
  23 +import java.security.cert.X509Certificate;
  24 +import java.util.concurrent.TimeUnit;
  25 +
  26 +import javax.net.ssl.HostnameVerifier;
  27 +import javax.net.ssl.SSLContext;
  28 +import javax.net.ssl.SSLSession;
  29 +import javax.net.ssl.TrustManager;
  30 +import javax.net.ssl.X509TrustManager;
  31 +
  32 +import okhttp3.OkHttpClient;
  33 +
  34 +import static com.cnlive.core.imageload.config.Contants.ANDROID_RESOURCE;
  35 +import static com.cnlive.core.imageload.config.Contants.FOREWARD_SLASH;
  36 +
  37 +/**
  38 + * created by hanyayun
  39 + * on 2019/11/19
  40 + */
  41 +public class ImageUtil {
  42 +
  43 + public static SingleConfig.BitmapListener getBitmapListenerProxy(final SingleConfig.BitmapListener listener) {
  44 + return (SingleConfig.BitmapListener) Proxy.newProxyInstance(SingleConfig.class.getClassLoader(),
  45 + listener.getClass().getInterfaces(), new InvocationHandler() {
  46 + @Override
  47 + public Object invoke(Object proxy, final Method method, final Object[] args) throws Throwable {
  48 +
  49 + runOnUIThread(new Runnable() {
  50 + @Override
  51 + public void run() {
  52 + try {
  53 + Object object = method.invoke(listener, args);
  54 + } catch (IllegalAccessException e) {
  55 + e.printStackTrace();
  56 + } catch (InvocationTargetException e) {
  57 + e.printStackTrace();
  58 + }
  59 + }
  60 + });
  61 + return null;
  62 + }
  63 + });
  64 + }
  65 +
  66 + public static void runOnUIThread(Runnable runnable) {
  67 + GlobalConfig.getMainHandler().post(runnable);
  68 + }
  69 +
  70 + public static boolean shouldSetPlaceHolder(SingleConfig config) {
  71 + if (config.getPlaceHolderResId() <= 0) {
  72 + return false;
  73 + }
  74 +
  75 + if (config.getResId() > 0 || !TextUtils.isEmpty(config.getFilePath()) || GlobalConfig.getLoader().isCached(config.getUrl())) {
  76 + return false;
  77 + } else {//只有在图片源为网络图片,并且图片没有缓存到本地时,才给显示placeholder
  78 + return true;
  79 + }
  80 + }
  81 +
  82 + public static int dip2px(float dipValue) {
  83 + final float scale = GlobalConfig.context.getResources().getDisplayMetrics().density;
  84 + return (int) (dipValue * scale + 0.5f);
  85 + }
  86 +
  87 +
  88 + /**
  89 + * 等比压缩(宽高等比缩放)
  90 + *
  91 + * @param bitmap
  92 + * @param needRecycle
  93 + * @param targetWidth
  94 + * @param targeHeight
  95 + * @return
  96 + */
  97 + public static Bitmap compressBitmap(Bitmap bitmap, boolean needRecycle, int targetWidth, int targeHeight) {
  98 + float sourceWidth = bitmap.getWidth();
  99 + float sourceHeight = bitmap.getHeight();
  100 +
  101 + float scaleWidth = targetWidth / sourceWidth;
  102 + float scaleHeight = targeHeight / sourceHeight;
  103 +
  104 + Matrix matrix = new Matrix();
  105 + matrix.postScale(scaleWidth, scaleHeight); //长和宽放大缩小的比例
  106 + Bitmap bm = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
  107 + if (needRecycle) {
  108 + bitmap.recycle();
  109 + }
  110 + bitmap = bm;
  111 + return bitmap;
  112 + }
  113 +
  114 + public static String getRealType(File file) {
  115 + FileInputStream is = null;
  116 + try {
  117 + is = new FileInputStream(file);
  118 + byte[] b = new byte[4];
  119 + try {
  120 + is.read(b, 0, b.length);
  121 + } catch (IOException e) {
  122 + e.printStackTrace();
  123 + return "";
  124 + }
  125 + String type = bytesToHexString(b).toUpperCase();
  126 + if (type.contains("FFD8FF")) {
  127 + return "jpg";
  128 + } else if (type.contains("89504E47")) {
  129 + return "png";
  130 + } else if (type.contains("47494638")) {
  131 + return "gif";
  132 + } else if (type.contains("49492A00")) {
  133 + return "tif";
  134 + } else if (type.contains("424D")) {
  135 + return "bmp";
  136 + }
  137 + return type;
  138 + } catch (Exception e) {
  139 + e.printStackTrace();
  140 + return "";
  141 + } finally {
  142 + try {
  143 + is.close();
  144 + } catch (IOException e) {
  145 + e.printStackTrace();
  146 + }
  147 + }
  148 +
  149 + }
  150 +
  151 + public static String bytesToHexString(byte[] src) {
  152 + StringBuilder stringBuilder = new StringBuilder();
  153 + if (src == null || src.length <= 0) {
  154 + return null;
  155 + }
  156 + for (int i = 0; i < src.length; i++) {
  157 + int v = src[i] & 0xFF;
  158 + String hv = Integer.toHexString(v);
  159 + if (hv.length() < 2) {
  160 + stringBuilder.append(0);
  161 + }
  162 + stringBuilder.append(hv);
  163 + }
  164 + return stringBuilder.toString();
  165 + }
  166 +
  167 +
  168 + /**
  169 + * 类型 SCHEME 示例
  170 + * 远程图片 http://, https:// HttpURLConnection 或者参考 使用其他网络加载方案
  171 + * 本地文件 file:// FileInputStream
  172 + * Content provider content:// ContentResolver
  173 + * asset目录下的资源 asset:// AssetManager
  174 + * res目录下的资源 res:// Resources.openRawResource
  175 + * Uri中指定图片数据 data:mime/type;base64, 数据类型必须符合 rfc2397规定 (仅支持 UTF-8)
  176 + *
  177 + * @param config
  178 + * @return
  179 + */
  180 + public static Uri buildUriByType(SingleConfig config) {
  181 +
  182 + Log.e("builduri:", "url: " + config.getUrl() + " ---filepath:" + config.getFilePath() + "--content:" + config.getContentProvider());
  183 +
  184 + if (!TextUtils.isEmpty(config.getUrl())) {
  185 + String url = ImageUtil.appendUrl(config.getUrl());
  186 + return Uri.parse(url);
  187 + }
  188 +
  189 + if (config.getResId() > 0) {
  190 + return Uri.parse("res://imageloader/" + config.getResId());
  191 + }
  192 +
  193 + if (!TextUtils.isEmpty(config.getFilePath())) {
  194 +
  195 + File file = new File(config.getFilePath());
  196 + if (file.exists()) {
  197 + return Uri.fromFile(file);
  198 + }
  199 + }
  200 +
  201 + if (!TextUtils.isEmpty(config.getContentProvider())) {
  202 + String content = config.getContentProvider();
  203 + if (!content.startsWith("content")) {
  204 + content = "content://" + content;
  205 + }
  206 + return Uri.parse(content);
  207 + }
  208 +
  209 +
  210 + return null;
  211 + }
  212 +
  213 +
  214 + public static String appendUrl(String url) {
  215 + String newUrl = url;
  216 + if (TextUtils.isEmpty(newUrl)) {
  217 + return newUrl;
  218 + }
  219 + boolean hasHost = url.contains("http:") || url.contains("https:");
  220 + if (!hasHost) {
  221 + if (!TextUtils.isEmpty(GlobalConfig.baseUrl)) {
  222 + newUrl = GlobalConfig.baseUrl + url;
  223 + }
  224 + }
  225 +
  226 + return newUrl;
  227 + }
  228 +
  229 + public static OkHttpClient getClient(boolean ignoreCertificateVerify) {
  230 + if (ignoreCertificateVerify) {
  231 + return getAllPassClient();
  232 + } else {
  233 + return getNormalClient();
  234 + }
  235 + }
  236 +
  237 + /**
  238 + * 不校验证书
  239 + *
  240 + * @return
  241 + */
  242 + private static OkHttpClient getAllPassClient() {
  243 +
  244 + X509TrustManager xtm = new X509TrustManager() {
  245 + @Override
  246 + public void checkClientTrusted(X509Certificate[] chain, String authType) {
  247 + }
  248 +
  249 + @Override
  250 + public void checkServerTrusted(X509Certificate[] chain, String authType) {
  251 + }
  252 +
  253 + @Override
  254 + public X509Certificate[] getAcceptedIssuers() {
  255 + X509Certificate[] x509Certificates = new X509Certificate[]{};
  256 + return x509Certificates;
  257 + // return null;
  258 + }
  259 + };
  260 +
  261 + SSLContext sslContext = null;
  262 + try {
  263 + sslContext = SSLContext.getInstance("SSL");
  264 +
  265 + sslContext.init(null, new TrustManager[]{xtm}, new SecureRandom());
  266 +
  267 + } catch (NoSuchAlgorithmException e) {
  268 + e.printStackTrace();
  269 + } catch (KeyManagementException e) {
  270 + e.printStackTrace();
  271 + }
  272 +
  273 +
  274 + HostnameVerifier DO_NOT_VERIFY = new HostnameVerifier() {
  275 + @Override
  276 + public boolean verify(String hostname, SSLSession session) {
  277 + return true;
  278 + }
  279 + };
  280 +
  281 + OkHttpClient client = new OkHttpClient.Builder()
  282 + .sslSocketFactory(sslContext.getSocketFactory())
  283 + .hostnameVerifier(DO_NOT_VERIFY)
  284 + .readTimeout(0, TimeUnit.SECONDS)
  285 + .connectTimeout(30, TimeUnit.SECONDS).writeTimeout(0, TimeUnit.SECONDS) //设置超时
  286 + .build();
  287 +
  288 + return client;
  289 + }
  290 +
  291 + private static OkHttpClient getNormalClient() {
  292 + OkHttpClient client = new OkHttpClient.Builder()
  293 + //.sslSocketFactory(sslContext.getSocketFactory())
  294 + //.hostnameVerifier(DO_NOT_VERIFY)
  295 + .readTimeout(0, TimeUnit.SECONDS)
  296 + .connectTimeout(30, TimeUnit.SECONDS).writeTimeout(0, TimeUnit.SECONDS) //设置超时
  297 + .build();
  298 + return client;
  299 + }
  300 +
  301 + private static Uri resourceIdToUri(Context context, int resourceId) {
  302 + return Uri.parse(ANDROID_RESOURCE + context.getPackageName() + FOREWARD_SLASH + resourceId);
  303 + }
  304 +
  305 +}
... ...
core/imageload/src/main/java/com/cnlive/core/imageload/util/MultiView.java 0 → 100644
  1 +package com.cnlive.core.imageload.util;
  2 +
  3 +import android.annotation.SuppressLint;
  4 +import android.content.Context;
  5 +import android.content.res.TypedArray;
  6 +import android.graphics.Bitmap;
  7 +import android.graphics.BitmapShader;
  8 +import android.graphics.Canvas;
  9 +import android.graphics.Matrix;
  10 +import android.graphics.Paint;
  11 +import android.graphics.Path;
  12 +import android.graphics.PointF;
  13 +import android.graphics.RectF;
  14 +import android.graphics.Shader;
  15 +import android.graphics.drawable.BitmapDrawable;
  16 +import android.graphics.drawable.Drawable;
  17 +import android.os.Bundle;
  18 +import android.os.Parcelable;
  19 +import android.util.AttributeSet;
  20 +import android.util.TypedValue;
  21 +import android.widget.ImageView;
  22 +
  23 +import com.cnlive.core.imageload.R;
  24 +
  25 +import java.util.ArrayList;
  26 +import java.util.List;
  27 +
  28 +import androidx.annotation.Nullable;
  29 +
  30 +/**
  31 + * created by hanyayun
  32 + * on 2019/11/22
  33 + */
  34 +public class MultiView extends ImageView {
  35 +
  36 + /**
  37 + * 图片的类型,圆形or圆角or多边形
  38 + */
  39 + private Context mContext;
  40 +
  41 + /**
  42 + * 传输类型
  43 + */
  44 + private int type;
  45 +
  46 + /**
  47 + * 圆形
  48 + */
  49 + public static final int TYPE_CIRCLE = 0;
  50 +
  51 + /**
  52 + * 圆角
  53 + */
  54 + public static final int TYPE_ROUND = 1;
  55 +
  56 + /**
  57 + * 多边形
  58 + */
  59 + public static final int TYPE_MULTI = 3;
  60 +
  61 + /**
  62 + *默认多边形角的个数
  63 + */
  64 + public static final int ANGLECOUNT = 5;
  65 +
  66 + /**
  67 + * 默认开始绘制的角度
  68 + */
  69 + public static final int CURRENTANGLE = 180;
  70 +
  71 + /**
  72 + * 多边形的半径
  73 + */
  74 + private int startRadius;
  75 +
  76 + /**
  77 + * 多边形角的个数
  78 + */
  79 + private int angleCount ;
  80 +
  81 + private int[] angles;
  82 +
  83 + /**
  84 + * 开始绘制的角度
  85 + */
  86 + private int currentAngle;
  87 +
  88 + /**
  89 + * 存储角位置的集合
  90 + */
  91 + private List<PointF> pointFList = new ArrayList<>();
  92 +
  93 + /**
  94 + * 圆角大小的默认值
  95 + */
  96 + private static final int BODER_RADIUS_DEFAULT = 10;
  97 +
  98 + /**
  99 + * 圆角的大小
  100 + */
  101 + private int mBorderRadius;
  102 +
  103 + /**
  104 + * 绘图的Paint
  105 + */
  106 + private Paint mBitmapPaint;
  107 +
  108 + /**
  109 + * 圆角的半径
  110 + */
  111 + private int mRadius;
  112 +
  113 + /**
  114 + * 3x3 矩阵,主要用于缩小放大
  115 + */
  116 + private Matrix mMatrix;
  117 +
  118 + /**
  119 + * 渲染图像,使用图像为绘制图形着色
  120 + */
  121 + private BitmapShader mBitmapShader;
  122 +
  123 + /**
  124 + * view的宽度
  125 + */
  126 + private int mWidth;
  127 + private RectF mRoundRect;
  128 +
  129 + public MultiView(Context context) {
  130 + this(context, null);
  131 + }
  132 +
  133 + public MultiView(Context context, AttributeSet attrs) {
  134 +
  135 + this(context, attrs, 0);
  136 +
  137 + }
  138 +
  139 + public MultiView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
  140 + super(context, attrs, defStyleAttr);
  141 +
  142 + this.mContext = context;
  143 +
  144 + init(context, attrs);
  145 +
  146 + }
  147 +
  148 + public void init(Context context, AttributeSet attrs) {
  149 + mMatrix = new Matrix();
  150 + mBitmapPaint = new Paint();
  151 + mBitmapPaint.setAntiAlias(true);
  152 +
  153 + TypedArray typedArray = context.obtainStyledAttributes(attrs,
  154 + R.styleable.RoundImageView);
  155 +
  156 + mBorderRadius = typedArray.getDimensionPixelSize(
  157 + R.styleable.RoundImageView_borderRadius, (int) TypedValue
  158 + .applyDimension(TypedValue.COMPLEX_UNIT_DIP,
  159 + BODER_RADIUS_DEFAULT, getResources()
  160 + .getDisplayMetrics()));// 默认为10dp
  161 + type = typedArray.getInt(R.styleable.RoundImageView_type, TYPE_CIRCLE);// 默认为Circle
  162 + angleCount = typedArray.getInt(R.styleable.RoundImageView_angleCount, ANGLECOUNT);
  163 + currentAngle = typedArray.getInt(R.styleable.RoundImageView_currentAngle, currentAngle);
  164 +
  165 + typedArray.recycle(); //回收之后对象可以重用
  166 + }
  167 + @Override
  168 + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  169 + super.onMeasure(widthMeasureSpec, heightMeasureSpec);
  170 +
  171 + /**
  172 + * 如果类型是圆形或多边形,则强制改变view的宽高一致,以小值为准
  173 + */
  174 + if (type == TYPE_CIRCLE) {
  175 + mWidth = Math.min(getMeasuredWidth(), getMeasuredHeight());
  176 + mRadius = mWidth / 2;
  177 + setMeasuredDimension(mWidth, mWidth);
  178 + }
  179 +
  180 + if (type == TYPE_MULTI) {
  181 + mWidth = Math.min(getMeasuredWidth(), getMeasuredHeight());
  182 +
  183 + setMeasuredDimension(mWidth, mWidth);
  184 +
  185 + angles = new int[angleCount];
  186 +
  187 + for (int i = 0; i < angleCount; i++) {
  188 + int partOfAngle = 360 / angleCount; //每个顶点的角度
  189 + angles[i] = currentAngle + partOfAngle * i;
  190 +
  191 + startRadius = mWidth / 2;
  192 + float x = (float) (Math.sin(Math.toRadians(angles[i])) * startRadius);
  193 + float y = (float) (Math.cos(Math.toRadians(angles[i])) * startRadius);
  194 + pointFList.add(new PointF(x, y));
  195 + }
  196 + }
  197 +
  198 + }
  199 +
  200 + /**
  201 + * 初始化BitmapShader
  202 + */
  203 + private void setUpShader() {
  204 + Drawable drawable = getDrawable();
  205 + if (drawable == null) {
  206 + return;
  207 + }
  208 +
  209 + Bitmap bmp = drawableToBitamp(drawable);
  210 + // 将bmp作为着色器,就是在指定区域内绘制bmp
  211 + mBitmapShader = new BitmapShader(bmp, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);
  212 + float scale = 1.0f;
  213 + if (type == TYPE_CIRCLE) {
  214 + // 拿到bitmap宽或高的小值
  215 + int bSize = Math.min(bmp.getWidth(), bmp.getHeight());
  216 + scale = mWidth * 1.0f / bSize;
  217 +
  218 + } else if (type == TYPE_ROUND) {
  219 + if (!(bmp.getWidth() == getWidth() && bmp.getHeight() == getHeight())) {
  220 + // 如果图片的宽或者高与view的宽高不匹配,计算出需要缩放的比例;缩放后的图片的宽高,一定要大于我们view的宽高;所以我们这里取大值;
  221 + scale = Math.max(getWidth() * 1.0f / bmp.getWidth(), getHeight() * 1.0f / bmp.getHeight());
  222 + }
  223 +
  224 + } else if (type == TYPE_MULTI) {
  225 + // 拿到bitmap宽或高的小值
  226 + int bSize = Math.min(bmp.getWidth(), bmp.getHeight());
  227 + scale = mWidth * 1.0f / bSize;
  228 + }
  229 + // shader的变换矩阵,我们这里主要用于放大或者缩小
  230 + mMatrix.setScale(scale, scale);
  231 +
  232 + // 设置变换矩阵
  233 + mBitmapShader.setLocalMatrix(mMatrix);
  234 + // 设置shader
  235 + mBitmapPaint.setShader(mBitmapShader);
  236 + }
  237 +
  238 + @Override
  239 + protected void onDraw(Canvas canvas) {
  240 + if (getDrawable() == null) {
  241 + return;
  242 + }
  243 + setUpShader();
  244 +
  245 + if (type == TYPE_ROUND) {
  246 + canvas.drawRoundRect(mRoundRect, mBorderRadius, mBorderRadius,
  247 + mBitmapPaint);
  248 + } else if (type == TYPE_MULTI) {
  249 + //canvas.translate(startRadius,startRadius);
  250 +
  251 + Path mPath = drawPath();
  252 +
  253 + canvas.drawPath(mPath, mBitmapPaint);
  254 + } else {
  255 + canvas.drawCircle(mRadius, mRadius, mRadius, mBitmapPaint);
  256 + }
  257 + }
  258 +
  259 + /**
  260 + * @return 多边形路径
  261 + */
  262 + private Path drawPath() {
  263 + Path mPath = new Path();
  264 + mPath.moveTo(pointFList.get(0).x, pointFList.get(0).y);
  265 + for (int i = 2; i < angleCount; i++) {
  266 + if (i % 2 == 0) {// 除以二取余数,余数为0则为偶数,否则奇数
  267 + mPath.lineTo(pointFList.get(i).x, pointFList.get(i).y);
  268 + }
  269 +
  270 + }
  271 +
  272 + if (angleCount % 2 == 0) { //偶数,moveTo
  273 + mPath.moveTo(pointFList.get(1).x, pointFList.get(1).y);
  274 + } else { //奇数,lineTo
  275 + mPath.lineTo(pointFList.get(1).x, pointFList.get(1).y);
  276 + }
  277 +
  278 + for (int i = 3; i < angleCount; i++) {
  279 + if (i % 2 != 0) {
  280 + mPath.lineTo(pointFList.get(i).x, pointFList.get(i).y);
  281 + }
  282 + }
  283 +
  284 + mPath.offset(startRadius, startRadius);
  285 + return mPath;
  286 + }
  287 +
  288 + @Override
  289 + protected void onSizeChanged(int w, int h, int oldw, int oldh) {
  290 + super.onSizeChanged(w, h, oldw, oldh);
  291 +
  292 + // 圆角图片的范围
  293 + if (type == TYPE_ROUND)
  294 + mRoundRect = new RectF(0, 0, w, h);
  295 + }
  296 +
  297 + /**
  298 + * drawable转bitmap
  299 + *
  300 + * @param drawable
  301 + * @return
  302 + */
  303 + private Bitmap drawableToBitamp(Drawable drawable) {
  304 + if (drawable instanceof BitmapDrawable) {
  305 + BitmapDrawable bd = (BitmapDrawable) drawable;
  306 + return bd.getBitmap();
  307 + }
  308 + int w = drawable.getIntrinsicWidth();
  309 + int h = drawable.getIntrinsicHeight();
  310 + Bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
  311 + Canvas canvas = new Canvas(bitmap);
  312 + drawable.setBounds(0, 0, w, h);
  313 + drawable.draw(canvas);
  314 + return bitmap;
  315 + }
  316 +
  317 + private static final String STATE_INSTANCE = "state_instance";
  318 + private static final String STATE_TYPE = "state_type";
  319 + private static final String STATE_BORDER_RADIUS = "state_border_radius";
  320 +
  321 + @Override
  322 + protected Parcelable onSaveInstanceState() {
  323 + Bundle bundle = new Bundle();
  324 + bundle.putParcelable(STATE_INSTANCE, super.onSaveInstanceState());
  325 + bundle.putInt(STATE_TYPE, type);
  326 + bundle.putInt(STATE_BORDER_RADIUS, mBorderRadius);
  327 + return bundle;
  328 + }
  329 +
  330 + @Override
  331 + protected void onRestoreInstanceState(Parcelable state) {
  332 + if (state instanceof Bundle) {
  333 + Bundle bundle = (Bundle) state;
  334 + super.onRestoreInstanceState(((Bundle) state)
  335 + .getParcelable(STATE_INSTANCE));
  336 + this.type = bundle.getInt(STATE_TYPE);
  337 + this.mBorderRadius = bundle.getInt(STATE_BORDER_RADIUS);
  338 + } else {
  339 + super.onRestoreInstanceState(state);
  340 + }
  341 +
  342 + }
  343 +
  344 + public void setType(int type) {
  345 + if (this.type != type) {
  346 + this.type = type;
  347 + if (this.type != TYPE_ROUND && this.type != TYPE_CIRCLE && this.type != TYPE_MULTI) {
  348 + this.type = TYPE_CIRCLE;
  349 + }
  350 + requestLayout();
  351 + }
  352 +
  353 + }
  354 +
  355 +}
  356 +
... ...
core/imageload/src/main/res/values/strings.xml 0 → 100644
  1 +<resources>
  2 + <string name="app_name">imageload</string>
  3 +</resources>
... ...
core/imageload/src/main/res/values/style.xml 0 → 100644
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<resources>
  3 + <declare-styleable name="RoundImageView">
  4 + <attr name="borderRadius" format="dimension" />
  5 + <attr name="type">
  6 + <enum name="circle" value="0" />
  7 + <enum name="round" value="1" />
  8 + <enum name="multi" value="3" />
  9 + </attr>
  10 + <attr name="angleCount" format="integer" />
  11 + <attr name="currentAngle" format="integer" />
  12 + </declare-styleable>
  13 +
  14 +</resources>
0 15 \ No newline at end of file
... ...
core/imageload/src/test/java/com/mm999/imageload/ExampleUnitTest.java 0 → 100644
  1 +package com.mm999.imageload;
  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() {
  15 + assertEquals(4, 2 + 2);
  16 + }
  17 +}
0 18 \ No newline at end of file
... ...
settings.gradle
1 1 include ':app:strike', ':network'
2 2 //基础库
3   -include ':core:base',':core:network'
  3 +include ':core:base',':core:network',':core:imageload'
4 4 //include ':cloud:user'
5 5  
6 6 rootProject.name='ModuleStrike'
... ...