├── .gitignore
├── .idea
├── encodings.xml
├── gradle.xml
├── misc.xml
├── modules.xml
├── runConfigurations.xml
└── vcs.xml
├── .travis.yml
├── README.md
├── Sample
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── assets
│ ├── about.html
│ └── about.md
│ ├── java
│ └── com
│ │ └── sunfusheng
│ │ └── glideimageview
│ │ └── sample
│ │ ├── BaseActivity.java
│ │ ├── MainActivity.java
│ │ ├── NineImageViewActivity.java
│ │ ├── RecyclerViewActivity.java
│ │ ├── about
│ │ ├── AboutActivity.java
│ │ └── WebViewWrapper.java
│ │ ├── image
│ │ ├── FixedViewPager.java
│ │ ├── ImagesActivity.java
│ │ ├── ImagesAdapter.java
│ │ ├── NineImageViewEventAdapter.java
│ │ └── SingleImageActivity.java
│ │ ├── model
│ │ ├── ImageModel.java
│ │ ├── ModelUtil.java
│ │ └── NewsModel.java
│ │ ├── util
│ │ ├── AppUtil.java
│ │ ├── ColorUtil.java
│ │ └── StatusBarUtil.java
│ │ └── widget
│ │ ├── DraggableFrameLayout.java
│ │ └── SlideVerticallyLayout.java
│ └── res
│ ├── drawable-v24
│ └── ic_launcher_foreground.xml
│ ├── drawable
│ ├── drawable_corner_icon_bg.xml
│ ├── gif_robot_walk.gif
│ ├── ic_launcher_background.xml
│ └── progressbar_orange_selector.xml
│ ├── layout
│ ├── activity_about.xml
│ ├── activity_image.xml
│ ├── activity_main.xml
│ ├── activity_preview.xml
│ ├── item_nine_images.xml
│ ├── item_photoview.xml
│ ├── item_right_image.xml
│ ├── item_three_images.xml
│ ├── item_top_image.xml
│ ├── layout_image_cell.xml
│ ├── layout_recyclerview.xml
│ ├── layout_roundimageview.xml
│ └── layout_webview.xml
│ ├── menu
│ └── menu_main.xml
│ ├── mipmap-anydpi-v26
│ └── ic_launcher.xml
│ ├── mipmap-hdpi
│ └── ic_launcher.png
│ ├── mipmap-mdpi
│ └── ic_launcher.png
│ ├── mipmap-xhdpi
│ ├── ic_launcher.png
│ └── ic_multi_imageview.png
│ ├── mipmap-xxhdpi
│ ├── ic_launcher.png
│ └── ic_multi_imageview.png
│ ├── mipmap-xxxhdpi
│ ├── ic_launcher.png
│ └── she.png
│ ├── values-v21
│ └── styles.xml
│ └── values
│ ├── attrs.xml
│ ├── colors.xml
│ ├── colors_material.xml
│ ├── dimens.xml
│ ├── strings.xml
│ └── styles.xml
├── build.gradle
├── glideimageview
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── com
│ │ └── sunfusheng
│ │ ├── GlideImageLoader.java
│ │ ├── GlideImageView.java
│ │ ├── progress
│ │ ├── CircleProgressView.java
│ │ ├── OnProgressListener.java
│ │ ├── ProgressAppGlideModule.java
│ │ ├── ProgressManager.java
│ │ └── ProgressResponseBody.java
│ │ ├── transformation
│ │ ├── BlurTransformation.java
│ │ ├── CircleTransformation.java
│ │ └── RadiusTransformation.java
│ │ ├── util
│ │ ├── BlurUtils.java
│ │ └── Utils.java
│ │ └── widget
│ │ ├── GridLayoutHelper.java
│ │ ├── ImageCell.java
│ │ ├── ImageData.java
│ │ ├── LayoutHelper.java
│ │ └── NineImageView.java
│ └── res
│ ├── drawable
│ ├── drawable_image_bg_0dp.xml
│ └── drawable_image_bg_5dp.xml
│ ├── mipmap-hdpi
│ ├── image_load_err.png
│ └── image_loading.png
│ ├── mipmap-xhdpi
│ ├── image_load_err.png
│ └── image_loading.png
│ ├── mipmap-xxhdpi
│ ├── image_load_err.png
│ └── image_loading.png
│ └── values
│ ├── colors.xml
│ └── style.xml
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── resources
├── cat.jpg
├── cat_thumbnail.jpg
├── gif1.gif
├── gif2.gif
├── gif3.gif
├── gif4.gif
├── gif5.gif
├── gif6.gif
├── girl.jpg
├── girl_thumbnail.jpg
├── image1.png
├── image2.png
├── image3.png
├── image4.png
└── image5.png
├── settings.gradle
└── signings
├── keystore.jks
├── keystore.jks.enc
└── signing.properties
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/workspace.xml
5 | /.idea/libraries
6 | .DS_Store
7 | /build
8 | /captures
9 | .externalNativeBuild
10 |
--------------------------------------------------------------------------------
/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
21 |
22 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/.idea/runConfigurations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: android
2 | jdk: oraclejdk8
3 | sudo: true
4 |
5 | android:
6 | components:
7 | - tools
8 | - platform-tools
9 | - tools
10 | - build-tools-28.0.3
11 | - android-28
12 | - sys-img-armeabi-v7a-android-28
13 | - extra-android-support
14 | - extra-android-m2repository
15 | - extra-google-m2repository
16 | - add-on
17 | - extra
18 | licenses:
19 | - android-sdk-preview-license-52d11cd2
20 | - android-sdk-license-.+
21 | - google-gdk-license-.+
22 |
23 | before_cache:
24 | - rm -f $HOME/.gradle/caches/modules-2/modules-2.lock
25 | - rm -fr $HOME/.gradle/caches/*/plugin-resolution/
26 |
27 | cache:
28 | directories:
29 | - "$HOME/.gradle/caches/"
30 | - "$HOME/.gradle/wrapper/"
31 | - "$HOME/.android/build-cache"
32 |
33 | before_install:
34 | - mkdir "$ANDROID_HOME/licenses" || true
35 | - echo "d56f5187479451eabf01fb78af6dfcb131a6481e" > "$ANDROID_HOME/licenses/android-sdk-license"
36 | - openssl aes-256-cbc -K $encrypted_0f82fc3ea788_key -iv $encrypted_0f82fc3ea788_iv
37 | -in signings/keystore.jks.enc -out signings/keystore.jks -d
38 | - gem install fir-cli
39 |
40 | before_script:
41 | - chmod +x gradlew
42 |
43 | script:
44 | - "./gradlew assembleRelease"
45 |
46 | deploy:
47 | provider: releases
48 | api_key:
49 | secure: BwzVE9rrCLQ1CKalfO66vdBVrpajt1AZVzG8n2qwRSRQxIKabnQht2NCEVWA9jBCGan6ahKG3ZV4Ky5Xeue49FZHb69zuvi7pdhL2AVGDv/T48TXks39FviJD40gSvtOC9H8ju5LokRBoTs74bdhg/weu0fbwjarioS+gsx/AdLYoji5xpe+FaCuwZEKRQ2Cer000XSntmm4d91oW1gJ9DiBLEyb0eEA4t0Trd+zCvC38pv5+sEEag1FIOnOnwc5dixozL0FSSSSPC3mDMxLJL0cgrDmSHzhRL6/DOb/taRGpAyyhOlrIn1H6fPcot8oQFPMv9LUzltYrdYjaKEgg5fGP/+4GVA50UqmQ7UEdtN6i1+UqfnRtkAugJRozy6M0+c8fgg9l5eZfH0jXCpNL8wYsTC0nmDnsG5kLayIM23nQRQOeYEoIiPZxnwvwCwyVZ0GbTEQIql/GHHBpcW9fjBDASsnK3CGtVVf/EHzU/5f0Y71GSPJ5DUHl79ZBNmw+fYkjuoAIt27vP+sf3WPAkGOUGT7PvwpAEe16Xh8cYr37R/Ryuw57Rk3vN/Js0pCqlDymIjMeOIeU57RK8KXKsqrYQtleC8Erjx89eeq1oqq/zZ2g3gFl31c9ajiCjjSpkMR+df518tqgfa40/SfqHX+oz6ihAsCs2PGwqPG8ig=
50 | file: sample/release/GlideImageView.apk
51 | skip_cleanup: true
52 | on:
53 | repo: sunfusheng/GlideImageView
54 | tags: true
55 | all_branches: true
56 |
57 | after_deploy:
58 | - "./gradlew clean build bintrayUpload -PbintrayUser=sunfusheng -PbintrayKey=$BINTRAY_TOKEN -PdryRun=false"
59 | - fir p sample/release/GlideImageView.apk -T $FIR_TOKEN -c "基于Glide V4.9.0封装的图片加载库,可以监听加载图片时的进度"
60 |
61 | notifications:
62 | email:
63 | - sfsheng0322@126.com
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # GlideImageView [  ](https://bintray.com/sfsheng0322/maven/GlideImageView/_latestVersion)
2 |
3 | ### 该库是基于[Glide](https://github.com/bumptech/glide) V4.9.0设计的,实现如下特性:
4 | 1、监听加载网络图片的进度
5 | 2、动态加载成有弧度的图片、圆形图片、高斯模糊图片更方便
6 | 3、链式设置触摸图片的透明度和非使能的透明度
7 | 4、增加九宫格控件,具体使用参考[NineImageViewActivity](https://github.com/sunfusheng/GlideImageView/blob/master/Sample/src/main/java/com/sunfusheng/glideimageview/sample/NineImageViewActivity.java)
8 |
9 |
10 |
11 | ### 监听加载高清图片进度的效果图
12 |
13 |
14 |
15 |
16 |
17 | ### [APK下载地址](https://fir.im/GlideImageView),去手机上体验吧 (◐‿◑)
18 |
19 |
20 |
21 | ### 具体使用说明如下
22 |
23 | #### Gradle:
24 |
25 | compile 'com.sunfusheng:GlideImageView:'
26 |
27 |
28 |
29 | #### GlideImageView 主要方法
30 |
31 | load(String url, @DrawableRes int placeholder, int radius, OnProgressListener onProgressListener)
32 |
33 | load(Object obj, @DrawableRes int placeholder, Transformation transformation, OnProgressListener onProgressListener)
34 |
35 | loadCircle(String url, @DrawableRes int placeholder, OnProgressListener onProgressListener)
36 |
37 | loadDrawable(@DrawableRes int resId, @DrawableRes int placeholder)
38 |
39 |
40 |
41 | ### 个人微信公众号
42 |
43 |
44 |
45 |
46 |
47 | ### 关于我
48 |
49 | [GitHub: sunfusheng](https://github.com/sunfusheng)
50 |
51 | [个人邮箱: sfsheng0322@126.com](https://mail.126.com/)
52 |
53 | [个人博客: sunfusheng.com](http://sunfusheng.com/)
54 |
55 | [简书主页](http://www.jianshu.com/users/88509e7e2ed1/latest_articles)
56 |
57 | [新浪微博](http://weibo.com/u/3852192525)
--------------------------------------------------------------------------------
/Sample/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/Sample/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | Properties signingProperties = new Properties()
4 | signingProperties.load(new FileInputStream(file("../signings/signing.properties")))
5 |
6 | android {
7 | compileSdkVersion COMPILE_SDK_VERSION
8 | defaultConfig {
9 | applicationId "com.sunfusheng.glideimageview.sample"
10 | minSdkVersion MIN_SDK_VERSION
11 | targetSdkVersion TARGET_SDK_VERSION
12 | versionCode VERSION_CODE
13 | versionName VERSION_NAME
14 | }
15 |
16 | compileOptions {
17 | sourceCompatibility JavaVersion.VERSION_1_8
18 | targetCompatibility JavaVersion.VERSION_1_8
19 | }
20 |
21 | lintOptions {
22 | abortOnError false
23 | }
24 |
25 | signingConfigs {
26 | release {
27 | storeFile file(signingProperties['KEYSTORE_FILEPATH'])
28 | storePassword signingProperties['STORE_PASSWORD']
29 | keyAlias signingProperties['KEY_ALIAS']
30 | keyPassword signingProperties['KEY_PASSWORD']
31 | }
32 | }
33 |
34 | buildTypes {
35 | debug {
36 | signingConfig signingConfigs.release
37 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
38 | }
39 | release {
40 | signingConfig signingConfigs.release
41 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
42 | applicationVariants.all { variant ->
43 | variant.outputs.all {
44 | outputFileName = "GlideImageView.apk"
45 | }
46 | }
47 | }
48 | }
49 | }
50 |
51 | dependencies {
52 | api 'com.android.support:appcompat-v7:' + SUPPORT_LIBRARY_VERSION
53 | api 'com.android.support:percent:' + SUPPORT_LIBRARY_VERSION
54 | api 'com.android.support:design:' + SUPPORT_LIBRARY_VERSION
55 | api 'com.android.support.constraint:constraint-layout:1.1.3'
56 | api 'com.github.chrisbanes:PhotoView:2.1.3'
57 |
58 | // api 'com.sunfusheng:FirUpdater:1.1.1'
59 | api project(':glideimageview')
60 | }
61 |
--------------------------------------------------------------------------------
/Sample/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /Users/sunfusheng/Android/Studio/sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
19 | # Uncomment this to preserve the line number information for
20 | # debugging stack traces.
21 | #-keepattributes SourceFile,LineNumberTable
22 |
23 | # If you keep the line number information, uncomment this to
24 | # hide the original source file name.
25 | #-renamesourcefileattribute SourceFile
26 |
--------------------------------------------------------------------------------
/Sample/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
20 |
21 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
35 |
36 |
39 |
40 |
41 |
42 |
43 |
44 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/Sample/src/main/assets/about.md:
--------------------------------------------------------------------------------
1 | #### GlideImageView
2 |
3 | #### 该库是基于[Glide](https://github.com/bumptech/glide) V4.9.0设计的,实现如下特性:
4 | 1、监听加载网络图片的进度
5 | 2、动态加载成有弧度的图片、圆形图片、高斯模糊图片更方便
6 | 3、链式设置触摸图片的透明度和非使能的透明度
7 | 4、增加九宫格控件,具体使用参考
8 |
9 | #### GitHub地址
10 |
11 | [https://github.com/sunfusheng/GlideImageView](https://github.com/sunfusheng/GlideImageView)
12 |
13 | #### 关于我
14 |
15 | 个人邮箱:sfsheng0322@126.com
16 | [GitHub主页](https://github.com/sunfusheng)
17 | [简书主页](http://www.jianshu.com/users/88509e7e2ed1/latest_articles)
18 | [个人博客](http://sunfusheng.com/)
19 | [新浪微博](http://weibo.com/u/3852192525)
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/Sample/src/main/java/com/sunfusheng/glideimageview/sample/BaseActivity.java:
--------------------------------------------------------------------------------
1 | package com.sunfusheng.glideimageview.sample;
2 |
3 | import android.app.Activity;
4 | import android.content.Context;
5 | import android.content.Intent;
6 | import android.os.Bundle;
7 | import android.support.annotation.Nullable;
8 | import android.support.v7.app.AppCompatActivity;
9 |
10 | import com.sunfusheng.glideimageview.sample.util.StatusBarUtil;
11 |
12 | /**
13 | * Created by sunfusheng on 2016/12/24.
14 | */
15 | public abstract class BaseActivity extends AppCompatActivity {
16 |
17 | protected Activity mActivity;
18 | protected Context mContext;
19 |
20 | @Override
21 | protected void onCreate(@Nullable Bundle savedInstanceState) {
22 | super.onCreate(savedInstanceState);
23 | mActivity = this;
24 | mContext = this;
25 | }
26 |
27 | protected void setStatusBarTranslucent(boolean isLightStatusBar) {
28 | StatusBarUtil.setStatusBarTranslucent(this, isLightStatusBar);
29 | }
30 |
31 | @Override
32 | public void startActivity(Intent intent) {
33 | super.startActivity(intent);
34 | if (intent == null) return;
35 | if (intent.getComponent() == null) return;
36 | String className = intent.getComponent().getClassName();
37 | if (!className.equals(MainActivity.class.getName())) {
38 | overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
39 | }
40 | }
41 |
42 | @Override
43 | public void startActivityForResult(Intent intent, int requestCode) {
44 | super.startActivityForResult(intent, requestCode);
45 | if (intent == null) return;
46 | if (intent.getComponent() == null) return;
47 | String className = intent.getComponent().getClassName();
48 | if (!className.equals(MainActivity.class.getName())) {
49 | overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
50 | }
51 | }
52 |
53 | @Override
54 | public void finish() {
55 | super.finish();
56 | if (!((Object) this).getClass().equals(MainActivity.class)) {
57 | overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
58 | }
59 | }
60 |
61 | @Override
62 | protected void onDestroy() {
63 | super.onDestroy();
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/Sample/src/main/java/com/sunfusheng/glideimageview/sample/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.sunfusheng.glideimageview.sample;
2 |
3 | import android.content.Intent;
4 | import android.os.Bundle;
5 | import android.support.v4.app.ActivityCompat;
6 | import android.support.v4.app.ActivityOptionsCompat;
7 | import android.view.Menu;
8 | import android.view.MenuItem;
9 | import android.view.View;
10 |
11 | import com.bumptech.glide.load.engine.DiskCacheStrategy;
12 | import com.sunfusheng.GlideImageView;
13 | import com.sunfusheng.glideimageview.sample.about.AboutActivity;
14 | import com.sunfusheng.glideimageview.sample.image.SingleImageActivity;
15 | import com.sunfusheng.progress.CircleProgressView;
16 | import com.sunfusheng.transformation.BlurTransformation;
17 |
18 | /**
19 | * @author by sunfusheng on 2017/6/3.
20 | */
21 | public class MainActivity extends BaseActivity {
22 |
23 | GlideImageView image11;
24 | GlideImageView image12;
25 | GlideImageView image13;
26 | GlideImageView image14;
27 |
28 | GlideImageView image21;
29 | GlideImageView image22;
30 | GlideImageView image23;
31 | GlideImageView image24;
32 |
33 | GlideImageView image31;
34 | CircleProgressView progressView1;
35 | GlideImageView image32;
36 | CircleProgressView progressView2;
37 |
38 | GlideImageView image41;
39 |
40 | View draggableView;
41 |
42 | String url1 =
43 | "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1497688355699&di=ea69a930b82ce88561c635089995e124&imgtype=0&src=http%3A%2F%2Fcms-bucket.nosdn.127.net%2Ff84e566bcf654b3698363409fbd676ef20161119091503.jpg";
44 | String url2 = "http://img1.imgtn.bdimg.com/it/u=4027212837,1228313366&fm=23&gp=0.jpg";
45 | String url3 =
46 | "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1529402445474&di=b5da3b2f6a466e618e1e32d4dd2bda4d&imgtype=0&src=http%3A%2F%2F2b.zol-img.com.cn%2Fproduct%2F133_500x2000%2F801%2Fce21ke76FRh4A.jpg";
47 |
48 | String gif1 = "http://img.zcool.cn/community/01e97857c929630000012e7e3c2acf.gif";
49 | String gif2 =
50 | "http://5b0988e595225.cdn.sohucs.com/images/20171202/a1cc52d5522f48a8a2d6e7426b13f82b.gif";
51 | String gif3 = "http://img.zcool.cn/community/01d6dd554b93f0000001bf72b4f6ec.jpg";
52 |
53 | public static final String cat =
54 | "https://raw.githubusercontent.com/sfsheng0322/GlideImageView/master/resources/cat.jpg";
55 | public static final String cat_thumbnail =
56 | "https://raw.githubusercontent.com/sfsheng0322/GlideImageView/master/resources/cat_thumbnail.jpg";
57 |
58 | public static final String girl =
59 | "https://raw.githubusercontent.com/sfsheng0322/GlideImageView/master/resources/girl.jpg";
60 | public static final String girl_thumbnail =
61 | "https://raw.githubusercontent.com/sfsheng0322/GlideImageView/master/resources/girl_thumbnail.jpg";
62 |
63 | @Override
64 | protected void onCreate(Bundle savedInstanceState) {
65 | super.onCreate(savedInstanceState);
66 | setContentView(R.layout.activity_main);
67 |
68 | //new FirUpdater(this, "3c57fb226edf7facf821501e4eba08d2", "59461f4c548b7a45cb000050").checkVersion();
69 |
70 | image11 = findViewById(R.id.image11);
71 | image12 = findViewById(R.id.image12);
72 | image13 = findViewById(R.id.image13);
73 | image14 = findViewById(R.id.image14);
74 |
75 | image21 = findViewById(R.id.image21);
76 | image22 = findViewById(R.id.image22);
77 | image23 = findViewById(R.id.image23);
78 | image24 = findViewById(R.id.image24);
79 |
80 | image31 = findViewById(R.id.image31);
81 | progressView1 = findViewById(R.id.progressView1);
82 | image32 = findViewById(R.id.image32);
83 | progressView2 = findViewById(R.id.progressView2);
84 |
85 | image41 = findViewById(R.id.image41);
86 |
87 | draggableView = findViewById(R.id.draggableView);
88 | image11.setOnClickListener(
89 | v -> startActivity(new Intent(mContext, RecyclerViewActivity.class)));
90 | draggableView.setOnClickListener(
91 | v -> startActivity(new Intent(mContext, NineImageViewActivity.class)));
92 |
93 | image31.setOnClickListener(v -> {
94 | Intent intent = new Intent(MainActivity.this, SingleImageActivity.class);
95 | intent.putExtra(SingleImageActivity.KEY_IMAGE_URL, girl);
96 | intent.putExtra(SingleImageActivity.KEY_IMAGE_URL_THUMBNAIL, girl_thumbnail);
97 | ActivityOptionsCompat compat =
98 | ActivityOptionsCompat.makeSceneTransitionAnimation(MainActivity.this, image31,
99 | getString(R.string.transitional_image));
100 | ActivityCompat.startActivity(MainActivity.this, intent, compat.toBundle());
101 | });
102 |
103 | image32.setOnClickListener(v -> {
104 | Intent intent = new Intent(MainActivity.this, SingleImageActivity.class);
105 | intent.putExtra(SingleImageActivity.KEY_IMAGE_URL, cat);
106 | intent.putExtra(SingleImageActivity.KEY_IMAGE_URL_THUMBNAIL, cat_thumbnail);
107 | ActivityOptionsCompat compat =
108 | ActivityOptionsCompat.makeSceneTransitionAnimation(MainActivity.this, image32,
109 | getString(R.string.transitional_image));
110 | ActivityCompat.startActivity(MainActivity.this, intent, compat.toBundle());
111 | });
112 |
113 | line1();
114 | line2();
115 | line3();
116 | line4();
117 | }
118 |
119 | private void line1() {
120 | image11.enableState(true).load(url1);
121 | image12.loadCircle(url1);
122 | image13.load(url2, R.mipmap.image_loading);
123 | image14.load(url2, R.mipmap.image_loading, 10);
124 | }
125 |
126 | private void line2() {
127 | image21.fitCenter().load(gif2, R.mipmap.image_loading, 10);
128 | image22.fitCenter().load(gif1);
129 | image23.fitCenter().loadCircle(gif3);
130 | image24.fitCenter().loadDrawable(R.drawable.gif_robot_walk);
131 | }
132 |
133 | private void line3() {
134 | image31.centerCrop()
135 | .error(R.mipmap.image_load_err)
136 | .diskCacheStrategy(DiskCacheStrategy.NONE)
137 | .load(girl, R.color.placeholder, (isComplete, percentage, bytesRead, totalBytes) -> {
138 | // Log.d("--->", "load percentage: " + percentage + " totalBytes: " + totalBytes + " bytesRead: " + bytesRead);
139 | if (isComplete) {
140 | progressView1.setVisibility(View.GONE);
141 | } else {
142 | progressView1.setVisibility(View.VISIBLE);
143 | progressView1.setProgress(percentage);
144 | }
145 | });
146 |
147 | image32.centerCrop()
148 | .error(R.mipmap.image_load_err)
149 | .load(cat, R.color.placeholder, (isComplete, percentage, bytesRead, totalBytes) -> {
150 | if (isComplete) {
151 | progressView2.setVisibility(View.GONE);
152 | } else {
153 | progressView2.setVisibility(View.VISIBLE);
154 | progressView2.setProgress(percentage);
155 | }
156 | });
157 | }
158 |
159 | private void line4() {
160 | image41.fitCenter().load(url3, R.mipmap.image_loading, new BlurTransformation(this, 25, 1));
161 |
162 | image41.setOnClickListener(v -> {
163 | Intent intent = new Intent(MainActivity.this, SingleImageActivity.class);
164 | intent.putExtra(SingleImageActivity.KEY_IMAGE_URL, url3);
165 | ActivityOptionsCompat compat =
166 | ActivityOptionsCompat.makeSceneTransitionAnimation(MainActivity.this, image41,
167 | getString(R.string.transitional_image));
168 | ActivityCompat.startActivity(MainActivity.this, intent, compat.toBundle());
169 | });
170 | }
171 |
172 | @Override
173 | public boolean onCreateOptionsMenu(Menu menu) {
174 | getMenuInflater().inflate(R.menu.menu_main, menu);
175 | return true;
176 | }
177 |
178 | @Override
179 | public boolean onOptionsItemSelected(MenuItem item) {
180 | switch (item.getItemId()) {
181 | case R.id.item_menu_app:
182 | startActivity(new Intent(this, AboutActivity.class));
183 | return true;
184 | default:
185 | return super.onOptionsItemSelected(item);
186 | }
187 | }
188 | }
189 |
--------------------------------------------------------------------------------
/Sample/src/main/java/com/sunfusheng/glideimageview/sample/NineImageViewActivity.java:
--------------------------------------------------------------------------------
1 | package com.sunfusheng.glideimageview.sample;
2 |
3 | import android.content.Context;
4 | import android.os.Bundle;
5 | import android.support.annotation.NonNull;
6 | import android.support.v7.widget.LinearLayoutManager;
7 | import android.support.v7.widget.RecyclerView;
8 | import android.view.LayoutInflater;
9 | import android.view.View;
10 | import android.view.ViewGroup;
11 | import android.widget.TextView;
12 | import android.widget.Toast;
13 |
14 | import com.sunfusheng.glideimageview.sample.model.ImageModel;
15 | import com.sunfusheng.glideimageview.sample.model.ModelUtil;
16 | import com.sunfusheng.widget.GridLayoutHelper;
17 | import com.sunfusheng.widget.ImageData;
18 | import com.sunfusheng.widget.NineImageView;
19 | import com.sunfusheng.util.Utils;
20 |
21 | import java.util.List;
22 |
23 | public class NineImageViewActivity extends BaseActivity {
24 |
25 | @Override
26 | protected void onCreate(Bundle savedInstanceState) {
27 | super.onCreate(savedInstanceState);
28 | setContentView(R.layout.layout_recyclerview);
29 |
30 | setTitle("NineImageView");
31 |
32 | RecyclerView recyclerView = findViewById(R.id.recycleView);
33 | LinearLayoutManager layoutManager = new LinearLayoutManager(this);
34 | recyclerView.setLayoutManager(layoutManager);
35 | RecyclerViewAdapter adapter = new RecyclerViewAdapter(this, ModelUtil.getImages());
36 | recyclerView.setAdapter(adapter);
37 | }
38 |
39 | private class RecyclerViewAdapter extends RecyclerView.Adapter {
40 | private List list;
41 | private int margin;
42 | private int maxImgWidth;
43 | private int maxImgHeight;
44 | private int cellWidth;
45 | private int cellHeight;
46 | private int minImgWidth;
47 | private int minImgHeight;
48 |
49 | RecyclerViewAdapter(Context context, List list) {
50 | this.list = list;
51 | margin = Utils.dp2px(context, 3);
52 | maxImgHeight = maxImgWidth = (Utils.getWindowWidth(context) - Utils.dp2px(context, 16) * 2) * 3 / 4;
53 | cellHeight = cellWidth = (maxImgWidth - margin * 3) / 3;
54 | minImgHeight = minImgWidth = cellWidth;
55 | }
56 |
57 | @NonNull
58 | @Override
59 | public ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int viewType) {
60 | View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_nine_images, viewGroup, false);
61 | return new ViewHolder(view);
62 | }
63 |
64 | @Override
65 | public void onBindViewHolder(@NonNull ViewHolder viewHolder, int position) {
66 | ImageModel model = list.get(position);
67 |
68 | viewHolder.vDesc.setText(model.desc);
69 | viewHolder.multiImageView.loadGif(false)
70 | .enableRoundCorner(true)
71 | .setRoundCornerRadius(5)
72 | .setData(model.images, getLayoutHelper(model.images));
73 |
74 | viewHolder.multiImageView.setOnLongClickListener(v -> {
75 | Toast.makeText(getApplicationContext(), "长按:" + model.desc, Toast.LENGTH_SHORT).show();
76 | return false;
77 | });
78 |
79 | viewHolder.multiImageView.setOnItemClickListener(index -> {
80 | Toast.makeText(getApplicationContext(), "点击:position = " + index, Toast.LENGTH_SHORT).show();
81 | });
82 | }
83 |
84 | private GridLayoutHelper getLayoutHelper(List list) {
85 | int spanCount = Utils.getSize(list);
86 | if (spanCount == 1) {
87 | int width = list.get(0).realWidth;
88 | int height = list.get(0).realHeight;
89 | if (width > 0 && height > 0) {
90 | float whRatio = width * 1f / height;
91 | if (width > height) {
92 | width = Math.max(minImgWidth, Math.min(width, maxImgWidth));
93 | height = Math.max(minImgHeight, (int) (width / whRatio));
94 | } else {
95 | height = Math.max(minImgHeight, Math.min(height, maxImgHeight));
96 | width = Math.max(minImgWidth, (int) (height * whRatio));
97 | }
98 | } else {
99 | width = cellWidth;
100 | height = cellHeight;
101 | }
102 | return new GridLayoutHelper(spanCount, width, height, margin);
103 | }
104 |
105 | if (spanCount > 3) {
106 | spanCount = (int) Math.ceil(Math.sqrt(spanCount));
107 | }
108 |
109 | if (spanCount > 3) {
110 | spanCount = 3;
111 | }
112 | return new GridLayoutHelper(spanCount, cellWidth, cellHeight, margin);
113 | }
114 |
115 | @Override
116 | public int getItemCount() {
117 | return list.size();
118 | }
119 |
120 | class ViewHolder extends RecyclerView.ViewHolder {
121 | TextView vDesc;
122 | NineImageView multiImageView;
123 |
124 | ViewHolder(View view) {
125 | super(view);
126 | vDesc = view.findViewById(R.id.desc);
127 | multiImageView = view.findViewById(R.id.multiImageView);
128 | }
129 | }
130 | }
131 | }
132 |
--------------------------------------------------------------------------------
/Sample/src/main/java/com/sunfusheng/glideimageview/sample/RecyclerViewActivity.java:
--------------------------------------------------------------------------------
1 | package com.sunfusheng.glideimageview.sample;
2 |
3 | import android.os.Bundle;
4 | import android.support.annotation.NonNull;
5 | import android.support.v7.widget.LinearLayoutManager;
6 | import android.support.v7.widget.RecyclerView;
7 | import android.view.LayoutInflater;
8 | import android.view.View;
9 | import android.view.ViewGroup;
10 | import android.widget.LinearLayout;
11 | import android.widget.TextView;
12 | import android.widget.Toast;
13 |
14 | import com.sunfusheng.GlideImageView;
15 | import com.sunfusheng.glideimageview.sample.model.ModelUtil;
16 | import com.sunfusheng.glideimageview.sample.model.NewsModel;
17 |
18 | import java.util.List;
19 |
20 | /**
21 | * @author sunfusheng on 2017/11/10.
22 | */
23 | public class RecyclerViewActivity extends BaseActivity {
24 |
25 | @Override
26 | protected void onCreate(Bundle savedInstanceState) {
27 | super.onCreate(savedInstanceState);
28 | setContentView(R.layout.layout_recyclerview);
29 |
30 | RecyclerView recyclerView = findViewById(R.id.recycleView);
31 | LinearLayoutManager layoutManager = new LinearLayoutManager(this);
32 | recyclerView.setLayoutManager(layoutManager);
33 | RecyclerViewAdapter adapter = new RecyclerViewAdapter(ModelUtil.getNewsList());
34 | recyclerView.setAdapter(adapter);
35 | }
36 |
37 | class RecyclerViewAdapter extends RecyclerView.Adapter {
38 | private List list;
39 |
40 | RecyclerViewAdapter(List list) {
41 | this.list = list;
42 | }
43 |
44 | @NonNull
45 | @Override
46 | public ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int viewType) {
47 | View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_right_image, viewGroup, false);
48 | return new ViewHolder(view);
49 | }
50 |
51 | @Override
52 | public void onBindViewHolder(@NonNull ViewHolder viewHolder, int position) {
53 | NewsModel entity = list.get(position);
54 | viewHolder.tvTitle.setText(entity.getTitle());
55 | viewHolder.imageView.centerCrop().load(entity.getImage_url(), R.color.placeholder);
56 | viewHolder.llRootView.setOnClickListener(v -> Toast.makeText(mContext, entity.getTitle(), Toast.LENGTH_SHORT).show());
57 | }
58 |
59 | @Override
60 | public int getItemCount() {
61 | return list.size();
62 | }
63 |
64 | class ViewHolder extends RecyclerView.ViewHolder {
65 | LinearLayout llRootView;
66 | TextView tvTitle;
67 | GlideImageView imageView;
68 |
69 | ViewHolder(View view) {
70 | super(view);
71 | llRootView = view.findViewById(R.id.ll_root_view);
72 | tvTitle = view.findViewById(R.id.tv_title);
73 | imageView = view.findViewById(R.id.giv);
74 | }
75 | }
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/Sample/src/main/java/com/sunfusheng/glideimageview/sample/about/AboutActivity.java:
--------------------------------------------------------------------------------
1 | package com.sunfusheng.glideimageview.sample.about;
2 |
3 | import android.content.Context;
4 | import android.content.Intent;
5 | import android.os.Bundle;
6 | import android.support.design.widget.AppBarLayout;
7 | import android.support.design.widget.CollapsingToolbarLayout;
8 | import android.support.v7.widget.Toolbar;
9 | import android.view.KeyEvent;
10 | import android.view.View;
11 | import android.widget.TextView;
12 |
13 | import com.sunfusheng.GlideImageView;
14 | import com.sunfusheng.glideimageview.sample.BaseActivity;
15 | import com.sunfusheng.glideimageview.sample.R;
16 | import com.sunfusheng.glideimageview.sample.util.AppUtil;
17 |
18 | /**
19 | * Created by sunfusheng on 2017/6/18.
20 | */
21 | public class AboutActivity extends BaseActivity {
22 |
23 | WebViewWrapper webViewWrapper;
24 | Toolbar toolbar;
25 | CollapsingToolbarLayout collapsingToolbarLayout;
26 | GlideImageView ivGirl;
27 | TextView tvTitle;
28 | AppBarLayout appBarLayout;
29 |
30 | private String url = "file:///android_asset/about.html";
31 |
32 | public static void startActivity(Context context) {
33 | Intent intent = new Intent(context, AboutActivity.class);
34 | context.startActivity(intent);
35 | }
36 |
37 | @Override
38 | protected void onCreate(Bundle savedInstanceState) {
39 | super.onCreate(savedInstanceState);
40 | setStatusBarTranslucent(false);
41 | setContentView(R.layout.activity_about);
42 |
43 | initView();
44 | initToolBar();
45 | webViewWrapper.loadUrl(url);
46 | }
47 |
48 | private void initView() {
49 | webViewWrapper = (WebViewWrapper) findViewById(R.id.webViewWrapper);
50 | toolbar = (Toolbar) findViewById(R.id.toolbar);
51 | collapsingToolbarLayout = (CollapsingToolbarLayout) findViewById(R.id.collapsingToolbarLayout);
52 | ivGirl = (GlideImageView) findViewById(R.id.iv_girl);
53 | tvTitle = (TextView) findViewById(R.id.tv_title);
54 | appBarLayout = (AppBarLayout) findViewById(R.id.appBarLayout);
55 | }
56 |
57 | private void initToolBar() {
58 | setSupportActionBar(toolbar);
59 | getSupportActionBar().setDisplayHomeAsUpEnabled(true);
60 | toolbar.setNavigationOnClickListener(new View.OnClickListener() {
61 | @Override
62 | public void onClick(View v) {
63 | onBackPressed();
64 | }
65 | });
66 | collapsingToolbarLayout.setTitle("");
67 | toolbar.setTitle("");
68 | collapsingToolbarLayout.setExpandedTitleColor(getResources().getColor(R.color.transparent));//设置还没收缩时状态下字体颜色
69 | collapsingToolbarLayout.setCollapsedTitleTextColor(getResources().getColor(R.color.transparent));//设置收缩后Toolbar上字体的颜色
70 | tvTitle.setText(getString(R.string.app_name) + " (" + AppUtil.getVersionName(this) + ")");
71 | appBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
72 | @Override
73 | public void onOffsetChanged(AppBarLayout appBar, int offset) {
74 | tvTitle.setAlpha(Math.abs(offset * 1f / appBar.getTotalScrollRange()));
75 | }
76 | });
77 | }
78 |
79 | @Override
80 | protected void onResume() {
81 | super.onResume();
82 | webViewWrapper.onResume();
83 | }
84 |
85 | @Override
86 | protected void onPause() {
87 | super.onPause();
88 | webViewWrapper.onPause();
89 | }
90 |
91 | @Override
92 | protected void onDestroy() {
93 | webViewWrapper.onDestroy();
94 | super.onDestroy();
95 | }
96 |
97 | @Override
98 | public boolean onKeyDown(int keyCode, KeyEvent event) {
99 | if (keyCode == KeyEvent.KEYCODE_BACK && webViewWrapper.goBack()) {
100 | return true;
101 | }
102 | return super.onKeyDown(keyCode, event);
103 | }
104 |
105 | }
106 |
--------------------------------------------------------------------------------
/Sample/src/main/java/com/sunfusheng/glideimageview/sample/about/WebViewWrapper.java:
--------------------------------------------------------------------------------
1 | package com.sunfusheng.glideimageview.sample.about;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.content.Context;
5 | import android.graphics.Bitmap;
6 | import android.support.annotation.DrawableRes;
7 | import android.util.AttributeSet;
8 | import android.view.LayoutInflater;
9 | import android.view.View;
10 | import android.webkit.WebChromeClient;
11 | import android.webkit.WebResourceError;
12 | import android.webkit.WebResourceRequest;
13 | import android.webkit.WebSettings;
14 | import android.webkit.WebView;
15 | import android.webkit.WebViewClient;
16 | import android.widget.ProgressBar;
17 | import android.widget.RelativeLayout;
18 |
19 | import com.sunfusheng.glideimageview.sample.R;
20 |
21 | /**
22 | * Created by sunfusheng on 2017/2/15.
23 | */
24 | @SuppressLint("SetJavaScriptEnabled")
25 | public class WebViewWrapper extends RelativeLayout {
26 |
27 | private WebView webView;
28 | private ProgressBar progressBar;
29 |
30 | private String mUrl;
31 |
32 | public WebViewWrapper(Context context) {
33 | this(context, null);
34 | }
35 |
36 | public WebViewWrapper(Context context, AttributeSet attrs) {
37 | this(context, attrs, 0);
38 | }
39 |
40 | public WebViewWrapper(Context context, AttributeSet attrs, int defStyleAttr) {
41 | super(context, attrs, defStyleAttr);
42 | initView(context);
43 | initWebViewSettings();
44 | initListener();
45 | }
46 |
47 | private void initView(Context context) {
48 | LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
49 | View view = inflater.inflate(R.layout.layout_webview, this);
50 | webView = (WebView) view.findViewById(R.id.webView);
51 | progressBar = (ProgressBar) view.findViewById(R.id.progressBar);
52 | }
53 |
54 | private void initWebViewSettings() {
55 | WebSettings settings = webView.getSettings();
56 | settings.setJavaScriptEnabled(true); // 默认false,设置true后我们才能在WebView里与我们的JS代码进行交互
57 | settings.setJavaScriptCanOpenWindowsAutomatically(true); // 设置JS是否可以打开WebView新窗口
58 |
59 | settings.setSupportZoom(true); // 支持缩放
60 | settings.setBuiltInZoomControls(true); // 支持手势缩放
61 | settings.setDisplayZoomControls(false); // 不显示缩放按钮
62 |
63 | settings.setDatabaseEnabled(true);
64 | settings.setSaveFormData(true);
65 | settings.setDomStorageEnabled(true);
66 | settings.setGeolocationEnabled(true);
67 | settings.setAppCacheEnabled(true);
68 |
69 | settings.setUseWideViewPort(true); // 将图片调整到适合WebView的大小
70 | settings.setLoadWithOverviewMode(true); // 自适应屏幕
71 |
72 | webView.setHorizontalScrollBarEnabled(false);
73 | webView.setScrollbarFadingEnabled(true);
74 | webView.setScrollBarStyle(View.SCROLLBARS_OUTSIDE_OVERLAY);
75 | webView.setOverScrollMode(View.OVER_SCROLL_NEVER); // 取消WebView中滚动或拖动到顶部、底部时的阴影
76 | }
77 |
78 | private void initListener() {
79 | webView.setWebViewClient(new WebViewClient() {
80 | @Override
81 | public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
82 | return super.shouldOverrideUrlLoading(view, request);
83 | }
84 |
85 | @Override
86 | public void onPageStarted(WebView view, String url, Bitmap favicon) {
87 | super.onPageStarted(view, url, favicon);
88 | progressBar.setVisibility(View.VISIBLE);
89 | }
90 |
91 | @Override
92 | public void onPageFinished(WebView view, String url) {
93 | super.onPageFinished(view, url);
94 | progressBar.setVisibility(View.GONE);
95 | }
96 |
97 | @Override
98 | public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
99 | super.onReceivedError(view, request, error);
100 | progressBar.setVisibility(View.GONE);
101 | }
102 | });
103 |
104 | webView.setWebChromeClient(new WebChromeClient() {
105 | @Override
106 | public void onProgressChanged(WebView view, int newProgress) {
107 | if (newProgress >= 100) {
108 | progressBar.setVisibility(View.GONE);
109 | } else {
110 | if (progressBar.getVisibility() == View.GONE) {
111 | progressBar.setVisibility(View.VISIBLE);
112 | }
113 | progressBar.setProgress(newProgress);
114 | }
115 | super.onProgressChanged(view, newProgress);
116 |
117 | }
118 | });
119 |
120 |
121 | }
122 |
123 | public void loadUrl(String url) {
124 | mUrl = url;
125 | webView.loadUrl(url);
126 | }
127 |
128 | public void setProgressDrawable(@DrawableRes int id) {
129 | progressBar.setProgressDrawable(progressBar.getContext().getResources().getDrawable(id));
130 | }
131 |
132 | public WebView getWebView() {
133 | return webView;
134 | }
135 |
136 | public String getUrl() {
137 | return mUrl;
138 | }
139 |
140 | public boolean goBack() {
141 | if (webView.canGoBack()) {
142 | webView.goBack();
143 | return true;
144 | }
145 | return false;
146 | }
147 |
148 | public void onResume() {
149 | webView.getSettings().setJavaScriptEnabled(true);
150 | webView.onResume();
151 | }
152 |
153 | public void onPause() {
154 | webView.getSettings().setJavaScriptEnabled(false);
155 | webView.onPause();
156 | }
157 |
158 | public void onDestroy() {
159 | webView.setVisibility(GONE);
160 | webView.destroy();
161 | }
162 |
163 | }
164 |
--------------------------------------------------------------------------------
/Sample/src/main/java/com/sunfusheng/glideimageview/sample/image/FixedViewPager.java:
--------------------------------------------------------------------------------
1 | package com.sunfusheng.glideimageview.sample.image;
2 |
3 | import android.content.Context;
4 | import android.support.v4.view.ViewPager;
5 | import android.util.AttributeSet;
6 | import android.view.MotionEvent;
7 |
8 | /** 修复图片在ViewPager控件中缩放报错的BUG */
9 | public class FixedViewPager extends ViewPager {
10 |
11 | public FixedViewPager(Context context) {
12 | super(context);
13 | }
14 |
15 | public FixedViewPager(Context context, AttributeSet attrs) {
16 | super(context, attrs);
17 | }
18 |
19 | @Override
20 | public boolean onTouchEvent(MotionEvent ev) {
21 | try {
22 | return super.onTouchEvent(ev);
23 | } catch (IllegalArgumentException ex) {
24 | ex.printStackTrace();
25 | }
26 | return false;
27 | }
28 |
29 | @Override
30 | public boolean onInterceptTouchEvent(MotionEvent ev) {
31 | try {
32 | return super.onInterceptTouchEvent(ev);
33 | } catch (IllegalArgumentException ex) {
34 | ex.printStackTrace();
35 | }
36 | return false;
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Sample/src/main/java/com/sunfusheng/glideimageview/sample/image/ImagesActivity.java:
--------------------------------------------------------------------------------
1 | package com.sunfusheng.glideimageview.sample.image;
2 |
3 | import android.animation.Animator;
4 | import android.animation.ValueAnimator;
5 | import android.app.Activity;
6 | import android.content.Intent;
7 | import android.graphics.Color;
8 | import android.os.Bundle;
9 | import android.support.v4.view.ViewPager;
10 | import android.view.ViewTreeObserver;
11 | import android.widget.RelativeLayout;
12 | import android.widget.TextView;
13 |
14 | import com.github.chrisbanes.photoview.PhotoView;
15 | import com.sunfusheng.glideimageview.sample.R;
16 | import com.sunfusheng.glideimageview.sample.util.ColorUtil;
17 | import com.sunfusheng.glideimageview.sample.util.StatusBarUtil;
18 | import com.sunfusheng.widget.ImageData;
19 | import com.sunfusheng.util.Utils;
20 |
21 | import java.util.List;
22 |
23 | public class ImagesActivity extends Activity implements ViewTreeObserver.OnPreDrawListener {
24 |
25 | public static final String IMAGE_ATTR = "image_attr";
26 | public static final String CUR_POSITION = "cur_position";
27 | public static final int ANIM_DURATION = 300; // ms
28 |
29 | private RelativeLayout rootView;
30 | private ViewPager viewPager;
31 | private TextView tvTip;
32 | private ImagesAdapter mAdapter;
33 | private List imageAttrs;
34 | private boolean isAnimating;
35 |
36 | private int curPosition;
37 | private int screenWidth;
38 | private int screenHeight;
39 | private float scaleX;
40 | private float scaleY;
41 | private float translationX;
42 | private float translationY;
43 |
44 | @Override
45 | protected void onCreate(Bundle savedInstanceState) {
46 | super.onCreate(savedInstanceState);
47 | setContentView(R.layout.activity_preview);
48 | StatusBarUtil.setStatusBarTranslucent(this, false);
49 |
50 | viewPager = (ViewPager) findViewById(R.id.viewPager);
51 | tvTip = (TextView) findViewById(R.id.tv_tip);
52 | rootView = (RelativeLayout) findViewById(R.id.rootView);
53 | screenWidth = Utils.getWindowWidth(this);
54 | screenHeight = Utils.getWindowHeight(this);
55 |
56 | Intent intent = getIntent();
57 | imageAttrs = (List) intent.getSerializableExtra(IMAGE_ATTR);
58 | curPosition = intent.getIntExtra(CUR_POSITION, 0);
59 | tvTip.setText(String.format(getString(R.string.image_index), (curPosition + 1), imageAttrs.size()));
60 |
61 | mAdapter = new ImagesAdapter(this, imageAttrs);
62 | viewPager.setAdapter(mAdapter);
63 | viewPager.setCurrentItem(curPosition);
64 | viewPager.getViewTreeObserver().addOnPreDrawListener(this);
65 | viewPager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
66 | @Override
67 | public void onPageSelected(int position) {
68 | curPosition = position;
69 | tvTip.setText(String.format(getString(R.string.image_index), (curPosition + 1), imageAttrs.size()));
70 | }
71 | });
72 | }
73 |
74 | @Override
75 | public void onBackPressed() {
76 | finishWithAnim();
77 | }
78 |
79 | private void initImageAttr(PhotoView photoView, ImageData attr, boolean isFinish) {
80 | // int originalWidth = attr.width;
81 | // int originalHeight = attr.height;
82 | // int originalCenterX = attr.left + originalWidth / 2;
83 | // int originalCenterY = attr.top + originalHeight / 2;
84 | //
85 | // float widthRatio = screenWidth * 1.0f / attr.realWidth;
86 | // float heightRatio = screenHeight * 1.0f / attr.realHeight;
87 | // int finalHeight = (int) (attr.realHeight * widthRatio);
88 | // int finalWidth = screenWidth; //imageAttrs.size() == 1 ? screenWidth : finalHeight;
89 | //
90 | // scaleX = originalWidth * 1.0f / finalWidth;
91 | // scaleY = originalHeight * 1.0f / finalHeight;
92 | // translationX = originalCenterX - screenWidth / 2;
93 | // translationY = originalCenterY - screenHeight / 2;
94 | //
95 | // Log.d("--->", "(left, top): (" + attr.left + ", " + attr.top + ")");
96 | // Log.d("--->", "originalWidth: " + originalWidth + " originalHeight: " + originalHeight);
97 | // Log.d("--->", "finalWidth: " + finalWidth + " finalHeight: " + finalHeight);
98 | // Log.d("--->", "scaleX: " + scaleX + " scaleY: " + scaleY);
99 | // Log.d("--->", "translationX: " + translationX + " translationY: " + translationY);
100 | // Log.d("--->", "" + attr.toString());
101 | // Log.d("--->", "----------------------------------------------------------------");
102 | }
103 |
104 | @Override
105 | public boolean onPreDraw() {
106 | // if (isAnimating) return true;
107 | // rootView.getViewTreeObserver().removeOnPreDrawListener(this);
108 | // PhotoView photoView = mAdapter.getPhotoView(curPosition);
109 | // ImageAttr attr = imageAttrs.get(curPosition);
110 | // initImageAttr(photoView, attr, false);
111 | //
112 | // translateXAnim(photoView, translationX, 0);
113 | // translateYAnim(photoView, translationY, 0);
114 | // scaleXAnim(photoView, scaleX, 1);
115 | // scaleYAnim(photoView, scaleY, 1);
116 | // setBackgroundColor(0f, 1f, new Animator.AnimatorListener() {
117 | // @Override
118 | // public void onAnimationStart(Animator animation) {
119 | // isAnimating = true;
120 | // }
121 | //
122 | // @Override
123 | // public void onAnimationEnd(Animator animation) {
124 | // isAnimating = false;
125 | // }
126 | //
127 | // @Override
128 | // public void onAnimationCancel(Animator animation) {
129 | // }
130 | //
131 | // @Override
132 | // public void onAnimationRepeat(Animator animation) {
133 | // }
134 | // });
135 | return true;
136 | }
137 |
138 | public void finishWithAnim() {
139 | if (isAnimating) return;
140 | PhotoView photoView = mAdapter.getPhotoView(curPosition);
141 | photoView.setScale(1f);
142 | ImageData attr = imageAttrs.get(curPosition);
143 | initImageAttr(photoView, attr, true);
144 |
145 | translateXAnim(photoView, 0, translationX);
146 | translateYAnim(photoView, 0, translationY);
147 | scaleXAnim(photoView, 1, scaleX);
148 | scaleYAnim(photoView, 1, scaleY);
149 | setBackgroundColor(1f, 0f, new Animator.AnimatorListener() {
150 | @Override
151 | public void onAnimationStart(Animator animation) {
152 | isAnimating = true;
153 | }
154 |
155 | @Override
156 | public void onAnimationEnd(Animator animation) {
157 | isAnimating = false;
158 | finish();
159 | overridePendingTransition(0, 0);
160 | }
161 |
162 | @Override
163 | public void onAnimationCancel(Animator animation) {
164 | }
165 |
166 | @Override
167 | public void onAnimationRepeat(Animator animation) {
168 | }
169 | });
170 | }
171 |
172 | private void translateXAnim(PhotoView photoView, float from, float to) {
173 | ValueAnimator anim = ValueAnimator.ofFloat(from, to);
174 | anim.addUpdateListener(it -> photoView.setX((Float) it.getAnimatedValue()));
175 | anim.setDuration(ANIM_DURATION);
176 | anim.start();
177 | }
178 |
179 | private void translateYAnim(PhotoView photoView, float from, float to) {
180 | ValueAnimator anim = ValueAnimator.ofFloat(from, to);
181 | anim.addUpdateListener(it -> photoView.setY((Float) it.getAnimatedValue()));
182 | anim.setDuration(ANIM_DURATION);
183 | anim.start();
184 | }
185 |
186 | private void scaleXAnim(PhotoView photoView, float from, float to) {
187 | ValueAnimator anim = ValueAnimator.ofFloat(from, to);
188 | anim.addUpdateListener(it -> photoView.setScaleX((Float) it.getAnimatedValue()));
189 | anim.setDuration(ANIM_DURATION);
190 | anim.start();
191 | }
192 |
193 | private void scaleYAnim(PhotoView photoView, float from, float to) {
194 | ValueAnimator anim = ValueAnimator.ofFloat(from, to);
195 | anim.addUpdateListener(it -> photoView.setScaleY((Float) it.getAnimatedValue()));
196 | anim.setDuration(ANIM_DURATION);
197 | anim.start();
198 | }
199 |
200 | private void setBackgroundColor(float from, float to, Animator.AnimatorListener listener) {
201 | ValueAnimator anim = ValueAnimator.ofFloat(from, to);
202 | anim.addUpdateListener(it -> rootView.setBackgroundColor(ColorUtil.evaluate((Float) it.getAnimatedValue(), Color.TRANSPARENT, Color.BLACK)));
203 | anim.setDuration(ANIM_DURATION);
204 | if (listener != null) {
205 | anim.addListener(listener);
206 | }
207 | anim.start();
208 | }
209 | }
210 |
--------------------------------------------------------------------------------
/Sample/src/main/java/com/sunfusheng/glideimageview/sample/image/ImagesAdapter.java:
--------------------------------------------------------------------------------
1 | package com.sunfusheng.glideimageview.sample.image;
2 |
3 | import android.content.Context;
4 | import android.support.annotation.NonNull;
5 | import android.support.v4.view.PagerAdapter;
6 | import android.util.SparseArray;
7 | import android.view.LayoutInflater;
8 | import android.view.View;
9 | import android.view.ViewGroup;
10 | import android.widget.ImageView;
11 |
12 | import com.github.chrisbanes.photoview.OnOutsidePhotoTapListener;
13 | import com.github.chrisbanes.photoview.OnPhotoTapListener;
14 | import com.github.chrisbanes.photoview.PhotoView;
15 | import com.sunfusheng.glideimageview.sample.R;
16 | import com.sunfusheng.widget.ImageData;
17 | import com.sunfusheng.progress.CircleProgressView;
18 |
19 | import java.util.List;
20 |
21 | public class ImagesAdapter extends PagerAdapter implements OnPhotoTapListener, OnOutsidePhotoTapListener {
22 |
23 | private Context mContext;
24 | private LayoutInflater mInflater;
25 | private List images;
26 | private SparseArray photoViews = new SparseArray<>();
27 |
28 | public ImagesAdapter(Context context, @NonNull List images) {
29 | super();
30 | this.mContext = context;
31 | this.mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
32 | this.images = images;
33 | }
34 |
35 | @Override
36 | public int getCount() {
37 | return images.size();
38 | }
39 |
40 | @Override
41 | public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
42 | return view == object;
43 | }
44 |
45 | @Override
46 | public void setPrimaryItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
47 | super.setPrimaryItem(container, position, object);
48 | }
49 |
50 | public PhotoView getPhotoView(int index) {
51 | return photoViews.get(index);
52 | }
53 |
54 | @Override
55 | public Object instantiateItem(@NonNull ViewGroup container, int position) {
56 | View view = mInflater.inflate(R.layout.item_photoview, container, false);
57 | CircleProgressView progressView = (CircleProgressView) view.findViewById(R.id.progressView);
58 | PhotoView photoView = (PhotoView) view.findViewById(R.id.photoView);
59 | photoView.setScaleType(ImageView.ScaleType.FIT_CENTER);
60 | photoView.setOnPhotoTapListener(this);
61 | photoView.setOnOutsidePhotoTapListener(this);
62 | photoViews.put(position, photoView);
63 |
64 | // GlideImageLoader imageLoader = GlideImageLoader.create(photoView);
65 | // imageLoader.setOnGlideImageViewListener(url, (percent, isDone, exception) -> {
66 | // progressView.setProgress(percent);
67 | // progressView.setVisibility(isDone ? View.GONE : View.VISIBLE);
68 | // });
69 | // RequestOptions requestOptions = imageLoader.requestOptions(R.color.placeholder)
70 | // .centerCrop()
71 | // .skipMemoryCache(false)
72 | // .diskCacheStrategy(DiskCacheStrategy.RESOURCE)
73 | // .override(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL);
74 | // RequestBuilder requestBuilder = imageLoader.requestBuilder(url, requestOptions)
75 | // .transition(DrawableTransitionOptions.withCrossFade());
76 | // requestBuilder.into(new SimpleTarget(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL) {
77 | // @Override
78 | // public void onResourceReady(Drawable resource, Transition super Drawable> transition) {
79 | // if (resource.getIntrinsicHeight() > DisplayUtil.getScreenHeight(mContext)) {
80 | // photoView.setScaleType(ImageView.ScaleType.CENTER_CROP);
81 | // }
82 | // requestBuilder.into(photoView);
83 | // }
84 | // });
85 |
86 | // container.addView(view, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
87 | return view;
88 | }
89 |
90 | @Override
91 | public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
92 | container.removeView((View) object);
93 | }
94 |
95 | @Override
96 | public void onPhotoTap(ImageView view, float x, float y) {
97 | ((ImagesActivity) mContext).finishWithAnim();
98 | }
99 |
100 | @Override
101 | public void onOutsidePhotoTap(ImageView imageView) {
102 | ((ImagesActivity) mContext).finishWithAnim();
103 | }
104 | }
--------------------------------------------------------------------------------
/Sample/src/main/java/com/sunfusheng/glideimageview/sample/image/NineImageViewEventAdapter.java:
--------------------------------------------------------------------------------
1 | package com.sunfusheng.glideimageview.sample.image;
2 |
3 | import android.app.Activity;
4 | import android.content.Context;
5 | import android.content.Intent;
6 | import android.os.Bundle;
7 |
8 | import com.sunfusheng.widget.ImageData;
9 | import com.sunfusheng.widget.NineImageView;
10 |
11 | import java.io.Serializable;
12 | import java.util.List;
13 |
14 |
15 | public class NineImageViewEventAdapter {
16 |
17 | protected void onImageItemClick(Context context, NineImageView nineImageView, int index, List images) {
18 | // for (int i = 0; i < images.size(); i++) {
19 | // ImageData attr = images.get(i);
20 | // View imageView = nineImageView.getChildAt(i);
21 | // if (i >= nineImageView.getMaxSize()) {
22 | // imageView = nineImageView.getChildAt(nineImageView.getMaxSize() - 1);
23 | // }
24 | // attr.width = imageView.getWidth();
25 | // attr.height = imageView.getHeight();
26 | // int[] points = new int[2];
27 | // imageView.getLocationInWindow(points);
28 | // attr.left = points[0];
29 | // attr.top = points[1];
30 | // }
31 |
32 | Intent intent = new Intent(context, ImagesActivity.class);
33 | Bundle bundle = new Bundle();
34 | bundle.putSerializable(ImagesActivity.IMAGE_ATTR, (Serializable) images);
35 | bundle.putInt(ImagesActivity.CUR_POSITION, index);
36 | intent.putExtras(bundle);
37 | context.startActivity(intent);
38 | ((Activity) context).overridePendingTransition(0, 0);
39 | }
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/Sample/src/main/java/com/sunfusheng/glideimageview/sample/image/SingleImageActivity.java:
--------------------------------------------------------------------------------
1 | package com.sunfusheng.glideimageview.sample.image;
2 |
3 | import android.os.Bundle;
4 | import android.support.annotation.Nullable;
5 | import android.support.v7.app.AppCompatActivity;
6 | import android.view.View;
7 |
8 | import com.sunfusheng.GlideImageView;
9 | import com.sunfusheng.glideimageview.sample.R;
10 | import com.sunfusheng.progress.CircleProgressView;
11 |
12 | /**
13 | * @author by sunfusheng on 2017/6/15.
14 | */
15 | public class SingleImageActivity extends AppCompatActivity {
16 |
17 | public static final String KEY_IMAGE_URL = "image_url";
18 | public static final String KEY_IMAGE_URL_THUMBNAIL = "image_url_thumbnail";
19 |
20 | GlideImageView glideImageView;
21 | CircleProgressView progressView;
22 |
23 | String image_url;
24 | String image_url_thumbnail;
25 |
26 | @Override
27 | protected void onCreate(@Nullable Bundle savedInstanceState) {
28 | super.onCreate(savedInstanceState);
29 | setContentView(R.layout.activity_image);
30 |
31 | image_url = getIntent().getStringExtra(KEY_IMAGE_URL);
32 | image_url_thumbnail = getIntent().getStringExtra(KEY_IMAGE_URL_THUMBNAIL);
33 |
34 | glideImageView = findViewById(R.id.glideImageView);
35 | progressView = findViewById(R.id.progressView);
36 | glideImageView.setOnClickListener(v -> onBackPressed());
37 |
38 | loadImage();
39 | }
40 |
41 | private void loadImage() {
42 | glideImageView.load(image_url, R.color.transparent, (isComplete, percentage, bytesRead, totalBytes) -> {
43 | if (isComplete) {
44 | progressView.setVisibility(View.GONE);
45 | } else {
46 | progressView.setVisibility(View.VISIBLE);
47 | progressView.setProgress(percentage);
48 | }
49 | });
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/Sample/src/main/java/com/sunfusheng/glideimageview/sample/model/ImageModel.java:
--------------------------------------------------------------------------------
1 | package com.sunfusheng.glideimageview.sample.model;
2 |
3 | import com.sunfusheng.widget.ImageData;
4 |
5 | import java.io.Serializable;
6 | import java.util.List;
7 |
8 | /**
9 | * @author by sunfusheng on 2017/6/27.
10 | */
11 | public class ImageModel implements Serializable {
12 | public String desc;
13 | public List images;
14 |
15 | public ImageModel(String desc, List images) {
16 | this.desc = desc;
17 | this.images = images;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/Sample/src/main/java/com/sunfusheng/glideimageview/sample/model/ModelUtil.java:
--------------------------------------------------------------------------------
1 | package com.sunfusheng.glideimageview.sample.model;
2 |
3 | import com.sunfusheng.widget.ImageData;
4 |
5 | import java.util.ArrayList;
6 | import java.util.List;
7 |
8 | /**
9 | * @author by sunfusheng on 2017/6/27.
10 | */
11 | public class ModelUtil {
12 |
13 | public static List getImages() {
14 | List list = new ArrayList<>();
15 |
16 | List images = new ArrayList<>();
17 | images.add(new ImageData("http://img3.imgtn.bdimg.com/it/u=3040385967,1031044866&fm=21&gp=0.jpg"));
18 | images.add(new ImageData("http://img1.imgtn.bdimg.com/it/u=1832737924,144748431&fm=21&gp=0.jpg"));
19 | images.add(new ImageData("http://img.zcool.cn/community/01d6dd554b93f0000001bf72b4f6ec.jpg"));
20 | list.add(new ImageModel("2张图片和1张GIF动态图", images));
21 |
22 | images = new ArrayList<>();
23 | images.add(new ImageData("http://5b0988e595225.cdn.sohucs.com/images/20171202/a1cc52d5522f48a8a2d6e7426b13f82b.gif"));
24 | list.add(new ImageModel("1张GIF动态图", images));
25 |
26 | images = new ArrayList<>();
27 | images.add(new ImageData("http://img3.imgtn.bdimg.com/it/u=524208507,12616758&fm=206&gp=0.jpg"));
28 | images.add(new ImageData("http://img5.imgtn.bdimg.com/it/u=2091366266,1524114981&fm=21&gp=0.jpg"));
29 | images.add(new ImageData("http://img5.imgtn.bdimg.com/it/u=1424970962,1243597989&fm=21&gp=0.jpg"));
30 | list.add(new ImageModel("3张图片", images));
31 |
32 | images = new ArrayList<>();
33 | ImageData imageData = new ImageData("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1529402445474&di=b5da3b2f6a466e618e1e32d4dd2bda4d&imgtype=0&src=http%3A%2F%2F2b.zol-img.com.cn%2Fproduct%2F133_500x2000%2F801%2Fce21ke76FRh4A.jpg");
34 | imageData.realWidth = 500;
35 | imageData.realHeight = 281;
36 | images.add(imageData);
37 | list.add(new ImageModel("一个小猫咪", images));
38 |
39 | images = new ArrayList<>();
40 | imageData = new ImageData("http://pic.58pic.com/58pic/13/62/02/07d58PICcxz_1024.jpg");
41 | imageData.realWidth = 1024;
42 | imageData.realHeight = 529;
43 | images.add(imageData);
44 | list.add(new ImageModel("画卷:天道酬勤", images));
45 |
46 | images = new ArrayList<>();
47 | imageData = new ImageData("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1498629002766&di=6fac924b9c9bc0858074a5eb455e4bd8&imgtype=0&src=http%3A%2F%2Fimg1.3lian.com%2F2015%2Fw21%2F8%2Fd%2F85.jpg");
48 | imageData.realWidth = 450;
49 | imageData.realHeight = 798;
50 | images.add(imageData);
51 | list.add(new ImageModel("又一个小猫咪", images));
52 |
53 | images = new ArrayList<>();
54 | images.add(new ImageData("http://img15.3lian.com/2015/h1/308/d/199.jpg"));
55 | images.add(new ImageData("http://pic1.win4000.com/wallpaper/f/566a714a786cc.jpg"));
56 | images.add(new ImageData("http://img15.3lian.com/2015/h1/308/d/204.jpg"));
57 | images.add(new ImageData("http://imglf1.ph.126.net/DIe00tFQ1SZOdKUDG8AO1g==/2068278128970036688.jpg"));
58 | list.add(new ImageModel("世界著名建筑", images));
59 |
60 | images = new ArrayList<>();
61 | imageData = new ImageData("http://wx4.sinaimg.cn/mw690/e59bcb0dly1fgqlue0vtvj20c83htx3d.jpg");
62 | imageData.realWidth = 440;
63 | imageData.realHeight = 4529;
64 | images.add(imageData);
65 | list.add(new ImageModel("开发者头条的截图(440X4529)", images));
66 |
67 | images = new ArrayList<>();
68 | images.add(new ImageData("http://img2.imgtn.bdimg.com/it/u=2850936076,2080165544&fm=206&gp=0.jpg"));
69 | images.add(new ImageData("http://img3.imgtn.bdimg.com/it/u=524208507,12616758&fm=206&gp=0.jpg"));
70 | images.add(new ImageData("http://img3.imgtn.bdimg.com/it/u=698582197,4250615262&fm=206&gp=0.jpg"));
71 | images.add(new ImageData("http://img5.imgtn.bdimg.com/it/u=3191365283,111438732&fm=21&gp=0.jpg"));
72 | images.add(new ImageData("http://img5.imgtn.bdimg.com/it/u=482494496,1350922497&fm=206&gp=0.jpg"));
73 | images.add(new ImageData("http://img4.imgtn.bdimg.com/it/u=2440866214,1867472386&fm=21&gp=0.jpg"));
74 | images.add(new ImageData("http://img3.imgtn.bdimg.com/it/u=3040385967,1031044866&fm=21&gp=0.jpg"));
75 | images.add(new ImageData("http://img1.imgtn.bdimg.com/it/u=1832737924,144748431&fm=21&gp=0.jpg"));
76 | images.add(new ImageData("http://img5.imgtn.bdimg.com/it/u=2091366266,1524114981&fm=21&gp=0.jpg"));
77 | images.add(new ImageData("http://img5.imgtn.bdimg.com/it/u=2091366266,1524114981&fm=21&gp=0.jpg"));
78 | images.add(new ImageData("http://img5.imgtn.bdimg.com/it/u=1424970962,1243597989&fm=21&gp=0.jpg"));
79 | list.add(new ImageModel("11张图片", images));
80 |
81 | images = new ArrayList<>();
82 | images.add(new ImageData("http://img2.imgtn.bdimg.com/it/u=2850936076,2080165544&fm=206&gp=0.jpg"));
83 | images.add(new ImageData("http://img3.imgtn.bdimg.com/it/u=524208507,12616758&fm=206&gp=0.jpg"));
84 | images.add(new ImageData("http://img3.imgtn.bdimg.com/it/u=698582197,4250615262&fm=206&gp=0.jpg"));
85 | list.add(new ImageModel("3张图片", images));
86 |
87 | images = new ArrayList<>();
88 | images.add(new ImageData("http://img.zcool.cn/community/01d6dd554b93f0000001bf72b4f6ec.jpg"));
89 | images.add(new ImageData("http://5b0988e595225.cdn.sohucs.com/images/20171202/a1cc52d5522f48a8a2d6e7426b13f82b.gif"));
90 | list.add(new ImageModel("2张GIF动态图", images));
91 |
92 | images = new ArrayList<>();
93 | images.add(new ImageData("http://img2.imgtn.bdimg.com/it/u=2850936076,2080165544&fm=206&gp=0.jpg"));
94 | images.add(new ImageData("http://img3.imgtn.bdimg.com/it/u=524208507,12616758&fm=206&gp=0.jpg"));
95 | images.add(new ImageData("http://img3.imgtn.bdimg.com/it/u=698582197,4250615262&fm=206&gp=0.jpg"));
96 | images.add(new ImageData("http://img5.imgtn.bdimg.com/it/u=3191365283,111438732&fm=21&gp=0.jpg"));
97 | images.add(new ImageData("http://img5.imgtn.bdimg.com/it/u=482494496,1350922497&fm=206&gp=0.jpg"));
98 | images.add(new ImageData("http://img4.imgtn.bdimg.com/it/u=2440866214,1867472386&fm=21&gp=0.jpg"));
99 | images.add(new ImageData("http://img3.imgtn.bdimg.com/it/u=3040385967,1031044866&fm=21&gp=0.jpg"));
100 | images.add(new ImageData("http://img1.imgtn.bdimg.com/it/u=1832737924,144748431&fm=21&gp=0.jpg"));
101 | images.add(new ImageData("http://img5.imgtn.bdimg.com/it/u=2091366266,1524114981&fm=21&gp=0.jpg"));
102 | list.add(new ImageModel("9张图片", images));
103 |
104 | images = new ArrayList<>();
105 | images.add(new ImageData("http://img3.imgtn.bdimg.com/it/u=524208507,12616758&fm=206&gp=0.jpg"));
106 | images.add(new ImageData("http://img3.imgtn.bdimg.com/it/u=698582197,4250615262&fm=206&gp=0.jpg"));
107 | images.add(new ImageData("http://img5.imgtn.bdimg.com/it/u=3191365283,111438732&fm=21&gp=0.jpg"));
108 | images.add(new ImageData("http://img5.imgtn.bdimg.com/it/u=482494496,1350922497&fm=206&gp=0.jpg"));
109 | images.add(new ImageData("http://img4.imgtn.bdimg.com/it/u=2440866214,1867472386&fm=21&gp=0.jpg"));
110 | list.add(new ImageModel("5张图片", images));
111 |
112 | images = new ArrayList<>();
113 | images.add(new ImageData("http://img2.imgtn.bdimg.com/it/u=2850936076,2080165544&fm=206&gp=0.jpg"));
114 | images.add(new ImageData("http://img3.imgtn.bdimg.com/it/u=524208507,12616758&fm=206&gp=0.jpg"));
115 | images.add(new ImageData("http://img3.imgtn.bdimg.com/it/u=698582197,4250615262&fm=206&gp=0.jpg"));
116 | images.add(new ImageData("http://img5.imgtn.bdimg.com/it/u=3191365283,111438732&fm=21&gp=0.jpg"));
117 | list.add(new ImageModel("4张图片", images));
118 |
119 | return list;
120 | }
121 |
122 | public static List getNewsList() {
123 | List list = new ArrayList<>();
124 |
125 | list.add(new NewsModel("为迎接伊万卡等宾客访问 印度一座城市将驱逐乞丐",
126 | "http://cms-bucket.nosdn.127.net/c80973c27a4541cda761f6a49045854720171110113147.png?imageView&thumbnail=140y88&quality=85"));
127 |
128 | list.add(new NewsModel("英国“脱欧”终于有眉目!政府将敲定具体离开时间",
129 | "http://cms-bucket.nosdn.127.net/f5e164f5805e4a4480b30d34826c70b920171110090734.png?imageView&thumbnail=140y88&quality=85"));
130 |
131 | list.add(new NewsModel("沙特:因无足够证据 先释放部分因涉贪腐被捕人员",
132 | "http://cms-bucket.nosdn.127.net/49d4eb3d6969440590cfb326b513d97b20171109234915.png?imageView&thumbnail=140y88&quality=85"));
133 |
134 | list.add(new NewsModel("关系骤然紧张!伊朗总统喊话沙特 "宿敌"死结何解?",
135 | "http://cms-bucket.nosdn.127.net/629515b9eb9946cfa65d33401bb1016120171109153300.png?imageView&thumbnail=140y88&quality=85"));
136 |
137 | list.add(new NewsModel("为迎接伊万卡等宾客访问 印度一座城市将驱逐乞丐",
138 | "http://cms-bucket.nosdn.127.net/c80973c27a4541cda761f6a49045854720171110113147.png?imageView&thumbnail=140y88&quality=85"));
139 |
140 | list.add(new NewsModel("英国“脱欧”终于有眉目!政府将敲定具体离开时间",
141 | "http://cms-bucket.nosdn.127.net/f5e164f5805e4a4480b30d34826c70b920171110090734.png?imageView&thumbnail=140y88&quality=85"));
142 |
143 | list.add(new NewsModel("沙特:因无足够证据 先释放部分因涉贪腐被捕人员",
144 | "http://cms-bucket.nosdn.127.net/49d4eb3d6969440590cfb326b513d97b20171109234915.png?imageView&thumbnail=140y88&quality=85"));
145 |
146 | list.add(new NewsModel("关系骤然紧张!伊朗总统喊话沙特 "宿敌"死结何解?",
147 | "http://cms-bucket.nosdn.127.net/629515b9eb9946cfa65d33401bb1016120171109153300.png?imageView&thumbnail=140y88&quality=85"));
148 |
149 | list.add(new NewsModel("为迎接伊万卡等宾客访问 印度一座城市将驱逐乞丐",
150 | "http://cms-bucket.nosdn.127.net/c80973c27a4541cda761f6a49045854720171110113147.png?imageView&thumbnail=140y88&quality=85"));
151 |
152 | list.add(new NewsModel("英国“脱欧”终于有眉目!政府将敲定具体离开时间",
153 | "http://cms-bucket.nosdn.127.net/f5e164f5805e4a4480b30d34826c70b920171110090734.png?imageView&thumbnail=140y88&quality=85"));
154 |
155 | list.add(new NewsModel("沙特:因无足够证据 先释放部分因涉贪腐被捕人员",
156 | "http://cms-bucket.nosdn.127.net/49d4eb3d6969440590cfb326b513d97b20171109234915.png?imageView&thumbnail=140y88&quality=85"));
157 |
158 | list.add(new NewsModel("关系骤然紧张!伊朗总统喊话沙特 "宿敌"死结何解?",
159 | "http://cms-bucket.nosdn.127.net/629515b9eb9946cfa65d33401bb1016120171109153300.png?imageView&thumbnail=140y88&quality=85"));
160 |
161 | return list;
162 | }
163 |
164 | }
165 |
--------------------------------------------------------------------------------
/Sample/src/main/java/com/sunfusheng/glideimageview/sample/model/NewsModel.java:
--------------------------------------------------------------------------------
1 | package com.sunfusheng.glideimageview.sample.model;
2 |
3 | import java.io.Serializable;
4 | import java.util.ArrayList;
5 |
6 | /**
7 | * @author sunfusheng on 2017/11/10.
8 | */
9 | public class NewsModel implements Serializable {
10 |
11 | private String title;
12 | private String image_url;
13 | private ArrayList images;
14 | private int type;
15 |
16 | public NewsModel(String title, String image_url) {
17 | this.title = title;
18 | this.image_url = image_url;
19 | }
20 |
21 | public String getTitle() {
22 | return title;
23 | }
24 |
25 | public void setTitle(String title) {
26 | this.title = title;
27 | }
28 |
29 | public String getImage_url() {
30 | return image_url;
31 | }
32 |
33 | public void setImage_url(String image_url) {
34 | this.image_url = image_url;
35 | }
36 |
37 | public ArrayList getImages() {
38 | return images;
39 | }
40 |
41 | public void setImages(ArrayList images) {
42 | this.images = images;
43 | }
44 |
45 | public int getType() {
46 | return type;
47 | }
48 |
49 | public void setType(int type) {
50 | this.type = type;
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/Sample/src/main/java/com/sunfusheng/glideimageview/sample/util/AppUtil.java:
--------------------------------------------------------------------------------
1 | package com.sunfusheng.glideimageview.sample.util;
2 |
3 | import android.content.Context;
4 | import android.content.pm.PackageInfo;
5 | import android.content.pm.PackageManager;
6 | import android.net.ConnectivityManager;
7 | import android.net.NetworkInfo;
8 | import android.text.TextUtils;
9 |
10 | import java.util.List;
11 |
12 | /**
13 | * Created by sunfusheng on 2017/1/17.
14 | */
15 | public class AppUtil {
16 |
17 | public static boolean notEmpty(List list) {
18 | return !isEmpty(list);
19 | }
20 |
21 | public static boolean isEmpty(List list) {
22 | if (list == null || list.size() == 0) {
23 | return true;
24 | }
25 | return false;
26 | }
27 |
28 | // 判断网络是否可用
29 | public static boolean isNetworkAvailable(Context context) {
30 | try {
31 | ConnectivityManager connectivity = (ConnectivityManager) context.getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
32 | if (connectivity != null) {
33 | NetworkInfo info = connectivity.getActiveNetworkInfo();
34 | if (info != null && info.isConnected()) {
35 | if (info.getState() == NetworkInfo.State.CONNECTED) {
36 | return true;
37 | }
38 | }
39 | }
40 | } catch (Exception e) {
41 | e.printStackTrace();
42 | return false;
43 | }
44 | return false;
45 | }
46 |
47 | // WiFi是否连接
48 | public static boolean isWiFiAvailable(Context context) {
49 | ConnectivityManager connectivityManager = (ConnectivityManager) context.getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
50 | NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
51 | if (networkInfo != null && networkInfo.isAvailable() && networkInfo.getType() == ConnectivityManager.TYPE_WIFI) {
52 | return true;
53 | }
54 | return false;
55 | }
56 |
57 | // 获取当前应用的版本号
58 | public static String getVersionName(Context context) {
59 | try {
60 | PackageManager packageManager = context.getApplicationContext().getPackageManager();
61 | PackageInfo packInfo = packageManager.getPackageInfo(context.getApplicationContext().getPackageName(), 0);
62 | String version = packInfo.versionName;
63 | if (!TextUtils.isEmpty(version)) {
64 | return "V" + version;
65 | }
66 | } catch (Exception e) {
67 | e.printStackTrace();
68 | }
69 | return "V1.0";
70 | }
71 |
72 | // 获取当前应用的版本号
73 | public static int getVersionCode(Context context) {
74 | try {
75 | PackageManager packageManager = context.getApplicationContext().getPackageManager();
76 | PackageInfo packInfo = packageManager.getPackageInfo(context.getApplicationContext().getPackageName(), 0);
77 | return packInfo.versionCode;
78 | } catch (Exception e) {
79 | e.printStackTrace();
80 | }
81 | return 1;
82 | }
83 |
84 | }
85 |
--------------------------------------------------------------------------------
/Sample/src/main/java/com/sunfusheng/glideimageview/sample/util/ColorUtil.java:
--------------------------------------------------------------------------------
1 | package com.sunfusheng.glideimageview.sample.util;
2 |
3 | import android.content.Context;
4 |
5 | /**
6 | * Created by sunfusheng on 16/4/22.
7 | */
8 | public class ColorUtil {
9 |
10 | // 合成新的颜色值
11 | public static int getNewColorByStartEndColor(Context context, float fraction, int startValue, int endValue) {
12 | return evaluate(fraction, context.getResources().getColor(startValue), context.getResources().getColor(endValue));
13 | }
14 | /**
15 | * 合成新的颜色值
16 | * @param fraction 颜色取值的级别 (0.0f ~ 1.0f)
17 | * @param startValue 开始显示的颜色
18 | * @param endValue 结束显示的颜色
19 | * @return 返回生成新的颜色值
20 | */
21 | public static int evaluate(float fraction, int startValue, int endValue) {
22 | int startA = (startValue >> 24) & 0xff;
23 | int startR = (startValue >> 16) & 0xff;
24 | int startG = (startValue >> 8) & 0xff;
25 | int startB = startValue & 0xff;
26 |
27 | int endA = (endValue >> 24) & 0xff;
28 | int endR = (endValue >> 16) & 0xff;
29 | int endG = (endValue >> 8) & 0xff;
30 | int endB = endValue & 0xff;
31 |
32 | return ((startA + (int) (fraction * (endA - startA))) << 24) |
33 | ((startR + (int) (fraction * (endR - startR))) << 16) |
34 | ((startG + (int) (fraction * (endG - startG))) << 8) |
35 | ((startB + (int) (fraction * (endB - startB))));
36 | }
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/Sample/src/main/java/com/sunfusheng/glideimageview/sample/util/StatusBarUtil.java:
--------------------------------------------------------------------------------
1 | package com.sunfusheng.glideimageview.sample.util;
2 |
3 | import android.app.Activity;
4 | import android.graphics.Color;
5 | import android.os.Build;
6 | import android.view.View;
7 | import android.view.Window;
8 | import android.view.WindowManager;
9 |
10 | import java.lang.reflect.Field;
11 | import java.lang.reflect.Method;
12 |
13 | /**
14 | * Created by sunfusheng on 16/11/20.
15 | */
16 | public class StatusBarUtil {
17 |
18 | // 设置状态栏透明与字体颜色
19 | public static void setStatusBarTranslucent(Activity activity, boolean isLightStatusBar) {
20 | if (activity == null) return;
21 | Window window = activity.getWindow();
22 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
23 | window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
24 | } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
25 | window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
26 | window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
27 | | View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
28 | window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
29 | window.setStatusBarColor(Color.TRANSPARENT);
30 | }
31 |
32 | if (isXiaomi()) {
33 | setXiaomiStatusBar(window, isLightStatusBar);
34 | } else if (isMeizu()) {
35 | setMeizuStatusBar(window, isLightStatusBar);
36 | }
37 | }
38 |
39 | // 是否是小米手机
40 | public static boolean isXiaomi() {
41 | return "Xiaomi".equals(Build.MANUFACTURER);
42 | }
43 |
44 | // 设置小米状态栏
45 | public static void setXiaomiStatusBar(Window window, boolean isLightStatusBar) {
46 | Class extends Window> clazz = window.getClass();
47 | try {
48 | Class> layoutParams = Class.forName("android.view.MiuiWindowManager$LayoutParams");
49 | Field field = layoutParams.getField("EXTRA_FLAG_STATUS_BAR_DARK_MODE");
50 | int darkModeFlag = field.getInt(layoutParams);
51 | Method extraFlagField = clazz.getMethod("setExtraFlags", int.class, int.class);
52 | extraFlagField.invoke(window, isLightStatusBar ? darkModeFlag : 0, darkModeFlag);
53 | } catch (Exception e) {
54 | e.printStackTrace();
55 | }
56 | }
57 |
58 | // 是否是魅族手机
59 | public static boolean isMeizu() {
60 | try {
61 | Method method = Build.class.getMethod("hasSmartBar");
62 | return method != null;
63 | } catch (NoSuchMethodException e) {
64 | }
65 | return false;
66 | }
67 |
68 | // 设置魅族状态栏
69 | public static void setMeizuStatusBar(Window window, boolean isLightStatusBar) {
70 | WindowManager.LayoutParams params = window.getAttributes();
71 | try {
72 | Field darkFlag = WindowManager.LayoutParams.class.getDeclaredField("MEIZU_FLAG_DARK_STATUS_BAR_ICON");
73 | Field meizuFlags = WindowManager.LayoutParams.class.getDeclaredField("meizuFlags");
74 | darkFlag.setAccessible(true);
75 | meizuFlags.setAccessible(true);
76 | int bit = darkFlag.getInt(null);
77 | int value = meizuFlags.getInt(params);
78 | if (isLightStatusBar) {
79 | value |= bit;
80 | } else {
81 | value &= ~bit;
82 | }
83 | meizuFlags.setInt(params, value);
84 | window.setAttributes(params);
85 | darkFlag.setAccessible(false);
86 | meizuFlags.setAccessible(false);
87 | } catch (Exception e) {
88 | e.printStackTrace();
89 | }
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/Sample/src/main/java/com/sunfusheng/glideimageview/sample/widget/DraggableFrameLayout.java:
--------------------------------------------------------------------------------
1 | package com.sunfusheng.glideimageview.sample.widget;
2 |
3 | import android.content.Context;
4 | import android.graphics.Rect;
5 | import android.support.annotation.AttrRes;
6 | import android.support.annotation.NonNull;
7 | import android.support.annotation.Nullable;
8 | import android.support.v4.widget.ViewDragHelper;
9 | import android.util.AttributeSet;
10 | import android.view.MotionEvent;
11 | import android.view.View;
12 | import android.widget.FrameLayout;
13 |
14 | import com.sunfusheng.util.Utils;
15 |
16 | /**
17 | * @author by sunfusheng on 2017/6/27.
18 | */
19 | public class DraggableFrameLayout extends FrameLayout {
20 |
21 | private ViewDragHelper dragHelper;
22 | private int screenWidth;
23 | private int margin = 10;
24 |
25 | public DraggableFrameLayout(@NonNull Context context) {
26 | this(context, null);
27 | }
28 |
29 | public DraggableFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs) {
30 | this(context, attrs, 0);
31 | }
32 |
33 | public DraggableFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs,
34 | @AttrRes int defStyleAttr) {
35 | super(context, attrs, defStyleAttr);
36 | init();
37 | }
38 |
39 | private void init() {
40 | screenWidth = Utils.getWindowWidth(getContext());
41 | margin = Utils.dp2px(getContext(), margin);
42 |
43 | dragHelper = ViewDragHelper.create(this, new ViewDragHelper.Callback() {
44 |
45 | @Override
46 | public boolean tryCaptureView(@NonNull View child, int pointerId) {
47 | return true;
48 | }
49 |
50 | @Override
51 | public void onViewCaptured(@NonNull View capturedChild, int activePointerId) {
52 | super.onViewCaptured(capturedChild, activePointerId);
53 | }
54 |
55 | @Override
56 | public int clampViewPositionHorizontal(@NonNull View child, int left, int dx) {
57 | return left;
58 | }
59 |
60 | @Override
61 | public int clampViewPositionVertical(@NonNull View child, int top, int dy) {
62 | return top;
63 | }
64 |
65 | @Override
66 | public int getViewHorizontalDragRange(@NonNull View child) {
67 | return getMeasuredWidth() - child.getMeasuredWidth();
68 | }
69 |
70 | @Override
71 | public int getViewVerticalDragRange(@NonNull View child) {
72 | return getMeasuredHeight() - child.getMeasuredHeight();
73 | }
74 |
75 | @Override
76 | public void onViewReleased(@NonNull View releasedChild, float xvel, float yvel) {
77 | super.onViewReleased(releasedChild, xvel, yvel);
78 | int viewWidth = releasedChild.getWidth();
79 | int viewHeight = releasedChild.getHeight();
80 | int curLeft = releasedChild.getLeft();
81 | int curTop = releasedChild.getTop();
82 |
83 | int finalLeft = margin;
84 | int finalTop = Math.max(curTop, margin);
85 |
86 | if ((curLeft + viewWidth / 2) > screenWidth / 2) {
87 | finalLeft = screenWidth - viewWidth - margin;
88 | }
89 |
90 | if ((finalTop + viewHeight) > getHeight()) {
91 | finalTop = getHeight() - viewHeight - margin;
92 | }
93 |
94 | dragHelper.settleCapturedViewAt(finalLeft, finalTop);
95 | invalidate();
96 | }
97 | });
98 | }
99 |
100 | @Override
101 | public boolean onInterceptTouchEvent(MotionEvent ev) {
102 | return dragHelper.shouldInterceptTouchEvent(ev);
103 | }
104 |
105 | @Override
106 | public boolean onTouchEvent(MotionEvent event) {
107 | dragHelper.processTouchEvent(event);
108 | return isTouchChildView(event);
109 | }
110 |
111 | @Override
112 | public void computeScroll() {
113 | super.computeScroll();
114 | if (dragHelper.continueSettling(true)) {
115 | invalidate();
116 | }
117 | }
118 |
119 | private boolean isTouchChildView(MotionEvent ev) {
120 | Rect rect = new Rect();
121 | for (int i = 0; i < getChildCount(); i++) {
122 | View view = getChildAt(i);
123 | rect.set((int) view.getX(), (int) view.getY(), (int) view.getX() + view.getWidth(),
124 | (int) view.getY() + view.getHeight());
125 | if (rect.contains((int) ev.getX(), (int) ev.getY())) {
126 | return true;
127 | }
128 | }
129 | return false;
130 | }
131 | }
132 |
--------------------------------------------------------------------------------
/Sample/src/main/java/com/sunfusheng/glideimageview/sample/widget/SlideVerticallyLayout.java:
--------------------------------------------------------------------------------
1 | package com.sunfusheng.glideimageview.sample.widget;
2 |
3 | import android.animation.Animator;
4 | import android.animation.AnimatorListenerAdapter;
5 | import android.animation.ValueAnimator;
6 | import android.content.Context;
7 | import android.os.Build;
8 | import android.support.v4.view.ViewCompat;
9 | import android.util.AttributeSet;
10 | import android.view.MotionEvent;
11 | import android.view.View;
12 | import android.widget.FrameLayout;
13 |
14 | import java.util.ArrayList;
15 | import java.util.List;
16 |
17 | public class SlideVerticallyLayout extends FrameLayout {
18 |
19 | private int mDownY;
20 | private int mEndY;
21 | private ValueAnimator mSlideAnimator;
22 | private boolean isCanScroll;
23 | private boolean isTouchWithAnimRunning;
24 | private final int MIN_SCROLL_OFFSET = 50;
25 | private final static int ANIM_DURATION = 280;
26 | private final static int THRESHOLD = 4;
27 | private List mSlideView = new ArrayList<>();
28 | private List slideCblist = new ArrayList<>();
29 | private List stateCblist = new ArrayList<>();
30 | private boolean isSlideShown = true;
31 |
32 | public void addSlideCallback(ISlideCallback callback) {
33 | slideCblist.add(callback);
34 | }
35 |
36 | public void addStateCallback(IStateCallback callback) {
37 | stateCblist.add(callback);
38 | }
39 |
40 | public SlideVerticallyLayout(Context context) {
41 | this(context, null);
42 | }
43 |
44 | public SlideVerticallyLayout(Context context, AttributeSet attrs) {
45 | this(context, attrs, 0);
46 | }
47 |
48 | public SlideVerticallyLayout(Context context, AttributeSet attrs, int defStyleAttr) {
49 | super(context, attrs, defStyleAttr);
50 | init();
51 | }
52 |
53 | void init() {
54 | mSlideAnimator = ValueAnimator.ofFloat(0, 1.0f).setDuration(ANIM_DURATION);
55 | mSlideAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
56 | @Override
57 | public void onAnimationUpdate(ValueAnimator animation) {
58 | float factor = (float) animation.getAnimatedValue();
59 | int diffY = mEndY - mDownY;
60 | for (ISlideCallback cb : slideCblist) {
61 | cb.onPositionChange((int) (mDownY + diffY * factor));
62 | }
63 | }
64 | });
65 | mSlideAnimator.addListener(new AnimatorListenerAdapter() {
66 | @Override
67 | public void onAnimationEnd(Animator animation) {
68 | if (isSlideShown && mEndY == getHeight()) {
69 | isSlideShown = false;
70 | for (IStateCallback cb : stateCblist) {
71 | cb.onHide();
72 | }
73 | } else if (!isSlideShown && mEndY == 0) {
74 | isSlideShown = true;
75 | for (IStateCallback cb : stateCblist) {
76 | cb.onShow();
77 | }
78 | }
79 | mDownY = mEndY;
80 | isCanScroll = false;
81 | }
82 | });
83 | addSlideCallback(offsetY -> {
84 | float factor = (float) (getHeight() - offsetY) / (float) getHeight();
85 | setBackgroundColor(((int) (factor * 0xc4)) << 24);
86 | });
87 | addSlideCallback(offsetY -> {
88 | for (View view : mSlideView) {
89 | view.setTranslationY(offsetY);
90 | }
91 | });
92 | }
93 |
94 | public void addSlideView(View view) {
95 | mSlideView.add(view);
96 | }
97 |
98 | public void slideDown(boolean anim) {
99 | if (!isSlideShown) return;
100 | if (anim) {
101 | mEndY = getHeight();
102 | mDownY = 0;
103 | mSlideAnimator.start();
104 | } else {
105 | for (ISlideCallback cb : slideCblist) {
106 | cb.onPositionChange(getHeight());
107 | }
108 | isSlideShown = false;
109 | }
110 | }
111 |
112 | public void slideUp(boolean anim) {
113 | if (isSlideShown) return;
114 | if (anim) {
115 | mEndY = 0;
116 | mDownY = getHeight();
117 | mSlideAnimator.start();
118 | } else {
119 | for (ISlideCallback cb : slideCblist) {
120 | cb.onPositionChange(0);
121 | }
122 | isSlideShown = true;
123 | }
124 | }
125 |
126 | @Override
127 | public boolean onInterceptTouchEvent(MotionEvent event) {
128 | if (!canChildScrollUp()) {
129 | final int y = (int) event.getY();
130 | switch (event.getAction() & MotionEvent.ACTION_MASK) {
131 | case MotionEvent.ACTION_DOWN:
132 | isTouchWithAnimRunning = mSlideAnimator.isRunning();
133 | mDownY = y;
134 | break;
135 | case MotionEvent.ACTION_MOVE:
136 | if (isGreaterThanMinSize(mDownY, y) && !isTouchWithAnimRunning) {
137 | isCanScroll = true;
138 | return true;
139 | }
140 | break;
141 | }
142 | }
143 | return super.onInterceptTouchEvent(event);
144 | }
145 |
146 | @Override
147 | public boolean onTouchEvent(MotionEvent event) {
148 | final int y = (int) event.getY();
149 | int offsetY = y - mDownY;
150 | switch (event.getAction() & MotionEvent.ACTION_MASK) {
151 | case MotionEvent.ACTION_MOVE:
152 | if (isGreaterThanMinSize(mDownY, y) && isCanScroll) {
153 | for (ISlideCallback cb : slideCblist) {
154 | cb.onPositionChange(getPositionChangeY(offsetY));
155 | }
156 | } else if (isCanScroll) {
157 | for (ISlideCallback cb : slideCblist) {
158 | cb.onPositionChange(0);
159 | }
160 | }
161 | return true;
162 | case MotionEvent.ACTION_POINTER_DOWN:
163 | case MotionEvent.ACTION_UP:
164 | if (isGreaterThanMinSize(mDownY, y) && isCanScroll) {
165 | mDownY = getPositionChangeY(offsetY);
166 | fixPosition(offsetY);
167 | mSlideAnimator.start();
168 | }
169 | break;
170 | }
171 | return super.onTouchEvent(event);
172 | }
173 |
174 | private boolean canChildScrollUp() {
175 | for (View view : mSlideView) {
176 | if (canChildScrollUp(view)) return true;
177 | }
178 | return false;
179 | }
180 |
181 | private boolean canChildScrollUp(View view) {
182 | if (Build.VERSION.SDK_INT < 14) {
183 | return ViewCompat.canScrollVertically(view, -1) || view.getScrollY() > 0;
184 | } else {
185 | return ViewCompat.canScrollVertically(view, -1);
186 | }
187 | }
188 |
189 | private int getPositionChangeY(int offsetY) {
190 | if (isSlideShown) {
191 | return Math.abs(offsetY) - MIN_SCROLL_OFFSET;
192 | } else {
193 | return getHeight() - (Math.abs(offsetY)) - MIN_SCROLL_OFFSET;
194 | }
195 | }
196 |
197 | private boolean isGreaterThanMinSize(int y1, int y2) {
198 | if (isSlideShown) {
199 | return y2 - y1 > MIN_SCROLL_OFFSET;
200 | } else {
201 | return y1 - y2 > MIN_SCROLL_OFFSET;
202 | }
203 | }
204 |
205 | private void fixPosition(int offsetY) {
206 | int absOffsetY = Math.abs(offsetY);
207 | if (isSlideShown && absOffsetY > getHeight() / THRESHOLD) {
208 | mEndY = getHeight();
209 | } else if (!isSlideShown && absOffsetY > getHeight() / THRESHOLD) {
210 | mEndY = 0;
211 | }
212 | }
213 |
214 | public interface ISlideCallback {
215 | void onPositionChange(int offsetY);
216 | }
217 |
218 | public interface IStateCallback {
219 | void onShow();
220 |
221 | void onHide();
222 | }
223 |
224 | }
225 |
--------------------------------------------------------------------------------
/Sample/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
12 |
13 |
19 |
22 |
25 |
26 |
27 |
28 |
34 |
35 |
--------------------------------------------------------------------------------
/Sample/src/main/res/drawable/drawable_corner_icon_bg.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
9 |
--------------------------------------------------------------------------------
/Sample/src/main/res/drawable/gif_robot_walk.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sunfusheng/GlideImageView/138876da6a424b6c72de7a834e4dd059e854532c/Sample/src/main/res/drawable/gif_robot_walk.gif
--------------------------------------------------------------------------------
/Sample/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
11 |
16 |
21 |
26 |
31 |
36 |
41 |
46 |
51 |
56 |
61 |
66 |
71 |
76 |
81 |
86 |
91 |
96 |
101 |
106 |
111 |
116 |
121 |
126 |
131 |
136 |
141 |
146 |
151 |
156 |
161 |
166 |
171 |
172 |
--------------------------------------------------------------------------------
/Sample/src/main/res/drawable/progressbar_orange_selector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | -
5 |
6 |
9 |
10 |
11 | -
12 |
13 |
14 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/Sample/src/main/res/layout/activity_about.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
14 |
15 |
22 |
23 |
31 |
32 |
38 |
39 |
45 |
46 |
47 |
48 |
49 |
50 |
55 |
56 |
60 |
61 |
62 |
--------------------------------------------------------------------------------
/Sample/src/main/res/layout/activity_image.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
16 |
17 |
25 |
26 |
27 |
40 |
41 |
--------------------------------------------------------------------------------
/Sample/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
11 |
12 |
18 |
19 |
25 |
26 |
32 |
33 |
39 |
40 |
46 |
47 |
53 |
54 |
55 |
60 |
61 |
66 |
67 |
72 |
73 |
78 |
79 |
84 |
85 |
86 |
92 |
93 |
98 |
99 |
112 |
113 |
114 |
120 |
121 |
126 |
127 |
141 |
142 |
143 |
151 |
152 |
153 |
154 |
155 |
158 |
159 |
166 |
167 |
--------------------------------------------------------------------------------
/Sample/src/main/res/layout/activity_preview.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
12 |
13 |
22 |
23 |
--------------------------------------------------------------------------------
/Sample/src/main/res/layout/item_nine_images.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
22 |
23 |
28 |
29 |
35 |
36 |
--------------------------------------------------------------------------------
/Sample/src/main/res/layout/item_photoview.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
13 |
14 |
26 |
27 |
--------------------------------------------------------------------------------
/Sample/src/main/res/layout/item_right_image.xml:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
17 |
18 |
30 |
31 |
36 |
37 |
38 |
44 |
45 |
--------------------------------------------------------------------------------
/Sample/src/main/res/layout/item_three_images.xml:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
23 |
24 |
29 |
30 |
34 |
35 |
43 |
44 |
45 |
50 |
51 |
59 |
60 |
61 |
66 |
67 |
75 |
76 |
77 |
78 |
84 |
85 |
--------------------------------------------------------------------------------
/Sample/src/main/res/layout/item_top_image.xml:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
23 |
24 |
29 |
30 |
38 |
39 |
40 |
46 |
47 |
--------------------------------------------------------------------------------
/Sample/src/main/res/layout/layout_image_cell.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
13 |
14 |
21 |
22 |
42 |
43 |
53 |
--------------------------------------------------------------------------------
/Sample/src/main/res/layout/layout_recyclerview.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
--------------------------------------------------------------------------------
/Sample/src/main/res/layout/layout_roundimageview.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/Sample/src/main/res/layout/layout_webview.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
11 |
12 |
18 |
--------------------------------------------------------------------------------
/Sample/src/main/res/menu/menu_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
--------------------------------------------------------------------------------
/Sample/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/Sample/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sunfusheng/GlideImageView/138876da6a424b6c72de7a834e4dd059e854532c/Sample/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/Sample/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sunfusheng/GlideImageView/138876da6a424b6c72de7a834e4dd059e854532c/Sample/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/Sample/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sunfusheng/GlideImageView/138876da6a424b6c72de7a834e4dd059e854532c/Sample/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/Sample/src/main/res/mipmap-xhdpi/ic_multi_imageview.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sunfusheng/GlideImageView/138876da6a424b6c72de7a834e4dd059e854532c/Sample/src/main/res/mipmap-xhdpi/ic_multi_imageview.png
--------------------------------------------------------------------------------
/Sample/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sunfusheng/GlideImageView/138876da6a424b6c72de7a834e4dd059e854532c/Sample/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/Sample/src/main/res/mipmap-xxhdpi/ic_multi_imageview.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sunfusheng/GlideImageView/138876da6a424b6c72de7a834e4dd059e854532c/Sample/src/main/res/mipmap-xxhdpi/ic_multi_imageview.png
--------------------------------------------------------------------------------
/Sample/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sunfusheng/GlideImageView/138876da6a424b6c72de7a834e4dd059e854532c/Sample/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/Sample/src/main/res/mipmap-xxxhdpi/she.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sunfusheng/GlideImageView/138876da6a424b6c72de7a834e4dd059e854532c/Sample/src/main/res/mipmap-xxxhdpi/she.png
--------------------------------------------------------------------------------
/Sample/src/main/res/values-v21/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
19 |
20 |
--------------------------------------------------------------------------------
/Sample/src/main/res/values/attrs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/Sample/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | #607d8b
5 | #607d8b
6 | #607d8b
7 |
8 |
9 | #ff000000
10 | #D9000000
11 | #8C000000
12 | #66000000
13 | #1A000000
14 | #C34A42
15 | #FF9800
16 | #009734
17 | #46AE36
18 | #47B000
19 | #007AFF
20 | #1194F6
21 | #9D1BB2
22 |
23 | #00000000
24 | #0B000000
25 | #1A000000
26 | #33000000
27 | #4D000000
28 | #66000000
29 | #80000000
30 | #9A000000
31 | #B3000000
32 | #CC000000
33 | #E5000000
34 | #FF000000
35 |
36 | #00ffffff
37 | #1Affffff
38 | #33ffffff
39 | #4Dffffff
40 | #66ffffff
41 | #80ffffff
42 | #9Affffff
43 | #B3ffffff
44 | #CCffffff
45 | #E5ffffff
46 | #FFffffff
47 |
48 | #33000000
49 | #33fbc02d
50 | #33f57c00
51 |
52 | #FFFFFF
53 | #fbc02d
54 | #FFD700
55 | #f57c00
56 | #d01716
57 | #808080
58 | #0a7e07
59 | #455ede
60 | #000000
61 |
62 |
63 |
--------------------------------------------------------------------------------
/Sample/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 28sp
5 | 26sp
6 | 24sp
7 | 20sp
8 | 17sp
9 | 16sp
10 | 14sp
11 | 12sp
12 | 10sp
13 | 8sp
14 |
15 |
16 | 1dp
17 | 2dp
18 | 4dp
19 | 8dp
20 | 12dp
21 | 16dp
22 | 24dp
23 |
24 |
25 | 73dp
26 | 36dp
27 | 28dp
28 | 22dp
29 | 15dp
30 |
31 | 0dp
32 |
33 |
34 |
--------------------------------------------------------------------------------
/Sample/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | GlideImageView
4 | the image of transition
5 | %1$d/%2$d
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Sample/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
18 |
19 |
28 |
29 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | repositories {
3 | google()
4 | jcenter()
5 | mavenCentral()
6 | maven { url "https://jitpack.io" }
7 | maven { url 'https://maven.google.com' }
8 | maven { url 'https://dl.bintray.com/sfsheng0322/maven' }
9 | }
10 |
11 | dependencies {
12 | classpath 'com.android.tools.build:gradle:3.5.1'
13 | classpath 'com.novoda:bintray-release:0.9'
14 | }
15 | }
16 |
17 | allprojects {
18 | repositories {
19 | google()
20 | jcenter()
21 | mavenCentral()
22 | maven { url "https://jitpack.io" }
23 | maven { url 'https://maven.google.com' }
24 | maven { url 'https://dl.bintray.com/sfsheng0322/maven' }
25 | }
26 |
27 | ext {
28 | COMPILE_SDK_VERSION = 28
29 | BUILD_TOOL_VERSION = '28.0.3'
30 | SUPPORT_LIBRARY_VERSION = '28.0.0'
31 | GLIDE_VERSION = '4.9.0'
32 |
33 | MIN_SDK_VERSION = 14
34 | TARGET_SDK_VERSION = 28
35 | VERSION_CODE = 8
36 | VERSION_NAME = '2.1.0'
37 | }
38 | }
39 |
40 | task clean(type: Delete) {
41 | delete rootProject.buildDir
42 | }
43 |
44 | ext {
45 | compileSdkVersion = 27
46 | buildToolsVersion = '27.1.1'
47 | supportLibraryVersion = '27.1.1'
48 |
49 | minSdkVersion = 14
50 | targetSdkVersion = 27
51 | versionCode = 7
52 | versionName = "2.0.2"
53 | }
--------------------------------------------------------------------------------
/glideimageview/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/glideimageview/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 | apply plugin: 'com.novoda.bintray-release'
3 |
4 | android {
5 | compileSdkVersion COMPILE_SDK_VERSION
6 | defaultConfig {
7 | minSdkVersion MIN_SDK_VERSION
8 | targetSdkVersion TARGET_SDK_VERSION
9 | versionCode VERSION_CODE
10 | versionName VERSION_NAME
11 | }
12 |
13 | compileOptions {
14 | sourceCompatibility JavaVersion.VERSION_1_8
15 | targetCompatibility JavaVersion.VERSION_1_8
16 | }
17 |
18 | lintOptions {
19 | abortOnError false
20 | }
21 |
22 | buildTypes {
23 | release {
24 | minifyEnabled false
25 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
26 | }
27 | }
28 | }
29 |
30 | dependencies {
31 | api 'com.android.support:support-v4:' + SUPPORT_LIBRARY_VERSION
32 | api 'com.github.bumptech.glide:glide:' + GLIDE_VERSION
33 | api 'com.github.bumptech.glide:annotations:' + GLIDE_VERSION
34 | annotationProcessor 'com.github.bumptech.glide:compiler:' + GLIDE_VERSION
35 | api 'com.github.bumptech.glide:okhttp3-integration:' + GLIDE_VERSION
36 | }
37 |
38 | publish {
39 | userOrg = 'sfsheng0322'
40 | groupId = 'com.sunfusheng'
41 | artifactId = 'GlideImageView'
42 | publishVersion = VERSION_NAME
43 | desc = 'GlideImageView is an image loading library which you can listen to the progress of loading.'
44 | website = 'https://github.com/sunfusheng/GlideImageView'
45 | }
46 |
--------------------------------------------------------------------------------
/glideimageview/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /Users/sunfusheng/Android/Studio/sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
19 | # Uncomment this to preserve the line number information for
20 | # debugging stack traces.
21 | #-keepattributes SourceFile,LineNumberTable
22 |
23 | # If you keep the line number information, uncomment this to
24 | # hide the original source file name.
25 | #-renamesourcefileattribute SourceFile
26 |
27 | -keep public class extends com.bumptech.glide.module.AppGlideModule
28 | -keep class com.bumptech.glide.GeneratedAppGlideModuleImpl
--------------------------------------------------------------------------------
/glideimageview/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/glideimageview/src/main/java/com/sunfusheng/GlideImageLoader.java:
--------------------------------------------------------------------------------
1 | package com.sunfusheng;
2 |
3 | import android.content.Context;
4 | import android.graphics.Bitmap;
5 | import android.graphics.drawable.Drawable;
6 | import android.net.Uri;
7 | import android.support.annotation.DrawableRes;
8 | import android.support.annotation.NonNull;
9 | import android.support.annotation.Nullable;
10 | import android.widget.ImageView;
11 |
12 | import com.bumptech.glide.load.Transformation;
13 | import com.bumptech.glide.request.target.DrawableImageViewTarget;
14 | import com.bumptech.glide.request.transition.Transition;
15 | import com.sunfusheng.progress.GlideApp;
16 | import com.sunfusheng.progress.GlideRequest;
17 | import com.sunfusheng.progress.OnProgressListener;
18 | import com.sunfusheng.progress.ProgressManager;
19 |
20 | import java.lang.ref.WeakReference;
21 |
22 | /**
23 | * @author by sunfusheng on 2017/6/6.
24 | */
25 | public class GlideImageLoader {
26 |
27 | protected static final String ANDROID_RESOURCE = "android.resource://";
28 | protected static final String FILE = "file://";
29 | protected static final String SEPARATOR = "/";
30 |
31 | private String url;
32 | private WeakReference imageViewWeakReference;
33 | private GlideRequest glideRequest;
34 |
35 | public static GlideImageLoader create(ImageView imageView) {
36 | return new GlideImageLoader(imageView);
37 | }
38 |
39 | private GlideImageLoader(ImageView imageView) {
40 | imageViewWeakReference = new WeakReference<>(imageView);
41 | glideRequest = GlideApp.with(getContext()).asDrawable();
42 | }
43 |
44 | public ImageView getImageView() {
45 | if (imageViewWeakReference != null) {
46 | return imageViewWeakReference.get();
47 | }
48 | return null;
49 | }
50 |
51 | public Context getContext() {
52 | if (getImageView() != null) {
53 | return getImageView().getContext();
54 | }
55 | return null;
56 | }
57 |
58 | public String getUrl() {
59 | return url;
60 | }
61 |
62 | public GlideRequest getGlideRequest() {
63 | if (glideRequest == null) {
64 | glideRequest = GlideApp.with(getContext()).asDrawable();
65 | }
66 | return glideRequest;
67 | }
68 |
69 | protected Uri resId2Uri(@DrawableRes int resId) {
70 | return Uri.parse(ANDROID_RESOURCE + getContext().getPackageName() + SEPARATOR + resId);
71 | }
72 |
73 | public GlideImageLoader load(@DrawableRes int resId, @DrawableRes int placeholder, @NonNull Transformation transformation) {
74 | return loadImage(resId2Uri(resId), placeholder, transformation);
75 | }
76 |
77 | protected GlideRequest loadImage(Object obj) {
78 | if (obj instanceof String) {
79 | url = (String) obj;
80 | }
81 | return glideRequest.load(obj);
82 | }
83 |
84 |
85 | protected GlideImageLoader loadImage(Object obj, @DrawableRes int placeholder, Transformation transformation) {
86 | glideRequest = loadImage(obj);
87 | if (placeholder != 0) {
88 | glideRequest = glideRequest.placeholder(placeholder);
89 | }
90 |
91 | if (transformation != null) {
92 | glideRequest = glideRequest.transform(transformation);
93 | }
94 |
95 | glideRequest.into(new GlideImageViewTarget(getImageView()));
96 | return this;
97 | }
98 |
99 | public GlideImageLoader listener(Object obj, OnProgressListener onProgressListener) {
100 | if (obj instanceof String) {
101 | url = (String) obj;
102 | }
103 | ProgressManager.addListener(url, onProgressListener);
104 | return this;
105 | }
106 |
107 | private class GlideImageViewTarget extends DrawableImageViewTarget {
108 | GlideImageViewTarget(ImageView view) {
109 | super(view);
110 | }
111 |
112 | @Override
113 | public void onLoadStarted(Drawable placeholder) {
114 | super.onLoadStarted(placeholder);
115 | }
116 |
117 | @Override
118 | public void onLoadFailed(@Nullable Drawable errorDrawable) {
119 | OnProgressListener onProgressListener = ProgressManager.getProgressListener(getUrl());
120 | if (onProgressListener != null) {
121 | onProgressListener.onProgress(true, 100, 0, 0);
122 | ProgressManager.removeListener(getUrl());
123 | }
124 | super.onLoadFailed(errorDrawable);
125 | }
126 |
127 | @Override
128 | public void onResourceReady(@NonNull Drawable resource, @Nullable Transition super Drawable> transition) {
129 | OnProgressListener onProgressListener = ProgressManager.getProgressListener(getUrl());
130 | if (onProgressListener != null) {
131 | onProgressListener.onProgress(true, 100, 0, 0);
132 | ProgressManager.removeListener(getUrl());
133 | }
134 | super.onResourceReady(resource, transition);
135 | }
136 | }
137 | }
138 |
--------------------------------------------------------------------------------
/glideimageview/src/main/java/com/sunfusheng/GlideImageView.java:
--------------------------------------------------------------------------------
1 | package com.sunfusheng;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.content.Context;
5 | import android.graphics.Bitmap;
6 | import android.support.annotation.DrawableRes;
7 | import android.support.annotation.NonNull;
8 | import android.util.AttributeSet;
9 | import android.widget.ImageView;
10 |
11 | import com.bumptech.glide.load.Transformation;
12 | import com.bumptech.glide.load.engine.DiskCacheStrategy;
13 | import com.bumptech.glide.request.RequestOptions;
14 | import com.sunfusheng.progress.OnProgressListener;
15 | import com.sunfusheng.transformation.CircleTransformation;
16 | import com.sunfusheng.transformation.RadiusTransformation;
17 |
18 | /**
19 | * @author sunfusheng on 2017/11/10.
20 | */
21 | @SuppressLint("CheckResult")
22 | public class GlideImageView extends ImageView {
23 |
24 | private boolean enableState = false;
25 | private float pressedAlpha = 0.4f;
26 | private float unableAlpha = 0.3f;
27 | private GlideImageLoader imageLoader;
28 |
29 | public GlideImageView(Context context) {
30 | this(context, null);
31 | }
32 |
33 | public GlideImageView(Context context, AttributeSet attrs) {
34 | this(context, attrs, 0);
35 | }
36 |
37 | public GlideImageView(Context context, AttributeSet attrs, int defStyleAttr) {
38 | super(context, attrs, defStyleAttr);
39 | init();
40 | }
41 |
42 | private void init() {
43 | imageLoader = GlideImageLoader.create(this);
44 | }
45 |
46 | public GlideImageLoader getImageLoader() {
47 | if (imageLoader == null) {
48 | imageLoader = GlideImageLoader.create(this);
49 | }
50 | return imageLoader;
51 | }
52 |
53 | public GlideImageView apply(RequestOptions options) {
54 | getImageLoader().getGlideRequest().apply(options);
55 | return this;
56 | }
57 |
58 | public GlideImageView centerCrop() {
59 | getImageLoader().getGlideRequest().centerCrop();
60 | return this;
61 | }
62 |
63 | public GlideImageView fitCenter() {
64 | getImageLoader().getGlideRequest().fitCenter();
65 | return this;
66 | }
67 |
68 | public GlideImageView diskCacheStrategy(@NonNull DiskCacheStrategy strategy) {
69 | getImageLoader().getGlideRequest().diskCacheStrategy(strategy);
70 | return this;
71 | }
72 |
73 | public GlideImageView placeholder(@DrawableRes int resId) {
74 | getImageLoader().getGlideRequest().placeholder(resId);
75 | return this;
76 | }
77 |
78 | public GlideImageView error(@DrawableRes int resId) {
79 | getImageLoader().getGlideRequest().error(resId);
80 | return this;
81 | }
82 |
83 | public GlideImageView fallback(@DrawableRes int resId) {
84 | getImageLoader().getGlideRequest().fallback(resId);
85 | return this;
86 | }
87 |
88 | public GlideImageView dontAnimate() {
89 | getImageLoader().getGlideRequest().dontTransform();
90 | return this;
91 | }
92 |
93 | public GlideImageView dontTransform() {
94 | getImageLoader().getGlideRequest().dontTransform();
95 | return this;
96 | }
97 |
98 | public void load(String url) {
99 | load(url, 0);
100 | }
101 |
102 | public void load(String url, @DrawableRes int placeholder) {
103 | load(url, placeholder, 0);
104 | }
105 |
106 | public void load(String url, @DrawableRes int placeholder, int radius) {
107 | load(url, placeholder, radius, null);
108 | }
109 |
110 | public void load(String url, @DrawableRes int placeholder, OnProgressListener onProgressListener) {
111 | load(url, placeholder, null, onProgressListener);
112 | }
113 |
114 | public void load(String url, @DrawableRes int placeholder, int radius, OnProgressListener onProgressListener) {
115 | load(url, placeholder, new RadiusTransformation(getContext(), radius), onProgressListener);
116 | }
117 |
118 | public void load(Object obj, @DrawableRes int placeholder, Transformation transformation) {
119 | getImageLoader().loadImage(obj, placeholder, transformation);
120 | }
121 |
122 | public void load(Object obj, @DrawableRes int placeholder, Transformation transformation, OnProgressListener onProgressListener) {
123 | getImageLoader().listener(obj, onProgressListener).loadImage(obj, placeholder, transformation);
124 | }
125 |
126 | public void loadCircle(String url) {
127 | loadCircle(url, 0);
128 | }
129 |
130 | public void loadCircle(String url, @DrawableRes int placeholder) {
131 | loadCircle(url, placeholder, null);
132 | }
133 |
134 | public void loadCircle(String url, @DrawableRes int placeholder, OnProgressListener onProgressListener) {
135 | load(url, placeholder, new CircleTransformation(), onProgressListener);
136 | }
137 |
138 | public void loadDrawable(@DrawableRes int resId) {
139 | loadDrawable(resId, 0);
140 | }
141 |
142 | public void loadDrawable(@DrawableRes int resId, @DrawableRes int placeholder) {
143 | loadDrawable(resId, placeholder, null);
144 | }
145 |
146 | public void loadDrawable(@DrawableRes int resId, @DrawableRes int placeholder, @NonNull Transformation transformation) {
147 | getImageLoader().load(resId, placeholder, transformation);
148 | }
149 |
150 | @Override
151 | protected void drawableStateChanged() {
152 | super.drawableStateChanged();
153 | if (enableState) {
154 | if (isPressed()) {
155 | setAlpha(pressedAlpha);
156 | } else if (!isEnabled()) {
157 | setAlpha(unableAlpha);
158 | } else {
159 | setAlpha(1.0f);
160 | }
161 | }
162 | }
163 |
164 | public GlideImageView enableState(boolean enableState) {
165 | this.enableState = enableState;
166 | return this;
167 | }
168 |
169 | public GlideImageView pressedAlpha(float pressedAlpha) {
170 | this.pressedAlpha = pressedAlpha;
171 | return this;
172 | }
173 |
174 | public GlideImageView unableAlpha(float unableAlpha) {
175 | this.unableAlpha = unableAlpha;
176 | return this;
177 | }
178 | }
179 |
--------------------------------------------------------------------------------
/glideimageview/src/main/java/com/sunfusheng/progress/OnProgressListener.java:
--------------------------------------------------------------------------------
1 | package com.sunfusheng.progress;
2 |
3 | /**
4 | * @author by sunfusheng on 2017/6/14.
5 | */
6 | public interface OnProgressListener {
7 | void onProgress(boolean isComplete, int percentage, long bytesRead, long totalBytes);
8 | }
9 |
--------------------------------------------------------------------------------
/glideimageview/src/main/java/com/sunfusheng/progress/ProgressAppGlideModule.java:
--------------------------------------------------------------------------------
1 | package com.sunfusheng.progress;
2 |
3 | import android.content.Context;
4 | import android.support.annotation.NonNull;
5 |
6 | import com.bumptech.glide.Glide;
7 | import com.bumptech.glide.Registry;
8 | import com.bumptech.glide.annotation.GlideModule;
9 | import com.bumptech.glide.integration.okhttp3.OkHttpUrlLoader;
10 | import com.bumptech.glide.load.model.GlideUrl;
11 | import com.bumptech.glide.module.AppGlideModule;
12 |
13 | import java.io.InputStream;
14 |
15 | /**
16 | * @author by sunfusheng on 2017/6/14.
17 | */
18 | @GlideModule
19 | public class ProgressAppGlideModule extends AppGlideModule {
20 | @Override
21 | public void registerComponents(@NonNull Context context, @NonNull Glide glide, @NonNull Registry registry) {
22 | super.registerComponents(context, glide, registry);
23 | registry.replace(GlideUrl.class, InputStream.class, new OkHttpUrlLoader.Factory(ProgressManager.getOkHttpClient()));
24 | }
25 | }
--------------------------------------------------------------------------------
/glideimageview/src/main/java/com/sunfusheng/progress/ProgressManager.java:
--------------------------------------------------------------------------------
1 | package com.sunfusheng.progress;
2 |
3 | import android.text.TextUtils;
4 |
5 | import java.util.Collections;
6 | import java.util.HashMap;
7 | import java.util.Map;
8 |
9 | import okhttp3.OkHttpClient;
10 | import okhttp3.Request;
11 | import okhttp3.Response;
12 |
13 | /**
14 | * @author by sunfusheng on 2017/6/14.
15 | */
16 | public class ProgressManager {
17 |
18 | private static Map listenersMap = Collections.synchronizedMap(new HashMap<>());
19 | private static OkHttpClient okHttpClient;
20 |
21 | private ProgressManager() {
22 | }
23 |
24 | public static OkHttpClient getOkHttpClient() {
25 | if (okHttpClient == null) {
26 | okHttpClient = new OkHttpClient.Builder()
27 | .addNetworkInterceptor(chain -> {
28 | Request request = chain.request();
29 | Response response = chain.proceed(request);
30 | return response.newBuilder()
31 | .body(new ProgressResponseBody(request.url().toString(), LISTENER, response.body()))
32 | .build();
33 | })
34 | .build();
35 | }
36 | return okHttpClient;
37 | }
38 |
39 | private static final ProgressResponseBody.InternalProgressListener LISTENER = (url, bytesRead, totalBytes) -> {
40 | OnProgressListener onProgressListener = getProgressListener(url);
41 | if (onProgressListener != null) {
42 | int percentage = (int) ((bytesRead * 1f / totalBytes) * 100f);
43 | boolean isComplete = percentage >= 100;
44 | onProgressListener.onProgress(isComplete, percentage, bytesRead, totalBytes);
45 | if (isComplete) {
46 | removeListener(url);
47 | }
48 | }
49 | };
50 |
51 | public static void addListener(String url, OnProgressListener listener) {
52 | if (!TextUtils.isEmpty(url) && listener != null) {
53 | listenersMap.put(url, listener);
54 | listener.onProgress(false, 1, 0, 0);
55 | }
56 | }
57 |
58 | public static void removeListener(String url) {
59 | if (!TextUtils.isEmpty(url)) {
60 | listenersMap.remove(url);
61 | }
62 | }
63 |
64 | public static OnProgressListener getProgressListener(String url) {
65 | if (TextUtils.isEmpty(url) || listenersMap == null || listenersMap.size() == 0) {
66 | return null;
67 | }
68 |
69 | OnProgressListener listenerWeakReference = listenersMap.get(url);
70 | if (listenerWeakReference != null) {
71 | return listenerWeakReference;
72 | }
73 | return null;
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/glideimageview/src/main/java/com/sunfusheng/progress/ProgressResponseBody.java:
--------------------------------------------------------------------------------
1 | package com.sunfusheng.progress;
2 |
3 | import android.os.Handler;
4 | import android.os.Looper;
5 | import android.support.annotation.NonNull;
6 |
7 | import java.io.IOException;
8 |
9 | import okhttp3.MediaType;
10 | import okhttp3.ResponseBody;
11 | import okio.Buffer;
12 | import okio.BufferedSource;
13 | import okio.ForwardingSource;
14 | import okio.Okio;
15 | import okio.Source;
16 |
17 | /**
18 | * @author by sunfusheng on 2017/6/14.
19 | */
20 | public class ProgressResponseBody extends ResponseBody {
21 |
22 | private static final Handler mainThreadHandler = new Handler(Looper.getMainLooper());
23 |
24 | private String url;
25 | private ProgressResponseBody.InternalProgressListener internalProgressListener;
26 |
27 | private ResponseBody responseBody;
28 | private BufferedSource bufferedSource;
29 |
30 | ProgressResponseBody(String url, ProgressResponseBody.InternalProgressListener internalProgressListener, ResponseBody responseBody) {
31 | this.url = url;
32 | this.internalProgressListener = internalProgressListener;
33 | this.responseBody = responseBody;
34 | }
35 |
36 | @Override
37 | public MediaType contentType() {
38 | return responseBody.contentType();
39 | }
40 |
41 | @Override
42 | public long contentLength() {
43 | return responseBody.contentLength();
44 | }
45 |
46 | @Override
47 | public BufferedSource source() {
48 | if (bufferedSource == null) {
49 | bufferedSource = Okio.buffer(source(responseBody.source()));
50 | }
51 | return bufferedSource;
52 | }
53 |
54 | private Source source(Source source) {
55 | return new ForwardingSource(source) {
56 | long totalBytesRead;
57 | long lastTotalBytesRead;
58 |
59 | @Override
60 | public long read(@NonNull Buffer sink, long byteCount) throws IOException {
61 | long bytesRead = super.read(sink, byteCount);
62 | totalBytesRead += (bytesRead == -1) ? 0 : bytesRead;
63 |
64 | if (internalProgressListener != null && lastTotalBytesRead != totalBytesRead) {
65 | lastTotalBytesRead = totalBytesRead;
66 | mainThreadHandler.post(() -> internalProgressListener.onProgress(url, totalBytesRead, contentLength()));
67 | }
68 | return bytesRead;
69 | }
70 | };
71 | }
72 |
73 | interface InternalProgressListener {
74 | void onProgress(String url, long bytesRead, long totalBytes);
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/glideimageview/src/main/java/com/sunfusheng/transformation/BlurTransformation.java:
--------------------------------------------------------------------------------
1 | package com.sunfusheng.transformation;
2 |
3 | import android.content.Context;
4 | import android.graphics.Bitmap;
5 | import android.graphics.Canvas;
6 | import android.graphics.Paint;
7 | import android.os.Build;
8 | import android.support.annotation.NonNull;
9 | import android.support.annotation.RequiresApi;
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.util.Util;
14 | import com.sunfusheng.util.BlurUtils;
15 |
16 | import java.security.MessageDigest;
17 |
18 | /**
19 | * @author sunfusheng on 2018/6/25.
20 | */
21 | public class BlurTransformation extends BitmapTransformation {
22 | private final String ID = getClass().getName();
23 |
24 | private static int MAX_RADIUS = 25;
25 | private static int DEFAULT_SAMPLING = 1;
26 |
27 | private Context context;
28 | private int radius; //模糊半径0~25
29 | private int sampling; //取样0~25
30 |
31 | public BlurTransformation(Context context) {
32 | this(context, MAX_RADIUS, DEFAULT_SAMPLING);
33 | }
34 |
35 | public BlurTransformation(Context context, int radius) {
36 | this(context, radius, DEFAULT_SAMPLING);
37 | }
38 |
39 | public BlurTransformation(Context context, int radius, int sampling) {
40 | this.context = context;
41 | this.radius = radius > MAX_RADIUS ? MAX_RADIUS : radius;
42 | this.sampling = sampling > MAX_RADIUS ? MAX_RADIUS : sampling;
43 | }
44 |
45 | @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR1)
46 | @Override
47 | protected Bitmap transform(@NonNull BitmapPool pool, @NonNull Bitmap toTransform, int outWidth, int outHeight) {
48 | int width = toTransform.getWidth();
49 | int height = toTransform.getHeight();
50 | int scaledWidth = width / sampling;
51 | int scaledHeight = height / sampling;
52 |
53 | Bitmap bitmap = pool.get(scaledWidth, scaledHeight, Bitmap.Config.ARGB_8888);
54 | Canvas canvas = new Canvas(bitmap);
55 | canvas.scale(1 / (float) sampling, 1 / (float) sampling);
56 | Paint paint = new Paint();
57 | paint.setFlags(Paint.FILTER_BITMAP_FLAG);
58 | canvas.drawBitmap(toTransform, 0, 0, paint);
59 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
60 | bitmap = BlurUtils.rsBlur(context, bitmap, radius);
61 | } else {
62 | bitmap = BlurUtils.blur(bitmap, radius);
63 | }
64 | return bitmap;
65 | }
66 |
67 | @Override
68 | public boolean equals(Object obj) {
69 | if (obj instanceof BlurTransformation) {
70 | BlurTransformation other = (BlurTransformation) obj;
71 | return radius == other.radius && sampling == other.sampling;
72 | }
73 | return false;
74 | }
75 |
76 | @Override
77 | public int hashCode() {
78 | return Util.hashCode(ID.hashCode(), Util.hashCode(radius, Util.hashCode(sampling)));
79 | }
80 |
81 | @Override
82 | public void updateDiskCacheKey(@NonNull MessageDigest messageDigest) {
83 | messageDigest.update((ID + radius * 10 + sampling).getBytes(CHARSET));
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/glideimageview/src/main/java/com/sunfusheng/transformation/CircleTransformation.java:
--------------------------------------------------------------------------------
1 | package com.sunfusheng.transformation;
2 |
3 | import android.graphics.Bitmap;
4 | import android.graphics.BitmapShader;
5 | import android.graphics.Canvas;
6 | import android.graphics.Paint;
7 | import android.support.annotation.NonNull;
8 |
9 | import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool;
10 | import com.bumptech.glide.load.resource.bitmap.BitmapTransformation;
11 | import com.bumptech.glide.util.Util;
12 |
13 | import java.security.MessageDigest;
14 |
15 | /**
16 | * @author by sunfusheng on 2017/6/6.
17 | */
18 | public class CircleTransformation extends BitmapTransformation {
19 | private final String ID = getClass().getName();
20 |
21 | @Override
22 | protected Bitmap transform(@NonNull BitmapPool pool, @NonNull Bitmap toTransform, int outWidth, int outHeight) {
23 | int size = Math.min(toTransform.getWidth(), toTransform.getHeight());
24 | int x = (toTransform.getWidth() - size) / 2;
25 | int y = (toTransform.getHeight() - size) / 2;
26 |
27 | Bitmap square = Bitmap.createBitmap(toTransform, x, y, size, size);
28 | Bitmap circle = pool.get(size, size, Bitmap.Config.ARGB_8888);
29 |
30 | Canvas canvas = new Canvas(circle);
31 | Paint paint = new Paint();
32 | paint.setShader(new BitmapShader(square, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP));
33 | paint.setAntiAlias(true);
34 | float r = size / 2f;
35 | canvas.drawCircle(r, r, r, paint);
36 | return circle;
37 | }
38 |
39 | @Override
40 | public boolean equals(Object obj) {
41 | if (obj instanceof BlurTransformation) {
42 | return this == obj;
43 | }
44 | return false;
45 | }
46 |
47 | @Override
48 | public int hashCode() {
49 | return Util.hashCode(ID.hashCode());
50 | }
51 |
52 | @Override
53 | public void updateDiskCacheKey(@NonNull MessageDigest messageDigest) {
54 | messageDigest.update(ID.getBytes(CHARSET));
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/glideimageview/src/main/java/com/sunfusheng/transformation/RadiusTransformation.java:
--------------------------------------------------------------------------------
1 | package com.sunfusheng.transformation;
2 |
3 | import android.content.Context;
4 | import android.graphics.Bitmap;
5 | import android.graphics.BitmapShader;
6 | import android.graphics.Canvas;
7 | import android.graphics.Paint;
8 | import android.graphics.RectF;
9 | import android.support.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.util.Util;
14 | import com.sunfusheng.util.Utils;
15 |
16 | import java.security.MessageDigest;
17 |
18 | /**
19 | * @author by sunfusheng on 2017/6/6.
20 | */
21 | public class RadiusTransformation extends BitmapTransformation {
22 | private final String ID = getClass().getName();
23 |
24 | private int radius;
25 |
26 | public RadiusTransformation(Context context, int radius) {
27 | this.radius = Utils.dp2px(context, radius);
28 | }
29 |
30 | @Override
31 | protected Bitmap transform(@NonNull BitmapPool pool, @NonNull Bitmap toTransform, int outWidth, int outHeight) {
32 | int width = toTransform.getWidth();
33 | int height = toTransform.getHeight();
34 |
35 | Bitmap bitmap = pool.get(width, height, Bitmap.Config.ARGB_8888);
36 | bitmap.setHasAlpha(true);
37 | Canvas canvas = new Canvas(bitmap);
38 | Paint paint = new Paint();
39 | paint.setAntiAlias(true);
40 | paint.setShader(new BitmapShader(toTransform, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP));
41 | canvas.drawRoundRect(new RectF(0, 0, width, height), radius, radius, paint);
42 | return bitmap;
43 | }
44 |
45 | @Override
46 | public boolean equals(Object obj) {
47 | if (obj instanceof RadiusTransformation) {
48 | RadiusTransformation other = (RadiusTransformation) obj;
49 | return radius == other.radius;
50 | }
51 | return false;
52 | }
53 |
54 | @Override
55 | public int hashCode() {
56 | return Util.hashCode(ID.hashCode(), Util.hashCode(radius));
57 | }
58 |
59 | @Override
60 | public void updateDiskCacheKey(@NonNull MessageDigest messageDigest) {
61 | messageDigest.update((ID + radius).getBytes(CHARSET));
62 | }
63 |
64 | }
65 |
--------------------------------------------------------------------------------
/glideimageview/src/main/java/com/sunfusheng/util/BlurUtils.java:
--------------------------------------------------------------------------------
1 | package com.sunfusheng.util;
2 |
3 | import android.content.Context;
4 | import android.graphics.Bitmap;
5 | import android.os.Build;
6 | import android.renderscript.Allocation;
7 | import android.renderscript.Element;
8 | import android.renderscript.RenderScript;
9 | import android.renderscript.ScriptIntrinsicBlur;
10 | import android.support.annotation.RequiresApi;
11 |
12 | /**
13 | * @author sunfusheng on 2018/6/25.
14 | */
15 | public class BlurUtils {
16 |
17 | @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR1)
18 | public static Bitmap rsBlur(Context context, Bitmap toTransform, int radius) {
19 | RenderScript renderScript = RenderScript.create(context);
20 | Allocation input = Allocation.createFromBitmap(renderScript, toTransform);
21 | Allocation output = Allocation.createTyped(renderScript, input.getType());
22 | ScriptIntrinsicBlur scriptIntrinsicBlur = ScriptIntrinsicBlur.create(renderScript, Element.U8_4(renderScript));
23 | scriptIntrinsicBlur.setInput(input);
24 | scriptIntrinsicBlur.setRadius(radius);
25 | scriptIntrinsicBlur.forEach(output);
26 | output.copyTo(toTransform);
27 | renderScript.destroy();
28 | return toTransform;
29 | }
30 |
31 | public static Bitmap blur(Bitmap toTransform, int radius) {
32 | if (radius < 1) {
33 | return (null);
34 | }
35 |
36 | int w = toTransform.getWidth();
37 | int h = toTransform.getHeight();
38 |
39 | int[] pix = new int[w * h];
40 | toTransform.getPixels(pix, 0, w, 0, 0, w, h);
41 |
42 | int wm = w - 1;
43 | int hm = h - 1;
44 | int wh = w * h;
45 | int div = radius + radius + 1;
46 |
47 | int r[] = new int[wh];
48 | int g[] = new int[wh];
49 | int b[] = new int[wh];
50 | int rsum, gsum, bsum, x, y, i, p, yp, yi, yw;
51 | int vmin[] = new int[Math.max(w, h)];
52 |
53 | int divsum = (div + 1) >> 1;
54 | divsum *= divsum;
55 | int dv[] = new int[256 * divsum];
56 | for (i = 0; i < 256 * divsum; i++) {
57 | dv[i] = (i / divsum);
58 | }
59 |
60 | yw = yi = 0;
61 |
62 | int[][] stack = new int[div][3];
63 | int stackpointer;
64 | int stackstart;
65 | int[] sir;
66 | int rbs;
67 | int r1 = radius + 1;
68 | int routsum, goutsum, boutsum;
69 | int rinsum, ginsum, binsum;
70 |
71 | for (y = 0; y < h; y++) {
72 | rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0;
73 | for (i = -radius; i <= radius; i++) {
74 | p = pix[yi + Math.min(wm, Math.max(i, 0))];
75 | sir = stack[i + radius];
76 | sir[0] = (p & 0xff0000) >> 16;
77 | sir[1] = (p & 0x00ff00) >> 8;
78 | sir[2] = (p & 0x0000ff);
79 | rbs = r1 - Math.abs(i);
80 | rsum += sir[0] * rbs;
81 | gsum += sir[1] * rbs;
82 | bsum += sir[2] * rbs;
83 | if (i > 0) {
84 | rinsum += sir[0];
85 | ginsum += sir[1];
86 | binsum += sir[2];
87 | } else {
88 | routsum += sir[0];
89 | goutsum += sir[1];
90 | boutsum += sir[2];
91 | }
92 | }
93 | stackpointer = radius;
94 |
95 | for (x = 0; x < w; x++) {
96 |
97 | r[yi] = dv[rsum];
98 | g[yi] = dv[gsum];
99 | b[yi] = dv[bsum];
100 |
101 | rsum -= routsum;
102 | gsum -= goutsum;
103 | bsum -= boutsum;
104 |
105 | stackstart = stackpointer - radius + div;
106 | sir = stack[stackstart % div];
107 |
108 | routsum -= sir[0];
109 | goutsum -= sir[1];
110 | boutsum -= sir[2];
111 |
112 | if (y == 0) {
113 | vmin[x] = Math.min(x + radius + 1, wm);
114 | }
115 | p = pix[yw + vmin[x]];
116 |
117 | sir[0] = (p & 0xff0000) >> 16;
118 | sir[1] = (p & 0x00ff00) >> 8;
119 | sir[2] = (p & 0x0000ff);
120 |
121 | rinsum += sir[0];
122 | ginsum += sir[1];
123 | binsum += sir[2];
124 |
125 | rsum += rinsum;
126 | gsum += ginsum;
127 | bsum += binsum;
128 |
129 | stackpointer = (stackpointer + 1) % div;
130 | sir = stack[(stackpointer) % div];
131 |
132 | routsum += sir[0];
133 | goutsum += sir[1];
134 | boutsum += sir[2];
135 |
136 | rinsum -= sir[0];
137 | ginsum -= sir[1];
138 | binsum -= sir[2];
139 |
140 | yi++;
141 | }
142 | yw += w;
143 | }
144 | for (x = 0; x < w; x++) {
145 | rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0;
146 | yp = -radius * w;
147 | for (i = -radius; i <= radius; i++) {
148 | yi = Math.max(0, yp) + x;
149 |
150 | sir = stack[i + radius];
151 |
152 | sir[0] = r[yi];
153 | sir[1] = g[yi];
154 | sir[2] = b[yi];
155 |
156 | rbs = r1 - Math.abs(i);
157 |
158 | rsum += r[yi] * rbs;
159 | gsum += g[yi] * rbs;
160 | bsum += b[yi] * rbs;
161 |
162 | if (i > 0) {
163 | rinsum += sir[0];
164 | ginsum += sir[1];
165 | binsum += sir[2];
166 | } else {
167 | routsum += sir[0];
168 | goutsum += sir[1];
169 | boutsum += sir[2];
170 | }
171 |
172 | if (i < hm) {
173 | yp += w;
174 | }
175 | }
176 | yi = x;
177 | stackpointer = radius;
178 | for (y = 0; y < h; y++) {
179 | pix[yi] = (0xff000000 & pix[yi]) | (dv[rsum] << 16) | (dv[gsum] << 8) | dv[bsum];
180 |
181 | rsum -= routsum;
182 | gsum -= goutsum;
183 | bsum -= boutsum;
184 |
185 | stackstart = stackpointer - radius + div;
186 | sir = stack[stackstart % div];
187 |
188 | routsum -= sir[0];
189 | goutsum -= sir[1];
190 | boutsum -= sir[2];
191 |
192 | if (x == 0) {
193 | vmin[y] = Math.min(y + r1, hm) * w;
194 | }
195 | p = x + vmin[y];
196 |
197 | sir[0] = r[p];
198 | sir[1] = g[p];
199 | sir[2] = b[p];
200 |
201 | rinsum += sir[0];
202 | ginsum += sir[1];
203 | binsum += sir[2];
204 |
205 | rsum += rinsum;
206 | gsum += ginsum;
207 | bsum += binsum;
208 |
209 | stackpointer = (stackpointer + 1) % div;
210 | sir = stack[stackpointer];
211 |
212 | routsum += sir[0];
213 | goutsum += sir[1];
214 | boutsum += sir[2];
215 |
216 | rinsum -= sir[0];
217 | ginsum -= sir[1];
218 | binsum -= sir[2];
219 |
220 | yi += w;
221 | }
222 | }
223 |
224 | toTransform.setPixels(pix, 0, w, 0, 0, w, h);
225 | return toTransform;
226 | }
227 | }
228 |
--------------------------------------------------------------------------------
/glideimageview/src/main/java/com/sunfusheng/util/Utils.java:
--------------------------------------------------------------------------------
1 | package com.sunfusheng.util;
2 |
3 | import android.content.Context;
4 | import android.graphics.Bitmap;
5 | import android.graphics.Canvas;
6 | import android.graphics.Color;
7 | import android.graphics.Paint;
8 | import android.graphics.RectF;
9 | import android.graphics.drawable.BitmapDrawable;
10 | import android.graphics.drawable.Drawable;
11 | import android.support.annotation.ColorRes;
12 | import android.text.TextUtils;
13 | import android.util.DisplayMetrics;
14 | import android.view.WindowManager;
15 |
16 | import java.util.Collection;
17 |
18 | public class Utils {
19 |
20 | private static WindowManager windowManager;
21 |
22 | private static WindowManager getWindowManager(Context context) {
23 | if (windowManager == null) {
24 | windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
25 | }
26 | return windowManager;
27 | }
28 |
29 | public static float getDensity(Context context) {
30 | return context.getResources().getDisplayMetrics().density;
31 | }
32 |
33 | public static float getFontDensity(Context context) {
34 | return context.getResources().getDisplayMetrics().scaledDensity;
35 | }
36 |
37 | public static DisplayMetrics getDisplayMetrics(Context context) {
38 | DisplayMetrics displayMetrics = new DisplayMetrics();
39 | getWindowManager(context).getDefaultDisplay().getMetrics(displayMetrics);
40 | return displayMetrics;
41 | }
42 |
43 | public static int dp2px(Context context, float dp) {
44 | return (int) (getDensity(context) * dp + 0.5f);
45 | }
46 |
47 | public static int px2dp(Context context, float px) {
48 | return (int) (px / getDensity(context) + 0.5f);
49 | }
50 |
51 | public static int sp2px(Context context, float sp) {
52 | return (int) (getFontDensity(context) * sp + 0.5f);
53 | }
54 |
55 | public static int px2sp(Context context, float px) {
56 | return (int) (px / getFontDensity(context) + 0.5f);
57 | }
58 |
59 | public static int getWindowWidth(Context context) {
60 | return getDisplayMetrics(context).widthPixels;
61 | }
62 |
63 | public static int getWindowHeight(Context context) {
64 | return getDisplayMetrics(context).heightPixels;
65 | }
66 |
67 | public static String getPathFormat(String path) {
68 | if (!TextUtils.isEmpty(path)) {
69 | int lastPeriodIndex = path.lastIndexOf('.');
70 | if (lastPeriodIndex > 0 && lastPeriodIndex + 1 < path.length()) {
71 | String format = path.substring(lastPeriodIndex + 1);
72 | if (!TextUtils.isEmpty(format)) {
73 | return format.toLowerCase();
74 | }
75 | }
76 | }
77 | return "";
78 | }
79 |
80 | public static boolean isGif(String url) {
81 | return "gif".equals(getPathFormat(url));
82 | }
83 |
84 | public static Bitmap getTextBitmap(Context context, int width, int height, int radius, String text, int textSize, @ColorRes int bgColor) {
85 | radius = dp2px(context, radius);
86 | Bitmap bitmap = Bitmap.createBitmap(dp2px(context, width), dp2px(context, height), Bitmap.Config.ARGB_8888);
87 | Canvas canvas = new Canvas(bitmap);
88 | RectF rect = new RectF(0, 0, canvas.getWidth(), canvas.getHeight());
89 | Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
90 | paint.setColor(context.getResources().getColor(bgColor));
91 | canvas.drawRoundRect(new RectF(0, 0, rect.width(), rect.height()), radius, radius, paint);
92 | paint.setColor(Color.WHITE);
93 | paint.setTextSize(dp2px(context, textSize));
94 | paint.setTextAlign(Paint.Align.CENTER);
95 | Paint.FontMetricsInt fontMetrics = paint.getFontMetricsInt();
96 | float baseline = (rect.bottom + rect.top - fontMetrics.bottom - fontMetrics.top) / 2;
97 | canvas.drawText(text, rect.centerX(), baseline, paint);
98 | return bitmap;
99 | }
100 |
101 | public static Drawable getTextDrawable(Context context, int width, int height, int radius, String text, int textSize, @ColorRes int bgColor) {
102 | return new BitmapDrawable(getTextBitmap(context, width, height, radius, text, textSize, bgColor));
103 | }
104 |
105 | public static boolean isEmpty(Collection> collection) {
106 | return collection == null || collection.isEmpty();
107 | }
108 |
109 | public static int getSize(Collection> collection) {
110 | return collection == null ? 0 : collection.size();
111 | }
112 | }
113 |
--------------------------------------------------------------------------------
/glideimageview/src/main/java/com/sunfusheng/widget/GridLayoutHelper.java:
--------------------------------------------------------------------------------
1 | package com.sunfusheng.widget;
2 |
3 | import android.graphics.Point;
4 |
5 | /**
6 | * @author sunfusheng on 2018/6/19.
7 | */
8 | public class GridLayoutHelper implements LayoutHelper {
9 | private int spanCount;
10 | private int cellWidth;
11 | private int cellHeight;
12 | private int margin;
13 |
14 | public GridLayoutHelper(int spanCount, int cellWidth, int cellHeight, int margin) {
15 | this.spanCount = spanCount;
16 | this.cellWidth = cellWidth;
17 | this.cellHeight = cellHeight;
18 | this.margin = margin;
19 | }
20 |
21 | @Override
22 | public Point getCoordinate(int position) {
23 | Point point = new Point();
24 | point.x = position % spanCount * (cellWidth + margin);
25 | point.y = position / spanCount * (cellHeight + margin);
26 | return point;
27 | }
28 |
29 | @Override
30 | public Point getSize(int position) {
31 | Point point = new Point();
32 | point.x = cellWidth;
33 | point.y = cellHeight;
34 | return point;
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/glideimageview/src/main/java/com/sunfusheng/widget/ImageCell.java:
--------------------------------------------------------------------------------
1 | package com.sunfusheng.widget;
2 |
3 | import android.content.Context;
4 | import android.graphics.Canvas;
5 | import android.graphics.Paint;
6 | import android.graphics.Rect;
7 | import android.graphics.drawable.BitmapDrawable;
8 | import android.graphics.drawable.Drawable;
9 | import android.graphics.drawable.GradientDrawable;
10 | import android.support.annotation.ColorRes;
11 | import android.support.annotation.DrawableRes;
12 | import android.support.annotation.NonNull;
13 | import android.support.annotation.Nullable;
14 | import android.text.TextUtils;
15 | import android.util.AttributeSet;
16 | import android.widget.ImageView;
17 |
18 | import com.bumptech.glide.load.engine.DiskCacheStrategy;
19 | import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions;
20 | import com.bumptech.glide.load.resource.gif.GifDrawable;
21 | import com.bumptech.glide.request.target.DrawableImageViewTarget;
22 | import com.bumptech.glide.request.transition.Transition;
23 | import com.sunfusheng.glideimageview.R;
24 | import com.sunfusheng.progress.GlideApp;
25 | import com.sunfusheng.util.Utils;
26 |
27 | /**
28 | * @author sunfusheng on 2018/6/19.
29 | */
30 | public class ImageCell extends ImageView {
31 |
32 | private static final float THUMBNAIL_RATIO = 0.1f;
33 | private ImageData imageData;
34 | private int radius;
35 |
36 | private static Drawable gifDrawable;
37 | private static Drawable longDrawable;
38 | private boolean isGif;
39 | private boolean loadGif;
40 | private int placeholderResId;
41 | private int errorResId;
42 |
43 | private boolean hasDrawCornerIcon;
44 | private Drawable cornerIconDrawable;
45 | private int cornerIconWidth;
46 | private int cornerIconHeight;
47 | private Rect cornerIconBounds;
48 | private int cornerIconMargin;
49 |
50 | private Paint textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
51 | private Paint.FontMetricsInt fontMetrics;
52 |
53 | public ImageCell(Context context) {
54 | this(context, null);
55 | }
56 |
57 | public ImageCell(Context context, AttributeSet attrs) {
58 | this(context, attrs, 0);
59 | }
60 |
61 | public ImageCell(Context context, AttributeSet attrs, int defStyleAttr) {
62 | super(context, attrs, defStyleAttr);
63 | init();
64 | }
65 |
66 | private void init() {
67 | cornerIconBounds = new Rect();
68 | cornerIconMargin = Utils.dp2px(getContext(), 3);
69 | textPaint.setTextAlign(Paint.Align.CENTER);
70 | }
71 |
72 | public void setData(ImageData imageData) {
73 | this.imageData = imageData;
74 | if (imageData != null) {
75 | load(imageData.url);
76 | }
77 | }
78 |
79 | public ImageCell setLoadGif(boolean loadGif) {
80 | this.loadGif = loadGif;
81 | return this;
82 | }
83 |
84 | public ImageCell setRadius(int radius) {
85 | this.radius = radius;
86 | return this;
87 | }
88 |
89 | public ImageCell placeholder(@DrawableRes int resId) {
90 | this.placeholderResId = resId;
91 | return this;
92 | }
93 |
94 | public ImageCell error(@DrawableRes int resId) {
95 | this.errorResId = resId;
96 | return this;
97 | }
98 |
99 | public void load(String url) {
100 | GlideApp.with(getContext()).load(url)
101 | .placeholder(placeholderResId)
102 | .error(errorResId)
103 | .fitCenter()
104 | .transition(new DrawableTransitionOptions().dontTransition())
105 | .thumbnail(THUMBNAIL_RATIO)
106 | .diskCacheStrategy(DiskCacheStrategy.DATA)
107 | .into(new DrawableTarget(this) {
108 | @Override
109 | public void onResourceReady(@NonNull Drawable resource, @Nullable Transition super Drawable> transition) {
110 | Drawable drawable = resource;
111 | if (resource instanceof GifDrawable) {
112 | isGif = true;
113 | if (!loadGif) {
114 | drawable = new BitmapDrawable(((GifDrawable) resource).getFirstFrame());
115 | }
116 | } else {
117 | isGif = false;
118 | }
119 | initCornerIcon();
120 | super.onResourceReady(drawable, transition);
121 | }
122 |
123 | @Override
124 | public void onLoadFailed(@Nullable Drawable errorDrawable) {
125 | isGif = Utils.isGif(url);
126 | initCornerIcon();
127 | super.onLoadFailed(errorDrawable);
128 | }
129 | });
130 | }
131 |
132 | private void initCornerIcon() {
133 | if (isGif && !loadGif) {
134 | cornerIconDrawable = getGifDrawable();
135 | } else if (isLongImage()) {
136 | cornerIconDrawable = getLongDrawable();
137 | } else {
138 | cornerIconDrawable = null;
139 | }
140 |
141 | if (cornerIconDrawable != null) {
142 | cornerIconWidth = Utils.dp2px(getContext(), cornerIconDrawable.getIntrinsicWidth());
143 | cornerIconHeight = Utils.dp2px(getContext(), cornerIconDrawable.getIntrinsicHeight());
144 | if (!hasDrawCornerIcon) {
145 | postInvalidate();
146 | }
147 | }
148 | }
149 |
150 | public boolean isGifImage() {
151 | return isGif;
152 | }
153 |
154 | public boolean isLongImage() {
155 | int realWidth = imageData != null ? imageData.realWidth : 0;
156 | int realHeight = imageData != null ? imageData.realHeight : 0;
157 | if (realWidth == 0 || realHeight == 0 || realWidth >= realHeight) {
158 | return false;
159 | }
160 | return (realHeight / realWidth) >= 4;
161 | }
162 |
163 | public Drawable getGifDrawable() {
164 | if (gifDrawable == null) {
165 | gifDrawable = Utils.getTextDrawable(getContext().getApplicationContext(), 24, 14, 2, "GIF", 11, R.color.nine_image_text_background_color);
166 | }
167 | return gifDrawable;
168 | }
169 |
170 | public Drawable getLongDrawable() {
171 | if (longDrawable == null) {
172 | longDrawable = Utils.getTextDrawable(getContext().getApplicationContext(), 25, 14, 2, "长图", 10, R.color.nine_image_text_background_color);
173 | }
174 | return longDrawable;
175 | }
176 |
177 | @Override
178 | protected void onLayout(boolean changed, int l, int t, int r, int b) {
179 | super.onLayout(changed, l, t, r, b);
180 | if (cornerIconDrawable != null) {
181 | cornerIconBounds.set(r - l - cornerIconMargin - cornerIconWidth,
182 | b - t - cornerIconHeight - cornerIconMargin,
183 | r - l - cornerIconMargin,
184 | b - t - cornerIconMargin);
185 | }
186 | }
187 |
188 | @Override
189 | public void draw(Canvas canvas) {
190 | super.draw(canvas);
191 | if (cornerIconDrawable != null) {
192 | hasDrawCornerIcon = true;
193 | cornerIconDrawable.setBounds(cornerIconBounds);
194 | cornerIconDrawable.draw(canvas);
195 | }
196 |
197 | if (!TextUtils.isEmpty(imageData.text)) {
198 | canvas.drawColor(getResources().getColor(R.color.nine_image_text_background_color));
199 | float textX = getWidth() / 2f;
200 | float textY = getHeight() / 2f + (fontMetrics.bottom - fontMetrics.top) / 2f - fontMetrics.bottom;
201 | canvas.drawText(imageData.text, textX, textY, textPaint);
202 | }
203 | }
204 |
205 | public ImageCell setText(String text) {
206 | if (imageData != null) {
207 | imageData.text = text;
208 | postInvalidate();
209 | }
210 | return this;
211 | }
212 |
213 | public ImageCell setTextColor(@ColorRes int color) {
214 | textPaint.setColor(getResources().getColor(color));
215 | return this;
216 | }
217 |
218 | public ImageCell setTextSize(int size) {
219 | textPaint.setTextSize(Utils.dp2px(getContext(), size));
220 | fontMetrics = textPaint.getFontMetricsInt();
221 | return this;
222 | }
223 |
224 | private class DrawableTarget extends DrawableImageViewTarget {
225 | DrawableTarget(ImageView view) {
226 | super(view);
227 | }
228 |
229 | private void setBackground() {
230 | if (radius == 0) {
231 | getView().setBackgroundResource(R.drawable.drawable_image_bg_0dp);
232 | } else if (radius == 5) {
233 | getView().setBackgroundResource(R.drawable.drawable_image_bg_5dp);
234 | } else {
235 | GradientDrawable drawable = (GradientDrawable) getResources().getDrawable(R.drawable.drawable_image_bg_0dp);
236 | drawable.setCornerRadius(radius);
237 | getView().setBackgroundDrawable(drawable);
238 | }
239 | }
240 |
241 | @Override
242 | public void onLoadStarted(Drawable placeholder) {
243 | setBackground();
244 | getView().setScaleType(ImageView.ScaleType.FIT_CENTER);
245 | super.onLoadStarted(placeholder);
246 | }
247 |
248 | @Override
249 | public void onLoadFailed(@Nullable Drawable errorDrawable) {
250 | setBackground();
251 | getView().setScaleType(ImageView.ScaleType.FIT_CENTER);
252 | super.onLoadFailed(errorDrawable);
253 | }
254 |
255 | @Override
256 | public void onResourceReady(@NonNull Drawable resource, @Nullable Transition super Drawable> transition) {
257 | getView().setBackgroundResource(0);
258 | getView().setScaleType(ImageView.ScaleType.CENTER_CROP);
259 | super.onResourceReady(resource, transition);
260 | }
261 | }
262 | }
263 |
--------------------------------------------------------------------------------
/glideimageview/src/main/java/com/sunfusheng/widget/ImageData.java:
--------------------------------------------------------------------------------
1 | package com.sunfusheng.widget;
2 |
3 | import android.graphics.Point;
4 |
5 | import java.io.Serializable;
6 |
7 | /**
8 | * @author sunfusheng on 2018/6/19.
9 | */
10 | public class ImageData implements Serializable {
11 | public String url;
12 | public String text;
13 |
14 | public int realWidth;
15 | public int realHeight;
16 |
17 | public int startX;
18 | public int startY;
19 | public int width;
20 | public int height;
21 |
22 | public ImageData(String url) {
23 | this.url = url;
24 | }
25 |
26 | public ImageData from(ImageData imageData, LayoutHelper layoutHelper, int position) {
27 | if (imageData != null && layoutHelper != null) {
28 | Point coordinate = layoutHelper.getCoordinate(position);
29 | if (coordinate != null) {
30 | imageData.startX = coordinate.x;
31 | imageData.startY = coordinate.y;
32 | }
33 |
34 | Point size = layoutHelper.getSize(position);
35 | if (size != null) {
36 | imageData.width = size.x;
37 | imageData.height = size.y;
38 | }
39 | }
40 | return imageData;
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/glideimageview/src/main/java/com/sunfusheng/widget/LayoutHelper.java:
--------------------------------------------------------------------------------
1 | package com.sunfusheng.widget;
2 |
3 | import android.graphics.Point;
4 |
5 | /**
6 | * @author sunfusheng on 2018/6/19.
7 | */
8 | public interface LayoutHelper {
9 | Point getCoordinate(int position);
10 |
11 | Point getSize(int position);
12 | }
13 |
--------------------------------------------------------------------------------
/glideimageview/src/main/res/drawable/drawable_image_bg_0dp.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
--------------------------------------------------------------------------------
/glideimageview/src/main/res/drawable/drawable_image_bg_5dp.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
--------------------------------------------------------------------------------
/glideimageview/src/main/res/mipmap-hdpi/image_load_err.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sunfusheng/GlideImageView/138876da6a424b6c72de7a834e4dd059e854532c/glideimageview/src/main/res/mipmap-hdpi/image_load_err.png
--------------------------------------------------------------------------------
/glideimageview/src/main/res/mipmap-hdpi/image_loading.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sunfusheng/GlideImageView/138876da6a424b6c72de7a834e4dd059e854532c/glideimageview/src/main/res/mipmap-hdpi/image_loading.png
--------------------------------------------------------------------------------
/glideimageview/src/main/res/mipmap-xhdpi/image_load_err.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sunfusheng/GlideImageView/138876da6a424b6c72de7a834e4dd059e854532c/glideimageview/src/main/res/mipmap-xhdpi/image_load_err.png
--------------------------------------------------------------------------------
/glideimageview/src/main/res/mipmap-xhdpi/image_loading.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sunfusheng/GlideImageView/138876da6a424b6c72de7a834e4dd059e854532c/glideimageview/src/main/res/mipmap-xhdpi/image_loading.png
--------------------------------------------------------------------------------
/glideimageview/src/main/res/mipmap-xxhdpi/image_load_err.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sunfusheng/GlideImageView/138876da6a424b6c72de7a834e4dd059e854532c/glideimageview/src/main/res/mipmap-xxhdpi/image_load_err.png
--------------------------------------------------------------------------------
/glideimageview/src/main/res/mipmap-xxhdpi/image_loading.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sunfusheng/GlideImageView/138876da6a424b6c72de7a834e4dd059e854532c/glideimageview/src/main/res/mipmap-xxhdpi/image_loading.png
--------------------------------------------------------------------------------
/glideimageview/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #4D000000
4 | #FFFFFF
5 |
6 |
7 |
--------------------------------------------------------------------------------
/glideimageview/src/main/res/values/style.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 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | org.gradle.jvmargs=-Xmx1536m
13 |
14 | # When configured, Gradle will run in incubating parallel mode.
15 | # This option should only be used with decoupled projects. More details, visit
16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
17 | # org.gradle.parallel=true
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sunfusheng/GlideImageView/138876da6a424b6c72de7a834e4dd059e854532c/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Tue May 08 11:31:11 CST 2018
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/resources/cat.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sunfusheng/GlideImageView/138876da6a424b6c72de7a834e4dd059e854532c/resources/cat.jpg
--------------------------------------------------------------------------------
/resources/cat_thumbnail.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sunfusheng/GlideImageView/138876da6a424b6c72de7a834e4dd059e854532c/resources/cat_thumbnail.jpg
--------------------------------------------------------------------------------
/resources/gif1.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sunfusheng/GlideImageView/138876da6a424b6c72de7a834e4dd059e854532c/resources/gif1.gif
--------------------------------------------------------------------------------
/resources/gif2.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sunfusheng/GlideImageView/138876da6a424b6c72de7a834e4dd059e854532c/resources/gif2.gif
--------------------------------------------------------------------------------
/resources/gif3.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sunfusheng/GlideImageView/138876da6a424b6c72de7a834e4dd059e854532c/resources/gif3.gif
--------------------------------------------------------------------------------
/resources/gif4.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sunfusheng/GlideImageView/138876da6a424b6c72de7a834e4dd059e854532c/resources/gif4.gif
--------------------------------------------------------------------------------
/resources/gif5.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sunfusheng/GlideImageView/138876da6a424b6c72de7a834e4dd059e854532c/resources/gif5.gif
--------------------------------------------------------------------------------
/resources/gif6.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sunfusheng/GlideImageView/138876da6a424b6c72de7a834e4dd059e854532c/resources/gif6.gif
--------------------------------------------------------------------------------
/resources/girl.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sunfusheng/GlideImageView/138876da6a424b6c72de7a834e4dd059e854532c/resources/girl.jpg
--------------------------------------------------------------------------------
/resources/girl_thumbnail.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sunfusheng/GlideImageView/138876da6a424b6c72de7a834e4dd059e854532c/resources/girl_thumbnail.jpg
--------------------------------------------------------------------------------
/resources/image1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sunfusheng/GlideImageView/138876da6a424b6c72de7a834e4dd059e854532c/resources/image1.png
--------------------------------------------------------------------------------
/resources/image2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sunfusheng/GlideImageView/138876da6a424b6c72de7a834e4dd059e854532c/resources/image2.png
--------------------------------------------------------------------------------
/resources/image3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sunfusheng/GlideImageView/138876da6a424b6c72de7a834e4dd059e854532c/resources/image3.png
--------------------------------------------------------------------------------
/resources/image4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sunfusheng/GlideImageView/138876da6a424b6c72de7a834e4dd059e854532c/resources/image4.png
--------------------------------------------------------------------------------
/resources/image5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sunfusheng/GlideImageView/138876da6a424b6c72de7a834e4dd059e854532c/resources/image5.png
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':sample', ':glideimageview'
2 |
--------------------------------------------------------------------------------
/signings/keystore.jks:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sunfusheng/GlideImageView/138876da6a424b6c72de7a834e4dd059e854532c/signings/keystore.jks
--------------------------------------------------------------------------------
/signings/keystore.jks.enc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sunfusheng/GlideImageView/138876da6a424b6c72de7a834e4dd059e854532c/signings/keystore.jks.enc
--------------------------------------------------------------------------------
/signings/signing.properties:
--------------------------------------------------------------------------------
1 | KEYSTORE_FILEPATH=../signings/keystore.jks
2 | STORE_PASSWORD=sunfusheng
3 | KEY_ALIAS=sunfusheng
4 | KEY_PASSWORD=sunfusheng
--------------------------------------------------------------------------------