├── BaseImageLoader ├── build.gradle ├── consumer-rules.pro ├── jcenter.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── me │ │ └── alex │ │ └── baseimageloader │ │ ├── BaseImageLoader.java │ │ ├── config │ │ ├── BaseImageConfig.java │ │ ├── BaseImageSetting.java │ │ └── Builder.java │ │ ├── entity │ │ └── ImageResult.java │ │ ├── listener │ │ ├── OnAsListener.java │ │ ├── OnBitmapResult.java │ │ ├── OnDrawableResult.java │ │ ├── OnFileResult.java │ │ ├── OnGifResult.java │ │ └── OnLoadListener.java │ │ ├── module │ │ └── MyAppGlideModule.java │ │ ├── observer │ │ └── BaseLifeObserver.java │ │ ├── srtategy │ │ ├── BaseImageLoaderStrategy.java │ │ └── CacheStrategy.java │ │ ├── tools │ │ ├── AutoLoadTools.java │ │ └── Tools.java │ │ ├── transform │ │ ├── RoundAndCenterCropTransform.java │ │ └── RoundedCornersTransform.java │ │ └── view │ │ └── BaseImageView.java │ └── res │ └── values │ └── attrs.xml ├── README.md ├── app ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── assets │ └── imgs.zip │ ├── java │ └── me │ │ └── alex │ │ └── baseimageloaderdemo │ │ ├── App.java │ │ ├── ImageConfig.java │ │ ├── ImageData.java │ │ ├── MainActivity.java │ │ └── fragment │ │ ├── AutoLoadFragment.java │ │ ├── BaseImageViewFragment.java │ │ ├── CustomFragment.java │ │ └── ImageFragment.java │ └── res │ ├── drawable │ ├── ic_baseline_adb_24.xml │ └── ic_launcher_background.xml │ ├── layout │ ├── activity_main.xml │ ├── fragment_autoload.xml │ ├── fragment_baseimageview.xml │ ├── fragment_custom.xml │ └── fragment_image.xml │ ├── mipmap-hdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── values │ ├── colors.xml │ ├── strings.xml │ └── styles.xml │ └── xml │ └── network_security_config.xml ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /BaseImageLoader/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion 29 5 | buildToolsVersion "29.0.3" 6 | 7 | defaultConfig { 8 | minSdkVersion 19 9 | targetSdkVersion 29 10 | versionCode 1 11 | versionName "1.0" 12 | 13 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 14 | consumerProguardFiles "consumer-rules.pro" 15 | } 16 | 17 | buildTypes { 18 | release { 19 | minifyEnabled false 20 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 21 | } 22 | } 23 | } 24 | 25 | dependencies { 26 | implementation fileTree(dir: "libs", include: ["*.jar"]) 27 | api 'com.github.bumptech.glide:glide:4.11.0' 28 | annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0' 29 | } 30 | apply from: 'jcenter.gradle' -------------------------------------------------------------------------------- /BaseImageLoader/consumer-rules.pro: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexFugui/BaseImageLoader/1422c4b2e91acb7295da56200a651de64f931803/BaseImageLoader/consumer-rules.pro -------------------------------------------------------------------------------- /BaseImageLoader/jcenter.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.github.dcendents.android-maven' 2 | apply plugin: 'com.jfrog.bintray' 3 | 4 | def siteUrl = 'https://github.com/AlexFugui/BaseImageLoader' //项目在github主页地址 5 | def gitUrl = 'https://github.com/AlexFugui/BaseImageLoader.git' //Git仓库的地址 6 | group = "com.alex" 7 | version = "1.1.0" 8 | 9 | 10 | install { 11 | repositories.mavenInstaller { 12 | pom { 13 | project { 14 | packaging 'aar'//打包类型 aar文件 15 | name 'BaseImageLoader'// 在pom库中的包名 16 | description 'Android BaseImageLoader'// 可选,项目描述。 17 | url siteUrl // 项目主页 18 | 19 | licenses { 20 | license { 21 | name 'The Apache Software License, Version 2.0' 22 | url 'http://www.apache.org/licenses/LICENSE-2.0.txt' 23 | } 24 | } 25 | 26 | developers { 27 | developer { 28 | id 'AlexFugui' // 开发者的id。 29 | name 'AlexFugui' // 开发者名字。 30 | email '329406095@qq.com' // 开发者邮箱。 31 | } 32 | } 33 | 34 | scm { 35 | connection gitUrl // Git仓库地址。 36 | developerConnection gitUrl // Git仓库地址。 37 | url siteUrl // 项目主页。 38 | } 39 | } 40 | } 41 | } 42 | } 43 | 44 | task sourcesJar(type: Jar) { 45 | from android.sourceSets.main.java.srcDirs 46 | getArchiveClassifier().convention("sources") 47 | getArchiveClassifier().set("sources") 48 | } 49 | 50 | task javadoc(type: Javadoc) { 51 | source = android.sourceSets.main.java.srcDirs 52 | classpath += project.files(android.getBootClasspath().join(File.pathSeparator)) 53 | failOnError false 54 | } 55 | 56 | task javadocJar(type: Jar, dependsOn: javadoc) { 57 | getArchiveClassifier().convention("javadoc") 58 | getArchiveClassifier().set("javadoc") 59 | from javadoc.destinationDir 60 | } 61 | artifacts { 62 | archives javadocJar 63 | archives sourcesJar 64 | } 65 | 66 | Properties properties = new Properties() 67 | properties.load(project.rootProject.file('local.properties').newDataInputStream()) 68 | bintray { 69 | user = properties.getProperty("bintray.user") 70 | key = properties.getProperty("bintray.apikey") 71 | 72 | configurations = ['archives'] 73 | pkg { 74 | repo = "maven" 75 | name = "BaseImageLoader"//项目上传以后在名为maven的库中的包名 76 | userOrg = 'alexfugui'//Bintray的组织中 id 77 | websiteUrl = siteUrl 78 | vcsUrl = gitUrl 79 | licenses = ["Apache-2.0"] 80 | publish = true // 是否是公开项目。 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /BaseImageLoader/proguard-rules.pro: -------------------------------------------------------------------------------- 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 -------------------------------------------------------------------------------- /BaseImageLoader/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | / 5 | -------------------------------------------------------------------------------- /BaseImageLoader/src/main/java/me/alex/baseimageloader/BaseImageLoader.java: -------------------------------------------------------------------------------- 1 | package me.alex.baseimageloader; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.content.Context; 5 | import android.graphics.Bitmap; 6 | import android.graphics.drawable.BitmapDrawable; 7 | import android.graphics.drawable.Drawable; 8 | import android.os.Handler; 9 | import android.view.View; 10 | import android.view.ViewGroup; 11 | import android.widget.ImageView; 12 | 13 | import androidx.annotation.NonNull; 14 | import androidx.annotation.Nullable; 15 | 16 | import com.bumptech.glide.load.DataSource; 17 | import com.bumptech.glide.load.engine.DiskCacheStrategy; 18 | import com.bumptech.glide.load.engine.GlideException; 19 | import com.bumptech.glide.load.resource.bitmap.RoundedCorners; 20 | import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions; 21 | import com.bumptech.glide.load.resource.gif.GifDrawable; 22 | import com.bumptech.glide.request.RequestListener; 23 | import com.bumptech.glide.request.target.CustomTarget; 24 | import com.bumptech.glide.request.target.CustomViewTarget; 25 | import com.bumptech.glide.request.target.ImageViewTarget; 26 | import com.bumptech.glide.request.target.Target; 27 | import com.bumptech.glide.request.transition.Transition; 28 | 29 | import java.io.File; 30 | 31 | import me.alex.baseimageloader.config.BaseImageConfig; 32 | import me.alex.baseimageloader.entity.ImageResult; 33 | import me.alex.baseimageloader.listener.OnAsListener; 34 | import me.alex.baseimageloader.listener.OnBitmapResult; 35 | import me.alex.baseimageloader.listener.OnDrawableResult; 36 | import me.alex.baseimageloader.listener.OnFileResult; 37 | import me.alex.baseimageloader.listener.OnGifResult; 38 | import me.alex.baseimageloader.listener.OnLoadListener; 39 | import me.alex.baseimageloader.module.GlideAlex; 40 | import me.alex.baseimageloader.module.GlideRequest; 41 | import me.alex.baseimageloader.module.GlideRequests; 42 | import me.alex.baseimageloader.srtategy.BaseImageLoaderStrategy; 43 | import me.alex.baseimageloader.srtategy.CacheStrategy; 44 | import me.alex.baseimageloader.tools.AutoLoadTools; 45 | import me.alex.baseimageloader.tools.Tools; 46 | import me.alex.baseimageloader.transform.RoundAndCenterCropTransform; 47 | import me.alex.baseimageloader.view.BaseImageView; 48 | 49 | 50 | /** 51 | * ================================================ 52 | * Description: 53 | *

54 | * Created by Alex on 2020/12/4 0004 55 | *

56 | * 页面内容介绍: 可自行实现 {@link BaseImageLoaderStrategy} 和 {@link BaseImageConfig} 替换现有策略 57 | *

58 | * ================================================ 59 | */ 60 | public class BaseImageLoader implements BaseImageLoaderStrategy { 61 | 62 | private static BaseImageLoader instance = new BaseImageLoader(); 63 | 64 | public static BaseImageLoader getInstance() { 65 | return instance; 66 | } 67 | 68 | public BaseImageLoader() { 69 | 70 | } 71 | 72 | @SuppressLint("CheckResult") 73 | @Override 74 | public void loadImage(@NonNull Context context, @NonNull final BaseImageConfig config) { 75 | GlideRequests requests; 76 | requests = GlideAlex.with(context);//如果context是activity/Fragment则自动使用V层的生命周期 77 | if (config.getAsBitmap()) { 78 | requests.asBitmap(); 79 | } 80 | GlideRequest glideRequest = requests.load(config.getUrl()); 81 | //缓存类型 82 | //如果BaseImageConfig缓存策略为默认的ALL 则使用默认缓存策略 83 | if (config.getCacheStrategy() == CacheStrategy.ALL) { 84 | glideRequest.diskCacheStrategy(DiskCacheStrategy.ALL); 85 | } else { 86 | //如果不是ALL则使用config中的配置 87 | switch (config.getCacheStrategy()) { 88 | //缓存策略 89 | case CacheStrategy.NONE: 90 | glideRequest.diskCacheStrategy(DiskCacheStrategy.NONE); 91 | break; 92 | case CacheStrategy.RESOURCE: 93 | glideRequest.diskCacheStrategy(DiskCacheStrategy.RESOURCE); 94 | break; 95 | case CacheStrategy.DATA: 96 | glideRequest.diskCacheStrategy(DiskCacheStrategy.DATA); 97 | break; 98 | case CacheStrategy.AUTOMATIC: 99 | glideRequest.diskCacheStrategy(DiskCacheStrategy.AUTOMATIC); 100 | break; 101 | case CacheStrategy.ALL: 102 | glideRequest.diskCacheStrategy(DiskCacheStrategy.ALL); 103 | default: 104 | glideRequest.diskCacheStrategy(DiskCacheStrategy.ALL); 105 | break; 106 | } 107 | } 108 | 109 | 110 | //占位图 111 | // if (config.getPlaceholder() != -1) { 112 | glideRequest.placeholder(config.getPlaceholder()); 113 | // } 114 | //错误图 115 | // if (config.getErrorPic() != -1) { 116 | glideRequest.error(config.getErrorPic()); 117 | // } 118 | //是否淡出淡入 119 | if (config.isCrossFade()) { 120 | glideRequest.transition(DrawableTransitionOptions.withCrossFade()); 121 | } 122 | //是否将图片剪切为圆形 123 | if (config.isCircle()) { 124 | //如果剪裁成圆形就忽略圆角 125 | if (config.isCenterCrop()) { 126 | glideRequest.centerCrop(); 127 | } 128 | glideRequest.circleCrop(); 129 | } else { 130 | //圆形和圆角同时只能设置一种 同时设置只生效圆形 131 | if (config.getRadius() > 0) { 132 | if (config.isCenterCrop()) {//设置裁剪+4个圆角相同 133 | glideRequest.transform(new RoundAndCenterCropTransform( 134 | config.isCenterCrop(), 135 | Tools.dp2px(context, config.getRadius()), 136 | Tools.dp2px(context, config.getRadius()), 137 | Tools.dp2px(context, config.getRadius()), 138 | Tools.dp2px(context, config.getRadius())) 139 | ); 140 | } else {//单独设置4个圆角 141 | glideRequest.transform(new RoundedCorners((int) config.getRadius())); 142 | } 143 | } else { 144 | //如果没设置通用圆角,设置了单独圆角+裁剪 145 | if (config.getTopRightRadius() > 0 || config.getTopLeftRadius() > 0 || config.getBottomRightRadius() > 0 || config.getBottomLeftRadius() > 0) { 146 | glideRequest.transform(new RoundAndCenterCropTransform( 147 | config.isCenterCrop(), 148 | Tools.dp2px(context, config.getTopRightRadius()), 149 | Tools.dp2px(context, config.getTopLeftRadius()), 150 | Tools.dp2px(context, config.getBottomRightRadius()), 151 | Tools.dp2px(context, config.getBottomLeftRadius())) 152 | ); 153 | } else { 154 | //没有设置圆角 155 | if (config.isCenterCrop()) { 156 | //裁减 157 | glideRequest.centerCrop(); 158 | } 159 | } 160 | } 161 | } 162 | 163 | final OnLoadListener listener = config.getListener(); 164 | if (listener != null) { 165 | glideRequest.listener(new RequestListener() { 166 | @Override 167 | public boolean onLoadFailed(@Nullable GlideException e, Object model, Target target, boolean isFirstResource) { 168 | listener.onLoadFailed(e, model, target, isFirstResource); 169 | return false; 170 | } 171 | 172 | @Override 173 | public boolean onResourceReady(Drawable resource, Object model, Target target, DataSource dataSource, boolean isFirstResource) { 174 | listener.onResourceReady(resource, model, target, dataSource, isFirstResource); 175 | return false; 176 | } 177 | }); 178 | } 179 | if (config.getImageView() instanceof ImageView) { 180 | glideRequest.into((ImageView) config.getImageView()); 181 | } else if (config.getImageView() instanceof ViewGroup) { 182 | glideRequest.into(new CustomViewTarget((ViewGroup) config.getImageView()) { 183 | @Override 184 | public void onLoadFailed(@Nullable Drawable errorDrawable) { 185 | config.getImageView().setBackground(errorDrawable); 186 | } 187 | 188 | @Override 189 | public void onResourceReady(@NonNull Drawable resource, @Nullable Transition transition) { 190 | config.getImageView().setBackground(resource); 191 | } 192 | 193 | @Override 194 | protected void onResourceCleared(@Nullable Drawable placeholder) { 195 | config.getImageView().setBackground(placeholder); 196 | } 197 | }); 198 | } else { 199 | glideRequest.into(new CustomTarget() { 200 | @Override 201 | public void onResourceReady(@NonNull Drawable resource, @Nullable Transition transition) { 202 | config.getImageView().setBackground(resource); 203 | } 204 | 205 | @Override 206 | public void onLoadCleared(@Nullable Drawable placeholder) { 207 | config.getImageView().setBackground(placeholder); 208 | } 209 | }); 210 | } 211 | 212 | } 213 | 214 | @Override 215 | public void autoLoadImage(@NonNull Context context, @NonNull ViewGroup viewGroup, @NonNull String zipFileRealPath) { 216 | try { 217 | handlerViewGroup(context, viewGroup, zipFileRealPath); 218 | } catch (Exception e) { 219 | e.printStackTrace(); 220 | } 221 | } 222 | 223 | private void handlerViewGroup(Context context, ViewGroup viewGroup, String zipFileRealPath) throws Exception { 224 | for (int i = 0; i < viewGroup.getChildCount(); i++) { 225 | if (viewGroup.getChildAt(i) instanceof ViewGroup) { 226 | if (viewGroup.getChildAt(i).getTag() != null && !viewGroup.getChildAt(i).getTag().equals("")) { 227 | loadImage(context, BaseImageConfig.builder() 228 | .url(AutoLoadTools.getInstance().readZipFile(zipFileRealPath, (String) viewGroup.getChildAt(i).getTag())) 229 | .imageView(viewGroup.getChildAt(i)) 230 | .show()); 231 | } 232 | if (viewGroup.getChildCount() > 0) { 233 | handlerViewGroup(context, (ViewGroup) viewGroup.getChildAt(i), zipFileRealPath); 234 | } 235 | } else { 236 | View view = viewGroup.getChildAt(i); 237 | if (view.getTag() != null && !view.getTag().equals("")) { 238 | if (view instanceof BaseImageView) { 239 | BaseImageConfig config = ((BaseImageView) view).getConfig(); 240 | config.setUrl(AutoLoadTools.getInstance().readZipFile(zipFileRealPath, (String) viewGroup.getChildAt(i).getTag())); 241 | loadImage(context, config); 242 | } else { 243 | loadImage(context, BaseImageConfig.builder() 244 | .url(AutoLoadTools.getInstance().readZipFile(zipFileRealPath, (String) viewGroup.getChildAt(i).getTag())) 245 | .imageView(view) 246 | .show()); 247 | } 248 | } 249 | } 250 | } 251 | 252 | } 253 | 254 | 255 | @Override 256 | public void loadImageAs(@NonNull Context context, @NonNull Object url, @NonNull OnAsListener listener) { 257 | loadImageAs(context, url, null, listener); 258 | } 259 | 260 | @Override 261 | public void loadImageAs(@NonNull final Context context, @NonNull final Object url, @Nullable final ImageView imageView, @NonNull final OnAsListener listener) { 262 | GlideRequests requests; 263 | requests = GlideAlex.with(context);//如果context是activity/Fragment则自动使用V层的生命周期 264 | if (listener instanceof OnBitmapResult) { 265 | requests.asBitmap() 266 | .load(url) 267 | .into(new ImageViewTarget(imageView != null ? imageView : new ImageView(context)) { 268 | @Override 269 | protected void setResource(@Nullable Bitmap resource) { 270 | if (resource != null) { 271 | if (imageView != null) { 272 | imageView.setImageBitmap(resource); 273 | } 274 | listener.OnResult(new ImageResult(resource)); 275 | } 276 | } 277 | }); 278 | } else if (listener instanceof OnFileResult) { 279 | requests.asFile() 280 | .load(url) 281 | // .error(GlideAlex.with(context).asFile().load(url)) 282 | .listener(new RequestListener() { 283 | @Override 284 | public boolean onLoadFailed(@Nullable GlideException e, Object model, Target target, boolean isFirstResource) { 285 | if (imageView != null) { 286 | new Handler().post(new Runnable() { 287 | @Override 288 | public void run() { 289 | GlideAlex.with(context).load(url).into(imageView); 290 | } 291 | }); 292 | } 293 | return false; 294 | } 295 | 296 | @Override 297 | public boolean onResourceReady(File resource, Object model, Target target, DataSource dataSource, boolean isFirstResource) { 298 | if (imageView != null) { 299 | new Handler().post(new Runnable() { 300 | @Override 301 | public void run() { 302 | GlideAlex.with(context).load(url).into(imageView); 303 | } 304 | }); 305 | } 306 | return false; 307 | } 308 | }) 309 | .into(new ImageViewTarget(imageView != null ? imageView : new ImageView(context)) { 310 | @Override 311 | protected void setResource(@Nullable File resource) { 312 | if (resource != null) { 313 | listener.OnResult(new ImageResult(resource)); 314 | } 315 | } 316 | }); 317 | } else if (listener instanceof OnGifResult) { 318 | requests.asGif() 319 | .load(url) 320 | .into(new ImageViewTarget(imageView != null ? imageView : new ImageView(context)) { 321 | @Override 322 | protected void setResource(@Nullable GifDrawable resource) { 323 | if (resource != null) { 324 | if (imageView != null) { 325 | imageView.setImageDrawable(resource); 326 | } 327 | listener.OnResult(new ImageResult(resource)); 328 | } 329 | } 330 | }); 331 | } else if (listener instanceof OnDrawableResult) { 332 | requests.asDrawable() 333 | .load(url) 334 | .into(new ImageViewTarget(imageView != null ? imageView : new ImageView(context)) { 335 | @Override 336 | protected void setResource(@Nullable Drawable resource) { 337 | if (resource != null) { 338 | if (imageView != null) { 339 | imageView.setImageDrawable(resource); 340 | } 341 | listener.OnResult(new ImageResult(resource)); 342 | } 343 | } 344 | }); 345 | } else { 346 | requests.asBitmap() 347 | .load(url) 348 | .into(new ImageViewTarget(imageView != null ? imageView : new ImageView(context)) { 349 | @Override 350 | protected void setResource(@Nullable Bitmap resource) { 351 | if (resource != null) { 352 | if (imageView != null) { 353 | imageView.setImageBitmap(resource); 354 | } 355 | listener.OnResult(new ImageResult(resource)); 356 | } 357 | } 358 | }); 359 | } 360 | // GlideRequest glideRequest = requests.load(url); 361 | } 362 | 363 | 364 | @Override 365 | public void clear(@Nullable Context context, @Nullable BaseImageConfig config) { 366 | if (context == null) { 367 | throw new NullPointerException("Context is required"); 368 | } 369 | if (config == null) { 370 | throw new NullPointerException("BaseImageConfig is required"); 371 | } 372 | 373 | if (config.getImageView() != null) {//取消在执行的任务并且释放资源 374 | GlideAlex.get(context).getRequestManagerRetriever().get(context).clear(config.getImageView()); 375 | } 376 | 377 | if (config.isClearMemory()) {//清除内存缓存 378 | GlideAlex.get(context).clearMemory(); 379 | } 380 | 381 | if (config.isClearDiskCache()) {//清除本地缓存 382 | GlideAlex.get(context).clearDiskCache(); 383 | } 384 | 385 | } 386 | } 387 | -------------------------------------------------------------------------------- /BaseImageLoader/src/main/java/me/alex/baseimageloader/config/BaseImageConfig.java: -------------------------------------------------------------------------------- 1 | package me.alex.baseimageloader.config; 2 | 3 | import android.view.View; 4 | import android.widget.ImageView; 5 | 6 | import me.alex.baseimageloader.listener.OnLoadListener; 7 | import me.alex.baseimageloader.srtategy.BaseImageLoaderStrategy; 8 | import me.alex.baseimageloader.srtategy.CacheStrategy; 9 | 10 | 11 | /** 12 | * ================================================ 13 | * Description: 14 | *

15 | * Created by Alex on 2020/12/4 0004 16 | *

17 | * 页面内容介绍: 18 | * 这里是图片加载配置信息的基类,定义一些所有图片加载框架都可以用的通用参数 19 | * 每个 {@link BaseImageLoaderStrategy} 应该对应一个 {@link BaseImageConfig} 实现类 20 | *

21 | * ================================================ 22 | */ 23 | public class BaseImageConfig { 24 | 25 | public BaseImageConfig() { 26 | 27 | } 28 | 29 | /** 30 | * 网络图片url 31 | */ 32 | protected Object url; 33 | 34 | /** 35 | * 需要显示图片的View 36 | */ 37 | protected View imageView; 38 | 39 | /** 40 | * 加载网络图片之前占位图片 41 | */ 42 | protected int placeholder; 43 | 44 | /** 45 | * 错误占位图片 46 | */ 47 | protected int errorPic; 48 | 49 | /** 50 | * 是否使用淡入淡出过渡动画 51 | */ 52 | protected boolean isCrossFade; 53 | 54 | /** 55 | * 是否将图片剪切为 CenterCrop 56 | */ 57 | protected boolean isCenterCrop; 58 | 59 | /** 60 | * 是否将图片剪切为圆形 61 | */ 62 | protected boolean isCircle; 63 | 64 | /** 65 | * 左上 圆角 66 | */ 67 | protected float topRightRadius; 68 | 69 | /** 70 | * 右上 圆角 71 | */ 72 | protected float topLeftRadius; 73 | 74 | /** 75 | * 左下 圆角 76 | */ 77 | protected float bottomRightRadius; 78 | 79 | /** 80 | * 右下 圆角 81 | */ 82 | protected float bottomLeftRadius; 83 | 84 | /** 85 | * 通用圆角 86 | */ 87 | protected float radius; 88 | 89 | /** 90 | * 是否以bitmap加载 91 | */ 92 | protected boolean asBitmap; 93 | 94 | /** 95 | * 缓存类型 默认为通用配置中的模式 96 | */ 97 | private @CacheStrategy.Strategy 98 | int cacheStrategy = BaseImageSetting.getInstance().getCacheStrategy(); 99 | 100 | /** 101 | * 加载监听 102 | */ 103 | protected OnLoadListener listener; 104 | 105 | /** 106 | * 是否清除内存中缓存 107 | */ 108 | protected boolean clearMemory; 109 | 110 | /** 111 | * 是否清除储存中缓存 112 | */ 113 | protected boolean clearDiskCache; 114 | 115 | public BaseImageConfig(Builder builder) { 116 | this.url = builder.url; 117 | this.imageView = builder.imageView; 118 | this.placeholder = builder.placeholder; 119 | this.errorPic = builder.errorPic; 120 | this.isCrossFade = builder.isCrossFade; 121 | this.isCenterCrop = builder.isCenterCrop; 122 | this.isCircle = builder.isCircle; 123 | this.topRightRadius = builder.topRightRadius; 124 | this.topLeftRadius = builder.topLeftRadius; 125 | this.bottomRightRadius = builder.bottomRightRadius; 126 | this.bottomLeftRadius = builder.bottomLeftRadius; 127 | this.radius = builder.radius; 128 | this.asBitmap = builder.asBitmap; 129 | this.listener = builder.listener; 130 | this.clearMemory = builder.clearMemory; 131 | this.clearDiskCache = builder.clearDiskCache; 132 | } 133 | 134 | 135 | public Object getUrl() { 136 | return url; 137 | } 138 | 139 | public View getImageView() { 140 | return imageView; 141 | } 142 | 143 | public int getPlaceholder() { 144 | return placeholder; 145 | } 146 | 147 | public int getErrorPic() { 148 | return errorPic; 149 | } 150 | 151 | public boolean isCrossFade() { 152 | return isCrossFade; 153 | } 154 | 155 | public boolean isCenterCrop() { 156 | return isCenterCrop; 157 | } 158 | 159 | public boolean isCircle() { 160 | return isCircle; 161 | } 162 | 163 | public float getTopRightRadius() { 164 | return topRightRadius; 165 | } 166 | 167 | public float getTopLeftRadius() { 168 | return topLeftRadius; 169 | } 170 | 171 | public float getBottomRightRadius() { 172 | return bottomRightRadius; 173 | } 174 | 175 | public float getBottomLeftRadius() { 176 | return bottomLeftRadius; 177 | } 178 | 179 | public float getRadius() { 180 | return radius; 181 | } 182 | 183 | public void setUrl(Object url) { 184 | this.url = url; 185 | } 186 | 187 | public void setImageView(ImageView imageView) { 188 | this.imageView = imageView; 189 | } 190 | 191 | public void setPlaceholder(int placeholder) { 192 | this.placeholder = placeholder; 193 | } 194 | 195 | public void setErrorPic(int errorPic) { 196 | this.errorPic = errorPic; 197 | } 198 | 199 | public void setCrossFade(boolean crossFade) { 200 | isCrossFade = crossFade; 201 | } 202 | 203 | public void setCenterCrop() { 204 | isCenterCrop = true; 205 | } 206 | 207 | public void setCircle() { 208 | isCircle = true; 209 | } 210 | 211 | public void setTopRightRadius(float topRightRadius) { 212 | this.topRightRadius = topRightRadius; 213 | } 214 | 215 | public void setTopLeftRadius(float topLeftRadius) { 216 | this.topLeftRadius = topLeftRadius; 217 | } 218 | 219 | public void setBottomRightRadius(float bottomRightRadius) { 220 | this.bottomRightRadius = bottomRightRadius; 221 | } 222 | 223 | public void setBottomLeftRadius(float bottomLeftRadius) { 224 | this.bottomLeftRadius = bottomLeftRadius; 225 | } 226 | 227 | public void setRadius(float radius) { 228 | this.radius = radius; 229 | } 230 | 231 | public OnLoadListener getListener() { 232 | return listener; 233 | } 234 | 235 | public void setListener(OnLoadListener listener) { 236 | this.listener = listener; 237 | } 238 | 239 | public boolean getAsBitmap() { 240 | return asBitmap; 241 | } 242 | 243 | public void asBitmap(boolean asBitmap) { 244 | this.asBitmap = asBitmap; 245 | } 246 | 247 | public @CacheStrategy.Strategy 248 | int getCacheStrategy() { 249 | return cacheStrategy; 250 | } 251 | 252 | public void setCacheStrategy(int cacheStrategy) { 253 | this.cacheStrategy = cacheStrategy; 254 | } 255 | 256 | public boolean isClearMemory() { 257 | return clearMemory; 258 | } 259 | 260 | public boolean isClearDiskCache() { 261 | return clearDiskCache; 262 | } 263 | 264 | public static Builder builder() { 265 | return new Builder(); 266 | } 267 | 268 | } 269 | -------------------------------------------------------------------------------- /BaseImageLoader/src/main/java/me/alex/baseimageloader/config/BaseImageSetting.java: -------------------------------------------------------------------------------- 1 | package me.alex.baseimageloader.config; 2 | 3 | 4 | import android.util.Log; 5 | 6 | import me.alex.baseimageloader.srtategy.CacheStrategy; 7 | 8 | /** 9 | * ================================================ 10 | * Description: 11 | *

12 | * Created by Alex on 2020/12/5 13 | *

14 | * 页面内容介绍: BaseImage通用设置 15 | *

16 | * ================================================ 17 | */ 18 | public class BaseImageSetting { 19 | private static BaseImageSetting baseImageSetting = new BaseImageSetting(); 20 | 21 | /** 22 | * 加载中图片 23 | */ 24 | private int placeholder; 25 | /** 26 | * 加载错误图片 27 | */ 28 | protected int errorPic; 29 | /** 30 | * 默认内存缓存大小 20mb 31 | */ 32 | private int memoryCacheSize = 20; 33 | /** 34 | * 默认bitmap池缓存大小 30mb 35 | */ 36 | private int bitmapPoolSize = 30; 37 | /** 38 | * 默认硬盘缓存大小250mb 39 | */ 40 | private int diskCacheSize = 250; 41 | /** 42 | * 默认的缓存文件夹名称 43 | */ 44 | private String cacheFileName = "BaseImageLoaderCache"; 45 | /** 46 | * 通用缓存类型设置 47 | */ 48 | private @CacheStrategy.Strategy 49 | int cacheStrategy = CacheStrategy.AUTOMATIC; 50 | 51 | /** 52 | * log级别设置,默认为ERROR级别 53 | */ 54 | private int logLevel = Log.ERROR; 55 | 56 | /** 57 | * 自动加载图片缓存数量最大值 58 | */ 59 | private int cacheSize = 50; 60 | 61 | 62 | public static BaseImageSetting getInstance() { 63 | return baseImageSetting; 64 | } 65 | 66 | public int getMemoryCacheSize() { 67 | return memoryCacheSize; 68 | } 69 | 70 | /** 71 | * 设置内存缓存大小 默认20mb 72 | * 73 | * @param memoryCacheSize 单位mb 74 | * @return 返回SImageConfig类可以连续设置 75 | */ 76 | public BaseImageSetting setMemoryCacheSize(int memoryCacheSize) { 77 | this.memoryCacheSize = memoryCacheSize; 78 | return this; 79 | } 80 | 81 | public int getBitmapPoolSize() { 82 | return bitmapPoolSize; 83 | } 84 | 85 | /** 86 | * 设置bitMap池缓存大小 默认30mb 87 | * 88 | * @param bitmapPoolSize 单位mb 89 | * @return 返回SImageConfig类可以连续设置 90 | */ 91 | public BaseImageSetting setBitmapPoolSize(int bitmapPoolSize) { 92 | this.bitmapPoolSize = bitmapPoolSize; 93 | return this; 94 | } 95 | 96 | public int getDiskCacheSize() { 97 | return diskCacheSize; 98 | } 99 | 100 | /** 101 | * 设置硬盘缓存大小 默认250mb 102 | * 103 | * @param diskCacheSize 单位mb 104 | * @return 返回SImageConfig类可以连续设置 105 | */ 106 | public BaseImageSetting setDiskCacheSize(int diskCacheSize) { 107 | this.diskCacheSize = diskCacheSize; 108 | return this; 109 | } 110 | 111 | public String getCacheFileName() { 112 | return cacheFileName; 113 | } 114 | 115 | public BaseImageSetting setCacheFileName(String cacheFileName) { 116 | this.cacheFileName = cacheFileName; 117 | return this; 118 | } 119 | 120 | public BaseImageSetting setCacheStrategy(@CacheStrategy.Strategy int cacheStrategy) { 121 | this.cacheStrategy = cacheStrategy; 122 | return this; 123 | } 124 | 125 | public @CacheStrategy.Strategy 126 | int getCacheStrategy() { 127 | return cacheStrategy; 128 | } 129 | 130 | public int getLogLevel() { 131 | return logLevel; 132 | } 133 | 134 | /** 135 | * 如果你拥有设备的访问权限,你可以使用 adb logcat 或你的 IDE 查看一些日志。 136 | * 你可以使用 adb shell setprop log.tag. 操作为任何下面提到的标签(tag))开启日志。 137 | * VERBOSE 级别的日志会显得更加冗余但包含更多有用的信息。根据你要查看的标签的不同,你可以把 VERBOSE 和 DEBUG 级别的信息都尝试一下,以决定哪个级别的信息是你最需要的。 138 | * 139 | * @param logLevel 详见 {@link Log} 中Log等级 140 | */ 141 | public BaseImageSetting setLogLevel(int logLevel) { 142 | this.logLevel = logLevel; 143 | return this; 144 | } 145 | 146 | public int getPlaceholder() { 147 | return placeholder; 148 | } 149 | 150 | public BaseImageSetting setPlaceholder(int placeholder) { 151 | this.placeholder = placeholder; 152 | return this; 153 | } 154 | 155 | public int getErrorPic() { 156 | return errorPic; 157 | } 158 | 159 | public BaseImageSetting setErrorPic(int errorPic) { 160 | this.errorPic = errorPic; 161 | return this; 162 | } 163 | 164 | public int getCacheSize() { 165 | return cacheSize; 166 | } 167 | 168 | public BaseImageSetting setCacheSize(int cacheSize) { 169 | this.cacheSize = cacheSize; 170 | return this; 171 | } 172 | } 173 | -------------------------------------------------------------------------------- /BaseImageLoader/src/main/java/me/alex/baseimageloader/config/Builder.java: -------------------------------------------------------------------------------- 1 | package me.alex.baseimageloader.config; 2 | 3 | import android.view.View; 4 | import android.widget.ImageView; 5 | 6 | import me.alex.baseimageloader.listener.OnLoadListener; 7 | import me.alex.baseimageloader.srtategy.CacheStrategy; 8 | 9 | /** 10 | * ================================================ 11 | * Description: 12 | *

13 | * Created by Alex on 2020/12/15 14 | *

15 | * 页面内容介绍: 16 | *

17 | * ================================================ 18 | */ 19 | public class Builder { 20 | 21 | public Builder() { 22 | 23 | } 24 | 25 | protected Object url; 26 | protected View imageView; 27 | protected int placeholder = BaseImageSetting.getInstance().getPlaceholder(); 28 | protected int errorPic = BaseImageSetting.getInstance().getErrorPic(); 29 | protected boolean isCrossFade = false; 30 | protected boolean isCenterCrop = false; 31 | protected boolean isCircle = false; 32 | protected int topRightRadius = 0; 33 | protected int topLeftRadius = 0; 34 | protected int bottomRightRadius = 0; 35 | protected int bottomLeftRadius = 0; 36 | protected int radius = 0; 37 | protected boolean asBitmap; 38 | protected @CacheStrategy.Strategy 39 | int cacheStrategy;//0对应DiskCacheStrategy.all,1对应DiskCacheStrategy.NONE,2对应DiskCacheStrategy.SOURCE,3对应DiskCacheStrategy.RESULT 40 | protected OnLoadListener listener; 41 | protected boolean clearMemory; 42 | protected boolean clearDiskCache; 43 | 44 | public Builder url(Object url) { 45 | this.url = url; 46 | return this; 47 | } 48 | 49 | public Builder imageView(View imageView) { 50 | this.imageView = imageView; 51 | return this; 52 | } 53 | 54 | public Builder placeholder(int placeholder) { 55 | this.placeholder = placeholder; 56 | return this; 57 | } 58 | 59 | public Builder errorPic(int errorPic) { 60 | this.errorPic = errorPic; 61 | return this; 62 | } 63 | 64 | public Builder crossFade(boolean crossFade) { 65 | isCrossFade = crossFade; 66 | return this; 67 | } 68 | 69 | public Builder centerCrop() { 70 | isCenterCrop = true; 71 | return this; 72 | } 73 | 74 | public Builder isCircle() { 75 | isCircle = true; 76 | return this; 77 | } 78 | 79 | public Builder setTopRightRadius(int topRightRadius) { 80 | this.topRightRadius = topRightRadius; 81 | return this; 82 | } 83 | 84 | public Builder setTopLeftRadius(int topLeftRadius) { 85 | this.topLeftRadius = topLeftRadius; 86 | return this; 87 | } 88 | 89 | public Builder setBottomRightRadius(int bottomRightRadius) { 90 | this.bottomRightRadius = bottomRightRadius; 91 | return this; 92 | } 93 | 94 | public Builder setBottomLeftRadius(int bottomLeftRadius) { 95 | this.bottomLeftRadius = bottomLeftRadius; 96 | return this; 97 | } 98 | 99 | public Builder setRadius(int radius) { 100 | this.radius = radius; 101 | return this; 102 | } 103 | 104 | public OnLoadListener getListener() { 105 | return listener; 106 | } 107 | 108 | public Builder setListener(OnLoadListener listener) { 109 | this.listener = listener; 110 | return this; 111 | } 112 | 113 | public boolean isAsBitmap() { 114 | return asBitmap; 115 | } 116 | 117 | public Builder setAsBitmap(boolean asBitmap) { 118 | this.asBitmap = asBitmap; 119 | return this; 120 | } 121 | 122 | 123 | public Builder cacheStrategy(@CacheStrategy.Strategy int cacheStrategy) { 124 | this.cacheStrategy = cacheStrategy; 125 | return this; 126 | } 127 | 128 | public Builder clearMemory() { 129 | this.clearMemory = true; 130 | return this; 131 | } 132 | 133 | public Builder clearDiskCache() { 134 | this.clearDiskCache = true; 135 | return this; 136 | } 137 | 138 | public BaseImageConfig show() { 139 | return new BaseImageConfig(this); 140 | } 141 | } 142 | 143 | -------------------------------------------------------------------------------- /BaseImageLoader/src/main/java/me/alex/baseimageloader/entity/ImageResult.java: -------------------------------------------------------------------------------- 1 | package me.alex.baseimageloader.entity; 2 | 3 | import android.graphics.Bitmap; 4 | import android.graphics.drawable.Drawable; 5 | 6 | import com.bumptech.glide.load.resource.gif.GifDrawable; 7 | 8 | import java.io.File; 9 | 10 | /** 11 | * ================================================ 12 | * Description: 13 | *

14 | * Created by Alex on 2020/12/8 0008 15 | *

16 | * 页面内容介绍: 17 | *

18 | * ================================================ 19 | */ 20 | public class ImageResult { 21 | private Bitmap bitmap; 22 | private File file; 23 | private Drawable drawable; 24 | private GifDrawable gif; 25 | 26 | public ImageResult(Bitmap bitmap) { 27 | this.bitmap = bitmap; 28 | } 29 | 30 | public ImageResult(File file) { 31 | this.file = file; 32 | } 33 | 34 | public ImageResult(Drawable drawable) { 35 | this.drawable = drawable; 36 | } 37 | 38 | public ImageResult(GifDrawable gif) { 39 | this.gif = gif; 40 | } 41 | 42 | public Bitmap getBitmap() { 43 | return bitmap; 44 | } 45 | 46 | 47 | public File getFile() { 48 | return file; 49 | } 50 | 51 | 52 | public Drawable getDrawable() { 53 | return drawable; 54 | } 55 | 56 | 57 | public GifDrawable getGif() { 58 | return gif; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /BaseImageLoader/src/main/java/me/alex/baseimageloader/listener/OnAsListener.java: -------------------------------------------------------------------------------- 1 | package me.alex.baseimageloader.listener; 2 | 3 | 4 | import me.alex.baseimageloader.entity.ImageResult; 5 | 6 | public interface OnAsListener { 7 | void OnResult(ImageResult result); 8 | } 9 | -------------------------------------------------------------------------------- /BaseImageLoader/src/main/java/me/alex/baseimageloader/listener/OnBitmapResult.java: -------------------------------------------------------------------------------- 1 | package me.alex.baseimageloader.listener; 2 | 3 | public interface OnBitmapResult extends OnAsListener { 4 | } 5 | -------------------------------------------------------------------------------- /BaseImageLoader/src/main/java/me/alex/baseimageloader/listener/OnDrawableResult.java: -------------------------------------------------------------------------------- 1 | package me.alex.baseimageloader.listener; 2 | 3 | 4 | public interface OnDrawableResult extends OnAsListener { 5 | } 6 | -------------------------------------------------------------------------------- /BaseImageLoader/src/main/java/me/alex/baseimageloader/listener/OnFileResult.java: -------------------------------------------------------------------------------- 1 | package me.alex.baseimageloader.listener; 2 | 3 | 4 | public interface OnFileResult extends OnAsListener { 5 | } 6 | -------------------------------------------------------------------------------- /BaseImageLoader/src/main/java/me/alex/baseimageloader/listener/OnGifResult.java: -------------------------------------------------------------------------------- 1 | package me.alex.baseimageloader.listener; 2 | 3 | 4 | public interface OnGifResult extends OnAsListener { 5 | } 6 | -------------------------------------------------------------------------------- /BaseImageLoader/src/main/java/me/alex/baseimageloader/listener/OnLoadListener.java: -------------------------------------------------------------------------------- 1 | package me.alex.baseimageloader.listener; 2 | 3 | import android.graphics.drawable.Drawable; 4 | 5 | import androidx.annotation.Nullable; 6 | 7 | import com.bumptech.glide.load.DataSource; 8 | import com.bumptech.glide.load.engine.GlideException; 9 | import com.bumptech.glide.request.target.Target; 10 | 11 | /** 12 | * ================================================ 13 | * Description: 14 | *

15 | * Created by Alex on 2020/12/8 0008 16 | *

17 | * 页面内容介绍: 默认加载结果监听,参数文档参考GlideV4 18 | *

19 | * ================================================ 20 | */ 21 | public interface OnLoadListener { 22 | /** 23 | * 加载成功结果回调监听 24 | * 25 | * @param resource 26 | * @param model 27 | * @param target 28 | * @param dataSource 29 | * @param isFirstResource 30 | */ 31 | void onResourceReady(Drawable resource, Object model, Target target, DataSource dataSource, boolean isFirstResource); 32 | 33 | void onLoadFailed(@Nullable GlideException e, Object model, Target target, boolean isFirstResource); 34 | } 35 | -------------------------------------------------------------------------------- /BaseImageLoader/src/main/java/me/alex/baseimageloader/module/MyAppGlideModule.java: -------------------------------------------------------------------------------- 1 | package me.alex.baseimageloader.module; 2 | 3 | import android.content.Context; 4 | import android.util.Log; 5 | 6 | import androidx.annotation.NonNull; 7 | 8 | import com.bumptech.glide.GlideBuilder; 9 | import com.bumptech.glide.annotation.GlideModule; 10 | import com.bumptech.glide.load.engine.bitmap_recycle.LruBitmapPool; 11 | import com.bumptech.glide.load.engine.cache.InternalCacheDiskCacheFactory; 12 | import com.bumptech.glide.load.engine.cache.LruResourceCache; 13 | import com.bumptech.glide.module.AppGlideModule; 14 | 15 | import me.alex.baseimageloader.config.BaseImageSetting; 16 | 17 | 18 | /** 19 | * ================================================ 20 | * Description: 21 | *

22 | * Created by Alex on 2020/12/2 0002 23 | *

24 | * 页面内容介绍: 生成GlideAlex的自定义Module 25 | *

26 | * ================================================ 27 | */ 28 | @GlideModule(glideName = "GlideAlex") 29 | public class MyAppGlideModule extends AppGlideModule { 30 | 31 | @Override 32 | public void applyOptions(@NonNull Context context, @NonNull GlideBuilder builder) { 33 | builder.setLogLevel(Log.ERROR); 34 | 35 | //内存缓存 20mb 36 | int memoryCacheSizeBytes = 1024 * 1024 * BaseImageSetting.getInstance().getMemoryCacheSize(); // 默认20mb 37 | builder.setMemoryCache(new LruResourceCache(memoryCacheSizeBytes)); 38 | 39 | //bitmap池缓存 30mb 40 | int bitmapPoolSizeBytes = 1024 * 1024 * BaseImageSetting.getInstance().getBitmapPoolSize(); // 默认30mb 41 | builder.setBitmapPool(new LruBitmapPool(bitmapPoolSizeBytes)); 42 | 43 | //磁盘缓存250mb 44 | int diskCacheSizeBytes = 1024 * 1024 * BaseImageSetting.getInstance().getDiskCacheSize(); //默认缓存文件夹名 GlideAlexCache 缓存大小默认150mb 45 | builder.setDiskCache(new InternalCacheDiskCacheFactory(context, BaseImageSetting.getInstance().getCacheFileName(), diskCacheSizeBytes)); 46 | 47 | // builder.setDefaultRequestOptions(new RequestOptions().format(DecodeFormat.PREFER_RGB_565)); 48 | // builder.setDefaultRequestOptions( 49 | // new RequestOptions() 50 | // .format(DecodeFormat.PREFER_RGB_565) 51 | // .disallowHardwareConfig() 52 | // .disallowHardwareBitmaps()); 53 | } 54 | } -------------------------------------------------------------------------------- /BaseImageLoader/src/main/java/me/alex/baseimageloader/observer/BaseLifeObserver.java: -------------------------------------------------------------------------------- 1 | package me.alex.baseimageloader.observer; 2 | 3 | import android.content.Context; 4 | import android.util.Log; 5 | 6 | import androidx.lifecycle.Lifecycle; 7 | import androidx.lifecycle.LifecycleObserver; 8 | import androidx.lifecycle.OnLifecycleEvent; 9 | 10 | /** 11 | * ================================================ 12 | * Description: 13 | *

14 | * Created by Alex on 2020/12/10 15 | *

16 | * 页面内容介绍: 17 | *

18 | * ================================================ 19 | */ 20 | public class BaseLifeObserver implements LifecycleObserver { 21 | 22 | private Context context; 23 | 24 | public BaseLifeObserver(Context context) { 25 | this.context = context; 26 | } 27 | 28 | @OnLifecycleEvent(Lifecycle.Event.ON_CREATE) 29 | void onCreate() { 30 | showLog("onCreate"); 31 | } 32 | 33 | @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY) 34 | void onDestroy() { 35 | showLog("onDestroy"); 36 | } 37 | 38 | @OnLifecycleEvent(Lifecycle.Event.ON_START) 39 | void onStart() { 40 | showLog("onStart"); 41 | } 42 | 43 | @OnLifecycleEvent(Lifecycle.Event.ON_STOP) 44 | void onStop() { 45 | showLog("onStop"); 46 | } 47 | 48 | @OnLifecycleEvent(Lifecycle.Event.ON_RESUME) 49 | void onResume() { 50 | showLog("onResume"); 51 | } 52 | 53 | @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE) 54 | void onPause() { 55 | showLog("onPause"); 56 | } 57 | 58 | private void showLog(String msg) { 59 | Log.e("===BaseLifeObserver", msg); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /BaseImageLoader/src/main/java/me/alex/baseimageloader/srtategy/BaseImageLoaderStrategy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 JessYan 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 | package me.alex.baseimageloader.srtategy; 17 | 18 | import android.content.Context; 19 | import android.view.ViewGroup; 20 | import android.widget.ImageView; 21 | 22 | import androidx.annotation.LayoutRes; 23 | import androidx.annotation.NonNull; 24 | import androidx.annotation.Nullable; 25 | 26 | import me.alex.baseimageloader.config.BaseImageConfig; 27 | import me.alex.baseimageloader.listener.OnAsListener; 28 | 29 | 30 | /** 31 | * ================================================ 32 | * Description: 33 | *

34 | * Created by Alex on 2020/12/2 0002 35 | *

36 | * 页面内容介绍: 37 | * 图片加载策略,实现 {@link BaseImageLoaderStrategy} 38 | * 并通过 {@link BaseImageLoaderStrategy} 配置后,才可进行图片请求 39 | *

40 | * ================================================ 41 | */ 42 | 43 | public interface BaseImageLoaderStrategy { 44 | 45 | /** 46 | * 加载图片 使用继承自BaseImageConfig的配置 47 | * 48 | * @param context {@link Context} 49 | * @param config {@link BaseImageConfig} 图片加载配置信息 50 | */ 51 | void loadImage(@NonNull Context context, @NonNull T config); 52 | 53 | /** 54 | * 自动加载图片 55 | * @param context {@link Context} 56 | * @param viewGroup xml中的根标签View 57 | * @param zipFileRealPath zip文件夹路径 58 | */ 59 | void autoLoadImage(@NonNull Context context, @NonNull ViewGroup viewGroup, @NonNull String zipFileRealPath); 60 | 61 | /** 62 | * 加载图片同时获取不同格式的资源 63 | * 64 | * @param context {@link Context} 65 | * @param url 资源url或资源文件 66 | * @param listener 获取的资源回调结果 67 | */ 68 | void loadImageAs(@NonNull Context context, @NonNull Object url, @NonNull L listener); 69 | 70 | /** 71 | * @param context {@link Context} 72 | * @param url 资源url或资源文件 73 | * @param imageView 显示的imageView 74 | * @param listener 获取的资源回调结果 75 | */ 76 | void loadImageAs(@NonNull Context context, @NonNull Object url, @Nullable ImageView imageView, @NonNull L listener); 77 | 78 | /** 79 | * 停止加载 或 清除缓存 80 | * 81 | * @param context {@link Context} 82 | * @param config {@link BaseImageConfig} 图片加载配置信息 83 | */ 84 | void clear(@NonNull Context context, @NonNull T config); 85 | 86 | } 87 | -------------------------------------------------------------------------------- /BaseImageLoader/src/main/java/me/alex/baseimageloader/srtategy/CacheStrategy.java: -------------------------------------------------------------------------------- 1 | package me.alex.baseimageloader.srtategy; 2 | 3 | import androidx.annotation.IntDef; 4 | 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | 8 | import me.alex.baseimageloader.config.BaseImageConfig; 9 | 10 | 11 | /** 12 | * ================================================ 13 | * Description: 14 | *

15 | * Created by Alex on 2020/12/2 0002 16 | *

17 | * 页面内容介绍: 18 | * Glide缓存方式 {@link com.bumptech.glide.load.engine.DiskCacheStrategy} 19 | * 0对应DiskCacheStrategy.ALL, 20 | * 1对应DiskCacheStrategy.NONE, 21 | * 2对应DiskCacheStrategy.SOURCE, 22 | * 3对应DiskCacheStrategy.RESULT, 23 | * 4对应DiskCacheStrategy.AUTOMATIC 24 | * 不配置{@link BaseImageConfig}中的缓存策略则默认为 ALL 25 | * 如配置了项目统一配置,则单独设置{@link BaseImageConfig}有更高的优先级 26 | *

27 | * ================================================ 28 | */ 29 | 30 | public interface CacheStrategy { 31 | 32 | int ALL = 0; 33 | 34 | int NONE = 1; 35 | 36 | int RESOURCE = 2; 37 | 38 | int DATA = 3; 39 | 40 | int AUTOMATIC = 4; 41 | 42 | @IntDef({ALL, NONE, RESOURCE, DATA, AUTOMATIC}) 43 | @Retention(RetentionPolicy.SOURCE) 44 | @interface Strategy { 45 | } 46 | 47 | } -------------------------------------------------------------------------------- /BaseImageLoader/src/main/java/me/alex/baseimageloader/tools/AutoLoadTools.java: -------------------------------------------------------------------------------- 1 | package me.alex.baseimageloader.tools; 2 | 3 | import android.graphics.Bitmap; 4 | import android.graphics.drawable.BitmapDrawable; 5 | import android.util.Log; 6 | 7 | import java.io.BufferedInputStream; 8 | import java.io.File; 9 | import java.io.FileInputStream; 10 | import java.io.FileNotFoundException; 11 | import java.io.IOException; 12 | import java.io.InputStream; 13 | import java.util.LinkedHashMap; 14 | import java.util.Map; 15 | import java.util.zip.ZipEntry; 16 | import java.util.zip.ZipException; 17 | import java.util.zip.ZipFile; 18 | import java.util.zip.ZipInputStream; 19 | 20 | import me.alex.baseimageloader.BaseImageLoader; 21 | import me.alex.baseimageloader.config.BaseImageSetting; 22 | 23 | /** 24 | * ================================================ 25 | * Description: 26 | *

27 | * Created by Alex on 2020/12/16 28 | *

29 | * 页面内容介绍: 30 | *

31 | * ================================================ 32 | */ 33 | public class AutoLoadTools { 34 | private int cacheSize = BaseImageSetting.getInstance().getCacheSize(); 35 | 36 | private static AutoLoadTools instance = new AutoLoadTools(); 37 | 38 | public static AutoLoadTools getInstance() { 39 | if (instance == null) { 40 | instance = new AutoLoadTools(); 41 | } 42 | return instance; 43 | } 44 | 45 | public AutoLoadTools() { 46 | 47 | } 48 | 49 | private Map cache = new LinkedHashMap() { 50 | @Override 51 | protected boolean removeEldestEntry(Entry pEldest) { 52 | return size() > cacheSize; 53 | } 54 | }; 55 | 56 | private String cacheZipFilePath = ""; 57 | private File zipFileCache; 58 | private ZipFile zfCache; 59 | 60 | /** 61 | * 读取zip包里的文件(不需要解压zip) 62 | * 63 | * @param zipFilePath      zip包路径 64 | * @param readFileName 需要读取的文件名 65 | * @return 读取结果 66 | */ 67 | public Bitmap readZipFile(String zipFilePath, String readFileName) { 68 | File zipFile = null; 69 | ZipFile zf = null; 70 | try { 71 | if (cacheZipFilePath.isEmpty()) { 72 | zipFile = new File(zipFilePath); 73 | zipFileCache = zipFile; 74 | cacheZipFilePath = zipFilePath; 75 | zf = new ZipFile(zipFileCache); 76 | zfCache = zf; 77 | } 78 | if (zipFilePath.endsWith(cacheZipFilePath)) { 79 | zipFile = zipFileCache; 80 | zf = zfCache; 81 | } 82 | if (zipFile == null) { 83 | zipFile = new File(zipFilePath); 84 | } 85 | if (zf == null) { 86 | zf = new ZipFile(zipFile); 87 | } 88 | if (!cache.containsKey(readFileName)) { 89 | InputStream in = new BufferedInputStream(new FileInputStream(zipFile)); 90 | ZipInputStream zin = new ZipInputStream(in); 91 | ZipEntry ze; 92 | while ((ze = zin.getNextEntry()) != null) { 93 | if (!ze.isDirectory()) { 94 | if (ze.getName().contains(readFileName)) { 95 | cache.put(ze.getName(), new BitmapDrawable(null, zf.getInputStream(ze)).getBitmap()); 96 | } 97 | } 98 | } 99 | zin.closeEntry(); 100 | in.close(); 101 | } 102 | } catch (Exception e) { 103 | e.fillInStackTrace(); 104 | } 105 | // Log.e(">>>cacheSize:", cache.size() + "," + cache); 106 | return cache.get(readFileName); 107 | } 108 | 109 | public int getCacheSize() { 110 | return cache.size(); 111 | } 112 | 113 | } 114 | -------------------------------------------------------------------------------- /BaseImageLoader/src/main/java/me/alex/baseimageloader/tools/Tools.java: -------------------------------------------------------------------------------- 1 | package me.alex.baseimageloader.tools; 2 | 3 | import android.content.Context; 4 | import android.graphics.Bitmap; 5 | import android.graphics.drawable.BitmapDrawable; 6 | import android.util.Log; 7 | 8 | import java.io.BufferedInputStream; 9 | import java.io.BufferedReader; 10 | import java.io.File; 11 | import java.io.FileInputStream; 12 | import java.io.InputStream; 13 | import java.io.InputStreamReader; 14 | import java.util.zip.ZipEntry; 15 | import java.util.zip.ZipFile; 16 | import java.util.zip.ZipInputStream; 17 | 18 | /** 19 | * ================================================ 20 | * Description: 21 | *

22 | * Created by Alex on 2020/12/10 23 | *

24 | * 页面内容介绍: 25 | *

26 | * ================================================ 27 | */ 28 | public class Tools { 29 | /** 30 | * 根据手机的分辨率从 dp 的单位 转成为 px(像素) 31 | */ 32 | public static int dp2px(Context context, float dpValue) { 33 | final float scale = context.getResources().getDisplayMetrics().density; 34 | return (int) (dpValue * scale + 0.5f); 35 | } 36 | 37 | /** 38 | * 根据手机的分辨率从 px(像素) 的单位 转成为 dp 39 | */ 40 | public static int px2dp(Context context, int pxValue) { 41 | final float scale = context.getResources().getDisplayMetrics().density; 42 | return (int) (pxValue / scale + 0.5f); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /BaseImageLoader/src/main/java/me/alex/baseimageloader/transform/RoundAndCenterCropTransform.java: -------------------------------------------------------------------------------- 1 | package me.alex.baseimageloader.transform; 2 | 3 | import android.graphics.Bitmap; 4 | import android.graphics.BitmapShader; 5 | import android.graphics.Canvas; 6 | import android.graphics.Paint; 7 | import android.graphics.RectF; 8 | 9 | import androidx.annotation.NonNull; 10 | 11 | import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool; 12 | import com.bumptech.glide.load.resource.bitmap.BitmapTransformation; 13 | import com.bumptech.glide.load.resource.bitmap.TransformationUtils; 14 | 15 | import java.nio.ByteBuffer; 16 | import java.security.MessageDigest; 17 | import java.util.Arrays; 18 | 19 | /** 20 | * ================================================ 21 | * Description: 22 | *

23 | * Created by Alex on 2020/12/4 24 | *

25 | * 页面内容介绍: 同时实现CenterCrop和自定义4个圆角效果 26 | *

27 | * ================================================ 28 | */ 29 | public class RoundAndCenterCropTransform extends BitmapTransformation { 30 | private static final String ID = RoundAndCenterCropTransform.class.getName(); 31 | private static final byte[] ID_BYTES = ID.getBytes(CHARSET); 32 | private boolean isCenterCrop = false; 33 | private Float[] radiusList = new Float[4]; 34 | 35 | public RoundAndCenterCropTransform(boolean isCenterCrop, float topRight, float topLeft, float bottomRight, float bottomLeft) { 36 | this.isCenterCrop = isCenterCrop; 37 | radiusList[0] = topRight; 38 | radiusList[1] = topLeft; 39 | radiusList[2] = bottomRight; 40 | radiusList[3] = bottomLeft; 41 | } 42 | 43 | @Override 44 | protected Bitmap transform(@NonNull BitmapPool pool, @NonNull Bitmap toTransform, int outWidth, int outHeight) { 45 | if (isCenterCrop) { 46 | Bitmap bitmap = TransformationUtils.centerCrop(pool, toTransform, outWidth, outHeight); 47 | return roundCrop(pool, bitmap); 48 | } else { 49 | return roundCrop(pool, toTransform); 50 | } 51 | } 52 | 53 | private Bitmap roundCrop(BitmapPool pool, Bitmap source) { 54 | if (source == null) return null; 55 | 56 | Bitmap result = pool.get(source.getWidth(), source.getHeight(), Bitmap.Config.ARGB_8888); 57 | 58 | Canvas canvas = new Canvas(result); 59 | Paint paint = new Paint(); 60 | paint.setShader(new BitmapShader(source, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP)); 61 | paint.setAntiAlias(true); 62 | RectF rectF = new RectF(0f, 0f, source.getWidth(), source.getHeight()); 63 | // 左上 64 | canvas.save(); 65 | canvas.clipRect(0, 0, canvas.getWidth() / 2, canvas.getHeight() / 2); 66 | canvas.drawRoundRect(rectF, radiusList[0], radiusList[0], paint); 67 | canvas.restore(); 68 | // 右上 69 | canvas.save(); 70 | canvas.clipRect(canvas.getWidth() / 2, 0, canvas.getWidth(), canvas.getHeight() / 2); 71 | canvas.drawRoundRect(rectF, radiusList[1], radiusList[1], paint); 72 | canvas.restore(); 73 | // 右下 74 | canvas.save(); 75 | canvas.clipRect(canvas.getWidth() / 2, canvas.getHeight() / 2, canvas.getWidth(), canvas.getHeight()); 76 | canvas.drawRoundRect(rectF, radiusList[2], radiusList[2], paint); 77 | canvas.restore(); 78 | // 左下 79 | canvas.save(); 80 | canvas.clipRect(0, canvas.getHeight() / 2, canvas.getWidth() / 2, canvas.getHeight()); 81 | canvas.drawRoundRect(rectF, radiusList[3], radiusList[3], paint); 82 | canvas.restore(); 83 | return result; 84 | } 85 | 86 | @Override 87 | public void updateDiskCacheKey(@NonNull MessageDigest messageDigest) { 88 | messageDigest.update(ID.getBytes(CHARSET)); 89 | byte[] radiusData = ByteBuffer.allocate(4).putInt(Arrays.hashCode(radiusList)).array(); 90 | messageDigest.update(radiusData); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /BaseImageLoader/src/main/java/me/alex/baseimageloader/transform/RoundedCornersTransform.java: -------------------------------------------------------------------------------- 1 | package me.alex.baseimageloader.transform; 2 | 3 | import android.graphics.Bitmap; 4 | import android.graphics.BitmapShader; 5 | import android.graphics.Canvas; 6 | import android.graphics.Paint; 7 | import android.graphics.RectF; 8 | import android.graphics.Shader; 9 | 10 | import androidx.annotation.NonNull; 11 | 12 | import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool; 13 | import com.bumptech.glide.load.resource.bitmap.BitmapTransformation; 14 | 15 | import java.nio.ByteBuffer; 16 | import java.security.MessageDigest; 17 | import java.util.Arrays; 18 | 19 | /** 20 | * ================================================ 21 | * Description: 22 | *

23 | * Created by Alex on 2020/12/4 24 | *

25 | * 页面内容介绍: 单独控制4个圆角效果 与 centerCrop不兼容 26 | *

27 | * ================================================ 28 | */ 29 | public class RoundedCornersTransform extends BitmapTransformation { 30 | 31 | private static final String ID = RoundedCornersTransform.class.getName(); 32 | private static final byte[] ID_BYTES = ID.getBytes(CHARSET); 33 | 34 | private Float[] radiusList = new Float[4]; 35 | private boolean isCenterCrop = false; 36 | 37 | /** 38 | * 默认构造方法 39 | * 40 | * @param topRight 左上圆角 41 | * @param topLeft 右上圆角 42 | * @param bottomRight 左下圆角 43 | * @param bottomLeft 右下圆角 44 | */ 45 | public RoundedCornersTransform(float topRight, float topLeft, float bottomRight, float bottomLeft) { 46 | radiusList[0] = topRight; 47 | radiusList[1] = topLeft; 48 | radiusList[2] = bottomRight; 49 | radiusList[3] = bottomLeft; 50 | } 51 | 52 | @Override 53 | protected Bitmap transform(@NonNull BitmapPool pool, @NonNull Bitmap toTransform, int outWidth, int outHeight) { 54 | //获取加载的图片 55 | Bitmap bitmap = pool.get(toTransform.getWidth(), toTransform.getHeight(), Bitmap.Config.ARGB_8888); 56 | Canvas canvas = new Canvas(bitmap); 57 | Paint paint = new Paint(); 58 | //关联画笔绘制的原图bitmap 59 | BitmapShader shader = new BitmapShader(toTransform, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); 60 | paint.setShader(shader); 61 | paint.setAntiAlias(true); 62 | RectF rectF = new RectF(0, 0, canvas.getWidth(), canvas.getHeight()); 63 | // 左上 64 | canvas.save(); 65 | canvas.clipRect(0, 0, canvas.getWidth() / 2, canvas.getHeight() / 2); 66 | canvas.drawRoundRect(rectF, radiusList[0], radiusList[0], paint); 67 | canvas.restore(); 68 | // 右上 69 | canvas.save(); 70 | canvas.clipRect(canvas.getWidth() / 2, 0, canvas.getWidth(), canvas.getHeight() / 2); 71 | canvas.drawRoundRect(rectF, radiusList[1], radiusList[1], paint); 72 | canvas.restore(); 73 | // 右下 74 | canvas.save(); 75 | canvas.clipRect(canvas.getWidth() / 2, canvas.getHeight() / 2, canvas.getWidth(), canvas.getHeight()); 76 | canvas.drawRoundRect(rectF, radiusList[2], radiusList[2], paint); 77 | canvas.restore(); 78 | // 左下 79 | canvas.save(); 80 | canvas.clipRect(0, canvas.getHeight() / 2, canvas.getWidth() / 2, canvas.getHeight()); 81 | canvas.drawRoundRect(rectF, radiusList[3], radiusList[3], paint); 82 | canvas.restore(); 83 | return bitmap; 84 | } 85 | 86 | 87 | @Override 88 | public void updateDiskCacheKey(@NonNull MessageDigest messageDigest) { 89 | messageDigest.update(ID.getBytes(CHARSET)); 90 | byte[] radiusData = ByteBuffer.allocate(4).putInt(Arrays.hashCode(radiusList)).array(); 91 | messageDigest.update(radiusData); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /BaseImageLoader/src/main/java/me/alex/baseimageloader/view/BaseImageView.java: -------------------------------------------------------------------------------- 1 | package me.alex.baseimageloader.view; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.content.Context; 5 | import android.content.res.TypedArray; 6 | import android.util.AttributeSet; 7 | import android.widget.ImageView; 8 | 9 | import androidx.annotation.NonNull; 10 | import androidx.annotation.Nullable; 11 | 12 | import me.alex.baseimageloader.BaseImageLoader; 13 | import me.alex.baseimageloader.R; 14 | import me.alex.baseimageloader.config.BaseImageConfig; 15 | import me.alex.baseimageloader.config.BaseImageSetting; 16 | import me.alex.baseimageloader.srtategy.CacheStrategy; 17 | import me.alex.baseimageloader.tools.Tools; 18 | 19 | 20 | /** 21 | * ================================================ 22 | * Description: 23 | *

24 | * Created by Alex on 2020/12/10 25 | *

26 | * 页面内容介绍: 27 | *

28 | * ================================================ 29 | */ 30 | @SuppressLint("AppCompatCustomView") 31 | public class BaseImageView extends ImageView { 32 | private Context context; 33 | private BaseImageLoader loader; 34 | private BaseImageConfig config = new BaseImageConfig(); 35 | /** 36 | * 图片资源指向 37 | */ 38 | protected Object url; 39 | /** 40 | * 加载网络图片之前占位图片 41 | */ 42 | protected int placeholder; 43 | 44 | /** 45 | * 错误占位图片 46 | */ 47 | protected int errorPic; 48 | 49 | /** 50 | * 是否使用淡入淡出过渡动画 51 | */ 52 | protected boolean isCrossFade; 53 | 54 | /** 55 | * 是否将图片剪切为 CenterCrop 56 | */ 57 | protected boolean isCenterCrop; 58 | 59 | /** 60 | * 是否将图片剪切为圆形 61 | */ 62 | protected boolean isCircle; 63 | 64 | /** 65 | * 左上 圆角 66 | */ 67 | protected int topRightRadius; 68 | 69 | /** 70 | * 右上 圆角 71 | */ 72 | protected int topLeftRadius; 73 | 74 | /** 75 | * 左下 圆角 76 | */ 77 | protected int bottomRightRadius; 78 | 79 | /** 80 | * 右下 圆角 81 | */ 82 | protected int bottomLeftRadius; 83 | 84 | /** 85 | * 通用圆角 86 | */ 87 | protected int radius; 88 | 89 | /** 90 | * 是否以bitmap加载 91 | */ 92 | protected boolean asBitmap; 93 | 94 | /** 95 | * 缓存类型 默认为通用配置中的模式 96 | */ 97 | private @CacheStrategy.Strategy 98 | int cacheStrategy; 99 | 100 | public BaseImageView(@NonNull Context context) { 101 | super(context); 102 | } 103 | 104 | public BaseImageView(@NonNull Context context, @Nullable AttributeSet attrs) { 105 | super(context, attrs); 106 | init(context, attrs); 107 | } 108 | 109 | public BaseImageView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { 110 | super(context, attrs, defStyleAttr); 111 | } 112 | 113 | private void init(@NonNull Context context, @Nullable AttributeSet attrs) { 114 | this.context = context; 115 | loader = new BaseImageLoader(); 116 | TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.BaseImageView, 0, 0); 117 | //资源指向 118 | url = typedArray.getString(R.styleable.BaseImageView_url); 119 | //占位图 120 | placeholder = typedArray.getResourceId(R.styleable.BaseImageView_placeholder, 0); 121 | //错误图 122 | errorPic = typedArray.getResourceId(R.styleable.BaseImageView_errorPic, 0); 123 | //是否淡出淡入 124 | isCrossFade = typedArray.getBoolean(R.styleable.BaseImageView_isCrossFade, false); 125 | //centerCrop 126 | isCenterCrop = typedArray.getBoolean(R.styleable.BaseImageView_isCenterCrop, false); 127 | //圆形裁剪 128 | isCircle = typedArray.getBoolean(R.styleable.BaseImageView_isCircle, false); 129 | 130 | //左上 圆角 131 | topRightRadius = Tools.px2dp(context, typedArray.getDimensionPixelSize(R.styleable.BaseImageView_topRightRadius, 0)); 132 | 133 | //右上 圆角 134 | topLeftRadius = Tools.px2dp(context, typedArray.getDimensionPixelSize(R.styleable.BaseImageView_topLeftRadius, 0)); 135 | 136 | //左下 圆角 137 | bottomRightRadius = Tools.px2dp(context, typedArray.getDimensionPixelSize(R.styleable.BaseImageView_bottomRightRadius, 0)); 138 | 139 | //右下 圆角 140 | bottomLeftRadius = Tools.px2dp(context, typedArray.getDimensionPixelSize(R.styleable.BaseImageView_bottomLeftRadius, 0)); 141 | 142 | //通用圆角 143 | radius = Tools.px2dp(context, typedArray.getDimensionPixelSize(R.styleable.BaseImageView_radius, 0)); 144 | 145 | //bitmap格式加载 146 | asBitmap = typedArray.getBoolean(R.styleable.BaseImageView_asBitmap, false); 147 | 148 | //缓存策略 149 | cacheStrategy = typedArray.getInt(R.styleable.BaseImageView_cacheStrategy, BaseImageSetting.getInstance().getCacheStrategy()); 150 | 151 | initConfig(); 152 | if (url != null && !url.equals("")) { 153 | loader.loadImage(context, config); 154 | } 155 | 156 | typedArray.recycle(); 157 | } 158 | 159 | private void initConfig() { 160 | config.setUrl(url); 161 | config.setImageView(BaseImageView.this); 162 | // getLifecycle().addObserver(new BaseLifeObserver(context)); 163 | //缓存类型 164 | //如果BaseImageConfig缓存策略为默认的ALL 则使用默认缓存策略 165 | config.setCacheStrategy(cacheStrategy); 166 | 167 | //占位图 168 | if (placeholder != 0) { 169 | config.setPlaceholder(placeholder); 170 | } 171 | 172 | //错误图 173 | if (errorPic != 0) { 174 | config.setErrorPic(errorPic); 175 | } 176 | 177 | //是否淡出淡入 178 | config.setCrossFade(isCrossFade); 179 | 180 | //centerCrop 181 | if (isCenterCrop) { 182 | config.setCenterCrop(); 183 | } 184 | //是否将图片剪切为圆形 185 | if (isCircle) { 186 | config.setCircle(); 187 | } 188 | config.setTopRightRadius(topRightRadius); 189 | config.setTopLeftRadius(topLeftRadius); 190 | config.setBottomRightRadius(bottomRightRadius); 191 | config.setBottomLeftRadius(bottomLeftRadius); 192 | config.setRadius(radius); 193 | } 194 | 195 | @SuppressLint("CheckResult") 196 | public void load(Object url) { 197 | this.url = url; 198 | config.setUrl(url); 199 | loader.loadImage(context, config); 200 | } 201 | 202 | public int getPlaceholder() { 203 | return placeholder; 204 | } 205 | 206 | public void setPlaceholder(int placeholder) { 207 | this.placeholder = placeholder; 208 | } 209 | 210 | public int getErrorPic() { 211 | return errorPic; 212 | } 213 | 214 | public void setErrorPic(int errorPic) { 215 | this.errorPic = errorPic; 216 | } 217 | 218 | public boolean isCrossFade() { 219 | return isCrossFade; 220 | } 221 | 222 | public void setCrossFade(boolean crossFade) { 223 | isCrossFade = crossFade; 224 | } 225 | 226 | public boolean isCenterCrop() { 227 | return isCenterCrop; 228 | } 229 | 230 | public void setCenterCrop(boolean centerCrop) { 231 | isCenterCrop = centerCrop; 232 | } 233 | 234 | public boolean isCircle() { 235 | return isCircle; 236 | } 237 | 238 | public void setCircle(boolean circle) { 239 | isCircle = circle; 240 | } 241 | 242 | public int getTopRightRadius() { 243 | return topRightRadius; 244 | } 245 | 246 | public void setTopRightRadius(int topRightRadius) { 247 | this.topRightRadius = topRightRadius; 248 | } 249 | 250 | public int getTopLeftRadius() { 251 | return topLeftRadius; 252 | } 253 | 254 | public void setTopLeftRadius(int topLeftRadius) { 255 | this.topLeftRadius = topLeftRadius; 256 | } 257 | 258 | public int getBottomRightRadius() { 259 | return bottomRightRadius; 260 | } 261 | 262 | public void setBottomRightRadius(int bottomRightRadius) { 263 | this.bottomRightRadius = bottomRightRadius; 264 | } 265 | 266 | public int getBottomLeftRadius() { 267 | return bottomLeftRadius; 268 | } 269 | 270 | public void setBottomLeftRadius(int bottomLeftRadius) { 271 | this.bottomLeftRadius = bottomLeftRadius; 272 | } 273 | 274 | public int getRadius() { 275 | return radius; 276 | } 277 | 278 | public void setRadius(int radius) { 279 | this.radius = radius; 280 | } 281 | 282 | public int getCacheStrategy() { 283 | return cacheStrategy; 284 | } 285 | 286 | public void setCacheStrategy(int cacheStrategy) { 287 | this.cacheStrategy = cacheStrategy; 288 | } 289 | 290 | public BaseImageConfig getConfig() { 291 | return config; 292 | } 293 | 294 | public void setUrl(String url) { 295 | load(url); 296 | } 297 | } 298 | -------------------------------------------------------------------------------- /BaseImageLoader/src/main/res/values/attrs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Demo效果图 2 | ![话不多说先放图](https://images.xiaozhuanlan.com/photo/2020/5bfda51d6beaa59c92358760212931b2.png) 3 | # 说明 4 | 支持加载网络图片(String格式url)/本地资源(mipmap和drawable)/网络.9图片/gif加载/自定义样式(圆形/圆角/centerCrop)/dataBinding 5 | 6 | v1.1.0起支持读取zip中图片加载至任意View中,无需解压. 7 | 8 | 更多使用方法和示例代码请下载demo源码查看 9 | 10 | github : [BaseImageLoader](https://github.com/AlexFugui/BaseImageLoader) 11 | 12 | # 设计说明 13 | 根据`BaseImageLoader`持有图片View层的`context`和`BaseImageConfig`类实现Glide原生的生命周期感知和多样化的自定义配置加载 14 | 15 | `BaseImageConfig`使用建造者模式,使用更灵活更方便,也可自行继承`BaseImageConfig`减少类名长度和实现自定义功能 16 | 17 | # 主要功能 18 | - loadImage 19 | 动态配置config加载你需求的资源图片 20 | - loadImageAs 21 | 获取网络url返回的资源,可获取`drawable`/`bitmap`/`file`/`gif`四种文件格式,可控知否获取资源的同时加载到View上 22 | - clear 23 | 取消加载或清除内存/储存中的缓存 24 | - BaseImageView 25 | 与动态config完全相同功能的自定义ImageView,支持xml中自定义属性配置各种加载需求 26 | - autoLoadImage 27 | 开发者自行指定zip压缩包的路径.并绑定当前View的根布局,配合View的tag字段自动加载zip中符合tag中图片名称的图片 28 | 29 | # 添加依赖 30 | ``implementation 'com.alex:BaseImageLoader:1.1.0'`` 31 | 32 | # 使用的依赖库 33 | - api 'com.github.bumptech.glide:glide:4.11.0' 34 | - annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0' 35 | 36 | 开发者如需剔除重复依赖自行处理 37 | 38 | # 使用说明 39 | ## 1.添加权限 40 | 需要添问网络和内存读写权限 41 | 42 | ## 2.项目通用配置 43 | 功能配置全部可选,如不配置则: 44 | 45 | 默认内存缓存大小20mb 46 | 47 | 默认bitmap池缓存30mb 48 | 49 | 默认硬盘缓存250mb 50 | 51 | 默认缓存文件夹名称`BaseImageLoaderCache` 52 | 53 | 默认缓存策略为`AUTOMATIC`,自动模式 54 | 55 | ```java 56 | BaseImageSetting.getInstance() 57 | .setMemoryCacheSize(30)//设置内存缓存大小 单位mb 58 | .setBitmapPoolSize(50)//设置bitmap池缓存大小 单位mb 59 | .setDiskCacheSize(80)//设置储存储存缓存大小 单位mb 60 | .setLogLevel(Log.ERROR)//设置log等级 61 | .setPlaceholder(R.drawable.ic_baseline_adb_24)//设置通用占位图片,全项目生效 62 | .setErrorPic(R.mipmap.ic_launcher)//设置通用加载错误图片,全项目生效 63 | .setCacheFileName("BaseImageLoaderDemo")//设置储存缓存文件夹名称,api基于Glide v4 64 | .setCacheStrategy(CacheStrategy.AUTOMATIC)//设置缓存策略 65 | .setCacheSize(50)//设置自动加载图片缓存数量,默认50 66 | ; 67 | ``` 68 | 69 | ## 3.使用 70 | ### 1.获取`BaseImageLoader`对象 71 | 根据开发者项目设计模式,MVC/MVP/MVVM自行获取`BaseImageLoader`类对象,并自行管理生命周期. 72 | 73 | `BaseImageLoader`自行提供单例,`BaseImageLoader.getInstance();` 74 | 75 | ### 2.加载至ImageView(包括但不限于任何继承于View或ViewGroup的view) 76 | ```java 77 | BaseImageLoader mImageLoader = new BaseImageLoader(); 78 | mImageLoader.loadImage(this, ImageConfig.builder() 79 | .url(Uri.parse(imageUrl))//url 80 | .imageView(img1)//imageView 81 | .placeholder(R.drawable.ic_baseline_adb_24)//占位图 82 | .errorPic(R.mipmap.ic_launcher)//加载错误图片 83 | .cacheStrategy(CacheStrategy.ALL)//缓存策略 84 | .centerCrop(true)//centerCrop 85 | .crossFade(true)//淡出淡入 86 | .isCircle(true)//是否圆形显示 87 | .setAsBitmap(true)//是否以bitmap加载图片,默认为drawable格式 88 | .setRadius(30)//设置通用圆角,单位dp 89 | .setTopRightRadius(10)//左上圆角,单位dp 90 | .setTopLeftRadius(20)//右上圆角,单位dp 91 | .setBottomRightRadius(30)//左下圆角,单位dp 92 | .setBottomLeftRadius(40)//右下圆角,单位dp 93 | .show()); 94 | ``` 95 | ### **注意:** 96 | 97 | 避免过度绘制和二次绘制,其中优先级 98 | 99 | isCircle(true) > setRadius(int) > setTopRightRadius(int) = setTopLeftRadius(int) = setBottomRightRadius(int) = setBottomLeftRadius(int) 100 | 101 | 1. 设置isCircle(true)会使通用圆角设置不生效,减少绘制次数 102 | 103 | 2. 设置setRadius()会使分别控制单独圆角不生效,减少绘制次数 104 | 105 | ### 3.资源文件直出 106 | 方法一: 107 | ```java 108 | /** 109 | * 加载图片同时获取不同格式的资源 110 | * @param context {@link Context} 111 | * @param url 资源url或资源文件 112 | * @param listener 获取的资源回调结果 113 | */ 114 | void loadImageAs(@NonNull Context context, @NonNull Object url, @NonNull L listener); 115 | 116 | /** 117 | * 根据图片类型直出对象 118 | * 需要根据参数类型判断获取的字段,比如使用OnBitmapResult,就只有getBitmap方法不为null 119 | * 根据是否传入imageView是否直接显示图片,如果想自己处理过资源再加载则不传入imageView 120 | * 121 | */ 122 | mImageLoader.loadImageAs(this, imageUrlTest, new OnBitmapResult() { 123 | @Override 124 | public void OnResult(ImageResult result) { 125 | Log.e("result", result.getBitmap() + ""); 126 | } 127 | }); 128 | ``` 129 | 130 | 方法二: 131 | ```java 132 | /** 133 | * 134 | * @param context {@link Context} 135 | * @param url 资源url或资源文件 136 | * @param imageView 显示的imageView 137 | * @param listener 获取的资源回调结果 138 | */ 139 | void loadImageAs(@NonNull Context context, @NonNull Object url, @Nullable ImageView imageView, @NonNull L listener); 140 | 141 | /** 142 | * 加载图片且获得bitmap格式图片 且以 imageView.setImageBitmap(bitmap) 模式加载图片 143 | */ 144 | mImageLoader.loadImageAs(this, imageUrlTest, img14, new OnBitmapResult() { 145 | @Override 146 | public void OnResult(ImageResult result) { 147 | Log.e("result", result.getBitmap() + ""); 148 | } 149 | }); 150 | 151 | /** 152 | * 使用File类型获取result时,默认result.getFile()是在设置的cache目录中 153 | * 加载图片且获得File文件 但是以Glide默认方式加载图片(drawable格式) imageView.setImageDrawable(drawable); 154 | */ 155 | mImageLoader.loadImageAs(this, imageUrlTest, img14, new OnFileResult() { 156 | @Override 157 | public void OnResult(ImageResult result) { 158 | Log.e("result", result.getFile() + ""); 159 | } 160 | }); 161 | 162 | /** 163 | * 加载gif且获得gif文件 以 imageView.setImageDrawable(GifDrawable); 模式加载图片 164 | */ 165 | mImageLoader.loadImageAs(this, gifUrl, img14, new OnGifResult() { 166 | @Override 167 | public void OnResult(ImageResult result) { 168 | Log.e("result", result.getGif() + ""); 169 | } 170 | }); 171 | 172 | /** 173 | * 加载图片且获得drawable格式图片 以Glide默认方式加载图片(drawable格式) imageView.setImageDrawable(drawable); 174 | */ 175 | mImageLoader.loadImageAs(this, imageUrlTest, img14, new OnDrawableResult() { 176 | @Override 177 | public void OnResult(ImageResult result) { 178 | Log.e("result", result.getDrawable() + ""); 179 | } 180 | }); 181 | ``` 182 | ### 4.自定义BaseImageView 183 | 184 | xml中: 185 | 186 | ```xml 187 | 203 | ``` 204 | api与代码设置相同 205 | 206 | 支持DataBinding: 207 | ```xml 208 | 212 | ``` 213 | 详见demo中dataBinding简单使用 214 | 优先级规则同上 215 | 216 | ### 4.自动加载图片 217 | ```java 218 | String ZIP_FILE_PATH = me.getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS).getAbsolutePath() + File.separator + "imgs.zip"; 219 | 220 | //ZIP_FILE_PATH真实路径为:/storage/emulated/0/Android/data/me.alex.baseimageloaderdemo/files/Documents/imgs.zip 221 | 222 | ScrollView autoLoadViewGroup = findViewById(R.id.autoLoadViewGroup); 223 | 224 | BaseImageLoader.getInstance().autoLoadImage(this, autoLoadViewGroup, ZIP_FILE_PATH); 225 | ``` 226 | xml中 227 | ```xml 228 | 229 | 237 | 238 | 243 | 244 | 249 | 250 | 256 | 257 | 262 | 263 | 268 | 269 | 270 | ``` 271 | - zip文件夹位置开发者自行设置,demo中是将assets中的imgs.zip复制至指定路径然后加载. 272 | - 配合xml中View对象的tag参数匹配zip中的文件名称. 273 | - 如使用BaseImageView+tag加载图片,支持自定义属性 274 | - Demo中加载6张图片耗时60ms左右 275 | - 本功能开发本意是减少apk体积 , 减少重复资源下载 , 开发者可在业务流程中自行处理zip文件的下载和存放位置 , 自行处理数据安全 276 | 277 | # 参数说明 278 | **1.BaseImageSetting:** 279 | | 函数名 | 入参类型 |参数说明| 280 | | -------- | -------- | -------- | 281 | | setMemoryCacheSize() | int | 设置内存缓存大小 单位mb | 282 | | setBitmapPoolSize() | int | 设置bitmap池缓存大小 单位mb | 283 | | setDiskCacheSize() | int | 设置储存储存缓存大小 单位mb | 284 | | setLogLevel() | int | 设置框架日志打印等级,详看android.util.Log类与Glide v4文档 | 285 | | placeholder() | int | v1.0.0版本仅支持resource类型int参数 | 286 | | errorPic() | int | v1.0.0版本仅支持resource类型int参数 | 287 | | setCacheFileName() | String | 设置储存缓存文件夹名称,api基于Glide v4 | 288 | 289 | **2.BaseImageLoader:** 290 | 291 | ```java 292 | /** 293 | * 加载图片 使用继承自BaseImageConfig的配置 294 | * 295 | * @param context {@link Context} 296 | * @param config {@link BaseImageConfig} 图片加载配置信息 297 | */ 298 | void loadImage(@NonNull Context context, @NonNull T config); 299 | ``` 300 | ```java 301 | /** 302 | * 自动加载图片 303 | * @param context {@link Context} 304 | * @param viewGroup xml中的根标签View 305 | * @param zipFileRealPath zip文件夹路径 306 | */ 307 | void autoLoadImage(@NonNull Context context, @NonNull ViewGroup viewGroup, @NonNull String zipFileRealPath); 308 | ``` 309 | ```java 310 | /** 311 | * 加载图片同时获取不同格式的资源 312 | * @param context {@link Context} 313 | * @param url 资源url或资源文件 314 | * @param listener 获取的资源回调结果 315 | */ 316 | void loadImageAs(@NonNull Context context, @NonNull Object url, @NonNull L listener); 317 | ``` 318 | ```java 319 | /** 320 | * 321 | * @param context {@link Context} 322 | * @param url 资源url或资源文件 323 | * @param imageView 显示的imageView 324 | * @param listener 获取的资源回调结果 325 | */ 326 | void loadImageAs(@NonNull Context context, @NonNull Object url, @Nullable ImageView imageView, @NonNull L listener); 327 | ``` 328 | ```java 329 | /** 330 | * 停止加载 或 清除缓存 331 | * 332 | * @param context {@link Context} 333 | * @param config {@link BaseImageConfig} 图片加载配置信息 334 | */ 335 | void clear(@NonNull Context context, @NonNull T config); 336 | ``` 337 | 338 | **3.BaseImageConfig:** 339 | | 函数名 | 入参类型类型 |参数说明| 340 | | -------- | -------- | -------- | 341 | | builder() | 无 | BaseImageConfig使用建造者模式,BaseImageConfig默认空构造方法 | 342 | | url() (代码使用) | Object | 支持原生Glide中所有类型 *1 | 343 | | url() (xml中) | Object | 支持原生Glide中所有类型,且支持resource类型 | 344 | | imageView() | View | 支持任何继承与View和ViewGroup的View *2 | 345 | | placeholder() | int | v1.0.0版本仅支持resource类型int参数 | 346 | | errorPic() | int | v1.0.0版本仅支持resource类型int参数 | 347 | | cacheStrategy() | int | 设置缓存策略,详看CacheStrategy类与Glide v4文档 | 348 | | setRadius() | int | 设置通用圆角 单位dp | 349 | | setTopRightRadius() | int | 设置左上圆角 单位dp | 350 | | setTopLeftRadius() | int | 设置右上圆角 单位dp | 351 | | setBottomRightRadius() | int | 设置左下圆角 单位dp | 352 | | setBottomLeftRadius() | int | 设置右下圆角 单位dp | 353 | | centerCrop() | Boolean | true为居中裁剪 | 354 | | crossFade() | Boolean | true为开启淡出淡入 | 355 | | isCircle() | Boolean | true为开启圆形裁剪 | 356 | | setAsBitmap() | Boolean | true为以bitmap格式加载图片 | 357 | | clearMemory() | Boolean | true为清除内存中缓存,仅在BaseImageLoader.clear()中生效 | 358 | | clearDiskCache() | Boolean | true为清除储存中缓存,仅在BaseImageLoader.clear()中生效 | 359 | | show() | 无 | BaseImageConfig使用建造者模式,用于new BaseImageConfig对象 | 360 | 361 | **1.支持的urlModel类型 :** 362 | `Bitmap`/`Drawable`/`String`/`Uri`/`File`/`Integer resourceId`/`URL`/`byte[]`/`Object` 363 | **2.ImageView的子类使用Glide默认的 setImageDrawable() 方式实现; 其他继承VIew或ViewGroup的以setBackground() 方式实现** 364 | 365 | 366 | ### [附 Glide v4 中文文档](https://muyangmin.github.io/glide-docs-cn/) 367 | 368 | ![ ](https://images.xiaozhuanlan.com/photo/2020/6ac26499784a44871d0f8d988b53a6cc.png) 369 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 29 5 | buildToolsVersion "29.0.3" 6 | 7 | defaultConfig { 8 | applicationId "me.alex.baseimageloaderdemo" 9 | minSdkVersion 19 10 | targetSdkVersion 29 11 | versionCode 1 12 | versionName "1.0" 13 | 14 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 15 | } 16 | 17 | buildTypes { 18 | release { 19 | minifyEnabled false 20 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 21 | } 22 | } 23 | dataBinding { 24 | android.buildFeatures.dataBinding = true 25 | } 26 | } 27 | 28 | dependencies { 29 | implementation fileTree(dir: "libs", include: ["*.jar"]) 30 | api 'androidx.appcompat:appcompat:1.2.0' 31 | implementation 'com.kongzue.baseframeworkx:baseframework:6.7.7' 32 | implementation 'com.kongzue.tabbarx:tabbar:1.5.4' 33 | implementation project(path: ':BaseImageLoader') 34 | // implementation 'com.alex:BaseImageLoader:1.1.0' 35 | } -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 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/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/assets/imgs.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexFugui/BaseImageLoader/1422c4b2e91acb7295da56200a651de64f931803/app/src/main/assets/imgs.zip -------------------------------------------------------------------------------- /app/src/main/java/me/alex/baseimageloaderdemo/App.java: -------------------------------------------------------------------------------- 1 | package me.alex.baseimageloaderdemo; 2 | 3 | import android.app.Application; 4 | import android.util.Log; 5 | 6 | import com.kongzue.baseframework.BaseApp; 7 | 8 | import me.alex.baseimageloader.config.BaseImageSetting; 9 | import me.alex.baseimageloader.srtategy.CacheStrategy; 10 | 11 | 12 | /** 13 | * ================================================ 14 | * Description: 15 | *

16 | * Created by Alex on 2020/12/2 0002 17 | *

18 | * 页面内容介绍: 19 | * 设置缓存大小,单位为MB 不设置默认为MemoryCache是20mb BitmapPool是30mb DiskCache是250mb 20 | * setCacheFileName();设置缓存文件夹使用Glide原生api 文档说明: Creates an {@link com.bumptech.glide.disklrucache.DiskLruCache} based disk cache in the internal disk cache directory. 21 | * setCacheStrategy(); 缓存类型详看{@link com.bumptech.glide.load.engine.DiskCacheStrategy} 22 | * 23 | *

24 | * ================================================ 25 | */ 26 | public class App extends BaseApp { 27 | @Override 28 | public void init() { 29 | BaseImageSetting.getInstance() 30 | .setMemoryCacheSize(30)//设置内存缓存大小 单位mb 31 | .setBitmapPoolSize(50)//设置bitmap池缓存大小 单位mb 32 | .setDiskCacheSize(80)//设置储存储存缓存大小 单位mb 33 | .setLogLevel(Log.ERROR)//设置log等级 34 | .setPlaceholder(R.drawable.ic_baseline_adb_24)//设置通用占位图片,全项目生效 35 | .setErrorPic(R.mipmap.ic_launcher)//设置通用加载错误图片,全项目生效 36 | .setCacheFileName("BaseImageLoaderDemo")//设置储存缓存文件夹名称,api基于Glide v4 37 | .setCacheStrategy(CacheStrategy.AUTOMATIC)//设置缓存策略 38 | .setCacheSize(50)//设置自动加载图片缓存数量,默认50 39 | ; 40 | 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /app/src/main/java/me/alex/baseimageloaderdemo/ImageConfig.java: -------------------------------------------------------------------------------- 1 | package me.alex.baseimageloaderdemo; 2 | 3 | import me.alex.baseimageloader.config.BaseImageConfig; 4 | import me.alex.baseimageloader.config.Builder; 5 | 6 | /** 7 | * ================================================ 8 | * Description: 9 | *

10 | * Created by Alex on 2020/12/4 0004 11 | *

12 | * 页面内容介绍: 13 | * 继承自 {@link BaseImageConfig} 实现了基本功能需求字段 14 | * 如需添加一个自定义功能 15 | * 自行实现构造方法并且在自定义的{@link BaseImageLoaderStrategy}中重写loadImage接口实现方法(暂时不建议重写BaseImageLoaderStrategy,自定义类继承BaseImageConfig是建议的方式) 16 | * 参照{@link BaseImageLoader} 17 | *

18 | * ================================================ 19 | */ 20 | public class ImageConfig extends BaseImageConfig { 21 | 22 | private boolean isVisibility; 23 | 24 | public void setVisibility(boolean visibility) { 25 | isVisibility = visibility; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/src/main/java/me/alex/baseimageloaderdemo/ImageData.java: -------------------------------------------------------------------------------- 1 | package me.alex.baseimageloaderdemo; 2 | 3 | 4 | import androidx.databinding.BaseObservable; 5 | import androidx.databinding.Bindable; 6 | 7 | /** 8 | * ================================================ 9 | * Description: 10 | *

11 | * Created by Alex on 2020/12/11 0011 12 | *

13 | * 页面内容介绍: DataBinding JavaBean 14 | *

15 | * ================================================ 16 | */ 17 | public class ImageData extends BaseObservable { 18 | private String content; 19 | private String imageUrl; 20 | 21 | @Bindable 22 | public String getContent() { 23 | return content; 24 | } 25 | 26 | public void setContent(String content) { 27 | this.content = content; 28 | notifyPropertyChanged(BR.content); 29 | } 30 | 31 | @Bindable 32 | public String getImageUrl() { 33 | return imageUrl; 34 | } 35 | 36 | public void setImageUrl(String imageUrl) { 37 | this.imageUrl = imageUrl; 38 | notifyPropertyChanged(BR.imageUrl); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /app/src/main/java/me/alex/baseimageloaderdemo/MainActivity.java: -------------------------------------------------------------------------------- 1 | package me.alex.baseimageloaderdemo; 2 | 3 | import android.view.View; 4 | 5 | import com.kongzue.baseframework.BaseActivity; 6 | import com.kongzue.baseframework.interfaces.DarkStatusBarTheme; 7 | import com.kongzue.baseframework.interfaces.FragmentLayout; 8 | import com.kongzue.baseframework.interfaces.Layout; 9 | import com.kongzue.baseframework.util.FragmentChangeUtil; 10 | import com.kongzue.baseframework.util.JumpParameter; 11 | import com.kongzue.tabbar.Tab; 12 | import com.kongzue.tabbar.TabBarView; 13 | import com.kongzue.tabbar.interfaces.OnTabChangeListener; 14 | 15 | import java.util.ArrayList; 16 | import java.util.List; 17 | 18 | import me.alex.baseimageloader.tools.AutoLoadTools; 19 | import me.alex.baseimageloaderdemo.fragment.AutoLoadFragment; 20 | import me.alex.baseimageloaderdemo.fragment.BaseImageViewFragment; 21 | import me.alex.baseimageloaderdemo.fragment.CustomFragment; 22 | import me.alex.baseimageloaderdemo.fragment.ImageFragment; 23 | 24 | @DarkStatusBarTheme(true) 25 | @Layout(R.layout.activity_main) 26 | @FragmentLayout(R.id.frame) 27 | public class MainActivity extends BaseActivity { 28 | 29 | @Override 30 | public void initViews() { 31 | List tabs = new ArrayList<>(); 32 | tabs.add(new Tab(me, "ImageView", 0)); 33 | tabs.add(new Tab(me, "自定义View", 0)); 34 | tabs.add(new Tab(me, "加载至任意View", 0)); 35 | tabs.add(new Tab(me, "自动加载", 0)); 36 | 37 | TabBarView tabBar = findViewById(R.id.tabbar); 38 | tabBar.setTab(tabs); 39 | tabBar.setOnTabChangeListener(new OnTabChangeListener() { 40 | @Override 41 | public void onTabChanged(View v, int index) { 42 | changeFragment(index); 43 | } 44 | }); 45 | } 46 | 47 | @Override 48 | public void initDatas(JumpParameter parameter) { 49 | 50 | } 51 | 52 | @Override 53 | public void setEvents() { 54 | 55 | } 56 | 57 | @Override 58 | public void initFragment(FragmentChangeUtil fragmentChangeUtil) { 59 | fragmentChangeUtil.addFragment(new ImageFragment()); 60 | fragmentChangeUtil.addFragment(new BaseImageViewFragment()); 61 | fragmentChangeUtil.addFragment(new CustomFragment()); 62 | fragmentChangeUtil.addFragment(new AutoLoadFragment()); 63 | changeFragment(0); 64 | } 65 | } -------------------------------------------------------------------------------- /app/src/main/java/me/alex/baseimageloaderdemo/fragment/AutoLoadFragment.java: -------------------------------------------------------------------------------- 1 | package me.alex.baseimageloaderdemo.fragment; 2 | 3 | import android.os.Environment; 4 | import android.widget.LinearLayout; 5 | import android.widget.ScrollView; 6 | 7 | import com.kongzue.baseframework.BaseFragment; 8 | import com.kongzue.baseframework.interfaces.Layout; 9 | 10 | import java.io.File; 11 | import java.io.FileOutputStream; 12 | import java.io.IOException; 13 | import java.io.InputStream; 14 | import java.io.OutputStream; 15 | 16 | import me.alex.baseimageloader.BaseImageLoader; 17 | import me.alex.baseimageloaderdemo.MainActivity; 18 | import me.alex.baseimageloaderdemo.R; 19 | 20 | /** 21 | * ================================================ 22 | * Description: 23 | *

24 | * Created by Alex on 2020/12/16 25 | *

26 | * 页面内容介绍: 自动加载 27 | *

28 | * ================================================ 29 | */ 30 | @Layout(R.layout.fragment_autoload) 31 | public class AutoLoadFragment extends BaseFragment { 32 | ScrollView linearLayout; 33 | private String ASSETS_NAME = "imgs.zip"; 34 | private String SDCARD_PATH; 35 | private String LOAD_PATH; 36 | 37 | 38 | @Override 39 | public void initViews() { 40 | //这里是讲assets文件夹中的imgs.zip释放至sd卡做demo演示 41 | SDCARD_PATH = me.getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS).getAbsolutePath(); 42 | LOAD_PATH = SDCARD_PATH + File.separator + ASSETS_NAME; 43 | // LOAD_PATH = /storage/emulated/0/Android/data/me.alex.baseimageloaderdemo/files/Documents/imgs.zip; 44 | log(LOAD_PATH); 45 | 46 | //初始化view 47 | linearLayout = findViewById(R.id.autoLoadViewGroup); 48 | } 49 | 50 | @Override 51 | public void initDatas() { 52 | try { 53 | copyDataBase(); 54 | } catch (IOException e) { 55 | e.printStackTrace(); 56 | } 57 | // log(me.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath()); 58 | log(System.currentTimeMillis());//1608123847926 59 | BaseImageLoader.getInstance() 60 | .autoLoadImage(me, linearLayout, LOAD_PATH); 61 | log(System.currentTimeMillis());//1608123847994 62 | } 63 | 64 | @Override 65 | public void setEvents() { 66 | 67 | } 68 | 69 | private void copyDataBase() throws IOException { 70 | // Path to the just created empty db 71 | String outFileName = SDCARD_PATH + File.separator + ASSETS_NAME; 72 | // 判断目录是否存在。如不存在则创建一个目录 73 | File file = new File(SDCARD_PATH); 74 | if (!file.exists()) { 75 | file.mkdirs(); 76 | } 77 | file = new File(outFileName); 78 | if (!file.exists()) { 79 | file.createNewFile(); 80 | } 81 | // Open your local db as the input stream 82 | InputStream myInput = me.getAssets().open(ASSETS_NAME); 83 | // Open the empty db as the output stream128 84 | OutputStream myOutput = new FileOutputStream(outFileName); 85 | // transfer bytes from the inputfile to the outputfile130 86 | byte[] buffer = new byte[1024]; 87 | int length; 88 | while ((length = myInput.read(buffer)) > 0) { 89 | myOutput.write(buffer, 0, length); 90 | } 91 | // Close the streams136 92 | myOutput.flush(); 93 | myOutput.close(); 94 | myInput.close(); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /app/src/main/java/me/alex/baseimageloaderdemo/fragment/BaseImageViewFragment.java: -------------------------------------------------------------------------------- 1 | package me.alex.baseimageloaderdemo.fragment; 2 | 3 | import com.kongzue.baseframework.BaseFragment; 4 | import com.kongzue.baseframework.interfaces.Layout; 5 | 6 | import me.alex.baseimageloader.view.BaseImageView; 7 | import me.alex.baseimageloaderdemo.MainActivity; 8 | import me.alex.baseimageloaderdemo.R; 9 | 10 | /** 11 | * ================================================ 12 | * Description: 13 | *

14 | * Created by Alex on 2020/12/15 15 | *

16 | * 页面内容介绍: 自定义View 17 | *

18 | * ================================================ 19 | */ 20 | @Layout(R.layout.fragment_baseimageview) 21 | public class BaseImageViewFragment extends BaseFragment { 22 | private final String imageUrlTest = "https://images.xiaozhuanlan.com/photo/2020/de67120589fd1b314c7a2e75a2233b06.png"; 23 | 24 | BaseImageView img15; 25 | 26 | @Override 27 | public void initViews() { 28 | img15 = findViewById(R.id.img15); 29 | 30 | } 31 | 32 | @Override 33 | public void initDatas() { 34 | //自定义VIew简单使用 35 | img15.setRadius(30); 36 | img15.load(imageUrlTest); 37 | 38 | //dataBinding使用,该框架不支持dataBinding 只做代码示例演示 39 | // ImageData data = new ImageData(); 40 | // data.setImageUrl(imageUrl); 41 | // data.setContent("自定义View dataBinding使用"); 42 | // binding.setData(data); 43 | } 44 | 45 | @Override 46 | public void setEvents() { 47 | 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /app/src/main/java/me/alex/baseimageloaderdemo/fragment/CustomFragment.java: -------------------------------------------------------------------------------- 1 | package me.alex.baseimageloaderdemo.fragment; 2 | 3 | import android.net.Uri; 4 | 5 | import com.kongzue.baseframework.BaseFragment; 6 | import com.kongzue.baseframework.interfaces.Layout; 7 | 8 | import me.alex.baseimageloader.BaseImageLoader; 9 | import me.alex.baseimageloaderdemo.ImageConfig; 10 | import me.alex.baseimageloaderdemo.MainActivity; 11 | import me.alex.baseimageloaderdemo.R; 12 | 13 | /** 14 | * ================================================ 15 | * Description: 16 | *

17 | * Created by Alex on 2020/12/16 18 | *

19 | * 页面内容介绍: 加载至任意View 20 | *

21 | * ================================================ 22 | */ 23 | @Layout(R.layout.fragment_custom) 24 | public class CustomFragment extends BaseFragment { 25 | BaseImageLoader loader; 26 | private final String imageUrl = "https://images.xiaozhuanlan.com/photo/2020/4919e1e317209facf63c83d0686398bb.png"; 27 | 28 | @Override 29 | public void initViews() { 30 | loader = new BaseImageLoader(); 31 | //LinearLayout 32 | loader.loadImage(me, ImageConfig.builder() 33 | .url(Uri.parse(imageUrl)) 34 | .imageView(findViewById(R.id.LinearLayout)) 35 | .setRadius(20) 36 | .show()); 37 | //RelativeLayout 38 | BaseImageLoader.getInstance().loadImage(me, ImageConfig.builder() 39 | .url(imageUrl) 40 | .imageView(findViewById(R.id.RelativeLayout)) 41 | .centerCrop() 42 | .show()); 43 | //ScrollView 44 | loader.loadImage(me, ImageConfig.builder() 45 | .url(Uri.parse(imageUrl)) 46 | .isCircle() 47 | .imageView(findViewById(R.id.ScrollView)) 48 | .show()); 49 | //TextClock 50 | loader.loadImage(me, ImageConfig.builder() 51 | .url(Uri.parse(imageUrl)) 52 | .imageView(findViewById(R.id.TextClock)) 53 | .show()); 54 | //Button 55 | loader.loadImage(me, ImageConfig.builder() 56 | .url(imageUrl) 57 | .setTopRightRadius(10) 58 | .setTopLeftRadius(20) 59 | .setBottomRightRadius(30) 60 | .setBottomLeftRadius(0) 61 | .imageView(findViewById(R.id.Button)) 62 | .show()); 63 | } 64 | 65 | @Override 66 | public void initDatas() { 67 | 68 | } 69 | 70 | @Override 71 | public void setEvents() { 72 | 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /app/src/main/java/me/alex/baseimageloaderdemo/fragment/ImageFragment.java: -------------------------------------------------------------------------------- 1 | package me.alex.baseimageloaderdemo.fragment; 2 | 3 | import android.graphics.drawable.Drawable; 4 | import android.net.Uri; 5 | import android.util.Log; 6 | import android.widget.ImageView; 7 | 8 | import androidx.annotation.Nullable; 9 | 10 | import com.bumptech.glide.load.DataSource; 11 | import com.bumptech.glide.load.engine.GlideException; 12 | import com.bumptech.glide.request.target.Target; 13 | import com.kongzue.baseframework.BaseFragment; 14 | import com.kongzue.baseframework.interfaces.Layout; 15 | 16 | import me.alex.baseimageloader.BaseImageLoader; 17 | import me.alex.baseimageloader.config.BaseImageConfig; 18 | import me.alex.baseimageloader.entity.ImageResult; 19 | import me.alex.baseimageloader.listener.OnBitmapResult; 20 | import me.alex.baseimageloader.listener.OnFileResult; 21 | import me.alex.baseimageloader.listener.OnGifResult; 22 | import me.alex.baseimageloader.listener.OnLoadListener; 23 | import me.alex.baseimageloader.srtategy.CacheStrategy; 24 | import me.alex.baseimageloader.view.BaseImageView; 25 | import me.alex.baseimageloaderdemo.ImageConfig; 26 | import me.alex.baseimageloaderdemo.MainActivity; 27 | import me.alex.baseimageloaderdemo.R; 28 | 29 | /** 30 | * ================================================ 31 | * Description: 32 | *

33 | * Created by Alex on 2020/12/15 34 | *

35 | * 页面内容介绍: ImageView 36 | *

37 | * ================================================ 38 | */ 39 | @Layout(R.layout.fragment_image) 40 | public class ImageFragment extends BaseFragment { 41 | ImageView img1, img2, img3, img4, img5, img6, img7, img10, img11, img12, img13, img14; 42 | BaseImageLoader mImageLoader; 43 | 44 | private final String imageUrl = "https://images.xiaozhuanlan.com/photo/2020/4919e1e317209facf63c83d0686398bb.png"; 45 | private final String imageUrlHeight = "https://images.xiaozhuanlan.com/photo/2020/b5a8f22bb93491d3b31ec2d60c709cf9.png"; 46 | private final String patchImageUrl = "http://kongzue.com/test/img_notification_ios.9.png"; 47 | private final String imageUrlTest = "https://images.xiaozhuanlan.com/photo/2020/de67120589fd1b314c7a2e75a2233b06.png"; 48 | private final String gifUrl = "https://images.xiaozhuanlan.com/photo/2020/e09ab1c37ca4fe242e63bc6ef2f34551.gif"; 49 | 50 | @Override 51 | public void initViews() { 52 | img1 = findViewById(R.id.img1); 53 | img2 = findViewById(R.id.img2); 54 | img3 = findViewById(R.id.img3); 55 | img4 = findViewById(R.id.img4); 56 | img5 = findViewById(R.id.img5); 57 | img6 = findViewById(R.id.img6); 58 | img7 = findViewById(R.id.img7); 59 | img10 = findViewById(R.id.img10); 60 | img11 = findViewById(R.id.img11); 61 | img12 = findViewById(R.id.img12); 62 | img13 = findViewById(R.id.img13); 63 | img14 = findViewById(R.id.img14); 64 | 65 | mImageLoader = new BaseImageLoader(); 66 | //全用法示例 67 | mImageLoader.loadImage(me, ImageConfig.builder() 68 | .url(Uri.parse(imageUrl))//url 69 | .imageView(img1)//imageView 70 | .placeholder(R.drawable.ic_baseline_adb_24)//占位图 71 | .errorPic(R.mipmap.ic_launcher)//加载错误图片 72 | .cacheStrategy(CacheStrategy.ALL)//缓存策略 73 | .centerCrop()//centerCrop 74 | .crossFade(true)//淡出淡入 75 | .isCircle()//是否圆形显示 76 | .setAsBitmap(true)//是否以bitmap加载图片,默认为drawable格式 77 | .setRadius(30)//设置通用圆角,单位dp 78 | .setTopRightRadius(10)//左上圆角,单位dp 79 | .setTopLeftRadius(20)//右上圆角,单位dp 80 | .setBottomRightRadius(30)//左下圆角,单位dp 81 | .setBottomLeftRadius(40)//右下圆角,单位dp 82 | .show()); 83 | 84 | //使用自定义ImageConfig的建造者模式加载 85 | 86 | //普通图片加载 87 | mImageLoader.loadImage(me, ImageConfig.builder().url(Uri.parse(imageUrl)).imageView(img1).show()); 88 | 89 | //圆形图片加载 90 | mImageLoader.loadImage(me, ImageConfig.builder().url(Uri.parse(imageUrl)).imageView(img2).isCircle().show()); 91 | 92 | //圆角图片加载 圆角30dp 93 | mImageLoader.loadImage(me, ImageConfig.builder().url(imageUrl).imageView(img3).setRadius(30).show()); 94 | 95 | //分别控制4个圆角 如设置通用圆角setRadius(int) 则单独控制圆角失效 96 | mImageLoader.loadImage(me, ImageConfig.builder().url(imageUrl).imageView(img4) 97 | .setTopRightRadius(10) 98 | .setTopLeftRadius(20) 99 | .setBottomRightRadius(30) 100 | .setBottomLeftRadius(0) 101 | // .setRadius(30) 102 | .show()); 103 | 104 | //长方形图片 普通模式加载 105 | mImageLoader.loadImage(me, ImageConfig.builder().url(imageUrlHeight).imageView(img5).show()); 106 | 107 | //长方形图片 centerCrop模式加载 108 | mImageLoader.loadImage(me, ImageConfig.builder().url(imageUrlHeight).imageView(img6).centerCrop().show()); 109 | 110 | //长方形图片 centerCrop模式加载 + 分别控制4个圆角 如设置通用圆角setRadius(int) 则单独控制圆角失效 111 | mImageLoader.loadImage(me, ImageConfig.builder().url(imageUrlHeight).imageView(img7).centerCrop() 112 | .setTopRightRadius(10) 113 | .setTopLeftRadius(20) 114 | .setBottomRightRadius(30) 115 | .setBottomLeftRadius(0) 116 | // .setRadius(30) 117 | .show()); 118 | 119 | //加载mipmap图片 120 | mImageLoader.loadImage(me, BaseImageConfig.builder().url(R.mipmap.ic_launcher).imageView(img10).show()); 121 | 122 | //单例加载drawable文件 (SVG格式) 123 | BaseImageLoader.getInstance().loadImage(me, ImageConfig.builder().url(R.drawable.ic_baseline_adb_24).imageView(img11).show()); 124 | 125 | //网络.9图片 126 | mImageLoader.loadImage(me, ImageConfig.builder().url(Uri.parse(patchImageUrl)).imageView(img12).show()); 127 | 128 | //网络.9图片 + 加载结果回调 129 | mImageLoader.loadImage(me, ImageConfig.builder().url(patchImageUrl).imageView(img13).setListener(new OnLoadListener() { 130 | @Override 131 | public void onResourceReady(Drawable resource, Object model, Target target, DataSource dataSource, boolean isFirstResource) { 132 | Log.e("OnResourceReady", "resource:" + resource.toString() + ",model:" + model.toString() + ",target:" + target.toString() + ",isFirstResource:" + isFirstResource); 133 | } 134 | 135 | @Override 136 | public void onLoadFailed(@Nullable GlideException e, Object model, Target target, boolean isFirstResource) { 137 | assert e != null; 138 | Log.e("OnLoadFailed", "GlideException:" + e.toString() + ",model:" + model.toString() + ",target:" + target.toString() + ",isFirstResource:" + isFirstResource); 139 | } 140 | }).show()); 141 | 142 | 143 | //根据图片类型直出对象 144 | //需要根据参数类型判断获取的字段,比如使用OnBitmapResult,就只有getBitmap方法不为null 145 | //根据是否传入imageView是否直接显示图片,如果想自己处理过资源再加载则不传入imageView 146 | 147 | //example: 148 | //mImageLoader.loadImageAs(me, imageUrlTest, new OnBitmapResult() { 149 | // @Override 150 | // public void OnResult(ImageResult result) { 151 | // Log.e("result", result.getBitmap() + ""); 152 | // } 153 | //}); 154 | 155 | 156 | //加载图片且获得bitmap格式图片 且以 imageView.setImageBitmap(bitmap) 模式加载图片 157 | mImageLoader.loadImageAs(me, imageUrlTest, img14, new OnBitmapResult() { 158 | @Override 159 | public void OnResult(ImageResult result) { 160 | Log.e("result", result.getBitmap() + ""); 161 | } 162 | }); 163 | 164 | 165 | //使用File类型获取result时,默认result.getFile()是在设置的cache目录中 166 | //加载图片且获得File文件 但是以Glide默认方式加载图片(drawable格式) imageView.setImageDrawable(drawable); 167 | mImageLoader.loadImageAs(me, imageUrlTest, img14, new OnFileResult() { 168 | @Override 169 | public void OnResult(ImageResult result) { 170 | Log.e("result", result.getFile() + ""); 171 | } 172 | }); 173 | 174 | //加载gif且获得gif文件 以 imageView.setImageDrawable(GifDrawable); 模式加载图片 175 | mImageLoader.loadImageAs(me, gifUrl, img14, new OnGifResult() { 176 | @Override 177 | public void OnResult(ImageResult result) { 178 | Log.e("result", result.getGif() + ""); 179 | } 180 | }); 181 | 182 | 183 | //加载图片且获得drawable格式图片 以Glide默认方式加载图片(drawable格式) imageView.setImageDrawable(drawable); 184 | //mImageLoader.loadImageAs(me, imageUrlTest, img14, new OnDrawableResult() { 185 | // @Override 186 | // public void OnResult(ImageResult result) { 187 | // Log.e("result", result.getDrawable() + ""); 188 | // } 189 | //}); 190 | 191 | } 192 | 193 | @Override 194 | public void initDatas() { 195 | 196 | } 197 | 198 | @Override 199 | public void setEvents() { 200 | 201 | } 202 | } 203 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_adb_24.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 14 | 15 | 26 | 27 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_autoload.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 17 | 18 | 23 | 24 | 29 | 30 | 36 | 37 | 42 | 43 | 48 | 49 | 54 | 55 | 60 | 61 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_baseimageview.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | 14 | 21 | 22 | 27 | 28 | 29 | 30 | 36 | 37 | 53 | 54 | 55 | 60 | 61 | 62 | 68 | 69 | 73 | 74 | 79 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_custom.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 16 | 17 | 22 | 23 | 28 | 29 | 34 | 35 | 36 | 42 | 43 | 47 | 48 | 53 | 54 | 55 | 61 | 62 | 66 | 67 | 72 | 73 | 74 | 80 | 81 | 85 | 86 | 91 | 92 | 93 | 99 | 100 |