package com.cheikh.lazywaimai.widget;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import com.cheikh.lazywaimai.model.bean.PaymentPlatform;
import com.google.common.base.Objects;
import com.google.common.base.Preconditions;
import com.squareup.picasso.Picasso;
import com.squareup.picasso.RequestCreator;
import com.squareup.picasso.Target;
import com.cheikh.lazywaimai.R;
import com.cheikh.lazywaimai.context.AppConfig;
import com.cheikh.lazywaimai.model.bean.Business;
import com.cheikh.lazywaimai.model.bean.Product;
import com.cheikh.lazywaimai.model.bean.User;
import com.cheikh.lazywaimai.util.AnimationUtils;
/**
* Picasso框架的辅助ImageView控件
* 修改自:https://github.com/chrisbanes/philm/blob/master/app/src/main/java/app/philm/in/view/PhilmImageView.java
*/
public class PicassoImageView extends ImageView {
private final String LOG_TAG = PicassoImageView.class.getSimpleName();
private PicassoHandler mPicassoHandler;
private boolean mAutoFade = true;
private boolean mAvatarMode = false;
public PicassoImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void setAutoFade(boolean autoFade) {
mAutoFade = autoFade;
}
public void setAvatarMode(boolean avatarMode) {
mAvatarMode = avatarMode;
}
public void loadProfile(User user) {
loadProfile(user, null);
}
public void loadProfile(User user, Listener listener) {
setAvatarMode(true);
if (!TextUtils.isEmpty(user.getAvatarUrl())) {
setPicassoHandler(new UserProfileHandler(user, listener));
} else {
reset();
setImageResourceImpl(R.drawable.ic_default_avatar);
}
}
public void loadBusinessPhoto(Business business) {
loadBusinessPhoto(business, null);
}
public void loadBusinessPhoto(Business business, Listener listener) {
if (!TextUtils.isEmpty(business.getPicUrl())) {
setPicassoHandler(new BusinessPhotoHandler(business, listener));
} else {
reset();
setImageResourceImpl(R.mipmap.ic_launcher);
}
}
public void loadProductPhoto(Product product) {
loadProductPhoto(product, null);
}
public void loadProductPhoto(Product product, Listener listener) {
if (!TextUtils.isEmpty(product.getImagePath())) {
setVisibility(View.VISIBLE);
setPicassoHandler(new ProductPhotoHandler(product, listener));
} else {
reset();
setVisibility(View.GONE);
}
}
public void loadPlatformIcon(PaymentPlatform platform) {
loadPlatformIcon(platform, null);
}
public void loadPlatformIcon(PaymentPlatform platform, Listener listener) {
if (!TextUtils.isEmpty(platform.getIconUrl())) {
setVisibility(View.VISIBLE);
setPicassoHandler(new PlatformIconHandler(platform, listener));
} else {
reset();
setVisibility(View.GONE);
}
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
if (changed && canLoadImage() && mPicassoHandler != null && !mPicassoHandler.isStarted()) {
loadUrlImmediate();
}
}
@Override
protected void onDetachedFromWindow() {
Picasso.with(getContext()).cancelRequest(mPicassoTarget);
super.onDetachedFromWindow();
}
private boolean canLoadImage() {
return getWidth() != 0 && getHeight() != 0;
}
private void loadUrlImmediate() {
Preconditions.checkNotNull(mPicassoHandler, "mPicassoHandler cannot be null");
final String url = mPicassoHandler.getUrl(this);
if (url != null) {
mPicassoHandler.markAsStarted();
RequestCreator request = Picasso.with(getContext()).load(url);
if (mPicassoHandler.shouldDisplayPlaceholder()
&& mPicassoHandler.getPlaceholderDrawable() != 0) {
request = request.placeholder(mPicassoHandler.getPlaceholderDrawable());
}
if (mPicassoHandler.centerCrop()) {
request = request.resize(getWidth(), getHeight()).centerCrop();
} else {
request = request.resize(getWidth(), getHeight()).centerInside();
}
request.into(mPicassoTarget);
if (AppConfig.DEBUG) {
Log.d(LOG_TAG, "Loading " + url);
}
}
}
private void reset() {
setPicassoHandler(null);
setImageDrawable(null);
}
private void setPicassoHandler(PicassoHandler handler) {
if (mPicassoHandler != null && mPicassoHandler.isStarted()
&& !mPicassoHandler.isFinished()) {
Picasso.with(getContext()).cancelRequest(mPicassoTarget);
}
if (handler != null && Objects.equal(handler, mPicassoHandler)) {
handler.setDisplayPlaceholder(false);
}
mPicassoHandler = handler;
if (handler != null && canLoadImage()) {
loadUrlImmediate();
}
}
private static abstract class PicassoHandler<T> {
private final T mObject;
private final Listener mCallback;
private boolean mIsStarted, mIsFinished;
private boolean mDisplayPlaceholder = true;
PicassoHandler(T object, Listener callback) {
mObject = Preconditions.checkNotNull(object, "object cannot be null");
mCallback = callback;
}
final String getUrl(ImageView imageView) {
return buildUrl(mObject, imageView);
}
protected abstract String buildUrl(T object, ImageView imageView);
void markAsStarted() {
mIsStarted = true;
}
void markAsFinished() {
mIsFinished = true;
}
boolean isStarted() {
return mIsStarted;
}
boolean isFinished() {
return mIsFinished;
}
int getPlaceholderDrawable() {
return 0;
}
void setDisplayPlaceholder(boolean displayPlaceholder) {
mDisplayPlaceholder = displayPlaceholder;
}
boolean shouldDisplayPlaceholder() {
return mDisplayPlaceholder;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
PicassoHandler that = (PicassoHandler) o;
return Objects.equal(mObject, that.mObject);
}
boolean centerCrop() {
return true;
}
@Override
public int hashCode() {
return mObject != null ? mObject.hashCode() : 0;
}
}
private class UserProfileHandler extends PicassoHandler<User> {
UserProfileHandler(User user, Listener callback) {
super(user, callback);
}
@Override
protected String buildUrl(User user, ImageView imageView) {
return user.getAvatarUrl();
}
}
private class BusinessPhotoHandler extends PicassoHandler<Business> {
BusinessPhotoHandler(Business business, Listener callback) {
super(business, callback);
}
@Override
protected String buildUrl(Business business, ImageView imageView) {
return business.getPicUrl();
}
}
private class ProductPhotoHandler extends PicassoHandler<Product> {
ProductPhotoHandler(Product product, Listener callback) {
super(product, callback);
}
@Override
protected String buildUrl(Product product, ImageView imageView) {
return product.getImagePath();
}
}
private class PlatformIconHandler extends PicassoHandler<PaymentPlatform> {
PlatformIconHandler(PaymentPlatform platform, Listener callback) {
super(platform, callback);
}
@Override
protected String buildUrl(PaymentPlatform platform, ImageView imageView) {
return platform.getIconUrl();
}
}
private final Target mPicassoTarget = new Target() {
@Override
public void onPrepareLoad(Drawable drawable) {
if (mPicassoHandler == null || mPicassoHandler.shouldDisplayPlaceholder()) {
setImageDrawableImpl(drawable);
}
}
@Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom loadedFrom) {
setImageBitmapFromNetwork(bitmap, loadedFrom);
if (mPicassoHandler != null) {
if (mPicassoHandler.mCallback != null) {
mPicassoHandler.mCallback.onSuccess(PicassoImageView.this, bitmap);
}
mPicassoHandler.markAsFinished();
}
}
@Override
public void onBitmapFailed(Drawable drawable) {
if (mPicassoHandler != null) {
if (mPicassoHandler.mCallback != null) {
mPicassoHandler.mCallback.onError(PicassoImageView.this);
}
mPicassoHandler.markAsFinished();
}
}
};
void setImageBitmapFromNetwork(final Bitmap bitmap, Picasso.LoadedFrom loadedFrom) {
final boolean fade = mAutoFade && loadedFrom != Picasso.LoadedFrom.MEMORY;
final Drawable currentDrawable = getDrawable();
if (fade) {
if (currentDrawable == null || mPicassoHandler.getPlaceholderDrawable() != 0) {
// If we have no current drawable, or it is a placeholder drawable. Just fade in
setVisibility(View.INVISIBLE);
setImageBitmapImpl(bitmap);
AnimationUtils.Fade.show(this);
} else {
AnimationUtils.startCrossFade(this, currentDrawable,
new BitmapDrawable(getResources(), bitmap));
}
} else {
setImageBitmapImpl(bitmap);
}
}
void setImageBitmapImpl(final Bitmap bitmap) {
if (mAvatarMode) {
setImageDrawable(new RoundedAvatarDrawable(bitmap));
} else {
setImageBitmap(bitmap);
}
}
void setImageDrawableImpl(final Drawable drawable) {
if (mAvatarMode && drawable instanceof BitmapDrawable) {
setImageBitmapImpl(((BitmapDrawable) drawable).getBitmap());
} else {
setImageDrawable(drawable);
}
}
void setImageResourceImpl(int resId) {
if (mAvatarMode) {
BitmapDrawable d = (BitmapDrawable) getResources().getDrawable(resId);
setImageDrawable(new RoundedAvatarDrawable(d.getBitmap()));
} else {
setImageResource(resId);
}
}
public interface Listener {
void onSuccess(PicassoImageView imageView, Bitmap bitmap);
void onError(PicassoImageView imageView);
}
}