package com.mogujie.widget.imageview;
import java.util.HashMap;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.widget.ImageView;
import com.mogujie.im.libs.R;
import com.squareup.picasso.Picasso;
import com.squareup.picasso.Picasso.LoadedFrom;
import com.squareup.picasso.RequestCreator;
import com.squareup.picasso.Target;
import com.squareup.picasso.Transformation;
/**
* Created by 6a209 on 9/11/13.
*
* @modify dolphinWang on 2014/02/07 不再使用Volley, 改用Picasso为图片下载与缓存框架
* @modify dolphinWang on 2014/02/08 改变picasso的使用方式,提供全局统一的picasso对象
* @modify dolphinWang on 2014/02/12
* 添加setImageUrlNeedResize函数,因为某些需求要求图片等高,坑爹的是还需要画一个cover上去
* ,ImageView的centerCrop模式又会忽略padding
* @modify dolphinWang on 2014/02/14 1.根据Picasso load(String
* url)函数的url检测做出代码外部的url拦截操作。 2.Fetch单图成功之后,在map中删掉这张bitmap减小内存占用。
*/
public class MGWebImageView extends ImageView {
@SuppressWarnings("unused")
private int mPlaceholder = -1;
protected String mUrl;
private Drawable mDefaultDrawable;
private boolean needFit;
private boolean needResize;
private int targetWidth;
private int targetHeight;
protected boolean isAttachedOnWindow;
private Transformation mTransformation;
/**
* 我们需要hold住一个target的强引用,以免被GC释放掉
*/
private static HashMap<String, Target> mTargetMap;
public MGWebImageView(Context context) {
this(context, null);
}
public MGWebImageView(Context context, AttributeSet attrs) {
super(context, attrs);
getConfiguration(context, attrs);
}
private void getConfiguration(Context context, AttributeSet attrs) {
if (attrs == null) {
return;
}
TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.MGWebImageView);
mTransformation = BitmapUtils.get(a.getInt(
R.styleable.MGWebImageView_shape, -1));
if (mTransformation instanceof RoundedCornerTransfrom) {
int cornerSize = (int) a.getDimension(
R.styleable.MGWebImageView_cornerSize, -1);
if (cornerSize != -1) {
((RoundedCornerTransfrom) mTransformation)
.setCornerSize(cornerSize);
}
}
a.recycle();
}
protected void beginProcess(RequestCreator creator) {
if (needFit && needResize) {
throw new IllegalArgumentException(
"fit and resize can not be use in same time!");
}
if (needResize && (targetWidth == 0 || targetHeight == 0)) {
throw new IllegalArgumentException(
"You need resize the bitmap but set target width(target height) zero. Do you really want do this?");
}
// fit和resize不应该同时出现
if (needFit) {
creator.fit();
} else if (needResize) {
creator.resize(targetWidth, targetHeight).centerCrop();
}
if (mDefaultDrawable != null) {
creator.placeholder(mDefaultDrawable).error(mDefaultDrawable);
}
if (mTransformation != null) {
creator.transform(mTransformation);
}
// 3.0一下取消fade
if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.HONEYCOMB) {
creator.noFade();
}
creator.into(this);
}
public String getImageUrl() {
return mUrl;
}
public void setImageUrl(String url) {
if (!allowedUrl(url)) {
return;
}
mUrl = url;
// 如果还没attach to window,就暂时不请求,留到onAttachToWindow调用的时候再请求
if (isAttachedOnWindow) {
beginProcess(Picasso.with(getContext()).load(url));
}
}
public void setImageUrlNeedFit(String url) {
needFit = true;
setImageUrl(url);
}
public void setImageUrlNeedResize(String url, int width, int height) {
needResize = true;
targetWidth = width;
targetHeight = height;
setImageUrl(url);
}
public void setDefaultImageResId(int resID) {
if (resID <= 0) {
return;
}
mDefaultDrawable = getResources().getDrawable(resID);
}
public void setDefaultImageDrawable(Drawable drawable) {
if (drawable == null) {
return;
}
mDefaultDrawable = drawable;
}
public void setDefaultImageBitmap(Bitmap bitmap) {
if (bitmap == null || bitmap.isRecycled()) {
return;
}
mDefaultDrawable = new BitmapDrawable(getResources(), bitmap);
}
@Override
protected void onAttachedToWindow() {
isAttachedOnWindow = true;
setImageUrl(mUrl);
super.onAttachedToWindow();
}
@Override
protected void onDetachedFromWindow() {
Picasso.with(getContext()).cancelRequest(this);
isAttachedOnWindow = false;
setImageBitmap(null);
super.onDetachedFromWindow();
}
public static boolean allowedUrl(String url) {
if (TextUtils.isEmpty(url) || url.trim().length() == 0)
return false;
else
return true;
}
public static void fetchBitmap(final Context context, String url,
TargetCallback cb) {
if (cb == null) {
return;
}
// 根据picasso的load方法,如果String.trim返回长度为0,则会报错
if (!allowedUrl(url)) {
return;
}
if (mTargetMap == null) {
mTargetMap = new HashMap<String, Target>();
}
CancelableTarget target = new CancelableTarget(context, cb);
mTargetMap.put(target.toString(), target);
Picasso.with(context).load(url).into(target);
}
/**
* 可以被删除引用的target~
*
* @author dolphinWang
*
*/
private static class CancelableTarget implements Target {
private Context mContext;
private TargetCallback mCallback;
public CancelableTarget(Context context, TargetCallback cb) {
mContext = context;
mCallback = cb;
}
@Override
public void onBitmapLoaded(Bitmap bitmap, LoadedFrom from) {
mTargetMap.remove(this.toString());
Picasso.with(mContext).cancelRequest(this);
mCallback.onBitmapLoaded(bitmap, from);
}
@Override
public void onBitmapFailed(Drawable errorDrawable) {
mTargetMap.remove(this.toString());
Picasso.with(mContext).cancelRequest(this);
mCallback.onBitmapFailed(errorDrawable);
}
@Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
mCallback.onPrepareLoad(placeHolderDrawable);
}
}
public interface TargetCallback {
public void onBitmapLoaded(Bitmap bitmap, LoadedFrom from);
public void onBitmapFailed(Drawable errorDrawable);
public void onPrepareLoad(Drawable placeHolderDrawable);
}
// public static class MGWebImageSaveState extends View.BaseSavedState {
// String mUrl;
// boolean needFit;
// boolean needResize;
// int targetWidth;
// int targetHeight;
//
// public MGWebImageSaveState(Parcelable state) {
// super(state);
// }
//
// private MGWebImageSaveState(Parcel in) {
// super(in);
//
// mUrl = in.readString();
//
// boolean[] bArray = new boolean[2];
// in.readBooleanArray(bArray);
// needFit = bArray[0];
// needResize = bArray[1];
//
// int[] iArrat = new int[2];
// in.readIntArray(iArrat);
// targetWidth = iArrat[0];
// targetHeight = iArrat[1];
// }
//
// public static final Creator<MGWebImageSaveState> CREATOR = new
// Creator<MGWebImageSaveState>() {
// public MGWebImageSaveState createFromParcel(Parcel in) {
// return new MGWebImageSaveState(in);
// }
//
// public MGWebImageSaveState[] newArray(int size) {
// return new MGWebImageSaveState[size];
// }
// };
//
// @Override
// public void writeToParcel(Parcel dest, int flags) {
// super.writeToParcel(dest, flags);
// dest.writeString(mUrl);
// dest.writeBooleanArray(new boolean[] { needFit, needResize });
// dest.writeIntArray(new int[] { targetWidth, targetHeight });
// }
// }
}