selectedPhotoList);
19 | }
20 |
--------------------------------------------------------------------------------
/imageset/src/main/java/com/sxu/smartpicture/album/listener/OnViewCreatedListener.java:
--------------------------------------------------------------------------------
1 | package com.sxu.smartpicture.album.listener;
2 |
3 | import android.view.View;
4 | import android.widget.AbsListView;
5 | import android.widget.GridView;
6 |
7 | /*******************************************************************************
8 | * Description: 监听View加载(用于修改View样式)
9 | *
10 | * Author: Freeman
11 | *
12 | * Date: 2018/12/24
13 | *
14 | * Copyright: all rights reserved by Freeman.
15 | *******************************************************************************/
16 | public interface OnViewCreatedListener {
17 | void onViewCreated(View containerView);
18 | }
19 |
--------------------------------------------------------------------------------
/imageset/src/main/java/com/sxu/smartpicture/choosepicture/ChoosePhotoDialog.java:
--------------------------------------------------------------------------------
1 | package com.sxu.smartpicture.choosepicture;
2 |
3 | import android.app.AlertDialog;
4 | import android.content.Context;
5 | import android.content.res.Resources;
6 | import android.graphics.Color;
7 | import android.os.Bundle;
8 | import android.view.Gravity;
9 | import android.view.View;
10 | import android.view.ViewGroup;
11 | import android.view.Window;
12 | import android.view.WindowManager;
13 | import android.widget.AbsListView;
14 | import android.widget.AdapterView;
15 | import android.widget.BaseAdapter;
16 | import android.widget.ListView;
17 | import android.widget.TextView;
18 |
19 | import com.sxu.smartpicture.R;
20 |
21 | import java.util.List;
22 |
23 | /*******************************************************************************
24 | * FileName: CommonChooseDialog
25 | *
26 | * Description:
27 | *
28 | * Author: Freeman
29 | *
30 | * Version: v1.0
31 | *
32 | * Date: 16/10/19
33 | *
34 | * Copyright: all rights reserved by Freeman.
35 | *******************************************************************************/
36 |
37 | public class ChoosePhotoDialog extends AlertDialog {
38 |
39 | private TextView cancelText;
40 | private ListView listView;
41 | private String[] items;
42 |
43 | private int textSize;
44 | private int textColor;
45 |
46 | public ChoosePhotoDialog(Context context, List itemList) {
47 | this(context, itemList != null ? itemList.toArray(new String[itemList.size()]) : null);
48 | }
49 |
50 | public ChoosePhotoDialog(Context context, String[] items) {
51 | super(context, R.style.CommonDialog);
52 | this.items = items;
53 | }
54 |
55 | @Override
56 | protected void onCreate(Bundle savedInstanceState) {
57 | super.onCreate(savedInstanceState);
58 | setContentView(R.layout.dialog_common_choose_layout);
59 | listView = (ListView) findViewById(R.id.listView);
60 | cancelText = (TextView) findViewById(R.id.cancel_text);
61 |
62 | if (items != null && items.length > 0) {
63 | textSize = 18;
64 | textColor = Color.parseColor("#333333");
65 | listView.setAdapter(new MenuAdapter());
66 | }
67 |
68 | cancelText.setOnClickListener(new View.OnClickListener() {
69 | @Override
70 | public void onClick(View v) {
71 | dismiss();
72 | }
73 | });
74 | }
75 |
76 | public void setOnItemListener(final AdapterView.OnItemClickListener listener) {
77 | if (listView != null && listener != null) {
78 | listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
79 | @Override
80 | public void onItemClick(AdapterView> parent, View view, int position, long id) {
81 | if (id >= 0) {
82 | listener.onItemClick(parent, view, (int) id, id);
83 | dismiss();
84 | }
85 | }
86 | });
87 | }
88 | }
89 |
90 | public void show() {
91 | super.show();
92 | Window window = getWindow();
93 | WindowManager.LayoutParams params = window.getAttributes();
94 | params.width = Resources.getSystem().getDisplayMetrics().widthPixels;
95 | params.gravity = Gravity.BOTTOM;
96 | window.setAttributes(params);
97 | }
98 |
99 | private class MenuAdapter extends BaseAdapter {
100 |
101 | @Override
102 | public int getCount() {
103 | return items.length;
104 | }
105 |
106 | @Override
107 | public Object getItem(int position) {
108 | return items[position];
109 | }
110 |
111 | @Override
112 | public long getItemId(int position) {
113 | return position;
114 | }
115 |
116 | @Override
117 | public View getView(int position, View convertView, ViewGroup parent) {
118 | TextView textView = new TextView(getContext());
119 | textView.setTextSize(textSize);
120 | AbsListView.LayoutParams params = new AbsListView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
121 | (int) (Resources.getSystem().getDisplayMetrics().density * 50));
122 | textView.setLayoutParams(params);
123 | textView.setGravity(Gravity.CENTER);
124 | textView.setText(items[position]);
125 | textView.setTextColor(textColor);
126 |
127 | return textView;
128 | }
129 | }
130 | }
131 |
132 |
--------------------------------------------------------------------------------
/imageset/src/main/java/com/sxu/smartpicture/choosepicture/ChoosePhotoManager.java:
--------------------------------------------------------------------------------
1 | package com.sxu.smartpicture.choosepicture;
2 |
3 | import android.Manifest;
4 | import android.app.Activity;
5 | import android.content.Intent;
6 | import android.graphics.Bitmap;
7 | import android.net.Uri;
8 | import android.os.Environment;
9 | import android.os.StrictMode;
10 | import android.provider.MediaStore;
11 | import android.util.Log;
12 |
13 | import com.sxu.permission.CheckPermission;
14 |
15 | import java.io.File;
16 | import java.text.SimpleDateFormat;
17 | import java.util.Date;
18 |
19 | /**
20 | * @author Freeman
21 | * @date 17/11/8
22 | */
23 |
24 | public class ChoosePhotoManager {
25 |
26 | private Uri iconUri;
27 | private Uri cropImageUri;
28 | private File imageFile;
29 | private boolean autoCrop = false;
30 | private OnChoosePhotoListener listener;
31 |
32 | private static final int REQUEST_CODE_TAKE_PHOTO = 1001;
33 | private static final int REQUEST_CODE_CHOOSE_IMAGE = 1002;
34 | private static final int REQUEST_CODE_CROP_IMAGE = 1003;
35 |
36 | private static ChoosePhotoManager instance;
37 |
38 | private ChoosePhotoManager() {
39 |
40 | }
41 |
42 | public static ChoosePhotoManager getInstance() {
43 | if (instance == null) {
44 | instance = new ChoosePhotoManager();
45 | }
46 |
47 | return instance;
48 | }
49 |
50 | public void choosePhotoFromAlbum(Activity activity) {
51 | choosePhotoFromAlbum(activity, false);
52 | }
53 |
54 | public void choosePhotoFromAlbum(Activity activity, boolean autoCrop) {
55 | this.autoCrop = autoCrop;
56 | Intent intent = new Intent(Intent.ACTION_PICK, null);
57 | intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");
58 | if (intent.resolveActivity(activity.getPackageManager()) != null) {
59 | activity.startActivityForResult(intent, REQUEST_CODE_CHOOSE_IMAGE);
60 | }
61 | }
62 |
63 | public void takePicture(Activity activity) {
64 | takePicture(activity, false);
65 | }
66 |
67 | @CheckPermission(permissions = {Manifest.permission.CAMERA}, permissionDesc = "此功能需要相机权限才可使用")
68 | public void takePicture(Activity activity, boolean autoCrop) {
69 | this.autoCrop = autoCrop;
70 | Date date = new Date();
71 | String fileName = "IMG_" + new SimpleDateFormat("yyyyMMddHHmmss").format(date);
72 | Log.i("out", "rootPath=" + Environment.getExternalStorageDirectory() + " cahce==" + activity.getCacheDir());
73 | imageFile = new File(activity.getExternalCacheDir() + fileName);
74 | StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
75 | StrictMode.setVmPolicy(builder.build());
76 | iconUri = Uri.fromFile(imageFile);
77 | Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
78 | intent.putExtra(MediaStore.EXTRA_OUTPUT, iconUri);
79 | if (intent.resolveActivity(activity.getPackageManager()) != null) {
80 | activity.startActivityForResult(intent, REQUEST_CODE_TAKE_PHOTO);
81 | }
82 | }
83 |
84 | public void cropPhoto(Activity activity, Uri uri) {
85 | Intent intent = new Intent("com.android.camera.action.CROP");
86 | intent.setDataAndType(uri, "image/*");
87 | intent.putExtra("crop", "true");
88 | intent.putExtra("aspectX", 1);
89 | intent.putExtra("aspectY", 1);
90 | intent.putExtra("scale", true);
91 | intent.putExtra("outputX", 300);
92 | intent.putExtra("outputY", 300);
93 | // 以Uri的方式传递照片
94 | File cropFile = new File(activity.getExternalCacheDir() + "crop_image.jpg");
95 | cropImageUri = Uri.fromFile(cropFile);
96 | intent.putExtra(MediaStore.EXTRA_OUTPUT, cropImageUri);
97 | intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
98 | // return-data=true传递的为缩略图,小米手机默认传递大图,所以会导致onActivityResult调用失败
99 | intent.putExtra("return-data", false);
100 | intent.putExtra("noFaceDetection", false);
101 | if (intent.resolveActivity(activity.getPackageManager()) != null) {
102 | activity.startActivityForResult(intent, REQUEST_CODE_CROP_IMAGE);
103 | }
104 | }
105 |
106 | public void onActivityResult(Activity activity, int requestCode, Intent intent) {
107 | if(intent != null) {
108 | switch (requestCode) {
109 | case REQUEST_CODE_TAKE_PHOTO:
110 | if (autoCrop && imageFile.length() != 0) {
111 | cropPhoto(activity, iconUri);
112 | }
113 | if (listener != null && imageFile.length() != 0) {
114 | listener.choosePhotoFromCamera(iconUri);
115 | }
116 | break;
117 | case REQUEST_CODE_CHOOSE_IMAGE:
118 | iconUri = intent.getData();
119 | if (autoCrop && iconUri != null) {
120 | cropPhoto(activity, iconUri);
121 | }
122 | if (listener != null) {
123 | listener.choosePhotoFromAlbum(iconUri);
124 | }
125 | break;
126 | case REQUEST_CODE_CROP_IMAGE:
127 | if (listener != null) {
128 | listener.cropPhoto(cropImageUri);
129 | }
130 | break;
131 | default:
132 | break;
133 | }
134 | } else {
135 | // 关闭拍照界面或拍照完成后都会调用
136 | if (requestCode == REQUEST_CODE_TAKE_PHOTO) {
137 | if (autoCrop && imageFile.length() != 0) {
138 | cropPhoto(activity, iconUri);
139 | }
140 | if (listener != null && imageFile.length() != 0) {
141 | listener.choosePhotoFromCamera(iconUri);
142 | }
143 | }
144 | }
145 | }
146 |
147 | /**
148 | * 选择照片或者拍照后是否需要裁剪
149 | * @param autoCrop
150 | */
151 | public void setAutoCrop(boolean autoCrop) {
152 | this.autoCrop = autoCrop;
153 | }
154 |
155 | public void setChoosePhotoListener(OnChoosePhotoListener listener) {
156 | this.listener = listener;
157 | }
158 | }
159 |
--------------------------------------------------------------------------------
/imageset/src/main/java/com/sxu/smartpicture/choosepicture/OnChoosePhotoListener.java:
--------------------------------------------------------------------------------
1 | package com.sxu.smartpicture.choosepicture;
2 |
3 | import android.net.Uri;
4 |
5 | /**
6 | * @author Freeman
7 | * @date 17/11/8
8 | */
9 |
10 |
11 | public interface OnChoosePhotoListener {
12 |
13 | /**
14 | * 从相册选择图片
15 | * @param uri uri != null表示成功,否则表示失败
16 | */
17 | void choosePhotoFromAlbum(Uri uri);
18 |
19 | /**
20 | * 拍照
21 | * @param uri
22 | */
23 | void choosePhotoFromCamera(Uri uri);
24 |
25 | /**
26 | * 裁剪图片
27 | * @param uri
28 | */
29 | void cropPhoto(Uri uri);
30 | }
31 |
--------------------------------------------------------------------------------
/imageset/src/main/java/com/sxu/smartpicture/choosepicture/OnSimpleChoosePhotoListener.java:
--------------------------------------------------------------------------------
1 | package com.sxu.smartpicture.choosepicture;
2 |
3 | import android.net.Uri;
4 |
5 | /*******************************************************************************
6 | * Description:
7 | *
8 | * Author: Freeman
9 | *
10 | * Date: 2018/12/17
11 | *
12 | * Copyright: all rights reserved by Freeman.
13 | *******************************************************************************/
14 | public abstract class OnSimpleChoosePhotoListener implements OnChoosePhotoListener {
15 |
16 | @Override
17 | public void choosePhotoFromAlbum(Uri uri) {
18 |
19 | }
20 |
21 | @Override
22 | public void choosePhotoFromCamera(Uri uri) {
23 |
24 | }
25 |
26 | @Override
27 | public void cropPhoto(Uri uri) {
28 |
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/imageset/src/main/java/com/sxu/smartpicture/imageloader/ImageLoaderManager.java:
--------------------------------------------------------------------------------
1 | package com.sxu.smartpicture.imageloader;
2 |
3 | import android.content.Context;
4 | import android.util.Log;
5 |
6 | import com.sxu.smartpicture.imageloader.instance.ImageLoaderInstance;
7 | import com.sxu.smartpicture.imageloader.listener.ImageLoaderListener;
8 |
9 | /**
10 |
11 | * 类或接口的描述信息
12 | *
13 | * @author Freeman
14 | * @date 2017/12/5
15 | */
16 |
17 |
18 | public class ImageLoaderManager {
19 |
20 | private ImageLoaderInstance mLoaderInstance;
21 |
22 | protected ImageLoaderManager() {
23 |
24 | }
25 |
26 | public static ImageLoaderManager getInstance() {
27 | return Singleton.instance;
28 | }
29 |
30 | public void init(Context context, ImageLoaderInstance loaderInstance) {
31 | if (loaderInstance == null) {
32 | throw new IllegalArgumentException("loaderInstance can't be null");
33 | } else if (mLoaderInstance != null) {
34 | Log.w("out", "ImageLoaderManager has initialized!!!");
35 | } else {
36 | synchronized (this) {
37 | mLoaderInstance = loaderInstance;
38 | mLoaderInstance.init(context);
39 | }
40 | }
41 | }
42 |
43 | public boolean isInit() {
44 | return mLoaderInstance != null;
45 | }
46 |
47 | public ImageLoaderInstance getImageLoaderInstance() {
48 | return mLoaderInstance;
49 | }
50 |
51 | public void displayImage(String url, WrapImageView imageView) {
52 | mLoaderInstance.displayImage(url, imageView);
53 | }
54 |
55 | public void displayImage(String url, WrapImageView imageView, int width, int height) {
56 | Log.i("out", "url====" + url);
57 | mLoaderInstance.displayImage(url, imageView, width, height);
58 | }
59 |
60 | public void displayImage(String url, WrapImageView imageView, ImageLoaderListener listener) {
61 | mLoaderInstance.displayImage(url, imageView, listener);
62 | }
63 |
64 | public void displayImage(String url, WrapImageView imageView, int width, int height, ImageLoaderListener listener) {
65 | mLoaderInstance.displayImage(url, imageView, width, height, listener);
66 | }
67 |
68 | public void downloadImage(Context context, String url, ImageLoaderListener listener) {
69 | mLoaderInstance.downloadImage(context, url, listener);
70 | }
71 |
72 | public void onDestroy() {
73 | mLoaderInstance.destroy();
74 | mLoaderInstance = null;
75 | }
76 |
77 | public static class Singleton {
78 | final static ImageLoaderManager instance = new ImageLoaderManager();
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/imageset/src/main/java/com/sxu/smartpicture/imageloader/WrapImageView.java:
--------------------------------------------------------------------------------
1 | package com.sxu.smartpicture.imageloader;
2 |
3 | import android.content.Context;
4 | import android.content.res.TypedArray;
5 | import android.graphics.Color;
6 | import android.graphics.Matrix;
7 | import android.support.annotation.DrawableRes;
8 | import android.util.AttributeSet;
9 |
10 | import com.facebook.drawee.view.GenericDraweeView;
11 | import com.sxu.smartpicture.R;
12 |
13 | /**
14 |
15 | * 类或接口的描述信息
16 | *
17 | * @author Freeman
18 | * @date 2017/12/5
19 | */
20 |
21 |
22 | public class WrapImageView extends GenericDraweeView {
23 |
24 | private int mPlaceHolder;
25 | private int mFailureHolder;
26 | private int mOverlayImageId;
27 | private int mShape;
28 | private int mRadius;
29 | private int mTopLeftRadius;
30 | private int mTopRightRadius;
31 | private int mBottomLeftRadius;
32 | private int mBottomRightRadius;
33 | private int mBorderWidth;
34 | private int mBorderColor;
35 | private int mBlurRadius;
36 | private boolean mIsBlur;
37 |
38 | public static final int SHAPE_NORMAL = 0;
39 | public static final int SHAPE_CIRCLE = 1;
40 | public static final int SHAPE_ROUND = 2;
41 |
42 | public WrapImageView(Context context) {
43 | this(context, null, 0);
44 | }
45 |
46 | public WrapImageView(Context context, AttributeSet attrs) {
47 | this(context, attrs, 0);
48 | }
49 |
50 | public WrapImageView(Context context, AttributeSet attrs, int theme) {
51 | super(context, attrs, theme);
52 | TypedArray arrays = context.obtainStyledAttributes(attrs, R.styleable.WrapImageView);
53 | mPlaceHolder = arrays.getResourceId(R.styleable.WrapImageView_placeHolder, 0);
54 | mFailureHolder = arrays.getResourceId(R.styleable.WrapImageView_failureHolder, 0);
55 | mOverlayImageId = arrays.getResourceId(R.styleable.WrapImageView_overlayImageId, 0);
56 | mShape = arrays.getInt(R.styleable.WrapImageView_shape, SHAPE_NORMAL);
57 | mRadius = arrays.getDimensionPixelSize(R.styleable.WrapImageView_radius, 0);
58 | mTopLeftRadius = arrays.getDimensionPixelSize(R.styleable.WrapImageView_topLeftRadius, 0);
59 | mTopRightRadius = arrays.getDimensionPixelSize(R.styleable.WrapImageView_topRightRadius, 0);
60 | mBottomLeftRadius = arrays.getDimensionPixelSize(R.styleable.WrapImageView_bottomLeftRadius, 0);
61 | mBottomRightRadius = arrays.getDimensionPixelSize(R.styleable.WrapImageView_bottomRightRadius, 0);
62 | mBorderWidth = arrays.getDimensionPixelSize(R.styleable.WrapImageView_shapeBorderWidth, 0);
63 | mBorderColor = arrays.getColor(R.styleable.WrapImageView_borderColor, Color.WHITE);
64 | mIsBlur = arrays.getBoolean(R.styleable.WrapImageView_isBlur, false);
65 | mBlurRadius = arrays.getInt(R.styleable.WrapImageView_blurRadius, 25);
66 | arrays.recycle();
67 | }
68 |
69 | public void setRadius(float radius) {
70 | this.mRadius = (int) radius;
71 | }
72 |
73 | public void setRadius(int[] radius) {
74 | if (radius != null && radius.length == 8) {
75 | mTopLeftRadius = radius[0] >= radius[1] ? radius[0] : radius[1];
76 | mTopRightRadius = radius[2] >= radius[3] ? radius[2] : radius[3];
77 | mBottomRightRadius = radius[4] >= radius[5] ? radius[4] : radius[5];
78 | mBottomLeftRadius = radius[6] >= radius[7] ? radius[6] : radius[7];
79 | }
80 | }
81 |
82 | public void setShape(int shape) {
83 | this.mShape = shape;
84 | }
85 |
86 | public void setBorderWidth(int width) {
87 | this.mBorderWidth = width;
88 | }
89 |
90 | public void setBorderColor(int color) {
91 | this.mBorderColor = color;
92 | }
93 |
94 | public void setPlaceHolder(int placeHolder) {
95 | this.mPlaceHolder = placeHolder;
96 | }
97 |
98 | public void setFailureHolder(int failureHolder) {
99 | this.mFailureHolder = failureHolder;
100 | }
101 |
102 | public void setOverlayImageId(@DrawableRes int overlayImageId) {
103 | this.mOverlayImageId = overlayImageId;
104 | }
105 |
106 | public void setBlur(boolean isBlur) {
107 | this.mIsBlur = isBlur;
108 | }
109 |
110 | public void setBlurRadius(int blurRadius) {
111 | this.mBlurRadius = blurRadius;
112 | }
113 |
114 | public int getPlaceHolder() {
115 | return mPlaceHolder;
116 | }
117 |
118 | public int getFailureHolder() {
119 | return mFailureHolder;
120 | }
121 |
122 | public int getOverlayImageId() {
123 | return mOverlayImageId;
124 | }
125 |
126 | public int getShape() {
127 | return mShape;
128 | }
129 |
130 | public float[] getRadii() {
131 | if (mTopLeftRadius != 0 || mTopRightRadius != 0 || mBottomRightRadius != 0 || mBottomLeftRadius != 0) {
132 | float[] radii = {mTopLeftRadius, mTopLeftRadius, mTopRightRadius, mTopRightRadius,
133 | mBottomRightRadius, mBottomRightRadius, mBottomLeftRadius, mBottomLeftRadius};
134 | return radii;
135 | }
136 |
137 | return null;
138 | }
139 |
140 | public int getRadius() {
141 | return mRadius;
142 | }
143 |
144 | public int getBorderWidth() {
145 | return mBorderWidth;
146 | }
147 |
148 | public int getBorderColor() {
149 | return mBorderColor;
150 | }
151 |
152 | public boolean isBlur() {
153 | return mIsBlur;
154 | }
155 |
156 | public int getBlurRadius() {
157 | return mBlurRadius;
158 | }
159 |
160 | public String getParams() {
161 | StringBuilder builder = new StringBuilder();
162 | builder.append(mIsBlur).append(mBlurRadius)
163 | .append(mShape).append(mRadius)
164 | .append(mBorderWidth).append(mBorderColor);
165 | return builder.toString();
166 | }
167 |
168 | /**
169 | * 解决共享动画无效的问题
170 | * @param matrix
171 | */
172 | public void animateTransform(Matrix matrix) {
173 | invalidate();
174 | }
175 | }
176 |
--------------------------------------------------------------------------------
/imageset/src/main/java/com/sxu/smartpicture/imageloader/instance/GlideInstance.java:
--------------------------------------------------------------------------------
1 | package com.sxu.smartpicture.imageloader.instance;
2 |
3 | import android.content.Context;
4 | import android.graphics.Bitmap;
5 | import android.graphics.drawable.BitmapDrawable;
6 | import android.graphics.drawable.Drawable;
7 | import android.support.annotation.Nullable;
8 |
9 | import com.bumptech.glide.Glide;
10 | import com.bumptech.glide.RequestBuilder;
11 | import com.bumptech.glide.RequestManager;
12 | import com.bumptech.glide.load.DataSource;
13 | import com.bumptech.glide.load.engine.GlideException;
14 | import com.bumptech.glide.request.RequestListener;
15 | import com.bumptech.glide.request.RequestOptions;
16 | import com.bumptech.glide.request.target.Target;
17 | import com.sxu.smartpicture.imageloader.WrapImageView;
18 | import com.sxu.smartpicture.imageloader.listener.ImageLoaderListener;
19 | import com.sxu.smartpicture.imageloader.transform.GlideBlurTransform;
20 | import com.sxu.smartpicture.imageloader.transform.GlideCircleBitmapTransform;
21 | import com.sxu.smartpicture.imageloader.transform.GlideRoundBitmapTransform;
22 | import com.sxu.smartpicture.imageloader.utils.DiskLruCacheManager;
23 |
24 |
25 | /*******************************************************************************
26 | * Description: Glide的封装类 【注意:Glide在加载图片时会自动将Image缩放到View的大小】
27 | *
28 | * Author: Freeman
29 | *
30 | * Date: 2018/12/17
31 | *
32 | * Copyright: all rights reserved by Freeman.
33 | *******************************************************************************/
34 |
35 | public class GlideInstance implements ImageLoaderInstance {
36 |
37 | private RequestManager requestManager;
38 |
39 | @Override
40 | public void init(Context context) {
41 | requestManager = Glide.with(context);
42 | }
43 |
44 | @Override
45 | public void displayImage(String url, WrapImageView imageView) {
46 | displayImage(url, imageView, null);
47 | }
48 |
49 | @Override
50 | public void displayImage(String url, WrapImageView imageView, int width, int height) {
51 | displayImage(url, imageView, width, height, null);
52 | }
53 |
54 | @Override
55 | public void displayImage(String url, WrapImageView imageView, ImageLoaderListener listener) {
56 | displayImage(url, imageView, 0, 0, listener);
57 | }
58 |
59 | @Override
60 | public void displayImage(String url, WrapImageView imageView, int width, int height, final ImageLoaderListener listener) {
61 | // 缓存的key
62 | Context context = imageView.getContext().getApplicationContext();
63 | String key = url + imageView.getParams();
64 | Bitmap bitmap = DiskLruCacheManager.getInstance(context).get(key);
65 | if (bitmap != null && !bitmap.isRecycled()) {
66 | imageView.setImageBitmap(bitmap);
67 | return;
68 | }
69 |
70 | RequestOptions options = new RequestOptions()
71 | .placeholder(imageView.getPlaceHolder())
72 | .error(imageView.getFailureHolder())
73 | .dontAnimate();
74 | // 根据imageView的形状,设置相应的transform
75 | boolean isBlur = imageView.isBlur();
76 | int shape = imageView.getShape();
77 | if (isBlur) {
78 | if (shape == WrapImageView.SHAPE_CIRCLE) {
79 | options.transforms(new GlideBlurTransform(context, key, imageView.getBlurRadius()),
80 | new GlideCircleBitmapTransform(context, key,imageView.getBorderWidth(),
81 | imageView.getBorderColor()));
82 | } else if (shape == WrapImageView.SHAPE_ROUND) {
83 | options.transforms(new GlideBlurTransform(context, key, imageView.getBlurRadius()),
84 | new GlideRoundBitmapTransform(context, key, imageView.getRadius(), imageView.getBorderWidth(),
85 | imageView.getBorderColor()));
86 | } else {
87 | options.transforms(new GlideBlurTransform(context, key, imageView.getBlurRadius()));
88 | }
89 | } else {
90 | if (shape == WrapImageView.SHAPE_CIRCLE) {
91 | options.transforms(new GlideCircleBitmapTransform(context, key,imageView.getBorderWidth(), imageView.getBorderColor()));
92 | } else if (shape == WrapImageView.SHAPE_ROUND) {
93 | options.transforms(new GlideRoundBitmapTransform(context, key,
94 | imageView.getRadius(), imageView.getBorderWidth(), imageView.getBorderColor()));
95 | }
96 | }
97 |
98 | RequestBuilder builder = requestManager.load(url).apply(options);
99 | if (listener != null) {
100 | builder.listener(new RequestListener() {
101 | @Override
102 | public boolean onLoadFailed(@Nullable GlideException e, Object model, Target target, boolean isFirstResource) {
103 | listener.onFailure(e);
104 | return false;
105 | }
106 |
107 | @Override
108 | public boolean onResourceReady(Object resource, Object model, Target target, DataSource dataSource, boolean isFirstResource) {
109 | if (resource instanceof BitmapDrawable) {
110 | listener.onCompleted(((BitmapDrawable) resource).getBitmap());
111 | }
112 | return false;
113 | }
114 | });
115 | }
116 | builder.into(imageView);
117 | }
118 |
119 | @Override
120 | public void downloadImage(Context context, String url, final ImageLoaderListener listener) {
121 | Glide.with(context.getApplicationContext())
122 | .load(url)
123 | .listener(new RequestListener() {
124 | @Override
125 | public boolean onLoadFailed(@Nullable GlideException e, Object model, Target target, boolean isFirstResource) {
126 | if (listener != null) {
127 | listener.onFailure(e);
128 | }
129 | return false;
130 | }
131 |
132 | @Override
133 | public boolean onResourceReady(Drawable resource, Object model, Target target, DataSource dataSource, boolean isFirstResource) {
134 | if (listener != null) {
135 | if (resource instanceof BitmapDrawable) {
136 | listener.onCompleted(((BitmapDrawable) resource).getBitmap());
137 | }
138 | }
139 | return false;
140 | }
141 | });
142 | }
143 |
144 | @Override
145 | public void destroy() {
146 | requestManager.onDestroy();
147 | requestManager = null;
148 | Glide.tearDown();
149 | }
150 | }
151 |
--------------------------------------------------------------------------------
/imageset/src/main/java/com/sxu/smartpicture/imageloader/instance/ImageLoaderInstance.java:
--------------------------------------------------------------------------------
1 | package com.sxu.smartpicture.imageloader.instance;
2 |
3 | import android.content.Context;
4 |
5 | import com.sxu.smartpicture.imageloader.WrapImageView;
6 | import com.sxu.smartpicture.imageloader.listener.ImageLoaderListener;
7 |
8 |
9 | /*******************************************************************************
10 | * Description: ImageLoader的接口
11 | *
12 | * Author: Freeman
13 | *
14 | * Date: 2018/12/17
15 | *
16 | * Copyright: all rights reserved by Freeman.
17 | *******************************************************************************/
18 |
19 | public interface ImageLoaderInstance {
20 |
21 | void init(Context context);
22 |
23 | void displayImage(String url, WrapImageView imageView);
24 |
25 | void displayImage(String url, WrapImageView imageView, int width, int height);
26 |
27 | void displayImage(String url, WrapImageView imageView, int width, int height, final ImageLoaderListener listener);
28 |
29 | void displayImage(String url, WrapImageView imageView, final ImageLoaderListener listener);
30 |
31 | void downloadImage(Context context, String url, ImageLoaderListener listener);
32 |
33 | void destroy();
34 | }
35 |
--------------------------------------------------------------------------------
/imageset/src/main/java/com/sxu/smartpicture/imageloader/instance/UILInstance.java:
--------------------------------------------------------------------------------
1 | package com.sxu.smartpicture.imageloader.instance;
2 |
3 | import android.content.Context;
4 | import android.graphics.Bitmap;
5 | import android.view.View;
6 |
7 | import com.nostra13.universalimageloader.cache.disc.naming.Md5FileNameGenerator;
8 | import com.nostra13.universalimageloader.core.DisplayImageOptions;
9 | import com.nostra13.universalimageloader.core.ImageLoader;
10 | import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
11 | import com.nostra13.universalimageloader.core.assist.FailReason;
12 | import com.nostra13.universalimageloader.core.assist.ImageScaleType;
13 | import com.nostra13.universalimageloader.core.assist.ImageSize;
14 | import com.nostra13.universalimageloader.core.assist.QueueProcessingType;
15 | import com.nostra13.universalimageloader.core.display.CircleBitmapDisplayer;
16 | import com.nostra13.universalimageloader.core.display.RoundedBitmapDisplayer;
17 | import com.nostra13.universalimageloader.core.download.BaseImageDownloader;
18 | import com.nostra13.universalimageloader.core.imageaware.ImageAware;
19 | import com.nostra13.universalimageloader.core.imageaware.ImageViewAware;
20 | import com.nostra13.universalimageloader.core.listener.ImageLoadingListener;
21 | import com.nostra13.universalimageloader.core.process.BitmapProcessor;
22 | import com.sxu.smartpicture.imageloader.WrapImageView;
23 | import com.sxu.smartpicture.imageloader.listener.ImageLoaderListener;
24 | import com.sxu.smartpicture.imageloader.utils.FastBlurUtil;
25 |
26 | /*******************************************************************************
27 | * Description: Universal ImageLoader封装类
28 | *
29 | * Author: Freeman
30 | *
31 | * Date: 2018/12/17
32 | *
33 | * Copyright: all rights reserved by Freeman.
34 | *******************************************************************************/
35 | public class UILInstance implements ImageLoaderInstance {
36 |
37 | private DisplayImageOptions options;
38 |
39 | private void initOptions(final WrapImageView imageView) {
40 | DisplayImageOptions.Builder builder = new DisplayImageOptions.Builder()
41 | .showImageOnLoading(imageView.getPlaceHolder())
42 | .showImageForEmptyUri(imageView.getPlaceHolder())
43 | .showImageOnFail(imageView.getFailureHolder())
44 | .cacheInMemory(true)
45 | .cacheOnDisk(true)
46 | .imageScaleType(ImageScaleType.IN_SAMPLE_INT)
47 | .bitmapConfig(Bitmap.Config.RGB_565)
48 | .considerExifParams(true)
49 | .preProcessor(!imageView.isBlur() ? null : new BitmapProcessor() {
50 | @Override
51 | public Bitmap process(Bitmap bitmap) {
52 | return FastBlurUtil.doBlur(bitmap, 2, imageView.getBlurRadius() * 4);
53 | }
54 | });
55 | int shape = imageView.getShape();
56 | if (shape == WrapImageView.SHAPE_CIRCLE) {
57 | builder.displayer(new CircleBitmapDisplayer(imageView.getBorderColor(), imageView.getBorderWidth()));
58 | } else if (shape == WrapImageView.SHAPE_ROUND) {
59 | builder.displayer(new RoundedBitmapDisplayer(imageView.getRadius()));
60 | }
61 | options = builder.build();
62 | }
63 |
64 | @Override
65 | public void init(Context context) {
66 | int memCacheSize = (int) Math.min(Runtime.getRuntime().maxMemory() / 8, 64 * 1024 * 1024);
67 | ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(context.getApplicationContext())
68 | .denyCacheImageMultipleSizesInMemory()
69 | .memoryCacheSize(memCacheSize)
70 | .diskCacheFileNameGenerator(new Md5FileNameGenerator())
71 | .threadPriority(10)
72 | .tasksProcessingOrder(QueueProcessingType.LIFO)
73 | .diskCacheFileCount(Integer.MAX_VALUE)
74 | .imageDownloader(new BaseImageDownloader(context, 5 * 1000, 5 * 1000))
75 | .writeDebugLogs()
76 | .build();
77 | ImageLoader.getInstance().init(config);
78 | }
79 |
80 | @Override
81 | public void displayImage(String url, WrapImageView imageView) {
82 | displayImage(url, imageView, 0, 0, null);
83 | }
84 |
85 | @Override
86 | public void displayImage(String url, WrapImageView imageView, int width, int height) {
87 | displayImage(url, imageView, width, height, null);
88 | }
89 |
90 | @Override
91 | public void displayImage(String url, WrapImageView imageView, ImageLoaderListener listener) {
92 | displayImage(url, imageView, 0, 0, listener);
93 | }
94 |
95 | @Override
96 | public void displayImage(String url, WrapImageView imageView, int width, int height, final ImageLoaderListener listener) {
97 | initOptions(imageView);
98 | ImageSize imageSize = null;
99 | if (width > 0 && height > 0) {
100 | imageSize = new ImageSize(width, height);
101 | }
102 | ImageLoader.getInstance().displayImage(url, new ImageViewAware(imageView), options, imageSize, new ImageLoadingListener() {
103 | @Override
104 | public void onLoadingStarted(String imageUri, View view) {
105 | if (listener != null) {
106 | listener.onStart();
107 | }
108 | }
109 |
110 | @Override
111 | public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
112 | if (listener != null) {
113 | listener.onFailure(new Exception(failReason.getCause()));
114 | }
115 | }
116 |
117 | @Override
118 | public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
119 | if (listener != null) {
120 | listener.onCompleted(loadedImage);
121 | }
122 | }
123 |
124 | @Override
125 | public void onLoadingCancelled(String imageUri, View view) {
126 | if (listener != null) {
127 | listener.onFailure(new Exception("task is cancelled"));
128 | }
129 | }
130 | }, null);
131 | }
132 |
133 | @Override
134 | public void downloadImage(Context context, String url, final ImageLoaderListener listener) {
135 | ImageLoader.getInstance().loadImage(url, new ImageLoadingListener() {
136 | @Override
137 | public void onLoadingStarted(String imageUri, View view) {
138 | if (listener != null) {
139 | listener.onStart();
140 | }
141 | }
142 |
143 | @Override
144 | public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
145 | if (listener != null) {
146 | listener.onFailure(new Exception(failReason.getCause()));
147 | }
148 | }
149 |
150 | @Override
151 | public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
152 | if (listener != null) {
153 | listener.onCompleted(loadedImage);
154 | }
155 | }
156 |
157 | @Override
158 | public void onLoadingCancelled(String imageUri, View view) {
159 | if (listener != null) {
160 | listener.onFailure(new Exception("task is cancelled"));
161 | }
162 | }
163 | });
164 | }
165 |
166 | @Override
167 | public void destroy() {
168 | if (ImageLoader.getInstance().isInited()) {
169 | ImageLoader.getInstance().clearMemoryCache();
170 | ImageLoader.getInstance().destroy();
171 | }
172 | }
173 | }
174 |
--------------------------------------------------------------------------------
/imageset/src/main/java/com/sxu/smartpicture/imageloader/listener/ImageLoaderListener.java:
--------------------------------------------------------------------------------
1 | package com.sxu.smartpicture.imageloader.listener;
2 |
3 | import android.graphics.Bitmap;
4 |
5 | /**
6 |
7 | * 图片加载监听
8 | *
9 | * @author Freeman
10 | * @date 2017/12/5
11 | */
12 |
13 |
14 | public interface ImageLoaderListener {
15 |
16 | void onStart();
17 |
18 | void onProcess(int completedSize, int totalSize);
19 |
20 | void onCompleted(Bitmap bitmap);
21 |
22 | void onFailure(Exception e);
23 | }
24 |
--------------------------------------------------------------------------------
/imageset/src/main/java/com/sxu/smartpicture/imageloader/listener/SimpleImageLoaderListener.java:
--------------------------------------------------------------------------------
1 | package com.sxu.smartpicture.imageloader.listener;
2 |
3 | import android.graphics.Bitmap;
4 |
5 | /**
6 |
7 | * 图片加载监听
8 | *
9 | * @author Freeman
10 | * @date 2017/12/5
11 | */
12 |
13 |
14 | public abstract class SimpleImageLoaderListener implements ImageLoaderListener {
15 |
16 | @Override
17 | public void onStart() {
18 |
19 | }
20 |
21 | @Override
22 | public void onProcess(int completedSize, int totalSize) {
23 |
24 | }
25 |
26 | @Override
27 | public void onCompleted(Bitmap bitmap) {
28 |
29 | }
30 |
31 | @Override
32 | public void onFailure(Exception e) {
33 |
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/imageset/src/main/java/com/sxu/smartpicture/imageloader/transform/GlideBlurTransform.java:
--------------------------------------------------------------------------------
1 | package com.sxu.smartpicture.imageloader.transform;
2 |
3 | import android.content.Context;
4 | import android.graphics.Bitmap;
5 | import android.support.annotation.NonNull;
6 |
7 | import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool;
8 | import com.bumptech.glide.load.resource.bitmap.BitmapTransformation;
9 | import com.sxu.smartpicture.imageloader.utils.DiskLruCacheManager;
10 | import com.sxu.smartpicture.imageloader.utils.FastBlurUtil;
11 |
12 | import java.security.MessageDigest;
13 |
14 | /**
15 |
16 | * 类或接口的描述信息
17 | *
18 | * @author Freeman
19 | * @date 2017/12/19
20 | */
21 |
22 |
23 | public class GlideBlurTransform extends BitmapTransformation {
24 |
25 | private String key;
26 | private Context context;
27 | private int blurRadius;
28 |
29 | public GlideBlurTransform(Context context, String key, int blurRadius) {
30 | this.context = context;
31 | this.key = key;
32 | this.blurRadius = blurRadius;
33 | }
34 |
35 | @Override
36 | protected Bitmap transform(@NonNull BitmapPool pool, @NonNull Bitmap toTransform, int outWidth, int outHeight) {
37 | Bitmap bitmap = FastBlurUtil.doBlur(toTransform, 8, blurRadius);
38 | // 缓存高斯模糊图片
39 | DiskLruCacheManager.getInstance(context).put(key, bitmap);
40 | return bitmap;
41 | }
42 |
43 | @Override
44 | public void updateDiskCacheKey(MessageDigest messageDigest) {
45 |
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/imageset/src/main/java/com/sxu/smartpicture/imageloader/transform/GlideCircleBitmapTransform.java:
--------------------------------------------------------------------------------
1 | package com.sxu.smartpicture.imageloader.transform;
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.support.annotation.NonNull;
9 |
10 | import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool;
11 | import com.bumptech.glide.load.resource.bitmap.BitmapTransformation;
12 | import com.sxu.smartpicture.imageloader.utils.DiskLruCacheManager;
13 |
14 | import java.security.MessageDigest;
15 |
16 | /**
17 |
18 | * 类或接口的描述信息
19 | *
20 | * @author Freeman
21 | * @date 2017/12/19
22 | */
23 |
24 |
25 | public class GlideCircleBitmapTransform extends BitmapTransformation {
26 |
27 | private int mBorderWidth;
28 | private int mBorderColor;
29 | private String mKey;
30 | private Context mContext;
31 |
32 | public GlideCircleBitmapTransform(Context context, String key, int borderWidth, int borderColor) {
33 | this.mContext = context;
34 | this.mKey = key;
35 | this.mBorderWidth = borderWidth;
36 | this.mBorderColor = borderColor;
37 | }
38 |
39 | @Override
40 | protected Bitmap transform(@NonNull BitmapPool pool, @NonNull Bitmap toTransform, int outWidth, int outHeight) {
41 | int size = Math.min(toTransform.getWidth(), toTransform.getHeight());
42 | int x = (toTransform.getWidth() - size) / 2 + mBorderWidth;
43 | int y = (toTransform.getHeight() - size) / 2 + mBorderWidth;
44 | int newSize = size - mBorderWidth * 2;
45 | int radius = newSize / 2;
46 | Bitmap bitmap = Bitmap.createBitmap(toTransform, x, y, newSize, newSize);
47 | Bitmap result = pool.get(newSize, newSize, toTransform.getConfig());
48 | if (result == null) {
49 | result = Bitmap.createBitmap(newSize, newSize, toTransform.getConfig());
50 | }
51 |
52 | Canvas canvas = new Canvas(result);
53 | if (mBorderWidth > 0) {
54 | Paint borderPaint = new Paint();
55 | borderPaint.setStyle(Paint.Style.STROKE);
56 | borderPaint.setStrokeWidth(mBorderWidth);
57 | borderPaint.setColor(mBorderColor);
58 | borderPaint.setAntiAlias(true);
59 | canvas.drawCircle(radius, radius, radius - mBorderWidth/2, borderPaint);
60 | }
61 | Paint paint = new Paint();
62 | paint.setShader(new BitmapShader(bitmap, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP));
63 | paint.setAntiAlias(true);
64 | canvas.drawCircle(radius, radius, radius - mBorderWidth, paint);
65 |
66 | DiskLruCacheManager.getInstance(mContext).put(mKey, result);
67 |
68 | return result;
69 | }
70 |
71 | @Override
72 | public void updateDiskCacheKey(MessageDigest messageDigest) {
73 |
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/imageset/src/main/java/com/sxu/smartpicture/imageloader/transform/GlideRoundBitmapTransform.java:
--------------------------------------------------------------------------------
1 | package com.sxu.smartpicture.imageloader.transform;
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.sxu.smartpicture.imageloader.utils.DiskLruCacheManager;
14 |
15 | import java.security.MessageDigest;
16 |
17 | /**
18 |
19 | * 类或接口的描述信息
20 | *
21 | * @author Freeman
22 | * @date 2017/12/19
23 | */
24 |
25 |
26 | public class GlideRoundBitmapTransform extends BitmapTransformation {
27 |
28 | private int mRadius;
29 | private int mBorderWidth;
30 | private int mBorderColor;
31 | private String mKey;
32 | private Context mContext;
33 |
34 | public GlideRoundBitmapTransform(Context context, String key, int radius, int borderWidth, int borderColor) {
35 | this.mContext = context;
36 | this.mKey = key;
37 | this.mRadius = radius;
38 | this.mBorderWidth = borderWidth;
39 | this.mBorderColor = borderColor;
40 | }
41 |
42 | @Override
43 | protected Bitmap transform(@NonNull BitmapPool pool, @NonNull Bitmap toTransform, int outWidth, int outHeight) {
44 | if (mRadius == 0 && mBorderWidth == 0) {
45 | return toTransform;
46 | }
47 | int width = toTransform.getWidth();
48 | int height = toTransform.getHeight();
49 | RectF rectF = new RectF(mBorderWidth, mBorderWidth, width - mBorderWidth, height - mBorderWidth);
50 | Bitmap result = pool.get(width, height, toTransform.getConfig());
51 | if (result == null) {
52 | result = toTransform.copy(toTransform.getConfig(), true);
53 | }
54 | Canvas canvas = new Canvas(result);
55 | Paint paint = new Paint();
56 | paint.setShader(new BitmapShader(toTransform, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP ));
57 | paint.setAntiAlias(true);
58 | canvas.drawRoundRect(rectF, mRadius, mRadius, paint);
59 | if (mBorderWidth > 0) {
60 | Paint borderPaint = new Paint();
61 | borderPaint.setStyle(Paint.Style.STROKE);
62 | borderPaint.setStrokeWidth(mBorderWidth);
63 | borderPaint.setColor(mBorderColor);
64 | borderPaint.setAntiAlias(true);
65 | canvas.drawRoundRect(rectF, mRadius, mRadius, borderPaint);
66 | }
67 | DiskLruCacheManager.getInstance(mContext).put(mKey, result);
68 |
69 | return result;
70 | }
71 |
72 | @Override
73 | public void updateDiskCacheKey(MessageDigest messageDigest) {
74 |
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/imageset/src/main/java/com/sxu/smartpicture/imageloader/utils/DiskLruCacheManager.java:
--------------------------------------------------------------------------------
1 | package com.sxu.smartpicture.imageloader.utils;
2 |
3 | import android.content.Context;
4 | import android.graphics.Bitmap;
5 | import android.graphics.BitmapFactory;
6 | import android.text.TextUtils;
7 |
8 | import java.io.InputStream;
9 | import java.io.OutputStream;
10 | import java.math.BigInteger;
11 | import java.security.MessageDigest;
12 |
13 | /*******************************************************************************
14 | * Description: 用于缓存经过高斯模糊的图片
15 | *
16 | * Author: Freeman
17 | *
18 | * Date: 2018/9/4
19 | *
20 | * Copyright: all rights reserved by Freeman.
21 | *******************************************************************************/
22 | public class DiskLruCacheManager {
23 |
24 | private DiskLruCache diskLruCache;
25 | private static DiskLruCacheManager instance;
26 |
27 | private final int MAX_CACHE_SIZE = 64 * 1024 * 1024;
28 |
29 | private DiskLruCacheManager(Context context) {
30 | try {
31 | diskLruCache = DiskLruCache.open(context.getCacheDir(), 1, 1,
32 | MAX_CACHE_SIZE, Integer.MAX_VALUE);
33 | } catch (Exception e) {
34 | e.printStackTrace(System.err);
35 | }
36 | }
37 |
38 | public static DiskLruCacheManager getInstance(Context context) {
39 | if (instance == null) {
40 | synchronized (DiskLruCacheManager.class) {
41 | if (instance == null) {
42 | instance = new DiskLruCacheManager(context.getApplicationContext());
43 | }
44 | }
45 | }
46 |
47 | return instance;
48 | }
49 |
50 | public void put(String url, Bitmap bitmap) {
51 | if (TextUtils.isEmpty(url) || bitmap == null || bitmap.isRecycled()) {
52 | return;
53 | }
54 |
55 | try {
56 | DiskLruCache.Editor editor = diskLruCache.edit(getKey(url));
57 | OutputStream outputStream = editor.newOutputStream(0);
58 | if (bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream)) {
59 | editor.commit();
60 | }
61 | diskLruCache.flush();
62 | } catch (Exception e) {
63 | e.printStackTrace(System.err);
64 | }
65 | }
66 |
67 | public Bitmap get(String url) {
68 | try {
69 | DiskLruCache.Snapshot snapshot = diskLruCache.get(getKey(url));
70 | if (snapshot != null) {
71 | InputStream inputStream = snapshot.getInputStream(0);
72 | return BitmapFactory.decodeStream(inputStream);
73 | }
74 | } catch (Exception e) {
75 | e.printStackTrace(System.err);
76 | }
77 |
78 | return null;
79 | }
80 |
81 | public static String getKey(String url) {
82 | try {
83 | MessageDigest digest = MessageDigest.getInstance("MD5");
84 | byte[] md5 = digest.digest(url.getBytes());
85 | BigInteger bigInteger = new BigInteger(1, md5);
86 | return bigInteger.toString(16);
87 | } catch (Exception e) {
88 | e.printStackTrace(System.err);
89 | }
90 |
91 | return null;
92 | }
93 |
94 | public void close() {
95 | try {
96 | diskLruCache.close();
97 | } catch (Exception e) {
98 | e.printStackTrace(System.err);
99 | }
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/imageset/src/main/java/com/sxu/smartpicture/imageloader/utils/StrictLineReader.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2012 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.sxu.smartpicture.imageloader.utils;
17 |
18 | import java.io.ByteArrayOutputStream;
19 | import java.io.Closeable;
20 | import java.io.EOFException;
21 | import java.io.IOException;
22 | import java.io.InputStream;
23 | import java.io.UnsupportedEncodingException;
24 | import java.nio.charset.Charset;
25 |
26 | /**
27 | * Buffers input from an {@link InputStream} for reading lines.
28 | *
29 | * This class is used for buffered reading of lines. For purposes of this class, a line ends
30 | * with "\n" or "\r\n". End of input is reported by throwing {@code EOFException}. Unterminated
31 | * line at end of input is invalid and will be ignored, the caller may use {@code
32 | * hasUnterminatedLine()} to detect it after catching the {@code EOFException}.
33 | *
34 | *
This class is intended for reading input that strictly consists of lines, such as line-based
35 | * cache entries or cache journal. Unlike the {@link java.io.BufferedReader} which in conjunction
36 | * with {@link java.io.InputStreamReader} provides similar functionality, this class uses different
37 | * end-of-input reporting and a more restrictive definition of a line.
38 | *
39 | *
This class supports only charsets that encode '\r' and '\n' as a single byte with value 13
40 | * and 10, respectively, and the representation of no other character contains these values.
41 | * We currently check in constructor that the charset is one of US-ASCII, UTF-8 and ISO-8859-1.
42 | * The default charset is US_ASCII.
43 | */
44 | class StrictLineReader implements Closeable {
45 | private static final byte CR = (byte) '\r';
46 | private static final byte LF = (byte) '\n';
47 |
48 | private final InputStream in;
49 | private final Charset charset;
50 |
51 | /*
52 | * Buffered data is stored in {@code buf}. As long as no exception occurs, 0 <= pos <= end
53 | * and the data in the range [pos, end) is buffered for reading. At end of input, if there is
54 | * an unterminated line, we set end == -1, otherwise end == pos. If the underlying
55 | * {@code InputStream} throws an {@code IOException}, end may remain as either pos or -1.
56 | */
57 | private byte[] buf;
58 | private int pos;
59 | private int end;
60 |
61 | /**
62 | * Constructs a new {@code LineReader} with the specified charset and the default capacity.
63 | *
64 | * @param in the {@code InputStream} to read data from.
65 | * @param charset the charset used to decode data. Only US-ASCII, UTF-8 and ISO-8859-1 are
66 | * supported.
67 | * @throws NullPointerException if {@code in} or {@code charset} is null.
68 | * @throws IllegalArgumentException if the specified charset is not supported.
69 | */
70 | public StrictLineReader(InputStream in, Charset charset) {
71 | this(in, 8192, charset);
72 | }
73 |
74 | /**
75 | * Constructs a new {@code LineReader} with the specified capacity and charset.
76 | *
77 | * @param in the {@code InputStream} to read data from.
78 | * @param capacity the capacity of the buffer.
79 | * @param charset the charset used to decode data. Only US-ASCII, UTF-8 and ISO-8859-1 are
80 | * supported.
81 | * @throws NullPointerException if {@code in} or {@code charset} is null.
82 | * @throws IllegalArgumentException if {@code capacity} is negative or zero
83 | * or the specified charset is not supported.
84 | */
85 | public StrictLineReader(InputStream in, int capacity, Charset charset) {
86 | if (in == null || charset == null) {
87 | throw new NullPointerException();
88 | }
89 | if (capacity < 0) {
90 | throw new IllegalArgumentException("capacity <= 0");
91 | }
92 | if (!(charset.equals(Util.US_ASCII))) {
93 | throw new IllegalArgumentException("Unsupported encoding");
94 | }
95 |
96 | this.in = in;
97 | this.charset = charset;
98 | buf = new byte[capacity];
99 | }
100 |
101 | /**
102 | * Closes the reader by closing the underlying {@code InputStream} and
103 | * marking this reader as closed.
104 | *
105 | * @throws IOException for errors when closing the underlying {@code InputStream}.
106 | */
107 | public void close() throws IOException {
108 | synchronized (in) {
109 | if (buf != null) {
110 | buf = null;
111 | in.close();
112 | }
113 | }
114 | }
115 |
116 | /**
117 | * Reads the next line. A line ends with {@code "\n"} or {@code "\r\n"},
118 | * this end of line marker is not included in the result.
119 | *
120 | * @return the next line from the input.
121 | * @throws IOException for underlying {@code InputStream} errors.
122 | * @throws EOFException for the end of source stream.
123 | */
124 | public String readLine() throws IOException {
125 | synchronized (in) {
126 | if (buf == null) {
127 | throw new IOException("LineReader is closed");
128 | }
129 |
130 | // Read more data if we are at the end of the buffered data.
131 | // Though it's an error to read after an exception, we will let {@code fillBuf()}
132 | // throw again if that happens; thus we need to handle end == -1 as well as end == pos.
133 | if (pos >= end) {
134 | fillBuf();
135 | }
136 | // Try to find LF in the buffered data and return the line if successful.
137 | for (int i = pos; i != end; ++i) {
138 | if (buf[i] == LF) {
139 | int lineEnd = (i != pos && buf[i - 1] == CR) ? i - 1 : i;
140 | String res = new String(buf, pos, lineEnd - pos, charset.name());
141 | pos = i + 1;
142 | return res;
143 | }
144 | }
145 |
146 | // Let's anticipate up to 80 characters on top of those already read.
147 | ByteArrayOutputStream out = new ByteArrayOutputStream(end - pos + 80) {
148 | @Override
149 | public String toString() {
150 | int length = (count > 0 && buf[count - 1] == CR) ? count - 1 : count;
151 | try {
152 | return new String(buf, 0, length, charset.name());
153 | } catch (UnsupportedEncodingException e) {
154 | throw new AssertionError(e); // Since we control the charset this will never happen.
155 | }
156 | }
157 | };
158 |
159 | while (true) {
160 | out.write(buf, pos, end - pos);
161 | // Mark unterminated line in case fillBuf throws EOFException or IOException.
162 | end = -1;
163 | fillBuf();
164 | // Try to find LF in the buffered data and return the line if successful.
165 | for (int i = pos; i != end; ++i) {
166 | if (buf[i] == LF) {
167 | if (i != pos) {
168 | out.write(buf, pos, i - pos);
169 | }
170 | pos = i + 1;
171 | return out.toString();
172 | }
173 | }
174 | }
175 | }
176 | }
177 |
178 | /**
179 | * Reads new input data into the buffer. Call only with pos == end or end == -1,
180 | * depending on the desired outcome if the function throws.
181 | */
182 | private void fillBuf() throws IOException {
183 | int result = in.read(buf, 0, buf.length);
184 | if (result == -1) {
185 | throw new EOFException();
186 | }
187 | pos = 0;
188 | end = result;
189 | }
190 | }
191 |
192 |
--------------------------------------------------------------------------------
/imageset/src/main/java/com/sxu/smartpicture/imageloader/utils/Util.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2010 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.sxu.smartpicture.imageloader.utils;
17 |
18 | import java.io.Closeable;
19 | import java.io.File;
20 | import java.io.IOException;
21 | import java.io.Reader;
22 | import java.io.StringWriter;
23 | import java.nio.charset.Charset;
24 |
25 | /** Junk drawer of utility methods. */
26 | final class Util {
27 | static final Charset US_ASCII = Charset.forName("US-ASCII");
28 | static final Charset UTF_8 = Charset.forName("UTF-8");
29 |
30 | private Util() {
31 | }
32 |
33 | static String readFully(Reader reader) throws IOException {
34 | try {
35 | StringWriter writer = new StringWriter();
36 | char[] buffer = new char[1024];
37 | int count;
38 | while ((count = reader.read(buffer)) != -1) {
39 | writer.write(buffer, 0, count);
40 | }
41 | return writer.toString();
42 | } finally {
43 | reader.close();
44 | }
45 | }
46 |
47 | /**
48 | * Deletes the contents of {@code dir}. Throws an IOException if any file
49 | * could not be deleted, or if {@code dir} is not a readable directory.
50 | */
51 | static void deleteContents(File dir) throws IOException {
52 | File[] files = dir.listFiles();
53 | if (files == null) {
54 | throw new IOException("not a readable directory: " + dir);
55 | }
56 | for (File file : files) {
57 | if (file.isDirectory()) {
58 | deleteContents(file);
59 | }
60 | if (!file.delete()) {
61 | throw new IOException("failed to delete file: " + file);
62 | }
63 | }
64 | }
65 |
66 | static void closeQuietly(/*Auto*/Closeable closeable) {
67 | if (closeable != null) {
68 | try {
69 | closeable.close();
70 | } catch (RuntimeException rethrown) {
71 | throw rethrown;
72 | } catch (Exception ignored) {
73 | }
74 | }
75 | }
76 | }
--------------------------------------------------------------------------------
/imageset/src/main/java/com/sxu/smartpicture/manager/ThreadPoolManager.java:
--------------------------------------------------------------------------------
1 | package com.sxu.smartpicture.manager;
2 |
3 | import android.os.Process;
4 |
5 | import java.util.concurrent.Executor;
6 | import java.util.concurrent.LinkedBlockingQueue;
7 | import java.util.concurrent.ThreadFactory;
8 | import java.util.concurrent.ThreadPoolExecutor;
9 | import java.util.concurrent.TimeUnit;
10 | import java.util.concurrent.atomic.AtomicInteger;
11 |
12 | /*******************************************************************************
13 | * Description: 自定义线程池
14 | *
15 | * Author: Freeman
16 | *
17 | * Date: 2017/11/08
18 | *
19 | * Copyright: all rights reserved by Freeman.
20 | *******************************************************************************/
21 | public class ThreadPoolManager {
22 |
23 | private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
24 | private static final int DEFAULT_QUEUE_SIZE = 128;
25 |
26 | private static int coreThreadCount = CPU_COUNT + 1;
27 | private static int maxThreadCount = CPU_COUNT * 2 + 1;
28 | private static int threadPriority = Process.THREAD_PRIORITY_BACKGROUND;
29 | private static Executor executor;
30 |
31 | static {
32 | init(coreThreadCount, threadPriority);
33 | }
34 |
35 | public static void init(int _coreThreadCount) {
36 | init(_coreThreadCount, threadPriority);
37 | }
38 |
39 | public static void init(int _coreThreadCount, int _threadPriority) {
40 | if (executor == null) {
41 | if (_coreThreadCount < 0 || _coreThreadCount > Integer.MAX_VALUE) {
42 | throw new IllegalStateException();
43 | }
44 | coreThreadCount = _coreThreadCount;
45 | threadPriority = _threadPriority;
46 | LinkedBlockingQueue workQueue = new LinkedBlockingQueue(DEFAULT_QUEUE_SIZE);
47 | executor = new ThreadPoolExecutor(coreThreadCount, maxThreadCount, 30L, TimeUnit.SECONDS,
48 | workQueue, new DefaultThreadFactory(threadPriority));
49 | }
50 | }
51 |
52 | private static class DefaultThreadFactory implements ThreadFactory {
53 | private AtomicInteger threadId = new AtomicInteger(1);
54 | private int threadPriority;
55 | private String threadNamePrefix;
56 | private ThreadGroup threadGroup;
57 |
58 | DefaultThreadFactory(int threadPriority) {
59 | this.threadPriority = threadPriority;
60 | this.threadNamePrefix = "thread-";
61 | this.threadGroup = Thread.currentThread().getThreadGroup();
62 | }
63 |
64 | @Override
65 | public Thread newThread(Runnable r) {
66 | Thread thread = new Thread(threadGroup, r, threadNamePrefix + threadId.getAndIncrement());
67 | if (thread.isDaemon()) {
68 | thread.setDaemon(false);
69 | }
70 | thread.setPriority(threadPriority);
71 |
72 | return thread;
73 | }
74 | }
75 |
76 | public static void executeTask(Runnable task) {
77 | if (executor == null) {
78 | throw new IllegalStateException();
79 | } else {
80 | executor.execute(task);
81 | }
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/imageset/src/main/java/com/sxu/smartpicture/utils/DisplayUtil.java:
--------------------------------------------------------------------------------
1 | package com.sxu.smartpicture.utils;
2 |
3 | import android.app.Activity;
4 | import android.content.Context;
5 | import android.content.res.Resources;
6 | import android.graphics.Rect;
7 |
8 | /*******************************************************************************
9 | * Description: 屏幕相关的工具类
10 | *
11 | * Author: Freeman
12 | *
13 | * Date: 2017/06/20
14 | *
15 | * Copyright: all rights reserved by Freeman.
16 | *******************************************************************************/
17 | public class DisplayUtil {
18 |
19 | public static int getScreenWidth() {
20 | return Resources.getSystem().getDisplayMetrics().widthPixels;
21 | }
22 |
23 | public static int getScreenHeight() {
24 | return Resources.getSystem().getDisplayMetrics().heightPixels;
25 | }
26 |
27 | public static float getScreenDensity() {
28 | return Resources.getSystem().getDisplayMetrics().density;
29 | }
30 |
31 | public static int dpToPx(int dp) {
32 | return Math.round(Resources.getSystem().getDisplayMetrics().density * dp + 0.5f);
33 | }
34 |
35 | public static int pxToDp(int px) {
36 | return Math.round(px / Resources.getSystem().getDisplayMetrics().density + 0.5f);
37 | }
38 |
39 | public static int getStatusHeight(Context context) {
40 | Rect rect = new Rect();
41 | ((Activity)context).getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);
42 | return rect.top;
43 | }
44 |
45 | public static String getScreenParams(Context context) {
46 | return getScreenWidth() + "*" + getScreenHeight();
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/imageset/src/main/java/com/sxu/smartpicture/zoomimage/FrescoAttacher.java:
--------------------------------------------------------------------------------
1 | package com.sxu.smartpicture.zoomimage;
2 |
3 | import android.graphics.Matrix;
4 | import android.graphics.RectF;
5 |
6 | import com.facebook.drawee.view.GenericDraweeView;
7 | import com.github.chrisbanes.photoview.PhotoViewAttacher;
8 |
9 | /*******************************************************************************
10 | * Description: 适配Fresco的Attacher
11 | *
12 | * Author: Freeman
13 | *
14 | * Date: 2018/9/12
15 | *
16 | * Copyright: all rights reserved by Freeman.
17 | *******************************************************************************/
18 | public class FrescoAttacher extends PhotoViewAttacher {
19 |
20 | private GenericDraweeView imageView;
21 |
22 | public FrescoAttacher(GenericDraweeView image) {
23 | super(image);
24 | this.imageView = image;
25 | }
26 |
27 | @Override
28 | protected RectF getDisplayRect(Matrix matrix) {
29 | RectF displayRect = new RectF();
30 | imageView.getHierarchy().getActualImageBounds(displayRect);
31 | matrix.mapRect(displayRect);
32 | return displayRect;
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/imageset/src/main/res/drawable-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Liberuman/ImageSet/233f3361d2ddd515af91f297288a9818542caa90/imageset/src/main/res/drawable-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/imageset/src/main/res/drawable-xxhdpi/photo_selected_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Liberuman/ImageSet/233f3361d2ddd515af91f297288a9818542caa90/imageset/src/main/res/drawable-xxhdpi/photo_selected_icon.png
--------------------------------------------------------------------------------
/imageset/src/main/res/drawable-xxhdpi/photo_unselected_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Liberuman/ImageSet/233f3361d2ddd515af91f297288a9818542caa90/imageset/src/main/res/drawable-xxhdpi/photo_unselected_icon.png
--------------------------------------------------------------------------------
/imageset/src/main/res/drawable-xxhdpi/return_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Liberuman/ImageSet/233f3361d2ddd515af91f297288a9818542caa90/imageset/src/main/res/drawable-xxhdpi/return_icon.png
--------------------------------------------------------------------------------
/imageset/src/main/res/drawable/common_line_e4.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/imageset/src/main/res/drawable/default_placeholder_image.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/imageset/src/main/res/drawable/place_checkbox_bg.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/imageset/src/main/res/layout/activity_choose_photo_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
8 |
15 |
23 |
35 |
44 |
45 |
50 |
58 |
63 |
73 |
74 |
--------------------------------------------------------------------------------
/imageset/src/main/res/layout/activity_photo_preview_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
10 |
11 |
15 |
22 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/imageset/src/main/res/layout/dialog_common_choose_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
15 |
21 |
25 |
33 |
34 |
--------------------------------------------------------------------------------
/imageset/src/main/res/layout/fragment_photo_grid_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
18 |
24 |
28 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/imageset/src/main/res/layout/fragment_photo_list_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/imageset/src/main/res/layout/fragment_photo_preview_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
--------------------------------------------------------------------------------
/imageset/src/main/res/layout/fragment_test_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
12 |
--------------------------------------------------------------------------------
/imageset/src/main/res/layout/item_photo_grid_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
12 |
23 |
--------------------------------------------------------------------------------
/imageset/src/main/res/layout/item_photo_list_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
14 |
27 |
39 |
46 |
47 |
--------------------------------------------------------------------------------
/imageset/src/main/res/values-v21/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
--------------------------------------------------------------------------------
/imageset/src/main/res/values/attrs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/imageset/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #00000000
4 | #333333
5 | #e4e4e4
6 |
--------------------------------------------------------------------------------
/imageset/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | SmartPicture
3 |
4 | 去设置
5 | 照片
6 | 预览照片
7 | 所有照片
8 | 取消
9 | 完成
10 | 完成(%d/%d)
11 | 你最多可以选择%d张照片
12 | 此应用需要获取相机使用\n权限,才能提供拍照功能
13 | 要使用相机功能,请在权限管理中开启相机权限
14 | 此功能需要获取读取存储卡\n权限,才能查看照片
15 | 请在权限管理中开启读取存储卡权限
16 | 无法打开应用详情,请手动去开启权限~
17 |
18 |
--------------------------------------------------------------------------------
/imageset/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
11 |
14 |
--------------------------------------------------------------------------------
/imageset/src/test/java/com/sxu/smartpicture/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.sxu.smartpicture;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.assertEquals;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() throws Exception {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app', ':imageset'
2 |
--------------------------------------------------------------------------------