├── .gitignore ├── .idea ├── codeStyles │ ├── Project.xml │ └── codeStyleConfig.xml ├── compiler.xml ├── gradle.xml ├── jarRepositories.xml ├── misc.xml └── vcs.xml ├── ImageViewEx ├── .gitignore ├── build.gradle ├── consumer-rules.pro ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── taoweiji │ │ └── image │ │ └── ExampleInstrumentedTest.java │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── taoweiji │ │ └── image │ │ ├── ImageViewEx.java │ │ ├── ImageViewExBase.java │ │ ├── RoundedColorDrawable.java │ │ └── RoundedCornerDrawable.java │ └── res │ └── values │ ├── attrs_image_view_ex.xml │ └── strings.xml ├── README.md ├── SimpleDraweeView ├── .gitignore ├── build.gradle ├── consumer-rules.pro ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── facebook │ │ └── drawee │ │ └── replace │ │ └── ExampleInstrumentedTest.java │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── facebook │ │ └── drawee │ │ └── view │ │ └── SimpleDraweeView.java │ └── res │ └── values │ ├── attrs_simple_drawee_view.xml │ └── strings.xml ├── build.gradle ├── example ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── taoweiji │ │ └── custom │ │ └── view │ │ └── ExampleInstrumentedTest.kt │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── taoweiji │ │ │ └── image │ │ │ └── example │ │ │ ├── MainActivity.kt │ │ │ └── MyApplication.kt │ └── res │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable │ │ ├── bg_main_domain.png │ │ ├── colours.xml │ │ ├── ic_launcher_background.xml │ │ ├── ic_launcher_test.png │ │ ├── test1.png │ │ └── test2.gif │ │ ├── layout │ │ └── activity_main.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ └── values │ │ ├── attrs_my_view.xml │ │ ├── attrs_rounded_image_view.xml │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── taoweiji │ └── custom │ └── view │ └── ExampleUnitTest.kt ├── example_01.png ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── maven_public.gradle └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /build 12 | /captures 13 | .externalNativeBuild 14 | .cxx 15 | /upload_jcenter.sh -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 9 | 10 | 11 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | xmlns:android 20 | 21 | ^$ 22 | 23 | 24 | 25 |
26 |
27 | 28 | 29 | 30 | xmlns:.* 31 | 32 | ^$ 33 | 34 | 35 | BY_NAME 36 | 37 |
38 |
39 | 40 | 41 | 42 | .*:id 43 | 44 | http://schemas.android.com/apk/res/android 45 | 46 | 47 | 48 |
49 |
50 | 51 | 52 | 53 | .*:name 54 | 55 | http://schemas.android.com/apk/res/android 56 | 57 | 58 | 59 |
60 |
61 | 62 | 63 | 64 | name 65 | 66 | ^$ 67 | 68 | 69 | 70 |
71 |
72 | 73 | 74 | 75 | style 76 | 77 | ^$ 78 | 79 | 80 | 81 |
82 |
83 | 84 | 85 | 86 | .* 87 | 88 | ^$ 89 | 90 | 91 | BY_NAME 92 | 93 |
94 |
95 | 96 | 97 | 98 | .* 99 | 100 | http://schemas.android.com/apk/res/android 101 | 102 | 103 | ANDROID_ATTRIBUTE_ORDER 104 | 105 |
106 |
107 | 108 | 109 | 110 | .* 111 | 112 | .* 113 | 114 | 115 | BY_NAME 116 | 117 |
118 |
119 |
120 |
121 | 122 | 124 |
125 |
-------------------------------------------------------------------------------- /.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 21 | 22 | -------------------------------------------------------------------------------- /.idea/jarRepositories.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 14 | 15 | 19 | 20 | 24 | 25 | 29 | 30 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 14 | 15 | 16 | 17 | 18 | 19 | 21 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /ImageViewEx/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /ImageViewEx/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion 30 5 | 6 | 7 | defaultConfig { 8 | minSdkVersion 14 9 | targetSdkVersion 30 10 | versionCode 1 11 | versionName "1.0" 12 | 13 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 14 | consumerProguardFiles 'consumer-rules.pro' 15 | } 16 | 17 | buildTypes { 18 | release { 19 | minifyEnabled false 20 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 21 | } 22 | } 23 | 24 | } 25 | 26 | dependencies { 27 | implementation fileTree(dir: 'libs', include: ['*.jar']) 28 | } 29 | 30 | apply from: '../maven_public.gradle' -------------------------------------------------------------------------------- /ImageViewEx/consumer-rules.pro: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/taoweiji/ImageViewEx/c06cd6d01442cb953d3ab5190a4751a64dcd6352/ImageViewEx/consumer-rules.pro -------------------------------------------------------------------------------- /ImageViewEx/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /ImageViewEx/src/androidTest/java/com/taoweiji/image/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.taoweiji.image; 2 | 3 | import android.content.Context; 4 | 5 | import androidx.test.platform.app.InstrumentationRegistry; 6 | import androidx.test.ext.junit.runners.AndroidJUnit4; 7 | 8 | import org.junit.Test; 9 | import org.junit.runner.RunWith; 10 | 11 | import static org.junit.Assert.*; 12 | 13 | /** 14 | * Instrumented test, which will execute on an Android device. 15 | * 16 | * @see Testing documentation 17 | */ 18 | @RunWith(AndroidJUnit4.class) 19 | public class ExampleInstrumentedTest { 20 | @Test 21 | public void useAppContext() { 22 | // Context of the app under test. 23 | Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); 24 | 25 | assertEquals("com.imageview.ex.test", appContext.getPackageName()); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /ImageViewEx/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | -------------------------------------------------------------------------------- /ImageViewEx/src/main/java/com/taoweiji/image/ImageViewEx.java: -------------------------------------------------------------------------------- 1 | package com.taoweiji.image; 2 | 3 | import android.content.Context; 4 | import android.content.res.TypedArray; 5 | import android.graphics.Color; 6 | import android.graphics.drawable.Drawable; 7 | import android.util.AttributeSet; 8 | 9 | 10 | public class ImageViewEx extends ImageViewExBase { 11 | 12 | 13 | public ImageViewEx(Context context) { 14 | this(context, null); 15 | } 16 | 17 | public ImageViewEx(Context context, AttributeSet attrs) { 18 | this(context, attrs, 0); 19 | } 20 | 21 | public ImageViewEx(Context context, AttributeSet attrs, int defStyleAttr) { 22 | super(context, attrs, defStyleAttr); 23 | TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.ImageViewEx); 24 | 25 | this.roundedCornerRadius = typedArray.getDimensionPixelSize(R.styleable.ImageViewEx_imageViewEx_roundCornerRadius, roundedCornerRadius); 26 | this.roundTopLeft = typedArray.getBoolean(R.styleable.ImageViewEx_imageViewEx_roundTopLeft, roundTopLeft); 27 | this.roundTopRight = typedArray.getBoolean(R.styleable.ImageViewEx_imageViewEx_roundTopRight, roundTopRight); 28 | this.roundBottomLeft = typedArray.getBoolean(R.styleable.ImageViewEx_imageViewEx_roundBottomLeft, roundBottomLeft); 29 | this.roundBottomRight = typedArray.getBoolean(R.styleable.ImageViewEx_imageViewEx_roundBottomRight, roundBottomRight); 30 | 31 | this.circle = typedArray.getBoolean(R.styleable.ImageViewEx_imageViewEx_asCircle, circle); 32 | this.borderColor = typedArray.getColor(R.styleable.ImageViewEx_imageViewEx_borderColor, Color.WHITE); 33 | this.borderWidth = typedArray.getDimensionPixelSize(R.styleable.ImageViewEx_imageViewEx_borderWidth, borderWidth); 34 | 35 | Drawable placeholderImageTmp = typedArray.getDrawable(R.styleable.ImageViewEx_placeholderImage); 36 | this.fadeDuration = typedArray.getInt(R.styleable.ImageViewEx_fadeDuration, fadeDuration); 37 | typedArray.recycle(); 38 | setImageDrawable(getDrawable()); 39 | setPlaceholderImageDrawable(placeholderImageTmp); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /ImageViewEx/src/main/java/com/taoweiji/image/ImageViewExBase.java: -------------------------------------------------------------------------------- 1 | package com.taoweiji.image; 2 | 3 | import android.content.Context; 4 | import android.graphics.Bitmap; 5 | import android.graphics.Color; 6 | import android.graphics.Matrix; 7 | import android.graphics.drawable.Drawable; 8 | import android.graphics.drawable.TransitionDrawable; 9 | import android.net.Uri; 10 | import android.util.AttributeSet; 11 | import android.widget.ImageView; 12 | 13 | 14 | public abstract class ImageViewExBase extends ImageView { 15 | // protected ScaleType scaleType = ScaleType.MATRIX; 16 | protected int borderWidth = 0; 17 | protected int borderColor = Color.WHITE; 18 | protected boolean circle = false; 19 | protected int roundedCornerRadius = 0; 20 | protected boolean roundTopLeft = true; 21 | protected boolean roundTopRight = true; 22 | protected boolean roundBottomLeft = true; 23 | protected boolean roundBottomRight = true; 24 | 25 | protected Drawable imageDrawable; 26 | private Drawable placeholderImage; 27 | protected int fadeDuration = 0; 28 | protected boolean superInited = false; 29 | 30 | public ImageViewExBase(Context context) { 31 | this(context, null); 32 | } 33 | 34 | public ImageViewExBase(Context context, AttributeSet attrs) { 35 | this(context, attrs, 0); 36 | } 37 | 38 | public ImageViewExBase(Context context, AttributeSet attrs, int defStyleAttr) { 39 | super(context, attrs, defStyleAttr); 40 | superInited = true; 41 | } 42 | 43 | public void setPlaceholderImageBitmap(Bitmap bm) { 44 | setPlaceholderImageDrawable(RoundedCornerDrawable.fromBitmap(bm, this)); 45 | } 46 | 47 | public void setPlaceholderImageResource(int resId) { 48 | if (resId == 0) { 49 | setPlaceholderImageDrawable(null); 50 | } else { 51 | setPlaceholderImageDrawable(getResources().getDrawable(resId)); 52 | } 53 | 54 | } 55 | 56 | public void setPlaceholderImageDrawable(Drawable drawable) { 57 | this.placeholderImage = RoundedCornerDrawable.fromDrawable(drawable, this); 58 | setImageDrawable(this.imageDrawable); 59 | } 60 | 61 | 62 | @Override 63 | public void setImageURI(Uri uri) { 64 | super.setImageURI(uri); 65 | setImageDrawable(getDrawable()); 66 | } 67 | 68 | @Override 69 | public void setImageBitmap(Bitmap bm) { 70 | setImageDrawable(RoundedCornerDrawable.fromBitmap(bm, this)); 71 | } 72 | 73 | @Override 74 | public void setImageResource(int resId) { 75 | if (resId == 0) { 76 | setImageDrawable(null); 77 | } else { 78 | setImageDrawable(getResources().getDrawable(resId)); 79 | } 80 | } 81 | 82 | 83 | @Override 84 | public void setImageDrawable(Drawable drawable) { 85 | if(!superInited){ 86 | super.setImageDrawable(drawable); 87 | return; 88 | } 89 | Drawable imageDrawableTmp = RoundedCornerDrawable.fromDrawable(drawable, this); 90 | boolean isSame = isSame(imageDrawableTmp, this.imageDrawable); 91 | this.imageDrawable = imageDrawableTmp; 92 | updateRoundedInfo(); 93 | if (this.imageDrawable != null) { 94 | if (!isSame && !isInEditMode() && fadeDuration > 0) { 95 | Drawable startDrawable = getResources().getDrawable(android.R.color.transparent); 96 | TransitionDrawable transitionDrawable = new TransitionDrawable(new Drawable[]{startDrawable, this.imageDrawable}); 97 | super.setImageDrawable(transitionDrawable); 98 | transitionDrawable.startTransition(fadeDuration); 99 | } else { 100 | super.setImageDrawable(imageDrawable); 101 | } 102 | } else { 103 | super.setImageDrawable(this.placeholderImage); 104 | } 105 | } 106 | 107 | @Override 108 | public void setScaleType(ScaleType scaleType) { 109 | if (scaleType != getScaleType()){ 110 | super.setScaleType(scaleType); 111 | invalidateSelf(); 112 | } 113 | 114 | } 115 | 116 | public int getBorderWidth() { 117 | return borderWidth; 118 | } 119 | 120 | public void setBorderWidth(int borderWidth) { 121 | this.borderWidth = borderWidth; 122 | invalidateSelf(); 123 | } 124 | 125 | public int getBorderColor() { 126 | return borderColor; 127 | } 128 | 129 | public void setBorderColor(int borderColor) { 130 | this.borderColor = borderColor; 131 | invalidateSelf(); 132 | } 133 | 134 | public boolean isCircle() { 135 | return circle; 136 | } 137 | 138 | public void setCircle(boolean circle) { 139 | this.circle = circle; 140 | invalidateSelf(); 141 | } 142 | 143 | public int getRoundedCornerRadius() { 144 | return roundedCornerRadius; 145 | } 146 | 147 | public void setRoundedCornerRadius(int roundedCornerRadius) { 148 | this.roundedCornerRadius = roundedCornerRadius; 149 | invalidateSelf(); 150 | } 151 | 152 | @Override 153 | public void setImageMatrix(Matrix matrix) { 154 | super.setImageMatrix(matrix); 155 | invalidateSelf(); 156 | } 157 | 158 | public void setRounded(boolean roundTopLeft, boolean roundTopRight, boolean roundBottomLeft, boolean roundBottomRight) { 159 | this.roundTopLeft = roundTopLeft; 160 | this.roundTopRight = roundTopRight; 161 | this.roundBottomLeft = roundBottomLeft; 162 | this.roundBottomRight = roundBottomRight; 163 | invalidateSelf(); 164 | } 165 | 166 | protected void updateRoundedInfo() { 167 | if (imageDrawable instanceof RoundedCornerDrawable) { 168 | RoundedCornerDrawable drawable = (RoundedCornerDrawable) imageDrawable; 169 | drawable.roundBottomLeft = this.roundBottomLeft; 170 | drawable.roundBottomRight = this.roundBottomRight; 171 | drawable.roundTopLeft = this.roundTopLeft; 172 | drawable.roundTopRight = this.roundTopRight; 173 | drawable.roundedCornerRadius = this.roundedCornerRadius; 174 | drawable.borderColor = this.borderColor; 175 | drawable.borderWidth = this.borderWidth; 176 | drawable.circle = this.circle; 177 | drawable.imageMatrix = this.getImageMatrix(); 178 | drawable.scaleType = this.getScaleType(); 179 | 180 | drawable.borderPaint.setColor(borderColor); 181 | } 182 | if (placeholderImage instanceof RoundedCornerDrawable) { 183 | RoundedCornerDrawable drawable = (RoundedCornerDrawable) placeholderImage; 184 | drawable.roundBottomLeft = this.roundBottomLeft; 185 | drawable.roundBottomRight = this.roundBottomRight; 186 | drawable.roundTopLeft = this.roundTopLeft; 187 | drawable.roundTopRight = this.roundTopRight; 188 | drawable.roundedCornerRadius = this.roundedCornerRadius; 189 | drawable.borderColor = this.borderColor; 190 | drawable.borderWidth = this.borderWidth; 191 | drawable.circle = this.circle; 192 | drawable.imageMatrix = this.getImageMatrix(); 193 | drawable.scaleType = this.getScaleType(); 194 | 195 | drawable.borderPaint.setColor(borderColor); 196 | } 197 | } 198 | 199 | protected void invalidateSelf() { 200 | if (imageDrawable instanceof RoundedCornerDrawable) { 201 | updateRoundedInfo(); 202 | imageDrawable.invalidateSelf(); 203 | } 204 | } 205 | 206 | /** 207 | * 判断两张图片是否相同 208 | */ 209 | private boolean isSame(Drawable drawable1, Drawable drawable2) { 210 | if (drawable1 == null || drawable2 == null) { 211 | return false; 212 | } 213 | if (!(drawable1 instanceof RoundedCornerDrawable)) { 214 | return false; 215 | } 216 | if (!(drawable2 instanceof RoundedCornerDrawable)) { 217 | return false; 218 | } 219 | RoundedCornerDrawable tmp1 = (RoundedCornerDrawable) drawable1; 220 | RoundedCornerDrawable tmp2 = (RoundedCornerDrawable) drawable2; 221 | if (tmp1.bitmap.getByteCount() != tmp2.bitmap.getByteCount()) { 222 | return false; 223 | } 224 | int tmpPixel1 = 0; 225 | int tmpPixel2 = 0; 226 | int gap1 = tmp1.bitmap.getWidth() / 20; 227 | int gap2 = tmp2.bitmap.getWidth() / 20; 228 | if (gap1 < 5) { 229 | gap1 = 5; 230 | } 231 | if (gap2 < 5) { 232 | gap2 = 5; 233 | } 234 | for (int i = 0; i < tmp1.bitmap.getWidth(); i += gap1) { 235 | for (int j = 0; j < tmp1.bitmap.getHeight(); j += gap1) { 236 | tmpPixel1 += tmp1.bitmap.getPixel(i, j); 237 | } 238 | } 239 | for (int i = 0; i < tmp2.bitmap.getWidth(); i += gap2) { 240 | for (int j = 0; j < tmp2.bitmap.getHeight(); j += gap2) { 241 | tmpPixel2 += tmp2.bitmap.getPixel(i, j); 242 | } 243 | } 244 | return tmpPixel1 == tmpPixel2; 245 | } 246 | } 247 | -------------------------------------------------------------------------------- /ImageViewEx/src/main/java/com/taoweiji/image/RoundedColorDrawable.java: -------------------------------------------------------------------------------- 1 | package com.taoweiji.image; 2 | 3 | import android.graphics.Canvas; 4 | import android.graphics.Color; 5 | import android.graphics.ColorFilter; 6 | import android.graphics.Paint; 7 | import android.graphics.PixelFormat; 8 | import android.graphics.RectF; 9 | import android.graphics.drawable.Drawable; 10 | 11 | /** 12 | * 13 | */ 14 | public class RoundedColorDrawable extends Drawable { 15 | private Paint paint; 16 | private int color; 17 | private boolean circle = true; 18 | private int roundedCornerRadius = 0; 19 | private boolean roundTopLeft = false; 20 | private boolean roundTopRight = true; 21 | private boolean roundBottomLeft = true; 22 | private boolean roundBottomRight = true; 23 | 24 | 25 | public RoundedColorDrawable() { 26 | paint = new Paint(); 27 | paint.setStyle(Paint.Style.FILL); 28 | paint.setAntiAlias(true); 29 | paint.setColor(Color.BLACK); 30 | } 31 | 32 | 33 | @Override 34 | public void draw(Canvas canvas) { 35 | int width = getBounds().width(); 36 | int height = getBounds().height(); 37 | if (!circle) { 38 | canvas.drawRoundRect(new RectF(0, 0, width, height), roundedCornerRadius, roundedCornerRadius, paint); 39 | // 如果部分是直角就绘制直角覆盖物 40 | if (!roundTopLeft) { 41 | canvas.drawRect(0, 0, width / 2, height / 2, paint); 42 | } 43 | if (!roundTopRight) { 44 | canvas.drawRect(width / 2, 0, width, height / 2, paint); 45 | } 46 | if (!roundBottomLeft) { 47 | canvas.drawRect(0, height / 2, width / 2, height, paint); 48 | } 49 | if (!roundBottomRight) { 50 | canvas.drawRect(width / 2, height / 2, width, height, paint); 51 | } 52 | } else { 53 | canvas.drawCircle(getBounds().centerX(), getBounds().centerX(), width / 2, paint); 54 | } 55 | // canvas.restore(); 56 | } 57 | 58 | @Override 59 | public void setAlpha(int alpha) { 60 | 61 | } 62 | 63 | @Override 64 | public void setColorFilter(ColorFilter colorFilter) { 65 | 66 | } 67 | 68 | @Override 69 | public int getOpacity() { 70 | return PixelFormat.TRANSPARENT; 71 | } 72 | 73 | public int getColor() { 74 | return color; 75 | } 76 | 77 | public void setColor(int color) { 78 | this.color = color; 79 | paint.setColor(color); 80 | invalidateSelf(); 81 | } 82 | 83 | public int getRoundedCornerRadius() { 84 | return roundedCornerRadius; 85 | } 86 | 87 | public void setRoundedCornerRadius(int roundedCornerRadius) { 88 | this.roundedCornerRadius = roundedCornerRadius; 89 | invalidateSelf(); 90 | } 91 | 92 | 93 | public void setRounded(boolean roundTopLeft, boolean roundTopRight, boolean roundBottomLeft, boolean roundBottomRight) { 94 | this.roundTopLeft = roundTopLeft; 95 | this.roundTopRight = roundTopRight; 96 | this.roundBottomLeft = roundBottomLeft; 97 | this.roundBottomRight = roundBottomRight; 98 | invalidateSelf(); 99 | } 100 | 101 | public boolean isCircle() { 102 | return circle; 103 | } 104 | 105 | public void setCircle(boolean circle) { 106 | this.circle = circle; 107 | invalidateSelf(); 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /ImageViewEx/src/main/java/com/taoweiji/image/RoundedCornerDrawable.java: -------------------------------------------------------------------------------- 1 | package com.taoweiji.image; 2 | 3 | import android.content.res.Resources; 4 | import android.graphics.Bitmap; 5 | import android.graphics.Canvas; 6 | import android.graphics.Color; 7 | import android.graphics.ColorFilter; 8 | import android.graphics.Matrix; 9 | import android.graphics.Paint; 10 | import android.graphics.PixelFormat; 11 | import android.graphics.PorterDuff; 12 | import android.graphics.PorterDuffXfermode; 13 | import android.graphics.Rect; 14 | import android.graphics.RectF; 15 | import android.graphics.drawable.BitmapDrawable; 16 | import android.graphics.drawable.Drawable; 17 | import android.graphics.drawable.LayerDrawable; 18 | import android.os.Build; 19 | import android.util.Log; 20 | import android.view.ViewGroup; 21 | import android.widget.ImageView; 22 | 23 | public class RoundedCornerDrawable extends Drawable { 24 | private static final String TAG = "RoundedCornerDrawable"; 25 | final Bitmap bitmap; 26 | private final ImageView imageView; 27 | 28 | Paint borderPaint; 29 | Paint bitmapPaint; 30 | 31 | ImageView.ScaleType scaleType = ImageView.ScaleType.MATRIX; 32 | int borderWidth = 0; 33 | int borderColor = Color.WHITE; 34 | boolean circle = false; 35 | int roundedCornerRadius = 0; 36 | boolean roundTopLeft = true; 37 | boolean roundTopRight = true; 38 | boolean roundBottomLeft = true; 39 | boolean roundBottomRight = true; 40 | Matrix imageMatrix; 41 | 42 | 43 | public RoundedCornerDrawable(Bitmap bitmap, ImageView imageView) { 44 | this.imageView = imageView; 45 | this.bitmap = bitmap; 46 | bitmapPaint = new Paint(); 47 | bitmapPaint.setAntiAlias(true); 48 | bitmapPaint.setColor(Color.WHITE); 49 | 50 | borderPaint = new Paint(); 51 | bitmapPaint.setAntiAlias(true); 52 | borderPaint.setColor(borderColor); 53 | } 54 | 55 | public static Drawable fromDrawable(Drawable drawable, ImageView imageView) { 56 | if (drawable == null) { 57 | return null; 58 | } 59 | if (drawable instanceof RoundedCornerDrawable) { 60 | return drawable; 61 | } 62 | if (drawable instanceof LayerDrawable) { 63 | return drawable; 64 | } 65 | Bitmap bitmap = drawableToBitmap(drawable); 66 | if (bitmap != null) { 67 | return new RoundedCornerDrawable(bitmap, imageView); 68 | } else { 69 | Log.w(TAG, "Failed to create bitmap from drawable!"); 70 | return null; 71 | } 72 | } 73 | 74 | public static Drawable fromBitmap(Bitmap bitmap, ImageView imageView) { 75 | if (bitmap == null) { 76 | return null; 77 | } 78 | return new RoundedCornerDrawable(bitmap, imageView); 79 | } 80 | 81 | /** 82 | * 绘制边框 83 | */ 84 | private void drawBorder(Canvas canvas) { 85 | if (borderWidth == 0) { 86 | return; 87 | } 88 | // 绘制边框 89 | int viewWidth = getBounds().width(); 90 | int viewHeight = getBounds().height(); 91 | if (viewWidth == 1 && viewHeight == 1) { 92 | viewWidth = bitmap.getWidth(); 93 | viewHeight = bitmap.getHeight(); 94 | } else if (viewHeight == 1) { 95 | viewHeight = (int) (viewWidth / (double) bitmap.getWidth() * bitmap.getHeight()); 96 | } else if (viewWidth == 1) { 97 | viewWidth = (int) (viewHeight / (double) bitmap.getHeight() * bitmap.getWidth()); 98 | } 99 | 100 | // boolean isCircle = circle; 101 | // if (!isCircle) { 102 | // if (width > height) { 103 | // isCircle = roundedCornerRadius > width / 2; 104 | // } else { 105 | // 106 | // } 107 | // } 108 | 109 | if (!circle) { 110 | canvas.drawRoundRect(new RectF(0, 0, viewWidth, viewHeight), roundedCornerRadius, roundedCornerRadius, borderPaint); 111 | // 如果部分是直角就绘制直角覆盖物 112 | if (!roundTopLeft) { 113 | canvas.drawRect(0, 0, viewWidth / 2, viewHeight / 2, borderPaint); 114 | } 115 | if (!roundTopRight) { 116 | canvas.drawRect(viewWidth / 2, 0, viewWidth, viewHeight / 2, borderPaint); 117 | } 118 | if (!roundBottomLeft) { 119 | canvas.drawRect(0, viewHeight / 2, viewWidth / 2, viewHeight, borderPaint); 120 | } 121 | if (!roundBottomRight) { 122 | canvas.drawRect(viewWidth / 2, viewHeight / 2, viewWidth, viewHeight, borderPaint); 123 | } 124 | } else { 125 | // 绘制圆圈 126 | // canvas.drawCircle(getBounds().centerX(), getBounds().centerX(), getBounds().width() / 2, borderPaint); 127 | if (viewWidth > viewHeight) { 128 | // 绘制圆圈 129 | canvas.drawCircle(getBounds().centerX(), getBounds().centerY(), viewHeight / 2, borderPaint); 130 | } else { 131 | // 绘制圆圈 132 | canvas.drawCircle(getBounds().centerX(), getBounds().centerY(), viewWidth / 2, borderPaint); 133 | } 134 | } 135 | } 136 | 137 | @Override 138 | public int getIntrinsicHeight() { 139 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { 140 | if (imageView != null && imageView.getAdjustViewBounds()){ 141 | return bitmap.getHeight(); 142 | } 143 | } 144 | return super.getIntrinsicHeight(); 145 | } 146 | 147 | @Override 148 | public int getIntrinsicWidth() { 149 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { 150 | if (imageView != null && imageView.getAdjustViewBounds()){ 151 | return bitmap.getWidth(); 152 | } 153 | } 154 | return super.getIntrinsicWidth(); 155 | } 156 | 157 | @Override 158 | public void draw(Canvas canvas) { 159 | drawBorder(canvas); 160 | int innerCornerRadius = roundedCornerRadius - borderWidth; 161 | int viewWidth = getBounds().width(); 162 | int viewHeight = getBounds().height(); 163 | if (viewWidth == 1 && viewHeight == 1) { 164 | viewWidth = bitmap.getWidth(); 165 | viewHeight = bitmap.getHeight(); 166 | new Exception("Be unable to handle android:layout_width=\"wrap_content\" and android:layout_height=\"wrap_content\"").printStackTrace(); 167 | if (imageView != null && imageView.getLayoutParams() != null && imageView.getLayoutParams().width == ViewGroup.LayoutParams.WRAP_CONTENT){ 168 | ViewGroup.LayoutParams layoutParams = imageView.getLayoutParams(); 169 | layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT; 170 | imageView.setLayoutParams(layoutParams); 171 | return; 172 | } 173 | } else if (viewHeight == 1) { 174 | viewHeight = (int) (viewWidth / (double) bitmap.getWidth() * bitmap.getHeight()); 175 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { 176 | if (imageView != null && !imageView.getAdjustViewBounds()) { 177 | this.scaleType = ImageView.ScaleType.FIT_CENTER; 178 | imageView.setAdjustViewBounds(true); 179 | } 180 | } 181 | } else if (viewWidth == 1) { 182 | viewWidth = (int) (viewHeight / (double) bitmap.getHeight() * bitmap.getWidth()); 183 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { 184 | if (imageView != null && !imageView.getAdjustViewBounds()) { 185 | this.scaleType = ImageView.ScaleType.FIT_CENTER; 186 | imageView.setAdjustViewBounds(true); 187 | } 188 | } 189 | } 190 | 191 | // 绘制边框 192 | int width = viewWidth - 2 * borderWidth; 193 | int height = viewHeight - 2 * borderWidth; 194 | int centerX = width / 2; 195 | int centerY = height / 2; 196 | Rect rect = new Rect(0, 0, width, height); 197 | 198 | if (width < 0 || height < 0) { 199 | Log.e("ImageViewEx", "viewWidth < 2 * borderWidth"); 200 | return; 201 | } 202 | 203 | Bitmap tmpBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); 204 | Canvas tmpCanvas = new Canvas(tmpBitmap); 205 | if (circle) { 206 | if (width > height) { 207 | // 绘制圆圈 208 | tmpCanvas.drawCircle(centerX, centerY, height / 2, bitmapPaint); 209 | } else { 210 | // 绘制圆圈 211 | tmpCanvas.drawCircle(centerX, centerY, width / 2, bitmapPaint); 212 | } 213 | // 设置混合模式 214 | bitmapPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); 215 | } else if (innerCornerRadius > 0 && (roundTopLeft || roundTopRight || roundBottomLeft || roundBottomRight)) { 216 | tmpCanvas.drawRoundRect(new RectF(0, 0, width, height), innerCornerRadius, innerCornerRadius, bitmapPaint); 217 | // 如果部分是直角就绘制直角覆盖物 218 | if (!roundTopLeft) { 219 | tmpCanvas.drawRect(0, 0, width / 2, height / 2, bitmapPaint); 220 | } 221 | if (!roundTopRight) { 222 | tmpCanvas.drawRect(width / 2, 0, width, height / 2, bitmapPaint); 223 | } 224 | if (!roundBottomLeft) { 225 | tmpCanvas.drawRect(0, height / 2, width / 2, height, bitmapPaint); 226 | } 227 | if (!roundBottomRight) { 228 | tmpCanvas.drawRect(width / 2, height / 2, width, height, bitmapPaint); 229 | } 230 | // 设置混合模式 231 | bitmapPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); 232 | } 233 | 234 | // 绘制图形 235 | Matrix matrix = new Matrix(); 236 | RectF srcRectF = new RectF(0, 0, bitmap.getWidth(), bitmap.getHeight()); 237 | RectF dstRectF = new RectF(0, 0, width, height); 238 | boolean isDrawBitmap = false; 239 | if (this.scaleType == ImageView.ScaleType.MATRIX) { 240 | if (this.imageMatrix != null) { 241 | tmpCanvas.drawBitmap(bitmap, this.imageMatrix, bitmapPaint); 242 | isDrawBitmap = true; 243 | } else { 244 | matrix.setRectToRect(srcRectF, dstRectF, Matrix.ScaleToFit.CENTER); 245 | } 246 | } else if (this.scaleType == ImageView.ScaleType.FIT_CENTER) { 247 | matrix.setRectToRect(srcRectF, dstRectF, Matrix.ScaleToFit.CENTER); 248 | } else if (this.scaleType == ImageView.ScaleType.FIT_START) { 249 | matrix.setRectToRect(srcRectF, dstRectF, Matrix.ScaleToFit.START); 250 | } else if (this.scaleType == ImageView.ScaleType.FIT_END) { 251 | matrix.setRectToRect(srcRectF, dstRectF, Matrix.ScaleToFit.END); 252 | } else if (this.scaleType == ImageView.ScaleType.FIT_XY) { 253 | matrix.setRectToRect(srcRectF, dstRectF, Matrix.ScaleToFit.FILL); 254 | } else if (this.scaleType == ImageView.ScaleType.CENTER_INSIDE) { 255 | matrix.setRectToRect(srcRectF, dstRectF, Matrix.ScaleToFit.CENTER); 256 | } else { 257 | Bitmap centerCrop = resizeBitmapByCenterCrop(bitmap, width, height); 258 | tmpCanvas.drawBitmap(centerCrop, new Rect(0, 0, centerCrop.getWidth(), centerCrop.getHeight()), rect, bitmapPaint); 259 | isDrawBitmap = true; 260 | } 261 | if (!isDrawBitmap) { 262 | tmpCanvas.drawBitmap(bitmap, matrix, bitmapPaint); 263 | } 264 | canvas.drawBitmap(tmpBitmap, borderWidth, borderWidth, null); 265 | bitmapPaint.setXfermode(null); 266 | } 267 | 268 | public Bitmap resizeBitmapByCenterCrop(Bitmap src, int dstWidth, int dstHeight) { 269 | if (src == null || dstWidth == 0 || dstHeight == 0) { 270 | return null; 271 | } 272 | float srcWHRate = src.getWidth() / (float) src.getHeight(); 273 | float dstWHRate = dstWidth / (float) dstHeight; 274 | 275 | if (srcWHRate == dstWHRate) { 276 | return src; 277 | } else if (srcWHRate > dstWHRate) { 278 | // 撑满高度,宽度居中裁剪 279 | int cutWidth = (int) (dstWHRate * src.getHeight()); 280 | int startX = (src.getWidth() - cutWidth) / 2; 281 | return Bitmap.createBitmap(src, startX, 0, cutWidth, src.getHeight()); 282 | } else { 283 | // 撑满宽度,高度居中裁剪 284 | int cutHeight = (int) (src.getWidth() / dstWHRate); 285 | if (cutHeight < 1) { 286 | cutHeight = 1; 287 | } 288 | int startY = (src.getHeight() - cutHeight) / 2; 289 | return Bitmap.createBitmap(src, 0, startY, src.getWidth(), cutHeight); 290 | } 291 | } 292 | 293 | public void setRounded(boolean roundTopLeft, boolean roundTopRight, boolean roundBottomLeft, boolean roundBottomRight) { 294 | this.roundTopLeft = roundTopLeft; 295 | this.roundTopRight = roundTopRight; 296 | this.roundBottomLeft = roundBottomLeft; 297 | this.roundBottomRight = roundBottomRight; 298 | invalidateSelf(); 299 | } 300 | 301 | 302 | @Override 303 | public void setAlpha(int alpha) { 304 | bitmapPaint.setAlpha(alpha); 305 | } 306 | 307 | @Override 308 | public void setColorFilter(ColorFilter colorFilter) { 309 | bitmapPaint.setColorFilter(colorFilter); 310 | invalidateSelf(); 311 | } 312 | 313 | @Override 314 | public int getOpacity() { 315 | return PixelFormat.TRANSPARENT; 316 | } 317 | 318 | public int getBorderColor() { 319 | return borderColor; 320 | } 321 | 322 | public void setBorderColor(int borderColor) { 323 | this.borderColor = borderColor; 324 | borderPaint.setColor(borderColor); 325 | invalidateSelf(); 326 | } 327 | 328 | public void setBorderWidth(int borderWidth) { 329 | this.borderWidth = borderWidth; 330 | invalidateSelf(); 331 | } 332 | 333 | public void setScaleType(ImageView.ScaleType scaleType) { 334 | this.scaleType = scaleType; 335 | invalidateSelf(); 336 | } 337 | 338 | public ImageView.ScaleType getScaleType() { 339 | return scaleType; 340 | } 341 | 342 | public boolean isCircle() { 343 | return circle; 344 | } 345 | 346 | public void setCircle(boolean circle) { 347 | this.circle = circle; 348 | invalidateSelf(); 349 | } 350 | 351 | public static Bitmap drawableToBitmap(Drawable drawable) { 352 | if (drawable == null) { 353 | return null; 354 | } 355 | 356 | if (drawable instanceof BitmapDrawable) { 357 | return ((BitmapDrawable) drawable).getBitmap(); 358 | } 359 | if (drawable.getIntrinsicWidth() == 0) { 360 | // TODO 如果设置color 361 | } 362 | 363 | Bitmap bitmap; 364 | int width = Math.max(drawable.getIntrinsicWidth(), 2); 365 | int height = Math.max(drawable.getIntrinsicHeight(), 2); 366 | try { 367 | bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); 368 | Canvas canvas = new Canvas(bitmap); 369 | drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); 370 | drawable.draw(canvas); 371 | } catch (IllegalArgumentException e) { 372 | e.printStackTrace(); 373 | bitmap = null; 374 | } 375 | return bitmap; 376 | } 377 | 378 | public Matrix getImageMatrix() { 379 | return imageMatrix; 380 | } 381 | 382 | public void setImageMatrix(Matrix imageMatrix) { 383 | this.imageMatrix = imageMatrix; 384 | invalidateSelf(); 385 | } 386 | 387 | public int getRoundedCornerRadius() { 388 | return roundedCornerRadius; 389 | } 390 | 391 | public void setRoundedCornerRadius(int roundedCornerRadius) { 392 | this.roundedCornerRadius = roundedCornerRadius; 393 | invalidateSelf(); 394 | } 395 | } -------------------------------------------------------------------------------- /ImageViewEx/src/main/res/values/attrs_image_view_ex.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /ImageViewEx/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | ImageViewEx 3 | 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 增强型ImageViewEx,提供圆角、边框功能、Fresco 替换其他图片框架方案 4 | 5 | [![Maven Central](https://img.shields.io/maven-central/v/io.github.taoweiji.image/image)](https://search.maven.org/search?q=io.github.taoweiji.image) 6 | 7 | 8 | 1. 提供替换Fresco框架的 SimpleDraweeView 9 | 2. 支持设置占位图 10 | 3. 支持设置四个圆角 11 | 4. 支持圆圈 12 | 5. 支持设置边框宽度,颜色 13 | 14 | ##### 引入项目 15 | 16 | ``` 17 | api 'io.github.taoweiji.image:ImageViewEx:+' 18 | ``` 19 | 替换 Fresco 的 SimpleDraweeView 类 20 | ``` 21 | api 'io.github.taoweiji.image:SimpleDraweeView:+' 22 | ``` 23 | 24 | ##### 使用 25 | ```xml 26 | 27 | 31 | 32 | 44 | 45 | 46 | ``` 47 | 48 | 49 | ##### 效果 50 | 51 | 52 | 53 | 54 | ## License 55 | 56 | Copyright 2019 taoweiji 57 | 58 | Licensed under the Apache License, Version 2.0 (the "License"); 59 | you may not use this file except in compliance with the License. 60 | You may obtain a copy of the License at 61 | 62 | http://www.apache.org/licenses/LICENSE-2.0 63 | 64 | Unless required by applicable law or agreed to in writing, software 65 | distributed under the License is distributed on an "AS IS" BASIS, 66 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 67 | See the License for the specific language governing permissions and 68 | limitations under the License. 69 | 70 | -------------------------------------------------------------------------------- /SimpleDraweeView/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /SimpleDraweeView/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion 30 5 | 6 | 7 | defaultConfig { 8 | minSdkVersion 14 9 | targetSdkVersion 30 10 | versionCode 1 11 | versionName "1.0" 12 | 13 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 14 | consumerProguardFiles 'consumer-rules.pro' 15 | } 16 | 17 | buildTypes { 18 | release { 19 | minifyEnabled false 20 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 21 | } 22 | } 23 | 24 | } 25 | 26 | dependencies { 27 | implementation fileTree(dir: 'libs', include: ['*.jar']) 28 | api project(path: ':ImageViewEx') 29 | } 30 | 31 | apply from: '../maven_public.gradle' -------------------------------------------------------------------------------- /SimpleDraweeView/consumer-rules.pro: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/taoweiji/ImageViewEx/c06cd6d01442cb953d3ab5190a4751a64dcd6352/SimpleDraweeView/consumer-rules.pro -------------------------------------------------------------------------------- /SimpleDraweeView/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /SimpleDraweeView/src/androidTest/java/com/facebook/drawee/replace/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.facebook.drawee.replace; 2 | 3 | import android.content.Context; 4 | 5 | import androidx.test.platform.app.InstrumentationRegistry; 6 | import androidx.test.ext.junit.runners.AndroidJUnit4; 7 | 8 | import org.junit.Test; 9 | import org.junit.runner.RunWith; 10 | 11 | import static org.junit.Assert.*; 12 | 13 | /** 14 | * Instrumented test, which will execute on an Android device. 15 | * 16 | * @see Testing documentation 17 | */ 18 | @RunWith(AndroidJUnit4.class) 19 | public class ExampleInstrumentedTest { 20 | @Test 21 | public void useAppContext() { 22 | // Context of the app under test. 23 | Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); 24 | 25 | assertEquals("com.facebook.drawee.replace.test", appContext.getPackageName()); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /SimpleDraweeView/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | -------------------------------------------------------------------------------- /SimpleDraweeView/src/main/java/com/facebook/drawee/view/SimpleDraweeView.java: -------------------------------------------------------------------------------- 1 | package com.facebook.drawee.view; 2 | 3 | import android.content.ContentResolver; 4 | import android.content.Context; 5 | import android.content.res.TypedArray; 6 | import android.graphics.Color; 7 | import android.graphics.drawable.Drawable; 8 | import android.net.Uri; 9 | import android.text.TextUtils; 10 | import android.util.AttributeSet; 11 | 12 | 13 | import com.facebook.drawee.replace.R; 14 | import com.taoweiji.image.ImageViewExBase; 15 | 16 | public class SimpleDraweeView extends ImageViewExBase { 17 | 18 | 19 | public SimpleDraweeView(Context context) { 20 | this(context, null); 21 | } 22 | 23 | public SimpleDraweeView(Context context, AttributeSet attrs) { 24 | this(context, attrs, 0); 25 | } 26 | 27 | public SimpleDraweeView(Context context, AttributeSet attrs, int defStyleAttr) { 28 | super(context, attrs, defStyleAttr); 29 | 30 | TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.SimpleDraweeView); 31 | 32 | this.roundedCornerRadius = typedArray.getDimensionPixelSize(R.styleable.SimpleDraweeView_roundedCornerRadius, roundedCornerRadius); 33 | this.roundTopLeft = typedArray.getBoolean(R.styleable.SimpleDraweeView_roundTopLeft, roundTopLeft); 34 | this.roundTopRight = typedArray.getBoolean(R.styleable.SimpleDraweeView_roundTopRight, roundTopRight); 35 | this.roundBottomLeft = typedArray.getBoolean(R.styleable.SimpleDraweeView_roundBottomLeft, roundBottomLeft); 36 | this.roundBottomRight = typedArray.getBoolean(R.styleable.SimpleDraweeView_roundBottomRight, roundBottomRight); 37 | 38 | 39 | this.circle = typedArray.getBoolean(R.styleable.SimpleDraweeView_roundAsCircle, circle); 40 | 41 | this.borderColor = typedArray.getColor(R.styleable.SimpleDraweeView_roundingBorderColor, Color.WHITE); 42 | this.borderWidth = typedArray.getDimensionPixelSize(R.styleable.SimpleDraweeView_roundingBorderWidth, borderWidth); 43 | this.fadeDuration = typedArray.getInt(R.styleable.SimpleDraweeView_fadeDuration, fadeDuration); 44 | 45 | int roundingBorderPadding = typedArray.getDimensionPixelSize(R.styleable.SimpleDraweeView_roundingBorderPadding, 0); 46 | int backgroundImage = typedArray.getResourceId(R.styleable.SimpleDraweeView_backgroundImage, 0); 47 | int actualImageScaleType = typedArray.getInt(R.styleable.SimpleDraweeView_actualImageScaleType, 0); 48 | int actualImageResource = typedArray.getResourceId(R.styleable.SimpleDraweeView_actualImageResource, 0); 49 | String actualImageUri = typedArray.getString(R.styleable.SimpleDraweeView_actualImageUri); 50 | 51 | Drawable placeholderImageTmp = typedArray.getDrawable(R.styleable.SimpleDraweeView_placeholderImage); 52 | int placeholderImageScaleType = typedArray.getInt(R.styleable.SimpleDraweeView_placeholderImageScaleType, 0); 53 | 54 | float viewAspectRatio = typedArray.getFloat(R.styleable.SimpleDraweeView_viewAspectRatio, 0); 55 | 56 | 57 | if (backgroundImage != 0) { 58 | setBackgroundResource(backgroundImage); 59 | } 60 | if (actualImageScaleType != 0) { 61 | ScaleType scaleType = intToScaleType(actualImageScaleType); 62 | setScaleType(scaleType); 63 | } else if (placeholderImageScaleType != 0) { 64 | ScaleType scaleType = intToScaleType(placeholderImageScaleType); 65 | setScaleType(scaleType); 66 | } 67 | if (actualImageUri != null) { 68 | Uri uri = Uri.parse(actualImageUri); 69 | if (!TextUtils.isEmpty(uri.getScheme())) { 70 | setImageURI(uri); 71 | } 72 | } 73 | if (actualImageResource != 0) { 74 | setImageResource(actualImageResource); 75 | } 76 | 77 | typedArray.recycle(); 78 | setImageDrawable(getDrawable()); 79 | setPlaceholderImageDrawable(placeholderImageTmp); 80 | } 81 | 82 | @Override 83 | public void setImageURI(Uri uri) { 84 | if (uri == null) { 85 | super.setImageURI(null); 86 | } else if ("res".equalsIgnoreCase(uri.getScheme())) { 87 | // 兼容 Fresco 的 res://xxx/xxx 的写法 88 | uri = uri.buildUpon().scheme(ContentResolver.SCHEME_ANDROID_RESOURCE).build(); 89 | super.setImageURI(uri); 90 | } else if (ContentResolver.SCHEME_ANDROID_RESOURCE.equals(uri.getScheme())) { 91 | super.setImageURI(uri); 92 | } else if (ContentResolver.SCHEME_CONTENT.equals(uri.getScheme()) || ContentResolver.SCHEME_FILE.equals(uri.getScheme())) { 93 | super.setImageURI(uri); 94 | } else { 95 | setImageURI(uri.toString()); 96 | } 97 | } 98 | 99 | public void setImageURI(String uriString) { 100 | loadHandler.load(this, uriString); 101 | } 102 | 103 | private static LoadHandler loadHandler; 104 | 105 | public static void setLoadHandler(LoadHandler loadHandler) { 106 | SimpleDraweeView.loadHandler = loadHandler; 107 | } 108 | 109 | public interface LoadHandler { 110 | void load(SimpleDraweeView imageView, String url); 111 | } 112 | 113 | private ScaleType intToScaleType(int type) { 114 | ScaleType scaleType; 115 | switch (type) { 116 | case 1: 117 | scaleType = ScaleType.FIT_XY; 118 | break; 119 | case 2: 120 | scaleType = ScaleType.FIT_START; 121 | break; 122 | case 3: 123 | scaleType = ScaleType.FIT_CENTER; 124 | break; 125 | case 4: 126 | scaleType = ScaleType.FIT_END; 127 | break; 128 | case 5: 129 | scaleType = ScaleType.CENTER; 130 | break; 131 | case 6: 132 | scaleType = ScaleType.CENTER_CROP; 133 | break; 134 | case 7: 135 | scaleType = ScaleType.CENTER_INSIDE; 136 | break; 137 | default: 138 | scaleType = ScaleType.MATRIX; 139 | } 140 | return scaleType; 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /SimpleDraweeView/src/main/res/values/attrs_simple_drawee_view.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 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | -------------------------------------------------------------------------------- /SimpleDraweeView/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | SimpleDraweeView 3 | 4 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | ext.kotlin_version = '1.3.41' 5 | repositories { 6 | google() 7 | mavenCentral() 8 | } 9 | dependencies { 10 | classpath 'com.android.tools.build:gradle:3.5.0' 11 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 12 | // NOTE: Do not place your application dependencies here; they belong 13 | // in the individual module build.gradle files 14 | } 15 | } 16 | 17 | allprojects { 18 | repositories { 19 | google() 20 | mavenCentral() 21 | } 22 | } 23 | 24 | task clean(type: Delete) { 25 | delete rootProject.buildDir 26 | } 27 | 28 | allprojects { 29 | tasks.withType(Javadoc) { 30 | options.addStringOption('Xdoclint:none', '-quiet') 31 | options.addStringOption('encoding', 'UTF-8') 32 | } 33 | } -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /example/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | apply plugin: 'kotlin-android' 3 | apply plugin: 'kotlin-android-extensions' 4 | 5 | android { 6 | compileSdkVersion 30 7 | defaultConfig { 8 | applicationId "com.taoweiji.image.example" 9 | minSdkVersion 14 10 | targetSdkVersion 30 11 | versionCode 1 12 | versionName "1.0" 13 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 14 | } 15 | buildTypes { 16 | release { 17 | minifyEnabled false 18 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 19 | } 20 | } 21 | } 22 | 23 | dependencies { 24 | implementation fileTree(dir: 'libs', include: ['*.jar']) 25 | implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 26 | implementation 'androidx.appcompat:appcompat:1.1.0' 27 | implementation 'androidx.core:core-ktx:1.1.0' 28 | implementation 'androidx.constraintlayout:constraintlayout:1.1.3' 29 | testImplementation 'junit:junit:4.12' 30 | androidTestImplementation 'androidx.test:runner:1.1.1' 31 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1' 32 | implementation project(path: ':ImageViewEx') 33 | implementation project(path: ':SimpleDraweeView') 34 | } 35 | -------------------------------------------------------------------------------- /example/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /example/src/androidTest/java/com/taoweiji/custom/view/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package com.taoweiji.custom.view 2 | 3 | import androidx.test.platform.app.InstrumentationRegistry 4 | import androidx.test.ext.junit.runners.AndroidJUnit4 5 | 6 | import org.junit.Test 7 | import org.junit.runner.RunWith 8 | 9 | import org.junit.Assert.* 10 | 11 | /** 12 | * Instrumented test, which will execute on an Android device. 13 | * 14 | * See [testing documentation](http://d.android.com/tools/testing). 15 | */ 16 | @RunWith(AndroidJUnit4::class) 17 | class ExampleInstrumentedTest { 18 | @Test 19 | fun useAppContext() { 20 | // Context of the app under test. 21 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext 22 | assertEquals("com.taoweiji.custom.view", appContext.packageName) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /example/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /example/src/main/java/com/taoweiji/image/example/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.taoweiji.image.example 2 | 3 | import androidx.appcompat.app.AppCompatActivity 4 | import android.os.Bundle 5 | import com.facebook.drawee.view.SimpleDraweeView 6 | import kotlinx.android.synthetic.main.activity_main.* 7 | 8 | class MainActivity : AppCompatActivity() { 9 | override fun onCreate(savedInstanceState: Bundle?) { 10 | super.onCreate(savedInstanceState) 11 | setContentView(R.layout.activity_main) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /example/src/main/java/com/taoweiji/image/example/MyApplication.kt: -------------------------------------------------------------------------------- 1 | package com.taoweiji.image.example 2 | 3 | import android.app.Application 4 | import com.facebook.drawee.view.SimpleDraweeView 5 | 6 | class MyApplication : Application() { 7 | override fun onCreate() { 8 | super.onCreate() 9 | SimpleDraweeView.setLoadHandler { imageView, url -> 10 | // 实现图片显示 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /example/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /example/src/main/res/drawable/bg_main_domain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/taoweiji/ImageViewEx/c06cd6d01442cb953d3ab5190a4751a64dcd6352/example/src/main/res/drawable/bg_main_domain.png -------------------------------------------------------------------------------- /example/src/main/res/drawable/colours.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | -------------------------------------------------------------------------------- /example/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /example/src/main/res/drawable/ic_launcher_test.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/taoweiji/ImageViewEx/c06cd6d01442cb953d3ab5190a4751a64dcd6352/example/src/main/res/drawable/ic_launcher_test.png -------------------------------------------------------------------------------- /example/src/main/res/drawable/test1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/taoweiji/ImageViewEx/c06cd6d01442cb953d3ab5190a4751a64dcd6352/example/src/main/res/drawable/test1.png -------------------------------------------------------------------------------- /example/src/main/res/drawable/test2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/taoweiji/ImageViewEx/c06cd6d01442cb953d3ab5190a4751a64dcd6352/example/src/main/res/drawable/test2.gif -------------------------------------------------------------------------------- /example/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 63 | 64 | 74 | 75 | 84 | 85 | 97 | 98 | 110 | 111 | 121 | 122 | -------------------------------------------------------------------------------- /example/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /example/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /example/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/taoweiji/ImageViewEx/c06cd6d01442cb953d3ab5190a4751a64dcd6352/example/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/taoweiji/ImageViewEx/c06cd6d01442cb953d3ab5190a4751a64dcd6352/example/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /example/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/taoweiji/ImageViewEx/c06cd6d01442cb953d3ab5190a4751a64dcd6352/example/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/taoweiji/ImageViewEx/c06cd6d01442cb953d3ab5190a4751a64dcd6352/example/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /example/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/taoweiji/ImageViewEx/c06cd6d01442cb953d3ab5190a4751a64dcd6352/example/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/taoweiji/ImageViewEx/c06cd6d01442cb953d3ab5190a4751a64dcd6352/example/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /example/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/taoweiji/ImageViewEx/c06cd6d01442cb953d3ab5190a4751a64dcd6352/example/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/taoweiji/ImageViewEx/c06cd6d01442cb953d3ab5190a4751a64dcd6352/example/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /example/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/taoweiji/ImageViewEx/c06cd6d01442cb953d3ab5190a4751a64dcd6352/example/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/taoweiji/ImageViewEx/c06cd6d01442cb953d3ab5190a4751a64dcd6352/example/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /example/src/main/res/values/attrs_my_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/src/main/res/values/attrs_rounded_image_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /example/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #008577 4 | #00574B 5 | #D81B60 6 | 7 | -------------------------------------------------------------------------------- /example/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | ImageViewEx 3 | 4 | -------------------------------------------------------------------------------- /example/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /example/src/test/java/com/taoweiji/custom/view/ExampleUnitTest.kt: -------------------------------------------------------------------------------- 1 | package com.taoweiji.custom.view 2 | 3 | import org.junit.Test 4 | 5 | import org.junit.Assert.* 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * See [testing documentation](http://d.android.com/tools/testing). 11 | */ 12 | class ExampleUnitTest { 13 | @Test 14 | fun addition_isCorrect() { 15 | assertEquals(4, 2 + 2) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /example_01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/taoweiji/ImageViewEx/c06cd6d01442cb953d3ab5190a4751a64dcd6352/example_01.png -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | # IDE (e.g. Android Studio) users: 3 | # Gradle settings configured through the IDE *will override* 4 | # any settings specified in this file. 5 | # For more details on how to configure your build environment visit 6 | # http://www.gradle.org/docs/current/userguide/build_environment.html 7 | # Specifies the JVM arguments used for the daemon process. 8 | # The setting is particularly useful for tweaking memory settings. 9 | org.gradle.jvmargs=-Xmx1536m 10 | # When configured, Gradle will run in incubating parallel mode. 11 | # This option should only be used with decoupled projects. More details, visit 12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 13 | # org.gradle.parallel=true 14 | # AndroidX package structure to make it clearer which packages are bundled with the 15 | # Android operating system, and which are packaged with your app's APK 16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 17 | android.useAndroidX=true 18 | # Automatically convert third-party libraries to use AndroidX 19 | android.enableJetifier=true 20 | # Kotlin code style for this project: "official" or "obsolete": 21 | kotlin.code.style=official 22 | 23 | GROUP_ID=io.github.taoweiji.image 24 | VERSION_NAME=1.3.0 25 | POM_NAME=ImageViewEx 26 | POM_DESCRIPTION=ImageViewEx for Android 27 | POM_URL=https://github.com/taoweiji/ImageViewEx 28 | POM_SCM_URL=https://github.com/taoweiji/ImageViewEx 29 | POM_SCM_CONNECTION=scm:git@github.com:taoweiji/ImageViewEx.git 30 | POM_SCM_DEV_CONNECTION=scm:git@github.com:taoweiji/ImageViewEx.git 31 | POM_LICENCE_NAME=The Apache Software License, Version 2.0 32 | POM_LICENCE_URL=http://www.apache.org/licenses/LICENSE-2.0.txt 33 | POM_LICENCE_DIST=repo 34 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/taoweiji/ImageViewEx/c06cd6d01442cb953d3ab5190a4751a64dcd6352/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Sun Sep 22 22:35:21 CST 2019 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 sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn () { 37 | echo "$*" 38 | } 39 | 40 | die () { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save () { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /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 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 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 Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /maven_public.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'maven' 2 | 3 | group = GROUP_ID 4 | version = VERSION_NAME 5 | 6 | uploadArchives { 7 | repositories { 8 | mavenDeployer { 9 | repository(url: uri('../repo')) 10 | } 11 | } 12 | } 13 | 14 | //return 15 | apply plugin: 'maven' 16 | apply plugin: 'signing' 17 | signing { 18 | sign configurations.archives 19 | } 20 | boolean isAndroid = project.getPlugins().hasPlugin('com.android.library') 21 | if (isAndroid) { 22 | task androidJavadocs(type: Javadoc) { 23 | source = android.sourceSets.main.java.source 24 | classpath += project.files(android.getBootClasspath().join(File.pathSeparator)) 25 | excludes = ['**/*.kt'] 26 | } 27 | task androidJavadocsJar(type: Jar, dependsOn: androidJavadocs) { 28 | classifier = 'javadoc' 29 | from androidJavadocs.destinationDir 30 | } 31 | task androidSourcesJar(type: Jar) { 32 | classifier = 'sources' 33 | from android.sourceSets.main.java.source 34 | } 35 | } else { 36 | task javadocJar(type: Jar) { 37 | classifier = 'javadoc' 38 | from javadoc 39 | } 40 | task sourcesJar(type: Jar) { 41 | classifier = 'sources' 42 | from sourceSets.main.allSource 43 | } 44 | artifacts { 45 | archives javadocJar, sourcesJar 46 | } 47 | } 48 | 49 | signing { 50 | // keyId = "0945148C" 51 | // password = "Tao408191243." 52 | // secretKeyRingFile = "/Users/wiki/.gnupg/secring.gpg" 53 | } 54 | 55 | 56 | uploadArchives { 57 | repositories { 58 | mavenDeployer { 59 | beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) } 60 | repository(url: "https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/") { 61 | authentication(userName: OSSRH_USERNAME, password: OSSRH_PASSWORD) 62 | } 63 | snapshotRepository(url: "https://s01.oss.sonatype.org/content/repositories/snapshots/") { 64 | authentication(userName: OSSRH_USERNAME, password: OSSRH_PASSWORD) 65 | } 66 | pom.project { 67 | name POM_NAME 68 | packaging isAndroid ? 'jar' : 'aar' 69 | description POM_DESCRIPTION 70 | url POM_URL 71 | scm { 72 | connection POM_SCM_CONNECTION 73 | developerConnection POM_SCM_DEV_CONNECTION 74 | url POM_SCM_URL 75 | } 76 | licenses { 77 | license { 78 | name POM_LICENCE_NAME 79 | url POM_LICENCE_URL 80 | } 81 | } 82 | developers { 83 | developer { 84 | id POM_DEVELOPER_ID 85 | name POM_DEVELOPER_NAME 86 | email POM_DEVELOPER_EMAIL 87 | } 88 | } 89 | } 90 | } 91 | } 92 | } -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':example', ':ImageViewEx', ':SimpleDraweeView' 2 | rootProject.name='ImageViewEx' 3 | --------------------------------------------------------------------------------